diff --git a/packages/mermaid/package.json b/packages/mermaid/package.json index bec56d3a04..982b9d0633 100644 --- a/packages/mermaid/package.json +++ b/packages/mermaid/package.json @@ -81,7 +81,7 @@ "katex": "^0.16.9", "khroma": "^2.1.0", "lodash-es": "^4.17.21", - "mdast-util-from-markdown": "^2.0.0", + "marked": "^13.0.2", "stylis": "^4.3.1", "ts-dedent": "^2.2.0", "uuid": "^9.0.1" diff --git a/packages/mermaid/src/rendering-util/createText.ts b/packages/mermaid/src/rendering-util/createText.ts index 18695c8187..462a4834f1 100644 --- a/packages/mermaid/src/rendering-util/createText.ts +++ b/packages/mermaid/src/rendering-util/createText.ts @@ -153,7 +153,7 @@ function updateTextContentAndStyles(tspan: any, wrappedLine: MarkdownWord[]) { wrappedLine.forEach((word, index) => { const innerTspan = tspan .append('tspan') - .attr('font-style', word.type === 'emphasis' ? 'italic' : 'normal') + .attr('font-style', word.type === 'em' ? 'italic' : 'normal') .attr('class', 'text-inner-tspan') .attr('font-weight', word.type === 'strong' ? 'bold' : 'normal'); if (index === 0) { diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts index 7362e6f70f..3ab4167a22 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-irregular-whitespace */ import { markdownToLines, markdownToHTML } from './handle-markdown-text.js'; import { test, expect } from 'vitest'; @@ -37,9 +36,9 @@ Here is a line *with an italic* section`; { content: 'is', type: 'normal' }, { content: 'a', type: 'normal' }, { content: 'line', type: 'normal' }, - { content: 'with', type: 'emphasis' }, - { content: 'an', type: 'emphasis' }, - { content: 'italic', type: 'emphasis' }, + { content: 'with', type: 'em' }, + { content: 'an', type: 'em' }, + { content: 'italic', type: 'em' }, { content: 'section', type: 'normal' }, ], ]; @@ -143,7 +142,7 @@ test('markdownToLines - Only italic formatting', () => { { content: 'This', type: 'normal' }, { content: 'is', type: 'normal' }, { content: 'an', type: 'normal' }, - { content: 'italic', type: 'emphasis' }, + { content: 'italic', type: 'em' }, { content: 'test', type: 'normal' }, ], ]; @@ -156,7 +155,7 @@ it('markdownToLines - Mixed formatting', () => { let input = `*Italic* and **bold** formatting`; let expected = [ [ - { content: 'Italic', type: 'emphasis' }, + { content: 'Italic', type: 'em' }, { content: 'and', type: 'normal' }, { content: 'bold', type: 'strong' }, { content: 'formatting', type: 'normal' }, @@ -167,9 +166,9 @@ it('markdownToLines - Mixed formatting', () => { input = `*Italic with space* and **bold ws** formatting`; expected = [ [ - { content: 'Italic', type: 'emphasis' }, - { content: 'with', type: 'emphasis' }, - { content: 'space', type: 'emphasis' }, + { content: 'Italic', type: 'em' }, + { content: 'with', type: 'em' }, + { content: 'space', type: 'em' }, { content: 'and', type: 'normal' }, { content: 'bold', type: 'strong' }, { content: 'ws', type: 'strong' }, @@ -191,9 +190,9 @@ Word!`; { content: 'the', type: 'strong' }, { content: 'hog...', type: 'normal' }, { content: 'a', type: 'normal' }, - { content: 'very', type: 'emphasis' }, - { content: 'long', type: 'emphasis' }, - { content: 'text', type: 'emphasis' }, + { content: 'very', type: 'em' }, + { content: 'long', type: 'em' }, + { content: 'text', type: 'em' }, { content: 'about', type: 'normal' }, { content: 'it', type: 'normal' }, ], @@ -215,13 +214,13 @@ test('markdownToLines - No auto wrapping', () => { [ [ { - "content": "Hello, how do", + "content": "Hello, how do", "type": "normal", }, ], [ { - "content": "you do?", + "content": "you do?", "type": "normal", }, ], @@ -298,3 +297,13 @@ test('markdownToHTML - no auto wrapping', () => { ) ).toMatchInlineSnapshot('"

Hello, how do
you do?

"'); }); + +test('markdownToHTML - auto wrapping', () => { + expect( + markdownToHTML( + `Hello, how do + you do?`, + { markdownAutoWrap: true } + ) + ).toMatchInlineSnapshot('"

Hello, how do
you do?

"'); +}); diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.ts index c539f72684..3846e7f37e 100644 --- a/packages/mermaid/src/rendering-util/handle-markdown-text.ts +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.ts @@ -1,5 +1,5 @@ -import type { Content } from 'mdast'; -import { fromMarkdown } from 'mdast-util-from-markdown'; +import type { MarkedToken, Token } from 'marked'; +import { marked } from 'marked'; import { dedent } from 'ts-dedent'; import type { MarkdownLine, MarkdownWordType } from './types.js'; import type { MermaidConfig } from '../config.type.js'; @@ -24,13 +24,13 @@ function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfi */ export function markdownToLines(markdown: string, config: MermaidConfig = {}): MarkdownLine[] { const preprocessedMarkdown = preprocessMarkdown(markdown, config); - const { children } = fromMarkdown(preprocessedMarkdown); + const nodes = marked.lexer(preprocessedMarkdown); const lines: MarkdownLine[] = [[]]; let currentLine = 0; - function processNode(node: Content, parentType: MarkdownWordType = 'normal') { + function processNode(node: MarkedToken, parentType: MarkdownWordType = 'normal') { if (node.type === 'text') { - const textLines = node.value.split('\n'); + const textLines = node.text.split('\n'); textLines.forEach((textLine, index) => { if (index !== 0) { currentLine++; @@ -42,17 +42,17 @@ export function markdownToLines(markdown: string, config: MermaidConfig = {}): M } }); }); - } else if (node.type === 'strong' || node.type === 'emphasis') { - node.children.forEach((contentNode) => { - processNode(contentNode, node.type); + } else if (node.type === 'strong' || node.type === 'em') { + node.tokens.forEach((contentNode) => { + processNode(contentNode as MarkedToken, node.type); }); } } - children.forEach((treeNode) => { + nodes.forEach((treeNode) => { if (treeNode.type === 'paragraph') { - treeNode.children.forEach((contentNode) => { - processNode(contentNode); + treeNode.tokens?.forEach((contentNode) => { + processNode(contentNode as MarkedToken); }); } }); @@ -61,23 +61,23 @@ export function markdownToLines(markdown: string, config: MermaidConfig = {}): M } export function markdownToHTML(markdown: string, { markdownAutoWrap }: MermaidConfig = {}) { - const { children } = fromMarkdown(markdown); + const nodes = marked.lexer(markdown); - function output(node: Content): string { + function output(node: Token): string { if (node.type === 'text') { if (markdownAutoWrap === false) { - return node.value.replace(/\n/g, '
').replace(/ /g, ' '); + return node.text.replace(/\n */g, '
').replace(/ /g, ' '); } - return node.value.replace(/\n/g, '
'); + return node.text.replace(/\n */g, '
'); } else if (node.type === 'strong') { - return `${node.children.map(output).join('')}`; - } else if (node.type === 'emphasis') { - return `${node.children.map(output).join('')}`; + return `${node.tokens?.map(output).join('')}`; + } else if (node.type === 'em') { + return `${node.tokens?.map(output).join('')}`; } else if (node.type === 'paragraph') { - return `

${node.children.map(output).join('')}

`; + return `

${node.tokens?.map(output).join('')}

`; } return `Unsupported markdown: ${node.type}`; } - return children.map(output).join(''); + return nodes.map(output).join(''); } diff --git a/packages/mermaid/src/rendering-util/types.d.ts b/packages/mermaid/src/rendering-util/types.d.ts index 6dabb476d0..d7a06a8fd9 100644 --- a/packages/mermaid/src/rendering-util/types.d.ts +++ b/packages/mermaid/src/rendering-util/types.d.ts @@ -1,4 +1,4 @@ -export type MarkdownWordType = 'normal' | 'strong' | 'emphasis'; +export type MarkdownWordType = 'normal' | 'strong' | 'em'; export interface MarkdownWord { content: string; type: MarkdownWordType; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35d96ff4ba..20475ea936 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -239,9 +239,9 @@ importers: lodash-es: specifier: ^4.17.21 version: 4.17.21 - mdast-util-from-markdown: - specifier: ^2.0.0 - version: 2.0.1 + marked: + specifier: ^13.0.2 + version: 13.0.2 stylis: specifier: ^4.3.1 version: 4.3.2 @@ -6831,6 +6831,11 @@ packages: markdown-table@3.0.3: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + marked@13.0.2: + resolution: {integrity: sha512-J6CPjP8pS5sgrRqxVRvkCIkZ6MFdRIjDkwUwgJ9nL2fbmM6qGQeB2C16hi8Cc9BOzj6xXzy0jyi0iPIfnMHYzA==} + engines: {node: '>= 18'} + hasBin: true + marked@4.3.0: resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} engines: {node: '>= 12'} @@ -17665,6 +17670,8 @@ snapshots: markdown-table@3.0.3: {} + marked@13.0.2: {} + marked@4.3.0: {} mdast-builder@1.1.1: diff --git a/scripts/size.ts b/scripts/size.ts index 2190fd9ef2..1c486197b0 100644 --- a/scripts/size.ts +++ b/scripts/size.ts @@ -25,6 +25,7 @@ const formatBytes = (bytes: number): string => { if (bytes == 0) { return '0 Bytes'; } + bytes = Math.abs(bytes); const base = 1024; const decimals = 2; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];