2015-08-07 3 views
8

Ich arbeite an einem benutzerdefinierten CMS, wo CKEditor (4.5.1) für freundliche HTML-Content-Generierung integriert ist.Block/Inline 'Meta-Markup' in CKEditor

Eine der Funktionen, die wir liefern, ist die Möglichkeit, Teile der Seite auf bestimmte Benutzergruppen zu beschränken, und die sauberste Möglichkeit, dies zu tun, war, ein neues Tag zu erstellen und dieses zum Nachverfolgen zu verwenden Inhalt, z <restrict data-usertype="1,2,3">restricted content for user types 1, 2, 3 here</restrict>, die durch das Backend entfernt werden würde.

Das Problem, das ich habe, ist, dass mein benutzerdefiniertes Tag implizit sowohl Block- als auch Inline-Tags unterstützen muss, und ich bin mir nicht sicher, wie ich das richtig einrichten soll.

Ich habe eine Vielzahl von Kombinationen von Dingen ausprobiert, die entweder das Hinzufügen von Inhalten überhaupt verbieten, oder das Plug-In vollständig deaktivieren (weil es mit ACFs eigener Plausibilitätsprüfung in Konflikt gerät); Im Moment wird die Konfiguration, die ich habe, lassen Sie mich den <restrict> Block hinzufügen, lassen Sie mich im Dialog (einschließlich durch Doppelklick) bearbeiten, aber lassen Sie mich keinen Inhalt irgendwelcher Art verschachteln und verursachen CKEditor zu werfen 'konnte nicht Lese Attribute von Null 'warnt beim Zurückschalten in den Quellmodus.

Meine aktuelle Konfiguration des Plugins wird wie folgt:

CKEDITOR.dtd.restrict = { 
     a: 1, abbr: 1, address: 1, area: 1, article: 1, aside: 1, audio: 1, b: 1, bdi: 1, bdo: 1, blockquote: 1, 
     br: 1, button: 1, canvas: 1, cite: 1, code: 1, command: 1, datalist: 1, del: 1, details: 1, dfn: 1, div: 1, 
     dl: 1, em: 1, embed: 1, fieldset: 1, figure: 1, footer: 1, form: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1, 
     header: 1, hgroup: 1, hr: 1, i: 1, iframe: 1, img: 1, input: 1, ins: 1, kbd: 1, keygen: 1, label: 1, map: 1, 
     mark: 1, meter: 1, noscript: 1, object: 1, ol: 1, output: 1, progress: 1, p: 1, pre: 1, q: 1, ruby: 1, s: 1, 
     samp: 1, script: 1, section: 1, select: 1, small: 1, span: 1, strong: 1, sub: 1, sup: 1, table: 1, 
     textarea: 1, time: 1, u: 1, ul: 1, 'var': 1, video: 1, wbr: 1, '#': 1 
    }; // Allow <restrict> as a valid tag. 
    CKEDITOR.dtd.$block.restrict = 1; 
    CKEDITOR.dtd.$inline.restrict = 1; 
    CKEDITOR.dtd.$blockLimit.restrict = 1; // Treat <restrict> as a block limiter tag 
    CKEDITOR.dtd.$removeEmpty.restrict = 1; // Remove <restrict /> tags if they are empty 
    CKEDITOR.dtd.$transparent.restrict = 1; // Treat the tag as transparent as far as content models go 
    CKEDITOR.dtd.body.restrict = 1; // Allow it in the body, div and p tags. 
    CKEDITOR.dtd.div.restrict = 1; 
    CKEDITOR.dtd.p.restrict = 1; 

    var allowedEls = ['restrict']; 
    for (var i in CKEDITOR.dtd.restrict) { 
     if (CKEDITOR.dtd.restrict.hasOwnProperty(i) && i != '#') { 
      allowedEls.push(i); 
     } 
    } 

    // Define the widget. 
    editor.widgets.add('restrict', { 
     button: 'Restricted Content', 
     dialog: 'restrictDialog', 
     template: '<restrict />', 
     editables: {}, 
     allowedContent: allowedEls.join(' ') + '[*]{*}(*)', // All the above elements, with any attributes, styles or classes. 
     requiredContent: 'restrict[data-*]', 
     upcast: function (element) { 
      return element.name == 'restrict'; 
     }, 
     init: function() { 
      // Some stuff which iterates through the various 
      // properties I care about, grabs from data 
      // attributes and pushes to this.setData(). 
     }, 
     data: function() { 
      // Some stuff that just fetches vars from this.data, 
      // sets the relevant data attribute and also sets an 
      // attribute on the span created by CKEditor since 
      // styling and ::before content is used to show who 
      // the block is visible to - the result is much like 
      // the Show Blocks plugin. This stuff all works 
      // correctly and being omitted changes nothing. 
     } 
    }); 

