content: Markdown doc export w/ frontmatter (md-doc.sx) + 12 tests (481/481)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 48s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 48s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ if [ ! -x "$SX_SERVER" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
SUITES=(block doc render api meta page markdown text section stats table validate store snapshot crdt crdt-store sync md-import fed)
|
||||
SUITES=(block doc render api meta page markdown text section stats table validate store snapshot crdt crdt-store sync md-import md-doc fed)
|
||||
|
||||
OUT_JSON="lib/content/scoreboard.json"
|
||||
OUT_MD="lib/content/scoreboard.md"
|
||||
@@ -56,6 +56,7 @@ run_suite() {
|
||||
(load "lib/content/crdt-store.sx")
|
||||
(load "lib/content/sync.sx")
|
||||
(load "lib/content/md-import.sx")
|
||||
(load "lib/content/md-doc.sx")
|
||||
(load "lib/content/fed.sx")
|
||||
(epoch 2)
|
||||
(eval "(define content-test-pass 0)")
|
||||
|
||||
63
lib/content/md-doc.sx
Normal file
63
lib/content/md-doc.sx
Normal file
@@ -0,0 +1,63 @@
|
||||
;; content-on-sx — Markdown document export (frontmatter + body).
|
||||
;;
|
||||
;; content/markdown-doc emits a YAML-ish --- frontmatter block from the document
|
||||
;; metadata (title/slug/tags) followed by the Markdown body, completing the
|
||||
;; metadata round-trip with md/import (md/import ∘ content/markdown-doc keeps
|
||||
;; title/slug/tags). With no metadata it is just asMarkdown.
|
||||
;;
|
||||
;; Requires (loaded by harness): doc.sx, meta.sx (doc-title/slug/tags),
|
||||
;; markdown.sx (asMarkdown).
|
||||
|
||||
(define mdd-nl (str "\n"))
|
||||
|
||||
(define
|
||||
mdd-join
|
||||
(fn
|
||||
(sep parts)
|
||||
(cond
|
||||
((= (len parts) 0) "")
|
||||
((= (len parts) 1) (first parts))
|
||||
(else (str (first parts) sep (mdd-join sep (rest parts)))))))
|
||||
|
||||
(define
|
||||
content/-fm-parts
|
||||
(fn
|
||||
(doc)
|
||||
(append
|
||||
(append
|
||||
(if
|
||||
(= (doc-title doc) nil)
|
||||
(list)
|
||||
(list (str "title: " (doc-title doc))))
|
||||
(if
|
||||
(= (doc-slug doc) nil)
|
||||
(list)
|
||||
(list (str "slug: " (doc-slug doc)))))
|
||||
(let
|
||||
((tags (doc-tags doc)))
|
||||
(if
|
||||
(= (len tags) 0)
|
||||
(list)
|
||||
(list (str "tags: " (mdd-join ", " tags))))))))
|
||||
|
||||
(define
|
||||
content/-frontmatter
|
||||
(fn
|
||||
(doc)
|
||||
(let
|
||||
((parts (content/-fm-parts doc)))
|
||||
(if
|
||||
(= (len parts) 0)
|
||||
""
|
||||
(str "---" mdd-nl (mdd-join mdd-nl parts) mdd-nl "---")))))
|
||||
|
||||
(define
|
||||
content/markdown-doc
|
||||
(fn
|
||||
(doc)
|
||||
(let
|
||||
((fm (content/-frontmatter doc)))
|
||||
(if
|
||||
(= fm "")
|
||||
(asMarkdown doc)
|
||||
(str fm mdd-nl mdd-nl (asMarkdown doc))))))
|
||||
@@ -18,9 +18,10 @@
|
||||
"crdt-store": {"pass": 14, "fail": 0},
|
||||
"sync": {"pass": 14, "fail": 0},
|
||||
"md-import": {"pass": 38, "fail": 0},
|
||||
"md-doc": {"pass": 12, "fail": 0},
|
||||
"fed": {"pass": 20, "fail": 0}
|
||||
},
|
||||
"total_pass": 469,
|
||||
"total_pass": 481,
|
||||
"total_fail": 0,
|
||||
"total": 469
|
||||
"total": 481
|
||||
}
|
||||
|
||||
@@ -22,5 +22,6 @@ _Generated by `lib/content/conformance.sh`_
|
||||
| crdt-store | 14 | 0 | 14 |
|
||||
| sync | 14 | 0 | 14 |
|
||||
| md-import | 38 | 0 | 38 |
|
||||
| md-doc | 12 | 0 | 12 |
|
||||
| fed | 20 | 0 | 20 |
|
||||
| **Total** | **469** | **0** | **469** |
|
||||
| **Total** | **481** | **0** | **481** |
|
||||
|
||||
71
lib/content/tests/md-doc.sx
Normal file
71
lib/content/tests/md-doc.sx
Normal file
@@ -0,0 +1,71 @@
|
||||
;; Extension — Markdown document export (frontmatter + body), round-trips with
|
||||
;; md/import including metadata.
|
||||
|
||||
(st-bootstrap-classes!)
|
||||
(content/bootstrap!)
|
||||
(content-bootstrap-markdown!)
|
||||
(content-bootstrap-table!)
|
||||
|
||||
(define nl (str "\n"))
|
||||
|
||||
;; ── no metadata → plain markdown (no frontmatter) ──
|
||||
(define plain (doc-append (doc-empty "d") (mk-heading "h" 1 "Hi")))
|
||||
(content-test
|
||||
"no-meta == asMarkdown"
|
||||
(content/markdown-doc plain)
|
||||
(asMarkdown plain))
|
||||
(content-test "no-meta no frontmatter" (content/markdown-doc plain) "# Hi")
|
||||
|
||||
;; ── full metadata frontmatter ──
|
||||
(define
|
||||
d
|
||||
(doc-with-meta
|
||||
(doc-append (doc-empty "post") (mk-heading "h" 1 "Hi"))
|
||||
{:slug "my-post" :title "My Post" :tags (list "a" "b")}))
|
||||
(content-test
|
||||
"frontmatter export"
|
||||
(content/markdown-doc d)
|
||||
(str
|
||||
"---"
|
||||
nl
|
||||
"title: My Post"
|
||||
nl
|
||||
"slug: my-post"
|
||||
nl
|
||||
"tags: a, b"
|
||||
nl
|
||||
"---"
|
||||
nl
|
||||
nl
|
||||
"# Hi"))
|
||||
|
||||
;; ── title only ──
|
||||
(content-test
|
||||
"title-only frontmatter"
|
||||
(content/markdown-doc
|
||||
(doc-with-title (doc-append (doc-empty "p") (mk-text "x" "body")) "T"))
|
||||
(str "---" nl "title: T" nl "---" nl nl "body"))
|
||||
|
||||
;; ── round-trip: import . export keeps metadata + blocks ──
|
||||
(define rt (md/import (content/markdown-doc d) "post"))
|
||||
(content-test "round-trip title" (doc-title rt) "My Post")
|
||||
(content-test "round-trip slug" (doc-slug rt) "my-post")
|
||||
(content-test "round-trip tags" (doc-tags rt) (list "a" "b"))
|
||||
(content-test "round-trip body" (doc-types rt) (list "heading"))
|
||||
(content-test
|
||||
"round-trip body text"
|
||||
(str (blk-send (doc-find rt "b0") "text"))
|
||||
"Hi")
|
||||
|
||||
;; ── round-trip a richer doc ──
|
||||
(define
|
||||
d2
|
||||
(doc-with-meta
|
||||
(doc-append
|
||||
(doc-append (doc-empty "p") (mk-heading "h" 2 "Title"))
|
||||
(mk-text "p" "para text"))
|
||||
{:title "Big" :tags (list "x")}))
|
||||
(define rt2 (md/import (content/markdown-doc d2) "p"))
|
||||
(content-test "rt2 title" (doc-title rt2) "Big")
|
||||
(content-test "rt2 tags" (doc-tags rt2) (list "x"))
|
||||
(content-test "rt2 types" (doc-types rt2) (list "heading" "text"))
|
||||
@@ -19,7 +19,7 @@ injected adapter, not core.
|
||||
|
||||
## Status (rolling)
|
||||
|
||||
`bash lib/content/conformance.sh` → **469/469** (Phases 1–4 COMPLETE + 13 extensions: HTML/SX escaping, Markdown render + import incl. tables & frontmatter, CRDT replication, tree-aware validation, snapshot cache, doc metadata, plain-text render, nested block trees, doc stats, table block, HTML page wrapper)
|
||||
`bash lib/content/conformance.sh` → **481/481** (Phases 1–4 COMPLETE + extensions: HTML/SX escaping, Markdown render + import/export incl. tables & frontmatter (full round-trip), CRDT replication, tree-aware validation, snapshot cache, doc metadata, plain-text render, nested block trees, doc stats, table block, HTML page wrapper)
|
||||
|
||||
## Ground rules
|
||||
|
||||
@@ -82,6 +82,7 @@ lib/content/api.sx ── (content/edit) (content/render) (content/history) ─
|
||||
- [x] durable CRDT replication (`crdt-store.sx`: ops on persist, replay + converge)
|
||||
- [x] document validation (`validate.sx`: ids, per-type fields, duplicate ids; tree-aware — descends into sections, tree-wide dup ids, section field check)
|
||||
- [x] Markdown import adapter (`md-import.sx`: text → blocks, round-trips export; incl. pipe tables + frontmatter → metadata)
|
||||
- [x] Markdown doc export (`md-doc.sx`: content/markdown-doc, frontmatter from metadata, full round-trip)
|
||||
- [x] snapshot cache over replay (`snapshot.sx`: cache-not-primary, transparent)
|
||||
- [x] document metadata (`meta.sx`: title/slug/tags + Ghost title plumbing)
|
||||
- [x] plain-text render + excerpt (`text.sx`: asText, content/excerpt)
|
||||
@@ -92,6 +93,12 @@ lib/content/api.sx ── (content/edit) (content/render) (content/history) ─
|
||||
|
||||
## Progress log
|
||||
|
||||
- 2026-06-07 — Extension: Markdown document export (`md-doc.sx`).
|
||||
`content/markdown-doc` emits a `---` frontmatter block from metadata
|
||||
(title/slug/tags, only present fields) ahead of the Markdown body, or plain
|
||||
asMarkdown when there's no metadata. Completes the metadata round-trip:
|
||||
`md/import ∘ content/markdown-doc` preserves title/slug/tags + blocks. 12
|
||||
tests; suite 481/481.
|
||||
- 2026-06-07 — Extension: Markdown frontmatter. `md/import` parses a leading
|
||||
`---` / `key: value` / `---` block into document metadata (title, slug,
|
||||
comma-separated tags via `doc-with-meta`) before parsing the body; a `---`
|
||||
|
||||
Reference in New Issue
Block a user