diff --git a/lib/content/conformance.sh b/lib/content/conformance.sh index 482edf4d..01ad9ba1 100755 --- a/lib/content/conformance.sh +++ b/lib/content/conformance.sh @@ -15,7 +15,7 @@ if [ ! -x "$SX_SERVER" ]; then fi fi -SUITES=(block doc render api meta page page-full markdown text section compose tree-edit move clone query toc anchor outline flatten transform normalize find-replace stats table callout data wire validate store snapshot crdt crdt-store sync md-import md-doc fed) +SUITES=(block doc render api meta page page-full markdown text section compose tree-edit move clone query toc anchor outline flatten transform normalize find-replace stats table callout media data wire validate store snapshot crdt crdt-store sync md-import md-doc fed) OUT_JSON="lib/content/scoreboard.json" OUT_MD="lib/content/scoreboard.md" @@ -60,6 +60,7 @@ run_suite() { (load "lib/content/stats.sx") (load "lib/content/table.sx") (load "lib/content/callout.sx") +(load "lib/content/media.sx") (load "lib/content/data.sx") (load "lib/content/wire.sx") (load "lib/content/page.sx") diff --git a/lib/content/media.sx b/lib/content/media.sx new file mode 100644 index 00000000..76e07979 --- /dev/null +++ b/lib/content/media.sx @@ -0,0 +1,52 @@ +;; content-on-sx — video/audio media block. +;; +;; CtMedia holds a `kind` (video/audio) and `src`. Self-contained: answers +;; asHTML/asSx/asText/asMarkdown: so it composes with the render boundary with no +;; changes elsewhere. HTML src is htmlEscaped, SX src sxEscaped. +;; +;; Requires (loaded by harness): block.sx, doc.sx, render.sx (escapers); +;; markdown.sx / text.sx for those formats. + +(define + content-bootstrap-media! + (fn + () + (begin + (st-class-define! "CtMedia" "CtBlock" (list "kind" "src")) + (ct-def-method! "CtMedia" "kind" "kind ^ kind") + (ct-def-method! "CtMedia" "src" "src ^ src") + (ct-def-method! "CtMedia" "type" "type ^ #media") + (ct-def-method! + "CtMedia" + "asHTML" + "asHTML ^ '<' , kind , ' src=\"' , src htmlEscaped , '\" controls>' , kind , '>'") + (ct-def-method! + "CtMedia" + "asSx" + "asSx ^ '(' , kind , ' :src \"' , src sxEscaped , '\")'") + (ct-def-method! "CtMedia" "asText" "asText ^ ''") + (ct-def-method! + "CtMedia" + "asMarkdown:" + "asMarkdown: nl ^ '[' , kind , '](' , src , ')'") + true))) + +(define + mk-media + (fn + (id kind src) + (st-iv-set! + (st-iv-set! + (st-iv-set! (st-make-instance "CtMedia") "id" id) + "kind" + kind) + "src" + src))) + +(define + media? + (fn (b) (and (st-instance? b) (= (get b :class) "CtMedia")))) +(define media-kind (fn (b) (st-send b "kind" (list)))) + +(define mk-video (fn (id src) (mk-media id "video" src))) +(define mk-audio (fn (id src) (mk-media id "audio" src))) diff --git a/lib/content/scoreboard.json b/lib/content/scoreboard.json index b0fd1304..8b6a7f87 100644 --- a/lib/content/scoreboard.json +++ b/lib/content/scoreboard.json @@ -25,6 +25,7 @@ "stats": {"pass": 17, "fail": 0}, "table": {"pass": 15, "fail": 0}, "callout": {"pass": 12, "fail": 0}, + "media": {"pass": 15, "fail": 0}, "data": {"pass": 21, "fail": 0}, "wire": {"pass": 11, "fail": 0}, "validate": {"pass": 23, "fail": 0}, @@ -37,7 +38,7 @@ "md-doc": {"pass": 12, "fail": 0}, "fed": {"pass": 20, "fail": 0} }, - "total_pass": 668, + "total_pass": 683, "total_fail": 0, - "total": 668 + "total": 683 } diff --git a/lib/content/scoreboard.md b/lib/content/scoreboard.md index d70fa4c2..3708c988 100644 --- a/lib/content/scoreboard.md +++ b/lib/content/scoreboard.md @@ -29,6 +29,7 @@ _Generated by `lib/content/conformance.sh`_ | stats | 17 | 0 | 17 | | table | 15 | 0 | 15 | | callout | 12 | 0 | 12 | +| media | 15 | 0 | 15 | | data | 21 | 0 | 21 | | wire | 11 | 0 | 11 | | validate | 23 | 0 | 23 | @@ -40,4 +41,4 @@ _Generated by `lib/content/conformance.sh`_ | md-import | 38 | 0 | 38 | | md-doc | 12 | 0 | 12 | | fed | 20 | 0 | 20 | -| **Total** | **668** | **0** | **668** | +| **Total** | **683** | **0** | **683** | diff --git a/lib/content/tests/media.sx b/lib/content/tests/media.sx new file mode 100644 index 00000000..1c2b4384 --- /dev/null +++ b/lib/content/tests/media.sx @@ -0,0 +1,59 @@ +;; Extension — video/audio media block. + +(st-bootstrap-classes!) +(content/bootstrap!) +(content-bootstrap-markdown!) +(content-bootstrap-text!) +(content-bootstrap-media!) + +(define v (mk-video "v" "/clip.mp4")) +(define a (mk-audio "a" "/song.mp3")) + +;; ── identity ── +(content-test "media is block" (block? v) true) +(content-test "media? yes" (media? v) true) +(content-test "video type" (blk-type v) "media") +(content-test "video kind" (media-kind v) "video") +(content-test "audio kind" (media-kind a) "audio") + +;; ── render ── +(content-test + "video html" + (asHTML v) + "") +(content-test + "audio html" + (asHTML a) + "") +(content-test "video sx" (asSx v) "(video :src \"/clip.mp4\")") +(content-test "video text" (asText v) "") +(content-test "video markdown" (asMarkdown v) "[video](/clip.mp4)") +(content-test "audio markdown" (asMarkdown a) "[audio](/song.mp3)") + +;; ── html escapes src ── +(content-test + "media html escapes" + (asHTML (mk-video "v" "/a.mp4?x=1&y=2")) + "") + +;; ── in a document ── +(define + d + (doc-append + (doc-append (doc-empty "d") (mk-heading "h" 1 "Watch")) + v)) +(content-test + "doc with media html" + (asHTML d) + "