Overview
Comment: | macro & doc improvements |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
52f88f818db58c95f4196293a2681596 |
User & Date: | lexi on 2022-09-09 21:08:16 |
Other Links: | manifest | tags |
Context
2022-09-09
| ||
21:20 | fix stupid table bug check-in: e8ab2a68d8 user: lexi tags: trunk | |
21:08 | macro & doc improvements check-in: 52f88f818d user: lexi tags: trunk | |
19:04 | enable basic ID interpolation check-in: 8b33bc074d user: lexi tags: trunk | |
Changes
Modified cortav.ct from [1a665df7bf] to [af24dd1316].
97 97 ** [`~~~ language] (markdown-style shorthand syntax) 98 98 ** [`~~~ \[language\] ~~~] (cortav syntax) 99 99 ** [`~~~ \[language\] #id ~~~] 100 100 ** [`~~~ title ~~~] 101 101 ** [`~~~ title \[language\] ~~~] 102 102 ** [`~~~ \[language\] title ~~~] 103 103 ** [`~~~ title \[language\] #id ~~~] 104 -*[*definition] ([^def-ex tab]): a line [^def-tab-enc beginning with a tab] is a multipurpose metadata syntax. the tab may be followed by an identifier, a colon, and a value string, in which case it opens a new definition; alternatively, a second tab character turns the line into a [*definition continuation], adding the remaining characters as a new line to the definition value on the previous line. when a new definition is opened on a line immediately following certain kinds of objects, such as resource, it attaches key-value metadata to that object. when a definition is not preceded by such an object, an independent [*reference] is created instad. 105 -** a [*reference] is a general mechanism for out-of-line metadata, and references are used in many different ways -- e.g. to specify link destinations, footnote contents, abbreviations, or macros. to ensure that a definition is interpreted as a reference, rather than as metadata for an object, precede it with a blank line. 104 +*[*definition] ([^def-ex tab]): a line [^def-tab-enc beginning with a tab] is a multipurpose metadata syntax. the tab may be followed by an identifier, a colon, and a value string, in which case it opens a new definition; alternatively, a second tab character turns the line into a [*definition continuation], adding the remaining characters as a new line to the definition value on the previous line. when a new definition is opened on a line immediately following certain kinds of objects, such as resources, embeds, or multiline macro expansions, it attaches key-value metadata to that object. when a definition is not preceded by such an object, an independent [*reference] is created instad. 105 +** a [*reference] is a general mechanism for out-of-line metadata, and references are used in many different ways -- e.g. to specify link destinations, footnote contents, abbreviations, or macro bodies. to ensure that a definition is interpreted as a reference, rather than as metadata for an object, precede it with a blank line. 106 106 def-tab-enc: in encodings without tab characters, a definition is opened by a line beginning with two blanks, and continued by a line beginning with four blanks. 107 107 def-ex: [*open a new reference]: [`[!\\t][$key]: [$value]] 108 108 [*continue a reference]: [`[!\\t\\t][$value]] 109 109 * [*quotation] ([`<]): a line of the form [`<[$name]> [$quote]] denotes an utterance by [$name]. 110 110 * [*blockquote] ([`>]): alternate blockquote syntax. can be nested by repeating the [`>] character. 111 111 * [*subtitle/caption] ([`\--]): attaches a subtitle to the previous header, or caption to the previous object 112 -* [*embed] ([`&]): embeds a referenced object. can be used to show images or repeat previously defined objects like lists or tables, optionally with a caption. 113 -** [`$[$macro] [$arg1]|[$arg2]|[$argn]…] invokes a block-level macro with the supplied arguments 114 -*** [`$mymacro arg 1|arg 2|arg 3] 112 +* [*embed] ([`&]): embeds a referenced object. can be used to show images or repeat previously defined objects like lists or tables, optionally with a caption. an embed line can be followed immediately by a sequence of [*definitions] in the same way that resource definitions can, to override resource properties on a per-instance basis. note that only presentation-related properties like [$desc] can be meaningful overridden, as embed does not trigger a re-render of the parse tree; if you want to override e.g. context variables, use a multiline macro invocation instead. 115 113 ** [`&[$image]] embeds an image or other block-level object. [!image] can be a reference with a url or file path, or it can be an embed section (e.g. for SVG files) 116 114 ***[`&myimg All that remained of the unfortunate blood magic pageant contestants and audience (police photo)] 117 115 ** [`&-[$ident] [$styled-text]] embeds a closed disclosure element containing the text of the named object (a nonprinting section or cortav resource should usually be used to store the content; it can also name an image or video, of course). in interactive outputs, this will display as a block which can be clicked on to view the full contents of the referenced object [$ident]; if [$styled-text] is present, it overrides the title of the section you are embedding (if any). in static outputs, the disclosure object will display as an enclosed box with [$styled-text] as the title text 118 116 *** [`&-ex-a Prosecution Exhibit A (GRAPHIC CONTENT)] 119 117 ** [`&+[$section] [$styled-text]] is like the above, but the disclosure element is open by default 118 +* [`$[$macro] [$arg1]|[$arg2]|[$argn]…] invokes a block-level macro with the supplied arguments, and can be followed by a property override definition list the same way embed and resource lines can. note that while both [`$[$id]] and [`&[$id]] can be used to instantiate resources of type [`text/x.cortav], there is a critical difference: [`$[$id]] renders out the sub-document separately each time it is named, allowing for parameter expansion and for context variables to be overridden for each invocation. by contrast, [`&[$id]] can only insert copies of the same render; no parameters can be passed and context variables will be expanded to their value at the time the resource was defined. 119 +** [`$mymacro arg 1|arg 2|arg 3] 120 120 * [*horizontal rule] ([`\---]): inserts a horizontal rule or other context break; does not end the section. must be followed by newline. underlines can also be used in place of dashes ([`___], [`-_-], [`__-__-__] etc), as can horizontal unicode box drawing characters ([`─ ━ ┈] etc). 121 121 * [*page break] ([`\^^]): for formats that support pagination, like EPUB or HTML (when printed), indicates that the rest of the current page should be blank. for formats that do not, extra margins will be inserted. does not create a new section 122 122 * [*page rule] ([`\^-^]): inserts a page break for formats that support them, and a horizontal rule for formats that do not. does not create a new section. comprised of any number of horizontal rule characters surrounded by a pair of carets (e.g. [`^-^] [`^_^] [`^----^] [`^__--^] [`^┈┈┈┈┈^]) 123 123 * [*table cells] ([`+ |]): see [>ex.tab table examples]. 124 124 * [*equations] ([`=]): block-level equations can be inserted with the [`=] sequence 125 125 * [*cross-references] ([`=>] [`⇒]): inserts a block-level link. uses the same syntax as span links ([`⇒[$ident] [$styled-text]]). can be followed by a caption to add a longer descriptive text. especially useful for gemtext output. ident can be omitted to cross-reference, for example, a physical book. 126 126 * [*empty lines] (that is, lines consisting of nothing but whitespace) constitute a [!break], which terminates multiline objects that do not have a dedicated termination sequence, for example lists and asides. ................................................................................ 368 368 *** [`image/*] (graphical outputs only) 369 369 *** [`video/*] (interactive outputs only) 370 370 *** [`image/svg+xml] is handled specially for HTML files, and may or may not be compatible with other renderer backends. 371 371 *** [`font/*] can be used with the HTML backend to reference a web font 372 372 *** [`font/woff2] can be used with the HTML backend to reference a web font 373 373 *** [`text/plain] (will be inserted as a preformatted text block) 374 374 *** [`text/css] (can be used when producing HTML files to link in an extra stylesheet, either by embedding it or referencing it from the header) 375 -*** [`text/x.cortav] (will be parsed and inserted as a formatted text block; context variables can be passed to the file by setting [`ctx.[$var]] parameters on the resource, e.g. [`ctx.recipient-name: Mr. Winthrop]) 375 +*** [`text/x.cortav] (will be parsed and inserted as a formatted text block; context variables can be passed to the file by setting [`.[$var]] properties on the resource, e.g. [`.recipient-name: Mr. Winthrop]) 376 376 *** [`application/x-troff] can be used to supply sections of text written in raw [`groff] syntax. these are ignored by other renderers. 377 377 *** [`text/html] can be used to supply sections of text written in raw HTML. these are ignored by non-HTML outputs. 378 378 *** any MIME-type that matches the type of file being generated by the renderer can be used to include a block of data that will be passed directly to the renderer. 379 379 ** URI types: additional URI types can be added by extensions or different implementations, but every compliant implementation must support these URIs. 380 380 *** [`http], [`https]/[`http+tls]: accesses resources over HTTP. add a [`file] fallback if possible for the benefit of renderers/viewers that do not have internet access abilities. 381 381 *** [`file]: references local files. (the meaning of "local" varies depending on the translation format.) absolute paths should begin [`file:/]; the slash should be omitted for relative paths. note that this doesn't have quite the same meaning as in HTML -- [`file] can (and usually should be) used with HTML outputs to refer to resources that reside on the same server. a cortav URI of [`file:/etc/passwd] will actually result in the link [`/etc/passwd], not [`file:///etc/passwd] when converted to HTML. generally, you only should use [`http] when you're referring to a resource that exists on a different domain. on systems where text and binary files are handled differently, the URIs [`file+txt:] and [`file+bin:] can be used to specify an opening mode. 382 382 *** [`asset]: identical to file [`file], except that paths are interpreted relative to the asset base (the parent directory of the source file if not otherwise defined), rather than the current working directory of the [`cortav] translator process. ................................................................................ 607 607 zombo: https://zombo.com 608 608 any: anything you want 609 609 ~~~ 610 610 611 611 ~~~ macros #mac [cortav] ~~~ 612 612 the ranuir word {gloss cor|writing}… 613 613 gloss: [*[#1]] “[#2]” 614 + 615 +$def sur|n|socialism 616 +$def par|n|speech 617 + def: * [*[#1]] [!([#2])] 618 + ** [#3] 619 + 620 +%% equivalent to 621 + 622 +@def { 623 + * [*[#1]] [!([#2])] 624 + ** [#3] 625 +} 626 +$def sur|n|socialism 627 +$def par|n|speech 628 + 629 +%% we could even do the same thing abusing context variables 630 + 631 +@def { 632 + * [*[#word]] [!([#pos])] 633 + ** [#meaning] 634 +} 635 + 636 +$def 637 + .word: sur 638 + .pos: n 639 + .meaning: socialism 640 +$def 641 + .word: par 642 + .pos: n 643 + .meaning: speech 644 + 645 +%% context variables are useful because they inherit from the enclosing context 646 +%% thus, we can exploit resource syntax to create templates with default values 647 + 648 +@agent { 649 + + CODENAME :| [#1] 650 + + CIVILIAN IDENTITY :| [#civil] 651 + + RULES of ENGAGEMENT :| [#roe] 652 + + DANGER LEVEL :| [#danger] 653 +} 654 + .civil: (unknown) 655 + .roe: Monitor; do not engage 656 + .danger: (unknown) 657 + 658 +$agent ZUCCHINI PARABLE 659 + .civil: Zephram "Rolodex" Goldberg 660 + .danger: Category Scarlet 661 +$agent RHADAMANTH EXQUISITE 662 + .roe: Eliminate with extreme prejudice; CBRN deployment authorized 663 + .danger: [*Unquantifiable] 614 664 ~~~ 615 665 616 666 ~~~ tables #tab [cortav] ~~~ 617 667 here is a glossary table. 618 668 619 669 + english :+ ranuir + zia ţai + thaliste + 620 670 | honor :| tef | pang | mbecheve |
Modified cortav.lua from [7f118fbbfd] to [827b243474].
282 282 if sp == nil then 283 283 if test then return false else return '' end 284 284 else 285 285 return sp 286 286 end 287 287 elseif self.vars[var] then 288 288 return self.vars[var] 289 + elseif ctx.invocation 290 + and ctx.invocation.props 291 + and ctx.invocation.props['.' .. var] then 292 + return ctx.invocation.props['.' .. var] 293 + elseif ctx.declaration 294 + and ctx.declaration.props['.' .. var] then 295 + return ctx.declaration.props['.' .. var] 289 296 else 290 297 local sp = scanParents(var) 291 298 if sp then return sp end 292 299 if test then return false end 293 300 return '' -- is this desirable behavior? 294 301 end 295 302 end; ................................................................................ 1107 1114 end}; 1108 1115 {seq = '\t', pred = function(l) 1109 1116 return (l:match '\t+([^:]+):%s*(.*)$') 1110 1117 end; fn = blockwrap(function(l,c,j,d) 1111 1118 local ref, val = l:match '\t+([^:]+):%s*(.*)$' 1112 1119 local last = d[#d] 1113 1120 local rsrc 1114 - if last and last.kind == 'resource' then 1121 + if last and last.kind == 'resource' 1122 + or last.kind == 'embed' 1123 + or last.kind == 'macro' then 1124 + last.props = last.props or {} 1115 1125 last.props[ref] = val 1116 - j:hook('rsrc_set_prop', c, last, ref, val, l) 1126 + j:hook('set_prop', c, last, ref, val, l) 1117 1127 rsrc = last 1118 1128 elseif last and last.kind == 'reference' and last.rsrc then 1119 1129 last.rsrc.props[ref] = val 1120 1130 rsrc = last.rsrc 1121 1131 else 1122 1132 c.sec.refs[ref] = val 1123 1133 end ................................................................................ 1286 1296 open = brak; 1287 1297 close = mirror(brak); 1288 1298 } 1289 1299 rsrc.raw = ''; 1290 1300 if src == nil then 1291 1301 rsrc.props.src = 'text/x.cortav' 1292 1302 end 1293 - else 1294 - -- load the raw body, where possible 1295 1303 end 1296 1304 if id then 1297 1305 if c.sec.refs[id] then 1298 1306 c:fail('an object with id “%s” already exists in that section',id) 1299 1307 else 1300 1308 c.sec.refs[id] = rsrc 1301 1309 end 1302 1310 end 1303 1311 table.insert(d, rsrc) 1304 1312 j:hook('block_insert', c, rsrc, s) 1305 - if id == '' then --shorthand syntax 1313 + if id == nil then --shorthand syntax 1306 1314 local embed = { 1307 1315 kind = 'embed'; 1308 1316 rsrc = rsrc; 1309 1317 origin = c; 1318 + mode = 'inline'; 1310 1319 } 1311 1320 table.insert(d, embed) 1312 1321 j:hook('block_insert', c, embed, s) 1313 1322 end 1314 1323 1315 1324 if brak then 1316 1325 c.mode = { ................................................................................ 1404 1413 local mf = job:proc('modes', ctx.mode.kind) 1405 1414 if not mf then 1406 1415 ctx:fail('unimplemented syntax mode %s', ctx.mode.kind) 1407 1416 end 1408 1417 mf(job, ctx, l, dest) --NOTE: you are responsible for triggering the appropriate hooks if you insert anything! 1409 1418 end 1410 1419 else 1411 - if l then 1420 + if l and l ~= '' then 1412 1421 local function tryseqs(seqs, ...) 1413 1422 for _, i in pairs(seqs) do 1414 1423 if ((not i.seq ) or startswith(l, i.seq)) and 1415 1424 ((not i.pred) or i.pred (l, ctx )) then 1416 1425 i.fn(l, ctx, job, dest, ...) 1417 1426 return true 1418 1427 end ................................................................................ 1547 1556 r.origin:fail('resource “%s” is not inline and supplies no URI', 1548 1557 r.id or "(anonymous)") 1549 1558 end 1550 1559 1551 1560 -- the resource has been cached. check the mime-type to see if 1552 1561 -- we need to parse it or if it is suitable as-is 1553 1562 1554 - if resource.mime.class == "text" then 1555 - if resource.mime.kind == "x.cortav" then 1556 - local sd, sc = r.origin.doc:sub(r.origin) 1557 - local lines = ss.str.breaklines(r.origin.doc.enc, resource.raw, {}) 1558 - for i, ln in ipairs(lines) do 1559 - sc.line = sc.line + 1 1560 - ct.parse_line(ln, sc, sc.sec.blocks) 1561 - end 1562 - resource.doc = sd 1563 + if ss.mime 'text/x.cortav' < resource.mime then 1564 + local sd, sc = r.origin.doc:sub(r.origin) 1565 + -- we store the resource block itself in the declaration 1566 + -- slot so that its properties (e.g. context variables) 1567 + -- can affect the way the document is rendered 1568 + sc.declaration = r 1569 + local lines = ss.str.breaklines(r.origin.doc.enc, resource.raw, {}) 1570 + for i, ln in ipairs(lines) do 1571 + sc.line = sc.line + 1 1572 + ct.parse_line(ln, sc, sc.sec.blocks) 1563 1573 end 1574 + resource.doc = sd 1564 1575 end 1565 1576 end 1566 1577 table.insert(srcs, resource) 1567 1578 end 1568 1579 r.srcs = srcs 1569 1580 -- note that resources do not themselves have kinds. when a 1570 1581 -- document requests to insert a resource, the renderer must ................................................................................ 1576 1587 end 1577 1588 end 1578 1589 1579 1590 -- expand block macros 1580 1591 for i, sec in ipairs(ctx.doc.secorder) do 1581 1592 for n, r in pairs(sec.blocks) do 1582 1593 if r.kind == 'macro' then 1583 - local mc = r.origin:clone() 1584 - mc.invocation = r 1585 - local mac = r.origin:ref(r.macro) 1594 + local mc = r.origin 1595 + local mac = mc:ref(r.macro) 1586 1596 if not mac then 1587 - r.origin:fail('no such reference or resource “%s”', r.macro) 1597 + mc:fail('no such reference or resource “%s”', r.macro) 1588 1598 end 1599 + 1589 1600 local subdoc, subctx = ctx.doc:sub(mc) 1590 1601 local rawbody 1602 + subctx.invocation = r 1591 1603 1592 1604 if type(mac) == 'string' then 1593 1605 rawbody = mac 1594 1606 elseif mac.raw then 1595 1607 rawbody = mac.raw 1608 + subctx.declaration = mac 1596 1609 else 1597 - r.origin:fail('block macro “%s” must be either a reference or an embedded text/x.cortav resource', r.macro) 1610 + mc:fail('block macro “%s” must be either a reference or an embedded text/x.cortav resource', r.macro) 1598 1611 end 1599 1612 1600 1613 local lines = ss.str.breaklines(ctx.doc.enc, rawbody) 1601 1614 for i, ln in ipairs(lines) do 1602 1615 ct.parse_line(ln, subctx, subctx.sec.blocks) 1603 1616 end 1604 1617 r.doc = subdoc
Modified render/html.lua from [14fa0c3d9d] to [84a861628f].
853 853 elseif s.mode == 'embed' then 854 854 local mime = s.mime:clone() 855 855 mime.opts = {} 856 856 return string.format('data:%s;base64,%s', mime, ss.str.b64e(s.raw)) 857 857 end 858 858 end 859 859 --figure out how to embed the given object 860 + local function P(p) -- get prop 861 + if b.props and b.props[p] then 862 + return b.props[p] 863 + end 864 + return obj.props[p] 865 + end 860 866 local embedActs = { 861 867 {ss.mime'image/*', function(s,ctr) 862 868 if s == nil then 863 869 return {tag = "picture", nodes = {}} 864 870 else 865 871 local uri = uriForSource(s) 866 872 local fbimg, idx 867 873 if next(ctr.nodes) == nil then 868 874 idx = 1 869 875 fbimg = { 870 876 elt = 'img'; --fallback 871 877 attrs = { 872 - alt = obj.props.desc or obj.props.detail or ''; 873 - title = obj.props.detail; 878 + alt = P'desc' or P'detail' or ''; 879 + title = P'detail'; 874 880 src = uri; 875 - width = obj.props.width; 876 - height = obj.props.height; 881 + width = P'width'; 882 + height = P'height'; 877 883 }; 878 884 } 879 885 else idx = #ctr.nodes end 880 886 table.insert(ctr.nodes, idx, { 881 887 elt = 'source'; --fallback 882 888 attrs = { srcset = uri; }; 883 889 }) ................................................................................ 972 978 local top = rtype[2]() -- create container 973 979 for n, src in ipairs(obj.srcs) do 974 980 if rtype[1] < src.mime then 975 981 rtype[2](src, top) 976 982 end 977 983 end 978 984 local ft = flatten(top) 979 - local cap = b.cap or obj.props.desc or obj.props.detail 985 + local cap = b.cap or P'desc' or P'detail' 980 986 if b.mode == 'inline' then 981 987 -- TODO insert caption 982 988 return ft 983 989 else 984 990 local prop = {} 985 991 if b.mode == 'open' then 986 992 prop.open = true