diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 61ff556e8..69eab8b62 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -51,6 +51,9 @@ font-family: monospace; font-size: 72px; } + /* tspan { + font-size: 6px !important; + } */
@@ -58,7 +61,7 @@ %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% %% graph BT -a{The cat in the hat} -- 1o --> b +a("`The **cat** in the hat} -- 1o --> b a -- 2o --> c a -- 3o --> d g --2i--> a @@ -66,8 +69,47 @@ d --1i--> a h --3i -->a b --> d(The dog in the hog) c --> d +%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% -++flowchart LR +b("`The dog in **the** hog... a a a a *very long text* about it +Word! + +Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. `") +++ %%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR +b("`The dog in **the** hog... a a a a *very long text* about it +Word! +Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. `") +++ %%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR +b("The dog in the hog... a very+
long text about it
Word!") ++ %%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR +b("The dog in the hog... a very+
long text about it
Word!") ++flowchart LR +subgraph "One" + a("`The **cat** + in the hat`") -- 1o --> b{{"`The **dog** in the hog`"}} +end +subgraph "`**Two**`" + c("`The **cat** + in the hat`") -- "`1o **ipa**`" --> d("The dog in the hog") +end ++mindmap id1["`**Start2** second line 😎 with long text that is wrapping to the next line`"] @@ -83,8 +125,9 @@ mindmapmindmap id1["`**Start** with - a second line 😎`"] + id2["`The dog in **the** hog... a *very long text* about it +Word!`"]%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% @@ -290,9 +333,9 @@ mindmap // defaultRenderer: 'elk', useMaxWidth: false, // htmlLabels: false, - htmlLabels: true, + htmlLabels: false, }, - htmlLabels: true, + htmlLabels: false, gantt: { useMaxWidth: false, }, diff --git a/packages/mermaid/src/Diagram.ts b/packages/mermaid/src/Diagram.ts index 3010ce130..3943a84c2 100644 --- a/packages/mermaid/src/Diagram.ts +++ b/packages/mermaid/src/Diagram.ts @@ -44,6 +44,16 @@ export class Diagram { // calls diagram.db.clear(), which would reset anything set by // extractFrontMatter(). this.parser.parse = (text: string) => originalParse(extractFrontMatter(text, this.db)); + + // this.parser.parse = (text: string) => { + // console.log('parse called'); + // try { + // originalParse(extractFrontMatter(text, this.db)); + // } catch (e) { + // console.log('parse called', e); + // } + // }; + this.parser.parser.yy = this.db; if (diagram.init) { diagram.init(cnf); diff --git a/packages/mermaid/src/dagre-wrapper/clusters.js b/packages/mermaid/src/dagre-wrapper/clusters.js index 57c3ff513..453fcb8f5 100644 --- a/packages/mermaid/src/dagre-wrapper/clusters.js +++ b/packages/mermaid/src/dagre-wrapper/clusters.js @@ -1,12 +1,13 @@ import intersectRect from './intersect/intersect-rect'; import { log } from '../logger'; import createLabel from './createLabel'; +import { createText } from '../rendering-util/createText'; import { select } from 'd3'; import { getConfig } from '../config'; import { evaluate } from '../diagrams/common/common'; const rect = (parent, node) => { - log.trace('Creating subgraph rect for ', node.id, node); + log.info('Creating subgraph rect for ', node.id, node); // Add outer g element const shapeSvg = parent @@ -17,12 +18,18 @@ const rect = (parent, node) => { // add the rect const rect = shapeSvg.insert('rect', ':first-child'); + const useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels); + // Create the label and insert it after the rect const label = shapeSvg.insert('g').attr('class', 'cluster-label'); - const text = label - .node() - .appendChild(createLabel(node.labelText, node.labelStyle, undefined, true)); + // const text = label + // .node() + // .appendChild(createLabel(node.labelText, node.labelStyle, undefined, true)); + const text = + node.labelType === 'markdown' + ? createText(label, node.labelText, { style: node.labelStyle, useHtmlLabels }) + : label.node().appendChild(createLabel(node.labelText, node.labelStyle, undefined, true)); // Get the size of the label let bbox = text.getBBox(); @@ -61,7 +68,7 @@ const rect = (parent, node) => { 'transform', // This puts the labal on top of the box instead of inside it // 'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2 - bbox.height) + ')' - 'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2) + ')' + 'translate(' + node.x + ', ' + (node.y - node.height / 2) + ')' ); const rectBox = rect.node().getBBox(); diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js index f8c113694..4f83e938a 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.js +++ b/packages/mermaid/src/dagre-wrapper/edges.js @@ -1,5 +1,6 @@ import { log } from '../logger'; import createLabel from './createLabel'; +import { createText } from '../rendering-util/createText'; import { line, curveBasis, select } from 'd3'; import { getConfig } from '../config'; import utils from '../utils'; @@ -14,8 +15,13 @@ export const clear = () => { }; export const insertEdgeLabel = (elem, edge) => { + const useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels); // Create the actual text element - const labelElement = createLabel(edge.label, edge.labelStyle); + const labelElement = + edge.labelType === 'markdown' + ? createText(elem, edge.label, { style: edge.labelStyle, useHtmlLabels }) + : createLabel(edge.label, edge.labelStyle); + log.info('abc82', edge, edge.labelType); // Create outer g, edgeLabel, this will be positioned after graph layout const edgeLabel = elem.insert('g').attr('class', 'edgeLabel'); @@ -26,7 +32,7 @@ export const insertEdgeLabel = (elem, edge) => { // Center the label let bbox = labelElement.getBBox(); - if (evaluate(getConfig().flowchart.htmlLabels)) { + if (useHtmlLabels) { const div = labelElement.children[0]; const dv = select(labelElement); bbox = div.getBoundingClientRect(); diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js index 49b96b685..3e71f500a 100644 --- a/packages/mermaid/src/dagre-wrapper/nodes.js +++ b/packages/mermaid/src/dagre-wrapper/nodes.js @@ -313,19 +313,18 @@ const cylinder = (parent, node) => { const rect = (parent, node) => { const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'node ' + node.classes, true); - log.trace('Classes = ', node.classes); // add the rect const rect = shapeSvg.insert('rect', ':first-child'); - const totalWidth = bbox.width + node.padding; - const totalHeight = bbox.height + node.padding; + const totalWidth = bbox.width + node.padding * 2; + const totalHeight = bbox.height + node.padding * 2; rect .attr('class', 'basic label-container') .attr('style', node.style) .attr('rx', node.rx) .attr('ry', node.ry) - .attr('x', -bbox.width / 2 - halfPadding) - .attr('y', -bbox.height / 2 - halfPadding) + .attr('x', -bbox.width / 2 - node.padding) + .attr('y', -bbox.height / 2 - node.padding) .attr('width', totalWidth) .attr('height', totalHeight); @@ -352,7 +351,7 @@ const rect = (parent, node) => { const labelRect = (parent, node) => { const { shapeSvg } = labelHelper(parent, node, 'label', true); - log.trace('Classes = ', node.classes); + log.info('Classes = ', node.classes); // add the rect const rect = shapeSvg.insert('rect', ':first-child'); diff --git a/packages/mermaid/src/dagre-wrapper/shapes/util.js b/packages/mermaid/src/dagre-wrapper/shapes/util.js index 6de0da638..d362d08f6 100644 --- a/packages/mermaid/src/dagre-wrapper/shapes/util.js +++ b/packages/mermaid/src/dagre-wrapper/shapes/util.js @@ -1,4 +1,5 @@ import createLabel from '../createLabel'; +import { createText } from '../../rendering-util/createText'; import { getConfig } from '../../config'; import { decodeEntities } from '../../mermaidAPI'; import { select } from 'd3'; @@ -27,9 +28,17 @@ export const labelHelper = (parent, node, _classes, isNode) => { labelText = typeof node.labelText === 'string' ? node.labelText : node.labelText[0]; } - const text = label - .node() - .appendChild( + const textNode = label.node(); + let text; + if (node.labelType === 'markdown') { + // text = textNode; + text = createText(label, sanitizeText(decodeEntities(labelText), getConfig()), { + useHtmlLabels: getConfig().flowchart.htmlLabels, + width: node.width || 200, + classes: 'markdown-node-label', + }); + } else { + text = textNode.appendChild( createLabel( sanitizeText(decodeEntities(labelText), getConfig()), node.labelStyle, @@ -37,6 +46,7 @@ export const labelHelper = (parent, node, _classes, isNode) => { isNode ) ); + } // Get the size of the label let bbox = text.getBBox(); @@ -52,7 +62,11 @@ export const labelHelper = (parent, node, _classes, isNode) => { const halfPadding = node.padding / 2; // Center the label - label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')'); + if (getConfig().flowchart.htmlLabels) { + label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')'); + } else { + label.attr('transform', 'translate(' + 0 + ', ' + -bbox.height / 2 + ')'); + } return { shapeSvg, bbox, halfPadding, label }; }; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.js b/packages/mermaid/src/diagrams/flowchart/flowDb.js index 31196ba96..26bc75c14 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.js +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.js @@ -59,13 +59,14 @@ export const lookUpDomId = function (id) { * * @param _id * @param text + * @param textObj * @param type * @param style * @param classes * @param dir * @param props */ -export const addVertex = function (_id, text, type, style, classes, dir, props = {}) { +export const addVertex = function (_id, textObj, type, style, classes, dir, props = {}) { let txt; let id = _id; if (id === undefined) { @@ -80,16 +81,17 @@ export const addVertex = function (_id, text, type, style, classes, dir, props = if (vertices[id] === undefined) { vertices[id] = { id: id, + labelType: 'text', domId: MERMAID_DOM_ID_PREFIX + id + '-' + vertexCounter, styles: [], classes: [], }; } vertexCounter++; - if (text !== undefined) { + if (textObj !== undefined) { config = configApi.getConfig(); - txt = sanitizeText(text.trim()); - + txt = sanitizeText(textObj.text.trim()); + vertices[id].labelType = textObj.type; // strip quotes if string starts and ends with a quote if (txt[0] === '"' && txt[txt.length - 1] === '"') { txt = txt.substring(1, txt.length - 1); @@ -131,24 +133,26 @@ export const addVertex = function (_id, text, type, style, classes, dir, props = * @param _end * @param type * @param linkText + * @param linkTextObj */ -export const addSingleLink = function (_start, _end, type, linkText) { +export const addSingleLink = function (_start, _end, type) { let start = _start; let end = _end; // if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start; // if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end; // log.info('Got edge...', start, end); - const edge = { start: start, end: end, type: undefined, text: '' }; - linkText = type.text; + const edge = { start: start, end: end, type: undefined, text: '', labelType: 'text' }; + const linkTextObj = type.text; - if (linkText !== undefined) { - edge.text = sanitizeText(linkText.trim()); + if (linkTextObj !== undefined) { + edge.text = sanitizeText(linkTextObj.text.trim()); // strip quotes if string starts and ends with a quote if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') { edge.text = edge.text.substring(1, edge.text.length - 1); } + edge.labelType = linkTextObj.type; } if (type !== undefined) { @@ -158,11 +162,11 @@ export const addSingleLink = function (_start, _end, type, linkText) { } edges.push(edge); }; -export const addLink = function (_start, _end, type, linktext) { +export const addLink = function (_start, _end, type) { let i, j; for (i = 0; i < _start.length; i++) { for (j = 0; j < _end.length; j++) { - addSingleLink(_start[i], _end[j], type, linktext); + addSingleLink(_start[i], _end[j], type); } } }; @@ -457,10 +461,9 @@ export const defaultStyle = function () { * @param _title */ export const addSubGraph = function (_id, list, _title) { - // console.log('addSubGraph', _id, list, _title); - let id = _id.trim(); - let title = _title; - if (_id === _title && _title.match(/\s/)) { + let id = _id.text.trim(); + let title = _title.text; + if (_id === _title && _title.text.match(/\s/)) { id = undefined; } /** @param a */ @@ -502,7 +505,14 @@ export const addSubGraph = function (_id, list, _title) { title = title || ''; title = sanitizeText(title); subCount = subCount + 1; - const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [], dir }; + const subGraph = { + id: id, + nodes: nodeList, + title: title.trim(), + classes: [], + dir, + labelType: _title.type, + }; log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir); diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js index 2d3e21a44..a87f23e04 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js @@ -47,7 +47,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) { if (vertex.classes.length > 0) { classStr = vertex.classes.join(' '); } - + classStr = classStr + ' flowchart-label'; const styles = getStylesFromArray(vertex.styles); // Use vertex id as text in the box if no text is provided by the graph definition @@ -55,31 +55,36 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) { // We create a SVG label, either by delegating to addHtmlLabel or manually let vertexNode; - if (evaluate(getConfig().flowchart.htmlLabels)) { - // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? - const node = { - label: vertexText.replace( - /fa[blrs]?:fa-[\w-]+/g, - (s) => `` - ), - }; - vertexNode = addHtmlLabel(svg, node).node(); - vertexNode.parentNode.removeChild(vertexNode); + log.info('vertex', vertex, vertex.labelType); + if (vertex.labelType === 'markdown') { + log.info('vertex', vertex, vertex.labelType); } else { - const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text'); - svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); + if (evaluate(getConfig().flowchart.htmlLabels)) { + // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? + const node = { + label: vertexText.replace( + /fa[blrs]?:fa-[\w-]+/g, + (s) => `` + ), + }; + vertexNode = addHtmlLabel(svg, node).node(); + vertexNode.parentNode.removeChild(vertexNode); + } else { + const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text'); + svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); - const rows = vertexText.split(common.lineBreakRegex); + const rows = vertexText.split(common.lineBreakRegex); - for (const row of rows) { - const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan'); - tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); - tspan.setAttribute('dy', '1em'); - tspan.setAttribute('x', '1'); - tspan.textContent = row; - svgLabel.appendChild(tspan); + for (const row of rows) { + const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan'); + tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); + tspan.setAttribute('dy', '1em'); + tspan.setAttribute('x', '1'); + tspan.textContent = row; + svgLabel.appendChild(tspan); + } + vertexNode = svgLabel; } - vertexNode = svgLabel; } let radious = 0; @@ -146,6 +151,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) { labelStyle: styles.labelStyle, shape: _shape, labelText: vertexText, + labelType: vertex.labelType, rx: radious, ry: radious, class: classStr, @@ -165,6 +171,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) { log.info('setNode', { labelStyle: styles.labelStyle, + labelType: vertex.labelType, shape: _shape, labelText: vertexText, rx: radious, @@ -312,7 +319,7 @@ export const addEdges = function (edges, g, diagObj) { edgeData.labelpos = 'c'; } - edgeData.labelType = 'text'; + edgeData.labelType = edge.labelType; edgeData.label = edge.text.replace(common.lineBreakRegex, '\n'); if (edge.style === undefined) { @@ -405,7 +412,14 @@ export const draw = function (text, id, _version, diagObj) { for (let i = subGraphs.length - 1; i >= 0; i--) { subG = subGraphs[i]; log.info('Subgraph - ', subG); - diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir); + diagObj.db.addVertex( + subG.id, + { text: subG.title, type: subG.labelType }, + 'group', + undefined, + subG.classes, + subG.dir + ); } // Fetch the vertices/nodes and edges/links from the parsed graph definition diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison index e2dad5881..d21104d49 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison @@ -7,6 +7,7 @@ /* lexical grammar */ %lex %x string +%x md_string %x acc_title %x acc_descr %x acc_descr_multiline @@ -37,6 +38,9 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili[\}] { this.popState(); } [^\}]* return "acc_descr_multiline_value"; // .*[^\n]* { return "acc_descr_line"} +["][`] { this.begin("md_string");} + [^`"]+ { return "MD_STR";} + [`]["] { this.popState();} ["] this.begin("string"); ["] this.popState(); [^"]* return "STR"; @@ -434,11 +438,13 @@ arrowText: ; text: textToken - {$$=$1;} + {$$={text:$1, type: 'text'};} | text textToken - {$$=$1+''+$2;} + {$$={text:$1.text+''+$2, type: 'text'};} | STR - {$$=$1;} + {$$={text: $1, type: 'text'};} + | MD_STR + {$$={text: $1, type: 'markdown'};} ; diff --git a/packages/mermaid/src/diagrams/flowchart/styles.ts b/packages/mermaid/src/diagrams/flowchart/styles.ts index a89d33d3d..86ffcb7ed 100644 --- a/packages/mermaid/src/diagrams/flowchart/styles.ts +++ b/packages/mermaid/src/diagrams/flowchart/styles.ts @@ -41,6 +41,15 @@ const getStyles = (options: FlowChartStyleOptions) => stroke: ${options.nodeBorder}; stroke-width: 1px; } + .flowchart-label text { + text-anchor: middle; + } + // .flowchart-label .text-outer-tspan { + // text-anchor: middle; + // } + // .flowchart-label .text-inner-tspan { + // text-anchor: start; + // } .node .label { text-align: center; diff --git a/packages/mermaid/src/rendering-util/createText.js b/packages/mermaid/src/rendering-util/createText.js index 5eea6f4c8..0fc7dda54 100644 --- a/packages/mermaid/src/rendering-util/createText.js +++ b/packages/mermaid/src/rendering-util/createText.js @@ -49,7 +49,7 @@ function addHtmlSpan(element, node, width, classes) { if (bbox.width === width) { div.style('display', 'table'); div.style('white-space', 'break-spaces'); - div.style('width', '200px'); + div.style('width', width + 'px'); bbox = div.node().getBoundingClientRect(); } @@ -70,8 +70,9 @@ function addHtmlSpan(element, node, width, classes) { function createTspan(textElement, lineIndex, lineHeight) { return textElement .append('tspan') + .attr('class', 'text-outer-tspan') .attr('x', 0) - .attr('y', lineIndex * lineHeight + 'em') + .attr('y', lineIndex * lineHeight - 0.1 + 'em') .attr('dy', lineHeight + 'em'); } @@ -86,9 +87,13 @@ function createTspan(textElement, lineIndex, lineHeight) { function createFormattedText(width, g, structuredText) { const lineHeight = 1.1; - const textElement = g.append('text'); - - structuredText.forEach((line, lineIndex) => { + const textElement = g.append('text').attr('y', '-10.1'); + // .attr('dominant-baseline', 'middle') + // .attr('text-anchor', 'middle'); + // .attr('text-anchor', 'middle'); + let lineIndex = -1; + structuredText.forEach((line) => { + lineIndex++; let tspan = createTspan(textElement, lineIndex, lineHeight); let words = [...line].reverse(); @@ -108,10 +113,13 @@ function createFormattedText(width, g, structuredText) { updateTextContentAndStyles(tspan, wrappedLine); wrappedLine = []; - tspan = createTspan(textElement, ++lineIndex, lineHeight); + lineIndex++; + tspan = createTspan(textElement, lineIndex, lineHeight); } } }); + return textElement.node(); + // return g.node(); } /** @@ -124,12 +132,36 @@ function createFormattedText(width, g, structuredText) { function updateTextContentAndStyles(tspan, wrappedLine) { tspan.text(''); - wrappedLine.forEach((word) => { - tspan + wrappedLine.forEach((word, index) => { + const innerTspan = tspan .append('tspan') .attr('font-style', word.type === 'em' ? 'italic' : 'normal') - .attr('font-weight', word.type === 'strong' ? 'bold' : 'normal') - .text(word.content + ' '); + .attr('class', 'text-inner-tspan') + .attr('font-weight', word.type === 'strong' ? 'bold' : 'normal'); + const special = [ + '<', + '>', + '&', + '"', + "'", + '.', + ',', + ':', + ';', + '!', + '?', + '(', + ')', + '[', + ']', + '{', + '}', + ]; + if (index !== 0 && special.includes(word.content)) { + innerTspan.text(word.content); + } else { + innerTspan.text(' ' + word.content); + } }); } diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.js b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.js index 005dd42f6..5e74a9956 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.js +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.js @@ -169,6 +169,37 @@ it('markdownToLines - Mixed formatting', () => { expect(output).toEqual(expectedOutput); }); +it('markdownToLines - Mixed formatting', () => { + const input = `The dog in **the** hog... a *very long text* about it +Word!`; + + const expectedOutput = [ + [ + { content: 'The', type: 'normal' }, + { content: 'dog', type: 'normal' }, + { content: 'in', type: 'normal' }, + { content: 'the', type: 'strong' }, + { content: 'hog', type: 'normal' }, + { content: '.', type: 'normal' }, + { content: '.', type: 'normal' }, + { content: '.', type: 'normal' }, + { content: 'a', type: 'normal' }, + { content: 'very', type: 'em' }, + { content: 'long', type: 'em' }, + { content: 'text', type: 'em' }, + { content: 'about', type: 'normal' }, + { content: 'it', type: 'normal' }, + ], + [ + { content: 'Word', type: 'normal' }, + { content: '!', type: 'normal' }, + ], + ]; + + const output = markdownToLines(input); + expect(output).toEqual(expectedOutput); +}); + test('markdownToHTML - Basic test', () => { const input = `This is regular text Here is a new line