cortav  Check-in [c15ffd5fef]

Overview
Comment:add weak modes that can be overridden by pragma
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: c15ffd5fef56f39abd50a1e181a3bc84c76b55a803978b4380c215e5dbc3c692
User & Date: lexi on 2021-12-20 14:10:16
Other Links: manifest | tags
Context
2021-12-21
01:22
tidy up repo, add freedesktop file format stuff and viewer handler script check-in: 3b2fea2df1 user: lexi tags: trunk
2021-12-20
14:10
add weak modes that can be overridden by pragma check-in: c15ffd5fef user: lexi tags: trunk
00:40
tweak headers check-in: bdd8d569a9 user: lexi tags: trunk
Changes

Modified cli.lua from [23a0968fc6] to [2240e68512].

22
23
24
25
26
27
28
29
30
31
32
33
34






35
36
37
38
39
40
41
..
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72


73
74
75
76
77
78

79
80
81




82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
...
117
118
119
120
121
122
123




124
125
126
127
128
129
130
...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
	for k, v in pairs(list) do
		if fn(k,v) then new[k] = v end
	end
	return new
end

local function
main(input, output, log, mode, vars)
	local doc = ct.parse(input.stream, input.src, mode)
	input.stream:close()
	if mode['parse:show-tree'] then
		log:write(dump(doc))
	end







	if not mode['render:format'] then
		error 'what output format should i translate the input to?'
	end
	if mode['render:format'] == 'none' then return 0 end
	if not ct.render[mode['render:format']] then
		ct.exns.unimpl('output format “%s” unsupported', mode['render:format']):throw()
................................................................................
	
	-- this is kind of gross but the context object belongs to the parser,
	-- not the renderer, so that's not a suitable place for this information
	doc.stage = {
		kind = 'render';
		format = mode['render:format'];
		mode = mode;

	}

	output:write(ct.render[mode['render:format']](doc, render_opts))
	return 0
end

local inp,outp,log = io.stdin, io.stdout, io.stderr

local function entry_cli()
	local mode, vars, input = default_mode, {}, {
		stream = inp;
		src = {
			file = '(stdin)';
		}
	}



	local optnparams = function(o)
		local param_opts = {
			out = 1;
			log = 1;
			define = 2; -- key value

			['mode-set'] = 1;
			['mode-clear'] = 1;
			mode = 2;




		}
		return param_opts[o] or 0
	end

	local optmap = {
		o = 'out';
		l = 'log';
		d = 'define';
		V = 'version';
		h = 'help';
		y = 'mode-set', n = 'mode-clear';

		m = 'mode';
	}

	local checkmodekey = function(key)
		if not key:match '[^:]+:.+' then
			ct.exns.cli('invalid mode key %s', key):throw()
		end
		return key
................................................................................
				ct.exns.cli 'cannot define variable in restricted namespace':throw()
			end
			vars[key] = value
		end;
		mode = function(key,value) mode[checkmodekey(key)] = value end;
		['mode-set'] = function(key) mode[checkmodekey(key)] = true end;
		['mode-clear'] = function(key) mode[checkmodekey(key)] = false end;




	}

	local args = {}
	local keepParsing = true
	do local i = 1 while i <= #arg do local v = arg[i]
		local execLongOpt = function(longopt)
			if not onswitch[longopt] then
................................................................................
	if args[1] and args[1] ~= '' then
		local file = io.open(arg[1], "rb")
		if not file then error('unable to load file ' .. args[1]) end
		input.stream = file
		input.src.file = args[1]
	end

	return main(input, outp, log, mode, vars)
end

local ok, e = pcall(entry_cli)
-- local ok, e = true, entry_cli()
if not ok then
	local str = 'translation failure'
	if ss.exn.is(e) then







|





>
>
>
>
>
>







 







>









|





>
>






>



>
>
>
>










|
>
|







 







>
>
>
>







 







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
	for k, v in pairs(list) do
		if fn(k,v) then new[k] = v end
	end
	return new
end

