packages/netlify-cms-widget-markdown/src/serializers/slateRemark.js
function convertTextNode(node) {
  /**
   * If the Slate text node has a "leaves" property, translate the Slate AST to
   * a nested MDAST structure. Otherwise, just return an equivalent MDAST text
   * node.
   */
  if (node.leaves) {
    const processedLeaves = node.leaves.map(processLeaves);
    // Compensate for Slate including leading and trailing whitespace in styled text nodes, which
    // cannot be represented in markdown (https://github.com/netlify/netlify-cms/issues/1448)
    for (let i = 0; i < processedLeaves.length; i += 1) {
      const leaf = processedLeaves[i];
      if (leaf.marks.length > 0 && leaf.text && leaf.text.trim() !== leaf.text) {
        const [, leadingWhitespace, trailingWhitespace] = leaf.text.match(/^(\s*).*?(\s*)$/);
        // Move the leading whitespace to a separate unstyled leaf, unless the current leaf
        // is preceded by another one with (at least) the same marks applied:
        if (
          leadingWhitespace.length > 0 &&
          (i === 0 ||
            !leaf.marks.every(
              mark => processedLeaves[i - 1].marks && processedLeaves[i - 1].marks.includes(mark),
            ))
        ) {
          processedLeaves.splice(i, 0, {
            text: leadingWhitespace,
            marks: [],
            textNodeType: leaf.textNodeType,
          });
          i += 1;
          leaf.text = leaf.text.replace(/^\s+/, '');
        }
        // Move the trailing whitespace to a separate unstyled leaf, unless the current leaf
        // is followed by another one with (at least) the same marks applied:
        if (
          trailingWhitespace.length > 0 &&
          (i === processedLeaves.length - 1 ||
            !leaf.marks.every(
              mark => processedLeaves[i + 1].marks && processedLeaves[i + 1].marks.includes(mark),
            ))
        ) {
          processedLeaves.splice(i + 1, 0, {
            text: trailingWhitespace,
            marks: [],
            textNodeType: leaf.textNodeType,
          });
          i += 1;
          leaf.text = leaf.text.replace(/\s+$/, '');
        }
      }
    }
    const condensedNodes = processedLeaves.reduce(condenseNodesReducer, { nodes: [] });
    return condensedNodes.nodes;
  }

  if (node.object === 'inline') {
    return transform(node);
  }

  return u('html', node.text);
}
function convertTextNode(node) {
  /**
   * If the Slate text node has a "leaves" property, translate the Slate AST to
   * a nested MDAST structure. Otherwise, just return an equivalent MDAST text
   * node.
   */
  if (node.leaves) {
    const processedLeaves = node.leaves.map(processLeaves);
    // Compensate for Slate including leading and trailing whitespace in styled text nodes, which
    // cannot be represented in markdown (https://github.com/netlify/netlify-cms/issues/1448)
    for (let i = 0; i < processedLeaves.length; i += 1) {
      const leaf = processedLeaves[i];
      if (leaf.marks.length > 0 && leaf.text && leaf.text.trim() !== leaf.text) {
        const [, leadingWhitespace, trailingWhitespace] = leaf.text.match(/^(\s*).*?(\s*)$/);
        // Move the leading whitespace to a separate unstyled leaf, unless the current leaf
        // is preceded by another one with (at least) the same marks applied:
        if (
          leadingWhitespace.length > 0 &&
          (i === 0 ||
            !leaf.marks.every(
              mark => processedLeaves[i - 1].marks && processedLeaves[i - 1].marks.includes(mark),
            ))
        ) {
          processedLeaves.splice(i, 0, {
            text: leadingWhitespace,
            marks: [],
            textNodeType: leaf.textNodeType,
          });
          i += 1;
          leaf.text = leaf.text.replace(/^\s+/, '');
        }
        // Move the trailing whitespace to a separate unstyled leaf, unless the current leaf
        // is followed by another one with (at least) the same marks applied:
        if (
          trailingWhitespace.length > 0 &&
          (i === processedLeaves.length - 1 ||
            !leaf.marks.every(
              mark => processedLeaves[i + 1].marks && processedLeaves[i + 1].marks.includes(mark),
            ))
        ) {
          processedLeaves.splice(i + 1, 0, {
            text: trailingWhitespace,
            marks: [],
            textNodeType: leaf.textNodeType,
          });
          i += 1;
          leaf.text = leaf.text.replace(/\s+$/, '');
        }
      }
    }
    const condensedNodes = processedLeaves.reduce(condenseNodesReducer, { nodes: [] });
    return condensedNodes.nodes;
  }

  if (node.object === 'inline') {
    return transform(node);
  }

  return u('html', node.text);
}
function convertTextNode ( node ) { /**
   * If the Slate text node has a "leaves" property, translate the Slate AST to
   * a nested MDAST structure. Otherwise, just return an equivalent MDAST text
   * node.
   */ if ( node . leaves ) { const processedLeaves = node . leaves . map ( processLeaves ) ; // Compensate for Slate including leading and trailing whitespace in styled text nodes, which // cannot be represented in markdown (https://github.com/netlify/netlify-cms/issues/1448) for ( let i = 0 ; i < processedLeaves . length ; i += 1 ) { const leaf = processedLeaves [ i ] ; if ( leaf . marks . length > 0 && leaf . text && leaf . text . trim ( ) !== leaf . text ) { const [ , leadingWhitespace , trailingWhitespace ] = leaf . text . match ( / ^(\s*).*?(\s*)$ / ) ; // Move the leading whitespace to a separate unstyled leaf, unless the current leaf // is preceded by another one with (at least) the same marks applied: if ( leadingWhitespace . length > 0 && ( i === 0 || ! leaf . marks . every ( mark => processedLeaves [ i - 1 ] . marks && processedLeaves [ i - 1 ] . marks . includes ( mark ) , ) ) ) { processedLeaves . splice ( i , 0 , { text : leadingWhitespace , marks : [ ] , textNodeType : leaf . textNodeType , } ) ; i += 1 ; leaf . text = leaf . text . replace ( / ^\s+ / , '' ) ; } // Move the trailing whitespace to a separate unstyled leaf, unless the current leaf // is followed by another one with (at least) the same marks applied: if ( trailingWhitespace . length > 0 && ( i === processedLeaves . length - 1 || ! leaf . marks . every ( mark => processedLeaves [ i + 1 ] . marks && processedLeaves [ i + 1 ] . marks . includes ( mark ) , ) ) ) { processedLeaves . splice ( i + 1 , 0 , { text : trailingWhitespace , marks : [ ] , textNodeType : leaf . textNodeType , } ) ; i += 1 ; leaf . text = leaf . text . replace ( / \s+$ / , '' ) ; } } } const condensedNodes = processedLeaves . reduce ( condenseNodesReducer , { nodes : [ ] } ) ; return condensedNodes . nodes ; } if ( node . object === 'inline' ) { return transform ( node ) ; } return u ( 'html' , node . text ) ; }
Converts a Slate Raw text node to an MDAST text node.

Slate text nodes without marks often simply have a "text" property with
the value. In this case the conversion to MDAST is simple. If a Slate
text node does not have a "text" property, it will instead have a
"leaves" property containing an array of objects, each with an array of
marks, such as "bold" or "italic", along with a "text" property.

MDAST instead expresses such marks in a nested structure, with individual
nodes for each mark type nested until the deepest mark node, which will
contain the text node.

To convert a Slate text node's marks to MDAST, we treat each "leaf" as a
separate text node, convert the text node itself to an MDAST text node,
and then recursively wrap the text node for each mark, collecting the results
of each leaf in a single array of child nodes.

For example, this Slate text node:

{
object: 'text',
leaves: [
{
text: 'test',
marks: ['bold', 'italic']
},
{
text: 'test two'
}
]
}

...would be converted to this MDAST nested structure:

[
{
type: 'strong',
children: [{
type: 'emphasis',
children: [{
type: 'text',
value: 'test'
}]
}]
},
{
type: 'text',
value: 'test two'
}
]

This example also demonstrates how a single Slate node may need to be
replaced with multiple MDAST nodes, so the resulting array must be flattened.
Converts a Slate Raw text node to an MDAST text node .