slweb.1.in (33349B)
1 .\" This program is licensed under the terms of GNU GPL v3 or (at your option) 2 .\" any later version. Copyright (C) 2020-2026 Страхиња Радић. 3 .\" See the file LICENSE for exact copyright and license details. 4 .Dd %DATE% 5 .Dt SLWEB 1 6 .Os 7 .Sh NAME 8 .Nm slweb 9 .Nd Simple static website generator 10 .Sh SYNOPSIS 11 .Nm 12 .Fl h | \-help | Fl V | \-full\-version | Fl v | \-version 13 .Nm 14 .Oo Fl b | Fl \-body\-only Oc Oo Fl d Ar directory | Fl \-basedir Ar directory 15 .Oc Oo Fl p Ar URL | Fl \-global\-link\-prefix Ar URL Oc Op Ar filename 16 . 17 .Sh DESCRIPTION 18 .Nm 19 is a static website generator which aims at being simplistic. 20 It transforms custom Markdown\-like syntax into HTML. 21 . 22 .Bl -tag -width Ds 23 .It Fl b , Fl \-body\-only 24 Only add the contents of the 25 .Ql <body> 26 tag, skipping 27 .Ql <html> 28 and 29 .Ql <head> . 30 .It Fl d Ar directory , Fl \-basedir Ar directory 31 Set the base directory for image file paths to pass to 32 .Xr identify 1 , 33 includes 34 .Pf "(" Ql {include} 35 and 36 .Ql {incdir} ) 37 and favicons. 38 Defaults to the current directory 39 .Pf "(" Dq "." Ns 40 ). 41 .It Fl h , Fl \-help 42 Print the usage information screen. 43 .It Fl p Ar URL , Fl \-global\-link\-prefix Ar URL 44 Set 45 .Ar URL 46 as a global prefix for relative links. 47 .It Fl V , Fl \-full\-version 48 Print full version (like 49 .Fl v Ns 50 ), 51 followed by copyright notice, and exit. 52 .It Fl v , Fl \-version 53 Print program version and commit date, and exit. 54 .El 55 . 56 Files processed by 57 .Nm 58 are using a minimal subset of Markdown with added directives. 59 . 60 .Ss Supported Markdown features 61 . 62 .Bl -bullet -width 1m 63 .It 64 .Sy Backticks . 65 Text inside 66 .Ql `backticks` 67 will be put inside 68 .Ql <code></code> . 69 Text surrounded by triple backticks 70 .Pf "(" Ql "```" ) 71 on the lines by themselves will be put inside 72 .Ql <pre></pre> . 73 Any 74 .Dq less\-than 75 characters inside backticks will be converted to 76 .Ql <\& 77 and 78 .Dq ampersand 79 characters to 80 .Ql &\& . 81 Any text following the first triple backticks until the end of the line will be 82 ignored. 83 This is to account for language highlighting specification, which isn't yet 84 supported. 85 . 86 .It 87 .Sy Blockquotes . 88 Starting the line with 89 .Ql > 90 will surround it with a 91 .Ql <blockquote> 92 tag. 93 Multiple lines are supported. 94 . 95 .It 96 .Sy Bold/italic . 97 Text inside 98 .Ql *asterisks* 99 or 100 .Ql _underlines_ 101 will be put inside 102 .Ql <em></em> . 103 Text inside 104 .Ql **double asterisks** 105 or 106 .Ql __double underlines__ 107 will be put inside 108 .Ql <strong></strong> . 109 .Ql ***More than two*** 110 of the 111 .Ql ___same symbol___ 112 should be avoided. 113 . 114 .It 115 .Tg Break_marks 116 .Sy Break marks . 117 To address combinations of lists and 118 .Dq raw 119 tags, which are problematic to mix together, 120 .Nm 121 supports explicitly marking a tag with a 122 .Dq break mark . 123 This currently means that when such a tag is introduced, any running list item 124 and list will be closed prior to outputting the tag. 125 Tags with break marks are introduced by prepending the exclamation mark to the 126 tag name. 127 For example, without a break mark, the input: 128 .Bd -literal -offset Ds 129 - Some list 130 {break-here} 131 .Ed 132 .Pp 133 produces the following output: 134 .Bd -literal -offset Ds 135 <ul><li><p>Some list 136 <break-here></li></ul> 137 .Ed 138 .Pp 139 When changed to: 140 .Bd -literal -offset Ds 141 - Some list 142 {!break-here} 143 .Ed 144 .Pp 145 .Nm 146 will output: 147 .Bd -literal -offset Ds 148 <ul><li><p>Some list 149 </li></ul> 150 <break-here> 151 .Ed 152 .Pp 153 Same for end tags: 154 .Bd -literal -offset Ds 155 {dl}{dt}{p}Introduction{/dt} 156 {dd} 157 - One 158 - Two 159 {/dd}{/dl} 160 .Ed 161 .Pp 162 produces: 163 .Bd -literal -offset Ds 164 <dl><dt><p>Introduction</dt> 165 <dd> 166 <ul><li><p>One 167 </li> 168 <li><p>Two 169 </dd></dl></li></ul> 170 .Ed 171 .Pp 172 while 173 .Bd -literal -offset Ds 174 {dl}{dt}{p}Introduction{/dt} 175 {dd} 176 - One 177 - Two 178 {/!dd}{/dl} 179 .Ed 180 .Pp 181 produces: 182 .Bd -literal -offset Ds 183 <dl><dt><p>Introduction</dt> 184 <dd> 185 <ul><li><p>One 186 </li> 187 <li><p>Two 188 </li></ul> 189 </dd></dl> 190 .Ed 191 .It 192 .Sy Footnotes (regular and inline) . 193 Two-part regular footnotes can be added in a manner similar to links (see 194 .Sx Links Ns 195 ). 196 Inline footnotes are also supported. 197 .Bl -dash -width 1m 198 .It 199 .Tg Regular_footnotes 200 .Sy Regular footnotes 201 have two mandatory parts: first, the footnote mark is represented by 202 .Ql [^ Ns Ar footnoteid Ns \[rB] , 203 where 204 .Ar footnoteid 205 is the footnote identifier. 206 Second, the text of the footnote is represented by 207 .Ql [^ Ns Ar footnoteid Ns \[rB] : Ar sometext , 208 with 209 .Ar sometext 210 being the text of the footnote. 211 Footnote text construct needs to begin at the start of a line, and it is the 212 most practical to have it placed near the bottom of the file, similar to normal 213 links. 214 .Pp 215 Combined, the input: 216 .Bd -literal -offset Ds 217 This is a text[^first]. 218 219 [^first]: With a footnote! 220 .Ed 221 .Pp 222 gives (some lines are wrapped for this manual): 223 .Bd -literal -offset Ds 224 <p>This is a text<a href="#footnote-1" id="footnote-text-1"> 225 <sup>1</sup></a>. 226 227 <hr> 228 <p id="footnote-1"><a href="#footnote-text-1">1.</a> 229 With a footnote! 230 .Ed 231 .It 232 .Tg Inline_footnotes 233 .Sy Inline footnotes 234 can be added by using the construct 235 .Ql ^[ Ns Ar footnotetext Ns \[rB] . 236 For example, input 237 .Bd -literal -offset Ds 238 Inline footnote^[Footnote text] in a paragraph. 239 .Ed 240 .Pp 241 will produce 242 .Bd -literal -offset Ds 243 Inline footnote<a href="#inline-footnote-1" 244 id="inline-footnote-text-1"><sup>1</sup></a> in a 245 paragraph. 246 <hr> 247 <p id="inline-footnote-1"><a href="#inline-footnote-text-1"> 248 1.</a> Footnote text 249 .Ed 250 .Pp 251 The horizontal rule and the list of footnotes is output only once, before the 252 end of HTML document body. 253 Rule and the list of footnotes can be surrounded by a div with the 254 .Dq Dv footnotes 255 id by setting the YAML variable 256 .Va add-footnote-div 257 to 258 .Dq 1 259 (see 260 .Sx add-footnote-div Ns 261 ). 262 .Pp 263 Inline and regular footnotes can be used at the same time, but they don't share 264 the numbering. 265 This doesn't affect functionality, but it does affect presentation, as some 266 footnote numbers will overlap. 267 As a result, whenever 268 .Nm 269 encounters both footnote types in the same document, a warning will be issued to 270 .Pa stderr . 271 .El 272 .It 273 .Sy Headings . 274 A line starting with 275 .Ql # 276 followed by space will be put inside 277 .Ql <h?></h?> , 278 where 279 .Ql ?\& 280 stands for 1-4, depending on the number of hash signs. 281 Tags will have 282 .Cm id 283 attributes set to 284 .Ql heading-?\& , 285 with 286 .Ql ?\& 287 set to the number representing its position within the list of all headings. 288 .It 289 .Tg Horizontal_rules 290 .Sy Horizontal rules . 291 Three dashes at the start of the line will produce a 292 .Ql <hr> 293 in the output. 294 As this Markdown feature clashes with YAML block boundaries, it will work only 295 if YAML block is present in the input and before the three dashes for the 296 horizontal rule. 297 Any text following the three dashes on the same line will be ignored. 298 .Pp 299 Alternatively, three asterisks 300 .Pq Ql "***" 301 can be used instead of dashes, avoiding the necessity for a YAML block preceding 302 the asterisks. 303 .It 304 .Sy Images . 305 Similar to links (see 306 .Sx Links Ns 307 ), 308 images can be added by using: 309 .Bd -literal -offset Ds 310  311 .Ed 312 .Pp 313 Which will produce: 314 .Bd -literal -offset Ds 315 <figure> 316 <a href="/path/to/image.png" title="Some title" class="image" 317 target="_blank"><img src="/path/to/image.png" alt="Some title" 318 width="100" height="50" ></a><figcaption>Some title</figcaption> 319 </figure> 320 .Ed 321 .Pp 322 The attributes 323 .Cm width 324 and 325 .Cm height 326 will be determined automatically using the command 327 .Xr identify 1 328 (if present), provided the 329 .Cm src 330 attribute contains a valid file path. (Also see 331 .Va image-file-prefix Ns ). 332 .Pp 333 As with links, a form similar to the 334 .Dq regular form 335 of links can also be used, using the image id instead of the direct URL. 336 .Pp 337 If the additional link or 338 .Ql <figure> Ns 339 .Pf / Ns Ql <figcaption> 340 tags are not desirable, they can be turned off by setting 341 .Va add-image-links 342 and 343 .Va add-figcaption 344 to 345 .Dq 0 . 346 .It 347 .Tg Keyboard_tags 348 .Sy Keyboard tags . 349 Text inside 350 .Ql ||double bars||\& 351 will be put inside 352 .Ql <kbd></kbd> 353 tags. 354 As with backticks, any 355 .Dq less\-than 356 character will be converted to 357 .Ql <\& . 358 .It 359 .Tg Line_breaks 360 .Sy Line breaks . 361 Two spaces followed by a newline will become 362 .Ql <br> . 363 .It 364 .Sy Links . 365 .Bl -dash -width 1m 366 .It 367 .Sy Inline links . 368 The construct 369 .Ql [A link](https://example.com) 370 will be converted into 371 .Ql <a href="https://example.com">A link</a> . 372 .Pp 373 Special case is the form 374 .Dl [= Ns Ar somemacro No Link title](https://anything) 375 which prepends the body of a macro 376 .Ar somemacro 377 into the 378 .Ql <a></a> 379 tag (here broken into multiple lines for clarity): 380 .Bd -literal -offset Ds 381 <a href="https://anything"> 382 <!-- contents of somemacro --> 383 Link title</a> 384 .Ed 385 .Pp 386 This can, for example, be used to add SVG icons to links. 387 See 388 .Sx Macros . 389 .Pp 390 Also, the form 391 .Ql [(Link title)](http://asite.com) 392 will surround the link title (text between 393 .Ql <a></a> 394 tags) with 395 .Ql <span></span> , 396 like so: 397 .Bd -literal -offset Ds 398 <a href="http://asite.com"><span>Link title</span></a> 399 .Ed 400 .Pp 401 This allows for separate styling of link text. 402 It can be combined with the macro\-form: 403 .Bd -literal -offset Ds 404 .No [= Ns Ar somemacro No (Link title)](http://asite.com) 405 .Ed 406 .Pp 407 It will prepend the body of a macro 408 .Ar somemacro 409 outside of the 410 .Ql <span></span> : 411 .Bd -literal -offset Ds 412 <a href="http://asite.com"> 413 .No <!-- contents of Ar somemacro No --> 414 <span>Link title</span></a> 415 .Ed 416 .Pp 417 Exception is the form 418 .Dl [Some text (parenthesized)](https://somelink) , 419 which won't output 420 .Ql <span> 421 tags, and will simply include the parentheses in the output instead. 422 This form doesn't apply to macro-form 423 .Dl [=macro Some (text)](http://link) , 424 which will always output 425 .Ql <span> 426 tags. 427 .It 428 .Sy Regular links . 429 Everything said about inline links applies to regular links, with the exception 430 that instead of the parenthesized URL, link text inside brackets should be 431 followed by link id (different than the 432 .Cm id 433 .Em attribute!\& ) 434 inside brackets, and a separate definition of that link id is needed, usually 435 near the end of input. 436 .Pp 437 For example: 438 .Bd -literal -offset Ds 439 Here's a link to [my website][mw]. 440 441 [mw]: https://mysite.com 442 .Ed 443 .Pp 444 will produce: 445 .Bd -literal -offset Ds 446 <p>Here's a link to <a href="https://mysite.com">my website</a>. 447 .Ed 448 .Pp 449 This can help reduce the amount of code in the text of the page. 450 .El 451 .It 452 .Sy Lists . 453 Lines starting with a dash 454 .Pf "(" Ql "-" Ns 455 ), 456 an asterisk 457 .Pf "(" Ql "*" ) 458 or lowercase 459 .Dq o , 460 followed by a space, will start an unordered list (if used for the first time) 461 and start a list item. 462 Input: 463 .Bd -literal -offset Ds 464 Colors are: 465 466 - Red 467 - Green 468 - Blue 469 470 and so on. 471 .Ed 472 .Pp 473 will produce: 474 .Bd -literal -offset Ds 475 <p>Colors are: 476 477 <ul> 478 <li><p>Red 479 </li> 480 <li><p>Green 481 </li> 482 <li><p>Blue 483 </li></ul> 484 <p>And so on. 485 .Ed 486 .Pp 487 Indenting a line after a blank line with two spaces will create a paragraph 488 within the list item, otherwise it will end the list: 489 .Bd -literal -offset Ds 490 - This is a text inside a list item. 491 492 Remarkably, this paragraph is as well. 493 - This is already a second item. 494 495 This is after the list. 496 .Ed 497 .Pp 498 will produce: 499 .Bd -literal -offset Ds 500 <ul><li><p>This is a text inside a list item. 501 <p>Remarkably, this paragraph is as well. 502 </li> 503 <li><p>This is already a second item.</li></ul> 504 <p>This is after the list. 505 .Ed 506 .Pp 507 Lists can't be nested, and the characters inside an existing list which would 508 otherwise start a list shall just be inserted as-is in the output. 509 .It 510 .Tg Non-breaking_hyphen 511 .Sy Non-breaking hyphen . 512 Tilde followed by a hyphen 513 .Pf "(" Ql "~-" ) 514 will insert 515 .Ql ‑\& 516 in the output. 517 .It 518 .Tg Non-breaking_space 519 .Sy Non-breaking space . 520 Two consecutive tildes 521 .Pf "(" Ql "~~" ) 522 will produce 523 .Ql \& 524 in the output. 525 .It 526 .Sy Paragraphs . 527 Text surrounded by newlines will be prepended by 528 .Ql <p> 529 tag. 530 See 531 .Sx Known limitations . 532 .It 533 .Sy Strikethrough . 534 Text surrounded by tildes 535 .Pf "(" Ql "~" ) 536 will be put inside 537 .Ql <s></s> . 538 .It 539 .Sy Tables . 540 Lines starting with vertical bars 541 .Pf "(" Ql "|" ) 542 will be transformed into HTML tables. 543 The first such line is treated as a header row, second as the alignment 544 specifier (currently ignored), and the rest regular rows. 545 Table cells and header cells are specified by additional bar characters. 546 For example, input: 547 .Bd -literal -offset Ds 548 | Month | Jan | Feb | Mar | Apr | 549 |-------|-----|-----|-----|-----| 550 | Qty | 2.35| 1.2 | 8 | 15 | 551 .Ed 552 .Pp 553 will be transformed into: 554 .Bd -literal -offset Ds 555 <table> 556 <thead> 557 <tr><th> Month </th><th> Jan </th><th> Feb </th><th> Mar </th> 558 <th> Apr </th></tr> 559 </thead> 560 <tbody> 561 <tr><td> Qty </td><td> 2.35</td><td> 1.2 </td><td> 8 </td> 562 <td> 15 </td></tr> 563 </tbody> 564 </table> 565 .Ed 566 .It 567 .Tg Partial_tables 568 .Sy Partial tables 569 are a modification of Markdown tables, allowing them to be combined with the TSV 570 or CSV directive. 571 In order for tables to work with templating, they need two additional lines at 572 the top and the bottom, to mark the start and the end of the table. 573 All the lines in partial tables need to start with 574 .Ql | , 575 with only the character following at-mark being different: 576 .Bd -literal -offset Ds 577 |@\\------|-----|-----|-----|-----| 578 {tsv "../tsv/sales" 1} 579 |@# $#1 | $#2 | $#3 | $#4 | $#5 | 580 {/tsv} 581 |@-------|-----|-----|-----|-----| 582 {tsv "../tsv/sales"} 583 |@ $1 | $2 | $3 | $4 | $5 | 584 {/tsv} 585 |@/------|-----|-----|-----|-----| 586 .Ed 587 .Pp 588 The rest of the line following the third character in top, bottom and lines 589 separating header from body is ignored by the parser and is included in this 590 example only for aesthetic purposes. 591 See 592 .Sx TSV/CSV templating . 593 .It 594 .Tg Zero_width_space 595 .Sy Zero width space . 596 Tilde followed by an exclamation mark 597 .Pf "(" Ql "~!" ) 598 will produce 599 .Ql ​\& 600 in the output. 601 .El 602 . 603 .Ss Math mode 604 Math mode is supported through KaTeX. 605 With 606 .Nm katex 607 installed, anything between dollar signs 608 .Pf "(" Ql "$" ) 609 will be transformed into MathML and HTML markup. 610 To generate display math, use double dollar signs 611 .Pf "(" Ql "$$" Ns 612 ). 613 The text between the dollar signs in both cases should be LaTeX source code, and 614 is passed to 615 .Nm katex . 616 The KaTeX stylesheet is not included, and needs to be included separately 617 through the 618 .Va stylesheet 619 or 620 .Va inline-stylesheet 621 YAML variables (see 622 .Sx stylesheet , 623 .Sx inline-stylesheet Ns 624 ). 625 . 626 .Ss Directives 627 .Bl -bullet -width 1m 628 .It 629 .Tg Brand_watermark 630 .Bf Sy 631 Brand 632 .Dq watermark Ns 633 .Ef 634 \&. 635 Directive 636 .Ql {made\-by} 637 results in a div to be output at the end of the document, with the id 638 .Ic made\-by 639 containing the 640 .Dq watermark 641 text and a link to the 642 .Nm 643 home page. 644 .It 645 .Tg General_tags 646 .Sy General tags . 647 Directive 648 .Ql {sometag}{/sometag} 649 will be transformed into 650 .Ql <sometag></sometag> . 651 .It 652 .Tg Class_attributes 653 .Sy Class attributes . 654 Directive 655 .Ql {tag.myclass mysecondclass}{/tag} 656 will be transformed into 657 .Ql <tag class="myclass mysecondclass"></tag> . 658 Only one class attribute is permitted per tag directive (subsequent dots will be 659 inserted as part of the 660 .Cm class 661 attribute), but you can include multiple classes by separating them with a 662 space, just like in HTML, and you can have both a class attribute and an id 663 attribute per tag. 664 .Pp 665 A variation of this is to use a special form 666 .Ql {.myclass}{/.myclass} , 667 which will be transformed into 668 .Ql <div class="myclass"></div> . 669 .It 670 .Tg Id_attributes 671 .Sy Id attributes . 672 Directive 673 .Ql {tag#myid}{/tag} 674 will be transformed into 675 .Ql <tag id="myid"></tag> . 676 Only one id attribute is permitted per tag directive (subsequent hash signs will 677 be included as part of the 678 .Cm id 679 attribute), and you can have both an id attribute and a class attribute per tag. 680 .Pp 681 A variation of this is to use a special form 682 .Ql {#myid}{/#myid} , 683 which will be transformed into 684 .Ql <div id="myid"></div> . 685 .It 686 .Sy Includes . 687 Directive 688 .Ql {include \&"somefile"} 689 will fork, parse 690 .Pa somefile.slw 691 (related to 692 .Pa basedir ) 693 and output the resulting HTML as if the option 694 .Fl \-body\-only 695 was specified. 696 All YAML variables will be preserved. 697 .It 698 .Sy Macros . 699 Macros can be declared using the directive 700 .Ql {=! Ns Ar macroname Ns }{/=! Ns Ar macroname Ns } , 701 where 702 .Ar macroname 703 is the name of the macro. 704 Anything between those two tags will then become the body of a macro. 705 Whenever 706 .Ql {= Ns Ar macroname Ns } 707 is subsequently encountered in the file, it will be replaced by the macro body. 708 Macro definitions can't be nested nor can they contain macro calls, and doing so 709 will produce an error. 710 Tags won't be processed within the body of a macro. 711 .It 712 .Tg Previous_Git_commit_information 713 .Sy Previous Git commit information . 714 Directive 715 .Ql {git\-log} 716 is converted into a div with the id 717 .Ql git-log 718 containing the information about the previous commit (as having information 719 about the current commit would be impossible). 720 .It 721 .Tg Subdirectory_inclusion 722 .Sy Subdirectory inclusion (blogging directive) . 723 The directive 724 .Bd -literal -offset Ds 725 .Pf { Ns Ic incdir Qo Ar dirname Qc Oo Ar num Oc Oo Cm = Ns Ar macroname Oc Oo Cm listonly Oc Ns } 726 .Ed 727 .Pf "(" Ar num , 728 .Ar macroname 729 and the literal 730 .Ql Cm listonly 731 are optional) will be expanded as follows: 732 .Bl -enum -offset Ds 733 .It 734 A 735 .Ql <ul class="incdir"> 736 tag will be inserted into the document instead of the directive. 737 .It 738 For every subdirectory of 739 .Ar dirname , 740 relative to current directory and up to 741 .Ar num 742 (if present) or 5 (if omitted) total subdirectories, a 743 .Ql <li> 744 tag will be inserted into the 745 .Ql ul 746 tag. 747 .Pp 748 If the parameter 749 .Cm listonly 750 was specified, a 751 .Ql <li> 752 tag will instead be inserted for every 753 .Pa .slw 754 file within each of the subdirectories, sorted in reverse lexicographical order. 755 In this case, each 756 .Ql <li> 757 will contain a permalink with a title preceded by a timestamp formatted 758 according to 759 .Va list_timestamp_format . 760 Title and date are read from each 761 .Pa .slw 762 file, as YAML variables 763 .Va title 764 and 765 .Va date . 766 For this case, processing of the 767 .Ic incdir 768 directive stops here. 769 .It 770 A 771 .Ql <details> 772 tag will be inserted into each 773 .Ql <li> 774 tag. 775 .It 776 Inside of the 777 .Ql <details> 778 tag, a 779 .Ql <summary> 780 tag will be inserted with the name of the subdirectory. 781 If 782 .Ar macroname 783 is present, the name of the subdirectory will be prepended with the body of a 784 macro 785 .Ar macroname 786 (for example, this can be used to include custom SVG markup as arrows). 787 .It 788 After 789 .Ql <summary> 790 tag, a 791 .Ql <div> 792 tag will be inserted into 793 .Ql <details> , 794 containing the concatenated output from processing each of the 795 .Pa .slw 796 files inside that subdirectory in reverse lexicographical order, in a manner 797 similar to the 798 .Ic include 799 directive. 800 (See 801 .Sx Includes 802 and 803 .Sx date , 804 .Sx ext-in-permalink , 805 .Sx permalink-url 806 variables.) 807 The output of each file will be surrounded by an 808 .Ql <article> 809 tag. 810 .El 811 .Pp 812 If the included file has the variable 813 .Va incdir-only-summary 814 set to 815 .Dq 1 , 816 only the text within the summary marks 817 .Pf "(" Ql /- 818 and 819 .Ql "-/" ) 820 will be output, and if the variable 821 .Va incdir-footer-permalink-text 822 is also set, 823 .Ql <footer> 824 element with a permalink to the article will be added after it. 825 Example: 826 .Pp 827 .Pf "(" Pa posts/blog-post.slw ) 828 .Bd -literal -offset Ds 829 --- 830 incdir-only-summary: 1 831 --- 832 833 /-This article is great!-/ The quick brown fox jumps over the lazy sleeping dog. 834 The quick brown fox jumps over the lazy sleeping dog. The quick brown fox jumps 835 over the lazy sleeping dog. The quick brown fox jumps over the lazy sleeping 836 dog. The quick brown fox jumps over the lazy sleeping dog. The quick brown fox 837 jumps over the lazy sleeping dog. 838 .Ed 839 .Pp 840 .Pf "(" Pa blog-index.slw ) 841 .Bd -literal -offset Ds 842 --- 843 incdir-footer-permalink-text: Click here! 844 --- 845 {incdir "."} 846 .Ed 847 .Pp 848 will produce 849 .Bd -literal -offset Ds 850 <!DOCTYPE html> 851 <html lang="en"> 852 <head> 853 <title></title> 854 <meta charset="utf-8"> 855 <meta name="viewport" content="width=device-width, initial-scale=1"> 856 <meta name="generator" content="slweb"> 857 </head> 858 <body> 859 <ul class="incdir"> 860 <li> 861 <details open> 862 <summary>posts</summary> 863 <div> 864 <article> 865 This article is great!<footer> 866 <a href="././posts/blog-post">Click here!</a> 867 </footer> 868 </article> 869 </div> 870 </details> 871 </li> 872 </ul> 873 </body> 874 </html> 875 .Ed 876 .Pp 877 for 878 .Pa blog-index.slw , 879 and 880 .Bd -literal -offset Ds 881 <!DOCTYPE html> 882 <html lang="en"> 883 <head> 884 <title></title> 885 <meta charset="utf-8"> 886 <meta name="viewport" content="width=device-width, initial-scale=1"> 887 <meta name="generator" content="slweb"> 888 </head> 889 <body> 890 891 <p>This article is great! The quick brown fox jumps over the lazy sleeping dog. 892 The quick brown fox jumps over the lazy sleeping dog. The quick brown fox jumps 893 over the lazy sleeping dog. The quick brown fox jumps over the lazy sleeping 894 dog. The quick brown fox jumps over the lazy sleeping dog. The quick brown fox 895 jumps over the lazy sleeping dog. 896 </body> 897 </html> 898 .Ed 899 .Pp 900 for 901 .Pa posts/blog-post.slw . 902 .It 903 .Tg TSV/CSV_templating 904 .Sy TSV/CSV templating . 905 Directive 906 .Bd -literal -offset Ds 907 .Pf { Ns Ic tsv Qo Ar tsvfile Qc Oo Ar iter Oc Ns }{/ Ns Ic tsv Ns } 908 .Ed 909 marks a template. 910 Whatever is between 911 .Ql {tsv} 912 and 913 .Ql {/tsv} 914 will be processed by 915 .Nm 916 and collected as a template. 917 Afterwards, file 918 .Pa tsvfile.tsv 919 will be read and for each of its lines (up to 920 .Ar iter , 921 if present) the collected template will be output, substituting each occurrence 922 of a register mark 923 .Ql $ Ns Ar n 924 (where 925 .Ar n 926 is between 1 and 9, inclusive) with the corresponding TSV field of the read 927 line. 928 .Pp 929 All of this applies to the similar 930 .Ql {csv} 931 directive for CSV files. 932 In the case of CSV files, they need to use semicolons 933 .Pf "(" Do ";" Dc Ns ) 934 or commas 935 .Pf "(" Do "," Dc Ns ) 936 as delimiters (or set 937 .Sx csv-delimiter 938 as a YAML variable in the calling 939 .Pa .slw 940 file) and double quotation marks 941 .Pf "(" Ql "\(dq" ) 942 as field boundaries. 943 First line in the TSV file is parsed as a header and associated with register 944 marks 945 .Ql $#1 946 to 947 .Ql $#9 . 948 The symbol 949 .Ql $ 950 is represented as 951 .Ql $$ . 952 Consequently, math modes (both inline and display) cannot be used within 953 templates. 954 .Pp 955 Parts of the template can be conditionally rendered by using the construct: 956 .Bd -literal -offset Ds 957 .No $? Ns Ar n 958 .No <!-- code to include if $ Ns Ar n No nonempty --> 959 $?! 960 .No <!-- code to include if $ Ns Ar n No empty --> 961 $?/ 962 .Ed 963 .Pp 964 where 965 .Ar n 966 is between 1 and 9, inclusive. 967 For example, having a file 968 .Pa sales.tsv : 969 .Bd -literal -offset Ds 970 Item Q1 2020 Q2 2020 Q3 2020 Q4 2020 971 Toothpick 15.2 12 10 972 Teapot 1.2 5 3.5 973 .Ed 974 .Pp 975 We can write 976 .Bd -literal -offset Ds 977 {tsv "sales"} 978 {.sales-segment} 979 $#1 {q}$1{/q} sales by quarter for the last year in 980 thousands of units sold (for $$) were as follows: 981 $?2{.q1}$2{/.q1}$?!{.q1 na}N/A{/.q1}$?/ 982 $?3{.q2}$3{/.q2}$?!{.q2 na}N/A{/.q2}$?/ 983 $?4{.q3}$4{/.q3}$?!{.q3 na}N/A{/.q3}$?/ 984 $?5{.q4}$5{/.q4}$?!{.q4 na}N/A{/.q4}$?/ 985 {/.sales-segment} 986 {/tsv} 987 .Ed 988 .Pp 989 to get: 990 .Bd -literal -offset Ds 991 <div class="sales-segment"> 992 Item <q>Toothpick</q> sales by quarter for the last year in 993 thousands of units sold (for $) were as follows: 994 <div class="q1">15.2</div> 995 <div class="q2">12</div> 996 <div class="q3 na">N/A</div> 997 <div class="q4">10</div> 998 </div> 999 1000 <div class="sales-segment"> 1001 Item <q>Teapot</q> sales by quarter for the last year in 1002 thousands of units sold (for $) were as follows: 1003 <div class="q1">1.2</div> 1004 <div class="q2 na">N/A</div> 1005 <div class="q3">5</div> 1006 <div class="q4">3.5</div> 1007 </div> 1008 .Ed 1009 .Pp 1010 TSV directives can't be nested and doing so will produce an error. 1011 .Pp 1012 The directives 1013 .Ql {csv\-count Qo Ar csvfile Qc Ns } 1014 and 1015 .Ql {tsv\-count Qo Ar tsvfile Qc Ns } 1016 output the number of 1017 .Dq records 1018 in the file 1019 .Pa csvfile.csv 1020 or 1021 .Pa tsvfile.tsv 1022 (number of lines minus one for the header row). 1023 No newline is output following the number. 1024 .El 1025 . 1026 .Ss Special YAML variables 1027 .Bl -bullet -width 1m 1028 .It 1029 .Va add-article-header . 1030 If set to 1031 .Dq 1 , 1032 title, date and header text at the beginning of the output body will be enclosed 1033 in a 1034 .Ql <header> 1035 tag. 1036 .It 1037 .Va add-figcaption . 1038 If set to 1039 .Dq 0 , 1040 .Ql <figure> 1041 and 1042 .Ql <figcaption> 1043 tags around images will not be added (otherwise they will by default, see 1044 .Sx Images Ns 1045 ). 1046 .It 1047 .Va add-footnote-div . 1048 If set to 1049 .Dq 1 , 1050 list of footnotes preceded by a horizontal rule will be surrounded with a div 1051 having the id 1052 .Dq footnotes 1053 (see 1054 .Sx Footnotes Ns 1055 ). 1056 .It 1057 .Va add-image-links . 1058 If set to 1059 .Dq 0 , 1060 links around images will not be added (otherwise they will by default, see 1061 .Sx Images Ns 1062 ). 1063 .It 1064 .Va author . 1065 If set, the contents of this variable will be added to the start of the output 1066 body (inside a 1067 .Ql <header> 1068 tag if it is set), surrounded by 1069 .Ql <address></address> . 1070 .It 1071 .Va canonical . 1072 Contents of this variable will be added as a value of a 1073 .Ql rel 1074 attribute for the 1075 .Ql <link rel="canonical"> 1076 tag. 1077 .It 1078 .Va csv-delimiter . 1079 Changes the delimiter used for 1080 .Pa .csv 1081 file parsing. 1082 By default, this will be a semicolon\ 1083 .Pf "(" Ns Ql ";" Ns 1084 ). 1085 See 1086 .Sx TSV/CSV templating . 1087 .It 1088 .Va date . 1089 If present, this variable, assumed to be in ISO\ 8601 UTC datetime format, will 1090 be parsed to determine the timestamp in permalinks generated by the 1091 .Ic incdir 1092 directive. 1093 The actual values used depend on the source\-level constants 1094 .Va article_timestamp_format 1095 (for 1096 .Ic incdir 1097 without the argument 1098 .Cm listonly ) 1099 and 1100 .Va list_timestamp_format 1101 (for 1102 .Ic incdir 1103 with the argument 1104 .Cm listonly Ns ). 1105 .It 1106 .Va ext-in-permalink . 1107 If set to 1108 .Dq 0 , 1109 permalinks generated by the 1110 .Ic incdir 1111 directive will not have the extension included in the 1112 .Cm href 1113 attribute. 1114 For example, instead of 1115 .Pa blog/2020/august.html , 1116 the resulting permalink will have 1117 .Pa blog/2020/august . 1118 .It 1119 .Va favicon-url . 1120 If present, this URL will be used as a favicon URL instead of the default, 1121 .Pa /favicon.ico . 1122 .It 1123 .Va feed , 1124 .Va feed-type , 1125 .Va feed-desc . 1126 If all are present, contents of those variables will be added as 1127 .Cm href , 1128 .Cm type 1129 and 1130 .Cm title 1131 attributes (respectively) to the 1132 .Ql <link rel="alternate"> 1133 tag in the page's 1134 .Ql <head> . 1135 .It 1136 .Va header-text . 1137 The contents of this variable will be added to the start of the output body 1138 (inside a 1139 .Ql <header> 1140 tag if it is set), preceeded by 1141 .Ql <p> . 1142 .It 1143 .Va image-file-prefix . 1144 If present, the value of 1145 .Cm src 1146 attribute will be appended to the contents of this variable, with path separator 1147 added as necessary, when determining the actual file path to pass to the 1148 .Xr identify 1 1149 command. 1150 Otherwise, 1151 .Cm src 1152 is appended to the base directory, specified by the parameter 1153 .Fl d 1154 (or 1155 .Fl \-basedir Ns ), 1156 and defaulting to 1157 .Dq .\& . 1158 .It 1159 .Va incdir-footer-permalink-text . 1160 If set, and the variable 1161 .Va incdir-only-summary 1162 is set to 1163 .Dq 1 , 1164 when the file where this variable is set is included by the 1165 .Ql {incdir} 1166 directive, 1167 .Ql <footer> 1168 tag containing the permalink to the calling file will be appended to the text 1169 between the summary marks 1170 .Ql /- 1171 and 1172 .Ql -/ . 1173 .It 1174 .Va incdir-only-summary . 1175 If set to 1176 .Dq 1 , 1177 when the file where this variable is set is included by the 1178 .Ql {incdir} 1179 directive, only the text within the summary marks 1180 .Ql /- 1181 and 1182 .Ql -/ 1183 will be output. 1184 .It 1185 .Va inline-stylesheet . 1186 The contents of this variable will be treated as a CSS file name to be included 1187 inline in the header using the 1188 .Ql <style> 1189 tag. 1190 You can add more than one 1191 .Va inline-stylesheet 1192 declaration per 1193 .Pa .slw 1194 file. 1195 .It 1196 .Va lang . 1197 Contents of this variable will be used for the 1198 .Cm lang 1199 attribute of the 1200 .Ql <html> 1201 tag. 1202 .It 1203 .Va link-prefix . 1204 This variable specifies the prefix which will be prepended to relative URLs in 1205 links. 1206 Final slash needs to be included if 1207 .Va link-prefix 1208 is a complete path. 1209 .It 1210 .Va meta . 1211 Contents of this variable is treated as a filename specifying the TSV file 1212 containing a list of values to be inserted into meta tags. 1213 The first row of this TSV file is treated as the header row and ignored. 1214 First column in this TSV file contains the meta variable names, and the second 1215 column contains meta variable values. 1216 For each row, a 1217 .Ql <meta name= Ns Qo Ar firstcol Qc content= Ns Qo Ar secondcol Qc Ns > 1218 is inserted, where 1219 .Ar firstcol 1220 is the first column, and 1221 .Ar secondcol 1222 is the second column. 1223 If the values in the second column are surrounded with percent signs 1224 .Pf "(" Ns Ql % Ns 1225 ), the value between them is treated as the name of the 1226 YAML variable to insert. 1227 For example, having the file 1228 .Pa m.tsv : 1229 .Bd -literal -offset Ds 1230 Name Content 1231 og:url %canonical% 1232 .Ed 1233 .Pp 1234 and 1235 .Bd -literal -offset Ds 1236 --- 1237 canonical: https://example.com/ 1238 meta: m.tsv 1239 --- 1240 .Ed 1241 .Pp 1242 in the 1243 .Pa .slw 1244 file, a 1245 .Bd -literal -offset Ds 1246 <meta name="og:url" content="https://example.com/"> 1247 .Ed 1248 .Pp 1249 line will be added to the output. 1250 .It 1251 .Va permalink-url . 1252 If present, this URL will completely replace the link used in the 1253 .Cm href 1254 attribute of permalinks generated by the 1255 .Ic incdir 1256 directive. 1257 This variable is more useful in individual 1258 .Pa .slw 1259 files inside the subdirectories of the 1260 .Ar dirname 1261 provided to the 1262 .Ic incdir 1263 directive. 1264 .It 1265 .Va site-desc . 1266 The contents of this variable will be inserted as the value of the 1267 .Cm content 1268 attribute of the 1269 .Ql <meta name="description"> 1270 tag. 1271 .It 1272 .Va site-name . 1273 The contents of this variable will be inserted inside the 1274 .Ql <title></title> 1275 tags. 1276 .It 1277 .Va stylesheet . 1278 The contents of this variable will be treated as a CSS file name to be included 1279 using the 1280 .Ql <link rel="stylesheet"> 1281 tag. 1282 You can add more than one 1283 .Va stylesheet 1284 declaration per 1285 .Pa .slw 1286 file. 1287 .It 1288 .Va title . 1289 If present, contents of this variable will be prepended to the body (inside a 1290 .Ql <header> 1291 tag if it is set) as a heading with the level determined by the 1292 .Va title-heading-level 1293 variable, defaulting to 2. 1294 .Pf "(" Ns Ql title: Some title 1295 becomes 1296 .Ql <h2>Some title</h2> Ns 1297 ). 1298 .It 1299 .Va title-heading-level . 1300 See 1301 .Sx title . 1302 .El 1303 . 1304 .Ss Special macros 1305 .Bl -bullet -width 1m 1306 .It 1307 .Ic permalink . 1308 If present, the body of this macro will be inserted into permalinks generated by 1309 the 1310 .Ic incdir 1311 directive, similar to the macro\-form of links. 1312 .El 1313 . 1314 .Sh EXIT STATUS 1315 .Ex -std 1316 .Pp 1317 For errors caused by the unsuccessful calls to libc functions setting 1318 .Va errno , 1319 that value is returned as the exit status. 1320 Otherwise, the exit status is one of the following: 1321 .Bl -tag -width Ds -offset indent -compact 1322 .It Li 201 1323 Argument to a function is not numeric. 1324 .It Li 202 1325 Argument to a function is not beginning and ending with double quotes (not a 1326 .Do string Dc Ns ). 1327 .It Li 203 1328 Command line argument is not recognized. 1329 .It Li 204 1330 Conditional mark is not recognized. 1331 .It Li 205 1332 Empty conditional mark is before or without the corresponding nonempty 1333 conditional. 1334 .It Li 206 1335 Header register mark is not recognized. 1336 .It Li 207 1337 Register mark is not recognized. 1338 .It Li 208 1339 Parsing arguments failed when formatting date. 1340 .It Li 209 1341 Macro is not defined. 1342 .It Li 210 1343 There are nested CSV/TSV directives. 1344 .It Li 211 1345 There are nested macro definitions. 1346 .It Li 212 1347 There are nested formulas. 1348 .It Li 213 1349 No arguments are supplied to a directive or to a command line argument which 1350 requires at least one. 1351 .It Li 214 1352 The function 1353 .Xr popen 3 1354 (which doesn't set 1355 .Va errno ) 1356 failed. 1357 .It Li 215 1358 The function 1359 .Xr scandir 3 1360 (which doesn't set 1361 .Va errno ) 1362 failed. 1363 .El 1364 . 1365 .Sh EXAMPLES 1366 Given the file 1367 .Pa index.slw 1368 in the current directory: 1369 .Bd -literal -offset Ds 1370 --- 1371 site-name: Test website 1372 site-desc: My first website in slweb 1373 --- 1374 1375 {main} 1376 # Hello world 1377 1378 This is an _example_ of a statically generated HTML. 1379 1380 {/main} 1381 .Ed 1382 .Pp 1383 after using the command: 1384 .Dl $ slweb index.slw > index.html 1385 file 1386 .Pa index.html 1387 contains: 1388 .Bd -literal -offset Ds 1389 <!DOCTYPE html> 1390 <html lang="en"> 1391 <head> 1392 <title>Test website</title> 1393 <meta charset="utf-8"> 1394 <meta name="description" content="My first website in slweb"> 1395 <meta name="viewport" content="width=device-width, initial-scale=1"> 1396 <meta name="generator" content="slweb"> 1397 </head> 1398 <body> 1399 1400 <main> 1401 <h1>Hello world</h1> 1402 1403 <p>This is an <em>example</em> of a statically generated HTML. 1404 1405 </main> 1406 </body> 1407 </html> 1408 .Ed 1409 . 1410 .Sh DIAGNOSTICS 1411 Error messages output by 1412 .Nm 1413 are in the format 1414 .Bd -ragged -offset Ds 1415 .Nm : Ns 1416 .Ar filename : Ns Ar lineno : Ns Ar colno : Ns Ar func : Ns 1417 .Ar source : Ns Ar line : Ns Ar msg 1418 .Ed 1419 .Pp 1420 where the 1421 .Ar filename 1422 is the name of the input file or 1423 .Ql (init/stdin) 1424 when no input file is specified or the error happened early on during 1425 initialization, 1426 .Ar lineno 1427 and 1428 .Ar colno 1429 are the line and column numbers in the input file where the error occured. 1430 The arguments 1431 .Ar func , 1432 .Ar source 1433 and 1434 .Ar line 1435 the function, filename and line number in the source code file. 1436 .Pp 1437 When the error is caused by an error in the libc function which sets 1438 .Va errno , 1439 .Nm 1440 calls 1441 .Xr perror 3 1442 prior to outputting an error message in the above format. 1443 . 1444 .Sh SEE ALSO 1445 .Xr sed 1 1446 . 1447 .Sh AUTHORS 1448 .An Strahinya Radich Aq Mt sr@strahinja.org , 1449 2020\-2026 1450 . 1451 .Sh BUGS 1452 Bugs can be reported using the ticket tracker at: 1453 .Lk https://\:todo.sr.ht/\:~strahinja/\:slweb 1454 . 1455 .Ss Known limitations 1456 The limitation of Markdown is that there is no clear way to determine where the 1457 paragraph inside a tag should begin and end. 1458 Before the addition of 1459 .Sx Break marks 1460 and the change of behavior of 1461 .Nm 1462 to not output ending 1463 .Ql </p> 1464 tags, without adding blank lines or using the 1465 .Ql {p}{/p} 1466 notation, 1467 .Ql <p></p> 1468 tags in the output would be intertwined together with other tags. 1469 For example, the code 1470 .Bd -literal -offset Ds 1471 {tag} 1472 First paragraph 1473 1474 Second paragraph 1475 {/tag} 1476 .Ed 1477 .Pp 1478 would produce 1479 .Bd -literal -offset Ds 1480 <tag> 1481 First paragraph 1482 1483 <p>Second paragraph 1484 </tag></p> 1485 .Ed 1486 .Pp 1487 One could suppress the paragraph starting/ending tags by prepending blank lines 1488 with a backslash, like this: 1489 .Bd -literal -offset Ds 1490 {tag} 1491 First paragraph 1492 \e 1493 Second paragraph 1494 {/tag} 1495 .Ed 1496 .Pp 1497 which would produce 1498 .Bd -literal -offset Ds 1499 <tag> 1500 First paragraph 1501 1502 Second paragraph 1503 </tag> 1504 .Ed 1505 .Pp 1506 Adding blank lines was another option if paragraphs were desired: 1507 .Bd -literal -offset Ds 1508 {tag} 1509 1510 First paragraph 1511 1512 Second paragraph 1513 1514 {/tag} 1515 .Ed 1516 .Pp 1517 would produce 1518 .Bd -literal -offset Ds 1519 <tag> 1520 <p>First paragraph</p> 1521 1522 <p>Second paragraph</p> 1523 </tag> 1524 .Ed