local function
main(input, output, log, mode, suggestions, vars)
	local doc = ct.parse(input.stream, input.src, mode)
	input.stream:close()
	if mode['parse:show-tree'] then
		log:write(dump(doc))
	end

	-- the document has now had a chance to give its say; if it hasn't specified
	-- any modes of its own, we now merge in the 'weak modes' (suggestions)
	for k,v in pairs(suggestions) do
		if not mode[k] then mode[k] = v end
	end

	if not mode['render:format'] then
		error 'what output format should i translate the input to?'
	end
	if mode['render:format'] == 'none' then return 0 end
	if not ct.render[mode['render:format']] then
		ct.exns.unimpl('output format “%s” unsupported', mode['render:format']):throw()
................................................................................
	
	-- this is kind of gross but the context object belongs to the parser,
	-- not the renderer, so that's not a suitable place for this information
	doc.stage = {
		kind = 'render';
		format = mode['render:format'];
		mode = mode;
		suggestions = suggestions;
	}

	output:write(ct.render[mode['render:format']](doc, render_opts))
	return 0
end

local inp,outp,log = io.stdin, io.stdout, io.stderr

local function entry_cli()
	local suggestions, vars, input = default_mode, {}, {
		stream = inp;
		src = {
			file = '(stdin)';
		}
	}

	local mode = {}

	local optnparams = function(o)
		local param_opts = {
			out = 1;
			log = 1;
			define = 2; -- key value

			['mode-set'] = 1;
			['mode-clear'] = 1;
			mode = 2;

			['mode-set-weak'] = 1;
			['mode-clear-weak'] = 1;
			['mode-weak'] = 2;
		}
		return param_opts[o] or 0
	end

	local optmap = {
		o = 'out';
		l = 'log';
		d = 'define';
		V = 'version';
		h = 'help';
		y = 'mode-set',   Y = 'mode-set-weak';
		n = 'mode-clear', N = 'mode-clear-weak';
		m = 'mode',       M = 'mode-weak';
	}

	local checkmodekey = function(key)
		if not key:match '[^:]+:.+' then
			ct.exns.cli('invalid mode key %s', key):throw()
		end
		return key
................................................................................
				ct.exns.cli 'cannot define variable in restricted namespace':throw()
			end
			vars[key] = value
		end;
		mode = function(key,value) mode[checkmodekey(key)] = value end;
		['mode-set'] = function(key) mode[checkmodekey(key)] = true end;
		['mode-clear'] = function(key) mode[checkmodekey(key)] = false end;

		['mode-weak'] = function(key,value) suggestions[checkmodekey(key)] = value end;
		['mode-set-weak'] = function(key) suggestions[checkmodekey(key)] = true end;
		['mode-clear-weak'] = function(key) suggestions[checkmodekey(key)] = false end;
	}

	local args = {}
	local keepParsing = true
	do local i = 1 while i <= #arg do local v = arg[i]
		local execLongOpt = function(longopt)
			if not onswitch[longopt] then
................................................................................
	if args[1] and args[1] ~= '' then
		local file = io.open(arg[1], "rb")
		if not file then error('unable to load file ' .. args[1]) end
		input.stream = file
		input.src.file = args[1]
	end

	return main(input, outp, log, mode, suggestions, vars)
end

local ok, e = pcall(entry_cli)
-- local ok, e = true, entry_cli()
if not ok then
	local str = 'translation failure'
	if ss.exn.is(e) then

Modified cortav.ct from [96194d0b88] to [b7a7fbb952].

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109













110
111
112
113
114
115
116
...
247
248
249
250
251
252
253


















254
255
256
257
258
259
260
...
270
271
272
273
274
275
276
277
278
279
280
281
282



283
284
285
286
287
288
289
290
291
...
315
316
317
318
319
320
321












on systems with environment variables, these may be accessed as context variables by prefixing their name with [$env.].

different renderers may provide context in different ways, such as from command line options or a context file. any predefined variables should carry an appropriate prefix to prevent conflation. 

