@chayns-components/format 5.0.0-beta.650 → 5.0.0-beta.674

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/lib/cjs/types/format.js +2 -0
  2. package/lib/cjs/types/format.js.map +1 -0
  3. package/lib/cjs/utils/escape.js +1 -3
  4. package/lib/cjs/utils/escape.js.map +1 -1
  5. package/lib/cjs/utils/formatString/bb-code/findBBCode.js +6 -4
  6. package/lib/cjs/utils/formatString/bb-code/findBBCode.js.map +1 -1
  7. package/lib/cjs/utils/formatString/bb-code/formatBBCode.js +37 -37
  8. package/lib/cjs/utils/formatString/bb-code/formatBBCode.js.map +1 -1
  9. package/lib/cjs/utils/formatString/formatString.js +30 -42
  10. package/lib/cjs/utils/formatString/formatString.js.map +1 -1
  11. package/lib/cjs/utils/formatString/formatString.test.js +549 -0
  12. package/lib/cjs/utils/formatString/formatString.test.js.map +1 -0
  13. package/lib/cjs/utils/formatString/markdown/formatMarkdown.js +145 -29
  14. package/lib/cjs/utils/formatString/markdown/formatMarkdown.js.map +1 -1
  15. package/lib/esm/types/format.js +2 -0
  16. package/lib/esm/types/format.js.map +1 -0
  17. package/lib/esm/utils/escape.js +0 -1
  18. package/lib/esm/utils/escape.js.map +1 -1
  19. package/lib/esm/utils/formatString/bb-code/findBBCode.js +6 -4
  20. package/lib/esm/utils/formatString/bb-code/findBBCode.js.map +1 -1
  21. package/lib/esm/utils/formatString/bb-code/formatBBCode.js +37 -39
  22. package/lib/esm/utils/formatString/bb-code/formatBBCode.js.map +1 -1
  23. package/lib/esm/utils/formatString/formatString.js +33 -45
  24. package/lib/esm/utils/formatString/formatString.js.map +1 -1
  25. package/lib/esm/utils/formatString/formatString.test.js +547 -0
  26. package/lib/esm/utils/formatString/formatString.test.js.map +1 -0
  27. package/lib/esm/utils/formatString/markdown/formatMarkdown.js +141 -26
  28. package/lib/esm/utils/formatString/markdown/formatMarkdown.js.map +1 -1
  29. package/lib/types/types/format.d.ts +5 -0
  30. package/lib/types/utils/escape.d.ts +0 -1
  31. package/lib/types/utils/formatString/bb-code/findBBCode.d.ts +2 -0
  32. package/lib/types/utils/formatString/bb-code/formatBBCode.d.ts +3 -4
  33. package/lib/types/utils/formatString/formatString.d.ts +1 -3
  34. package/lib/types/utils/formatString/formatString.test.d.ts +1 -0
  35. package/lib/types/utils/formatString/markdown/formatMarkdown.d.ts +3 -1
  36. package/package.json +6 -4
  37. package/lib/cjs/utils/formatString/markdown/formatMarkdownTable.js +0 -86
  38. package/lib/cjs/utils/formatString/markdown/formatMarkdownTable.js.map +0 -1
  39. package/lib/esm/utils/formatString/markdown/formatMarkdownTable.js +0 -78
  40. package/lib/esm/utils/formatString/markdown/formatMarkdownTable.js.map +0 -1
  41. package/lib/types/utils/formatString/markdown/formatMarkdownTable.d.ts +0 -9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatString.test.js","names":["_vitest","require","_formatString","removeLinebreaks","text","replace","describe","test","result","formatStringToHtml","expect","html","toEqual","tables","resultEscape","resultEscape1","resultEscape2","boldResult","italicResult","inlineCodeResult","h1Result","h2Result","h3Result","h4Result","h5Result","h6Result","expectedUnorderedListResult","expectedOrderedListResult","unorderedListResult1","unorderedListResult2","orderedListResult","orderedListResult2","expectedThematicBreakResult","result1","result2","resultWithoutLanguage","resultWithLanguage","inputString","csv","raw","id","parseBBCode","table1","getTable1Result","index","table1Csv","table2","getTable2TResult","table2Csv","getHeadingInput","tag","getHeadingOutput","headingTags","forEach","input","output","customInlineLevelBBCodeTags","customBlockLevelBBCodeTags"],"sources":["../../../../src/utils/formatString/formatString.test.ts"],"sourcesContent":["import { describe, expect, test } from 'vitest';\nimport { formatStringToHtml } from './formatString';\n\nconst removeLinebreaks = (text: string) => text.replace(/\\n/g, '');\n\ndescribe('HTML Formatter Function', () => {\n describe('Format Plain Text', () => {\n describe('Line breaks', () => {\n test('should format line breaks correctly', () => {\n const result = formatStringToHtml('Line 1\\nLine 2');\n expect(result.html).toEqual('<p>Line 1\\nLine 2</p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format multiple line breaks correctly', () => {\n const result = formatStringToHtml('Line 1\\n\\nLine 2');\n expect(result.html).toEqual('<p>Line 1</p>\\n<p>Line 2</p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should remove trailing and leading new lines', () => {\n const result = formatStringToHtml('\\n\\n\\nLine 1\\n\\n\\n');\n expect(result.html).toEqual('<p>Line 1</p>');\n expect(result.tables).toEqual([]);\n });\n });\n\n describe('Whitespaces', () => {\n test('should not remove repeated whitespaces', () => {\n const result = formatStringToHtml('Text with spaces');\n expect(result.html).toEqual('<p>Text with spaces</p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should not remove leading and trailing whitespaces', () => {\n const result = formatStringToHtml(' Text ');\n expect(result.html).toEqual('<p> Text </p>');\n expect(result.tables).toEqual([]);\n });\n });\n\n describe('HTML', () => {\n test('should escape < and > correctly', () => {\n const resultEscape = formatStringToHtml('<div>Test</div>');\n expect(resultEscape.html).toEqual('<p>&lt;div&gt;Test&lt;/div&gt;</p>');\n expect(resultEscape.tables).toEqual([]);\n });\n\n test('should not escape &', () => {\n const resultEscape1 = formatStringToHtml('&lt;div&gt;Test&lt;/div&gt;');\n expect(resultEscape1.html).toEqual('<p>&lt;div&gt;Test&lt;/div&gt;</p>');\n expect(resultEscape1.tables).toEqual([]);\n\n const resultEscape2 = formatStringToHtml(\n '&amp;lt;div&amp;gt;Test&amp;lt;/div&amp;gt;',\n );\n expect(resultEscape2.html).toEqual(\n '<p>&amp;lt;div&amp;gt;Test&amp;lt;/div&amp;gt;</p>',\n );\n expect(resultEscape2.tables).toEqual([]);\n });\n\n // TODO Decide if & should be escaped, when they are not part of an HTML entity.\n });\n\n describe('URLs', () => {\n test('should not format URLs', () => {\n const result = formatStringToHtml('https://example.com');\n expect(result.html).toEqual('<p>https://example.com</p>');\n expect(result.tables).toEqual([]);\n });\n });\n });\n\n describe('Format Markdown', () => {\n describe('All Elements', () => {\n test('should format text styling correctly', () => {\n const boldResult = formatStringToHtml('**bold**');\n expect(boldResult.html).toEqual('<p><strong>bold</strong></p>');\n expect(boldResult.tables).toEqual([]);\n\n const italicResult = formatStringToHtml('*italic*');\n expect(italicResult.html).toEqual('<p><em>italic</em></p>');\n expect(italicResult.tables).toEqual([]);\n\n const inlineCodeResult = formatStringToHtml('`inline code`');\n expect(inlineCodeResult.html).toEqual('<p><code>inline code</code></p>');\n expect(inlineCodeResult.tables).toEqual([]);\n });\n\n test('should format headings correctly', () => {\n const h1Result = formatStringToHtml('# h1');\n expect(h1Result.html).toEqual('<h1>h1</h1>');\n expect(h1Result.tables).toEqual([]);\n\n const h2Result = formatStringToHtml('## h2');\n expect(h2Result.html).toEqual('<h2>h2</h2>');\n expect(h2Result.tables).toEqual([]);\n\n const h3Result = formatStringToHtml('### h3');\n expect(h3Result.html).toEqual('<h3>h3</h3>');\n expect(h3Result.tables).toEqual([]);\n\n const h4Result = formatStringToHtml('#### h4');\n expect(h4Result.html).toEqual('<h4>h4</h4>');\n expect(h4Result.tables).toEqual([]);\n\n const h5Result = formatStringToHtml('##### h5');\n expect(h5Result.html).toEqual('<h5>h5</h5>');\n expect(h5Result.tables).toEqual([]);\n\n const h6Result = formatStringToHtml('###### h6');\n expect(h6Result.html).toEqual('<h6>h6</h6>');\n expect(h6Result.tables).toEqual([]);\n });\n\n test('should format links correctly', () => {\n const result = formatStringToHtml('[Link](https://example.com)');\n expect(result.html).toEqual('<p><a href=\"https://example.com\">Link</a></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format images correctly', () => {\n const result = formatStringToHtml('![Alt Text](https://example.com/image.jpg)');\n expect(result.html).toEqual(\n '<p><img src=\"https://example.com/image.jpg\" alt=\"Alt Text\"></p>',\n );\n expect(result.tables).toEqual([]);\n });\n\n test('should format lists correctly', () => {\n const expectedUnorderedListResult =\n '<ul>\\n<li>Item 1</li>\\n<li>Item 2</li>\\n<li>Item 3</li>\\n</ul>';\n const expectedOrderedListResult =\n '<ol>\\n<li>Item 1</li>\\n<li>Item 2</li>\\n<li>Item 3</li>\\n</ol>';\n\n const unorderedListResult1 = formatStringToHtml('- Item 1\\n- Item 2\\n- Item 3');\n expect(unorderedListResult1.html).toEqual(expectedUnorderedListResult);\n expect(unorderedListResult1.tables).toEqual([]);\n\n const unorderedListResult2 = formatStringToHtml('* Item 1\\n* Item 2\\n* Item 3');\n expect(unorderedListResult2.html).toEqual(expectedUnorderedListResult);\n expect(unorderedListResult2.tables).toEqual([]);\n\n const orderedListResult = formatStringToHtml('1. Item 1\\n2. Item 2\\n3. Item 3');\n expect(orderedListResult.html).toEqual(expectedOrderedListResult);\n expect(orderedListResult.tables).toEqual([]);\n\n const orderedListResult2 = formatStringToHtml('1) Item 1\\n2) Item 2\\n3) Item 3');\n expect(orderedListResult2.html).toEqual(expectedOrderedListResult);\n expect(orderedListResult2.tables).toEqual([]);\n });\n\n test('should format thematic breaks correctly', () => {\n const expectedThematicBreakResult = '<hr>';\n\n const result1 = formatStringToHtml('---');\n expect(result1.html).toEqual(expectedThematicBreakResult);\n expect(result1.tables).toEqual([]);\n\n const result2 = formatStringToHtml('***');\n expect(result2.html).toEqual(expectedThematicBreakResult);\n expect(result2.tables).toEqual([]);\n });\n\n test('should format code blocks correctly', () => {\n const resultWithoutLanguage = formatStringToHtml('```\\nconst a = 1;\\n```');\n expect(resultWithoutLanguage.html).toEqual('<pre><code>const a = 1;</code></pre>');\n expect(resultWithoutLanguage.tables).toEqual([]);\n\n const resultWithLanguage = formatStringToHtml('```js\\nconst a = 1;\\n```');\n expect(resultWithLanguage.html).toEqual(\n '<pre><code class=\"language-js\">const a = 1;</code></pre>',\n );\n expect(resultWithLanguage.tables).toEqual([]);\n });\n\n test('should format tables correctly', () => {\n const inputString =\n '| Header 1 | Header 2 |\\n|----------|----------|\\n| Cell 1 | Cell 2 |';\n const result = formatStringToHtml(inputString);\n expect(removeLinebreaks(result.html)).toEqual(\n '<table id=\"formatted-table-0\"><thead><tr><th>Header 1</th><th>Header 2</th></tr></thead><tbody><tr><td>Cell 1</td><td>Cell 2</td></tr></tbody></table>',\n );\n expect(result.tables).toEqual([\n {\n csv: 'Header 1,Header 2\\nCell 1,Cell 2\\n',\n raw: inputString,\n id: 'formatted-table-0',\n },\n ]);\n });\n });\n\n describe('Inline Code', () => {\n describe('HTML In Code', () => {\n test('should escape < and > within inline code correctly', () => {\n const result1 = formatStringToHtml('`<div>Test</div>`');\n expect(result1.html).toEqual('<p><code>&lt;div&gt;Test&lt;/div&gt;</code></p>');\n expect(result1.tables).toEqual([]);\n });\n\n test('should not escape & within inline code', () => {\n const resultEscape1 = formatStringToHtml('`&lt;div&gt;Test&lt;/div&gt;`');\n expect(resultEscape1.html).toEqual(\n '<p><code>&lt;div&gt;Test&lt;/div&gt;</code></p>',\n );\n expect(resultEscape1.tables).toEqual([]);\n\n const resultEscape2 = formatStringToHtml(\n '`&amp;lt;div&amp;gt;Test&amp;lt;/div&amp;gt;`',\n );\n expect(resultEscape2.html).toEqual(\n '<p><code>&amp;lt;div&amp;gt;Test&amp;lt;/div&amp;gt;</code></p>',\n );\n expect(resultEscape2.tables).toEqual([]);\n });\n });\n\n test('should not format markdown within inline code', () => {\n const result = formatStringToHtml('`**bold** *italic*`');\n expect(result.html).toEqual('<p><code>**bold** *italic*</code></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should not format bb-code within inline code', () => {\n const result = formatStringToHtml('`[b]bold[/b]`', { parseBBCode: true });\n expect(result.html).toEqual('<p><code>[b]bold[/b]</code></p>');\n expect(result.tables).toEqual([]);\n });\n });\n\n describe('Codeblock', () => {\n test('should format code blocks with multiple lines correctly', () => {\n const resultWithoutLanguage = formatStringToHtml(\n '```\\nconst a = 1;\\nconst b = 2;\\n```',\n );\n expect(resultWithoutLanguage.html).toEqual(\n '<pre><code>const a = 1;\\nconst b = 2;</code></pre>',\n );\n expect(resultWithoutLanguage.tables).toEqual([]);\n\n const resultWithLanguage = formatStringToHtml(\n '```js\\nconst a = 1;\\nconst b = 2;\\n```',\n );\n expect(resultWithLanguage.html).toEqual(\n '<pre><code class=\"language-js\">const a = 1;\\nconst b = 2;</code></pre>',\n );\n expect(resultWithLanguage.tables).toEqual([]);\n });\n\n describe('HTML In Code', () => {\n test('should escape < and > within code block', () => {\n const resultWithoutLanguage = formatStringToHtml('```\\n<div>Test</div>\\n```');\n expect(resultWithoutLanguage.html).toEqual(\n '<pre><code>&lt;div&gt;Test&lt;/div&gt;</code></pre>',\n );\n expect(resultWithoutLanguage.tables).toEqual([]);\n\n const resultWithLanguage = formatStringToHtml('```html\\n<div>Test</div>\\n```');\n expect(resultWithLanguage.html).toEqual(\n '<pre><code class=\"language-html\">&lt;div&gt;Test&lt;/div&gt;</code></pre>',\n );\n expect(resultWithLanguage.tables).toEqual([]);\n });\n\n test('should not escape & within code block', () => {\n const resultEscape1 = formatStringToHtml(\n '```\\n&lt;div&gt;Test&lt;/div&gt;\\n```',\n );\n expect(resultEscape1.html).toEqual(\n '<pre><code>&lt;div&gt;Test&lt;/div&gt;</code></pre>',\n );\n expect(resultEscape1.tables).toEqual([]);\n\n const resultEscape2 = formatStringToHtml(\n '```\\n&amp;lt;div&amp;gt;Test&amp;lt;/div&amp;gt;\\n```',\n );\n expect(resultEscape2.html).toEqual(\n '<pre><code>&amp;lt;div&amp;gt;Test&amp;lt;/div&amp;gt;</code></pre>',\n );\n expect(resultEscape2.tables).toEqual([]);\n });\n });\n\n test('should not format markdown within code block', () => {\n const resultWithoutLanguage = formatStringToHtml('```\\n**Test**\\n```');\n expect(resultWithoutLanguage.html).toEqual('<pre><code>**Test**</code></pre>');\n expect(resultWithoutLanguage.tables).toEqual([]);\n\n const resultWithLanguage = formatStringToHtml('```html\\n**Test**\\n```');\n expect(resultWithLanguage.html).toEqual(\n '<pre><code class=\"language-html\">**Test**</code></pre>',\n );\n expect(resultWithLanguage.tables).toEqual([]);\n });\n\n test('should not format bb-code within code block', () => {\n const resultWithoutLanguage = formatStringToHtml('```\\n[b]Test[/b]\\n```');\n expect(resultWithoutLanguage.html).toEqual('<pre><code>[b]Test[/b]</code></pre>');\n expect(resultWithoutLanguage.tables).toEqual([]);\n\n const resultWithLanguage = formatStringToHtml('```html\\n[b]Test[/b]\\n```');\n expect(resultWithLanguage.html).toEqual(\n '<pre><code class=\"language-html\">[b]Test[/b]</code></pre>',\n );\n expect(resultWithLanguage.tables).toEqual([]);\n });\n });\n\n describe('Table', () => {\n test('should format markdown within table correctly', () => {\n const inputString =\n '| Header 1 | Header 2 |\\n|----------|----------|\\n| **Cell 1** | *Cell 2* |';\n const result = formatStringToHtml(inputString);\n expect(removeLinebreaks(result.html)).toEqual(\n '<table id=\"formatted-table-0\"><thead><tr><th>Header 1</th><th>Header 2</th></tr></thead><tbody><tr><td><strong>Cell 1</strong></td><td><em>Cell 2</em></td></tr></tbody></table>',\n );\n expect(result.tables).toEqual([\n {\n csv: 'Header 1,Header 2\\n**Cell 1**,*Cell 2*\\n',\n raw: inputString,\n id: 'formatted-table-0',\n },\n ]);\n });\n\n test('should format bb-code within table correctly', () => {\n const inputString =\n '| Header 1 | Header 2 |\\n|----------|----------|\\n| [b]Cell 1[/b] | [i]Cell 2[/i] |';\n const result = formatStringToHtml(inputString, {\n parseBBCode: true,\n });\n expect(removeLinebreaks(result.html)).toEqual(\n '<table id=\"formatted-table-0\"><thead><tr><th>Header 1</th><th>Header 2</th></tr></thead><tbody><tr><td><b>Cell 1</b></td><td><i>Cell 2</i></td></tr></tbody></table>',\n );\n expect(result.tables).toEqual([\n {\n csv: 'Header 1,Header 2\\n[b]Cell 1[/b],[i]Cell 2[/i]\\n',\n raw: inputString,\n id: 'formatted-table-0',\n },\n ]);\n });\n\n test('should format html within table correctly', () => {\n const inputString =\n '| Header 1 | Header 2 | Header 3 |\\n|----------|----------|----------|\\n| <div>Cell 1</div> | &lt;div&gt;Cell 2&lt;/div&gt; | &amp;lt;div&amp;gt;Cell 3&amp;lt;/div&amp;gt; |';\n const result = formatStringToHtml(inputString, {\n parseBBCode: true,\n });\n expect(removeLinebreaks(result.html)).toEqual(\n '<table id=\"formatted-table-0\"><thead><tr><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr></thead><tbody><tr><td>&lt;div&gt;Cell 1&lt;/div&gt;</td><td>&lt;div&gt;Cell 2&lt;/div&gt;</td><td>&amp;lt;div&amp;gt;Cell 3&amp;lt;/div&amp;gt;</td></tr></tbody></table>',\n );\n expect(result.tables).toEqual([\n {\n csv: 'Header 1,Header 2,Header 3\\n<div>Cell 1</div>,<div>Cell 2</div>,&lt;div&gt;Cell 3&lt;/div&gt;\\n',\n raw: '| Header 1 | Header 2 | Header 3 |\\n|----------|----------|----------|\\n| <div>Cell 1</div> | <div>Cell 2</div> | &lt;div&gt;Cell 3&lt;/div&gt; |',\n id: 'formatted-table-0',\n },\n ]);\n });\n\n test('should format multiple tables correctly', () => {\n const table1 =\n '| Header 1 | Header 2 |\\n|----------|----------|\\n| Cell 1 | Cell 2 |';\n const getTable1Result = (index: number) =>\n `<table id=\"formatted-table-${index}\"><thead><tr><th>Header 1</th><th>Header 2</th></tr></thead><tbody><tr><td>Cell 1</td><td>Cell 2</td></tr></tbody></table>`;\n const table1Csv = 'Header 1,Header 2\\nCell 1,Cell 2\\n';\n const table2 =\n '| Header 3 | Header 4 |\\n|----------|----------|\\n| Cell 3 | Cell 4 |';\n const getTable2TResult = (index: number) =>\n `<table id=\"formatted-table-${index}\"><thead><tr><th>Header 3</th><th>Header 4</th></tr></thead><tbody><tr><td>Cell 3</td><td>Cell 4</td></tr></tbody></table>`;\n const table2Csv = 'Header 3,Header 4\\nCell 3,Cell 4\\n';\n\n const result1 = formatStringToHtml(`${table1}\\n\\n${table2}`);\n expect(removeLinebreaks(result1.html)).toEqual(\n `${getTable1Result(0)}${getTable2TResult(1)}`,\n );\n expect(result1.tables).toEqual([\n {\n csv: table1Csv,\n raw: `${table1}\\n\\n`,\n id: 'formatted-table-0',\n },\n {\n csv: table2Csv,\n raw: table2,\n id: 'formatted-table-1',\n },\n ]);\n\n // Tables in reverse order.\n const result2 = formatStringToHtml(`${table2}\\n\\n${table1}`);\n expect(removeLinebreaks(result2.html)).toEqual(\n `${getTable2TResult(0)}${getTable1Result(1)}`,\n );\n expect(result2.tables).toEqual([\n {\n csv: table2Csv,\n raw: `${table2}\\n\\n`,\n id: 'formatted-table-0',\n },\n {\n csv: table1Csv,\n raw: table1,\n id: 'formatted-table-1',\n },\n ]);\n });\n });\n\n describe('List', () => {\n test('should format markdown within list correctly', () => {\n const result = formatStringToHtml('- **Item 1**\\n- *Item 2*');\n expect(removeLinebreaks(result.html)).toEqual(\n '<ul><li><strong>Item 1</strong></li><li><em>Item 2</em></li></ul>',\n );\n expect(result.tables).toEqual([]);\n });\n\n test('should format task lists correctly', () => {\n const result1 = formatStringToHtml('- [ ] 1\\n- [x] 2\\n- [X] 3');\n expect(removeLinebreaks(result1.html)).toEqual(\n '<ul><li>[ ] 1</li><li>[x] 2</li><li>[x] 3</li></ul>',\n );\n expect(result1.tables).toEqual([]);\n });\n });\n\n describe('Combined Elements', () => {\n test('should format code block within list correctly', () => {\n const result = formatStringToHtml('* test\\n ```\\n test\\n ```');\n expect(removeLinebreaks(result.html)).toEqual(\n '<ul><li>test<pre><code>test</code></pre></li></ul>',\n );\n expect(result.tables).toEqual([]);\n });\n });\n\n describe('Conflicts with BB-Code', () => {\n test('should not format bb code tag followed by paranthese to link', () => {\n const result = formatStringToHtml('[b]bold[/b](test)', { parseBBCode: true });\n expect(result.html).toEqual('<p><b>bold</b>(test)</p>');\n expect(result.tables).toEqual([]);\n });\n });\n });\n\n describe('Format BB-Code', () => {\n describe('All Elements', () => {\n describe('Inline Elements', () => {\n // b, strong, i, em, u, s, span, img\n test('should format b tag correctly', () => {\n const result = formatStringToHtml('[b]bold[/b]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><b>bold</b></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format strong tag correctly', () => {\n const result = formatStringToHtml('[strong]bold[/strong]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><strong>bold</strong></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format i tag correctly', () => {\n const result = formatStringToHtml('[i]italic[/i]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><i>italic</i></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format em tag correctly', () => {\n const result = formatStringToHtml('[em]italic[/em]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><em>italic</em></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format u tag correctly', () => {\n const result = formatStringToHtml('[u]underline[/u]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><u>underline</u></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format s tag correctly', () => {\n const result = formatStringToHtml('[s]strike[/s]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><s>strike</s></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format span tag correctly', () => {\n const result = formatStringToHtml('[span]span[/span]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><span>span</span></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format img tag correctly', () => {\n const result = formatStringToHtml(\n '[img src=\"https://example.com/image.jpg\"][/img]',\n {\n parseBBCode: true,\n },\n );\n expect(result.html).toEqual('<p><img src=\"https://example.com/image.jpg\"></p>');\n expect(result.tables).toEqual([]);\n });\n });\n\n describe('Block Level Elements', () => {\n test('should format center tag correctly', () => {\n const result = formatStringToHtml('[center]centered text[/center]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><center>centered text</center></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format ul tag correctly', () => {\n const result = formatStringToHtml('[ul][li]Item 1[/li][li]Item 2[/li][/ul]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><ul><li>Item 1</li><li>Item 2</li></ul></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format ol tag correctly', () => {\n const result = formatStringToHtml('[ol][li]Item 1[/li][li]Item 2[/li][/ol]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><ol><li>Item 1</li><li>Item 2</li></ol></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format li tag correctly', () => {\n const result = formatStringToHtml('[li]Item[/li]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><li>Item</li></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format heading tags correctly', () => {\n const getHeadingInput = (tag: string) => `[${tag}]${tag}[/${tag}]`;\n const getHeadingOutput = (tag: string) => `<p><${tag}>${tag}</${tag}></p>`;\n const headingTags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\n\n headingTags.forEach((tag) => {\n const result = formatStringToHtml(getHeadingInput(tag), {\n parseBBCode: true,\n });\n expect(result.html).toEqual(getHeadingOutput(tag));\n expect(result.tables).toEqual([]);\n });\n });\n\n test('should format p tag correctly', () => {\n const result = formatStringToHtml('[p]paragraph[/p]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><p>paragraph</p></p>');\n expect(result.tables).toEqual([]);\n });\n });\n\n describe('Custom Elements', () => {\n test('should format custom tags correctly', () => {\n const input = '[custom attribute1=\"test1\" attribute2=\"test2\"]custom[/custom]';\n const output =\n '<p><bb-code-custom attribute1=\"test1\" attribute2=\"test2\">custom</bb-code-custom></p>';\n const result1 = formatStringToHtml(input, {\n parseBBCode: true,\n customInlineLevelBBCodeTags: ['custom'],\n });\n expect(result1.html).toEqual(output);\n expect(result1.tables).toEqual([]);\n\n const result2 = formatStringToHtml(input, {\n parseBBCode: true,\n customBlockLevelBBCodeTags: ['custom'],\n });\n expect(result2.html).toEqual(output);\n expect(result2.tables).toEqual([]);\n });\n\n test('should not format unknown custom tags', () => {\n const result = formatStringToHtml('[unknown]unknown[/unknown]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p>[unknown]unknown[/unknown]</p>');\n expect(result.tables).toEqual([]);\n });\n });\n\n describe('Line breaks', () => {\n describe('Between Elements', () => {\n test('should format line breaks between block level elements correctly', () => {\n const result1 = formatStringToHtml('[h1]h1[/h1]\\n[h2]h2[/h2]', {\n parseBBCode: true,\n });\n expect(result1.html).toEqual('<p><h1>h1</h1><h2>h2</h2></p>');\n expect(result1.tables).toEqual([]);\n\n const result2 = formatStringToHtml('[h1]h1[/h1]\\n\\n[h2]h2[/h2]', {\n parseBBCode: true,\n });\n expect(result2.html).toEqual('<p><h1>h1</h1></p>\\n<p><h2>h2</h2></p>');\n expect(result2.tables).toEqual([]);\n });\n\n test('should format line breaks between inline elements correctly', () => {\n const result1 = formatStringToHtml('[b]bold[/b]\\n[i]italic[/i]', {\n parseBBCode: true,\n });\n expect(result1.html).toEqual('<p><b>bold</b>\\n<i>italic</i></p>');\n expect(result1.tables).toEqual([]);\n\n const result2 = formatStringToHtml('[b]bold[/b]\\n\\n[i]italic[/i]', {\n parseBBCode: true,\n });\n expect(result2.html).toEqual('<p><b>bold</b></p>\\n<p><i>italic</i></p>');\n expect(result2.tables).toEqual([]);\n });\n });\n\n describe('Within Elements', () => {\n test('should format line breaks within block level elements correctly', () => {\n const result = formatStringToHtml('[h1]Line 1\\nLine 2[/h1]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><h1>Line 1\\nLine 2</h1></p>');\n expect(result.tables).toEqual([]);\n });\n\n // This is a test that would fail!\n // test('should format multiple line breaks within block level elements correctly', () => {\n // const result = formatStringToHtml('[h1]Line 1\\n\\nLine 2[/h1]', {\n // parseBBCode: true,\n // });\n // expect(result.html).toEqual('<p><h1>Line 1\\nLine 2</h1></p>');\n // expect(result.tables).toEqual([]);\n // });\n\n test('should remove trailing and leading new lines within block level elements', () => {\n const result = formatStringToHtml('[h1]\\n\\n\\nLine 1\\n\\n\\n[/h1]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><h1>Line 1</h1></p>');\n expect(result.tables).toEqual([]);\n });\n });\n });\n\n test('should not format url in tag attributes', () => {\n const result = formatStringToHtml(\n '[link url=\"https://www.google.com\"]Google[/link]',\n {\n parseBBCode: true,\n customInlineLevelBBCodeTags: ['link'],\n },\n );\n expect(result.html).toEqual(\n '<p><bb-code-link url=\"https://www.google.com\">Google</bb-code-link></p>',\n );\n expect(result.tables).toEqual([]);\n });\n\n test('should apply style attribute correctly', () => {\n const result = formatStringToHtml('[span style=\"color: red;\"]red text[/span]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><span style=\"color: red;\">red text</span></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format nested elements correctly', () => {\n const result = formatStringToHtml('[b][i]bold italic[/i][/b]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><b><i>bold italic</i></b></p>');\n expect(result.tables).toEqual([]);\n });\n });\n });\n\n describe('Combined Formatting (Markdown + BB-Code)', () => {\n test('should format bb-code within markdown correctly', () => {\n const result = formatStringToHtml('*[b]bold[/b]*', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><em><b>bold</b></em></p>');\n expect(result.tables).toEqual([]);\n });\n\n test('should format markdown within bb-code correctly', () => {\n const result = formatStringToHtml('[b]*bold*[/b]', {\n parseBBCode: true,\n });\n expect(result.html).toEqual('<p><b><em>bold</em></b></p>');\n expect(result.tables).toEqual([]);\n });\n });\n});\n"],"mappings":";;AAAA,IAAAA,OAAA,GAAAC,OAAA;AACA,IAAAC,aAAA,GAAAD,OAAA;AAEA,MAAME,gBAAgB,GAAIC,IAAY,IAAKA,IAAI,CAACC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;AAElE,IAAAC,gBAAQ,EAAC,yBAAyB,EAAE,MAAM;EACtC,IAAAA,gBAAQ,EAAC,mBAAmB,EAAE,MAAM;IAChC,IAAAA,gBAAQ,EAAC,aAAa,EAAE,MAAM;MAC1B,IAAAC,YAAI,EAAC,qCAAqC,EAAE,MAAM;QAC9C,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,gBAAgB,CAAC;QACnD,IAAAC,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,uBAAuB,CAAC;QACpD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,8CAA8C,EAAE,MAAM;QACvD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,kBAAkB,CAAC;QACrD,IAAAC,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,8BAA8B,CAAC;QAC3D,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,8CAA8C,EAAE,MAAM;QACvD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,oBAAoB,CAAC;QACvD,IAAAC,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,eAAe,CAAC;QAC5C,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;IACN,CAAC,CAAC;IAEF,IAAAN,gBAAQ,EAAC,aAAa,EAAE,MAAM;MAC1B,IAAAC,YAAI,EAAC,wCAAwC,EAAE,MAAM;QACjD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,wBAAwB,CAAC;QAC3D,IAAAC,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,+BAA+B,CAAC;QAC5D,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,oDAAoD,EAAE,MAAM;QAC7D,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,YAAY,CAAC;QAC/C,IAAAC,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,mBAAmB,CAAC;QAChD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;IACN,CAAC,CAAC;IAEF,IAAAN,gBAAQ,EAAC,MAAM,EAAE,MAAM;MACnB,IAAAC,YAAI,EAAC,iCAAiC,EAAE,MAAM;QAC1C,MAAMO,YAAY,GAAG,IAAAL,gCAAkB,EAAC,iBAAiB,CAAC;QAC1D,IAAAC,cAAM,EAACI,YAAY,CAACH,IAAI,CAAC,CAACC,OAAO,CAAC,oCAAoC,CAAC;QACvE,IAAAF,cAAM,EAACI,YAAY,CAACD,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MAC3C,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,qBAAqB,EAAE,MAAM;QAC9B,MAAMQ,aAAa,GAAG,IAAAN,gCAAkB,EAAC,6BAA6B,CAAC;QACvE,IAAAC,cAAM,EAACK,aAAa,CAACJ,IAAI,CAAC,CAACC,OAAO,CAAC,oCAAoC,CAAC;QACxE,IAAAF,cAAM,EAACK,aAAa,CAACF,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAExC,MAAMI,aAAa,GAAG,IAAAP,gCAAkB,EACpC,6CACJ,CAAC;QACD,IAAAC,cAAM,EAACM,aAAa,CAACL,IAAI,CAAC,CAACC,OAAO,CAC9B,oDACJ,CAAC;QACD,IAAAF,cAAM,EAACM,aAAa,CAACH,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MAC5C,CAAC,CAAC;;MAEF;IACJ,CAAC,CAAC;IAEF,IAAAN,gBAAQ,EAAC,MAAM,EAAE,MAAM;MACnB,IAAAC,YAAI,EAAC,wBAAwB,EAAE,MAAM;QACjC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,qBAAqB,CAAC;QACxD,IAAAC,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,4BAA4B,CAAC;QACzD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;IACN,CAAC,CAAC;EACN,CAAC,CAAC;EAEF,IAAAN,gBAAQ,EAAC,iBAAiB,EAAE,MAAM;IAC9B,IAAAA,gBAAQ,EAAC,cAAc,EAAE,MAAM;MAC3B,IAAAC,YAAI,EAAC,sCAAsC,EAAE,MAAM;QAC/C,MAAMU,UAAU,GAAG,IAAAR,gCAAkB,EAAC,UAAU,CAAC;QACjD,IAAAC,cAAM,EAACO,UAAU,CAACN,IAAI,CAAC,CAACC,OAAO,CAAC,8BAA8B,CAAC;QAC/D,IAAAF,cAAM,EAACO,UAAU,CAACJ,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAErC,MAAMM,YAAY,GAAG,IAAAT,gCAAkB,EAAC,UAAU,CAAC;QACnD,IAAAC,cAAM,EAACQ,YAAY,CAACP,IAAI,CAAC,CAACC,OAAO,CAAC,wBAAwB,CAAC;QAC3D,IAAAF,cAAM,EAACQ,YAAY,CAACL,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAEvC,MAAMO,gBAAgB,GAAG,IAAAV,gCAAkB,EAAC,eAAe,CAAC;QAC5D,IAAAC,cAAM,EAACS,gBAAgB,CAACR,IAAI,CAAC,CAACC,OAAO,CAAC,iCAAiC,CAAC;QACxE,IAAAF,cAAM,EAACS,gBAAgB,CAACN,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MAC/C,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,kCAAkC,EAAE,MAAM;QAC3C,MAAMa,QAAQ,GAAG,IAAAX,gCAAkB,EAAC,MAAM,CAAC;QAC3C,IAAAC,cAAM,EAACU,QAAQ,CAACT,IAAI,CAAC,CAACC,OAAO,CAAC,aAAa,CAAC;QAC5C,IAAAF,cAAM,EAACU,QAAQ,CAACP,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAEnC,MAAMS,QAAQ,GAAG,IAAAZ,gCAAkB,EAAC,OAAO,CAAC;QAC5C,IAAAC,cAAM,EAACW,QAAQ,CAACV,IAAI,CAAC,CAACC,OAAO,CAAC,aAAa,CAAC;QAC5C,IAAAF,cAAM,EAACW,QAAQ,CAACR,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAEnC,MAAMU,QAAQ,GAAG,IAAAb,gCAAkB,EAAC,QAAQ,CAAC;QAC7C,IAAAC,cAAM,EAACY,QAAQ,CAACX,IAAI,CAAC,CAACC,OAAO,CAAC,aAAa,CAAC;QAC5C,IAAAF,cAAM,EAACY,QAAQ,CAACT,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAEnC,MAAMW,QAAQ,GAAG,IAAAd,gCAAkB,EAAC,SAAS,CAAC;QAC9C,IAAAC,cAAM,EAACa,QAAQ,CAACZ,IAAI,CAAC,CAACC,OAAO,CAAC,aAAa,CAAC;QAC5C,IAAAF,cAAM,EAACa,QAAQ,CAACV,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAEnC,MAAMY,QAAQ,GAAG,IAAAf,gCAAkB,EAAC,UAAU,CAAC;QAC/C,IAAAC,cAAM,EAACc,QAAQ,CAACb,IAAI,CAAC,CAACC,OAAO,CAAC,aAAa,CAAC;QAC5C,IAAAF,cAAM,EAACc,QAAQ,CAACX,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAEnC,MAAMa,QAAQ,GAAG,IAAAhB,gCAAkB,EAAC,WAAW,CAAC;QAChD,IAAAC,cAAM,EAACe,QAAQ,CAACd,IAAI,CAAC,CAACC,OAAO,CAAC,aAAa,CAAC;QAC5C,IAAAF,cAAM,EAACe,QAAQ,CAACZ,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACvC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,+BAA+B,EAAE,MAAM;QACxC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,6BAA6B,CAAC;QAChE,IAAAC,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,+CAA+C,CAAC;QAC5E,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,gCAAgC,EAAE,MAAM;QACzC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,4CAA4C,CAAC;QAC/E,IAAAC,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CACvB,iEACJ,CAAC;QACD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,+BAA+B,EAAE,MAAM;QACxC,MAAMmB,2BAA2B,GAC7B,gEAAgE;QACpE,MAAMC,yBAAyB,GAC3B,gEAAgE;QAEpE,MAAMC,oBAAoB,GAAG,IAAAnB,gCAAkB,EAAC,8BAA8B,CAAC;QAC/E,IAAAC,cAAM,EAACkB,oBAAoB,CAACjB,IAAI,CAAC,CAACC,OAAO,CAACc,2BAA2B,CAAC;QACtE,IAAAhB,cAAM,EAACkB,oBAAoB,CAACf,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAE/C,MAAMiB,oBAAoB,GAAG,IAAApB,gCAAkB,EAAC,8BAA8B,CAAC;QAC/E,IAAAC,cAAM,EAACmB,oBAAoB,CAAClB,IAAI,CAAC,CAACC,OAAO,CAACc,2BAA2B,CAAC;QACtE,IAAAhB,cAAM,EAACmB,oBAAoB,CAAChB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAE/C,MAAMkB,iBAAiB,GAAG,IAAArB,gCAAkB,EAAC,iCAAiC,CAAC;QAC/E,IAAAC,cAAM,EAACoB,iBAAiB,CAACnB,IAAI,CAAC,CAACC,OAAO,CAACe,yBAAyB,CAAC;QACjE,IAAAjB,cAAM,EAACoB,iBAAiB,CAACjB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAE5C,MAAMmB,kBAAkB,GAAG,IAAAtB,gCAAkB,EAAC,iCAAiC,CAAC;QAChF,IAAAC,cAAM,EAACqB,kBAAkB,CAACpB,IAAI,CAAC,CAACC,OAAO,CAACe,yBAAyB,CAAC;QAClE,IAAAjB,cAAM,EAACqB,kBAAkB,CAAClB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACjD,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,yCAAyC,EAAE,MAAM;QAClD,MAAMyB,2BAA2B,GAAG,MAAM;QAE1C,MAAMC,OAAO,GAAG,IAAAxB,gCAAkB,EAAC,KAAK,CAAC;QACzC,IAAAC,cAAM,EAACuB,OAAO,CAACtB,IAAI,CAAC,CAACC,OAAO,CAACoB,2BAA2B,CAAC;QACzD,IAAAtB,cAAM,EAACuB,OAAO,CAACpB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAElC,MAAMsB,OAAO,GAAG,IAAAzB,gCAAkB,EAAC,KAAK,CAAC;QACzC,IAAAC,cAAM,EAACwB,OAAO,CAACvB,IAAI,CAAC,CAACC,OAAO,CAACoB,2BAA2B,CAAC;QACzD,IAAAtB,cAAM,EAACwB,OAAO,CAACrB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACtC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,qCAAqC,EAAE,MAAM;QAC9C,MAAM4B,qBAAqB,GAAG,IAAA1B,gCAAkB,EAAC,wBAAwB,CAAC;QAC1E,IAAAC,cAAM,EAACyB,qBAAqB,CAACxB,IAAI,CAAC,CAACC,OAAO,CAAC,sCAAsC,CAAC;QAClF,IAAAF,cAAM,EAACyB,qBAAqB,CAACtB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAEhD,MAAMwB,kBAAkB,GAAG,IAAA3B,gCAAkB,EAAC,0BAA0B,CAAC;QACzE,IAAAC,cAAM,EAAC0B,kBAAkB,CAACzB,IAAI,CAAC,CAACC,OAAO,CACnC,0DACJ,CAAC;QACD,IAAAF,cAAM,EAAC0B,kBAAkB,CAACvB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACjD,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,gCAAgC,EAAE,MAAM;QACzC,MAAM8B,WAAW,GACb,2EAA2E;QAC/E,MAAM7B,MAAM,GAAG,IAAAC,gCAAkB,EAAC4B,WAAW,CAAC;QAC9C,IAAA3B,cAAM,EAACP,gBAAgB,CAACK,MAAM,CAACG,IAAI,CAAC,CAAC,CAACC,OAAO,CACzC,wJACJ,CAAC;QACD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,CAC1B;UACI0B,GAAG,EAAE,oCAAoC;UACzCC,GAAG,EAAEF,WAAW;UAChBG,EAAE,EAAE;QACR,CAAC,CACJ,CAAC;MACN,CAAC,CAAC;IACN,CAAC,CAAC;IAEF,IAAAlC,gBAAQ,EAAC,aAAa,EAAE,MAAM;MAC1B,IAAAA,gBAAQ,EAAC,cAAc,EAAE,MAAM;QAC3B,IAAAC,YAAI,EAAC,oDAAoD,EAAE,MAAM;UAC7D,MAAM0B,OAAO,GAAG,IAAAxB,gCAAkB,EAAC,mBAAmB,CAAC;UACvD,IAAAC,cAAM,EAACuB,OAAO,CAACtB,IAAI,CAAC,CAACC,OAAO,CAAC,iDAAiD,CAAC;UAC/E,IAAAF,cAAM,EAACuB,OAAO,CAACpB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACtC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,wCAAwC,EAAE,MAAM;UACjD,MAAMQ,aAAa,GAAG,IAAAN,gCAAkB,EAAC,+BAA+B,CAAC;UACzE,IAAAC,cAAM,EAACK,aAAa,CAACJ,IAAI,CAAC,CAACC,OAAO,CAC9B,iDACJ,CAAC;UACD,IAAAF,cAAM,EAACK,aAAa,CAACF,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;UAExC,MAAMI,aAAa,GAAG,IAAAP,gCAAkB,EACpC,+CACJ,CAAC;UACD,IAAAC,cAAM,EAACM,aAAa,CAACL,IAAI,CAAC,CAACC,OAAO,CAC9B,iEACJ,CAAC;UACD,IAAAF,cAAM,EAACM,aAAa,CAACH,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAC5C,CAAC,CAAC;MACN,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,+CAA+C,EAAE,MAAM;QACxD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,qBAAqB,CAAC;QACxD,IAAAC,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,uCAAuC,CAAC;QACpE,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,8CAA8C,EAAE,MAAM;QACvD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,eAAe,EAAE;UAAEgC,WAAW,EAAE;QAAK,CAAC,CAAC;QACzE,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,iCAAiC,CAAC;QAC9D,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;IACN,CAAC,CAAC;IAEF,IAAAN,gBAAQ,EAAC,WAAW,EAAE,MAAM;MACxB,IAAAC,YAAI,EAAC,yDAAyD,EAAE,MAAM;QAClE,MAAM4B,qBAAqB,GAAG,IAAA1B,gCAAkB,EAC5C,sCACJ,CAAC;QACD,IAAAC,cAAM,EAACyB,qBAAqB,CAACxB,IAAI,CAAC,CAACC,OAAO,CACtC,oDACJ,CAAC;QACD,IAAAF,cAAM,EAACyB,qBAAqB,CAACtB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAEhD,MAAMwB,kBAAkB,GAAG,IAAA3B,gCAAkB,EACzC,wCACJ,CAAC;QACD,IAAAC,cAAM,EAAC0B,kBAAkB,CAACzB,IAAI,CAAC,CAACC,OAAO,CACnC,wEACJ,CAAC;QACD,IAAAF,cAAM,EAAC0B,kBAAkB,CAACvB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACjD,CAAC,CAAC;MAEF,IAAAN,gBAAQ,EAAC,cAAc,EAAE,MAAM;QAC3B,IAAAC,YAAI,EAAC,yCAAyC,EAAE,MAAM;UAClD,MAAM4B,qBAAqB,GAAG,IAAA1B,gCAAkB,EAAC,2BAA2B,CAAC;UAC7E,IAAAC,cAAM,EAACyB,qBAAqB,CAACxB,IAAI,CAAC,CAACC,OAAO,CACtC,qDACJ,CAAC;UACD,IAAAF,cAAM,EAACyB,qBAAqB,CAACtB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;UAEhD,MAAMwB,kBAAkB,GAAG,IAAA3B,gCAAkB,EAAC,+BAA+B,CAAC;UAC9E,IAAAC,cAAM,EAAC0B,kBAAkB,CAACzB,IAAI,CAAC,CAACC,OAAO,CACnC,2EACJ,CAAC;UACD,IAAAF,cAAM,EAAC0B,kBAAkB,CAACvB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACjD,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,uCAAuC,EAAE,MAAM;UAChD,MAAMQ,aAAa,GAAG,IAAAN,gCAAkB,EACpC,uCACJ,CAAC;UACD,IAAAC,cAAM,EAACK,aAAa,CAACJ,IAAI,CAAC,CAACC,OAAO,CAC9B,qDACJ,CAAC;UACD,IAAAF,cAAM,EAACK,aAAa,CAACF,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;UAExC,MAAMI,aAAa,GAAG,IAAAP,gCAAkB,EACpC,uDACJ,CAAC;UACD,IAAAC,cAAM,EAACM,aAAa,CAACL,IAAI,CAAC,CAACC,OAAO,CAC9B,qEACJ,CAAC;UACD,IAAAF,cAAM,EAACM,aAAa,CAACH,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAC5C,CAAC,CAAC;MACN,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,8CAA8C,EAAE,MAAM;QACvD,MAAM4B,qBAAqB,GAAG,IAAA1B,gCAAkB,EAAC,oBAAoB,CAAC;QACtE,IAAAC,cAAM,EAACyB,qBAAqB,CAACxB,IAAI,CAAC,CAACC,OAAO,CAAC,kCAAkC,CAAC;QAC9E,IAAAF,cAAM,EAACyB,qBAAqB,CAACtB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAEhD,MAAMwB,kBAAkB,GAAG,IAAA3B,gCAAkB,EAAC,wBAAwB,CAAC;QACvE,IAAAC,cAAM,EAAC0B,kBAAkB,CAACzB,IAAI,CAAC,CAACC,OAAO,CACnC,wDACJ,CAAC;QACD,IAAAF,cAAM,EAAC0B,kBAAkB,CAACvB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACjD,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,6CAA6C,EAAE,MAAM;QACtD,MAAM4B,qBAAqB,GAAG,IAAA1B,gCAAkB,EAAC,uBAAuB,CAAC;QACzE,IAAAC,cAAM,EAACyB,qBAAqB,CAACxB,IAAI,CAAC,CAACC,OAAO,CAAC,qCAAqC,CAAC;QACjF,IAAAF,cAAM,EAACyB,qBAAqB,CAACtB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QAEhD,MAAMwB,kBAAkB,GAAG,IAAA3B,gCAAkB,EAAC,2BAA2B,CAAC;QAC1E,IAAAC,cAAM,EAAC0B,kBAAkB,CAACzB,IAAI,CAAC,CAACC,OAAO,CACnC,2DACJ,CAAC;QACD,IAAAF,cAAM,EAAC0B,kBAAkB,CAACvB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACjD,CAAC,CAAC;IACN,CAAC,CAAC;IAEF,IAAAN,gBAAQ,EAAC,OAAO,EAAE,MAAM;MACpB,IAAAC,YAAI,EAAC,+CAA+C,EAAE,MAAM;QACxD,MAAM8B,WAAW,GACb,6EAA6E;QACjF,MAAM7B,MAAM,GAAG,IAAAC,gCAAkB,EAAC4B,WAAW,CAAC;QAC9C,IAAA3B,cAAM,EAACP,gBAAgB,CAACK,MAAM,CAACG,IAAI,CAAC,CAAC,CAACC,OAAO,CACzC,kLACJ,CAAC;QACD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,CAC1B;UACI0B,GAAG,EAAE,0CAA0C;UAC/CC,GAAG,EAAEF,WAAW;UAChBG,EAAE,EAAE;QACR,CAAC,CACJ,CAAC;MACN,CAAC,CAAC;MAEF,IAAAjC,YAAI,EAAC,8CAA8C,EAAE,MAAM;QACvD,MAAM8B,WAAW,GACb,qFAAqF;QACzF,MAAM7B,MAAM,GAAG,IAAAC,gCAAkB,EAAC4B,WAAW,EAAE;UAC3CI,WAAW,EAAE;QACjB,CAAC,CAAC;QACF,IAAA/B,cAAM,EAACP,gBAAgB,CAACK,MAAM,CAACG,IAAI,CAAC,CAAC,CAACC,OAAO,CACzC,sKACJ,CAAC;QACD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,CAC1B;UACI0B,GAAG,EAAE,kDAAkD;UACvDC,GAAG,EAAEF,WAAW;UAChBG,EAAE,EAAE;QACR,CAAC,CACJ,CAAC;MACN,CAAC,CAAC;MAEF,IAAAjC,YAAI,EAAC,2CAA2C,EAAE,MAAM;QACpD,MAAM8B,WAAW,GACb,+KAA+K;QACnL,MAAM7B,MAAM,GAAG,IAAAC,gCAAkB,EAAC4B,WAAW,EAAE;UAC3CI,WAAW,EAAE;QACjB,CAAC,CAAC;QACF,IAAA/B,cAAM,EAACP,gBAAgB,CAACK,MAAM,CAACG,IAAI,CAAC,CAAC,CAACC,OAAO,CACzC,6QACJ,CAAC;QACD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,CAC1B;UACI0B,GAAG,EAAE,iGAAiG;UACtGC,GAAG,EAAE,mJAAmJ;UACxJC,EAAE,EAAE;QACR,CAAC,CACJ,CAAC;MACN,CAAC,CAAC;MAEF,IAAAjC,YAAI,EAAC,yCAAyC,EAAE,MAAM;QAClD,MAAMmC,MAAM,GACR,2EAA2E;QAC/E,MAAMC,eAAe,GAAIC,KAAa,IAClC,8BAA8BA,KAAK,4HAA4H;QACnK,MAAMC,SAAS,GAAG,oCAAoC;QACtD,MAAMC,MAAM,GACR,2EAA2E;QAC/E,MAAMC,gBAAgB,GAAIH,KAAa,IACnC,8BAA8BA,KAAK,4HAA4H;QACnK,MAAMI,SAAS,GAAG,oCAAoC;QAEtD,MAAMf,OAAO,GAAG,IAAAxB,gCAAkB,EAAC,GAAGiC,MAAM,OAAOI,MAAM,EAAE,CAAC;QAC5D,IAAApC,cAAM,EAACP,gBAAgB,CAAC8B,OAAO,CAACtB,IAAI,CAAC,CAAC,CAACC,OAAO,CAC1C,GAAG+B,eAAe,CAAC,CAAC,CAAC,GAAGI,gBAAgB,CAAC,CAAC,CAAC,EAC/C,CAAC;QACD,IAAArC,cAAM,EAACuB,OAAO,CAACpB,MAAM,CAAC,CAACD,OAAO,CAAC,CAC3B;UACI0B,GAAG,EAAEO,SAAS;UACdN,GAAG,EAAE,GAAGG,MAAM,MAAM;UACpBF,EAAE,EAAE;QACR,CAAC,EACD;UACIF,GAAG,EAAEU,SAAS;UACdT,GAAG,EAAEO,MAAM;UACXN,EAAE,EAAE;QACR,CAAC,CACJ,CAAC;;QAEF;QACA,MAAMN,OAAO,GAAG,IAAAzB,gCAAkB,EAAC,GAAGqC,MAAM,OAAOJ,MAAM,EAAE,CAAC;QAC5D,IAAAhC,cAAM,EAACP,gBAAgB,CAAC+B,OAAO,CAACvB,IAAI,CAAC,CAAC,CAACC,OAAO,CAC1C,GAAGmC,gBAAgB,CAAC,CAAC,CAAC,GAAGJ,eAAe,CAAC,CAAC,CAAC,EAC/C,CAAC;QACD,IAAAjC,cAAM,EAACwB,OAAO,CAACrB,MAAM,CAAC,CAACD,OAAO,CAAC,CAC3B;UACI0B,GAAG,EAAEU,SAAS;UACdT,GAAG,EAAE,GAAGO,MAAM,MAAM;UACpBN,EAAE,EAAE;QACR,CAAC,EACD;UACIF,GAAG,EAAEO,SAAS;UACdN,GAAG,EAAEG,MAAM;UACXF,EAAE,EAAE;QACR,CAAC,CACJ,CAAC;MACN,CAAC,CAAC;IACN,CAAC,CAAC;IAEF,IAAAlC,gBAAQ,EAAC,MAAM,EAAE,MAAM;MACnB,IAAAC,YAAI,EAAC,8CAA8C,EAAE,MAAM;QACvD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,0BAA0B,CAAC;QAC7D,IAAAC,cAAM,EAACP,gBAAgB,CAACK,MAAM,CAACG,IAAI,CAAC,CAAC,CAACC,OAAO,CACzC,mEACJ,CAAC;QACD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,oCAAoC,EAAE,MAAM;QAC7C,MAAM0B,OAAO,GAAG,IAAAxB,gCAAkB,EAAC,2BAA2B,CAAC;QAC/D,IAAAC,cAAM,EAACP,gBAAgB,CAAC8B,OAAO,CAACtB,IAAI,CAAC,CAAC,CAACC,OAAO,CAC1C,qDACJ,CAAC;QACD,IAAAF,cAAM,EAACuB,OAAO,CAACpB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACtC,CAAC,CAAC;IACN,CAAC,CAAC;IAEF,IAAAN,gBAAQ,EAAC,mBAAmB,EAAE,MAAM;MAChC,IAAAC,YAAI,EAAC,gDAAgD,EAAE,MAAM;QACzD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,8BAA8B,CAAC;QACjE,IAAAC,cAAM,EAACP,gBAAgB,CAACK,MAAM,CAACG,IAAI,CAAC,CAAC,CAACC,OAAO,CACzC,oDACJ,CAAC;QACD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;IACN,CAAC,CAAC;IAEF,IAAAN,gBAAQ,EAAC,wBAAwB,EAAE,MAAM;MACrC,IAAAC,YAAI,EAAC,8DAA8D,EAAE,MAAM;QACvE,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,mBAAmB,EAAE;UAAEgC,WAAW,EAAE;QAAK,CAAC,CAAC;QAC7E,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,0BAA0B,CAAC;QACvD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;IACN,CAAC,CAAC;EACN,CAAC,CAAC;EAEF,IAAAN,gBAAQ,EAAC,gBAAgB,EAAE,MAAM;IAC7B,IAAAA,gBAAQ,EAAC,cAAc,EAAE,MAAM;MAC3B,IAAAA,gBAAQ,EAAC,iBAAiB,EAAE,MAAM;QAC9B;QACA,IAAAC,YAAI,EAAC,+BAA+B,EAAE,MAAM;UACxC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,aAAa,EAAE;YAC7CgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,oBAAoB,CAAC;UACjD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,oCAAoC,EAAE,MAAM;UAC7C,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,uBAAuB,EAAE;YACvDgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,8BAA8B,CAAC;UAC3D,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,+BAA+B,EAAE,MAAM;UACxC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,eAAe,EAAE;YAC/CgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,sBAAsB,CAAC;UACnD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,gCAAgC,EAAE,MAAM;UACzC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,iBAAiB,EAAE;YACjDgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,wBAAwB,CAAC;UACrD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,+BAA+B,EAAE,MAAM;UACxC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,kBAAkB,EAAE;YAClDgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,yBAAyB,CAAC;UACtD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,+BAA+B,EAAE,MAAM;UACxC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,eAAe,EAAE;YAC/CgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,sBAAsB,CAAC;UACnD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,kCAAkC,EAAE,MAAM;UAC3C,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,mBAAmB,EAAE;YACnDgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,0BAA0B,CAAC;UACvD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,iCAAiC,EAAE,MAAM;UAC1C,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAC7B,iDAAiD,EACjD;YACIgC,WAAW,EAAE;UACjB,CACJ,CAAC;UACD,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,kDAAkD,CAAC;UAC/E,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;MACN,CAAC,CAAC;MAEF,IAAAN,gBAAQ,EAAC,sBAAsB,EAAE,MAAM;QACnC,IAAAC,YAAI,EAAC,oCAAoC,EAAE,MAAM;UAC7C,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,gCAAgC,EAAE;YAChEgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,uCAAuC,CAAC;UACpE,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,gCAAgC,EAAE,MAAM;UACzC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,yCAAyC,EAAE;YACzEgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,gDAAgD,CAAC;UAC7E,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,gCAAgC,EAAE,MAAM;UACzC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,yCAAyC,EAAE;YACzEgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,gDAAgD,CAAC;UAC7E,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,gCAAgC,EAAE,MAAM;UACzC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,eAAe,EAAE;YAC/CgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,sBAAsB,CAAC;UACnD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,sCAAsC,EAAE,MAAM;UAC/C,MAAM0C,eAAe,GAAIC,GAAW,IAAK,IAAIA,GAAG,IAAIA,GAAG,KAAKA,GAAG,GAAG;UAClE,MAAMC,gBAAgB,GAAID,GAAW,IAAK,OAAOA,GAAG,IAAIA,GAAG,KAAKA,GAAG,OAAO;UAC1E,MAAME,WAAW,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;UAExDA,WAAW,CAACC,OAAO,CAAEH,GAAG,IAAK;YACzB,MAAM1C,MAAM,GAAG,IAAAC,gCAAkB,EAACwC,eAAe,CAACC,GAAG,CAAC,EAAE;cACpDT,WAAW,EAAE;YACjB,CAAC,CAAC;YACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAACuC,gBAAgB,CAACD,GAAG,CAAC,CAAC;YAClD,IAAAxC,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;UACrC,CAAC,CAAC;QACN,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,+BAA+B,EAAE,MAAM;UACxC,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,kBAAkB,EAAE;YAClDgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,yBAAyB,CAAC;UACtD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;MACN,CAAC,CAAC;MAEF,IAAAN,gBAAQ,EAAC,iBAAiB,EAAE,MAAM;QAC9B,IAAAC,YAAI,EAAC,qCAAqC,EAAE,MAAM;UAC9C,MAAM+C,KAAK,GAAG,+DAA+D;UAC7E,MAAMC,MAAM,GACR,sFAAsF;UAC1F,MAAMtB,OAAO,GAAG,IAAAxB,gCAAkB,EAAC6C,KAAK,EAAE;YACtCb,WAAW,EAAE,IAAI;YACjBe,2BAA2B,EAAE,CAAC,QAAQ;UAC1C,CAAC,CAAC;UACF,IAAA9C,cAAM,EAACuB,OAAO,CAACtB,IAAI,CAAC,CAACC,OAAO,CAAC2C,MAAM,CAAC;UACpC,IAAA7C,cAAM,EAACuB,OAAO,CAACpB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;UAElC,MAAMsB,OAAO,GAAG,IAAAzB,gCAAkB,EAAC6C,KAAK,EAAE;YACtCb,WAAW,EAAE,IAAI;YACjBgB,0BAA0B,EAAE,CAAC,QAAQ;UACzC,CAAC,CAAC;UACF,IAAA/C,cAAM,EAACwB,OAAO,CAACvB,IAAI,CAAC,CAACC,OAAO,CAAC2C,MAAM,CAAC;UACpC,IAAA7C,cAAM,EAACwB,OAAO,CAACrB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACtC,CAAC,CAAC;QAEF,IAAAL,YAAI,EAAC,uCAAuC,EAAE,MAAM;UAChD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,4BAA4B,EAAE;YAC5DgC,WAAW,EAAE;UACjB,CAAC,CAAC;UACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,mCAAmC,CAAC;UAChE,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;QACrC,CAAC,CAAC;MACN,CAAC,CAAC;MAEF,IAAAN,gBAAQ,EAAC,aAAa,EAAE,MAAM;QAC1B,IAAAA,gBAAQ,EAAC,kBAAkB,EAAE,MAAM;UAC/B,IAAAC,YAAI,EAAC,kEAAkE,EAAE,MAAM;YAC3E,MAAM0B,OAAO,GAAG,IAAAxB,gCAAkB,EAAC,0BAA0B,EAAE;cAC3DgC,WAAW,EAAE;YACjB,CAAC,CAAC;YACF,IAAA/B,cAAM,EAACuB,OAAO,CAACtB,IAAI,CAAC,CAACC,OAAO,CAAC,+BAA+B,CAAC;YAC7D,IAAAF,cAAM,EAACuB,OAAO,CAACpB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;YAElC,MAAMsB,OAAO,GAAG,IAAAzB,gCAAkB,EAAC,4BAA4B,EAAE;cAC7DgC,WAAW,EAAE;YACjB,CAAC,CAAC;YACF,IAAA/B,cAAM,EAACwB,OAAO,CAACvB,IAAI,CAAC,CAACC,OAAO,CAAC,wCAAwC,CAAC;YACtE,IAAAF,cAAM,EAACwB,OAAO,CAACrB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;UACtC,CAAC,CAAC;UAEF,IAAAL,YAAI,EAAC,6DAA6D,EAAE,MAAM;YACtE,MAAM0B,OAAO,GAAG,IAAAxB,gCAAkB,EAAC,4BAA4B,EAAE;cAC7DgC,WAAW,EAAE;YACjB,CAAC,CAAC;YACF,IAAA/B,cAAM,EAACuB,OAAO,CAACtB,IAAI,CAAC,CAACC,OAAO,CAAC,mCAAmC,CAAC;YACjE,IAAAF,cAAM,EAACuB,OAAO,CAACpB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;YAElC,MAAMsB,OAAO,GAAG,IAAAzB,gCAAkB,EAAC,8BAA8B,EAAE;cAC/DgC,WAAW,EAAE;YACjB,CAAC,CAAC;YACF,IAAA/B,cAAM,EAACwB,OAAO,CAACvB,IAAI,CAAC,CAACC,OAAO,CAAC,0CAA0C,CAAC;YACxE,IAAAF,cAAM,EAACwB,OAAO,CAACrB,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;UACtC,CAAC,CAAC;QACN,CAAC,CAAC;QAEF,IAAAN,gBAAQ,EAAC,iBAAiB,EAAE,MAAM;UAC9B,IAAAC,YAAI,EAAC,iEAAiE,EAAE,MAAM;YAC1E,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,yBAAyB,EAAE;cACzDgC,WAAW,EAAE;YACjB,CAAC,CAAC;YACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,gCAAgC,CAAC;YAC7D,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;UACrC,CAAC,CAAC;;UAEF;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA,IAAAL,YAAI,EAAC,0EAA0E,EAAE,MAAM;YACnF,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,6BAA6B,EAAE;cAC7DgC,WAAW,EAAE;YACjB,CAAC,CAAC;YACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,wBAAwB,CAAC;YACrD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;UACrC,CAAC,CAAC;QACN,CAAC,CAAC;MACN,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,yCAAyC,EAAE,MAAM;QAClD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAC7B,kDAAkD,EAClD;UACIgC,WAAW,EAAE,IAAI;UACjBe,2BAA2B,EAAE,CAAC,MAAM;QACxC,CACJ,CAAC;QACD,IAAA9C,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CACvB,yEACJ,CAAC;QACD,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,wCAAwC,EAAE,MAAM;QACjD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,2CAA2C,EAAE;UAC3EgC,WAAW,EAAE;QACjB,CAAC,CAAC;QACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,kDAAkD,CAAC;QAC/E,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;MAEF,IAAAL,YAAI,EAAC,yCAAyC,EAAE,MAAM;QAClD,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,2BAA2B,EAAE;UAC3DgC,WAAW,EAAE;QACjB,CAAC,CAAC;QACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,kCAAkC,CAAC;QAC/D,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;MACrC,CAAC,CAAC;IACN,CAAC,CAAC;EACN,CAAC,CAAC;EAEF,IAAAN,gBAAQ,EAAC,0CAA0C,EAAE,MAAM;IACvD,IAAAC,YAAI,EAAC,iDAAiD,EAAE,MAAM;MAC1D,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,eAAe,EAAE;QAC/CgC,WAAW,EAAE;MACjB,CAAC,CAAC;MACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,6BAA6B,CAAC;MAC1D,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;IACrC,CAAC,CAAC;IAEF,IAAAL,YAAI,EAAC,iDAAiD,EAAE,MAAM;MAC1D,MAAMC,MAAM,GAAG,IAAAC,gCAAkB,EAAC,eAAe,EAAE;QAC/CgC,WAAW,EAAE;MACjB,CAAC,CAAC;MACF,IAAA/B,cAAM,EAACF,MAAM,CAACG,IAAI,CAAC,CAACC,OAAO,CAAC,6BAA6B,CAAC;MAC1D,IAAAF,cAAM,EAACF,MAAM,CAACK,MAAM,CAAC,CAACD,OAAO,CAAC,EAAE,CAAC;IACrC,CAAC,CAAC;EACN,CAAC,CAAC;AACN,CAAC,CAAC","ignoreList":[]}
@@ -3,39 +3,155 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.parseMarkdown = void 0;
7
- var _commonmark = require("commonmark");
8
- var _escape = require("../../escape");
9
- var _InternalHTMLRenderer = _interopRequireDefault(require("./InternalHTMLRenderer.js"));
10
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
12
- // @ts-ignore
6
+ exports.parseMarkdown = exports.getMarkdownTables = void 0;
7
+ var _marked = require("marked");
8
+ var _sync = require("csv-stringify/browser/esm/sync");
9
+ var _formatBBCode = require("../bb-code/formatBBCode");
10
+ // eslint-disable-next-line import/extensions,import/no-unresolved
13
11
 
14
- const parseMarkdown = text => {
15
- let newText = text;
12
+ const inlineCodeRule = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
13
+ const inlineTextRule = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<![`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
14
+ const TABLE_ID_PREFIX = 'formatted-table-';
16
15
 
17
- // Markdown has its own line break handling. For that reason, we need to replace line breaks with a custom element.
18
- // In this case I chose a custom <br> Tag.
19
- // Since commonmark doesn't parse markdown in lines with html, the custom <br> Tag needs to be in its own line.
20
- // Since there are issues, when the <br> Tag + \n is followed by text, there needs to be a second line break.
21
- // Thus, we replace \n with \n<br>\n\n.
22
- newText = newText.replaceAll(/\n/gm, `\n${_escape.MESSAGE_CONVERSION_LINE_BREAK}\n\n`);
23
- const commonmarkParser = new _commonmark.Parser();
24
- // TODO Check if esc needs to be passed to InternalHTMLRenderer.
25
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call
26
- const internalHTMLRenderer = new _InternalHTMLRenderer.default({
27
- esc: _escape.escapeHtmlInText
16
+ /*
17
+ The marked Pipeline, including tokenizer, renderer and hooks are explained here:
18
+ https://marked.js.org/using_pro
19
+ */
20
+
21
+ const tokenizer = {
22
+ // Codespan Tokenizer is overwritten to prevent html escaping, since html is already escaped.
23
+ // The function is copied from marked.js and slightly modified: https://github.com/markedjs/marked/blob/42954aaba960b6f815b24ec0d39da464960e4ec9/src/Tokenizer.ts#L749
24
+ codespan(src) {
25
+ const cap = inlineCodeRule.exec(src);
26
+ if (cap) {
27
+ let text = cap[2].replace(/\n/g, ' ');
28
+ const hasNonSpaceChars = /[^ ]/.test(text);
29
+ const hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);
30
+ if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
31
+ text = text.substring(1, text.length - 1);
32
+ }
33
+ return {
34
+ type: 'codespan',
35
+ raw: cap[0],
36
+ text
37
+ };
38
+ }
39
+ return undefined;
40
+ },
41
+ lheading() {
42
+ return undefined;
43
+ },
44
+ url() {
45
+ return undefined;
46
+ },
47
+ // inlineText is overwritten to prevent html escaping, specifically since quote characters are escaped, which breaks the attributes of bb-code elements.
48
+ // The function is copied from marked.js and slightly modified: https://github.com/markedjs/marked/blob/42954aaba960b6f815b24ec0d39da464960e4ec9/src/Tokenizer.ts#L854
49
+ inlineText(src) {
50
+ const cap = inlineTextRule.exec(src);
51
+ if (cap) {
52
+ return {
53
+ type: 'text',
54
+ raw: cap[0],
55
+ text: cap[0]
56
+ };
57
+ }
58
+ return undefined;
59
+ }
60
+ };
61
+ const renderer = {
62
+ // Code Renderer is overwritten to prevent html escaping, since html is already escaped.
63
+ // The function is copied from marked.js and slightly modified: https://github.com/markedjs/marked/blob/42954aaba960b6f815b24ec0d39da464960e4ec9/src/Renderer.ts#L24
64
+ code(text, lang) {
65
+ var _match;
66
+ const langString = (_match = (lang || '').match(/^\S*/)) === null || _match === void 0 ? void 0 : _match[0];
67
+ const code = `${text.replace(/\n$/, '')}`;
68
+ if (!langString) {
69
+ return `<pre><code>${code}</code></pre>\n`;
70
+ }
71
+ return `<pre><code class="language-${langString}">${code}</code></pre>\n`;
72
+ },
73
+ // Replaces the checkbox input elements with markdown checkboxes.
74
+ // This is the easiest way to prevent the formatting of markdown checkboxes in lists.
75
+ // This can modify the input string slightly, since the capitalization of the checkbox can be lost.
76
+ // If a user types '- [X]' it will be replaced with '- [x]' => the capitalization is lost.
77
+ checkbox({
78
+ checked
79
+ }) {
80
+ return checked ? '[x]' : '[ ]';
81
+ }
82
+ };
83
+ const postprocess = html => {
84
+ let tableIndex = 0;
85
+ // Assigns ids to tables.
86
+ const modifiedString = html.replace(/(<table>)/g, () => {
87
+ const result = `<table id="${TABLE_ID_PREFIX}${tableIndex}">`;
88
+ tableIndex++;
89
+ return result;
28
90
  });
91
+ return modifiedString;
92
+ };
29
93
 
30
- // Converts markdown to HTML.
31
- const parsedText = commonmarkParser.parse(newText);
32
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
33
- newText = internalHTMLRenderer.render(parsedText);
94
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
95
+ // @ts-ignore
96
+ _marked.marked.use({
97
+ tokenizer,
98
+ renderer,
99
+ hooks: {
100
+ postprocess
101
+ }
102
+ });
34
103
 
35
- // The Linebreak handling of markdown is ignored, by removing \n. Then the custom <br> Tags are converted back to \n.
36
- newText = newText.replaceAll(/\n/gm, '');
37
- newText = newText.replaceAll(_escape.MESSAGE_CONVERSION_LINE_BREAK, '\n').replaceAll(_escape.MESSAGE_CONVERSION_LINE_BREAK_ESCAPED, '\n');
38
- return newText;
39
- };
104
+ // Parses markdown following the Github Flavored Markdown specification.
105
+ // The tokenizer and renderer are slightly modified to prevent html escaping in code block and inline code.
106
+ const parseMarkdown = (text, parseBBCode) => _marked.marked.parse(text, {
107
+ walkTokens: token => {
108
+ if (parseBBCode && (token.type === 'codespan' || token.type === 'code')) {
109
+ // eslint-disable-next-line no-param-reassign
110
+ token.text = (0, _formatBBCode.escapeBBCodeSquareBrackets)(token.text);
111
+ }
112
+ }
113
+ });
114
+
115
+ // It is important that, &amp; is replaced lastly to prevent double escaping.
40
116
  exports.parseMarkdown = parseMarkdown;
117
+ const unescapeHtml = text => text.replaceAll('&lt;', '<').replaceAll('&gt;', '>').replaceAll('&amp;', '&');
118
+ const getMarkdownTables = text => {
119
+ const tableTokens = [];
120
+ _marked.marked.parse(text, {
121
+ walkTokens: token => {
122
+ if (token.type === 'table') {
123
+ tableTokens.push(token);
124
+ }
125
+ }
126
+ });
127
+ const tables = [];
128
+ tableTokens.forEach((tableToken, index) => {
129
+ var _tableToken$header, _tableToken$rows;
130
+ const tableArray = [];
131
+ if (((_tableToken$header = tableToken.header) === null || _tableToken$header === void 0 ? void 0 : _tableToken$header.length) > 0) {
132
+ const rowArray = [];
133
+ tableToken.header.forEach(header => {
134
+ rowArray.push(unescapeHtml(header.text));
135
+ });
136
+ tableArray.push(rowArray);
137
+ }
138
+ if (((_tableToken$rows = tableToken.rows) === null || _tableToken$rows === void 0 ? void 0 : _tableToken$rows.length) > 0) {
139
+ tableToken.rows.forEach(row => {
140
+ const rowArray = [];
141
+ row.forEach(cell => {
142
+ rowArray.push(unescapeHtml(cell.text));
143
+ });
144
+ tableArray.push(rowArray);
145
+ });
146
+ }
147
+ const csv = (0, _sync.stringify)(tableArray || []);
148
+ tables.push({
149
+ raw: unescapeHtml(tableToken.raw),
150
+ csv,
151
+ id: `${TABLE_ID_PREFIX}${index}`
152
+ });
153
+ });
154
+ return tables;
155
+ };
156
+ exports.getMarkdownTables = getMarkdownTables;
41
157
  //# sourceMappingURL=formatMarkdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatMarkdown.js","names":["_commonmark","require","_escape","_InternalHTMLRenderer","_interopRequireDefault","e","__esModule","default","parseMarkdown","text","newText","replaceAll","MESSAGE_CONVERSION_LINE_BREAK","commonmarkParser","Parser","internalHTMLRenderer","InternalHTMLRenderer","esc","escapeHtmlInText","parsedText","parse","render","MESSAGE_CONVERSION_LINE_BREAK_ESCAPED","exports"],"sources":["../../../../../src/utils/formatString/markdown/formatMarkdown.ts"],"sourcesContent":["import { Parser } from 'commonmark';\nimport {\n escapeHtmlInText,\n MESSAGE_CONVERSION_LINE_BREAK,\n MESSAGE_CONVERSION_LINE_BREAK_ESCAPED,\n} from '../../escape';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport InternalHTMLRenderer from './InternalHTMLRenderer.js';\n\nexport const parseMarkdown = (text: string) => {\n let newText = text;\n\n // Markdown has its own line break handling. For that reason, we need to replace line breaks with a custom element.\n // In this case I chose a custom <br> Tag.\n // Since commonmark doesn't parse markdown in lines with html, the custom <br> Tag needs to be in its own line.\n // Since there are issues, when the <br> Tag + \\n is followed by text, there needs to be a second line break.\n // Thus, we replace \\n with \\n<br>\\n\\n.\n newText = newText.replaceAll(/\\n/gm, `\\n${MESSAGE_CONVERSION_LINE_BREAK}\\n\\n`);\n\n const commonmarkParser = new Parser();\n // TODO Check if esc needs to be passed to InternalHTMLRenderer.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call\n const internalHTMLRenderer = new InternalHTMLRenderer({ esc: escapeHtmlInText });\n\n // Converts markdown to HTML.\n const parsedText = commonmarkParser.parse(newText);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access\n newText = internalHTMLRenderer.render(parsedText) as string;\n\n // The Linebreak handling of markdown is ignored, by removing \\n. Then the custom <br> Tags are converted back to \\n.\n newText = newText.replaceAll(/\\n/gm, '');\n newText = newText\n .replaceAll(MESSAGE_CONVERSION_LINE_BREAK, '\\n')\n .replaceAll(MESSAGE_CONVERSION_LINE_BREAK_ESCAPED, '\\n');\n\n return newText;\n};\n"],"mappings":";;;;;;AAAA,IAAAA,WAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AAOA,IAAAE,qBAAA,GAAAC,sBAAA,CAAAH,OAAA;AAA6D,SAAAG,uBAAAC,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAF7D;AACA;;AAGO,MAAMG,aAAa,GAAIC,IAAY,IAAK;EAC3C,IAAIC,OAAO,GAAGD,IAAI;;EAElB;EACA;EACA;EACA;EACA;EACAC,OAAO,GAAGA,OAAO,CAACC,UAAU,CAAC,MAAM,EAAE,KAAKC,qCAA6B,MAAM,CAAC;EAE9E,MAAMC,gBAAgB,GAAG,IAAIC,kBAAM,CAAC,CAAC;EACrC;EACA;EACA,MAAMC,oBAAoB,GAAG,IAAIC,6BAAoB,CAAC;IAAEC,GAAG,EAAEC;EAAiB,CAAC,CAAC;;EAEhF;EACA,MAAMC,UAAU,GAAGN,gBAAgB,CAACO,KAAK,CAACV,OAAO,CAAC;EAClD;EACAA,OAAO,GAAGK,oBAAoB,CAACM,MAAM,CAACF,UAAU,CAAW;;EAE3D;EACAT,OAAO,GAAGA,OAAO,CAACC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;EACxCD,OAAO,GAAGA,OAAO,CACZC,UAAU,CAACC,qCAA6B,EAAE,IAAI,CAAC,CAC/CD,UAAU,CAACW,6CAAqC,EAAE,IAAI,CAAC;EAE5D,OAAOZ,OAAO;AAClB,CAAC;AAACa,OAAA,CAAAf,aAAA,GAAAA,aAAA","ignoreList":[]}
1
+ {"version":3,"file":"formatMarkdown.js","names":["_marked","require","_sync","_formatBBCode","inlineCodeRule","inlineTextRule","TABLE_ID_PREFIX","tokenizer","codespan","src","cap","exec","text","replace","hasNonSpaceChars","test","hasSpaceCharsOnBothEnds","substring","length","type","raw","undefined","lheading","url","inlineText","renderer","code","lang","_match","langString","match","checkbox","checked","postprocess","html","tableIndex","modifiedString","result","marked","use","hooks","parseMarkdown","parseBBCode","parse","walkTokens","token","escapeBBCodeSquareBrackets","exports","unescapeHtml","replaceAll","getMarkdownTables","tableTokens","push","tables","forEach","tableToken","index","_tableToken$header","_tableToken$rows","tableArray","header","rowArray","rows","row","cell","csv","stringify","id"],"sources":["../../../../../src/utils/formatString/markdown/formatMarkdown.ts"],"sourcesContent":["import { marked, Tokens } from 'marked';\nimport type { TableObject } from '../../../types/format';\n// eslint-disable-next-line import/extensions,import/no-unresolved\nimport { stringify } from 'csv-stringify/browser/esm/sync';\nimport { escapeBBCodeSquareBrackets } from '../bb-code/formatBBCode';\n\nconst inlineCodeRule = /^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/;\nconst inlineTextRule = /^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\<![`*_]|\\b_|$)|[^ ](?= {2,}\\n)))/;\n\nconst TABLE_ID_PREFIX = 'formatted-table-';\n\n/*\n The marked Pipeline, including tokenizer, renderer and hooks are explained here:\n https://marked.js.org/using_pro\n*/\n\nconst tokenizer = {\n // Codespan Tokenizer is overwritten to prevent html escaping, since html is already escaped.\n // The function is copied from marked.js and slightly modified: https://github.com/markedjs/marked/blob/42954aaba960b6f815b24ec0d39da464960e4ec9/src/Tokenizer.ts#L749\n codespan(src: string): Tokens.Codespan | undefined {\n const cap = inlineCodeRule.exec(src);\n if (cap) {\n let text = (cap[2] as string).replace(/\\n/g, ' ');\n const hasNonSpaceChars = /[^ ]/.test(text);\n const hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);\n if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {\n text = text.substring(1, text.length - 1);\n }\n\n return {\n type: 'codespan',\n raw: cap[0],\n text,\n };\n }\n\n return undefined;\n },\n lheading(): Tokens.Heading | undefined {\n return undefined;\n },\n url() {\n return undefined;\n },\n // inlineText is overwritten to prevent html escaping, specifically since quote characters are escaped, which breaks the attributes of bb-code elements.\n // The function is copied from marked.js and slightly modified: https://github.com/markedjs/marked/blob/42954aaba960b6f815b24ec0d39da464960e4ec9/src/Tokenizer.ts#L854\n inlineText(src: string) {\n const cap = inlineTextRule.exec(src);\n if (cap) {\n return {\n type: 'text',\n raw: cap[0],\n text: cap[0],\n };\n }\n return undefined;\n },\n};\n\nconst renderer = {\n // Code Renderer is overwritten to prevent html escaping, since html is already escaped.\n // The function is copied from marked.js and slightly modified: https://github.com/markedjs/marked/blob/42954aaba960b6f815b24ec0d39da464960e4ec9/src/Renderer.ts#L24\n code(text: string, lang: string): string {\n const langString = (lang || '').match(/^\\S*/)?.[0];\n\n const code = `${text.replace(/\\n$/, '')}`;\n\n if (!langString) {\n return `<pre><code>${code}</code></pre>\\n`;\n }\n\n return `<pre><code class=\"language-${langString}\">${code}</code></pre>\\n`;\n },\n // Replaces the checkbox input elements with markdown checkboxes.\n // This is the easiest way to prevent the formatting of markdown checkboxes in lists.\n // This can modify the input string slightly, since the capitalization of the checkbox can be lost.\n // If a user types '- [X]' it will be replaced with '- [x]' => the capitalization is lost.\n checkbox({ checked }: Tokens.Checkbox) {\n return checked ? '[x]' : '[ ]';\n },\n};\n\nconst postprocess = (html: string): string => {\n let tableIndex = 0;\n // Assigns ids to tables.\n const modifiedString = html.replace(/(<table>)/g, () => {\n const result = `<table id=\"${TABLE_ID_PREFIX}${tableIndex}\">`;\n tableIndex++;\n return result;\n });\n\n return modifiedString;\n};\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nmarked.use({ tokenizer, renderer, hooks: { postprocess } });\n\n// Parses markdown following the Github Flavored Markdown specification.\n// The tokenizer and renderer are slightly modified to prevent html escaping in code block and inline code.\nexport const parseMarkdown = (text: string, parseBBCode: boolean) =>\n marked.parse(text, {\n walkTokens: (token) => {\n if (parseBBCode && (token.type === 'codespan' || token.type === 'code')) {\n // eslint-disable-next-line no-param-reassign\n (token as Tokens.Codespan).text = escapeBBCodeSquareBrackets(\n (token as Tokens.Codespan).text,\n );\n }\n },\n }) as string;\n\n// It is important that, &amp; is replaced lastly to prevent double escaping.\nconst unescapeHtml = (text: string) =>\n text.replaceAll('&lt;', '<').replaceAll('&gt;', '>').replaceAll('&amp;', '&');\n\nexport const getMarkdownTables = (text: string): TableObject[] => {\n const tableTokens: Tokens.Table[] = [];\n\n marked.parse(text, {\n walkTokens: (token) => {\n if (token.type === 'table') {\n tableTokens.push(token as Tokens.Table);\n }\n },\n }) as string;\n\n const tables: TableObject[] = [];\n\n tableTokens.forEach((tableToken, index) => {\n const tableArray: string[][] = [];\n\n if (tableToken.header?.length > 0) {\n const rowArray: string[] = [];\n\n tableToken.header.forEach((header) => {\n rowArray.push(unescapeHtml(header.text));\n });\n\n tableArray.push(rowArray);\n }\n if (tableToken.rows?.length > 0) {\n tableToken.rows.forEach((row) => {\n const rowArray: string[] = [];\n\n row.forEach((cell) => {\n rowArray.push(unescapeHtml(cell.text));\n });\n\n tableArray.push(rowArray);\n });\n }\n\n const csv = stringify(tableArray || []);\n\n tables.push({\n raw: unescapeHtml(tableToken.raw),\n csv,\n id: `${TABLE_ID_PREFIX}${index}`,\n });\n });\n\n return tables;\n};\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+
2
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","names":[],"sources":["../../../src/types/format.ts"],"sourcesContent":["export type TableObject = {\n raw: string;\n csv: string;\n id: string;\n};\n"],"mappings":"","ignoreList":[]}
@@ -1,5 +1,4 @@
1
1
  export const escapeHtmlInText = text => text.replace(/</g, '&lt;').replace(/>/g, '&gt;');
2
- export const unescapeSquareBrackets = text => text.replaceAll('&#91;', '[').replaceAll('&#93;', ']');
3
2
  export const MESSAGE_CONVERSION_LINE_BREAK = '<br is-replaced-linebreak>';
4
3
  export const MESSAGE_CONVERSION_LINE_BREAK_ESCAPED = escapeHtmlInText(MESSAGE_CONVERSION_LINE_BREAK);
5
4
  //# sourceMappingURL=escape.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"escape.js","names":["escapeHtmlInText","text","replace","unescapeSquareBrackets","replaceAll","MESSAGE_CONVERSION_LINE_BREAK","MESSAGE_CONVERSION_LINE_BREAK_ESCAPED"],"sources":["../../../src/utils/escape.ts"],"sourcesContent":["export const escapeHtmlInText = (text: string): string =>\n text.replace(/</g, '&lt;').replace(/>/g, '&gt;');\n\nexport const unescapeSquareBrackets = (text: string): string =>\n text.replaceAll('&#91;', '[').replaceAll('&#93;', ']');\n\nexport const MESSAGE_CONVERSION_LINE_BREAK = '<br is-replaced-linebreak>';\nexport const MESSAGE_CONVERSION_LINE_BREAK_ESCAPED = escapeHtmlInText(\n MESSAGE_CONVERSION_LINE_BREAK,\n);\n"],"mappings":"AAAA,OAAO,MAAMA,gBAAgB,GAAIC,IAAY,IACzCA,IAAI,CAACC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAACA,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;AAEpD,OAAO,MAAMC,sBAAsB,GAAIF,IAAY,IAC/CA,IAAI,CAACG,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAACA,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC;AAE1D,OAAO,MAAMC,6BAA6B,GAAG,4BAA4B;AACzE,OAAO,MAAMC,qCAAqC,GAAGN,gBAAgB,CACjEK,6BACJ,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"escape.js","names":["escapeHtmlInText","text","replace","MESSAGE_CONVERSION_LINE_BREAK","MESSAGE_CONVERSION_LINE_BREAK_ESCAPED"],"sources":["../../../src/utils/escape.ts"],"sourcesContent":["export const escapeHtmlInText = (text: string): string =>\n text.replace(/</g, '&lt;').replace(/>/g, '&gt;');\n\nexport const MESSAGE_CONVERSION_LINE_BREAK = '<br is-replaced-linebreak>';\nexport const MESSAGE_CONVERSION_LINE_BREAK_ESCAPED = escapeHtmlInText(\n MESSAGE_CONVERSION_LINE_BREAK,\n);\n"],"mappings":"AAAA,OAAO,MAAMA,gBAAgB,GAAIC,IAAY,IACzCA,IAAI,CAACC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAACA,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;AAEpD,OAAO,MAAMC,6BAA6B,GAAG,4BAA4B;AACzE,OAAO,MAAMC,qCAAqC,GAAGJ,gBAAgB,CACjEG,6BACJ,CAAC","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- const BB_REGEX = /\[([a-zA-Z0-9_]*)(.*?)\](.*?)\[\/\1\]/s;
1
+ const BB_REGEX = /(\[([a-zA-Z0-9_]*)(.*?)\])(.*?)(\[\/\2\])/s;
2
2
  // Also matches "\" before quote to fix button for voucher messages
3
3
  const PARAMETER_REGEX = /([\w]*?)=\\?["„](.*?)["“]/g;
4
4
  // TODO Use external package instead of RegExp to parse BBCode.
@@ -8,11 +8,11 @@ const PARAMETER_REGEX = /([\w]*?)=\\?["„](.*?)["“]/g;
8
8
  export function findFirstBBCode(inputString) {
9
9
  const matches = BB_REGEX.exec(inputString);
10
10
  if (matches !== null) {
11
- const [fullMatch, tag, params, content] = matches;
11
+ const [fullMatch, openingTag, tag, params, content, closingTag] = matches;
12
12
  const {
13
13
  index
14
14
  } = matches;
15
- if (fullMatch === undefined || tag === undefined || params === undefined || content === undefined) return null;
15
+ if (fullMatch === undefined || tag === undefined || params === undefined || content === undefined || openingTag === undefined || closingTag === undefined) return null;
16
16
  const parameters = {};
17
17
  let match = null;
18
18
  // eslint-disable-next-line no-cond-assign
@@ -27,7 +27,9 @@ export function findFirstBBCode(inputString) {
27
27
  tag,
28
28
  parameters,
29
29
  content,
30
- index
30
+ index,
31
+ openingTag,
32
+ closingTag
31
33
  };
32
34
  }
33
35
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"findBBCode.js","names":["BB_REGEX","PARAMETER_REGEX","findFirstBBCode","inputString","matches","exec","fullMatch","tag","params","content","index","undefined","parameters","match","key","value"],"sources":["../../../../../src/utils/formatString/bb-code/findBBCode.ts"],"sourcesContent":["const BB_REGEX = /\\[([a-zA-Z0-9_]*)(.*?)\\](.*?)\\[\\/\\1\\]/s;\n// Also matches \"\\\" before quote to fix button for voucher messages\nconst PARAMETER_REGEX = /([\\w]*?)=\\\\?[\"„](.*?)[\"“]/g;\n\nexport interface BBCodeMatch {\n fullMatch: string;\n tag: string;\n parameters: Record<string, string>;\n content: string;\n index: number;\n}\n\n// TODO Use external package instead of RegExp to parse BBCode.\n// It is not recommended to use RegExp to parse markup languages like BBCode, because it is not possible to parse nested tags with it.\n\n// Finds and returns the first BBCode tag in the input string.\nexport function findFirstBBCode(inputString: string): BBCodeMatch | null {\n const matches = BB_REGEX.exec(inputString);\n\n if (matches !== null) {\n const [fullMatch, tag, params, content] = matches;\n const { index } = matches;\n\n if (\n fullMatch === undefined ||\n tag === undefined ||\n params === undefined ||\n content === undefined\n )\n return null;\n\n const parameters: Record<string, string> = {};\n\n let match: RegExpExecArray | null = null;\n // eslint-disable-next-line no-cond-assign\n while ((match = PARAMETER_REGEX.exec(params))) {\n const [, key, value] = match;\n\n if (value) {\n parameters[key || 'url'] = value;\n }\n }\n\n return {\n fullMatch,\n tag,\n parameters,\n content,\n index,\n };\n }\n\n return null;\n}\n"],"mappings":"AAAA,MAAMA,QAAQ,GAAG,wCAAwC;AACzD;AACA,MAAMC,eAAe,GAAG,4BAA4B;AAUpD;AACA;;AAEA;AACA,OAAO,SAASC,eAAeA,CAACC,WAAmB,EAAsB;EACrE,MAAMC,OAAO,GAAGJ,QAAQ,CAACK,IAAI,CAACF,WAAW,CAAC;EAE1C,IAAIC,OAAO,KAAK,IAAI,EAAE;IAClB,MAAM,CAACE,SAAS,EAAEC,GAAG,EAAEC,MAAM,EAAEC,OAAO,CAAC,GAAGL,OAAO;IACjD,MAAM;MAAEM;IAAM,CAAC,GAAGN,OAAO;IAEzB,IACIE,SAAS,KAAKK,SAAS,IACvBJ,GAAG,KAAKI,SAAS,IACjBH,MAAM,KAAKG,SAAS,IACpBF,OAAO,KAAKE,SAAS,EAErB,OAAO,IAAI;IAEf,MAAMC,UAAkC,GAAG,CAAC,CAAC;IAE7C,IAAIC,KAA6B,GAAG,IAAI;IACxC;IACA,OAAQA,KAAK,GAAGZ,eAAe,CAACI,IAAI,CAACG,MAAM,CAAC,EAAG;MAC3C,MAAM,GAAGM,GAAG,EAAEC,KAAK,CAAC,GAAGF,KAAK;MAE5B,IAAIE,KAAK,EAAE;QACPH,UAAU,CAACE,GAAG,IAAI,KAAK,CAAC,GAAGC,KAAK;MACpC;IACJ;IAEA,OAAO;MACHT,SAAS;MACTC,GAAG;MACHK,UAAU;MACVH,OAAO;MACPC;IACJ,CAAC;EACL;EAEA,OAAO,IAAI;AACf","ignoreList":[]}
1
+ {"version":3,"file":"findBBCode.js","names":["BB_REGEX","PARAMETER_REGEX","findFirstBBCode","inputString","matches","exec","fullMatch","openingTag","tag","params","content","closingTag","index","undefined","parameters","match","key","value"],"sources":["../../../../../src/utils/formatString/bb-code/findBBCode.ts"],"sourcesContent":["const BB_REGEX = /(\\[([a-zA-Z0-9_]*)(.*?)\\])(.*?)(\\[\\/\\2\\])/s;\n// Also matches \"\\\" before quote to fix button for voucher messages\nconst PARAMETER_REGEX = /([\\w]*?)=\\\\?[\"„](.*?)[\"“]/g;\n\nexport interface BBCodeMatch {\n fullMatch: string;\n tag: string;\n parameters: Record<string, string>;\n content: string;\n index: number;\n openingTag: string;\n closingTag: string;\n}\n\n// TODO Use external package instead of RegExp to parse BBCode.\n// It is not recommended to use RegExp to parse markup languages like BBCode, because it is not possible to parse nested tags with it.\n\n// Finds and returns the first BBCode tag in the input string.\nexport function findFirstBBCode(inputString: string): BBCodeMatch | null {\n const matches = BB_REGEX.exec(inputString);\n\n if (matches !== null) {\n const [fullMatch, openingTag, tag, params, content, closingTag] = matches;\n const { index } = matches;\n\n if (\n fullMatch === undefined ||\n tag === undefined ||\n params === undefined ||\n content === undefined ||\n openingTag === undefined ||\n closingTag === undefined\n )\n return null;\n\n const parameters: Record<string, string> = {};\n\n let match: RegExpExecArray | null = null;\n // eslint-disable-next-line no-cond-assign\n while ((match = PARAMETER_REGEX.exec(params))) {\n const [, key, value] = match;\n\n if (value) {\n parameters[key || 'url'] = value;\n }\n }\n\n return {\n fullMatch,\n tag,\n parameters,\n content,\n index,\n openingTag,\n closingTag,\n };\n }\n\n return null;\n}\n"],"mappings":"AAAA,MAAMA,QAAQ,GAAG,4CAA4C;AAC7D;AACA,MAAMC,eAAe,GAAG,4BAA4B;AAYpD;AACA;;AAEA;AACA,OAAO,SAASC,eAAeA,CAACC,WAAmB,EAAsB;EACrE,MAAMC,OAAO,GAAGJ,QAAQ,CAACK,IAAI,CAACF,WAAW,CAAC;EAE1C,IAAIC,OAAO,KAAK,IAAI,EAAE;IAClB,MAAM,CAACE,SAAS,EAAEC,UAAU,EAAEC,GAAG,EAAEC,MAAM,EAAEC,OAAO,EAAEC,UAAU,CAAC,GAAGP,OAAO;IACzE,MAAM;MAAEQ;IAAM,CAAC,GAAGR,OAAO;IAEzB,IACIE,SAAS,KAAKO,SAAS,IACvBL,GAAG,KAAKK,SAAS,IACjBJ,MAAM,KAAKI,SAAS,IACpBH,OAAO,KAAKG,SAAS,IACrBN,UAAU,KAAKM,SAAS,IACxBF,UAAU,KAAKE,SAAS,EAExB,OAAO,IAAI;IAEf,MAAMC,UAAkC,GAAG,CAAC,CAAC;IAE7C,IAAIC,KAA6B,GAAG,IAAI;IACxC;IACA,OAAQA,KAAK,GAAGd,eAAe,CAACI,IAAI,CAACI,MAAM,CAAC,EAAG;MAC3C,MAAM,GAAGO,GAAG,EAAEC,KAAK,CAAC,GAAGF,KAAK;MAE5B,IAAIE,KAAK,EAAE;QACPH,UAAU,CAACE,GAAG,IAAI,KAAK,CAAC,GAAGC,KAAK;MACpC;IACJ;IAEA,OAAO;MACHX,SAAS;MACTE,GAAG;MACHM,UAAU;MACVJ,OAAO;MACPE,KAAK;MACLL,UAAU;MACVI;IACJ,CAAC;EACL;EAEA,OAAO,IAAI;AACf","ignoreList":[]}
@@ -2,15 +2,14 @@ import { findFirstBBCode } from './findBBCode';
2
2
  const BB_CODE_HTML_TAG_PREFIX = 'bb-code-';
3
3
  const BLOCK_LEVEL_TAGS = ['center', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'];
4
4
  const INLINE_LEVEL_TAGS = ['b', 'strong', 'i', 'em', 'u', 's', 'span', 'img'];
5
- const HTML_CODE_PATTERN = /(?:<code>|<code class="inline-code">)[\s\S]*?<\/code>/;
6
5
  // Parses BB-Code to HTML recursively.
7
6
  // When justEscapeSquareBrackets is true, square brackets are escaped to prevent conflicts between markdown and BB Code.
8
7
  // In that case the function only escapes square brackets and doesn't remove line breaks.
9
8
  export const parseBBCode = (text, options) => {
10
9
  const {
11
- justEscapeSquareBrackets = false,
12
10
  customBlockLevelBBCodeTags: customBlockLevelTags = [],
13
- customInlineLevelBBCodeTags: customInlineLevelTags = []
11
+ customInlineLevelBBCodeTags: customInlineLevelTags = [],
12
+ justEscapeSquareBrackets = false
14
13
  } = options || {};
15
14
  let html = text;
16
15
 
@@ -18,26 +17,19 @@ export const parseBBCode = (text, options) => {
18
17
  let parseBehindIndex = 0;
19
18
  while (parseBehindIndex < html.length) {
20
19
  const htmlToParse = html.slice(parseBehindIndex);
21
- const firstCodeElementMatch = HTML_CODE_PATTERN.exec(htmlToParse);
22
20
  const firstBBCodeMatch = findFirstBBCode(htmlToParse);
23
21
 
24
22
  // Stops parsing if no BB-Code is found.
25
23
  if (!firstBBCodeMatch) {
26
24
  return html;
27
25
  }
28
-
29
- // Prevents bb-code parsing within code block.
30
- if (firstCodeElementMatch && firstBBCodeMatch && firstCodeElementMatch.index < firstBBCodeMatch.index) {
31
- // If a code block is found before a BB-Code tag, BB-Code parsing continues behind the code block.
32
- parseBehindIndex += firstCodeElementMatch.index + firstCodeElementMatch[0].length;
33
- // eslint-disable-next-line no-continue
34
- continue;
35
- }
36
26
  const {
37
27
  content,
38
28
  fullMatch,
39
29
  parameters,
40
- index
30
+ index,
31
+ openingTag,
32
+ closingTag
41
33
  } = firstBBCodeMatch;
42
34
  const Tag = firstBBCodeMatch.tag.toLowerCase();
43
35
  const isValidTag = [...BLOCK_LEVEL_TAGS, ...customBlockLevelTags, ...INLINE_LEVEL_TAGS, ...customInlineLevelTags].includes(Tag);
@@ -52,39 +44,45 @@ export const parseBBCode = (text, options) => {
52
44
  }
53
45
 
54
46
  // Converts BB-Code tag's content before converting itself, because it may contain other BB-Codes.
55
- let parsedContent = parseBBCode(content);
47
+ let parsedContent = parseBBCode(content, options);
48
+ if (justEscapeSquareBrackets) {
49
+ const indexOfFullMatch = html.indexOf(fullMatch);
50
+ const escapedOpeningTag = escapeBBCodeSquareBrackets(openingTag);
51
+ const escapedClosingTag = escapeBBCodeSquareBrackets(closingTag);
56
52
 
57
- // Removes leading and trailing line-breaks from within bb code elements, to prevent unwanted spacing.
58
- if (!justEscapeSquareBrackets) {
53
+ // Removes leading and trailing line-breaks from within bb code elements, to prevent unwanted spacing.
54
+ // This needs to be done before formatting Markdown, so the Markdown formatting doesn't interpret line breaks unexpectedly.
59
55
  parsedContent = parsedContent.replace(/^\n+|\n+$/g, '');
60
- }
61
- const indexOfFullMatch = html.indexOf(fullMatch);
62
- let htmlAfterTag = html.slice(indexOfFullMatch + fullMatch.length);
63
-
64
- // Removes leading line-break (ONE, NOT ALL) after block level elements, to prevent unwanted spacing.
65
- if (!justEscapeSquareBrackets && isBlockLevelTag) {
66
- htmlAfterTag = htmlAfterTag.replace(/^\n/, '');
67
- }
68
56
 
69
- // Use escaped square brackets to prevent conflicts between markdown and BB Code.
70
- const openTag = justEscapeSquareBrackets ? '&#91;' : '<';
71
- const closeTag = justEscapeSquareBrackets ? '&#93;' : '>';
57
+ // Simply escapes the square brackets of the BB-Code opening and closing tag.
58
+ html = html.slice(0, indexOfFullMatch) + escapedOpeningTag + parsedContent + escapedClosingTag + html.slice(indexOfFullMatch + fullMatch.length);
72
59
 
73
- // TODO Don't alter content of bb-code tags when justEscapeSquareBrackets is true.
74
- // This is necessary to preserve whitespaces in bb-code tags within code blocks.
60
+ // Continues parsing behind the parsed bb-code.
61
+ parseBehindIndex = indexOfFullMatch + escapedOpeningTag.length + parsedContent.length + escapedClosingTag.length;
62
+ } else {
63
+ const indexOfFullMatch = html.indexOf(fullMatch);
64
+ let htmlAfterTag = html.slice(indexOfFullMatch + fullMatch.length);
75
65
 
76
- const isCustomTag = [...customBlockLevelTags, ...customInlineLevelTags].includes(Tag);
77
- const htmlTag = !justEscapeSquareBrackets && isCustomTag ? `${BB_CODE_HTML_TAG_PREFIX}${Tag}` : Tag;
78
- const openingTag = `${openTag}${htmlTag}${Object.entries(parameters).length > 0 ? ' ' : ''}${Object.entries(parameters).map(_ref => {
79
- let [key, value] = _ref;
80
- return `${key}="${value}"`;
81
- }).join(' ')}${closeTag}`;
82
- const closingTag = `${openTag}/${htmlTag}${closeTag}`;
83
- html = html.slice(0, indexOfFullMatch) + openingTag + parsedContent + closingTag + htmlAfterTag;
66
+ // Removes leading line-break (ONE, NOT ALL) after block level elements, to prevent unwanted spacing.
67
+ if (isBlockLevelTag) {
68
+ htmlAfterTag = htmlAfterTag.replace(/^\n/, '');
69
+ }
70
+ const isCustomTag = [...customBlockLevelTags, ...customInlineLevelTags].includes(Tag);
71
+ const htmlTag = isCustomTag ? `${BB_CODE_HTML_TAG_PREFIX}${Tag}` : Tag;
72
+ const openingHtmlTag = `<${htmlTag}${Object.entries(parameters).length > 0 ? ' ' : ''}${Object.entries(parameters).map(_ref => {
73
+ let [key, value] = _ref;
74
+ return `${key}="${value}"`;
75
+ }).join(' ')}>`;
76
+ const closingHtmlTag = `</${htmlTag}>`;
77
+ const element = Tag === 'img' ? openingHtmlTag : openingHtmlTag + parsedContent + closingHtmlTag;
78
+ html = `${html.slice(0, indexOfFullMatch)}${element}${htmlAfterTag}`;
84
79
 
85
- // Continues parsing behind the parsed bb-code.
86
- parseBehindIndex = indexOfFullMatch + openingTag.length + parsedContent.length + closingTag.length;
80
+ // Continues parsing behind the parsed bb-code.
81
+ parseBehindIndex = indexOfFullMatch + element.length;
82
+ }
87
83
  }
88
84
  return html;
89
85
  };
86
+ export const escapeBBCodeSquareBrackets = text => text.replaceAll('[', '&zwj;[&zwj;').replaceAll(']', '&zwj;]&zwj;');
87
+ export const unescapeBBCodeSquareBrackets = text => text.replaceAll('&zwj;[&zwj;', '[').replaceAll('&zwj;]&zwj;', ']');
90
88
  //# sourceMappingURL=formatBBCode.js.map