diff options
| author | Jonas Smedegaard <dr@jones.dk> | 2025-03-16 19:28:29 +0100 |
|---|---|---|
| committer | Jonas Smedegaard <dr@jones.dk> | 2025-03-16 19:28:29 +0100 |
| commit | 0664e64525ebd2f8a78f9040f249eb69a9fb038c (patch) | |
| tree | 09780c75f974ea0003f3079c50e6f2e07ada812b | |
| parent | c8ef87f9c167e6eb83dee73a76d806e9b3c59f6b (diff) | |
add draft filter plugin
| -rw-r--r-- | _extensions/ruc-play/semantic-markdown/_extension.yaml | 6 | ||||
| -rw-r--r-- | _extensions/ruc-play/semantic-markdown/semantic-markdown.lua | 129 | ||||
| -rw-r--r-- | example/example.qmd | 20 |
3 files changed, 155 insertions, 0 deletions
diff --git a/_extensions/ruc-play/semantic-markdown/_extension.yaml b/_extensions/ruc-play/semantic-markdown/_extension.yaml new file mode 100644 index 0000000..76b9a7a --- /dev/null +++ b/_extensions/ruc-play/semantic-markdown/_extension.yaml @@ -0,0 +1,6 @@ +name: semantic-markdown +author: Jonas Smedegaard +version: 0.0.1 +contributes: + filters: + - semantic-markdown.lua diff --git a/_extensions/ruc-play/semantic-markdown/semantic-markdown.lua b/_extensions/ruc-play/semantic-markdown/semantic-markdown.lua new file mode 100644 index 0000000..f17f309 --- /dev/null +++ b/_extensions/ruc-play/semantic-markdown/semantic-markdown.lua @@ -0,0 +1,129 @@ +--- semantic-markdown - Pandoc plugin to process semantic hints +--- +--- SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk> +--- SPDX-License-Identifier: GPL-3.0-or-later +--- +--- simple example +--- +--- ``` +--- "A [map]{foaf:depiction} is not the territory" +--- | || | +--- | |brace_open brace_close +--- | bracket_close +--- bracket_open +--- +--- TODO: complex example with nesting and mixed-use enclosure +--- +--- ["[Ceci]{foaf:depiction} n'est pas une pipe"{lang=fr dc:Text} +--- | | || | +--- | | |brace_open brace_close +--- | | bracket_close +--- | bracket_open +--- ``` +--- +--- * v0.0.1 +--- * initial release +--- +--- @version 0.0.1 +--- @see <https://source.jones.dk/semantic-markdown/about/> +--- @see <https://moodle.ruc.dk/course/view.php?id=23505> + +-- TODO: maybe use topdown traversal +-- * order of declaring annotations might matter (but should not) +-- * might enable simpler functions and/or faster processing +-- @see <https://pandoc.org/lua-filters.html#topdown-traversal> + +-- ensure stable character classes independent of system locale +-- @see <https://pandoc.org/lua-filters.html#common-pitfalls> +os.setlocale 'C' + +-- TODO: support Unicode +-- @see <https://www.lua.org/manual/5.4/manual.html#6.5> +--- qnameLong - RDF/turtle QName with prefix and name as set of chars +--- @see <https://www.w3.org/TeamSubmission/turtle/#name> +local _nameStartChar = "A-Z_a-z" +local _nameChar = _nameStartChar.."-0-9" +local _name = "[".._nameStartChar.."][".._nameChar.."]*" +local _prefixName = "[".._nameStartChar.."_-][".._nameChar.."]*" +local qnameLong = _prefixName..":".._name + +--- qnamePrefixed - RDF/turtle QName with only prefix as set of chars +local qnamePrefixed = _prefixName..":" + +--- qnameLocal - RDF/turtle QName with only name as set of chars +local qnameLocal = ":".._name + +--- qnameDefault - RDF/turtle QName without prefix or name as char +local qnameDefault = ":" + +-- TODO: qname - RDF/turtle QName as `LPeg.re` regex object +-- TODO: test and replace above qname* patterns +-- @see <https://pandoc.org/lua-filters.html#global-variables> +--local qname_re = re.compile("(".._prefixName..")?:(".._name..")?") + +-- TODO: process Blocks (vocabulary blocks first) + +--- Extract and strip semantic annotations from inlines +--- +--- This function is a Pandoc hook executed for each Inlines object +--- when iterating through its Abstract Syntax Tree (AST) of a document. +--- +--- @param inlines Markdown with semantic annotations as Inlines +--- @returns Markdown stripped of semantic annotations as Inlines +--- @see <https://pandoc.org/lua-filters.html#type-inline> +function Inlines (inlines) + + -- positions of enclosure markers + local bracket_open, bracket_close, brace_open, brace_close + + -- maintain states across inlines + local bracketed, braced, has_hints + + local new_inlines = {} + + for i, el in ipairs(inlines) do + + -- only string inlines can alter state + if el.t ~= 'Str' then + table.insert(new_inlines, el) + goto continue + end + + -- unenclosed + if not (bracketed or braced) then + _, bracket_open = string.find(el.text, "%[") + if bracket_open then + bracketed = true + end + end + + -- enters a bracket enclosure + -- TODO: maybe support nested bracket enclosure + if bracketed and not braced then + _, bracket_close, s = string.find(el.text, "^([^%[%]}]*)%]{", + bracket_open) + if bracket_close then + braced = true + table.insert(new_inlines, pandoc.Str(s)) + end + end + + -- (ignore space-delimited enclosures: not in spec for inlines) + + -- completes a brace enclosure + -- TODO: support mixed-use enclosure (non-qname enclosure content) + -- TODO: cover qnamePrefix and qnameLocal and qnameDefault + if braced then + _, brace_close = string.find(el.text, "^"..qnameLong.."}", + bracket_close) + if brace_close then + has_hints = true + -- TODO: call same function with remains of Str + end + end + ::continue:: + end + if has_hints then + return pandoc.Inlines {new_inlines} + end +end diff --git a/example/example.qmd b/example/example.qmd new file mode 100644 index 0000000..57e03b5 --- /dev/null +++ b/example/example.qmd @@ -0,0 +1,20 @@ +--- +title: "Test Document" +format: + html: + minimal: true +filters: + - semantic-markdown +--- + +My name is +[Manu Sporny]{:name} +and you can give me a ring via +[1-800-555-0199]{:telephone}. +{:image} +My favorite animal is the [Liger]{ov:preferredAnimal}. +{=<#manu> .:Person} + +{schema}: @default + +{ov}: http://open.vocab.org/terms/ |
