This commit is contained in:
527
node_modules/decap-cms-widget-markdown/dist/esm/serializers/remarkSlate.js
generated
vendored
Normal file
527
node_modules/decap-cms-widget-markdown/dist/esm/serializers/remarkSlate.js
generated
vendored
Normal file
@@ -0,0 +1,527 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = remarkToSlate;
|
||||
exports.mergeAdjacentTexts = mergeAdjacentTexts;
|
||||
var _isEqual2 = _interopRequireDefault(require("lodash/isEqual"));
|
||||
var _flatten2 = _interopRequireDefault(require("lodash/flatten"));
|
||||
var _map2 = _interopRequireDefault(require("lodash/map"));
|
||||
var _flatMap2 = _interopRequireDefault(require("lodash/flatMap"));
|
||||
var _isArray2 = _interopRequireDefault(require("lodash/isArray"));
|
||||
var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
||||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
||||
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); }
|
||||
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
||||
/**
|
||||
* Map of MDAST node types to Slate node types.
|
||||
*/
|
||||
const typeMap = {
|
||||
root: 'root',
|
||||
paragraph: 'paragraph',
|
||||
blockquote: 'quote',
|
||||
code: 'code-block',
|
||||
listItem: 'list-item',
|
||||
table: 'table',
|
||||
tableRow: 'table-row',
|
||||
tableCell: 'table-cell',
|
||||
thematicBreak: 'thematic-break',
|
||||
link: 'link',
|
||||
image: 'image',
|
||||
shortcode: 'shortcode'
|
||||
};
|
||||
|
||||
/**
|
||||
* Map of MDAST node types to Slate mark types.
|
||||
*/
|
||||
const markMap = {
|
||||
strong: 'bold',
|
||||
emphasis: 'italic',
|
||||
delete: 'delete',
|
||||
inlineCode: 'code'
|
||||
};
|
||||
function isText(node) {
|
||||
return !!node.text;
|
||||
}
|
||||
function isMarksEqual(node1, node2) {
|
||||
return (0, _isEqual2.default)(node1.marks, node2.marks);
|
||||
}
|
||||
function mergeAdjacentTexts(children) {
|
||||
if (children.length <= 0) {
|
||||
return children;
|
||||
}
|
||||
const mergedChildren = [];
|
||||
let isMerging = false;
|
||||
let current;
|
||||
for (let i = 0; i < children.length - 1; i++) {
|
||||
if (!isMerging) {
|
||||
current = children[i];
|
||||
}
|
||||
const next = children[i + 1];
|
||||
if (isText(current) && isText(next) && isMarksEqual(current, next)) {
|
||||
isMerging = true;
|
||||
current = _objectSpread(_objectSpread({}, current), {}, {
|
||||
text: `${current.text}${next.text}`
|
||||
});
|
||||
} else {
|
||||
mergedChildren.push(current);
|
||||
isMerging = false;
|
||||
}
|
||||
}
|
||||
if (isMerging) {
|
||||
mergedChildren.push(current);
|
||||
} else {
|
||||
mergedChildren.push(children[children.length - 1]);
|
||||
}
|
||||
return mergedChildren;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Remark plugin for converting an MDAST to Slate Raw AST. Remark plugins
|
||||
* return a `transformNode` function that receives the MDAST as it's first argument.
|
||||
*/
|
||||
function remarkToSlate({
|
||||
voidCodeBlock
|
||||
} = {}) {
|
||||
return transformNode;
|
||||
function transformNode(node) {
|
||||
/**
|
||||
* Call `transformNode` recursively on child nodes.
|
||||
*
|
||||
* If a node returns a falsey value, filter it out. Some nodes do not
|
||||
* translate from MDAST to Slate, such as definitions for link/image
|
||||
* references or footnotes.
|
||||
*/
|
||||
let children = !['strong', 'emphasis', 'delete'].includes(node.type) && !(0, _isEmpty2.default)(node.children) && (0, _flatMap2.default)(node.children, transformNode).filter(val => val);
|
||||
if (Array.isArray(children)) {
|
||||
// Merge adjacent text nodes with the same marks to conform to slate schema
|
||||
children = mergeAdjacentTexts(children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run individual nodes through the conversion factory.
|
||||
*/
|
||||
const output = convertNode(node, children || undefined);
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add nodes to a parent node only if `nodes` is truthy.
|
||||
*/
|
||||
function addNodes(parent, nodes) {
|
||||
return nodes ? _objectSpread(_objectSpread({}, parent), {}, {
|
||||
children: nodes
|
||||
}) : parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Slate Block node.
|
||||
*/
|
||||
function createBlock(type, nodes, props = {}) {
|
||||
if (!(0, _isArray2.default)(nodes)) {
|
||||
props = nodes;
|
||||
nodes = undefined;
|
||||
}
|
||||
|
||||
// Ensure block nodes have at least one text child to conform to slate schema
|
||||
const children = (0, _isEmpty2.default)(nodes) ? [createText('')] : nodes;
|
||||
const node = _objectSpread({
|
||||
type
|
||||
}, props);
|
||||
return addNodes(node, children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Slate Inline node.
|
||||
*/
|
||||
function createInline(type, props = {}, nodes) {
|
||||
const node = _objectSpread({
|
||||
type
|
||||
}, props);
|
||||
|
||||
// Ensure inline nodes have at least one text child to conform to slate schema
|
||||
const children = (0, _isEmpty2.default)(nodes) ? [createText('')] : nodes;
|
||||
return addNodes(node, children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Slate Raw text node.
|
||||
*/
|
||||
function createText(node) {
|
||||
const newNode = {};
|
||||
if (typeof node === 'string') {
|
||||
return _objectSpread(_objectSpread({}, newNode), {}, {
|
||||
text: node
|
||||
});
|
||||
}
|
||||
const {
|
||||
text,
|
||||
marks
|
||||
} = node;
|
||||
return normalizeMarks(_objectSpread(_objectSpread({}, newNode), {}, {
|
||||
text,
|
||||
marks
|
||||
}));
|
||||
}
|
||||
function processMarkChild(childNode, marks) {
|
||||
switch (childNode.type) {
|
||||
/**
|
||||
* If a text node is a direct child of the current node, it should be
|
||||
* set aside as a text, and all marks that have been collected in the
|
||||
* `marks` array should apply to that specific text.
|
||||
*/
|
||||
case 'html':
|
||||
case 'text':
|
||||
return _objectSpread(_objectSpread({}, convertNode(childNode)), {}, {
|
||||
marks
|
||||
});
|
||||
|
||||
/**
|
||||
* MDAST inline code nodes don't have children, just a text value, similar
|
||||
* to a text node, so it receives the same treatment as a text node, but we
|
||||
* first add the inline code mark to the marks array.
|
||||
*/
|
||||
case 'inlineCode':
|
||||
{
|
||||
return _objectSpread(_objectSpread({}, convertNode(childNode)), {}, {
|
||||
marks: [...marks, {
|
||||
type: 'code'
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Process nested style nodes. The recursive results should be pushed into
|
||||
* the texts array. This way, every MDAST nested text structure becomes a
|
||||
* flat array of texts that can serve as the value of a single Slate Raw
|
||||
* text node.
|
||||
*/
|
||||
case 'strong':
|
||||
case 'emphasis':
|
||||
case 'delete':
|
||||
return processMarkNode(childNode, marks);
|
||||
case 'link':
|
||||
{
|
||||
const nodes = (0, _map2.default)(childNode.children, child => normalizeMarks(processMarkChild(child, marks)));
|
||||
const result = convertNode(childNode, (0, _flatten2.default)(nodes));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remaining nodes simply need mark data added to them, and to then be
|
||||
* added into the cumulative children array.
|
||||
*/
|
||||
default:
|
||||
return transformNode(_objectSpread(_objectSpread({}, childNode), {}, {
|
||||
data: _objectSpread(_objectSpread({}, childNode.data), {}, {
|
||||
marks
|
||||
})
|
||||
}));
|
||||
}
|
||||
}
|
||||
function processMarkNode(node, parentMarks = []) {
|
||||
/**
|
||||
* Add the current node's mark type to the marks collected from parent
|
||||
* mark nodes, if any.
|
||||
*/
|
||||
const markType = markMap[node.type];
|
||||
const marks = markType ? [...parentMarks.filter(({
|
||||
type
|
||||
}) => type !== markType), {
|
||||
type: markType
|
||||
}] : parentMarks;
|
||||
const children = (0, _flatMap2.default)(node.children, child => normalizeMarks(processMarkChild(child, marks)));
|
||||
return children;
|
||||
}
|
||||
function normalizeMarks(node) {
|
||||
if (node.marks) {
|
||||
node.marks.forEach(mark => {
|
||||
node[mark.type] = true;
|
||||
});
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a single MDAST node to a Slate Raw node. Uses local node factories
|
||||
* that mimic the unist-builder function utilized in the slateRemark
|
||||
* transformer.
|
||||
*/
|
||||
function convertNode(node, nodes) {
|
||||
switch (node.type) {
|
||||
/**
|
||||
* General
|
||||
*
|
||||
* Convert simple cases that only require a type and children, with no
|
||||
* additional properties.
|
||||
*/
|
||||
case 'paragraph':
|
||||
case 'blockquote':
|
||||
case 'tableRow':
|
||||
case 'tableCell':
|
||||
{
|
||||
return createBlock(typeMap[node.type], nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Root element
|
||||
* If the root node is empty, we need to add a paragraph node to it.
|
||||
*/
|
||||
case 'root':
|
||||
{
|
||||
const children = (0, _isEmpty2.default)(nodes) ? [createBlock('paragraph')] : nodes;
|
||||
return createBlock(typeMap[node.type], children);
|
||||
}
|
||||
|
||||
/**
|
||||
* List Items
|
||||
*
|
||||
* Markdown list items can be empty, but a list item in the Slate schema
|
||||
* should at least have an empty paragraph node.
|
||||
*/
|
||||
case 'listItem':
|
||||
{
|
||||
const children = (0, _isEmpty2.default)(nodes) ? [createBlock('paragraph')] : nodes;
|
||||
return createBlock(typeMap[node.type], children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcodes
|
||||
*
|
||||
* Shortcode nodes are represented as "void" blocks in the Slate AST. They
|
||||
* maintain the same data as MDAST shortcode nodes. Slate void blocks must
|
||||
* contain a blank text node.
|
||||
*/
|
||||
case 'shortcode':
|
||||
{
|
||||
const nodes = [createText('')];
|
||||
const data = _objectSpread(_objectSpread({}, node.data), {}, {
|
||||
id: node.data.shortcode,
|
||||
shortcodeNew: true
|
||||
});
|
||||
return createBlock(typeMap[node.type], nodes, {
|
||||
data
|
||||
});
|
||||
}
|
||||
case 'text':
|
||||
{
|
||||
const text = node.value;
|
||||
return createText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML
|
||||
*
|
||||
* HTML nodes contain plain text like text nodes, except they only contain
|
||||
* HTML. Our serialization results in non-HTML being placed in HTML nodes
|
||||
* sometimes to ensure that we're never escaping HTML from the rich text
|
||||
* editor. We do not replace line feeds in HTML because the HTML is raw
|
||||
* in the rich text editor, so the writer knows they're writing HTML, and
|
||||
* should expect soft breaks to be visually absent in the rendered HTML.
|
||||
*/
|
||||
case 'html':
|
||||
{
|
||||
return createText(node.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inline Code
|
||||
*
|
||||
* Inline code nodes from an MDAST are represented in our Slate schema as
|
||||
* text nodes with a "code" mark. We manually create the text containing
|
||||
* the inline code value and a "code" mark, and place it in an array for use
|
||||
* as a Slate text node's children array.
|
||||
*/
|
||||
case 'inlineCode':
|
||||
{
|
||||
return createText({
|
||||
text: node.value,
|
||||
code: true,
|
||||
marks: [{
|
||||
type: 'code'
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks
|
||||
*
|
||||
* Marks are typically decorative sub-types that apply to text nodes. In an
|
||||
* MDAST, marks are nodes that can contain other nodes. This nested
|
||||
* hierarchy has to be flattened and split into distinct text nodes with
|
||||
* their own set of marks.
|
||||
*/
|
||||
case 'strong':
|
||||
case 'emphasis':
|
||||
case 'delete':
|
||||
{
|
||||
return processMarkNode(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Headings
|
||||
*
|
||||
* MDAST headings use a single type with a separate "depth" property to
|
||||
* indicate the heading level, while the Slate schema uses a separate node
|
||||
* type for each heading level. Here we get the proper Slate node name based
|
||||
* on the MDAST node depth.
|
||||
*/
|
||||
case 'heading':
|
||||
{
|
||||
const depthMap = {
|
||||
1: 'one',
|
||||
2: 'two',
|
||||
3: 'three',
|
||||
4: 'four',
|
||||
5: 'five',
|
||||
6: 'six'
|
||||
};
|
||||
const slateType = `heading-${depthMap[node.depth]}`;
|
||||
return createBlock(slateType, nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Code Blocks
|
||||
*
|
||||
* MDAST code blocks are a distinct node type with a simple text value. We
|
||||
* convert that value into a nested child text node for Slate. If a void
|
||||
* node is required due to a custom code block handler, the value is
|
||||
* stored in the "code" data property instead. We also carry over the "lang"
|
||||
* data property if it's defined.
|
||||
*/
|
||||
case 'code':
|
||||
{
|
||||
const data = _objectSpread(_objectSpread({
|
||||
lang: node.lang
|
||||
}, voidCodeBlock ? {
|
||||
code: node.value
|
||||
} : {}), {}, {
|
||||
shortcode: 'code-block',
|
||||
shortcodeData: {
|
||||
code: node.value,
|
||||
lang: node.lang
|
||||
}
|
||||
});
|
||||
const text = createText(voidCodeBlock ? '' : node.value);
|
||||
const nodes = [text];
|
||||
const block = createBlock('shortcode', nodes, {
|
||||
data
|
||||
});
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists
|
||||
*
|
||||
* MDAST has a single list type and an "ordered" property. We derive that
|
||||
* information into the Slate schema's distinct list node types. We also
|
||||
* include the "start" property, which indicates the number an ordered list
|
||||
* starts at, if defined.
|
||||
*/
|
||||
case 'list':
|
||||
{
|
||||
const slateType = node.ordered ? 'numbered-list' : 'bulleted-list';
|
||||
const data = {
|
||||
start: node.start
|
||||
};
|
||||
return createBlock(slateType, nodes, {
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Breaks
|
||||
*
|
||||
* MDAST soft break nodes represent a trailing double space or trailing
|
||||
* slash from a Markdown document. In Slate, these are simply transformed to
|
||||
* line breaks within a text node.
|
||||
*/
|
||||
case 'break':
|
||||
{
|
||||
const {
|
||||
data
|
||||
} = node;
|
||||
return createInline('break', {
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Thematic Breaks
|
||||
*
|
||||
* Thematic breaks are void nodes in the Slate schema.
|
||||
*/
|
||||
case 'thematicBreak':
|
||||
{
|
||||
return createBlock(typeMap[node.type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Links
|
||||
*
|
||||
* MDAST stores the link attributes directly on the node, while our Slate
|
||||
* schema references them in the data object.
|
||||
*/
|
||||
case 'link':
|
||||
{
|
||||
const {
|
||||
title,
|
||||
url,
|
||||
data
|
||||
} = node;
|
||||
const newData = _objectSpread(_objectSpread({}, data), {}, {
|
||||
title,
|
||||
url
|
||||
});
|
||||
return createInline(typeMap[node.type], {
|
||||
data: newData
|
||||
}, nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Images
|
||||
*
|
||||
* Identical to link nodes except for the lack of child nodes and addition
|
||||
* of alt attribute data MDAST stores the link attributes directly on the
|
||||
* node, while our Slate schema references them in the data object.
|
||||
*/
|
||||
case 'image':
|
||||
{
|
||||
const {
|
||||
title,
|
||||
url,
|
||||
alt,
|
||||
data
|
||||
} = node;
|
||||
const newData = _objectSpread(_objectSpread({}, data), {}, {
|
||||
title,
|
||||
alt,
|
||||
url
|
||||
});
|
||||
return createInline(typeMap[node.type], {
|
||||
data: newData
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tables
|
||||
*
|
||||
* Tables are parsed separately because they may include an "align"
|
||||
* property, which should be passed to the Slate node.
|
||||
*/
|
||||
case 'table':
|
||||
{
|
||||
const data = {
|
||||
align: node.align
|
||||
};
|
||||
return createBlock(typeMap[node.type], nodes, {
|
||||
data
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user