## directives
	d: [$%[*[##1]]]
* {d format} gives a hint on how the document should be formatted. the first hint that is understood will be applied; all others will be discarded. standard hints include:
** essay
** narrative
** screenplay: uses asides to denote actions, quotes for dialogue
** stageplay: uses asides to denote actions, quotes for dialogue
** manual
** glossary
** news
* {d author} encodes document authorship
* {d cols} specifies the number of columns the next object should be rendered with
* {d include} transcludes another file
* {d quote} transcludes another file, without expanding the text except for paragraphs 
* {d embed}, where possible, embeds another file as an object within the current one. in HTML this could be accomplished with e.g. an iframe.
* {d expand} causes the next object (usually a code block) to be fully expanded when it would otherwise not be














##ex examples

~~~ blockquotes #bq [cortav] ~~~
the following excerpts of text were recovered from a partially erased hard drive found in the Hawthorne manor in the weeks after the Incident. context is unknown.

#>
................................................................................

~~~
$ luac -s -o stdin2html.lc $cortav_repo/{sirsem,cortav,ext/toc}.lua stdin2html.lua
~~~

and can then be operated with the command [$lua stdin2html.lc], with no further need for the cortav repository files. note that the order of the [$luac] command is important! [$sirsem.lua] must come first, followed by [$cortav.lua], followed by any extensions. your driver script (i.e. the script with the entry point into the application) should always come last.



















## command line driver
the [$cortav.lua] command line driver can be run from the repository directory with the command [$lua ./cli.lua], or by first compiling it into a bytecode form that links in all its dependencies. this is the preferred method for installation, as it produces a self-contained executable which loads more quickly, but running the driver in script form may be desirable for development or debugging.

the repository contains a GNU makefile to automate compilation of the reference implementation on unix-like OSes. simply run [$$ make cortav] or [$$ gmake cortav] from the repository root to produce a self-contained bytecode executable that can be installed anywhere on your filesystem, with no dependencies other than the lua interpreter.

! note that the makefile strips debugging symbols to save space, so running [$cli.lua] directly as a script may be helpful if you encounter errors and need stacktraces or other debugging information.

................................................................................
$ cortav readme.ct
	# reads from readme.ct, writes to standard output
~~~

### switches
[$cortav.lua] offers various switches to control its behavior.
+ long                      + short + function                                    +
| [$--out [!file]]         :|:[$-o]:| sets the output file (default stdout)       |
| [$--log [!file]]         :|:[$-l]:| sets the log file (default stderr)          |
| [$--define [!var] [!val]]:|:[$-d]:| sets the context variable [$var] to [$val]  |
| [$--mode-set [!mode]]    :|:[$-y]:| activates the [>refimpl-mode mode] with ID [!mode]
| [$--mode-clear [!mode]]  :|:[$-n]:| disables the mode with ID [!mode]           |
| [$--mode [!id] [!val]]   :|:[$-m]:| configures mode [!id] with the value [!val] |



| [$--help]                :|:[$-h]:| display online help                         |
| [$--version]             :|:[$-V]:| display the interpreter version             |

###refimpl-mode modes
most of [$cortav.lua]'s implementation-specific behavior is controlled by use of [!modes]. these are namespaced options which may have a boolean, string, or numeric value. boolean modes are set with the [$-y] [$-n] flags; other modes use the [$-m] flags.

most modes are defined by the renderer backend. the following modes affect the behavior of the frontend:

+ ID                 + type   + effect
................................................................................
	-m render:format html \
	-m html:width 40em \
	-m html:accent 80 \
	-m html:hue-spread 35 \
	-y html:dark-on-light # could also be written as:
$ cortav readme.ct -ommmmy readme.html render:format html html:width 40em html:accent 80 html:hue-spread 35 html:dark-on-light
~~~


















<
<
<
<
<
<
<
<






>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|
|
|
|
|
>
>
>
|
|







 







>
>
>
>
>
>
>
>
>
>
>
89
90
91
92
93
94
95








96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358

on systems with environment variables, these may be accessed as context variables by prefixing their name with [$env.].

different renderers may provide context in different ways, such as from command line options or a context file. any predefined variables should carry an appropriate prefix to prevent conflation. 

## directives
	d: [$%[*[##1]]]








* {d author} encodes document authorship
* {d cols} specifies the number of columns the next object should be rendered with
* {d include} transcludes another file
* {d quote} transcludes another file, without expanding the text except for paragraphs 
* {d embed}, where possible, embeds another file as an object within the current one. in HTML this could be accomplished with e.g. an iframe.
* {d expand} causes the next object (usually a code block) to be fully expanded when it would otherwise not be
* {d pragma} supplies semantic data about author intent, the kind of information document contains and hints about how it should be displayed to the user. think of them like offhand remarks to the renderer -- there's no guarantee that it'll pay any attention, but if it does, your document will look better. pragmas have no scope; they affect the entire document. the pragma function exists primarily as a means to allow parameters that would normally need to be specified on e.g. the command line to be encoded in the document instead in a way that multiple implementations can understand. a few standard pragmas are defined
** {d pragma layout} gives a hint on how the document should be layed out. the first hint that is understood will be applied; all others will be discarded. standard hints include:
*** essay
*** narrative
*** screenplay: uses asides to denote actions, quotes for dialogue
*** stageplay: uses asides to denote actions, quotes for dialogue
*** manual
*** glossary
*** news
** {d pragma accent} specifies an accent hue (in degrees around the color wheel) for renderers which support colorized output
** {d pragma accent-spread} is a factor that controls the "spread" of hues used in the document. if 0, only the accent color will be used; if larger, other hues will be used in addition to the primary accent color.
** {d pragma dark-on-light on|off} controls whether the color scheme used should be light-on-dark or dark-on-light
** {d pragma page-width} indicates how wide the pages should be

##ex examples

~~~ blockquotes #bq [cortav] ~~~
the following excerpts of text were recovered from a partially erased hard drive found in the Hawthorne manor in the weeks after the Incident. context is unknown.

#>
................................................................................

~~~
$ luac -s -o stdin2html.lc $cortav_repo/{sirsem,cortav,ext/toc}.lua stdin2html.lua
~~~

and can then be operated with the command [$lua stdin2html.lc], with no further need for the cortav repository files. note that the order of the [$luac] command is important! [$sirsem.lua] must come first, followed by [$cortav.lua], followed by any extensions. your driver script (i.e. the script with the entry point into the application) should always come last.

### building custom tools
generally, most existing file-format conversion tools (cmark, pandoc, and so on) have a crucial limitation: they hardcode specific assumptions like document structure. this means that the files they output are generally not suitable as-is for the users' purposes, and require further munging, usually by hateful shell or perl scripts. some tools do provide libraries end users to use as a basis for designing their own tools, but these are often limited, and in any case the user ends up having to write their own (non-standard) driver. it's no surprise that very few people end up doing this.

[$cortav.lua]'s design lends itself to a more elegant solution. one can of course write their own driver using [$cortav] as a library, but most of the time when you're compiling document sources, you just want a binary you can run from the command line or a makefile. with [$cortav.lua], you can extend its capabilities easily while keeping the same driver.

in the [$cortav] spec, extensions are mostly intended to give different implementations the ability to offer extra capabilities, but the reference implementation uses an extension architecture that makes it easy to write and add your own. for each type of new behavior you want to implement, just create a new extension and list it on the make command line:

~~~
$ nvim ~/dev/my-cortav-exts/imperial-edict.lua
$ make cortav extens+=$HOME/dev/my-cortav-exts/*.lua
~~~

the cortav binary this produces will have all the extra capabilities you personally need, without any need to fork [$cortav.lua] itself or even touch the repository.

there's no reason [$cortav.lua] shouldn't be able to load extensions at runtime as well; i just haven't implemented this behavior yet. it probably would only take a few extra lines of code tho.

i will eventually document the extension API, but for now, look at [$ext/toc.lua] for a simple example of how to register an extension.

## command line driver
the [$cortav.lua] command line driver can be run from the repository directory with the command [$lua ./cli.lua], or by first compiling it into a bytecode form that links in all its dependencies. this is the preferred method for installation, as it produces a self-contained executable which loads more quickly, but running the driver in script form may be desirable for development or debugging.

the repository contains a GNU makefile to automate compilation of the reference implementation on unix-like OSes. simply run [$$ make cortav] or [$$ gmake cortav] from the repository root to produce a self-contained bytecode executable that can be installed anywhere on your filesystem, with no dependencies other than the lua interpreter.

! note that the makefile strips debugging symbols to save space, so running [$cli.lua] directly as a script may be helpful if you encounter errors and need stacktraces or other debugging information.

................................................................................
$ cortav readme.ct
	# reads from readme.ct, writes to standard output
~~~

### switches
[$cortav.lua] offers various switches to control its behavior.
+ long                      + short + function                                    +
| [$--out [!file]]              :|:[$-o]:| sets the output file (default stdout)       |
| [$--log [!file]]              :|:[$-l]:| sets the log file (default stderr)          |
| [$--define [!var] [!val]]     :|:[$-d]:| sets the context variable [$var] to [$val]  |
| [$--mode-set [!mode]]         :|:[$-y]:| activates the [>refimpl-mode mode] with ID [!mode]
| [$--mode-clear [!mode]]       :|:[$-n]:| disables the mode with ID [!mode]           |
| [$--mode [!id] [!val]]        :|:[$-m]:| configures mode [!id] with the value [!val] |
| [$--mode-set-weak [!mode]]    :|:[$-Y]:| activates the [>refimpl-mode mode] with ID [!mode] if the source file does not specify otherwise
| [$--mode-clear-weak [!mode]]  :|:[$-N]:| disables the mode with ID [!mode] if the source file does not specify otherwise
| [$--mode-weak [!id] [!val]]   :|:[$-M]:| configures mode [!id] with the value [!val] if the source file does not specify otherwise
| [$--help]                     :|:[$-h]:| display online help                         |
| [$--version]                  :|:[$-V]:| display the interpreter version             |

###refimpl-mode modes
most of [$cortav.lua]'s implementation-specific behavior is controlled by use of [!modes]. these are namespaced options which may have a boolean, string, or numeric value. boolean modes are set with the [$-y] [$-n] flags; other modes use the [$-m] flags.

most modes are defined by the renderer backend. the following modes affect the behavior of the frontend:

+ ID                 + type   + effect
................................................................................
	-m render:format html \
	-m html:width 40em \
	-m html:accent 80 \
	-m html:hue-spread 35 \
	-y html:dark-on-light # could also be written as:
$ cortav readme.ct -ommmmy readme.html render:format html html:width 40em html:accent 80 html:hue-spread 35 html:dark-on-light
~~~

## further directions

### LCH support
right now, the use of color in the HTML renderer is very unsatisfactory. the accent mechanism operates on the basis of the CSS HSL function, which is not perceptually uniform; different hues will present different mixes of brightness and some (yellows?) may be ugly or unreadable.

the ideal solution would be to simply switch to using LCH based colors. unfortunately, only Safari actually supports the LCH color function right now, and it's unlikely (unless Lea Verou and her husband manage to work a miracle) that Colors Level 4 is going to be implemented very widely any time soon.

this leaves us in an awkward position. we can of course do the math ourselves, working in LCH to implement the internal [$@tone] macro, and then "converting" these colors to HSL. unfortunately, you can't actually convert from LCH to HSL; it's like converting from pounds to kilograms. LCH can represent any color the human visual system can perceive; sRGB can't, and CSS HSL is implemented in sRGB. however, we could at least approximate something that would allow for perceptually uniform brightness, which would be an improvement, and this is probably the direction to go in, unless a miracle occurs and [$lch()] or [$color()] pop up in Blink.

it may be possible to do a more reasonable job of handling colors in the postscript and TeX outputs. unsure about SVG but i assume it suffers the same problems HTML/CSS do. does groff even support color??

Modified cortav.lua from [19e0c83304] to [cf364bf145].

209
210
211
212
213
214
215

216
217
218
219
220
221
222



















































223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
...
442
443
444
445
446
447
448

449
450
451
452
453
454
455
...
544
545
546
547
548
549
550










551

552
553
554
555
556
557
558
		fortran = { color = 0xff779a };
		python = { color = 0xffd277 };
		python = { color = 0xcdd6ff };
	}

	local stylesets = {
		header = [[

			h1 { font-size: 200%; border-bottom-style: double !important; border-bottom-width: 3px !important; }
			h2 { font-size: 130%; }
			h3 { font-size: 110%; }
			h4 { font-size: 100%; font-weight: normal; }
			h5 { font-size: 90%; font-weight: normal; }
			h6 { font-size: 80%; font-weight: normal; }
			h3, h4, h5, h6 { border-bottom-style: dotted !important; }



















































		]];
		accent = [[
			body { background: @bg; color: @fg }
			a[href] {
				color: @tone(0.7 30);
				text-decoration-color: @tone/0.4(0.7 30);
			}
			a[href]:hover {
				color: @tone(0.9 30);
				text-decoration-color: @tone/0.7(0.7 30);
			}
			h1,h2,h3,h4,h5,h6 { border-bottom: 1px solid @tone(0.7); }
			h1 { color: @tone(2); }
			h2 { color: @tone(1.5); }
			h3 { color: @tone(1.2); }
			h4 { color: @tone(1); }
			h5,h6 { color: @tone(0.8); }
		]];
		code = [[
................................................................................
				end
			end
			return lst
		end

		local block_renderers = {
			paragraph = function(b,s)

				return tag('p', nil, sr.htmlSpan(b.spans, b, s), b)
			end;
			directive = function(b,s)
				-- deal with renderer directives
				local _, cmd, args = b.words(2)
				if cmd == 'page-title' then
					if not opts.title then doctitle = args end
................................................................................
		local irs
		if sec.kind == 'ordinary' then
			if #(sec.blocks) > 0 then
				irs = {tag='section',attrs={id = getSafeID(sec)},nodes={}}

				for i, block in ipairs(sec.blocks) do
					local rd = irBlockRdrs[block.kind](block,sec)










					if rd then table.insert(irs.nodes, rd) end

				end
			end
		elseif sec.kind == 'blockquote' then
		elseif sec.kind == 'listing' then
		elseif sec.kind == 'embed' then
		end
		if irs then table.insert(ir, irs) end







>
|
|
|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











<







 







>







 







>
>
>
>
>
>
>
>
>
>
|
>







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

286
287
288
289
290
291
292
...
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
...
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
		fortran = { color = 0xff779a };
		python = { color = 0xffd277 };
		python = { color = 0xcdd6ff };
	}

	local stylesets = {
		header = [[
			h1,h2,h3,h4,h5,h6 { border-bottom: 1px solid @tone(0.7); }
			h1 { font-size: 200%; border-bottom-style: double !important; border-bottom-width: 3px !important; margin: 0em -1em; }
			h2 { font-size: 130%; margin: 0em -0.7em; }
			h3 { font-size: 110%; margin: 0em -0.5em; }
			h4 { font-size: 100%; font-weight: normal; margin: 0em -0.2em; }
			h5 { font-size: 90%; font-weight: normal; }
			h6 { font-size: 80%; font-weight: normal; }
			h3, h4, h5, h6 { border-bottom-style: dotted !important; }
			h1,h2,h3,h4,h5,h6 { 
				margin-top: 0;
				margin-bottom: 0;
			}
			:is(h1,h2,h3,h4,h5,h6) + p {
				margin-top: 0.4em;
			}

		]];
		headingAnchors = [[
			:is(h1,h2,h3,h4,h5,h6) > a[href].anchor {
				text-decoration: none;
				font-size: 1.2em;
				padding: 0.3em;
				opacity: 0%;
				transition: 0.3s;
				font-weight: 100;
			}
			:is(h1,h2,h3,h4,h5,h6):hover > a[href].anchor {
				opacity: 50%;
			}
			:is(h1,h2,h3,h4,h5,h6) > a[href].anchor:hover {
				opacity: 100%;
			}

			]] .. -- this is necessary to avoid the sections jumping around
			      -- when focus changes from one to another
			[[ section {
				border: 1px solid transparent;
			}

			section:target {
				margin-left: -2em;
				margin-right: -2em;
				padding: 0 2em;
				background: @tone(0.04);
				border: 1px dotted @tone(0.3);
			}

			section:target > :is(h1,h2,h3,h4,h5,h6) {

			}
		]];
		paragraph = [[
			p {
				margin: 0.7em 0;
			}
			section {
				margin: 1.2em 0;
			}
			section:first-child { margin-top: 0; }
		]];
		accent = [[
			body { background: @bg; color: @fg }
			a[href] {
				color: @tone(0.7 30);
				text-decoration-color: @tone/0.4(0.7 30);
			}
			a[href]:hover {
				color: @tone(0.9 30);
				text-decoration-color: @tone/0.7(0.7 30);
			}

			h1 { color: @tone(2); }
			h2 { color: @tone(1.5); }
			h3 { color: @tone(1.2); }
			h4 { color: @tone(1); }
			h5,h6 { color: @tone(0.8); }
		]];
		code = [[
................................................................................
				end
			end
			return lst
		end

		local block_renderers = {
			paragraph = function(b,s)
				stylesNeeded.paragraph = true;
				return tag('p', nil, sr.htmlSpan(b.spans, b, s), b)
			end;
			directive = function(b,s)
				-- deal with renderer directives
				local _, cmd, args = b.words(2)
				if cmd == 'page-title' then
					if not opts.title then doctitle = args end
................................................................................
		local irs
		if sec.kind == 'ordinary' then
			if #(sec.blocks) > 0 then
				irs = {tag='section',attrs={id = getSafeID(sec)},nodes={}}

				for i, block in ipairs(sec.blocks) do
					local rd = irBlockRdrs[block.kind](block,sec)
					if rd then
						if opts['heading-anchors'] and block == sec.heading_node then
							stylesNeeded.headingAnchors = true
							table.insert(rd.nodes, ' ')
							table.insert(rd.nodes, {
								tag = 'a';
								attrs = {href = '#' .. irs.attrs.id, class='anchor'};
								nodes = {type(opts['heading-anchors'])=='string' and opts['heading-anchors'] or '&sect;'};
							})
						end
						table.insert(irs.nodes, rd)
					end
				end
			end
		elseif sec.kind == 'blockquote' then
		elseif sec.kind == 'listing' then
		elseif sec.kind == 'embed' then
		end
		if irs then table.insert(ir, irs) end

Modified makefile from [5cfd42ea5f] to [5a68812ac4].

1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
lua != which lua
luac != which luac

extens ?= $(patsubst ext/%.lua,%,$(wildcard ext/*.lua))
extens_srcs = $(patsubst %,ext/%.lua,$(extens))

cortav: sirsem.lua cortav.lua $(extens_srcs) cli.lua

	echo '#!$(lua)' > $@
	luac -o - $^ >> $@
	chmod +x $@

cortav.html: cortav.ct cortav
	./cortav $< -o $@ -m render:format html -y html:fossil-uv

.PHONY: syncdoc
syncdoc: cortav.html
	fossil uv add $<
	fossil uv sync



|
|

|
>











1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
lua != which lua
luac != which luac

extens = $(wildcard ext/*.lua)
extens_names ?= $(basename $(notdir $(extens)))

cortav: sirsem.lua cortav.lua $(extens) cli.lua
	@echo ' » building with extensions $(extens_names)'
	echo '#!$(lua)' > $@
	luac -o - $^ >> $@
	chmod +x $@

cortav.html: cortav.ct cortav
	./cortav $< -o $@ -m render:format html -y html:fossil-uv

.PHONY: syncdoc
syncdoc: cortav.html
	fossil uv add $<
	fossil uv sync