diff options
Diffstat (limited to 'app/assets/javascripts/content_editor/services/serialization_helpers.js')
-rw-r--r-- | app/assets/javascripts/content_editor/services/serialization_helpers.js | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js index 478b87372d7..b2cbc9c3fed 100644 --- a/app/assets/javascripts/content_editor/services/serialization_helpers.js +++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js @@ -53,6 +53,16 @@ function getRowsAndCells(table) { return { rows, cells }; } +// Buffers the output of the given action (fn) and returns the output that was written +// to the prosemirror-markdown serializer state output. +function buffer(state, action = () => {}) { + const buf = state.out; + action(); + const retval = state.out.substring(buf.length); + state.out = buf; + return retval; +} + function getChildren(node) { const children = []; for (let i = 0; i < node.childCount; i += 1) { @@ -147,6 +157,11 @@ function setIsInBlockTable(table, value) { }); } +function ensureSpace(state) { + state.flushClose(); + if (!state.atBlank() && !state.out.endsWith(' ')) state.write(' '); +} + function unsetIsInBlockTable(table) { tableMap.delete(table); @@ -194,7 +209,8 @@ function renderTableRowAsMarkdown(state, node, isHeaderRow = false) { if (i) state.write(' | '); const { length } = state.out; - state.render(cell, node, i); + const cellContent = buffer(state, () => state.render(cell, node, i)); + state.write(cellContent.replace(/\|/g, '\\|')); cellWidths.push(state.out.length - length); }); state.write(' |'); @@ -212,13 +228,20 @@ function renderTableRowAsHTML(state, node) { renderTagOpen(state, tag, omit(cell.attrs, 'sourceMapKey', 'sourceMarkdown')); - if (!containsParagraphWithOnlyText(cell)) { - state.closeBlock(node); - state.flushClose(); - } + const buffered = buffer(state, () => { + if (!containsParagraphWithOnlyText(cell)) { + state.closeBlock(node); + state.flushClose(); + } - state.render(cell, node, i); - state.flushClose(1); + state.render(cell, node, i); + state.flushClose(1); + }); + if (buffered.includes('\\') && !buffered.includes('\n')) { + state.out += `\n\n${buffered}\n`; + } else { + state.out += buffered; + } renderTagClose(state, tag); }); @@ -253,7 +276,14 @@ export function renderContent(state, node, forceRenderInline) { export function renderHTMLNode(tagName, forceRenderContentInline = false) { return (state, node) => { renderTagOpen(state, tagName, node.attrs); - renderContent(state, node, forceRenderContentInline); + + const buffered = buffer(state, () => renderContent(state, node, forceRenderContentInline)); + if (buffered.includes('\\') && !buffered.includes('\n')) { + state.out += `\n\n${buffered}\n`; + } else { + state.out += buffered; + } + renderTagClose(state, tagName, false); if (forceRenderContentInline) { @@ -446,9 +476,15 @@ export function renderOrderedList(state, node) { } export function renderReference(state, node) { + ensureSpace(state); state.write(node.attrs.originalText || node.attrs.text); } +export function renderReferenceLabel(state, node) { + ensureSpace(state); + state.write(node.attrs.originalText || `~${state.quote(node.attrs.text)}`); +} + const generateBoldTags = (wrapTagName = openTag) => { return (_, mark) => { const type = /^(\*\*|__|<strong|<b).*/.exec(mark.attrs.sourceMarkdown)?.[1]; |