# Test page --- This is just a test page so I can check if anything breaks when I update the code / CSS. Mainly based on the [djot syntax reference][]. [djot syntax reference]: https://htmlpreview.github.io/?https://github.com/jgm/djot/blob/master/doc/syntax.html \ # Djot Syntax - Inline --- Syntax that can be included within a block. ## Text styling - Emphasized inline content is delimited by \_ characters. Strong emphasis is delimited by \* characters. - Verbatim content begins with a string of consecutive backtick characters (\`) and ends with an equal-lengthed string of consecutive backtick characters. Material between the backticks is treated as verbatim text (backslash escapes don't work there). - Inline content between \{\= and \=\} will be treated as highlighted text (in HTML, ). Note that the \{ and \} are mandatory. - Superscript is delimited by \^ characters, subscript by \~. - To mark inline text as inserted, use \{\+ and \+\}. To mark it as deleted, use \{\- and \-\}. The \{ and \} are mandatory. :::: example-block ``` *strong* text _emphasized_ text `verbatim` text {=highlighted=} text ^superscript^ text ~subscript~ text {-deleted-} text {+inserted+} text ``` ::: *strong* text _emphasized_ text `verbatim` text {=highlighted=} text ^superscript^ text ~subscript~ text {-deleted-} text {+inserted+} text :::: ## Links There are two kinds of links, inline links and reference links. Both kinds start with the link text (which may contain arbitrary inline formatting) inside [ ... ] delimiters. - A URL or email address that is enclosed in \<...\> will be hyperlinked. The content between pointy braces is treated literally (backslash-escapes may not be used). - Inline links then contain the link destination (URL) in parentheses. There should be no space between the ] at the end of the link text and the open \( defining the link destination. - Reference links use a reference label in square brackets, instead of a destination in parentheses. This must come immediately after the link text. If the label is empty, then the link text will be taken to be the reference label as well as the link text. - A footnote reference is \^ \+ the reference label in square brackets. :::: example-block ``` Autolinks look like this: Inline links look like this: [link](www.example.com) Reference links look like this: [link][ref name] [ref name]: www.example.com Reference links can also look like this: [link][] [link]: www.example.com Footnote references look like: [^foo] [^foo]: And here is the footnote with two paragraphs. Second paragraph must be indented, at least in the first line. ``` ::: Autolinks look like this: Inline links look like this: [link](www.example.com) Reference links look like this: [link][ref name] [ref name]: www.example.com Reference links can also look like this: [link][] [link]: www.example.com Footnote references look like: [^foo] [^foo]: And here is the footnote with two paragraphs. Second paragraph must be indented, at least in the first line. :::: ## Images Images work just like links, but have a \! prefixed. As with links, both inline and reference variants are possible. :::: example-block ``` Inline images look like: ![Profile](/images/profile.png){style="width: 3rem"} Reference images look like: ![Profile][]{style="width: 3rem"} [Profile]: /images/profile.png ``` ::: Inline images look like: ![Profile](/images/profile.png){style="width: 3rem"} Reference images look like: ![Profile][]{style="width: 3rem"} [Profile]: /images/profile.png :::: ## Math To include LaTeX math, put the math in a verbatim span and prefix it with \$ (for inline math) or \$\$ (for display math): :::: example-block ``` Einstein derived $`e=mc^2`. Pythagoras proved $$` x^n + y^n = z^n ` ``` ::: Einstein derived $`e=mc^2`. Pythagoras proved $$` x^n + y^n = z^n ` :::: ## Line Breaks Line breaks in inline content are treated as "soft" breaks; they may be rendered as spaces, or (in contexts where newlines are treated semantically like spaces, such as HTML) as newlines. To get a hard line break (of the sort represented by HTML's
), use backslash \+ newline: :::: example-block ``` This is a soft break and this is a hard\ break. \ This is after a hard break. ``` ::: This is a soft break and this is a hard\ break. \ This is after a hard break. :::: ## Symbols Surrounding a word with \: signs creates a "symbol," which by default is converted to emojis. :::: example-block ``` My reaction is :+1: :smiley:. ``` ::: My reaction is :+1: :smiley:. :::: ## Attributes and Span Attributes are put inside curly braces and must immediately follow the inline element to which they are attached (with no intervening whitespace). Attribute specifiers may contain line breaks. Attribute specifiers may be "stacked," in which case they will be combined. Inside the curly braces, the following syntax is possible: - `.foo` specifies foo as a class. Multiple classes may be given in this way; they will be combined. - `#foo` specifies foo as an identifier. An element may have only one identifier; if multiple identifiers are given, the last one is used. - `key="value"` or key=value specifies a key-value attribute. Quotes are not needed when the value consists entirely of ASCII alphanumeric characters or \_ or \: or \-. Backslash escapes may be used inside quoted values. - `%` begins a comment, which ends with the next `%` or the end of the attribute (\}). - Text in square brackets that is not a link or image and is followed immediately by an attribute is treated as a generic span. :::: example-block ``` An attribute on _emphasized text_{#foo .bar .baz key="my value"} Comments {% such as this %} won't show up in the final text. It can be helpful to [read the manual]{style="color: red;"}. ``` ::: An attribute on _emphasized text_{#foo .bar .baz key="my value"} Comments {% such as this %} won't show up in the final text. It can be helpful to [read the manual]{style="color: red;"}. :::: \ # Djot Syntax - Block --- Blocks contain inline content. Indentation is only significant for list item or footnote nesting. Block-level items should be separated from one another by blank lines. There are some cases in which two block-level elements can be adjacent—e.g., a thematic break or fenced code block can be directly followed by a paragraph. ## Paragraph A paragraph is a sequence of nonblank lines that does not meet the condition for being one of the other block-level elements. A paragraph ends with a blank line or the end of the document. ## Heading A heading starts with a sequence of one or more # characters, followed by whitespace. The number of # characters defines the heading level. The following text is parsed as inline content. The heading text may spill over onto following lines, which may optionally be preceded by the same number of # characters. Identifiers are added automatically to any headings that do not have explicit identifiers attached to them. The identifier is formed by taking the textual content of the heading, removing punctuation (other than _ and -), replacing spaces with -, and if necessary for uniqueness, adding a numerical suffix. However, for the most part you do not need to know the identifiers that are assigned to headings, because implicit link references are created for all headings. :::: example-block ``` #### A level _four_ heading! #### A heading that #### takes up three lines See the [Heading][]. ``` ::: #### A level _four_ heading! #### A heading that #### takes up three lines See the [Heading][]. :::: ## Block quote A block quote is a sequence of lines, each of which begins with >, followed either by a space or by the end of the line. The contents of the block quote (minus initial >) are parsed as block-level content. It's possible to "lazily" omit the > prefixes from regular paragraph lines inside the block quote, except in front of the first line of a paragraph. :::: example-block ``` > This is a block quote. > > 1. with a > 2. list in it. > This is a block quote. ``` ::: > This is a block quote. > > 1. with a > 2. list in it. > This is a block quote. :::: ## Lists A list is simply a sequence of list items of the same type. Changing ordered list style or bullet will stop one list and start a new one. A list is classed as tight if it does not contain blank lines between items, or between blocks inside an item, otherwise it's loose. The start number of an ordered list will be determined by the number of its first item. The numbers of subsequent items are irrelevant. A list item consists of a list marker followed by a space (or a newline) followed by one or more lines, indented relative to the list marker. Indentation may be "lazily" omitted on paragraph lines following the first line of a paragraph. :::: example-block ``` 1. This is a list item. > containing a block quote 42. loose list indented 42. loose list indented 2. The next tight item 4. The next tight item 1) The next tight item (style change) - [ ] Task item 1 - [x] Task item 2 - [ ] Indented task item 1 - [X] Indented task item 2 - [ ] Task item 3 : Hip an angled obstacle skateboarders use to perform tricks to be cool ``` ::: 1. This is a list item. > containing a block quote 42. loose list indented 42. loose list indented 2. The next tight item 4. The next tight item 1) The next tight item (style change) - [ ] Task item 1 - [x] Task item 2 - [ ] Indented task item 1 - [X] Indented task item 2 - [ ] Task item 3 : Hip an angled obstacle skateboarders use to perform tricks to be cool :::: The following basic types of list markers are available: | Marker | List type | | ------ | --------- | | - | bullet | | + | bullet | | * | bullet | | 1. | ordered, decimal-enumerated, followed by period | | 1) | ordered, decimal-enumerated, followed by parenthesis | | (1) | ordered, decimal-enumerated, enclosed in parentheses | | a. | ordered, lower-alpha-enumerated, followed by period | | a) | ordered, lower-alpha-enumerated, followed by parenthesis | | (a) | ordered, lower-alpha-enumerated, enclosed in parentheses | | A. | ordered, upper-alpha-enumerated, followed by period | | A) | ordered, upper-alpha-enumerated, followed by parenthesis | | (A) | ordered, upper-alpha-enumerated, enclosed in parentheses | | i. | ordered, lower-roman-enumerated, followed by period | | i) | ordered, lower-roman-enumerated, followed by parenthesis | | (i) | ordered, lower-roman-enumerated, enclosed in parentheses | | I. | ordered, upper-roman-enumerated, followed by period | | I) | ordered, upper-roman-enumerated, followed by parenthesis | | (I) | ordered, upper-roman-enumerated, enclosed in parentheses | | : | definition | | - [ ] | task unchecked | | - [x] | task checked (lower) | | - [X] | task checked (upper) | ## Code block A code block starts with a line of three or more consecutive backticks, optionally followed by a language specifier, but nothing else. (The language specifier may optionally be preceded and/or followed by whitespace.) The code block ends with a line of backticks equal or greater in length to the opening backtick “fence,” or the end of the document or enclosing block, if no such line is encountered. Its contents are interpreted as verbatim text. If the contents contain a line of backticks, be sure to select a longer string of backticks to use as the “fence”: :::: example-block ```` ``` This is a verbatim block with no title or line numbers. | Name | Type | Params ----------------------------------- 0 | model | Fontogen | 73.7 M ----------------------------------- 73.7 M Trainable params 0 Non-trainable params 73.7 M Total params 294.728 Total estimated model params size (MB) ``` ```` ::: ``` This is a verbatim block with no title or line numbers. | Name | Type | Params ----------------------------------- 0 | model | Fontogen | 73.7 M ----------------------------------- 73.7 M Trainable params 0 Non-trainable params 73.7 M Total params 294.728 Total estimated model params size (MB) ``` :::: :::: example-block ```` ```python # Python code. It should allow horizontal scrolling. def generate_html(self): result = [] current_node = self.html_tree_root result = self.generate_html_helper(result, current_node, -1); result = self.generate_html_helper(result, current_node, -1); return '\n'.join(result) ``` ```` ::: ```python # Python code. It should allow horizontal scrolling. def generate_html(self): result = [] current_node = self.html_tree_root result = self.generate_html_helper(result, current_node, -1); result = self.generate_html_helper(result, current_node, -1); return '\n'.join(result) ``` :::: ## Thematic Break A line containing three or more * or - characters, and nothing else (except spaces or tabs) is treated is a thematic break (
in HTML). Unlike in Markdown, a thematic break may be indented: :::: example-block ``` Then they went to sleep. * * * * When they woke up, ... --- ``` ::: Then they went to sleep. * * * * When they woke up, ... --- :::: ## Raw Block A code block with =FORMAT where the language specification would normally go is interpreted as raw content in FORMAT and will be passed through verbatim to output in that format. For example: :::: example-block ```` ```=html

