Created
June 20, 2019 19:55
-
-
Save nelsonpecora/708b962cc849d77b87e5460c8ce8a6ed to your computer and use it in GitHub Desktop.
Janky server-side rendering of prosemirror docs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const _ = require('lodash'); | |
const cuid = require('cuid'); | |
function renderText(renderBranch, renderLeaf) { | |
return (acc, node) => { | |
if (node.doc) { | |
return renderText(renderBranch, renderLeaf)(acc, node, node.doc); | |
} else if (node.content) { | |
return renderBranch(acc, node, node.content); | |
} else if (node.text) { | |
return renderLeaf(acc, node, node.text, node.marks); | |
} else { | |
return acc; | |
} | |
}; | |
} | |
const toPlaintext = renderText( | |
(acc, node, childNodes) => acc + _.reduce(childNodes, toPlaintext, ''), | |
(acc, node, text) => acc + text | |
); | |
const toHTML = renderText( | |
(acc, node, childNodes) => acc + _.reduce(childNodes, toHTML, ''), | |
(acc, node, text, marks) => { | |
if (marks) { | |
return acc + marks.map((m) => `<${m.type}>`).join('') + text + marks.map((m) => `</${m.type}>`).join(''); | |
} else { | |
return acc + text; | |
} | |
} | |
); | |
function getKindOfTexture(type) { | |
const kinds = { | |
em: 'style.italics', | |
strong: 'style.bold' | |
}; | |
return kinds[type]; | |
} | |
// Texture is a lossy format similar to Quill's deltas, | |
// where the text is represented by a flat string and nodes/marks | |
// are 'textures' that have start and end indices | |
const toTexture = renderText( | |
(acc, node, childNodes) => { | |
if (node.type === 'paragraph') { | |
acc.textures.push({ | |
length: _.reduce(childNodes, (length, child) => length + child.text.length, 0), | |
kind: 'style.paragraph', | |
id: cuid(), | |
offset: acc.text.length | |
}); | |
} | |
return _.reduce(childNodes, toTexture, acc); | |
}, | |
(acc, node, text, marks) => { | |
if (marks) { | |
marks.forEach((mark) => { | |
acc.textures.push({ | |
length: text.length, | |
kind: getKindOfTexture(mark.type), | |
id: cuid(), | |
offset: acc.text.length | |
}); | |
}); | |
} | |
acc.text += text; | |
return acc; | |
} | |
); | |
/** | |
* Render prosemirror's data model in various formats. | |
* | |
* @param {Object} field | |
* @param {string} format | |
* @return {string|Object} | |
*/ | |
function renderTo(field, format) { | |
switch (format) { | |
case 'TEXT_RAW': return field; | |
case 'TEXT_HTML': return _.reduce([field], toHTML, ''); | |
case 'TEXT_TEXTURE': return _.reduce([field], toTexture, {text: '', textures: []}); | |
default: return _.reduce([field], toPlaintext, ''); | |
} | |
} | |
module.exports.renderTo = renderTo; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment