const { JSDOM } = require('jsdom'); const fs = require('fs'); const path = require('path'); // Set up a DOM environment and load the bundle const dom = new JSDOM('
', { url: 'http://localhost', pretendToBeVisual: true, }); global.window = dom.window; global.document = dom.window.document; global.HTMLElement = dom.window.HTMLElement; global.Node = dom.window.Node; // Load the compiled bundle (attaches globals to window) const bundle = fs.readFileSync(path.join(__dirname, '..', 'dist', 'ribbit', 'ribbit.js'), 'utf8'); dom.window.eval(bundle); const hopdown = new dom.window.HopDown(); const H = hopdown.toHTML.bind(hopdown); const M = hopdown.toMarkdown.bind(hopdown); function rt(md) { return M(H(md)); } // Test harness let passed = 0, failed = 0, errors = []; function norm(s) { return (s || '').replace(/\r\n/g, '\n').trim(); } function eq(name, actual, expected) { const a = norm(actual), e = norm(expected); if (a === e) { passed++; } else { failed++; errors.push(name); console.log(` ✗ ${name}`); console.log(` expected: ${e}`); console.log(` actual: ${a}`); } } function has(name, actual, sub) { if (norm(actual).indexOf(norm(sub)) !== -1) { passed++; } else { failed++; errors.push(name); console.log(` ✗ ${name}`); console.log(` expected to contain: ${sub}`); console.log(` actual: ${actual}`); } } function not(name, actual, sub) { if (norm(actual).indexOf(norm(sub)) === -1) { passed++; } else { failed++; errors.push(name); console.log(` ✗ ${name}`); console.log(` should NOT contain: ${sub}`); console.log(` actual: ${actual}`); } } function section(n) { /* silent */ } // ── 1. Inline formatting ──────────────────────────────── section('1. Inline Formatting → HTML'); eq('bold', H('**bold**'), 'bold
'); eq('italic', H('*italic*'), 'italic
'); eq('inline code', H('`code`'), 'code
bi
'); eq('mixed inline', H('a **b** *c* `d`'), 'a b c d
a b
'); has('bq content', H('> hello'), 'hello'); has('multi-line bq', H('> a\n> b'), 'a'); // ── 6. Fenced code blocks ─────────────────────────────── has('code block', H('```\nx = 1\n```'), ''); has('code content', H('```\nx = 1\n```'), 'x = 1'); has('lang class', H('```js\nvar x;\n```'), 'language-js'); has('html escaped', H('```\n\n```'), '<div>'); not('no lang attr when none', H('```\nplain\n```'), 'language-'); // ── 7. Tables ─────────────────────────────────────────── var tbl = '| a | b |\n|---|---|\n| 1 | 2 |'; has('table tag', H(tbl), '