feat(linkedin-studio): N3.5 — MR-F8 build-html-forsoning (blockquote+lenker+FIGUR->SVG port + paritetstest) [skip-docs]

Plugin eier hele render/ (KTG-go 16.07, eierskapsvalg a). Portet fra
maskinrommets tools/build-html.mjs (read-only): flerlinjers blockquote
(avsnitt i quote), [tekst](url)-lenker med http/https/mailto-whitelist,
FIGUR-markoer -> inline SVG med figcaption + fallback til blockquote.
CSS for de tre konstruktene. 7 nye paritetstester (repoets testtilfeller
kopiert + med-SVG-case); paritetsbevis: samme fixture gjennom begge
motorer = byte-identisk parser-HTML. Render-floor 53 -> 60.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: c61b308e-e4fa-4a49-9ff0-a3ce725cf703
This commit is contained in:
Kjell Tore Guttormsen 2026-07-17 03:22:20 +02:00
commit 81510297db
3 changed files with 145 additions and 7 deletions

View file

@ -1,7 +1,11 @@
import { describe, test } from 'node:test';
import assert from 'node:assert/strict';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { markdownToHtml, inline } from '../build-html.mjs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
describe('markdownToHtml — tables (beslutning H)', () => {
test('converts a pipe table to <table>/<tr>/<td>', () => {
const md = [
@ -63,3 +67,66 @@ describe('inline — backtick code span (beslutning H)', () => {
assert.match(inline('**fet** og *kursiv*'), /<em>kursiv<\/em>/);
});
});
// Paritetstilfeller portet fra maskinrommets tools/__tests__/build-html.test.mjs
// (N3.5/MR-F8): lenker, flerlinjers blockquote, FIGUR→SVG. Samme markdown skal
// gi samme parser-HTML i begge motorer.
describe('inline — lenker [tekst](url) (N3.5 MR-F8)', () => {
test('renders [tekst](url) as a link with target/rel', () => {
const out = inline('se [Reuters](https://www.reuters.com/x) for detaljer');
assert.match(out, /<a href="https:\/\/www\.reuters\.com\/x"[^>]*>Reuters<\/a>/);
assert.match(out, /target="_blank"/);
assert.match(out, /rel="noopener"/);
});
test('mailto is allowed', () => {
assert.match(inline('[skriv](mailto:x@y.no)'), /<a href="mailto:x@y\.no"/);
});
test('drops non-http(s)/mailto schemes — link text survives, href does not', () => {
const out = inline('[klikk](javascript:alert(1))');
assert.doesNotMatch(out, /<a /);
assert.match(out, /klikk/);
});
});
describe('markdownToHtml — flerlinjers blockquote (N3.5 MR-F8)', () => {
test('a blockquote keeps its paragraph breaks', () => {
const md = ['> Første avsnitt.', '>', '> Andre avsnitt.'].join('\n');
const html = markdownToHtml(md);
assert.match(html, /<blockquote>/);
// two separate <p> inside the quote — the old parser collapsed these into one
const paras = html.match(/<blockquote>(.*?)<\/blockquote>/s)[1].match(/<p>/g) || [];
assert.equal(paras.length, 2);
});
test('a single-paragraph blockquote still renders one <p>', () => {
const html = markdownToHtml('> Bare ett avsnitt her.');
const paras = html.match(/<blockquote>(.*?)<\/blockquote>/s)[1].match(/<p>/g) || [];
assert.equal(paras.length, 1);
});
});
describe('markdownToHtml — FIGUR→SVG (N3.5 MR-F8)', () => {
test('a FIGUR blockquote with no matching SVG falls back to a plain blockquote', () => {
const html = markdownToHtml('> **[FIGUR 9 — «finnes ikke»]**');
assert.match(html, /<blockquote>/);
assert.doesNotMatch(html, /<figure/);
});
test('a FIGUR blockquote with matching figurer/figN*.svg inlines the SVG as <figure>', () => {
const prev = process.cwd();
process.chdir(path.join(__dirname, 'fixtures', 'figur-serie'));
try {
const html = markdownToHtml('> **[FIGUR 1 — «Demo-figur»]**');
assert.match(html, /<figure class="fig">/);
assert.match(html, /<svg/);
assert.match(html, /<figcaption>Figur 1 — Demo-figur<\/figcaption>/);
// xml-deklarasjonen i SVG-fila skal strippes før inlining
assert.doesNotMatch(html, /<\?xml/);
assert.doesNotMatch(html, /<blockquote>/);
} finally {
process.chdir(prev);
}
});
});

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100" role="img" aria-label="Demo-figur for FIGUR-markørtesten">
<rect x="10" y="10" width="180" height="80" fill="none" stroke="#333" stroke-width="2"/>
<text x="100" y="55" text-anchor="middle" font-size="14">fixture</text>
</svg>

After

Width:  |  Height:  |  Size: 333 B