spb/tendril Public
Tendril — web ingestion platform (scrape/crawl/map/search) on macOS Apple Silicon: WebKit fidelity, authenticated pages, deterministic testable extraction. A self-hosted Firecrawl alternative.
JavaScript 82.6%
TypeScript 11.8%
HTML 5.3%
1// author: simon-pierre boucher <contact@spboucher.ai>2import { describe, expect, it } from "vitest";3import { htmlToMarkdown } from "./markdown.js";45describe("htmlToMarkdown", () => {6 it("uses ATX headings and dash bullets", () => {7 const md = htmlToMarkdown("<h1>Title</h1><ul><li>a</li><li>b</li></ul>");8 expect(md).toContain("# Title");9 expect(md).toContain("- a");10 expect(md).toContain("- b");11 });1213 it("emits fenced code blocks with a language tag", () => {14 const md = htmlToMarkdown('<pre><code class="language-ts">const x = 1;</code></pre>');15 expect(md).toContain("```ts");16 expect(md).toContain("const x = 1;");17 });1819 it("converts tables to GFM with a header separator", () => {20 const md = htmlToMarkdown(21 "<table><thead><tr><th>Name</th><th>Age</th></tr></thead><tbody><tr><td>Ada</td><td>36</td></tr></tbody></table>",22 );23 expect(md).toContain("| Name | Age |");24 expect(md).toContain("| --- | --- |");25 expect(md).toContain("| Ada | 36 |");26 });2728 it("escapes pipes inside table cells", () => {29 const md = htmlToMarkdown("<table><tr><th>a|b</th></tr><tr><td>c|d</td></tr></table>");30 expect(md).toContain("a\\|b");31 expect(md).toContain("c\\|d");32 });3334 it("renders figure + figcaption as image plus italic caption", () => {35 const md = htmlToMarkdown('<figure><img src="https://x/y.png" alt="chart"><figcaption>Fig 1</figcaption></figure>');36 expect(md).toContain("");37 expect(md).toContain("_Fig 1_");38 });3940 it("removes heading anchor links", () => {41 const md = htmlToMarkdown('<h2>Sec <a class="headerlink" href="#sec">¶</a></h2>');42 expect(md).toContain("## Sec");43 expect(md).not.toContain("¶");44 expect(md).not.toContain("#sec");45 });4647 it("renders definition lists", () => {48 const md = htmlToMarkdown("<dl><dt>Term</dt><dd>Meaning</dd></dl>");49 expect(md).toContain("**Term**");50 expect(md).toContain(": Meaning");51 });5253 it("collapses 3+ blank lines to 2", () => {54 const md = htmlToMarkdown("<p>a</p><br><br><br><p>b</p>");55 expect(md).not.toMatch(/\n{3,}/);56 });57});58