I'm working on a custom CMS where CKEditor (4.5.1) is integrated for friendly HTML content generation.
One of the features we're shipping is the ability to restrict parts of the page to specific groups of users and the cleanest way to do that as far as I could tell was create a new tag and use that for tracking of content, e.g. <restrict data-usertype="1,2,3">restricted content for user types 1, 2, 3 here</restrict>
which would be stripped out by the backend.
The problem I have is that my custom tag implicitly needs to support both block and inline tags, and I'm not sure how to set this up correctly.
I've tried a variety of combinations of things which either disallow any content being added at all, or disable the plugin entirely (because it falls foul of ACF's own sanity checking); right now the configuration I have will let me add the <restrict>
block, will let me edit it in the dialog (including by double-clicking) but will not let me nest any content of any kind and will cause CKEditor to throw a 'could not read attributes of null' warning when switching back to source mode.
My current configuration of this plugin is as follows:
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.
}
} );
I guess I've set up editables
incorrectly and probably the general allowed content stuff for this tag, but I can't see how I'm supposed to create such a tag, and I can't imagine that creating such a phantom tag that will be parsed outside of the browser would be a new problem.
Thanks in advance!