import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; globalThis.location = {origin:'https://example.org'}; let source = readFileSync('static/js/markdown.js','utf8') .replace(/^import .*;$/gm, ''); source = `const EMOJI_SHORTCODES = {}; const t = (key,vars,alternative) => alternative; const parseImageAlias = () => null;\n` + source; const {renderMarkdown, setMarkdownMentions} = await import('data:text/javascript;base64,'+Buffer.from(source).toString('base64')); function has(re, text, message) { assert.match(text,re,message); } let html = renderMarkdown('# Instrukcja testowa\n[Przejdź](#instrukcja-testowa)\n# Instrukcja testowa\n[TOC]\n## Etap drugi'); has(/

]*style="margin-left:2ch"[^>]*>const value = 1;\n console\.log\(value\);<\/code><\/pre>/,html,'code container indentation + dedent'); has(/]*>after<\/p>/,html,'code closed'); html = renderMarkdown(' ```python=42\n print(42)\n ```'); has(/class="code-with-lines[^>]*style="margin-left:4ch"/,html,'numbered fenced code whole block shifted'); has(/data-line="42">print\(42\)/,html,'numbered content dedented'); html = renderMarkdown(' ```\n ~~~\n ```'); has(/~~~<\/code>/,html,'other marker must remain inside code'); html = renderMarkdown('```\n## hidden in code\n```\n## Visible'); assert.doesNotMatch(html, /id="hidden-in-code"/); has(/id="visible"/,html,'headings outside code'); setMarkdownMentions([{nickname:'Ala',color:'#aabbcc'},{nickname:'John+Dev',color:'red'}]); html = renderMarkdown('Cześć @Ala i @John+Dev! @Other @Alana a@Ala `@Ala` [@Ala](https://site.test)'); assert.equal((html.match(/class="markdown-mention"/g)||[]).length,2,'valid mentions only'); has(/style="--owner:#aabbcc"/,html,'real author color'); has(/@Other @Alana a@Ala/,html,'nonmembers and suffixes not chips'); has(/@Ala<\/code>/,html,'inline code excluded'); has(/]*>@Ala<\/a>/,html,'links excluded'); assert.doesNotMatch(renderMarkdown('```\n@Ala\n```'), /markdown-mention/); html = renderMarkdown('Sentence @Ala. Domain @Ala.example'); assert.equal((html.match(/class="markdown-mention"/g) || []).length, 1, 'punctuation after a mention is allowed, domains are not'); setMarkdownMentions([]); assert.doesNotMatch(renderMarkdown('@Ala'), /markdown-mention/); console.log('PASS: anchors, TOC, duplicate headings, indented fences, numbered blocks, mentions, exclusions'); html = renderMarkdown('[TOC]\n# Procedura\n
\nSzczegóły\n## Procedura\n
'); has(/id="procedura"/,html); has(/id="procedura-2"/,html,'nested heading anchor unique'); has(/href="#procedura-2"/,html,'TOC link for heading inside details'); console.log('PASS: anchors in nested details match TOC'); setMarkdownMentions([{nickname: 'a[1]\\x', color: '#123456'}, {nickname: '&"', color: '#112233'}]); html = renderMarkdown('Hello @a[1]\\x and @&" but not @a[1]\\xy'); assert.equal((html.match(/class="markdown-mention"/g)||[]).length, 2, 'escaped nicknames'); assert.doesNotMatch(html, //, 'no raw HTML from nickname'); console.log('PASS: special-character nicknames remain escaped');