emphasized text

strong emphasis

``` ```` ::: ```=html

emphasized text

strong emphasis

``` :::: ## Div A div begins with a line of three or more consecutive colons, optionally followed by white space and a class name (but nothing else). It ends with a line of consecutive colons at least as long as the opening fence, or with the end of the document or containing block. ::::: example-block ``` ::: special-div Here is a paragraph. And here is another. ::: ``` :::: ::: special-div Here is a paragraph. And here is another. ::: ::::: ## Pipe table A pipe table consists of a sequence of rows. Each row starts and ends with a pipe character (|) and contains one or more cells separated by pipe characters. A separator line is a row in which every cell consists of a sequence of one of more - characters, optionally prefixed and/or suffixed by a : character. When a separator line is encountered, the previous row is treated as a header, and alignments on that row and any subsequent rows are determined by the separator line (until a new header is found). The separator line itself does not contribute a row to the parsed table. :::: example-block ``` | fruit | price | |--------|------:| | apple | 4 | | banana | 10 | ``` ::: | fruit | price | |--------|------:| | apple | 4 | | banana | 10 | :::: Column alignments are determined by the separator line in the following way: - if the line of - begins with a : and does not end with one, the column is left-aligned - if it ends with : and does not begin with one, the column is right-aligned - if it both begins and ends with :, the column is center-aligned - if it neither begins nor ends with :, the column is default-aligned In the below example the row with a and b is a header, with the left column default-aligned and the right column center-aligned. The next real row, containing 1 and 2, is also a header, in which the left column is left-aligned and the right column is right-aligned. This alignment is also applied to the row that follows, containing 3 and 4. A table need not have a header: just omit any separator lines, or (if you need to specify column alignments) begin with a separator line Contents of table cells are parsed as inlines. Block-level content is not possible in pipe table cells. Djot is smart enough to recognize backslash-escaped pipes and pipes in verbatim spans; these do not count as cell separators: You can attach a caption to a table. The caption can come directly after the table, or there can be an intervening blank line. :::: example-block ``` | a | b | |----|:--:| | 1 | 2 | |:---|---:| | 3 | 4 | |:--|---:| | x | 2 | | just two \| `|` | cells in this table | ^ This is the caption. It can contain _inline formatting_ and can extend over multiple lines, provided they are indented relative to the `^`. ``` ::: | a | b | |----|:--:| | 1 | 2 | |:---|---:| | 3 | 4 | | a | b | |:--|---:| | x | 2 | | just two \| `|` | cells in this table | ^ This is the caption. It can contain _inline formatting_ and can extend over multiple lines, provided they are indented relative to the `^`. :::: ## Block attributes To attach attributes to a block-level element, put the attributes on the line immediately before the block. Block attributes have the same syntax as inline attributes, but if they don’t fit on one line, subsequent lines must be indented. Repeated attribute specifiers can be used, and the attributes will accumulate. :::: example-block ``` {#water} {.very-important .large style="color: green;"} Don't forget to turn off the water! {source="Iliad"} > Sing, muse, of the wrath of Achilles ``` ::: {#water} {.very-important .large style="color: green;"} Don't forget to turn off the water! {source="Iliad"} > Sing, muse, of the wrath of Achilles :::: \ # Custom Syntax --- The syntax in this section are custom extensions for djot, only supported on this site. \ ## Center Div Center the div content horizontally and vertically :::: example-block ``` ::: center A paragraph ![Profile](/images/profile.png){style="width: 10rem"} ::: ``` ::: center A paragraph ![Profile](/images/profile.png){style="width: 10rem"} :::: ## Side-by-Side Div Display the contents horizontally. It may contain more than two children. ::::: example-block ``` ::: side-by-side This paragraph is on the left. This paragraph is on the right. ::: ``` :::: ::: side-by-side This paragraph is on the left. This paragraph is on the right. ::: ::::: ## Example Div Used to make this page. It's basically the side-by-side div with some styling. :::::: example-block ```` :::: example-block ``` raw text ``` ::: processed text :::: ```` ::::: :::: example-block ``` raw text ``` ::: processed text :::: :::::: ## Special Div These are based on [GitHub alerts][]. They allow for some informational content to be more prominent on the page. [GitHub alerts]: https://github.com/orgs/community/discussions/16925 :::::: example-block ``` :::: note Highlights information that users should take into account, even when skimming. :::: :::: tip Optional information to help a user be more successful. :::: :::: important Crucial information necessary for users to succeed. :::: :::: warning Critical content demanding immediate user attention due to potential risks. :::: :::: caution Negative potential consequences of an action. Content stacks vertically. Crazy? I was crazy once. They locked me in a room. A rubber room filled with rats. And rats make me crazy. Crazy? I was crazy once. They locked me in a room. A rubber room filled with rats. And rats make me crazy... :::: ``` ::::: :::: note Highlights information that users should take into account, even when skimming. :::: :::: tip Optional information to help a user be more successful. :::: :::: important Crucial information necessary for users to succeed. :::: :::: warning Critical content demanding immediate user attention due to potential risks. :::: :::: caution Negative potential consequences of an action. Content stacks vertically. Crazy? I was crazy once. They locked me in a room. A rubber room filled with rats. And rats make me crazy. Crazy? I was crazy once. They locked me in a room. A rubber room filled with rats. And rats make me crazy... :::: :::::: ## Tabs Div Each element is grouped into a set of tabs, with only the active tabs content on display. Normally the first tab is active when a page is loaded, unless the `{.active}` attribute is present above a tabs name. The first title level found is considered the base title. Anything equal to it or above is considered another tab. ::::: example-block ``` ::: tabset ### One Thing Sentences. {.active} ### Context Other sentences. ::: ``` :::: ::: tabset ### One Thing Sentences. {.active} ### Context Other sentences. ::: ::::: ## Captions Captions can now be attached to anything. This is mainly useful for pictures. :::: example-block ``` ![Profile](/images/profile.png){style="width: 10rem"} ^ *Figure 1:* A demo image ``` ::: center ![Profile](/images/profile.png){style="width: 10rem"} ^ *Figure 1:* A demo image :::: ## Enhanced Code Blocks Along with syntax highlighting, you can also display line numbers (arbitrary offset), a title, and highlight lines for emphasis. Attributes: - `title`: Defaults to ` language`. - `lineno`: The starting line number. Starts at one by default. Set to zero to not display them. - `hl_lines`: comma separated list of lines to highlight (first line is one). :::: example-block ````` {title="" lineno=122 hl_lines="1,3"} ```python # Starts at line 122, no title, highlights lines 122 and 124. def generate_html(self): result = self.generate_html_helper(self.html_tree_root) return '\n'.join(result) ``` {lineno=0 title="Not Python"} ```python # No line numbers, has the title "Not Python" def generate_html(self): result = self.generate_html_helper(self.html_tree_root) return '\n'.join(result) ``` ````lua -- Has line numbers and an automatic title num = 42 -- Numbers can be integer or floating point. s = 'walternate' -- Immutable strings like Python. t = nil -- Undefines t; Lua has garbage collection. -- Blocks are denoted with keywords like do/end: while num < 50 do num = num + 1 -- No ++ or += type operators. end ```` ````` ::: {title="" lineno=122 hl_lines="1,3"} ```python # Starts at line 122, no title, highlights lines 122 and 124. def generate_html(self): result = self.generate_html_helper(self.html_tree_root) return '\n'.join(result) ``` {lineno=0 title="Not Python"} ```python # No line numbers, has the title "Not Python" def generate_html(self): result = self.generate_html_helper(self.html_tree_root) return '\n'.join(result) ``` ````lua -- Has line numbers and an automatic title num = 42 -- Numbers can be integer or floating point. s = 'walternate' -- Immutable strings like Python. t = nil -- Undefines t; Lua has garbage collection. -- Blocks are denoted with keywords like do/end: while num < 50 do num = num + 1 -- No ++ or += type operators. end ```` :::: ## Scripting Raw Blocks For the javascript block it simply wraps the code in script tags (specifying javascript). For pyscript, it'll handle importing the pyscript core (only once). :::: example-block ```` ```=pyscript from pyscript import display display("Hello there") ``` ```=javascript document.currentScript.outerHTML = "General Kenobi"; ``` ```` ::: ```=pyscript from pyscript import display display("Hello there") ``` ```=javascript document.currentScript.outerHTML = "General Kenobi"; ``` :::: ## Index List A special styling where the list uses lines instead of dots for list items. :::: example-block ``` {.index-list} - First item - Second item ``` ::: {.index-list} - First item - Second item :::: ## Mermaid Mermaid diagrams can be used in code blocks, similar to other programs. :::: example-block ```` ```mermaid graph TD A[Client] --> B[Load Balancer] B --> C[Server01] B --> D[Server02] ``` ```` ::: ```mermaid graph TD A[Client] --> B[Load Balancer] B --> C[Server01] B --> D[Server02] ``` :::: ## TOC Macro Macros allow for generated text to be inserted. They follow the syntax `:{#name argument=value ... argument=value}`. This macro will be expanded into a collapsible table of contents for the page. :::: example-block ``` :{#toc} ``` ::: :{#toc} :::: ## Include Macro Includes an entire file in another. This happens during file processing. When an include macro is encountered, it'll read the file in the path and parse it from text. The result is placed directly into the processed tree where the macro was. :::: example-block ``` :{#include path="include_example.dj"} ``` ::: :{#include path="include_example.dj"} :::: ## Metadata Macro Similar to [frontmatter][], but it isn't parsed separate from the document. This macro defines some document properties. It can appear anywhere (duplicates overwrite each other). [frontmatter]: https://docs.github.com/en/contributing/writing-for-github-docs/using-yaml-frontmatter Attributes: - `title`: The tab title. Defaults to the first title block. - `file-type`: Used to identify `html` or `xslt` files. Defaults to `html`. This is mainly used for the RSS feed style. - `banner`: The image to use at the top. Defaults to no image being displayed. :::: example-block ``` :{#metadata title="Syntax" file_type=html banner="blue-and-white-planet-display.jpg" } ``` ::: :{#metadata title="Syntax" file_type="html" banner="blue-and-white-planet-display.jpg" } :::: ## Post List Macro Expands to a list (sorted by date and series) of all posts on the site. :::: example-block ``` :{#post-list} ``` ::: :{#post-list} :::: ```=html ``` ```=javascript class Scroller { static init() { if(document.querySelector('.tocLinks')) { this.tocLinks = document.querySelectorAll('.tocLinks a'); this.tocLinks.forEach(link => link.classList.add('transition', 'duration-200')) this.headers = Array.from(this.tocLinks).map(link => { try { return document.querySelector(`#${link.href.split('#')[1]}`); } catch (ignore) { // Invalid header } }).filter(x => x); this.ticking = false; window.addEventListener('scroll', (e) => { this.onScroll() }) this.onScroll() } } static onScroll() { if(!this.ticking) { // If no scroll is being processed requestAnimationFrame(this.update.bind(this)); this.ticking = true; } } static update() { this.activeHeader ||= null; let activeIndex = this.headers.findIndex((header) => { return header.getBoundingClientRect().top > 1; }); if(activeIndex == -1) { // No header on screen, we're at the bottom activeIndex = this.headers.length - 1; } else if(activeIndex > 0) { activeIndex--; } let active = this.headers[activeIndex]; if(active !== this.activeHeader) { this.activeHeader = active; this.tocLinks.forEach(link => link.classList.remove('text-active')); this.tocLinks[activeIndex].classList.add('text-active'); } this.ticking = false; } } document.addEventListener('DOMContentLoaded', function(e) { Scroller.init(); }) ```