Ich glaube, ich habe falsch editables eingerichtet und wahrscheinlich die allgemeinen erlaubt Inhalt Material für diesen Tag, aber ich kann nicht sehen, wie ich Ich sollte ein solches Tag erstellen und ich kann mir nicht vorstellen, dass das Erstellen eines solchen Phantom-Tags, das außerhalb des Browsers geparst wird, ein neues Problem darstellen würde.

Vielen Dank im Voraus!

Antwort

1

Ich fand tatsächlich eine alternative Antwort auf dieses Problem, meistens indem ich das Problem ein wenig neu definierte.

Zuerst erkannte ich, dass das CMS fast immer den Inhalt einschränkt, es wird es in einem Blockkontext statt in einem Inline sowieso tun - ganze div Sektionen würden eher entfernt werden als Teile einer Linie.

Sobald ich das erkannte, erkannte ich dann, dass es nicht wirklich ein Widget ist, das ich bauen musste, sondern ein konventionelleres Plugin.

Ich begann dann, indem ich das Insert-Div-Plugin für CKEditor nahm, und begann es anzupassen. In dem Init-Methode des Plugins gibt es die folgende Ersteinrichtung:

CKEDITOR.dtd.restrict = {}; 
CKEDITOR.tools.extend(CKEDITOR.dtd.restrict, CKEDITOR.dtd.div); 
CKEDITOR.dtd.$block.restrict = 1; 
CKEDITOR.dtd.$blockLimit.restrict = 1; // Treat <restrict> as a block limiter tag 
CKEDITOR.dtd.$removeEmpty.restrict = 1; // Remove <restrict /> tags if they are empty 
CKEDITOR.dtd.body.restrict = 1; // Allow it in the body, div and p tags. 
CKEDITOR.dtd.div.restrict = 1; 

Das weitgehend die Plugin-Bedürfnisse eingerichtet, aber ich arbeite aus einer vorgefertigten Kopie von CKEditor, und ich habe weder die Zeit noch Neigung zu Richten Sie einen Prozess ein, um den CKEditor neu zu erstellen/wiederherzustellen - was ein Problem ist, da $blockLimit nur beim Start verwendet wird und das Hinzufügen auf der Plugin-Ebene nicht funktioniert, da das einzige Mal, wenn es ausgewertet wird, bereits ausgeführt wurde, bevor Plugins geladen werden. Um dem entgegenzuwirken, klont das Plugin die Schließung und Definition von CKEDITOR.dom.editorPath, nachdem das Plugin ausgeführt wurde, so dass es die DTD-Methoden korrekt neu bewertet.

Ansonsten änderte ich alle 'creatediv'/'editdiv'/'removediv' Verweise auf '* restricte' entsprechend, änderte die Stellen, die auf 'div' geprüft wurden, auf 'restricte' und ersetzte die Dialogdefinition mit der Dialog, den ich wirklich brauche, was sehr anwendungsfallspezifisch ist. Da es sich meistens um einen Copy/Paste-Job handelt, scheint es nicht wirklich nützlich zu sein, welchen Code ich bereitstellen kann, da die Bits, die nicht Kopieren/Einfügen sind, für das Produkt spezifisch sind.

Was dies komplexer gemacht hat, ist die Tatsache, dass ich auch Styling dynamisch auf das Element beschränken, um ein ähnliches Aussehen der Show Blocks Tag, wo die Liste der Einschränkungen im Tag selbst durch restrict::before { content: '...' } dokumentiert Dies verweist auf ein Attribut auf dem restrict-Tag selbst, cke-restrict-description, das jedes Mal aktualisiert wird, wenn der Dialog ausgeführt wird, sowie jedes Mal, wenn der Editor in den WYSIWYG-Modus wechselt (einmal in instanceReady, einmal in editor.on) ') wo editor.mode ==' wysiwyg ')