2015-08-07 3 views
8

Я работаю над пользовательской CMS, где CKEditor (4.5.1) интегрирован для создания дружественного HTML-контента.Block/inline 'meta markup' в CKEditor

Одна из функций, которые мы отправляем, - это возможность ограничить части страницы конкретными группами пользователей, а самый чистый способ сделать это, насколько я мог судить, - создать новый тег и использовать его для отслеживания контента, например <restrict data-usertype="1,2,3">restricted content for user types 1, 2, 3 here</restrict>, который будет удален бэкэнд.

Проблема заключается в том, что мой пользовательский тег неявно должен поддерживать как блочные, так и встроенные теги, и я не уверен, как правильно настроить это.

Я пробовал различные комбинации вещей, которые либо запрещают любой контент, добавленный вообще, либо полностью отключает плагин (потому что он не соответствует действительности проверки ACF); прямо сейчас, у меня будет возможность добавить блок <restrict>, позволит мне отредактировать его в диалоговом окне (в том числе двойным щелчком), но не позволит мне встраивать какой-либо контент любого типа и заставит CKEditor сбросить 'can not читать атрибуты нулевого предупреждения при возврате в исходный режим.

Моя текущая конфигурация этого плагина выглядит следующим образом:

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. 
     } 
    }); 

Я предполагаю, что я создал editables неправильно и, вероятно, общее допустимое содержание материала для этого тега, но я не могу видеть, как я m должен создать такой тег, и я не могу себе представить, что создание такого фантомного тега, который будет анализироваться вне браузера, будет новой проблемой.

Заранее благодарен!

ответ

1

На самом деле я нашел альтернативный ответ на эту проблему, в основном, переопределив проблему.

Во-первых, я понял, что почти все время, когда CMS будет ограничивать контент, он будет делать это в блочном контексте, а не в линейном, так или иначе - целые секции div будут удалены, а не части строки.

Как только я понял это, я понял, что это не действительно виджет, который мне нужно создать, а более обычный плагин.

Затем я начал с создания плагина-вставки для CKEditor и начал его настраивать. В методе инициализации плагина, есть следующие начальная настройка:

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; 

Это в значительной степени установить потребности плагина, но я работаю с предварительно встроенной копии CKEditor, и у меня нет ни времени, ни склонности к настроить процесс восстановления/реминирования CKEditor, что является проблемой здесь, потому что $blockLimit используется только при запуске и добавление к нему на уровне плагина не работает, потому что только один раз, когда он был оценен, уже был запущен до загрузки плагинов. Чтобы противостоять этому, плагин клонирует закрытие и определение CKEDITOR.dom.editorPath после запуска плагина, чтобы он правильно оценивал методы DTD.

Кроме этого, я изменил все ссылки 'creatediv'/'editdiv'/'removediv' на '* ограничитель' соответствующим образом, изменил места, которые он проверяет для 'div', на 'ограничение' и заменил определение диалога на диалог, который мне действительно нужен, что очень важно для конкретного случая. Поскольку это, в основном, операция копирования/вставки, на самом деле не представляется полезным предоставить какой код я могу, так как биты, которые не копируются/вставляются, являются специфичными для продукта.

Что сделало это более сложным, так это то, что я также динамически управляю стилем элемента ограничения, чтобы создать вид, похожий на тег Show Blocks, где список ограничений документирован в самом теге через restrict::before { content: '...' } который указывает на атрибут самого ограничивающего тега, cke-restrict-description, который обновляется каждый раз при запуске диалога, а также каждый раз, когда редактор переключается в режим WYSIWYG (один раз на экземпляр Ready, один раз на editor.on ('mode '), где editor.mode ==' wysiwyg ')