;; Extension — Markdown import adapter (markdown text -> blocks), inverse of ;; asMarkdown. Round-trips canonical Markdown; parses frontmatter + tables. (st-bootstrap-classes!) (content/bootstrap!) (content-bootstrap-markdown!) (content-bootstrap-table!) (define nl (str "\n")) ;; ── headings ── (define dh (md/import "# Title" "d")) (content-test "heading import type" (doc-types dh) (list "heading")) (content-test "heading level" (blk-send (doc-find dh "b0") "level") 1) (content-test "heading text" (str (blk-send (doc-find dh "b0") "text")) "Title") (content-test "h3 import" (blk-send (doc-find (md/import "### Deep" "d") "b0") "level") 3) ;; ── paragraph (consecutive lines join with space) ── (content-test "paragraph join" (str (blk-send (doc-find (md/import (str "hello" nl "world") "d") "b0") "text")) "hello world") ;; ── blockquote, divider ── (content-test "blockquote" (str (blk-send (doc-find (md/import "> quoted" "d") "b0") "text")) "quoted") (content-test "divider" (doc-types (md/import "---" "d")) (list "divider")) ;; ── unordered + ordered lists ── (define dul (md/import (str "- a" nl "- b" nl "- c") "d")) (content-test "ul type" (doc-types dul) (list "list")) (content-test "ul not ordered" (blk-send (doc-find dul "b0") "ordered") false) (content-test "ul items" (blk-send (doc-find dul "b0") "items") (list "a" "b" "c")) (define dol (md/import (str "1. x" nl "2. y") "d")) (content-test "ol ordered" (blk-send (doc-find dol "b0") "ordered") true) (content-test "ol items" (blk-send (doc-find dol "b0") "items") (list "x" "y")) ;; ── fenced code ── (define dc (md/import (str "```sx" nl "(+ 1 2)" nl "(* 3 4)" nl "```") "d")) (content-test "code type" (doc-types dc) (list "code")) (content-test "code language" (str (blk-send (doc-find dc "b0") "language")) "sx") (content-test "code body" (str (blk-send (doc-find dc "b0") "text")) (str "(+ 1 2)" nl "(* 3 4)")) ;; ── multiple blocks separated by blank lines ── (define dm (md/import (str "# H" nl nl "para" nl nl "- a" nl "- b") "d")) (content-test "multi types" (doc-types dm) (list "heading" "text" "list")) (content-test "multi ids" (doc-ids dm) (list "b0" "b1" "b2")) ;; ── empty / blank input ── (content-test "empty input" (doc-ids (md/import "" "d")) (list)) (content-test "blank lines only" (doc-ids (md/import (str nl nl) "d")) (list)) ;; ── pipe tables ── (define dt (md/import (str "| Name | Age |" nl "| --- | --- |" nl "| Ada | 36 |" nl "| Al | 40 |") "d")) (content-test "table import type" (doc-types dt) (list "table")) (content-test "table headers" (table-headers (doc-find dt "b0")) (list "Name" "Age")) (content-test "table rows" (table-rows (doc-find dt "b0")) (list (list "Ada" "36") (list "Al" "40"))) (content-test "table round-trip" (asMarkdown (md/import (str "| A | B |" nl "| --- | --- |" nl "| 1 | 2 |") "d")) (str "| A | B |" nl "| --- | --- |" nl "| 1 | 2 |")) (define dmix (md/import (str "# Title" nl nl "| H1 | H2 |" nl "| --- | --- |" nl "| a | b |" nl nl "para") "d")) (content-test "table mixed types" (doc-types dmix) (list "heading" "table" "text")) ;; ── frontmatter ── (define dfm (md/import (str "---" nl "title: My Post" nl "slug: my-post" nl "tags: a, b, c" nl "---" nl "# Hi" nl nl "body") "d")) (content-test "fm title" (doc-title dfm) "My Post") (content-test "fm slug" (doc-slug dfm) "my-post") (content-test "fm tags" (doc-tags dfm) (list "a" "b" "c")) (content-test "fm body types" (doc-types dfm) (list "heading" "text")) (content-test "fm body content" (str (blk-send (doc-find dfm "b0") "text")) "Hi") (content-test "no fm title nil" (doc-title (md/import "# Hi" "d")) nil) (content-test "hr not frontmatter" (doc-types (md/import (str "text" nl nl "---") "d")) (list "text" "divider")) (define dfmo (md/import (str "---" nl "title: T" nl "---") "d")) (content-test "fm only title" (doc-title dfmo) "T") (content-test "fm only empty body" (doc-ids dfmo) (list)) ;; ── round-trip: import . export == identity (canonical markdown) ── (define src (str "# Title" nl nl "hello world" nl nl "> quoted" nl nl "- a" nl "- b" nl nl "---")) (content-test "round-trip markdown" (asMarkdown (md/import src "d")) src) (content-test "round-trip code" (asMarkdown (md/import (str "```js" nl "x = 1" nl "```") "d")) (str "```js" nl "x = 1" nl "```")) ;; ── adapter form ── (content-test "adapter import" (doc-types (content/import markdown-adapter "# Hi" "d")) (list "heading")) (content-test "adapter export round-trip" (content/export markdown-adapter (content/import markdown-adapter src "d")) src) ;; ── imported doc validates ── (content-test "imported doc valid" (content/valid? (md/import src "d")) true)