diff --git a/src/js/editor/editor.js b/src/js/editor/editor.js index aea2c057f..657b00985 100644 --- a/src/js/editor/editor.js +++ b/src/js/editor/editor.js @@ -79,7 +79,7 @@ class Editor { this._elementListeners = []; this._views = []; this.isEditable = null; - this._cardParsers = options.cardParsers || []; + this._parserPlugins = options.parserPlugins || []; // FIXME: This should merge onto this.options mergeWithOptions(this, defaults, options); @@ -735,7 +735,7 @@ class Editor { this.handleDeletion(); } - let pastedPost = parsePostFromPaste(event, this.builder, this._cardParsers); + let pastedPost = parsePostFromPaste(event, this.builder, this._parserPlugins); this.run(postEditor => { let nextPosition = postEditor.insertPost(position, pastedPost); diff --git a/src/js/parsers/section.js b/src/js/parsers/section.js index 7ae6b64ba..3360737c8 100644 --- a/src/js/parsers/section.js +++ b/src/js/parsers/section.js @@ -39,6 +39,8 @@ import { transformHTMLText } from '../parsers/dom'; +import assert from '../utils/assert'; + function isListSection(section) { return section.type === LIST_SECTION_TYPE; } @@ -55,7 +57,7 @@ function isListItem(section) { export default class SectionParser { constructor(builder, options={}) { this.builder = builder; - this.cardParsers = options.cardParsers || []; + this.plugins = options.plugins || []; } parse(element) { @@ -90,11 +92,49 @@ export default class SectionParser { }); } + runPlugins(node) { + let isNodeFinished = false; + let env = { + addSection: (section) => { + this._closeCurrentSection(); + this.sections.push(section); + }, + addMarkerable: (marker) => { + let { state } = this; + let { section } = state; + assert( + 'Markerables can only be appended to markup sections and list item sections', + section && section.isMarkerable + ); + if (state.text) { + this._createMarker(); + } + section.markers.append(marker); + }, + nodeFinished() { + isNodeFinished = true; + } + }; + for (let i=0; i/); @@ -35,7 +35,7 @@ export function parsePostFromPaste(pasteEvent, builder, cardParsers=[]) { mobiledoc = JSON.parse(mobiledocString); post = mobiledocParsers.parse(builder, mobiledoc); } else { - post = new HTMLParser(builder, {cardParsers}).parse(html); + post = new HTMLParser(builder, {plugins}).parse(html); } return post; diff --git a/tests/unit/parsers/dom-google-docs-test.js b/tests/unit/parsers/dom-google-docs-test.js index 3827f5c52..7ba22dc99 100644 --- a/tests/unit/parsers/dom-google-docs-test.js +++ b/tests/unit/parsers/dom-google-docs-test.js @@ -79,12 +79,11 @@ Object.keys(GoogleDocs).forEach(key => { test('img in span can use a cardParser to turn img into image-card', function(assert) { let example = GoogleDocs['img in span']; let options = { - cardParsers: [{ - parse(element, builder) { - if (element.tagName === 'IMG') { - let payload = {url: element.src}; - return builder.createCardSection('image-card', payload); - } + plugins: [function(element, builder, {addSection}) { + if (element.tagName === 'IMG') { + let payload = {url: element.src}; + let cardSection = builder.createCardSection('image-card', payload); + addSection(cardSection); } }] }; diff --git a/tests/unit/parsers/section-test.js b/tests/unit/parsers/section-test.js index 7759e757e..7b2779b18 100644 --- a/tests/unit/parsers/section-test.js +++ b/tests/unit/parsers/section-test.js @@ -104,21 +104,21 @@ test('#parse turns a textNode into a section', (assert) => { assert.equal(m1.value, 'I am a text node'); }); -test('#parse allows passing in cardParsers that can override parsing', (assert) => { +test('#parse allows passing in parserPlugins that can override element parsing', (assert) => { let container = buildDOM(`

text 1text 2

`); let element = container.firstChild; - let cardParsers = [{ - parse(element, builder) { - if (element.tagName === 'IMG') { - let payload = {url: element.src}; - return builder.createCardSection('test-image', payload); - } + let plugins = [function(element, builder, {addSection}) { + if (element.tagName !== 'IMG') { + return; } + let payload = {url: element.src}; + let cardSection = builder.createCardSection('test-image', payload); + addSection(cardSection); }]; - parser = new SectionParser(builder, {cardParsers}); + parser = new SectionParser(builder, {plugins}); const sections = parser.parse(element); assert.equal(sections.length, 3, '3 sections'); @@ -130,3 +130,24 @@ test('#parse allows passing in cardParsers that can override parsing', (assert) assert.equal(cardSection.name, 'test-image'); assert.deepEqual(cardSection.payload, {url: 'http://placehold.it/100x100'}); }); + +test('#parse allows passing in parserPlugins that can override text parsing', (assert) => { + let container = buildDOM(` +

text 1text 2

+ `); + + let element = container.firstChild; + let plugins = [function(element, builder, {addMarkerable, nodeFinished}) { + if (element.nodeType === 3) { + if (element.textContent === 'text 1') { + addMarkerable(builder.createMarker('oh my')); + } + nodeFinished(); + } + }]; + parser = new SectionParser(builder, {plugins}); + const sections = parser.parse(element); + + assert.equal(sections.length, 1, '1 section'); + assert.equal(sections[0].text, 'oh my'); +});