'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var escapeHtml = _interopDefault(require('escape-html')); function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } var defaultNodeTypes = { paragraph: 'paragraph', block_quote: 'block_quote', code_block: 'code_block', link: 'link', ul_list: 'ul_list', ol_list: 'ol_list', listItem: 'list_item', heading: { 1: 'heading_one', 2: 'heading_two', 3: 'heading_three', 4: 'heading_four', 5: 'heading_five', 6: 'heading_six' }, emphasis_mark: 'italic', strong_mark: 'bold', delete_mark: 'strikeThrough', inline_code_mark: 'code', thematic_break: 'thematic_break', image: 'image' }; function deserialize(node, opts) { var _opts$nodeTypes, _opts$linkDestination, _opts$imageSourceKey, _opts$imageCaptionKey, _ref, _ref2, _node$value, _extends2, _extends3, _extends4, _extends5; var types = _extends({}, defaultNodeTypes, opts === null || opts === void 0 ? void 0 : opts.nodeTypes, { heading: _extends({}, defaultNodeTypes.heading, opts === null || opts === void 0 ? void 0 : (_opts$nodeTypes = opts.nodeTypes) === null || _opts$nodeTypes === void 0 ? void 0 : _opts$nodeTypes.heading) }); var linkDestinationKey = (_opts$linkDestination = opts === null || opts === void 0 ? void 0 : opts.linkDestinationKey) !== null && _opts$linkDestination !== void 0 ? _opts$linkDestination : 'link'; var imageSourceKey = (_opts$imageSourceKey = opts === null || opts === void 0 ? void 0 : opts.imageSourceKey) !== null && _opts$imageSourceKey !== void 0 ? _opts$imageSourceKey : 'link'; var imageCaptionKey = (_opts$imageCaptionKey = opts === null || opts === void 0 ? void 0 : opts.imageCaptionKey) !== null && _opts$imageCaptionKey !== void 0 ? _opts$imageCaptionKey : 'caption'; var children = [{ text: '' }]; var nodeChildren = node.children; if (nodeChildren && Array.isArray(nodeChildren) && nodeChildren.length > 0) { children = nodeChildren.flatMap(function (c) { return deserialize(_extends({}, c, { ordered: node.ordered || false }), opts); }); } switch (node.type) { case 'heading': return { type: types.heading[node.depth || 1], children: children }; case 'list': return { type: node.ordered ? types.ol_list : types.ul_list, children: children }; case 'listItem': return { type: types.listItem, children: children }; case 'paragraph': return { type: types.paragraph, children: children }; case 'link': return _ref = { type: types.link }, _ref[linkDestinationKey] = node.url, _ref.children = children, _ref; case 'image': return _ref2 = { type: types.image, children: [{ text: '' }] }, _ref2[imageSourceKey] = node.url, _ref2[imageCaptionKey] = node.alt, _ref2; case 'blockquote': return { type: types.block_quote, children: children }; case 'code': return { type: types.code_block, language: node.lang, children: [{ text: node.value }] }; case 'html': if ((_node$value = node.value) !== null && _node$value !== void 0 && _node$value.includes('
')) { var _node$value2; return { "break": true, type: types.paragraph, children: [{ text: ((_node$value2 = node.value) === null || _node$value2 === void 0 ? void 0 : _node$value2.replace(/
/g, '')) || '' }] }; } return { type: 'paragraph', children: [{ text: node.value || '' }] }; case 'emphasis': return _extends((_extends2 = {}, _extends2[types.emphasis_mark] = true, _extends2), forceLeafNode(children), persistLeafFormats(children)); case 'strong': return _extends((_extends3 = {}, _extends3[types.strong_mark] = true, _extends3), forceLeafNode(children), persistLeafFormats(children)); case 'delete': return _extends((_extends4 = {}, _extends4[types.delete_mark] = true, _extends4), forceLeafNode(children), persistLeafFormats(children)); case 'inlineCode': return _extends((_extends5 = {}, _extends5[types.inline_code_mark] = true, _extends5.text = node.value, _extends5), persistLeafFormats(children)); case 'thematicBreak': return { type: types.thematic_break, children: [{ text: '' }] }; case 'text': default: return { text: node.value || '' }; } } var forceLeafNode = function forceLeafNode(children) { return { text: children.map(function (k) { return k === null || k === void 0 ? void 0 : k.text; }).join('') }; }; // This function is will take any unknown keys, and bring them up a level // allowing leaf nodes to have many different formats at once // for example, bold and italic on the same node function persistLeafFormats(children) { return children.reduce(function (acc, node) { Object.keys(node).forEach(function (key) { if (key === 'children' || key === 'type' || key === 'text') return; acc[key] = node[key]; }); return acc; }, {}); } var isLeafNode = function isLeafNode(node) { return typeof node.text === 'string'; }; var VOID_ELEMENTS = ['thematic_break', 'image']; var BREAK_TAG = '
'; function serialize(chunk, opts) { if (opts === void 0) { opts = { nodeTypes: defaultNodeTypes }; } var _opts = opts, _opts$nodeTypes = _opts.nodeTypes, userNodeTypes = _opts$nodeTypes === void 0 ? defaultNodeTypes : _opts$nodeTypes, _opts$ignoreParagraph = _opts.ignoreParagraphNewline, ignoreParagraphNewline = _opts$ignoreParagraph === void 0 ? false : _opts$ignoreParagraph, _opts$listDepth = _opts.listDepth, listDepth = _opts$listDepth === void 0 ? 0 : _opts$listDepth; var text = chunk.text || ''; var type = chunk.type || ''; var nodeTypes = _extends({}, defaultNodeTypes, userNodeTypes, { heading: _extends({}, defaultNodeTypes.heading, userNodeTypes.heading) }); var LIST_TYPES = [nodeTypes.ul_list, nodeTypes.ol_list]; var children = text; if (!isLeafNode(chunk)) { children = chunk.children.map(function (c) { var isList = !isLeafNode(c) ? LIST_TYPES.includes(c.type || '') : false; var selfIsList = LIST_TYPES.includes(chunk.type || ''); // Links can have the following shape // In which case we don't want to surround // with break tags // { // type: 'paragraph', // children: [ // { text: '' }, // { type: 'link', children: [{ text: foo.com }]} // { text: '' } // ] // } var childrenHasLink = false; if (!isLeafNode(chunk) && Array.isArray(chunk.children)) { childrenHasLink = chunk.children.some(function (f) { return !isLeafNode(f) && f.type === nodeTypes.link; }); } return serialize(_extends({}, c, { parentType: type }), { nodeTypes: nodeTypes, // WOAH. // what we're doing here is pretty tricky, it relates to the block below where // we check for ignoreParagraphNewline and set type to paragraph. // We want to strip out empty paragraphs sometimes, but other times we don't. // If we're the descendant of a list, we know we don't want a bunch // of whitespace. If we're parallel to a link we also don't want // to respect neighboring paragraphs ignoreParagraphNewline: (ignoreParagraphNewline || isList || selfIsList || childrenHasLink) && // if we have c.break, never ignore empty paragraph new line !c["break"], // track depth of nested lists so we can add proper spacing listDepth: LIST_TYPES.includes(c.type || '') ? listDepth + 1 : listDepth }); }).join(''); } // This is pretty fragile code, check the long comment where we iterate over children if (!ignoreParagraphNewline && (text === '' || text === '\n') && chunk.parentType === nodeTypes.paragraph) { type = nodeTypes.paragraph; children = BREAK_TAG; } if (children === '' && !VOID_ELEMENTS.find(function (k) { return nodeTypes[k] === type; })) return; // Never allow decorating break tags with rich text formatting, // this can malform generated markdown // Also ensure we're only ever applying text formatting to leaf node // level chunks, otherwise we can end up in a situation where // we try applying formatting like to a node like this: // "Text foo bar **baz**" resulting in "**Text foo bar **baz****" // which is invalid markup and can mess everything up if (children !== BREAK_TAG && isLeafNode(chunk)) { if (chunk.strikeThrough && chunk.bold && chunk.italic) { children = retainWhitespaceAndFormat(children, '~~***'); } else if (chunk.bold && chunk.italic) { children = retainWhitespaceAndFormat(children, '***'); } else { if (chunk.bold) { children = retainWhitespaceAndFormat(children, '**'); } if (chunk.italic) { children = retainWhitespaceAndFormat(children, '_'); } if (chunk.strikeThrough) { children = retainWhitespaceAndFormat(children, '~~'); } if (chunk.code) { children = retainWhitespaceAndFormat(children, '`'); } } } switch (type) { case nodeTypes.heading[1]: return "# " + children + "\n"; case nodeTypes.heading[2]: return "## " + children + "\n"; case nodeTypes.heading[3]: return "### " + children + "\n"; case nodeTypes.heading[4]: return "#### " + children + "\n"; case nodeTypes.heading[5]: return "##### " + children + "\n"; case nodeTypes.heading[6]: return "###### " + children + "\n"; case nodeTypes.block_quote: // For some reason, marked is parsing blockquotes w/ one new line // as contiued blockquotes, so adding two new lines ensures that doesn't // happen return "> " + children + "\n\n"; case nodeTypes.code_block: return "```" + (chunk.language || '') + "\n" + children + "\n```\n"; case nodeTypes.link: return "[" + children + "](" + (chunk.link || '') + ")"; case nodeTypes.image: return "![" + chunk.caption + "](" + (chunk.link || '') + ")"; case nodeTypes.ul_list: case nodeTypes.ol_list: return "\n" + children + "\n"; case nodeTypes.listItem: var isOL = chunk && chunk.parentType === nodeTypes.ol_list; var treatAsLeaf = chunk.children.length === 1 && isLeafNode(chunk.children[0]); var spacer = ''; for (var k = 0; listDepth > k; k++) { if (isOL) { // https://github.com/remarkjs/remark-react/issues/65 spacer += ' '; } else { spacer += ' '; } } return "" + spacer + (isOL ? '1.' : '-') + " " + children + (treatAsLeaf ? '\n' : ''); case nodeTypes.paragraph: return children + "\n"; case nodeTypes.thematic_break: return "---\n"; default: return escapeHtml(children); } } // This function handles the case of a string like this: " foo " // Where it would be invalid markdown to generate this: "** foo **" // We instead, want to trim the whitespace out, apply formatting, and then // bring the whitespace back. So our returned string looks like this: " **foo** " function retainWhitespaceAndFormat(string, format) { // we keep this for a comparison later var frozenString = string.trim(); // children will be mutated var children = frozenString; // We reverse the right side formatting, to properly handle bold/italic and strikeThrough // formats, so we can create ~~***FooBar***~~ var fullFormat = "" + format + children + reverseStr(format); // This conditions accounts for no whitespace in our string // if we don't have any, we can return early. if (children.length === string.length) { return fullFormat; } // if we do have whitespace, let's add our formatting around our trimmed string // We reverse the right side formatting, to properly handle bold/italic and strikeThrough // formats, so we can create ~~***FooBar***~~ var formattedString = format + children + reverseStr(format); // and replace the non-whitespace content of the string return string.replace(frozenString, formattedString); } var reverseStr = function reverseStr(string) { return string.split('').reverse().join(''); }; function plugin(opts) { var compiler = function compiler(node) { return node.children.map(function (c) { return deserialize(c, opts); }); }; // @ts-ignore this.Compiler = compiler; } exports.default = plugin; exports.defaultNodeTypes = defaultNodeTypes; exports.deserialize = deserialize; exports.serialize = serialize; //# sourceMappingURL=remark-slate.cjs.development.js.map