]> Lady’s Gitweb - LesML/commitdiff
New block behaviour and repository layout
authorLady <redacted>
Tue, 31 Mar 2026 01:28:11 +0000 (21:28 -0400)
committerLady <redacted>
Tue, 31 Mar 2026 02:11:44 +0000 (22:11 -0400)
This commit makes extremely breaking changes to the block‐level
  semantics of the language, effectively rewriting those aspects of
  parsing from scratch.
At the same time, it restructures the repository and adds test cases.
Commits (and tags) prior to this commit have been redone with
  Les·M·L‐format commit messages, and the repository now uses Sha·256
  hashes rather than Sha·1.

One could consider this a “version 2” of the Les·M·L format, but it is
  the softest of reboots:
Most files will continue to produce more·or·less exactly the same
  result after only a replacement of `#!lesml´ with `#?lesml´.
(There are some negligible differences in whitespace handling.)

The major cases where this is ⹐not⹑ true are those of blockquotes,
  footers, and continuations.
The concepts of bracketed and quoted paragraphs have been removed and
  footers and blockquotes are now ordinary block types alongside
  sections and list items.
Blocks now have a “level”, indicated by the number of leading `⋮´
  characters, and blocks of higher level are nested inside preceding
  ones of lower level.
This makes the existing continuation behaviour more consistent and
  makes the language more flexible.
The character `⋮´ is used instead of `⋯´ because it is semantically
  more accurate and the latter can also make up horizontal rules.

Multiple block sigils can now be used together to create deeply nested
  block structures that an equal number of continuation symbols are
  used to continue.
For example, a leading `» • •´ introduces a list inside a list inside a
  blockquote, and `⋮ ⋮ •´ introduces a second list item in the nested
  list.

The higher‐level unordered list characters `◦▪⁃´ are supported only as
  the first block sigils after any continuation symbols.
They are simply a shorthand for `⋮ •´, `⋮ ⋮ •´, and `⋮ ⋮ ⋮ •´,
  respectively.
The ordered list characters have been replaced by a single `№´.

Preformatted text requires the same prefix on each line.
The prefix, which begins with any continuation characters or block
  sigils, can end in one of three ways :⁠—

№ With a pipe, a syntax name, and a dollar sign, such as `|sh$´.
The syntax name can consist only of Ascii lowercase letters, numbers,
  slashes, dots, and hyphen dashes and identifies the preformatted text
  as code in the corresponding language.
The semantics of syntax names are left undefined and up to profiles or
  applications to determine.

№ With a pipe and a dollar sign with nothing inbetween.
In this case, the preformatted text is code of an unspecified syntax.

№ With a pipe only.
In this case, the text is preformatted, but not code.

Footnote references now have the format `[^fn_id]´ and the
  corresponding footnotes `^¶fn_id´.
“Footnotes” which are never referenced in a document are now dropped,
  meaning that they can be used to fully remove text from the output
  (unlike most forms of commenting, which produce X·M·L comments).
The character `*´ was considered over `^´, but it has too many
  additional meanings in English text.

The character introducing footers has been changed from `]´ to `∎´.
The character introducing abstracts has been changed from `@´ to `∫´.
A new “tip” section has been introduced, with sigil `💡´.

Whitespace is no longer ignored before attribute specifications.
In general, more whitespace is preserved literally.

The hope at this point is that the Les·M·L format is fairly stable, and
  no major backwards‐incompatible changes will be made (excepting the
  minor backwards incompatibility which is inherent in adding new
  features to a syntax which already accepts all inputs with·out
  complaint).
A couple more features are anticipated, but “Version 1.0.0” will
  probably come soon.

47 files changed:
.gitignore [new file with mode: 0644]
README.lesml [new file with mode: 0644]
README.markdown [deleted file]
TESTING/REUSE.toml [new file with mode: 0644]
TESTING/ð\9f\93¤/at-id [new file with mode: 0644]
TESTING/ð\9f\93¤/attributes [new file with mode: 0644]
TESTING/ð\9f\93¤/comments [new file with mode: 0644]
TESTING/ð\9f\93¤/comments-continuations [new file with mode: 0644]
TESTING/ð\9f\93¤/empty-para [new file with mode: 0644]
TESTING/ð\9f\93¤/empty-para-id [new file with mode: 0644]
TESTING/ð\9f\93¤/footnotes [new file with mode: 0644]
TESTING/ð\9f\93¤/funky-tags [new file with mode: 0644]
TESTING/ð\9f\93¤/hgroup [new file with mode: 0644]
TESTING/ð\9f\93¤/hr [new file with mode: 0644]
TESTING/ð\9f\93¤/keys-and-values [new file with mode: 0644]
TESTING/ð\9f\93¤/langtags [new file with mode: 0644]
TESTING/ð\9f\93¤/links [new file with mode: 0644]
TESTING/ð\9f\93¤/lists [new file with mode: 0644]
TESTING/ð\9f\93¤/pre [new file with mode: 0644]
TESTING/ð\9f\93¤/profile-with-comment [new file with mode: 0644]
TESTING/ð\9f\93¤/quotes [new file with mode: 0644]
TESTING/ð\9f\93¤/sections [new file with mode: 0644]
TESTING/ð\9f\93¤/unicode-escapes [new file with mode: 0644]
TESTING/ð\9f\93¥/at-id [new file with mode: 0644]
TESTING/ð\9f\93¥/attributes [new file with mode: 0644]
TESTING/ð\9f\93¥/comments [new file with mode: 0644]
TESTING/ð\9f\93¥/comments-continuations [new file with mode: 0644]
TESTING/ð\9f\93¥/empty-para [new file with mode: 0644]
TESTING/ð\9f\93¥/empty-para-id [new file with mode: 0644]
TESTING/ð\9f\93¥/footnotes [new file with mode: 0644]
TESTING/ð\9f\93¥/funky-tags [new file with mode: 0644]
TESTING/ð\9f\93¥/hgroup [new file with mode: 0644]
TESTING/ð\9f\93¥/hr [new file with mode: 0644]
TESTING/ð\9f\93¥/keys-and-values [new file with mode: 0644]
TESTING/ð\9f\93¥/langtags [new file with mode: 0644]
TESTING/ð\9f\93¥/links [new file with mode: 0644]
TESTING/ð\9f\93¥/lists [new file with mode: 0644]
TESTING/ð\9f\93¥/pre [new file with mode: 0644]
TESTING/ð\9f\93¥/profile-with-comment [new file with mode: 0644]
TESTING/ð\9f\93¥/quotes [new file with mode: 0644]
TESTING/ð\9f\93¥/sections [new file with mode: 0644]
TESTING/ð\9f\93¥/unicode-escapes [new file with mode: 0644]
bin/lesml [new symlink]
magic [deleted file]
magic/lesml.magic [new file with mode: 0644]
sh/lesml.sh [new file with mode: 0755]
xslt/lesml.xslt [moved from parser.xslt with 59% similarity]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..05296c1
--- /dev/null
@@ -0,0 +1,7 @@
+# SPDX-FileCopyrightText: 2026 Hojarasca <https://www.hoja.red/about/#hoja>
+# SPDX-License-Identifier: CC0-1.0
+
+/@*
+!/@modules.tmp
+*%*
+.~*
diff --git a/README.lesml b/README.lesml
new file mode 100644 (file)
index 0000000..dfc813b
--- /dev/null
@@ -0,0 +1,311 @@
+#!lesml@en$
+## @(#)💄📝 Les·M·L      README.lesml    2026-03-31T01:28:11Z
+## SPDX-FileCopyrightText: 2024, 2025, 2026 Lady <https://www.ladys.computer/about/#lady>
+## SPDX-License-Identifier: CC0-1.0
+
+⁌ 💄📝 Les·M·L
+
+💄📝 Les·M·L is a document markup language designed with two goals in
+  mind :⁠—
+
+№ It must be trivial to parse, even with limited tooling such as that
+  provided by X·S·L·T.
+
+№ It must be sophisticated enough to handle longform hypertext
+  documents and associated metadata.
+
+It is implemented as an X·S·L·T transformation from a
+  `<html:script type="text/lesml">´ element into H·T·M·L
+  (`parser.xslt´).
+
+§ Nomenclature
+
+⟨Les·M·L⟩ is an abbreviation of the phrase ⟨Ladys Extremely Simple
+  Markup Language⟩.
+
+§ Markup syntax
+
+❦ Document headers
+
+The first line of any 💄📝 Les·M·L document should be the string
+  `#?lesml´.
+A language tag may follow this, beginning with `@´ and terminated with
+  `$´, like so: `#?lesml@en$´.
+Regardless of whether a language tag is present, this initial line may
+  be terminated by a space‐separated list of properties of the form
+  `key=value´.
+Only one property is currently permitted—`profile´—whose value should
+  be a U·R·I and identifies the set of conventions that the document is
+  using.
+
+Following the opening line, document metadata may be provided in the
+  {🔗Record
+  Jar<http://www.catb.org/~esr/writings/taoup/html/ch05s02.html>}
+  {@title="Data File Metaformats | The Art of Unix Programming"}
+  format.[*fn_record-jar]
+The body of the document begins after the last line which begins with
+  the string `%%´, or after the opening line if none exists.
+
+*¶fn_record-jar
+The format differs a bit from the Record Jar format specified in the
+  I·E·T·F `draft-phillips-record-jar-02´ draft:
+There are no restrictions on field names; newlines are a simple line
+  feed; continuation lines insert a space; character escapes are not
+  supported.
+These differences are negligible for most uses.
+
+Multiple documents can be catenated into a single file; a new document
+  is begun on any line which starts with `#?lesml´ or `##´.
+Documents in the later case inherit the latest preceding `#?lesml´
+  declaration.
+`##´ may be followed by other text; this is treated as an interdocument
+  comment.
+
+❦ Document bodies
+
+Document bodies are broken into blocks by blank lines.
+Empty blocks are ignored.
+
+Non·empty blocks (which, to be clear, may still result in empty
+  elements) are classified by the sigils which begin them.
+
+✠ Block level
+
+A block can begin with any number of `⋮´ characters; these
+  increase the level of the block.
+Blocks of higher level are nested within blocks of lower level, with
+  the exception that plain blocks cannot be nested as the first
+  children of other plain blocks, and no blocks are nestable within
+  comments.
+
+✠ Block sigils
+
+Following this, new blocks are opened for each successive sigil :⁠—
+
+• A `•´ sigil indicates an unordered list item.
+When it is the first sigil in the list, `◦´ may be used as a
+  shorthand for `⋮•´, `▪´ for `⋮⋮•´, and `⁃´ for `⋮⋮⋮•´.
+
+• A `№´ sigil indicates an ordered list item.
+
+• A `※´ sigil indicates an ordinary note.
+
+• A `⯑´ sigil indicates a questioning note.
+
+• A `∫´ sigil indicates an abstract or summary.
+
+• A `☡´ sigil indicates a cautionary notice.
+
+• A `⚠´ sigil indicates a warning notice.
+
+• A `🛈´ sigil indicates an informative callout.
+
+• A `💡´ sigil indicates a tip.
+
+• A `»´ sigil indicates a block quotation.
+
+• A `∎´ sigil indicates a footer or caption.
+
+A conceptual “plain” block exists at the end of the list of explicit
+  blocks.
+
+Whitespace characters can appear on either side of each sigil or `⋮´
+  character.
+
+✠ Paragraph types
+
+Each block contains a single paragraph, which is classified as
+  follows :⁠—
+
+• If the paragraph is a single line and consists of only the following
+  section‐break characters, plus any amount of white·space, then it is
+  considered to be a section break.
+
+⋮ The section break characters are :⁠—
+
+⋮ • `U+002A * ASTERISK´
+
+⋮ • `U+002D - HYPHEN-MINUS´
+
+⋮ • `U+002E . FULL STOP´
+
+⋮ • `U+003D = EQUALS SIGN´
+
+⋮ • `U+005F _ LOW LINE´
+
+⋮ • `U+007E ~ TILDE´
+
+⋮ • `U+00A0   NO-BREAK SPACE´
+
+⋮ • `U+00B7 · MIDDLE DOT´
+
+⋮ • `U+2024 ․ ONE DOT LEADER´
+
+⋮ • `U+2025 ‥ TWO DOT LEADER´
+
+⋮ • `U+2026 … HORIZONTAL ELLIPSIS´
+
+⋮ • `U+2042 ⁂ ASTERISM´
+
+⋮ • `U+2060 ⁠ WORD JOINER´
+
+⋮ • `U+22EF ⋯ MIDLINE HORIZONTAL ELLIPSIS´
+
+⋮ • `U+2500 ─ BOX DRAWINGS LIGHT HORIZONTAL´
+
+⋮ • `U+2501 ━ BOX DRAWINGS HEAVY HORIZONTAL´
+
+⋮ • `U+2504 ┄ BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL´
+
+⋮ • `U+2505 ┅ BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL´
+
+⋮ • `U+2508 ┈ BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL´
+
+⋮ • `U+2509 ┉ BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL´
+
+⋮ • `U+254C ╌ BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL´
+
+⋮ • `U+254D ╍ BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL´
+
+⋮ • `U+2550 ═ BOX DRAWINGS DOUBLE HORIZONTAL´
+
+⋮ • `U+2574 ╴ BOX DRAWINGS LIGHT LEFT´
+
+⋮ • `U+2576 ╶ BOX DRAWINGS LIGHT RIGHT´
+
+⋮ • `U+2578 ╸ BOX DRAWINGS HEAVY LEFT´
+
+⋮ • `U+257A ╺ BOX DRAWINGS HEAVY RIGHT´
+
+⋮ • `U+2619 ☙ REVERSED ROTATED FLORAL HEART BULLET´
+
+⋮ • `U+2767 ❧ ROTATED FLORAL HEART BULLET´
+
+⋮ • `U+3000   IDEOGRAPHIC SPACE´
+
+⋮ • `U+30FB ・ KATAKANA MIDDLE DOT´
+
+⋮ • `U+FF0A * FULLWIDTH ASTERISK´
+
+⋮ • `U+FF0D - FULLWIDTH HYPHEN-MINUS´
+
+⋮ • `U+FF0E . FULLWIDTH FULL STOP´
+
+⋮ • `U+FF1D = FULLWIDTH EQUALS SIGN´
+
+⋮ • `U+FF3F _ FULLWIDTH LOW LINE´
+
+⋮ • `U+FF5E ~ FULLWIDTH TILDE´
+
+• If the opening string of `⋮´ characters, sigils, and whitespace
+  characters is followed by a `|´, and this full sequence appears at
+  the beginning of each successive line, the paragraph is preformatted.
+If each `|´ is immediately followed by a `$´, it is a code block.
+A syntax may be specified for the code block by inserting its name
+  between the `|´ and `$´.
+
+• If the paragraph begins with `#´, it is an editorial comment and
+  should not be rendered or processed further.
+
+• If the paragraph begins with `⁌´, `§´, `❦´, or `✠´, it is a
+  chapter, section, subsection, or subsubsection heading, respectively.
+
+• If the paragraph begins with `^´, it is a footnote.
+To be reference·able, the footnote must have an identifier, described
+  below.
+Footnotes which are not referenced are dropped from the output.
+
+• Otherwise, the paragraph is ordinary.
+
+Finally, at the beginning of each (noncomment, nonrule) paragraph there
+  may be a `¶´ (optionally preceded by whitespace) followed by zero or
+  more nonwhitespace characters.
+The characters following the `¶´, if present, give the identifier for
+  the paragraph, which is expected to be unique within a document.
+This may be suffixed with a language tag beginning with `@´ and
+  terminated with `$´.
+
+The remaining characters in a paragraph form its contents.
+Markup within paragraphs is delimited with·out exception by pairs of
+  characters, with the following precedence :⁠—
+
+• The characters `⌦´ and `⌫´ indicate inline comments.
+A single character `⌧´ may be used to indicate an “empty” comment
+  (consisting of `U+034F COMBINING GRAPHEME JOINER´ for X·M·L
+  compatibility).
+
+• The characters `{@´ and `"}´ indicate attribute specifications.
+The attribute specification must contain at least one `="´ which
+  separates the key of the attribute from the value.
+Attributes attach to the previous element or text node; if there is no
+  such previous element or text node, an empty text node is used
+  instead.
+Multiple attributes can be given in sequence using multiple
+  specifications.
+
+• The characters `{🔗´ and `>}´ indicate a hyperlink to a U·R·L.
+The hyperlink must contain at least one `<´; the content before the
+  last `<` gives the text of the link, and the content after gives the
+  U·R·L that the link points to.
+If no text is given, the U·R·L will be used instead.
+
+• The characters `⸠´ and `⸡´ indicate a strikethru.
+
+• The characters `⸤´ and `⸥´ indicate underlining.
+
+• The characters `⟦´ and `⟧´ indicate an inline note.
+
+• The characters `⸨´ and `⸩´ indicate parenthetical content.
+
+• The characters `{U+60}´ and `{U+B4}´ indicate code.
+
+• The characters `⟪´ and `⟫´ indicate titles.
+
+• The characters `⸶´ and `⸷´ indicate names.
+
+• The characters `⟨´ and `⟩´ indicate offset text.
+
+• The characters `⦃´ and `⦄´ indicate keyword highlighting.
+
+• The characters `☞︎´ and `☜︎´ indicate strong importance.
+
+• The characters `⹐´ and `⹑´ indicate emphasis.
+
+• The characters `[^´ and `]´ indicate a footnote reference.
+  The characters between these sigils must match the i·d of some
+    footnote which is a sibling to the current paragraph or one of its
+    ancestors.
+
+Once the tree is built as above, it is remediated into its final form
+  by the following steps :⁠—
+
+• Blocks of higher level are nested within preceding blocks of lower
+  level, as described above.
+
+• Successive list items of the same type are joined into a single list.
+
+Finally, any character can be escaped by instead providing its Unicode
+  codepoint in the form `{U+NNNN}´, where `NNNN´ is one or more
+  hexadecimal digits.
+Multiple codepoints may be provided separated by periods, as in
+  `{U+WWWW.ZZZZ}´.
+Due to limitations in X·S·L·T, characters cannot be escaped in
+  attributes (including link targets).
+
+§ Usage
+
+💄📝 Les·M·L is designed for usage with
+  {🔗⛩📰 书社<https://git.ladys.computer/Shushe/>}.
+Simply include the `xslt/lesml.xslt´ provided by this repository to
+  ⛩📰 书社 as an additional parser, and `magic/lesml.magic´ as an
+  additional magic file.
+
+For simpler usecases, the `bin/lesml´ script can be used to convert a
+  single file (or standard input).
+
+§ License
+
+This repository conforms to {🔗REUSE<https://reuse.software/spec/>}.
+
+The parser is licensed under the terms of the Mozilla Public
+  License, version 2.0.
diff --git a/README.markdown b/README.markdown
deleted file mode 100644 (file)
index 835285c..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-<!--
-SPDX-FileCopyrightText: 2024, 2025 Lady <https://www.ladys.computer/about/#lady>
-SPDX-License-Identifier: CC0-1.0
--->
-# 💄📝 Les·M·L
-
-<b>Ladys simple markup language.</b>
-
-💄📝 Les·M·L is a document markup language designed with two goals in
-  mind :⁠—
-
-1. It must be trivial to parse, even with limited tooling such as that
-     provided by X·S·L·T.
-
-2. It must be sophisticated enough to handle longform hypertext
-     documents and associated metadata.
-
-It is implemented as an X·S·L·T transformation from a
-  `<html:script type="text/lesml">` element into H·T·M·L
-  (`parser.xslt`).
-
-## Nomenclature
-
-<i>Les·M·L</i> is an abbreviation of the phrase “Ladys Extremely Simple
-  Markup Language”.
-
-## Markup Syntax
-
-The first line of any 💄📝 Les·M·L document should be the string
-  `#!lesml`.
-A language tag may follow this, beginning with `@` and terminated with
-  `$`, like so:
-`#!lesml@en$`.
-Regardless of whether a language tag is present, the shebang line may
-  be terminated by a space‐separated list of properties of the form
-  `key=value`.
-Only one property is currently permitted: `profile`, whose value should
-  be a U·R·I and is translated to the `@data-lesml-profile` attribute
-  on the resulting `<html:article>` element.
-
-Following the shebang line, document metadata may be provided in the
-  [Record Jar][draft-phillips-record-jar-01] format.
-The body of the document begins after the last line which begins with
-  the string `%%`, or after the shebang line if none exists.
-
-Multiple documents can be catenated into a single file; a new document
-  is begun on any line which starts with `#!lesml` or `##`.
-Documents in the later case inherit the latest preceding `#!lesml`
-  declaration.
-`##` may be followed by other text; this is treated as an interdocument
-  comment.
-
-Documents are broken into paragraphs by blank lines.
-Empty paragraphs are ignored.
-
-If every line in the paragraph begins with (optional white·space
-  followed by) `»` it is quoted (`<html:blockquote>`); if every line
-  begins with `]` it is bracketed.
-The lines, minus this leading, are then re‐analysed.
-Bracketed paragraphs which end quotes are treated as captions
-  (`<html:figcaption>`); otherwise, they are footers (`<html:footer>`).
-
-Non·empty paragraphs (which, to be clear, may still result in empty
-  `<html:p>` elements) are classified as follows :⁠—
-
-- If the paragraph consists of only the following section‐break
-    characters, plus any amount of white·space, then it is
-    considered to be a section break (`<html:hr>`).
-
-  The section break characters are :⁠—
-
-  | Character | Codepoint | Unicode Name |
-  | --------- | --------- | ------------ |
-  | `*` | `U+002A` | `ASTERISK` |
-  | `-` | `U+002D` | `HYPHEN-MINUS` |
-  | `.` | `U+002E` | `FULL STOP` |
-  | `=` | `U+003D` | `EQUALS SIGN` |
-  | `_` | `U+005F` | `LOW LINE` |
-  | `~` | `U+007E` | `TILDE` |
-  | `·` | `U+00B7` | `MIDDLE DOT` |
-  | `․` | `U+2024` | `ONE DOT LEADER` |
-  | `‥` | `U+2025` | `TWO DOT LEADER` |
-  | `…` | `U+2026` | `HORIZONTAL ELLIPSIS` |
-  | `⁂` | `U+2042` | `ASTERISM` |
-  | `⋯` | `U+22EF` | `MIDLINE HORIZONTAL ELLIPSIS` |
-  | `─` | `U+2500` | `BOX DRAWINGS LIGHT HORIZONTAL` |
-  | `━` | `U+2501` | `BOX DRAWINGS HEAVY HORIZONTAL` |
-  | `┄` | `U+2504` | `BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL` |
-  | `┅` | `U+2505` | `BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL` |
-  | `┈` | `U+2508` | `BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL` |
-  | `┉` | `U+2509` | `BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL` |
-  | `╌` | `U+254C` | `BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL` |
-  | `╍` | `U+254D` | `BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL` |
-  | `═` | `U+2550` | `BOX DRAWINGS DOUBLE HORIZONTAL` |
-  | `╴` | `U+2574` | `BOX DRAWINGS LIGHT LEFT` |
-  | `╶` | `U+2576` | `BOX DRAWINGS LIGHT RIGHT` |
-  | `╸` | `U+2578` | `BOX DRAWINGS HEAVY LEFT` |
-  | `╺` | `U+257A` | `BOX DRAWINGS HEAVY RIGHT` |
-  | `☙` | `U+2619` | `REVERSED ROTATED FLORAL HEART BULLET` |
-  | `❧` | `U+2767` | `ROTATED FLORAL HEART BULLET` |
-  | ` ` | `U+3000` | `IDEOGRAPHIC SPACE` |
-  | `・` | `U+30FB` | `KATAKANA MIDDLE DOT` |
-  | `*` | `U+FF0A` | `FULLWIDTH ASTERISK` |
-  | `-` | `U+FF0D` | `FULLWIDTH HYPHEN-MINUS` |
-  | `.` | `U+FF0E` | `FULLWIDTH FULL STOP` |
-  | `=` | `U+FF1D` | `FULLWIDTH EQUALS SIGN` |
-  | `_` | `U+FF3F` | `FULLWIDTH LOW LINE` |
-  | `~` | `U+FF5E` | `FULLWIDTH TILDE` |
-
-- If every line in the paragraph begins with zero or more white·space
-    characters followed by `|`, it is a “preformatted” paragraph and
-    white·space is not collapsed (`<html:pre>`).
-
-- Otherwise, the paragraph is ordinary.
-
-After this classification, each ordinary paragraph is further
-  classified by type based on its first character (which must be
-  followed by white·space or a pilcrow, or else be the only thing on
-  the line) :⁠—
-
-- If the paragraph is preformatted, it is an ordinary paragraph.
-
-- If the paragraph begins with `⁌`, it is a chapter heading
-    (`<html:h1>`).
-
-- If the paragraph begins with `§`, it is a section heading
-    (`<html:h2>`).
-
-- If the paragraph begins with `❦`, it is a subsection heading
-    (`<html:h3>`).
-
-- If the paragraph begins with `✠`, it is a subsubsection heading
-    (`<html:h4>`).
-
-- If the paragraph begins with `•` or `🔢`, it is a primary unordered
-    or ordered list item (`<html:li class="unordered" data-level="1">`
-    or `<html:li class="ordered" data-level="1">`).
-
-- If the paragraph begins with `◦` or `🔠`, it is a secondary unordered
-    or ordered list item (`<html:li class="unordered" data-level="2">`
-    or `<html:li class="ordered" data-level="2">`).
-  Secondary list items are considered to be nested inside of primary
-    list items which precede them.
-
-- If the paragraph begins with `▪` or `🔡`, it is a tertiary unordered
-    or ordered list item (`<html:li class="unordered" data-level="3">`
-    or `<html:li class="ordered" data-level="3">`).
-  Tertiary list items are considered to be nested inside of primary
-    and secondary list items which precede them.
-
-- If the paragraph begins with `⁃` or `🔣`, it is a quaternary
-    unordered or ordered list item
-    (`<html:li class="unordered" data-level="4">` or
-    `<html:li class="ordered" data-level="4">`).
-  Quaternary list items are considered to be nested inside of primary,
-    secondary, and tertiary list items which precede them.
-
-- If the paragraph begins with `※`, it is an ordinary note
-    (`<html:section role="note" class="note">`).
-
-- If the paragraph begins with `☡`, it is a cautionary note
-    (`<html:section role="note" class="caution">`).
-
-- If the paragraph begins with `⯑`, it is a questioning note
-    (`<html:section role="note" class="query">`).
-
-- If the paragraph begins with `@`, it is an abstract
-    (`<html:section role="doc-abstract">`).
-
-- If the paragraph begins with `🛈`, it is a (informative) tip
-    (`<html:section role="doc-tip">`).
-
-- If the paragraph begins with `⚠︎`, it is a (warning) notice
-    (`<html:section role="doc-notice">`).
-
-- If the paragraph begins with `^`, it is a footnote
-    (`<html:li class="ordered footnote" data-level="1">`).
-  Footnotes are ignored unless their first paragraph has an i·d
-    (specified with `¶`) which is referenced by one or more footnote
-    references.
-  Footnotes are treated as level 1 ordered list items, so they can
-    contain nested lists.
-
-  Footnotes are removed from the normal document flow and placed in a
-    footer (`<html:section role="doc-endnotes">`) in order of first
-    reference.
-  It is recommended that the i·d¦s you choose are kept stable, so that
-    links to footnotes do not break.
-
-- If the paragraph begins with `#`, it is a comment.
-  Comments produce X·M·L comment nodes and can be used to break up list
-    items into separate lists.
-
-- If the paragraph begins with `⋯`, it is a continuation paragraph.
-  Continuation paragraphs may be used to continue a preceding note,
-    footnote, or list item.
-  If there is no such preceding note, footnote, or list item, they will
-    attach to adjacent heading elements to form heading groups
-    (`<html:hgroup>`).
-  Otherwise, they will be treated as ordinary paragraphs.
-
-- Otherwise, it is an ordinary paragraph.
-
-Following this sigil (if any) there may be a `¶` followed by zero or
-  more non·white·space characters.
-The characters following the `¶` give the identifier for the paragraph,
-  which is expected to be unique within a document.
-This may be suffixed with a language tag beginning with `@` and
-  terminated with `$`.
-
-When a paragraph produces an `<html:p>` element “wrapped in” another
-  kind of element (e·g, a blockquote, section, or list item), the
-  identifier and language of the first paragraph are applied to the
-  wrapping element.
-If the first paragraph has no other contents, it is deleted.
-To apply the identifier or language to the `<html:p>` element itself,
-  and not its wrapper, one can simply make the first paragraph empty
-  (using a literal `¶` with no other contents).
-This paragraph will be dropped, but the following paragraphs will still
-  be processed as non·initial.
-
-The remaining characters in a paragraph form its contents.
-Markup within paragraphs is delimited with·out exception by pairs of
-  characters, with the following precedence :⁠—
-
-- The characters `⌦` and `⌫` indicate inline comments.
-  A single character `⌧` may be used to indicate an “empty” comment
-    (consisting of `U+034F COMBINING GRAPHEME JOINER` for X·M·L
-    compatibility).
-
-- The characters `{@` and `"}` indicate attribute specifications.
-  The attribute specification must contain at least one `="` which
-    separates the key of the attribute from the value.
-  Attributes attach to the previous element or text node, with
-    white·space‐only text nodes after elements ignored; if there is no
-    such previous element or text node, an empty text node is used
-    instead.
-  Multiple attributes can be given in sequence using multiple
-    specifications.
-  Text nodes with attributes are wrapped in `<html:span>`.
-
-- The characters `{🔗` and `>}` indicate a hyperlink to a U·R·L
-    (`<html:a>`).
-  The hyperlink must contain at least one `<`; the content before the
-    last `<` gives the text of the link, and the content after gives
-    the U·R·L that the link points to.
-  If no text is given, the U·R·L will be used instead.
-
-- The characters `⸠` and `⸡` indicate a strikethru (`<html:s>`).
-
-- The characters `⸤` and `⸥` indicate underlining (`<html:u>`).
-
-- The characters `⟦` and `⟧` indicate an inline note
-    (`<html:small role="note">`).
-
-- The characters `⸨` and `⸩` indicate parenthetical content
-    (`<html:small>`).
-
-- The characters `` ` `` and `´` indicate code (`<html:code>`).
-
-- The characters `⟪` and `⟫` indicate titles (`<html:cite>`).
-
-- The characters `⸶` and `⸷` indicate names (`<html:u class="name">`).
-
-- The characters `⟨` and `⟩` indicate offset text (`<html:i>`).
-
-- The characters `⦃` and `⦄` indicate keyword highlighting
-    (`<html:b>`).
-
-- The characters `☞︎` and `☜︎` indicate strong importance
-    (`<html:strong>`).
-
-- The characters `⹐` and `⹑` indicate emphasis (`<html:em>`).
-
-- The characters `^` and `.` indicate a footnote reference
-    (`<html:a role="doc-noteref">`).
-  The characters between these sigils must match the i·d of the first
-    paragraph of some footnote in the same document.
-
-Once the tree is built as above, it is remediated into its final form
-  by the following steps :⁠—
-
-- Continuation paragraphs are joined with the preceding list items or
-    sections.
-
-- List items of a higher level are nested in preceding list items, when
-    present.
-  List items of a level greater than 1 can also be nested in preceding
-    sections (notes, abstracts, ⁊·c…).
-
-- Successive list items of the same level and class are joined into
-    a single list.
-
-- Linebreaks in preformatted paragraphs are replaced with `<html:br>`.
-
-Finally, any character can be escaped by instead providing its Unicode
-  codepoint in the form `{U+NNNN}`, where `NNNN` is one or more
-  hexadecimal digits.
-Multiple codepoints may be provided separated by periods, as in
-  `{U+WWWW.ZZZZ}`.
-Due to limitations in X·S·L·T, characters cannot be escaped in
-  attributes (including link targets).
-
-## Usage
-
-💄📝 Les·M·L is designed for usage with [⛩📰 书社][Shushe].
-Simply include the `parser.xslt` provided by this repository to
-  ⛩📰 书社 as an additional parser, and `magic` as an additional
-  magic file.
-
-## License
-
-This repository conforms to [REUSE][].
-
-The parser is licensed under the terms of the <cite>Mozilla Public
-  License, version 2.0</cite>.
-
-[REUSE]: <https://reuse.software/spec/>
-[Shushe]: <https://git.ladys.computer/Shushe/>
-[draft-phillips-record-jar-01]: <https://datatracker.ietf.org/doc/html/draft-phillips-record-jar-01>
diff --git a/TESTING/REUSE.toml b/TESTING/REUSE.toml
new file mode 100644 (file)
index 0000000..57994d6
--- /dev/null
@@ -0,0 +1,24 @@
+#?toml
+
+# This file provides licensing information for the files in this
+#   (`TESTING´) directory, as it would complicate the tests to include
+#   license information in the files themselves, and `.license´ files
+#   would really clutter up the directory.
+# In short:
+# The input and output files located in the `📥´ and `📤´
+#   subdirectories are all dedicated to the public domain.
+#
+# See {🔗<https://reuse.software/spec-3.3/#reusetoml>} for more on how
+#   this file should be understood.
+
+version = 1
+
+[[annotations]]
+path = "📥/**"
+SPDX-FileCopyrightText = "2026 Lady <https://www.ladys.computer/about#lady>"
+SPDX-License-Identifier = "CC0-1.0"
+
+[[annotations]]
+path = "📤/**"
+SPDX-FileCopyrightText = "2026 Lady <https://www.ladys.computer/about#lady>"
+SPDX-License-Identifier = "CC0-1.0"
diff --git a/TESTING/ð\9f\93¤/at-id b/TESTING/ð\9f\93¤/at-id
new file mode 100644 (file)
index 0000000..1f69024
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><ul><li class="unordered"><p id="item@example.com" lang="es" xml:lang="es">este tambien</p></li></ul></div></article></div>
diff --git a/TESTING/ð\9f\93¤/attributes b/TESTING/ð\9f\93¤/attributes
new file mode 100644 (file)
index 0000000..9588778
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><h2> Testing attributes</h2><p><span data-test="at the beginning"/><span data-test="some text">, after</span><span data-test=" by&#10;white space ">, broken
+ </span>, <code data-test="an element">after</code>, and <code>separated by</code><span data-test="some whitespace">
+</span>.</p><p>Each of these lines begins with a space; how does it affect the result?</p><pre role="paragraph"><span data-test="at the beginning"> </span><span data-test="some text">, after</span>, broken<br/><span data-test=" by&#10; white space "> </span>, <code data-test="an element">after</code>, and<br/> <code>separated by</code><br/><span data-test="some whitespace"> </span>.</pre><p><span data-nesting="in an">{@invalid </span><span data-ok-escape="{U+22}attribute{U+22}">="attribute"}; {@invalid data-characters="in an attribute"}; {@data-bad-escape-{U+40}="attribute"}; </span><span data-eqquot-ok="=&quot;">; </span><span data-and-a="second"> </span></p><p>{@inline="<!--comments"}-->(this shouldn’t work)"}</p></div></article></div>
diff --git a/TESTING/ð\9f\93¤/comments b/TESTING/ð\9f\93¤/comments
new file mode 100644 (file)
index 0000000..36032fc
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><p><!--͏-͏-͏-͏-͏-͏-⌦-͏-͏-->-----⌫ <!--a second ⌧ comment--> ye<!--͏-->p</p></div></article></div>
diff --git a/TESTING/ð\9f\93¤/comments-continuations b/TESTING/ð\9f\93¤/comments-continuations
new file mode 100644 (file)
index 0000000..1cf9bb5
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><div data-level="1"><p>This continues nothing.</p></div><div><!-- This is a comment.
+It can extend over multiple lines.--><p>Here is a continuation of the div containing the comment.</p><p>It keeps going on.</p></div></div></article></div>
diff --git a/TESTING/ð\9f\93¤/empty-para b/TESTING/ð\9f\93¤/empty-para
new file mode 100644 (file)
index 0000000..24ff415
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><p>Empty paragraphs are kept around :⁠—</p><p/><p>Except when starting containers :⁠—</p><blockquote id="blockquote-id" lang="en" xml:lang="en"><p/><p>(but other ones stay)</p><p/></blockquote><p>but conversely…</p><blockquote><p id="do-not-assign-to-containing-blockquote" lang="en" xml:lang="en"/></blockquote></div></article></div>
diff --git a/TESTING/ð\9f\93¤/empty-para-id b/TESTING/ð\9f\93¤/empty-para-id
new file mode 100644 (file)
index 0000000..fb800e4
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><p id="this-id-should-be-preserved"/></div></article></div>
diff --git a/TESTING/ð\9f\93¤/footnotes b/TESTING/ð\9f\93¤/footnotes
new file mode 100644 (file)
index 0000000..db80aa8
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><p>real footnote.<a id="LesML.fnref.id3" role="doc-noteref" href="#fn1" target="_self">1</a> real footnote 2.<a id="LesML.fnref.id2" role="doc-noteref" href="#fn2" target="_self">2</a> not a real footnote.[^fn3]
+also not a real footnote[^bad]footnote] the first footnote again.<a id="LesML.fnref.id1" role="doc-noteref" href="#fn1" target="_self">1</a></p></div><section role="doc-endnotes"><ol><ul><li id="fn1" value="1"><p>In the source, this footnote comes <em>second</em>, but it should be listed <em>first</em>.</p><ul><li class="unordered" data-level="1"><p>This footnote contains a nested list.</p></li></ul><footer class="backlinks"><a role="doc-backlink" href="#LesML.fnref.id3">1</a> <a role="doc-backlink" href="#LesML.fnref.id1">2</a></footer></li></ul><ul><li id="fn2" value="2"><p>In the source, this footnote comes <em>first</em>, but it should be listed <em>second</em>.</p><p>This footnote has multiple paragraphs.</p><footer class="backlinks"><a role="doc-backlink" href="#LesML.fnref.id2">1</a></footer></li></ul></ol></section></article></div>
diff --git a/TESTING/ð\9f\93¤/funky-tags b/TESTING/ð\9f\93¤/funky-tags
new file mode 100644 (file)
index 0000000..ac50a28
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><p>Here are ☞some `<strong>funky</strong> nested <code>☜tags</code>.</p></div></article></div>
diff --git a/TESTING/ð\9f\93¤/hgroup b/TESTING/ð\9f\93¤/hgroup
new file mode 100644 (file)
index 0000000..740cff7
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><hgroup><p>Start HGROUP</p><h1 lang="en" xml:lang="en">My Test Document</h1><p>End HGROUP</p></hgroup><hgroup><h2>
+An amazing document</h2><p>End another HGROUP</p></hgroup></div></article></div>
diff --git a/TESTING/ð\9f\93¤/hr b/TESTING/ð\9f\93¤/hr
new file mode 100644 (file)
index 0000000..6153276
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><blockquote><blockquote data-level="1"><blockquote data-level="2"><hr data-source-text="***"/></blockquote></blockquote></blockquote><hr data-source-text="&#x2619; &#x2042; &#x2767;"/></div></article></div>
diff --git a/TESTING/ð\9f\93¤/keys-and-values b/TESTING/ð\9f\93¤/keys-and-values
new file mode 100644 (file)
index 0000000..7c34284
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><!-- document comment--><!-- this is allowed following the opening shebang--><article lang="en" xml:lang="en" data-lesml-profile="about:test"><footer class="head"><dl><div><dt>Key</dt><dd>Value</dd></div></dl><!--comm--><!--ent--><dl><div><dt/><dd>Key value</dd></div></dl><dl><div><dt>multiline</dt><dd>keyand value</dd></div></dl><dl><div><dt>bad spaced</dt><dd>key</dd></div></dl></footer><div class="body"/></article></div>
diff --git a/TESTING/ð\9f\93¤/langtags b/TESTING/ð\9f\93¤/langtags
new file mode 100644 (file)
index 0000000..0529982
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><p lang="es" xml:lang="es"/><p lang="es" xml:lang="es">este es en español</p></div></article></div>
diff --git a/TESTING/ð\9f\93¤/links b/TESTING/ð\9f\93¤/links
new file mode 100644 (file)
index 0000000..b413d28
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><!-- Keep these links in one paragraph as it is important for testing how they interrelate:--><p><a href="http://example.com">Here is &lt;&lt;&lt; a <em>very good</em>@en$ <i>link</i>@en$ </a>
+{🔗 A {🔗 messy <a href="http://example.com">link </a>
+<a href="{&#x1F517;messier"> Even </a>
+<a href="http://example.com/2">   </a>
+<a href="example:example"><span class="important"> This</span> works now </a>
+{🔗 Not a link &gt;}</p></div></article></div>
diff --git a/TESTING/ð\9f\93¤/lists b/TESTING/ð\9f\93¤/lists
new file mode 100644 (file)
index 0000000..76deade
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><ul><li class="unordered" data-level="2"><p>List 3</p><ul><li class="unordered" data-level="3"><p>List 3.4</p></li></ul></li></ul><ul><li class="unordered"><p>List 1</p></li></ul><div><!-- Comments prevent continuations.--><p>Not List 1 Continued</p></div><ul><li class="unordered"><p>A New List 1</p><ul><li class="unordered" data-level="1"><p>List 1.2</p><div data-level="2"><p>List 1.2 Continued</p><ul><li class="unordered" data-level="3"><p>List 1.2.4-1</p><p>List 1.2.4-1 Continued</p></li><li class="unordered" data-level="3"><p>List 1.2.4-2</p></li></ul></div><ul><li class="unordered" data-level="2"><p>List 1.2.3</p><p id="1.2.3.c">List 1.2.3 Continued</p></li></ul></li></ul></li><li class="unordered"><p>List 1 again</p></li></ul><blockquote><ol><li class="ordered" data-level="1"><p>Quoted List 1-1</p></li><li class="ordered" data-level="1"><p>Quoted List 1-2</p></li><li class="ordered" data-level="1"><p>Quoted List 1-2.4</p><p>Quoted List 1-2.4 Continued</p></li></ol></blockquote><ul><li class="unordered"><p>Another List 1</p></li></ul><ol><li class="ordered"><p>List 1 of a different type</p></li></ol><section role="note" class="note"><div data-level="1"><p>This note contains two lists.</p><ul><li class="unordered" data-level="2"><p>The first list.</p></li></ul></div><ul><li class="unordered" data-level="1"><div data-level="2"><p>The second list.</p><ul><li class="unordered" data-level="3"><p>Nested in the second list.</p></li></ul></div></li></ul></section></div></article></div>
diff --git a/TESTING/ð\9f\93¤/pre b/TESTING/ð\9f\93¤/pre
new file mode 100644 (file)
index 0000000..fc96236
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><pre role="paragraph">Here is some<br/>   poetry<br/>Here is some<br/><code>code</code></pre><figure><blockquote><pre role="paragraph" class="code"><code>This is a <strong>code</strong> sample<br/>Inside of a blockquote</code></pre></blockquote><figcaption><p>Caption for the code sample.</p></figcaption></figure><pre role="paragraph" class="code" data-syntax="sh"><code>printf '%s\n' "A shell script" \<br/>  "Stretching across multiple lines"</code></pre></div></article></div>
diff --git a/TESTING/ð\9f\93¤/profile-with-comment b/TESTING/ð\9f\93¤/profile-with-comment
new file mode 100644 (file)
index 0000000..ad20a8c
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><!-- document comment--><!-- this is allowed following the opening shebang--><article lang="en" xml:lang="en" data-lesml-profile="about:test"><div class="body"><p>content</p></div></article></div>
diff --git a/TESTING/ð\9f\93¤/quotes b/TESTING/ð\9f\93¤/quotes
new file mode 100644 (file)
index 0000000..37b1c8e
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><figure><blockquote><blockquote data-level="1"><p>Nested quote.</p></blockquote><p id="foo">— Its caption.</p></blockquote><figcaption><p id="foo2">Its real caption</p><pre role="paragraph"> It can be multiple pars and contain markup.</pre></figcaption></figure></div></article></div>
diff --git a/TESTING/ð\9f\93¤/sections b/TESTING/ð\9f\93¤/sections
new file mode 100644 (file)
index 0000000..aefb24a
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><section role="doc-tip" class="info"><p>Testing the different note kinds.</p></section><section role="note" class="query"><p>Hmm…</p></section><section role="doc-notice" class="warning"><p>Watch out!</p></section><section role="note" class="note"><p>This is just an ordinary note.</p></section><section role="doc-abstract" class="abstract"><p>This is an abstract of this document.</p><p>It is continued here.</p></section><section role="doc-notice" class="caution"><p>This is some cautionary text.</p></section><section role="doc-tip" class="tip"><p>This is a tip</p></section></div></article></div>
diff --git a/TESTING/ð\9f\93¤/unicode-escapes b/TESTING/ð\9f\93¤/unicode-escapes
new file mode 100644 (file)
index 0000000..2acdeb5
--- /dev/null
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<div xmlns="http://www.w3.org/1999/xhtml"><article lang="en" xml:lang="en"><div class="body"><p>Testing &#x2764; some &#x2764;&#xFE0F; things {U+}! &#x2764;&#x2764;&#xFE0E;&#x2764;&#xFE0F;{U+2764.bad}{U+2764..2766}{U+}</p></div></article></div>
diff --git a/TESTING/ð\9f\93¥/at-id b/TESTING/ð\9f\93¥/at-id
new file mode 100644 (file)
index 0000000..541b49c
--- /dev/null
@@ -0,0 +1,3 @@
+#?lesml@en$
+
+• ¶item@example.com@es$ este tambien
diff --git a/TESTING/ð\9f\93¥/attributes b/TESTING/ð\9f\93¥/attributes
new file mode 100644 (file)
index 0000000..b7c0e66
--- /dev/null
@@ -0,0 +1,20 @@
+#?lesml@en$
+
+§ Testing attributes
+
+{@data-test="at the beginning"}, after{@data-test="some text"}, broken
+ {@data-test=" by
+white space "}, `after´{@data-test="an element"}, and `separated by´
+{@data-test="some whitespace"}.
+
+Each of these lines begins with a space; how does it affect the result?
+
+| {@data-test="at the beginning"}, after{@data-test="some text"}, broken
+| {@data-test=" by
+| white space "}, `after´{@data-test="an element"}, and
+| `separated by´
+| {@data-test="some whitespace"}.
+
+{@invalid {@data-nesting="in an"}="attribute"}; {@invalid data-characters="in an attribute"}; {@data-bad-escape-{U+40}="attribute"}; {@data-ok-escape="{U+22}attribute{U+22}"}; {@data-eqquot-ok="=""} {@data-and-a="second"}
+
+{@inline="⌦comments"}⌫(this shouldn’t work)"}
diff --git a/TESTING/ð\9f\93¥/comments b/TESTING/ð\9f\93¥/comments
new file mode 100644 (file)
index 0000000..adcd1d8
--- /dev/null
@@ -0,0 +1,3 @@
+#?lesml@en$
+
+⌦------⌦--⌫-----⌫ ⌦a second ⌧ comment⌫ ye⌧p
diff --git a/TESTING/ð\9f\93¥/comments-continuations b/TESTING/ð\9f\93¥/comments-continuations
new file mode 100644 (file)
index 0000000..f33775c
--- /dev/null
@@ -0,0 +1,10 @@
+#?lesml@en$
+
+⋮ This continues nothing.
+
+# This is a comment.
+It can extend over multiple lines.
+
+⋮ Here is a continuation of the div containing the comment.
+
+⋮ It keeps going on.
diff --git a/TESTING/ð\9f\93¥/empty-para b/TESTING/ð\9f\93¥/empty-para
new file mode 100644 (file)
index 0000000..30ec4b7
--- /dev/null
@@ -0,0 +1,21 @@
+#?lesml@en$
+
+Empty paragraphs are kept around :⁠—
+
+
+Except when starting containers :⁠—
+
+» ¶blockquote-id@en$
+
+⋮ ¶
+
+⋮ (but other ones stay)
+
+⋮ ¶
+
+but conversely…
+
+» ¶
+
+⋮ ¶do-not-assign-to-containing-blockquote@en$
diff --git a/TESTING/ð\9f\93¥/empty-para-id b/TESTING/ð\9f\93¥/empty-para-id
new file mode 100644 (file)
index 0000000..8e6e6d6
--- /dev/null
@@ -0,0 +1,3 @@
+#?lesml@en$
+
+¶this-id-should-be-preserved
diff --git a/TESTING/ð\9f\93¥/footnotes b/TESTING/ð\9f\93¥/footnotes
new file mode 100644 (file)
index 0000000..e3f2423
--- /dev/null
@@ -0,0 +1,14 @@
+#?lesml@en$
+
+real footnote.[^fn1] real footnote 2.[^fn2] not a real footnote.[^fn3]
+also not a real footnote[^bad]footnote] the first footnote again.[^fn1]
+
+^¶fn2 In the source, this footnote comes ⹐first⹑, but it should be listed ⹐second⹑.
+
+⋮ This footnote has multiple paragraphs.
+
+^¶fn1 In the source, this footnote comes ⹐second⹑, but it should be listed ⹐first⹑.
+
+◦ This footnote contains a nested list.
+
+^¶bad]footnote This footnote can¦t be referenced.
diff --git a/TESTING/ð\9f\93¥/funky-tags b/TESTING/ð\9f\93¥/funky-tags
new file mode 100644 (file)
index 0000000..860ddbc
--- /dev/null
@@ -0,0 +1,3 @@
+#?lesml@en$
+
+Here are ☞some `☞funky☜ nested `☜tags´.
diff --git a/TESTING/ð\9f\93¥/hgroup b/TESTING/ð\9f\93¥/hgroup
new file mode 100644 (file)
index 0000000..ab70729
--- /dev/null
@@ -0,0 +1,12 @@
+#?lesml@en$
+
+Start HGROUP
+
+⋮ ⁌¶@en$       My Test Document
+
+⋮ End HGROUP
+
+An amazing document
+
+⋮ End another HGROUP
diff --git a/TESTING/ð\9f\93¥/hr b/TESTING/ð\9f\93¥/hr
new file mode 100644 (file)
index 0000000..a8a1863
--- /dev/null
@@ -0,0 +1,5 @@
+#?lesml@en$
+
+»»» ***
+
+☙ ⁂ ❧
diff --git a/TESTING/ð\9f\93¥/keys-and-values b/TESTING/ð\9f\93¥/keys-and-values
new file mode 100644 (file)
index 0000000..62187d2
--- /dev/null
@@ -0,0 +1,15 @@
+#?lesml@en$ profile=about:test
+## document comment
+## this is allowed following the opening shebang
+%%
+Key : Value
+%%comm
+%%ent
+Key value
+%%
+multiline: key
+  and \
+  value
+%%
+  bad spaced : key
+%%
diff --git a/TESTING/ð\9f\93¥/langtags b/TESTING/ð\9f\93¥/langtags
new file mode 100644 (file)
index 0000000..1910581
--- /dev/null
@@ -0,0 +1,5 @@
+#?lesml@en$
+
+¶@es$
+
+¶@es$ este es en español
diff --git a/TESTING/ð\9f\93¥/links b/TESTING/ð\9f\93¥/links
new file mode 100644 (file)
index 0000000..069dc5a
--- /dev/null
@@ -0,0 +1,10 @@
+#?lesml@en$
+
+# Keep these links in one paragraph as it is important for testing how they interrelate:
+
+{🔗Here is <<< a ⹐very good⹑@en$ ⟨link⟩@en$ <http://example.com>}
+{🔗 A {🔗 messy {🔗link <http://example.com>}
+{🔗 Even <{🔗messier>}
+{🔗   <http://example.com/2>}
+{🔗 This{@class="important"} works now <example:example>}
+{🔗 Not a link >}
diff --git a/TESTING/ð\9f\93¥/lists b/TESTING/ð\9f\93¥/lists
new file mode 100644 (file)
index 0000000..f96e1ac
--- /dev/null
@@ -0,0 +1,49 @@
+#?lesml@en$
+
+▪ List 3
+
+⁃ List 3.4
+
+• List 1
+
+# Comments prevent continuations.
+
+⋮ Not List 1 Continued
+
+• A New List 1
+
+◦ List 1.2
+
+⋮⋮ List 1.2 Continued
+
+⁃ List 1.2.4-1
+
+⋮⋮⋮⋮ List 1.2.4-1 Continued
+
+⁃ List 1.2.4-2
+
+▪ List 1.2.3
+
+⋮⋮⋮ ¶1.2.3.c List 1.2.3 Continued
+
+• List 1 again
+
+» № Quoted List 1-1
+
+⋮ № Quoted List 1-2
+
+⋮ № Quoted List 1-2.4
+
+⋮ ⋮ Quoted List 1-2.4 Continued
+
+• Another List 1
+
+№ List 1 of a different type
+
+※ This note contains two lists.
+
+▪ The first list.
+
+◦ The second list.
+
+⁃ Nested in the second list.
diff --git a/TESTING/ð\9f\93¥/pre b/TESTING/ð\9f\93¥/pre
new file mode 100644 (file)
index 0000000..5faa40e
--- /dev/null
@@ -0,0 +1,14 @@
+#?lesml@en$
+
+|Here is some
+|      poetry
+|Here is some
+|`code´
+
+» |$This is a ☞code☜ sample
+» |$Inside of a blockquote
+
+⋮ ∎ Caption for the code sample.
+
+|sh$printf '%s\n' "A shell script" \
+|sh$  "Stretching across multiple lines"
diff --git a/TESTING/ð\9f\93¥/profile-with-comment b/TESTING/ð\9f\93¥/profile-with-comment
new file mode 100644 (file)
index 0000000..522e699
--- /dev/null
@@ -0,0 +1,4 @@
+#?lesml@en$ profile=about:test
+## document comment
+## this is allowed following the opening shebang
+content
diff --git a/TESTING/ð\9f\93¥/quotes b/TESTING/ð\9f\93¥/quotes
new file mode 100644 (file)
index 0000000..823ca9a
--- /dev/null
@@ -0,0 +1,9 @@
+#?lesml@en$
+
+» » Nested quote.
+
+⋮ ¶foo — Its caption.
+
+⋮ ∎¶foo2 Its real caption
+
+⋮ ⋮ | It can be multiple pars and contain markup.
diff --git a/TESTING/ð\9f\93¥/sections b/TESTING/ð\9f\93¥/sections
new file mode 100644 (file)
index 0000000..edf3d12
--- /dev/null
@@ -0,0 +1,17 @@
+#?lesml@en$
+
+🛈 Testing the different note kinds.
+
+⯑ Hmm…
+
+⚠ Watch out!
+
+※ This is just an ordinary note.
+
+∫ This is an abstract of this document.
+
+⋮ It is continued here.
+
+☡ This is some cautionary text.
+
+💡 This is a tip
diff --git a/TESTING/ð\9f\93¥/unicode-escapes b/TESTING/ð\9f\93¥/unicode-escapes
new file mode 100644 (file)
index 0000000..25f95b9
--- /dev/null
@@ -0,0 +1,3 @@
+#?lesml@en$
+
+Testing {U+2764} some {U+2764.FE0F} things {U+}! {U+2764}{U+2764.FE0E}{U+2764.FE0F}{U+2764.bad}{U+2764..2766}{U+}
diff --git a/bin/lesml b/bin/lesml
new file mode 120000 (symlink)
index 0000000..40c2f0f
--- /dev/null
+++ b/bin/lesml
@@ -0,0 +1 @@
+../sh/lesml.sh
\ No newline at end of file
diff --git a/magic b/magic
deleted file mode 100644 (file)
index b4bb1bc..0000000
--- a/magic
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady>
-# SPDX-License-Identifier: CC0-1.0
-
-0  string  #!lesml  LesML text
-!:mime text/lesml
-!:strength + 100
diff --git a/magic/lesml.magic b/magic/lesml.magic
new file mode 100644 (file)
index 0000000..4d7d52e
--- /dev/null
@@ -0,0 +1,7 @@
+# @(#)💄📝 Les·M·L       magic/lesml.magic       2026-03-31T01:28:11Z
+# SPDX-FileCopyrightText: 2024, 2026 Lady <https://www.ladys.computer/about/#lady>
+# SPDX-License-Identifier: CC0-1.0
+
+0  string  #?lesml  LesML text
+!:mime text/lesml
+!:strength + 100
diff --git a/sh/lesml.sh b/sh/lesml.sh
new file mode 100755 (executable)
index 0000000..d0bedeb
--- /dev/null
@@ -0,0 +1,138 @@
+#!/usr/bin/env sh
+# @(#)💄📝 Les·M·L       sh/lesml.sh     2026-03-31T01:28:11Z
+# SPDX-FileCopyrightText: 2023, 2024, 2026 Lady <https://www.ladys.computer/about/#lady>
+# SPDX-License-Identifier: MPL-2.0
+
+## ⁌ The 💄📝 Les·M·L shell script
+##
+## ∎ Copyright © 2023–2024, 2026 Lady [@ Ladys Computer].
+##
+## ⋮ This Source Code Form is subject to the terms of the Mozilla
+##   Public License, version 2.0.
+## If a copy of the M·P·L was not distributed with this file, You can
+##   obtain one at {🔗<https://mozilla.org/MPL/2.0/>}.
+##
+## Usage :⁠—
+##
+## »|sh$sh ./sh/lesml.sh [--] [filename]
+##
+## This script provides a simple solution for converting a Les·M·L file
+##   into X·H·T·M·L.
+
+set -o 'errexit'
+
+## `LANG´ and `LC_ALL´ are set to `C´ because this script assumes
+##   working with U·T·F‐8 strings as opaque series of bytes.
+
+LANG=C
+LC_ALL=C
+
+## § Configuration
+##
+## All of the commands used by this script are overridable with your
+##   own implementations by setting the corresponding `cmd_COMMAND´
+##   variable.
+
+: "${cmd_DIRNAME:=dirname}"
+: "${cmd_PRINTF:=printf}"
+: "${cmd_REALPATH:=realpath}"
+: "${cmd_SED:=sed}"
+: "${cmd_TEST:=test}"
+: "${cmd_TR:=tr}"
+: "${cmd_XSLTPROC:=xsltproc}"
+
+## In order to run, this program needs to know the location of the
+##   💄📝 Les·M·L transform, which is calculated below.
+## This location can be manually configured by setting the `path_LESML´
+##   or `path_TRANSFORM´ environment variables.
+
+thisfile="$(
+  "${cmd_REALPATH}" -- "${0}"
+)"
+thisdir="$(
+  "${cmd_DIRNAME}" -- "${thisfile}"
+)"
+
+defaultlesml="$(
+  "${cmd_REALPATH}" -- "${thisdir}"'/..'
+)"
+: "${path_LESML:=${defaultlesml}}"
+
+defaulttransform="${path_LESML}"'/xslt/lesml.xslt'
+: "${path_TRANSFORM:=${defaulttransform}}"
+
+## The (unregistered) media type for Les·M·L files is `text/lesml´.
+## By overriding both the media type and the transform, one can re·use
+##   this script for processing other kinds of files with X·S·L·T.
+
+: "${name_MEDIATYPE:=text/lesml}"
+
+## § Parameter processing
+##
+## A leading `--´ is allowed (and ignored).
+## Otherwise, the first parameter is the source filename.
+
+if "${cmd_TEST}" "${1}" = '--'
+then :
+  shift
+fi
+
+## If no input file is provided, it defaults to `-´ (standard input).
+
+if "${cmd_TEST}" -n "${1}" && "${cmd_TEST}" "${1}" != '-'
+then :
+  inputfile="$(
+    "${cmd_REALPATH}" -- "${1}"
+  )"
+else :
+  inputfile='-'
+fi
+
+## § Implementation
+##
+## ※ This implementation is derived from
+##   {🔗⛩📰 书社<https://git.ladys.computer/Shushe/>} code written
+##   2023–2024.
+##
+## The `sanitizeprog´ variable contains a Sed program for sanitizing
+##   an arbitrary string into characters which are valid in X·M·L.
+## Ideally this would be written using dollar‐single‐quote literals,
+##   but Mac·O·S Dash is outdated and does not support them.
+
+sanitizeprog="$(
+  "${cmd_PRINTF}" '%b' \
+    's/]]>/]]]]><!\\[CDATA\\[>/g\n' \
+    's/\0357\0277\0276/�/g\n' \
+    's/\0357\0277\0277/�/g\n' \
+    '$!s/\r$//g\n' \
+    's/\r/\\n/g\n' \
+    '$!s/\0302\0205$//g\n' \
+    's/\0302\0205/\\n/g\n' \
+    's/\0342\0200\0250/\\n/g\n' \
+    's/[\0001\0002\0003\0004\0005\0006\0007\0010]/�/g\n' \
+    's/[\0016\0017\0020\0021\0022\0023\0024\0025\0026\0027]/�/g\n' \
+    's/[\0031\0032\0033\0034\0035\0036\0037]/�/g'
+)"
+
+## A compound statement is used to group together the wrapping X·M·L
+##   and the sanitized input into one output which can be piped to
+##   `xsltproc´.
+
+{
+  "${cmd_PRINTF}" '%s\n%s%s%s' \
+    '<?xml version="1.0"?>' \
+    '<script xmlns="http://www.w3.org/1999/xhtml" type="' \
+    "${name_MEDIATYPE}" \
+    '"><![CDATA['
+  if "${cmd_TEST}" "${inputfile}" = '-'
+  then :
+    "${cmd_TR}" '\000\013\014' '\032\011\012'
+  else :
+    "${cmd_TR}" '\000\013\014' '\032\011\012' <"${inputfile}"
+  fi |
+  "${cmd_SED}" "${sanitizeprog}"
+  "${cmd_PRINTF}" '%s\n' ']]></script>'
+} |
+"${cmd_XSLTPROC}" --nonet --nowrite --novalid \
+  "${path_TRANSFORM}" \
+  -
similarity index 59%
rename from parser.xslt
rename to xslt/lesml.xslt
index e5b3bf0fe52ffb60dcbe5a3c37b695ffe5512640f962dbce44ef85236c5bc8f1..9a603834c4bbef7c765730fdbce743b28a721df24c006aea7d1ef3110a405e68 100644 (file)
@@ -1,39 +1,51 @@
 <?xml version="1.0"?>
 <!--
-SPDX-FileCopyrightText: 2024, 2025 Lady <https://www.ladys.computer/about/#lady>
+@(#)💄📝 Les·M·L xslt/lesml.xslt 2026-03-31T01:28:11Z
+SPDX-FileCopyrightText: 2024, 2025, 2026 Lady <https://www.ladys.computer/about/#lady>
 SPDX-License-Identifier: MPL-2.0
 -->
-<!--
-⁌ 💄📝 Les·M·L ∷ parser.xslt
 
-© 2024–2025 Lady [@ Ladys Computer]
+<!-->
+⁌ The 💄📝 Les·M·L transform
+
+∎ Copyright © 2024–2026 Lady [@ Ladys Computer]
+
+⋮ This Source Code Form is subject to the terms of the Mozilla Public
+  License, v 2.0.
+If a copy of the M·P·L was not distributed with this file, You can
+  obtain one at {🔗<https://mozilla.org/MPL/2.0/>}.
+
+This file implements a transformation, via X·S·L·T, from an H·T·M·L
+  `<script>´ element with `@type="text/lesml"´ into the corresponding
+  H·T·M·L representation of the text it contains.
+This forms the “canonical” definition of the Les·M·L syntax;
+  no features will be added to the language which are not feasible to
+  be implemented here.
+</!-->
 
-This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
-If a copy of the M·P·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
--->
 <!DOCTYPE transform [
        <!ENTITY LesML "urn:fdc:ladys.computer:20240512:LesML">
-       <!ENTITY pilcrow-atts "(local-name()='id' or local-name()='lang') and namespace-uri()='' or local-name()='lang' and namespace-uri()='http://www.w3.org/XML/1998/namespace'">
-       <!ENTITY sigiled-text "(string-length($text)=1 or substring($text, 2, 1)=' ' or substring($text, 2, 1)='¶')">
-       <!ENTITY unsigiled-text "concat(translate(substring($text, 2, 1), ' ', ''), substring($text, 3, string-length($text)-2))">
+       <!ENTITY block-types "self::html:blockquote or self::html:footer or self::html:li or self::html:dt or self::html:dd or self::html:section or &paragraph-types;">
+       <!ENTITY paragraph-types "self::html:p or self::html:pre or self::html:h1 or self::html:h2 or self::html:h3 or self::html:h4">
+       <!ENTITY level-pi "processing-instruction()[local-name()='LesML-Level']">
        <!ENTITY xhtml "http://www.w3.org/1999/xhtml">
 ]>
 <transform
        xmlns="http://www.w3.org/1999/XSL/Transform"
-       xmlns:LesML="urn:fdc:ladys.computer:20240512:LesML"
+       xmlns:LesML="&LesML;"
        xmlns:exsl="http://exslt.org/common"
        xmlns:exsldyn="http://exslt.org/dynamic"
        xmlns:exslfunc="http://exslt.org/functions"
        xmlns:exslset="http://exslt.org/sets"
        xmlns:exslstr="http://exslt.org/strings"
-       xmlns:html="http://www.w3.org/1999/xhtml"
+       xmlns:html="&xhtml;"
        xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
        exclude-result-prefixes="LesML"
        extension-element-prefixes="exsl exsldyn exslfunc exslset exslstr"
        version="1.0"
 >
        <书社:id>urn:fdc:ladys.computer:20240512:LesML:parser.xslt</书社:id>
-       <param name="LESML_SECTION_BREAK_CHARS" select="'*-.=_~·․‥…⁂⋯─━┄┅┈┉╌╍═╴╶╸╺☙❧ ・*-.=_~'"/>
+       <param name="LESML_SECTION_BREAK_CHARS" select="'*-.=_~ ·․‥…⁂⁠⋯─━┄┅┈┉╌╍═╴╶╸╺☙❧ ・*-.=_~'"/>
        <exslfunc:function name="LesML:split">
                <param name="source" select="string()"/>
                <param name="separator" select="'&#xA;'"/>
@@ -65,16 +77,24 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                        </otherwise>
                </choose>
        </template>
-       <template name="LesML:break-and-unescape">
+       <template name="LesML:comment-out">
                <param name="source"/>
-               <for-each select="LesML:split($source)">
-                       <call-template name="LesML:unescape">
-                               <with-param name="source" select="string()"/>
-                       </call-template>
-                       <if test="position()!=last()">
-                               <element name="br" namespace="&xhtml;"/>
-                       </if>
-               </for-each>
+               <comment>
+                       <for-each select="LesML:split($source, '--')">
+                               <if test="string()='' or starts-with(., '‐')">
+                                       <text>&#x034F;</text>
+                               </if>
+                               <value-of select="."/>
+                               <if test="substring(., string-length(.), 1)='‐'">
+                                       <text>&#x034F;</text>
+                               </if>
+                               <choose>
+                                       <when test="position()!=last()">
+                                               <text>-&#x034F;-</text>
+                                       </when>
+                               </choose>
+                       </for-each>
+               </comment>
        </template>
        <template name="LesML:unescape">
                <param name="source"/>
@@ -121,115 +141,476 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                        </otherwise>
                </choose>
        </template>
-       <template name="LesML:comment-out">
-               <param name="source"/>
-               <comment>
-                       <for-each select="LesML:split($source, '--')">
-                               <if test="string()='' or starts-with(., '‐')">
-                                       <text>&#x034F;</text>
-                               </if>
-                               <value-of select="."/>
-                               <if test="substring(., string-length(.), 1)='‐'">
-                                       <text>&#x034F;</text>
-                               </if>
+       <template name="LesML:expand-sigils">
+               <param name="sigils" select="/.."/>
+               <param name="level" select="0"/>
+               <param name="partype"/>
+               <param name="syntax"/>
+               <param name="lines" select="/.."/>
+               <choose>
+                       <when test="$sigils">
+                               <variable name="wrapper-frag">
+                                       <choose>
+                                               <when test="$sigils[1]='•'">
+                                                       <element name="li" namespace="&xhtml;">
+                                                               <attribute name="class">
+                                                                       <text>unordered</text>
+                                                               </attribute>
+                                                       </element>
+                                               </when>
+                                               <when test="$sigils[1]='№'">
+                                                       <element name="li" namespace="&xhtml;">
+                                                               <attribute name="class">
+                                                                       <text>ordered</text>
+                                                               </attribute>
+                                                       </element>
+                                               </when>
+                                               <when test="$sigils[1]='※'">
+                                                       <element name="section" namespace="&xhtml;">
+                                                               <attribute name="role">
+                                                                       <text>note</text>
+                                                               </attribute>
+                                                               <attribute name="class">
+                                                                       <text>note</text>
+                                                               </attribute>
+                                                       </element>
+                                               </when>
+                                               <when test="$sigils[1]='⯑'">
+                                                       <element name="section" namespace="&xhtml;">
+                                                               <attribute name="role">
+                                                                       <text>note</text>
+                                                               </attribute>
+                                                               <attribute name="class">
+                                                                       <text>query</text>
+                                                               </attribute>
+                                                       </element>
+                                               </when>
+                                               <when test="$sigils[1]='∫'">
+                                                       <element name="section" namespace="&xhtml;">
+                                                               <attribute name="role">
+                                                                       <text>doc-abstract</text>
+                                                               </attribute>
+                                                               <attribute name="class">
+                                                                       <text>abstract</text>
+                                                               </attribute>
+                                                       </element>
+                                               </when>
+                                               <when test="$sigils[1]='☡'">
+                                                       <element name="section" namespace="&xhtml;">
+                                                               <attribute name="role">
+                                                                       <text>doc-notice</text>
+                                                               </attribute>
+                                                               <attribute name="class">
+                                                                       <text>caution</text>
+                                                               </attribute>
+                                                       </element>
+                                               </when>
+                                               <when test="$sigils[1]='⚠'">
+                                                       <element name="section" namespace="&xhtml;">
+                                                               <attribute name="role">
+                                                                       <text>doc-notice</text>
+                                                               </attribute>
+                                                               <attribute name="class">
+                                                                       <text>warning</text>
+                                                               </attribute>
+                                                       </element>
+                                               </when>
+                                               <when test="$sigils[1]='🛈'">
+                                                       <element name="section" namespace="&xhtml;">
+                                                               <attribute name="role">
+                                                                       <text>doc-tip</text>
+                                                               </attribute>
+                                                               <attribute name="class">
+                                                                       <text>info</text>
+                                                               </attribute>
+                                                       </element>
+                                               </when>
+                                               <when test="$sigils[1]='💡'">
+                                                       <element name="section" namespace="&xhtml;">
+                                                               <attribute name="role">
+                                                                       <text>doc-tip</text>
+                                                               </attribute>
+                                                               <attribute name="class">
+                                                                       <text>tip</text>
+                                                               </attribute>
+                                                       </element>
+                                               </when>
+                                               <when test="$sigils[1]='»'">
+                                                       <element name="blockquote" namespace="&xhtml;"/>
+                                               </when>
+                                               <when test="$sigils[1]='∎'">
+                                                       <element name="footer" namespace="&xhtml;"/>
+                                               </when>
+                                               <otherwise>
+                                                       <message terminate="yes">
+                                                               <text>Unrecognized sigil: </text>
+                                                               <value-of select="$sigils[1]"/>
+                                                               <text>.</text>
+                                                       </message>
+                                               </otherwise>
+                                       </choose>
+                               </variable>
+                               <for-each select="exsl:node-set($wrapper-frag)/*">
+                                       <copy>
+                                               <copy-of select="@*|node()"/>
+                                               <processing-instruction name="LesML-Level">
+                                                       <value-of select="$level"/>
+                                               </processing-instruction>
+                                               <call-template name="LesML:expand-sigils">
+                                                       <with-param name="sigils" select="$sigils[position()>1]"/>
+                                                       <with-param name="level" select="$level+1"/>
+                                                       <with-param name="partype" select="$partype"/>
+                                                       <with-param name="syntax" select="$syntax"/>
+                                                       <with-param name="lines" select="$lines"/>
+                                               </call-template>
+                                       </copy>
+                               </for-each>
+                       </when>
+                       <when test="$partype='comment'">
+                               <element name="div" namespace="&xhtml;">
+                                       <processing-instruction name="LesML-Level">
+                                               <value-of select="$level"/>
+                                       </processing-instruction>
+                                       <call-template name="LesML:comment-out">
+                                               <with-param name="source">
+                                                       <for-each select="$lines">
+                                                               <value-of select="."/>
+                                                               <if test="position()!=count($lines)">
+                                                                       <text>&#xA;</text>
+                                                               </if>
+                                                       </for-each>
+                                               </with-param>
+                                       </call-template>
+                               </element>
+                       </when>
+                       <otherwise>
+                               <variable name="firstchar" select="substring(translate($lines[1], ' &#x9;', ''), 1, 1)"/>
+                               <variable name="firstline">
+                                       <choose>
+                                               <when test="$firstchar!=''">
+                                                       <value-of select="concat($firstchar, substring-after($lines[1], $firstchar))"/>
+                                               </when>
+                                       </choose>
+                               </variable>
+                               <variable name="firsttokens" select="exslstr:tokenize($firstline, ' &#x9;')"/>
+                               <variable name="id-and-lang">
+                                       <if test="$firstchar='¶'">
+                                               <value-of select="$firsttokens[1]"/>
+                                       </if>
+                               </variable>
+                               <variable name="restofline">
+                                       <choose>
+                                               <when test="$id-and-lang!=''">
+                                                       <variable name="nosp" select="substring($firsttokens[1+number($id-and-lang!='')], 1, 1)"/>
+                                                       <if test="$nosp!=''">
+                                                               <value-of select="concat($nosp, substring-after(substring-after($firstline, $id-and-lang), $nosp))"/>
+                                                       </if>
+                                               </when>
+                                               <otherwise>
+                                                       <value-of select="$lines[1]"/>
+                                               </otherwise>
+                                       </choose>
+                               </variable>
+                               <variable name="maybe-langtag">
+                                       <if test="substring($id-and-lang, string-length($id-and-lang), 1)='$' and contains($id-and-lang, '@')">
+                                               <value-of select="LesML:split(substring($id-and-lang, 2, string-length($id-and-lang)-2), '@')[last()]"/>
+                                       </if>
+                               </variable>
+                               <variable name="langtag">
+                                       <if test="translate($maybe-langtag, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-', '')=''">
+                                               <value-of select="$maybe-langtag"/>
+                                       </if>
+                               </variable>
+                               <variable name="id">
+                                       <choose>
+                                               <when test="string($langtag)!=''">
+                                                       <value-of select="substring($id-and-lang, 2, string-length($id-and-lang)-(string-length($langtag)+3))"/>
+                                               </when>
+                                               <otherwise>
+                                                       <value-of select="substring($id-and-lang, 2)"/>
+                                               </otherwise>
+                                       </choose>
+                               </variable>
+                               <variable name="newline">
+                                       <choose>
+                                               <when test="$partype='pre' or $partype='pre code'">
+                                                       <element name="br" namespace="&xhtml;"/>
+                                               </when>
+                                               <otherwise>
+                                                       <text>&#xA;</text>
+                                               </otherwise>
+                                       </choose>
+                               </variable>
+                               <variable name="text">
+                                       <if test="$id-and-lang='' or $restofline!=''">
+                                               <value-of select="$restofline"/>
+                                               <if test="count($lines)>1">
+                                                       <copy-of select="$newline"/>
+                                               </if>
+                                       </if>
+                                       <for-each select="$lines[position()>1]">
+                                               <value-of select="."/>
+                                               <if test="position()!=count($lines[position()>1])">
+                                                       <copy-of select="$newline"/>
+                                               </if>
+                                       </for-each>
+                               </variable>
+                               <variable name="parwrapper">
+                                       <choose>
+                                               <when test="$partype='pre code'">
+                                                       <text>pre</text>
+                                               </when>
+                                               <when test="$partype='footnote'">
+                                                       <text>p</text>
+                                               </when>
+                                               <when test="$partype!=''">
+                                                       <value-of select="$partype"/>
+                                               </when>
+                                               <otherwise>
+                                                       <text>p</text>
+                                               </otherwise>
+                                       </choose>
+                               </variable>
+                               <element name="div" namespace="&xhtml;">
+                                       <if test="$id!=''">
+                                               <attribute name="id">
+                                                       <value-of select="$id"/>
+                                               </attribute>
+                                       </if>
+                                       <if test="$langtag!=''">
+                                               <attribute name="lang">
+                                                       <value-of select="$langtag"/>
+                                               </attribute>
+                                               <attribute name="xml:lang">
+                                                       <value-of select="$langtag"/>
+                                               </attribute>
+                                       </if>
+                                       <if test="$partype='footnote'">
+                                               <processing-instruction name="LesML-Footnote">
+                                                       <value-of select="$id"/>
+                                               </processing-instruction>
+                                       </if>
+                                       <processing-instruction name="LesML-Level">
+                                               <value-of select="$level"/>
+                                       </processing-instruction>
+                                       <element name="{$parwrapper}" namespace="&xhtml;">
+                                               <if test="$parwrapper='pre'">
+                                                       <attribute name="role">
+                                                               <text>paragraph</text>
+                                                       </attribute>
+                                               </if>
+                                               <if test="$partype='pre code'">
+                                                       <attribute name="class">
+                                                               <text>code</text>
+                                                       </attribute>
+                                               </if>
+                                               <if test="$syntax!=''">
+                                                       <attribute name="data-syntax">
+                                                               <value-of select="$syntax"/>
+                                                       </attribute>
+                                               </if>
+                                               <choose>
+                                                       <when test="$parwrapper='hr'">
+                                                               <attribute name="data-source-text">
+                                                                       <value-of select="$text"/>
+                                                               </attribute>
+                                                       </when>
+                                                       <otherwise>
+                                                               <copy-of select="$text"/>
+                                                       </otherwise>
+                                               </choose>
+                                       </element>
+                               </element>
+                       </otherwise>
+               </choose>
+       </template>
+       <template name="LesML:chunk">
+               <param name="lines" select="/.."/>
+               <variable name="last-lines" select="$lines[normalize-space()!='' and (normalize-space(following-sibling::*[1])='' or position()=last())]"/>
+               <for-each select="$last-lines">
+                       <variable name="position" select="position()"/>
+                       <variable name="prev-last" select="$last-lines[($position)-1]"/>
+                       <variable name="linespans" select="(exslset:intersection(exslset:trailing($lines, $prev-last), exslset:leading($lines, .))|.)[normalize-space()!='']"/>
+                       <variable name="nospace" select="translate($linespans[1], ' &#x9;', '')"/>
+                       <variable name="firstnolevel" select="substring(translate($nospace, '⋮', ''), 1, 1)"/>
+                       <variable name="levelling">
                                <choose>
-                                       <when test="position()!=last()">
-                                               <text>-&#x034F;-</text>
+                                       <when test="$firstnolevel!=''">
+                                               <value-of select="substring-before($linespans[1], $firstnolevel)"/>
                                        </when>
+                                       <otherwise>
+                                               <value-of select="$linespans[1]"/>
+                                       </otherwise>
                                </choose>
-                       </for-each>
-               </comment>
-       </template>
-       <template name="LesML:id-and-contents">
-               <param name="source"/>
-               <variable name="id-and-lang">
-                       <if test="starts-with($source, '¶')">
+                       </variable>
+                       <variable name="nested-bullet">
+                               <choose>
+                                       <when test="contains('◦▪⁃', $firstnolevel)">
+                                               <value-of select="$firstnolevel"/>
+                                       </when>
+                                       <otherwise/>
+                               </choose>
+                       </variable>
+                       <variable name="level-modifier">
                                <choose>
-                                       <when test="contains($source, ' ')">
-                                               <value-of select="substring-before(substring-after($source, '¶'), ' ')"/>
+                                       <when test="$nested-bullet='◦'">
+                                               <text>1</text>
+                                       </when>
+                                       <when test="$nested-bullet='▪'">
+                                               <text>2</text>
+                                       </when>
+                                       <when test="$nested-bullet='⁃'">
+                                               <text>3</text>
                                        </when>
                                        <otherwise>
-                                               <value-of select="substring-after($source, '¶')"/>
+                                               <text>0</text>
                                        </otherwise>
                                </choose>
-                       </if>
-               </variable>
-               <variable name="restoftext">
-                       <choose>
-                               <when test="starts-with($source, '¶') and contains($source, ' ')">
-                                       <value-of select="substring-after($source, ' ')"/>
-                               </when>
-                               <when test="starts-with($source, '¶')"/>
-                               <otherwise>
-                                       <value-of select="$source"/>
-                               </otherwise>
-                       </choose>
-               </variable>
-               <variable name="maybe-langtag">
-                       <if test="substring($id-and-lang, string-length($id-and-lang), 1)='$' and contains($id-and-lang, '@')">
-                               <value-of select="LesML:split(substring($id-and-lang, 2, string-length($id-and-lang)-2), '@')[last()]"/>
-                       </if>
-               </variable>
-               <variable name="langtag">
-                       <if test="translate($maybe-langtag, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-', '')=''">
-                               <value-of select="$maybe-langtag"/>
-                       </if>
-               </variable>
-               <variable name="id">
-                       <choose>
-                               <when test="string($langtag)!=''">
-                                       <value-of select="substring($id-and-lang, 1, string-length($id-and-lang)-(string-length($langtag)+2))"/>
-                               </when>
-                               <otherwise>
-                                       <value-of select="$id-and-lang"/>
-                               </otherwise>
-                       </choose>
-               </variable>
-               <if test="string($id)!=''">
-                       <attribute name="id">
-                               <value-of select="$id"/>
-                       </attribute>
-               </if>
-               <if test="string($langtag)!=''">
-                       <attribute name="lang">
-                               <value-of select="$langtag"/>
-                       </attribute>
-                       <attribute name="xml:lang">
-                               <value-of select="$langtag"/>
-                       </attribute>
-               </if>
-               <value-of select="$restoftext"/>
-       </template>
-       <template name="LesML:parse">
-               <param name="lines" select="/.."/>
-               <param name="parent-params" select="/.."/>
-               <variable name="first-line" select="$lines[1]"/>
-               <variable name="shebang">
-                       <if test="starts-with($first-line, '#!lesml')">
-                               <value-of select="$first-line"/>
-                       </if>
-               </variable>
-               <variable name="params-string">
-                       <choose>
-                               <when test="starts-with($shebang, '#!lesml@')">
-                                       <value-of select="substring-after($shebang, '$')"/>
-                               </when>
+                       </variable>
+                       <variable name="nobullet">
+                               <choose>
+                                       <when test="$nested-bullet!=''">
+                                               <value-of select="substring-after($nospace, $nested-bullet)"/>
+                                       </when>
+                                       <otherwise>
+                                               <value-of select="concat($firstnolevel, substring-after($nospace, $firstnolevel))"/>
+                                       </otherwise>
+                               </choose>
+                       </variable>
+                       <variable name="firstnosigil" select="substring(translate($nobullet, '•№※⯑∫☡⚠🛈💡»∎', ''), 1, 1)"/>
+                       <variable name="sigilling">
+                               <choose>
+                                       <when test="$firstnosigil!=''">
+                                               <value-of select="substring-before(substring-after($linespans[1], concat($levelling, $nested-bullet)), $firstnosigil)"/>
+                                       </when>
+                                       <otherwise>
+                                               <value-of select="substring-after($linespans[1], concat($levelling, $nested-bullet))"/>
+                                       </otherwise>
+                               </choose>
+                       </variable>
+                       <variable name="nosigil">
+                               <value-of select="concat($firstnosigil, substring-after($nobullet, $firstnosigil))"/>
+                       </variable>
+                       <variable name="ruled" select="count($linespans)=1 and $nosigil!='' and translate($nosigil, $LESML_SECTION_BREAK_CHARS, '')=''"/>
+                       <variable name="prefix">
+                               <choose>
+                                       <when test="not($ruled) and $firstnosigil='|'">
+                                               <variable name="postpipe" select="substring-after($linespans[1], '|')"/>
+                                               <choose>
+                                                       <when test="substring(translate($postpipe, '0123456789abcdefghijklmnopqrstuvwxyz/.-', ''), 1, 1)='$'">
+                                                               <value-of select="concat(substring-before($linespans[1], '$'), '$')"/>
+                                                       </when>
+                                                       <otherwise>
+                                                               <value-of select="concat(substring-before($linespans[1], '|'), '|')"/>
+                                                       </otherwise>
+                                               </choose>
+                                       </when>
+                                       <when test="not($ruled) and contains('⁌§❦✠#^', $firstnosigil)">
+                                               <value-of select="concat(substring-before($linespans[1], $firstnosigil), $firstnosigil)"/>
+                                       </when>
+                                       <when test="$firstnosigil!=''">
+                                               <value-of select="substring-before($linespans[1], $firstnosigil)"/>
+                                       </when>
+                                       <otherwise>
+                                               <value-of select="$linespans[1]"/>
+                                       </otherwise>
+                               </choose>
+                       </variable>
+                       <variable name="preformatted" select="$firstnosigil='|' and not($linespans[not(starts-with(., $prefix))])"/>
+                       <variable name="inner-lines-fragment">
+                               <for-each select="$linespans">
+                                       <choose>
+                                               <when test="$preformatted or position()=1">
+                                                       <html:span>
+                                                               <value-of select="substring-after(., $prefix)"/>
+                                                       </html:span>
+                                               </when>
+                                               <otherwise>
+                                                       <copy-of select="."/>
+                                               </otherwise>
+                                       </choose>
+                               </for-each>
+                       </variable>
+                       <variable name="inner-lines" select="exsl:node-set($inner-lines-fragment)/node()"/>
+                       <call-template name="LesML:expand-sigils">
+                               <with-param name="sigils" select="exslstr:tokenize(translate(concat($nested-bullet, $sigilling), '◦▪⁃ &#x9;', '•••'), '')"/>
+                               <with-param name="level" select="string-length(translate($levelling, ' &#x9;', ''))+$level-modifier"/>
+                               <with-param name="partype">
+                                       <choose>
+                                               <when test="$preformatted">
+                                                       <text>pre</text>
+                                                       <if test="contains($prefix, '$')">
+                                                               <text> code</text>
+                                                       </if>
+                                               </when>
+                                               <when test="$ruled">
+                                                       <text>hr</text>
+                                               </when>
+                                               <when test="$firstnosigil='#'">
+                                                       <text>comment</text>
+                                               </when>
+                                               <when test="$firstnosigil='^'">
+                                                       <text>footnote</text>
+                                               </when>
+                                               <when test="$firstnosigil='⁌'">
+                                                       <text>h1</text>
+                                               </when>
+                                               <when test="$firstnosigil='§'">
+                                                       <text>h2</text>
+                                               </when>
+                                               <when test="$firstnosigil='❦'">
+                                                       <text>h3</text>
+                                               </when>
+                                               <when test="$firstnosigil='✠'">
+                                                       <text>h4</text>
+                                               </when>
+                                               <otherwise/>
+                                       </choose>
+                               </with-param>
+                               <with-param name="syntax" select="substring-before(substring-after($prefix, '|'), '$')"/>
+                               <with-param name="lines" select="$inner-lines"/>
+                       </call-template>
+               </for-each>
+       </template>
+       <template name="LesML:paragraphize">
+               <param name="lines" select="/.."/>
+               <variable name="chunked-fragment">
+                       <call-template name="LesML:chunk">
+                               <with-param name="lines" select="$lines"/>
+                       </call-template>
+               </variable>
+               <apply-templates select="exsl:node-set($chunked-fragment)" mode="LesML:blockify"/>
+       </template>
+       <template name="LesML:parse">
+               <param name="lines" select="/.."/>
+               <param name="parent-params" select="/.."/>
+               <variable name="first-line" select="$lines[1]"/>
+               <variable name="shero">
+                       <if test="starts-with($first-line, '#?lesml')">
+                               <value-of select="$first-line"/>
+                       </if>
+               </variable>
+               <variable name="params-string">
+                       <choose>
+                               <when test="starts-with($shero, '#?lesml@')">
+                                       <value-of select="substring-after($shero, '$')"/>
+                               </when>
                                <otherwise>
-                                       <value-of select="substring-after($shebang, '#!lesml')"/>
+                                       <value-of select="substring-after($shero, '#?lesml')"/>
                                </otherwise>
                        </choose>
                </variable>
                <variable name="params-fragment">
                        <choose>
-                               <when test="$shebang!=''">
+                               <when test="$shero!=''">
                                        <html:dl>
-                                               <if test="starts-with($shebang, '#!lesml@') and contains($shebang, '$')">
+                                               <if test="starts-with($shero, '#?lesml@') and contains($shero, '$')">
                                                        <html:div>
                                                                <html:dt>
                                                                        <text> LANG </text>
                                                                </html:dt>
                                                                <html:dd>
-                                                                       <value-of select="substring-before(substring-after($shebang, '#!lesml@'), '$')"/>
+                                                                       <value-of select="substring-before(substring-after($shero, '#?lesml@'), '$')"/>
                                                                </html:dd>
                                                        </html:div>
                                                </if>
@@ -265,10 +646,10 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                </otherwise>
                        </choose>
                </variable>
-               <variable name="params" select="exsl:node-set($params-fragment)/*"/>
-               <variable name="noshebang" select="$lines[position()>1 or not(starts-with(., '#!lesml') or starts-with(., '##'))]"/>
-               <variable name="docsep" select="$noshebang[starts-with(., '#!lesml') or starts-with(., '##')][1]"/>
-               <variable name="doclines" select="exslset:leading($noshebang, $docsep)"/>
+               <variable name="params" select="exsl:node-set($params-fragment)/node()"/>
+               <variable name="noshero" select="$lines[position()>1 or not(starts-with(., '#?lesml') or starts-with(., '##'))]"/>
+               <variable name="docsep" select="$noshero[starts-with(., '#?lesml') or starts-with(., '##')][1]"/>
+               <variable name="doclines" select="exslset:leading($noshero, $docsep)"/>
                <if test="starts-with($first-line, '##') and $first-line!='##'">
                        <call-template name="LesML:comment-out">
                                <with-param name="source" select="substring-after($first-line, '##')"/>
@@ -281,27 +662,28 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                        <with-param name="lines" select="exslset:trailing($doclines, $record-separators[last()])"/>
                                </call-template>
                        </variable>
-                       <variable name="paragraphized" select="exsl:node-set($paragraphized-fragment)"/>
+                       <variable name="paragraphized-document" select="exsl:node-set($paragraphized-fragment)"/>
                        <variable name="filtered-ordered-footnotes-fragment">
-                               <for-each select="$paragraphized//html:li[processing-instruction()[local-name()='LesML-Footnote'] and html:p[position()=1 and @id]]">
-                                       <sort select="count(($paragraphized//html:a[@role='doc-noteref' and @href=concat('#', string(current()/html:p[1]/@id))])[1]/preceding::*)" data-type="number"/>
-                                       <if test="$paragraphized//html:a[@role='doc-noteref' and @href=concat('#', string(current()/html:p[1]/@id))]">
-                                               <copy-of select="."/>
+                               <for-each select="$paragraphized-document//processing-instruction()[local-name()='LesML-Footnote']">
+                                       <sort select="count(($paragraphized-document//html:a[@role='doc-noteref' and @href=concat('#', string(current()))])[1]/preceding::*)" data-type="number"/>
+                                       <if test="$paragraphized-document//html:a[@role='doc-noteref' and @href=concat('#', string(current()))]">
+                                               <copy-of select=".."/>
                                        </if>
                                </for-each>
                        </variable>
                        <variable name="used-footnotes-fragment">
                                <for-each select="exsl:node-set($filtered-ordered-footnotes-fragment)/node()">
-                                       <variable name="links" select="$paragraphized//html:a[@role='doc-noteref' and @href=concat('#', string(current()/html:p[1]/@id))]"/>
+                                       <variable name="footnote-id" select="processing-instruction()[local-name()='LesML-Footnote']"/>
+                                       <variable name="links" select="$paragraphized-document//html:a[@role='doc-noteref' and @href=concat('#', string($footnote-id))]"/>
                                        <element name="li" namespace="&xhtml;">
                                                <variable name="numero" select="position()"/>
                                                <attribute name="id">
-                                                       <value-of select="html:p[1]/@id"/>
+                                                       <value-of select="$footnote-id"/>
                                                </attribute>
                                                <attribute name="value">
                                                        <value-of select="$numero"/>
                                                </attribute>
-                                               <copy-of select="@*|node()"/>
+                                               <copy-of select="node()[not(self::processing-instruction() and local-name()='LesML-Footnote')]"/>
                                                <element name="footer" namespace="&xhtml;">
                                                        <attribute name="class">
                                                                <text>backlinks</text>
@@ -325,7 +707,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                        </element>
                                </for-each>
                        </variable>
-                       <variable name="used-footnote-nodes" select="exsl:node-set($used-footnotes-fragment)/node()"/>
+                       <variable name="used-footnotes" select="exsl:node-set($used-footnotes-fragment)/node()"/>
                        <element name="article" namespace="&xhtml;">
                                <for-each select="$params/html:div/html:dt[string()=' LANG ']">
                                        <attribute name="lang">
@@ -340,7 +722,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                                <value-of select="following-sibling::html:dd"/>
                                        </attribute>
                                </for-each>
-                               <if test="$record-separators[preceding-sibling::*[normalize-space()!='']]">
+                               <if test="$record-separators and exslset:difference(exslset:leading($doclines, $record-separators[last()]), $record-separators)[normalize-space()!='']">
                                        <element name="footer" namespace="&xhtml;">
                                                <attribute name="class">
                                                        <text>head</text>
@@ -348,14 +730,15 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                                <for-each select="$record-separators">
                                                        <variable name="position" select="position()"/>
                                                        <variable name="prev-separator" select="$record-separators[($position)-1]"/>
-                                                       <variable name="fields" select="exslset:leading(exslset:trailing($doclines, $prev-separator), .)"/>
+                                                       <variable name="fields" select="exslset:leading(exslset:trailing($doclines, $prev-separator), .)[normalize-space()!='']"/>
                                                        <if test="$fields">
                                                                <element name="dl" namespace="&xhtml;">
                                                                        <for-each select="$fields">
+                                                                               <variable name="following" select="exslset:intersection($fields, following-sibling::*)"/>
                                                                                <choose>
-                                                                                       <when test="starts-with(., ' ') and exslset:leading($fields, .)"/>
+                                                                                       <when test="contains(' &#x9;', substring(., 1, 1)) and exslset:has-same-node($fields, preceding-sibling::*[1])"/>
                                                                                        <otherwise>
-                                                                                               <variable name="next" select="exslset:intersection(following-sibling::*[not(starts-with(., ' '))][1], $fields)"/>
+                                                                                               <variable name="next" select="$following[not(contains(' &#x9;', substring(., 1, 1)))][1]"/>
                                                                                                <element name="div" namespace="&xhtml;">
                                                                                                        <element name="dt" namespace="&xhtml;">
                                                                                                                <value-of select="normalize-space(substring-before(., ':'))"/>
@@ -372,17 +755,17 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                                                                                                        </choose>
                                                                                                                </variable>
                                                                                                                <choose>
-                                                                                                                       <when test="substring($firstline, string-length($firstline))='\' and following-sibling::*[position()=1 and starts-with(., ' ')]">
+                                                                                                                       <when test="substring($firstline, string-length($firstline))='\' and $following[position()=1 and contains(' &#x9;', substring(., 1, 1))]">
                                                                                                                                <value-of select="substring($firstline, 1, string-length($firstline)-1)"/>
                                                                                                                        </when>
                                                                                                                        <otherwise>
                                                                                                                                <value-of select="$firstline"/>
                                                                                                                        </otherwise>
                                                                                                                </choose>
-                                                                                                               <for-each select="exslset:intersection(following-sibling::*[starts-with(., ' ')], exslset:leading($fields, $next))">
+                                                                                                               <for-each select="exslset:leading($following, $next)[contains(' &#x9;', substring(., 1, 1))]">
                                                                                                                        <variable name="nextline" select="normalize-space(.)"/>
                                                                                                                        <choose>
-                                                                                                                               <when test="substring($nextline, string-length($nextline))='\' and following-sibling::*[position()=1 and starts-with(., ' ')]">
+                                                                                                                               <when test="substring($nextline, string-length($nextline))='\' and exslset:intersection($fields, following-sibling::*)[position()=1 and contains(' &#x9;', substring(., 1, 1))]">
                                                                                                                                        <value-of select="substring($nextline, 1, string-length($nextline)-1)"/>
                                                                                                                                </when>
                                                                                                                                <otherwise>
@@ -397,7 +780,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                                                        </for-each>
                                                                </element>
                                                        </if>
-                                                       <if test=".!='%%'">
+                                                       <if test="substring-after(., '%%')!=''">
                                                                <call-template name="LesML:comment-out">
                                                                        <with-param name="source" select="substring-after(., '%%')"/>
                                                                </call-template>
@@ -409,18 +792,18 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                        <attribute name="class">
                                                <text>body</text>
                                        </attribute>
-                                       <apply-templates select="$paragraphized/node()" mode="LesML:finalize">
-                                               <with-param name="used-footnotes" select="$used-footnote-nodes"/>
+                                       <apply-templates select="$paragraphized-document/node()" mode="LesML:finalize">
+                                               <with-param name="used-footnotes" select="$used-footnotes"/>
                                        </apply-templates>
                                </element>
-                               <if test="$used-footnote-nodes">
+                               <if test="$used-footnotes">
                                        <element name="section" namespace="&xhtml;">
                                                <attribute name="role">
                                                        <text>doc-endnotes</text>
                                                </attribute>
                                                <element name="ol" namespace="&xhtml;">
-                                                       <apply-templates select="$used-footnote-nodes" mode="LesML:finalize">
-                                                               <with-param name="used-footnotes" select="$used-footnote-nodes"/>
+                                                       <apply-templates select="$used-footnotes" mode="LesML:finalize">
+                                                               <with-param name="used-footnotes" select="$used-footnotes"/>
                                                        </apply-templates>
                                                </element>
                                        </element>
@@ -434,389 +817,6 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                        </call-template>
                </if>
        </template>
-       <template name="LesML:block">
-               <param name="lines" select="/.."/>
-               <variable name="last-lines" select="$lines[normalize-space()!='' and (normalize-space(following-sibling::*[1])='' or position()=last())]"/>
-               <for-each select="$last-lines">
-                       <variable name="position" select="position()"/>
-                       <variable name="prev-last" select="$last-lines[($position)-1]"/>
-                       <variable name="linespans" select="(exslset:intersection(exslset:trailing($lines, $prev-last), exslset:leading($lines, .))|.)[normalize-space()!='']"/>
-                       <variable name="prefix" select="substring(translate(., ' &#x9;', ''), 1, 1)"/>
-                       <variable name="all-prefixed" select="not($linespans[not(starts-with(translate(., ' &#x9;', ''), $prefix))])"/>
-                       <variable name="quoted" select="$all-prefixed and $prefix='»'"/>
-                       <variable name="bracketed" select="$all-prefixed and $prefix=']'"/>
-                       <choose>
-                               <when test="count($linespans)=1 and translate(., concat($LESML_SECTION_BREAK_CHARS, ' &#x9;'), '')=''">
-                                       <element name="hr" namespace="&xhtml;"/>
-                               </when>
-                               <when test="$quoted or $bracketed">
-                                       <variable name="innerlines-fragment">
-                                               <for-each select="$linespans">
-                                                       <variable name="inner">
-                                                               <value-of select="substring-after(., $prefix)"/>
-                                                       </variable>
-                                                       <copy>
-                                                               <choose>
-                                                                       <when test="starts-with($inner, ' ') or starts-with($inner, '&#x9;')">
-                                                                               <value-of select="substring($inner, 1+count(exslstr:tokenize($inner, '')[normalize-space()='' and not(preceding-sibling::*[normalize-space()!=''])]))"/>
-                                                                       </when>
-                                                                       <otherwise>
-                                                                               <value-of select="$inner"/>
-                                                                       </otherwise>
-                                                               </choose>
-                                                       </copy>
-                                               </for-each>
-                                       </variable>
-                                       <variable name="blocked-fragment">
-                                               <call-template name="LesML:block">
-                                                       <with-param name="lines" select="exsl:node-set($innerlines-fragment)/*"/>
-                                               </call-template>
-                                       </variable>
-                                       <variable name="innerpars" select="exsl:node-set($blocked-fragment)/node()"/>
-                                       <choose>
-                                               <when test="$quoted and $innerpars[position()=last() and self::html:footer]">
-                                                       <element name="figure" namespace="&xhtml;">
-                                                               <element name="blockquote" namespace="&xhtml;">
-                                                                       <copy-of select="$innerpars[position()!=last()]"/>
-                                                               </element>
-                                                               <element name="figcaption" namespace="&xhtml;">
-                                                                       <copy-of select="$innerpars[last()]/node()"/>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="$quoted">
-                                                       <element name="blockquote" namespace="&xhtml;">
-                                                               <copy-of select="$innerpars"/>
-                                                       </element>
-                                               </when>
-                                               <when test="$bracketed">
-                                                       <element name="footer" namespace="&xhtml;">
-                                                               <copy-of select="$innerpars"/>
-                                                       </element>
-                                               </when>
-                                       </choose>
-                               </when>
-                               <otherwise>
-                                       <variable name="preformatted" select="$all-prefixed and $prefix='|'"/>
-                                       <variable name="text">
-                                               <for-each select="$linespans">
-                                                       <choose>
-                                                               <when test="$preformatted">
-                                                                       <value-of select="substring-after(., '|')"/>
-                                                               </when>
-                                                               <otherwise>
-                                                                       <value-of select="normalize-space()"/>
-                                                               </otherwise>
-                                                       </choose>
-                                                       <if test="position()!=count($linespans)">
-                                                               <choose>
-                                                                       <when test="$preformatted">
-                                                                               <text>&#xA;</text>
-                                                                       </when>
-                                                                       <otherwise>
-                                                                               <text> </text>
-                                                                       </otherwise>
-                                                               </choose>
-                                                       </if>
-                                               </for-each>
-                                       </variable>
-                                       <choose>
-                                               <when test="$preformatted">
-                                                       <element name="pre" namespace="&xhtml;">
-                                                               <call-template name="LesML:id-and-contents">
-                                                                       <with-param name="source" select="$text"/>
-                                                               </call-template>
-                                                       </element>
-                                               </when>
-                                               <when test="string($text)=''"/>
-                                               <when test="starts-with($text, '⁌') and &sigiled-text;">
-                                                       <element name="h1" namespace="&xhtml;">
-                                                               <call-template name="LesML:id-and-contents">
-                                                                       <with-param name="source" select="&unsigiled-text;"/>
-                                                               </call-template>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '§') and &sigiled-text;">
-                                                       <element name="h2" namespace="&xhtml;">
-                                                               <call-template name="LesML:id-and-contents">
-                                                                       <with-param name="source" select="&unsigiled-text;"/>
-                                                               </call-template>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '❦') and &sigiled-text;">
-                                                       <element name="h3" namespace="&xhtml;">
-                                                               <call-template name="LesML:id-and-contents">
-                                                                       <with-param name="source" select="&unsigiled-text;"/>
-                                                               </call-template>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '✠') and &sigiled-text;">
-                                                       <element name="h4" namespace="&xhtml;">
-                                                               <call-template name="LesML:id-and-contents">
-                                                                       <with-param name="source" select="&unsigiled-text;"/>
-                                                               </call-template>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '•') and &sigiled-text;">
-                                                       <element name="li" namespace="&xhtml;">
-                                                               <attribute name="class">
-                                                                       <text>unordered</text>
-                                                               </attribute>
-                                                               <attribute name="data-level">
-                                                                       <text>1</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '🔢') and &sigiled-text;">
-                                                       <element name="li" namespace="&xhtml;">
-                                                               <attribute name="class">
-                                                                       <text>ordered</text>
-                                                               </attribute>
-                                                               <attribute name="data-level">
-                                                                       <text>1</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '◦') and &sigiled-text;">
-                                                       <element name="li" namespace="&xhtml;">
-                                                               <attribute name="class">
-                                                                       <text>unordered</text>
-                                                               </attribute>
-                                                               <attribute name="data-level">
-                                                                       <text>2</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '🔠') and &sigiled-text;">
-                                                       <element name="li" namespace="&xhtml;">
-                                                               <attribute name="class">
-                                                                       <text>ordered</text>
-                                                               </attribute>
-                                                               <attribute name="data-level">
-                                                                       <text>2</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '▪') and &sigiled-text;">
-                                                       <element name="li" namespace="&xhtml;">
-                                                               <attribute name="class">
-                                                                       <text>unordered</text>
-                                                               </attribute>
-                                                               <attribute name="data-level">
-                                                                       <text>3</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '🔡') and &sigiled-text;">
-                                                       <element name="li" namespace="&xhtml;">
-                                                               <attribute name="class">
-                                                                       <text>ordered</text>
-                                                               </attribute>
-                                                               <attribute name="data-level">
-                                                                       <text>3</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '⁃') and &sigiled-text;">
-                                                       <element name="li" namespace="&xhtml;">
-                                                               <attribute name="class">
-                                                                       <text>unordered</text>
-                                                               </attribute>
-                                                               <attribute name="data-level">
-                                                                       <text>4</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '🔣') and &sigiled-text;">
-                                                       <element name="li" namespace="&xhtml;">
-                                                               <attribute name="class">
-                                                                       <text>ordered</text>
-                                                               </attribute>
-                                                               <attribute name="data-level">
-                                                                       <text>4</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '※') and &sigiled-text;">
-                                                       <element name="section" namespace="&xhtml;">
-                                                               <attribute name="role">
-                                                                       <text>note</text>
-                                                               </attribute>
-                                                               <attribute name="class">
-                                                                       <text>note</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '☡') and &sigiled-text;">
-                                                       <element name="section" namespace="&xhtml;">
-                                                               <attribute name="role">
-                                                                       <text>note</text>
-                                                               </attribute>
-                                                               <attribute name="class">
-                                                                       <text>caution</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '⯑') and &sigiled-text;">
-                                                       <element name="section" namespace="&xhtml;">
-                                                               <attribute name="role">
-                                                                       <text>note</text>
-                                                               </attribute>
-                                                               <attribute name="class">
-                                                                       <text>query</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '@') and &sigiled-text;">
-                                                       <element name="section" namespace="&xhtml;">
-                                                               <attribute name="role">
-                                                                       <text>doc-abstract</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '🛈') and &sigiled-text;">
-                                                       <element name="section" namespace="&xhtml;">
-                                                               <attribute name="role">
-                                                                       <text>doc-tip</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '⚠') and &sigiled-text;">
-                                                       <element name="section" namespace="&xhtml;">
-                                                               <attribute name="role">
-                                                                       <text>doc-notice</text>
-                                                               </attribute>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '⋯') and &sigiled-text;">
-                                                       <element name="div" namespace="&xhtml;">
-                                                               <processing-instruction name="LesML-Continuation"/>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '^') and &sigiled-text;">
-                                                       <element name="li" namespace="&xhtml;">
-                                                               <attribute name="class">
-                                                                       <text>ordered footnote</text>
-                                                               </attribute>
-                                                               <attribute name="data-level">
-                                                                       <text>1</text>
-                                                               </attribute>
-                                                               <processing-instruction name="LesML-Footnote"/>
-                                                               <element name="p" namespace="&xhtml;">
-                                                                       <call-template name="LesML:id-and-contents">
-                                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                                       </call-template>
-                                                               </element>
-                                                       </element>
-                                               </when>
-                                               <when test="starts-with($text, '#') and &sigiled-text;">
-                                                       <call-template name="LesML:comment-out">
-                                                               <with-param name="source" select="&unsigiled-text;"/>
-                                                       </call-template>
-                                               </when>
-                                               <otherwise>
-                                                       <element name="p" namespace="&xhtml;">
-                                                               <call-template name="LesML:id-and-contents">
-                                                                       <with-param name="source" select="$text"/>
-                                                               </call-template>
-                                                       </element>
-                                               </otherwise>
-                                       </choose>
-                               </otherwise>
-                       </choose>
-               </for-each>
-       </template>
-       <template name="LesML:paragraphize">
-               <param name="lines" select="/.."/>
-               <variable name="blocked-fragment">
-                       <call-template name="LesML:block">
-                               <with-param name="lines" select="$lines"/>
-                       </call-template>
-               </variable>
-               <variable name="blocked" select="exsl:node-set($blocked-fragment)"/>
-               <variable name="footnote-ids" select="$blocked//html:li[processing-instruction()[local-name()='LesML-Footnote']]/html:p[1]/@id"/>
-               <variable name="inlined-fragment">
-                       <apply-templates select="$blocked/node()" mode="LesML:comment">
-                               <with-param name="footnote-ids" select="$footnote-ids"/>
-                       </apply-templates>
-               </variable>
-               <apply-templates select="exsl:node-set($inlined-fragment)/node()" mode="LesML:finalize-tree"/>
-       </template>
        <template match="html:script[@type='text/lesml']">
                <variable name="source">
                        <for-each select=".//text()">
@@ -829,294 +829,142 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                        </call-template>
                </element>
        </template>
-       <template match="html:ol[processing-instruction()[local-name()='LesML-Footnote']]|processing-instruction()[local-name()='LesML-Footnote']" mode="LesML:finalize" priority="1"/>
-       <template match="html:a[@role='doc-noteref']" mode="LesML:finalize">
-               <param name="used-footnotes" select="/.."/>
-               <variable name="matching-note" select="$used-footnotes[concat('#', @id)=current()/@href]"/>
-               <copy>
-                       <apply-templates select="@*" mode="LesML:finalize">
-                               <with-param name="used-footnotes" select="$used-footnotes"/>
-                       </apply-templates>
-                       <choose>
-                               <when test="$matching-note">
-                                       <value-of select="$matching-note/@value"/>
-                               </when>
-                               <otherwise>
-                                       <apply-templates select="node()" mode="LesML:finalize">
-                                               <with-param name="used-footnotes" select="$used-footnotes"/>
-                                       </apply-templates>
-                               </otherwise>
-                       </choose>
-               </copy>
+       <template match="/" mode="LesML:blockify">
+               <variable name="nested-fragment">
+                       <apply-templates mode="LesML:nesting-blocks"/>
+               </variable>
+               <variable name="nested-document" select="exsl:node-set($nested-fragment)"/>
+               <apply-templates select="exsl:node-set($nested-fragment)/node()" mode="LesML:inlinify">
+                       <with-param name="footnote-ids" select="$nested-document/*/processing-instruction()[local-name()='LesML-Footnote']"/>
+               </apply-templates>
        </template>
-       <template match="html:p[position()=1 and ancestor::*]" mode="LesML:finalize">
-               <param name="used-footnotes" select="/.."/>
-               <variable name="content" select="@*[not(&pilcrow-atts;)]|node()"/>
-               <if test="$content">
+       <template match="*[&level-pi;]" mode="LesML:nesting-blocks">
+               <variable name="current-level" select="number(&level-pi;)"/>
+               <if test="not(preceding-sibling::*[&level-pi; and $current-level>&level-pi;])">
+                       <variable name="notatlevel" select="following-sibling::*[$current-level>=&level-pi;][1]"/>
+                       <variable name="contents-fragment">
+                               <copy-of select="node()"/>
+                               <copy-of select="exslset:leading(following-sibling::*, $notatlevel)"/>
+                       </variable>
                        <copy>
-                               <apply-templates select="$content" mode="LesML:finalize">
-                                       <with-param name="used-footnotes" select="$used-footnotes"/>
-                               </apply-templates>
+                               <copy-of select="@*"/>
+                               <apply-templates select="exsl:node-set($contents-fragment)/node()" mode="LesML:nesting-blocks"/>
                        </copy>
                </if>
        </template>
-       <template match="html:section" mode="LesML:finalize">
-               <param name="used-footnotes" select="/.."/>
-               <variable name="notinsection" select="following-sibling::node()[not(html:li/@data-level>1)][1]"/>
+       <template match="node()" mode="LesML:nesting-blocks" priority="-1">
                <copy>
-                       <apply-templates select="@*|html:p[1]/@*[&pilcrow-atts;]" mode="LesML:finalize"/>
-                       <apply-templates select="node()" mode="LesML:finalize"/>
-                       <for-each select="exslset:leading(following-sibling::node(), $notinsection)">
-                               <copy>
-                                       <apply-templates select="@*|node()" mode="LesML:finalize">
-                                               <with-param name="used-footnotes" select="$used-footnotes"/>
-                                       </apply-templates>
-                               </copy>
-                       </for-each>
+                       <copy-of select="@*"/>
+                       <apply-templates select="node()" mode="LesML:nesting-blocks"/>
                </copy>
        </template>
-       <template match="html:*[html:li/@data-level>1]" mode="LesML:finalize">
-               <param name="used-footnotes" select="/.."/>
-               <if test="not(preceding-sibling::node()[not(html:li/@data-level>1)][1]/self::html:section)">
-                       <copy>
-                               <apply-templates select="@*|node()" mode="LesML:finalize">
-                                       <with-param name="used-footnotes" select="$used-footnotes"/>
-                               </apply-templates>
-                       </copy>
-               </if>
-       </template>
-       <template match="text()" mode="LesML:finalize">
-               <call-template name="LesML:break-and-unescape">
-                       <with-param name="source" select="string()"/>
-               </call-template>
-       </template>
-       <template match="@*|node()" mode="LesML:finalize" priority="-1">
-               <param name="used-footnotes" select="/.."/>
+       <template match="*[&level-pi;]" mode="LesML:inlinify">
+               <param name="footnote-ids" select="/.."/>
                <copy>
-                       <apply-templates select="@*|html:p[1]/@*[&pilcrow-atts;]" mode="LesML:finalize"/>
-                       <apply-templates select="node()" mode="LesML:finalize">
-                               <with-param name="used-footnotes" select="$used-footnotes"/>
+                       <copy-of select="@*"/>
+                       <apply-templates mode="LesML:inlinify">
+                               <with-param name="footnote-ids" select="$footnote-ids|*/processing-instruction()[local-name()='LesML-Footnote']"/>
                        </apply-templates>
                </copy>
        </template>
-       <template match="node()" mode="LesML:finalize-attributes">
-               <variable name="notattr" select="following-sibling::node()[not(self::text() and translate(., ' &#x9;', '')='' or self::LesML:attribute)]"/>
-               <for-each select="(.|exslset:leading(following-sibling::node(), $notattr)[self::LesML:attribute])/@*">
-                       <copy-of select="."/>
-                       <if test="local-name()='lang' and namespace-uri()=''">
-                               <attribute name="xml:lang">
-                                       <value-of select="."/>
-                               </attribute>
-                       </if>
-               </for-each>
-       </template>
-       <template match="html:li" mode="LesML:finalize-list">
-               <param name="parent-level" select="0"/>
-               <variable name="current-class" select="string(@class)"/>
-               <variable name="current-level" select="number(@data-level)"/>
-               <variable name="wrapper">
-                       <choose>
-                               <when test="contains(concat(' ', @class, ' '), ' ordered ')">
-                                       <text>ol</text>
-                               </when>
-                               <otherwise>
-                                       <text>ul</text>
-                               </otherwise>
-                       </choose>
-               </variable>
-               <variable name="notinlist" select="following-sibling::node()[not(self::html:div/processing-instruction()[local-name()='LesML-Continuation'] or self::html:li and (@data-level>$current-level or @data-level=$current-level and @class=$current-class))][1]"/>
-               <element name="{$wrapper}" namespace="&xhtml;">
-                       <if test="contains(concat(' ', @class, ' '), ' footnote ')">
-                               <processing-instruction name="LesML-Footnote"/>
-                       </if>
-                       <for-each select=".|exslset:leading(following-sibling::node(), $notinlist)[self::html:li and @data-level=$current-level]">
-                               <variable name="notcontinuation" select="following-sibling::node()[not(self::html:div/processing-instruction()[local-name()='LesML-Continuation'])][1]"/>
-                               <copy>
-                                       <apply-templates select="@*|node()" mode="LesML:finalize-tree"/>
-                                       <for-each select="exslset:leading(following-sibling::node(), $notcontinuation)">
-                                               <apply-templates select="node()" mode="LesML:finalize-tree"/>
-                                       </for-each>
-                                       <if test="$notcontinuation/self::html:li[@data-level>$current-level]">
-                                               <apply-templates select="$notcontinuation" mode="LesML:finalize-list">
-                                                       <with-param name="parent-level" select="$current-level"/>
-                                               </apply-templates>
-                                       </if>
-                               </copy>
-                       </for-each>
-               </element>
-               <if test="$notinlist/self::html:li[@data-level>$parent-level]">
-                       <apply-templates select="$notinlist" mode="LesML:finalize-list">
-                               <with-param name="parent-level" select="$parent-level"/>
-                       </apply-templates>
-               </if>
-       </template>
-       <template match="LesML:attribute[preceding-sibling::node()[position()=1 and (self::text() or self::*)]]|text()[preceding-sibling::node()[position()=1 and self::*] and following-sibling::node()[position()=1 and self::LesML:attribute] and translate(., ' &#x9;', '')='']" mode="LesML:finalize-tree" priority="2"/>
-       <template match="LesML:attribute|text()[following-sibling::node()[position()=1 and self::LesML:attribute]]" mode="LesML:finalize-tree" priority="1">
-               <element name="span" namespace="&xhtml;">
-                       <apply-templates select="." mode="LesML:finalize-attributes"/>
-                       <if test="self::text()">
-                               <copy/>
-                       </if>
-               </element>
-       </template>
-       <template match="html:div" mode="LesML:finalize-tree">
-               <if test="not(processing-instruction()[local-name()='LesML-Continuation']) or not(preceding-sibling::node()[position()=1 and self::html:* and contains(' div h1 h2 h3 h4 h5 h6 li section ', local-name())])">
-                       <variable name="notcontinuation" select="following-sibling::node()[not(self::html:div/processing-instruction()[local-name()='LesML-Continuation'])][1]"/>
-                       <choose>
-                               <when test="processing-instruction()[local-name()='LesML-Continuation'] and $notcontinuation[self::html:* and contains(' h1 h2 h3 h4 h5 h6 ', local-name())]">
-                                       <variable name="notcontinuation2" select="$notcontinuation/following-sibling::node()[not(self::html:div/processing-instruction()[local-name()='LesML-Continuation'])][1]"/>
-                                       <element name="hgroup" namespace="&xhtml;">
-                                               <apply-templates select="node()" mode="LesML:finalize-tree"/>
-                                               <for-each select="exslset:leading(following-sibling::node(), $notcontinuation2)">
-                                                       <choose>
-                                                               <when test="self::html:div">
-                                                                       <apply-templates select="node()" mode="LesML:finalize-tree"/>
-                                                               </when>
-                                                               <otherwise>
-                                                                       <copy>
-                                                                               <apply-templates select="@*|node()" mode="LesML:finalize-tree"/>
-                                                                       </copy>
-                                                               </otherwise>
-                                                       </choose>
-                                               </for-each>
-                                       </element>
-                               </when>
-                               <when test="not(processing-instruction()[local-name()='LesML-Continuation'])">
-                                       <copy>
-                                               <apply-templates select="@*|node()" mode="LesML:finalize-tree"/>
-                                               <for-each select="exslset:leading(following-sibling::node(), $notcontinuation)">
-                                                       <apply-templates select="node()" mode="LesML:finalize-tree"/>
-                                               </for-each>
-                                       </copy>
-                               </when>
-                               <otherwise>
-                                       <apply-templates select="node()" mode="LesML:finalize-tree"/>
-                                       <for-each select="exslset:leading(following-sibling::node(), $notcontinuation)">
-                                               <apply-templates select="node()" mode="LesML:finalize-tree"/>
-                                       </for-each>
-                               </otherwise>
-                       </choose>
-               </if>
+       <template match="node()" mode="LesML:inlinify" priority="-1">
+               <param name="footnote-ids" select="/.."/>
+               <apply-templates select="." mode="LesML:comment">
+                       <with-param name="footnote-ids" select="$footnote-ids"/>
+               </apply-templates>
        </template>
-       <template match="html:h1|html:h2|html:h3|html:h4|html:h5|html:h6" mode="LesML:finalize-tree">
-               <if test="not(preceding-sibling::node()[position()=1 and self::html:div/processing-instruction()[local-name()='LesML-Continuation']]) or preceding-sibling::node()[not(self::html:div/processing-instruction()[local-name()='LesML-Continuation'])][position()=1 and self::html:* and contains(' h1 h2 h3 h4 h5 h6 ', local-name())]">
+       <template match="node()" mode="LesML:comment">
+               <param name="footnote-ids" select="/.."/>
+               <variable name="result-fragment">
                        <choose>
-                               <when test="following-sibling::node()[position()=1 and self::html:div]/processing-instruction()[local-name()='LesML-Continuation']">
-                                       <variable name="notcontinuation" select="following-sibling::node()[not(self::html:div/processing-instruction()[local-name()='LesML-Continuation'])][1]"/>
-                                       <element name="hgroup" namespace="&xhtml;">
-                                               <copy>
-                                                       <apply-templates select="@*|node()" mode="LesML:finalize-tree"/>
-                                               </copy>
-                                               <for-each select="exslset:leading(following-sibling::node(), $notcontinuation)">
-                                                       <apply-templates select="node()" mode="LesML:finalize-tree"/>
-                                               </for-each>
-                                       </element>
-                               </when>
-                               <otherwise>
-                                       <copy>
-                                               <apply-templates select="@*|node()" mode="LesML:finalize-tree"/>
-                                       </copy>
-                               </otherwise>
-                       </choose>
-               </if>
-       </template>
-       <template match="html:li" mode="LesML:finalize-tree">
-               <if test="not(preceding-sibling::node()) or preceding-sibling::node()[not(preceding-sibling::* and self::html:div/processing-instruction()[local-name()='LesML-Continuation'])][position()=1 and not(self::html:li)]">
-                       <apply-templates select="." mode="LesML:finalize-list"/>
-               </if>
-       </template>
-       <template match="html:section" mode="LesML:finalize-tree">
-               <variable name="notcontinuation" select="following-sibling::node()[not(self::html:div/processing-instruction()[local-name()='LesML-Continuation'])][1]"/>
-               <copy>
-                       <apply-templates select="@*|node()" mode="LesML:finalize-tree"/>
-                       <for-each select="exslset:leading(following-sibling::node(), $notcontinuation)">
-                               <apply-templates select="node()" mode="LesML:finalize-tree"/>
-                       </for-each>
-               </copy>
-       </template>
-       <template match="processing-instruction()[local-name()='LesML-Continuation']" mode="LesML:finalize-tree"/>
-       <template match="processing-instruction()[local-name()='LesML-Token-Escape']" mode="LesML:finalize-tree">
-               <value-of select="."/>
-       </template>
-       <template match="@*|node()" mode="LesML:finalize-tree" priority="-1">
-               <copy>
-                       <apply-templates select="." mode="LesML:finalize-attributes"/>
-                       <apply-templates select="node()" mode="LesML:finalize-tree"/>
-               </copy>
-       </template>
-       <template match="node()" mode="LesML:inline">
-               <param name="element-name"/>
-               <param name="element-namespace" select="'http://www.w3.org/1999/xhtml'"/>
-               <param name="start-sigil"/>
-               <param name="end-sigil"/>
-               <param name="class"/>
-               <param name="role"/>
-               <choose>
-                       <when test="self::*">
-                               <variable name="end-node" select="text()[contains(., $end-sigil)][1]"/>
-                               <variable name="has-start-node" select="$end-node/preceding-sibling::text()[contains(., $start-sigil)] or string-length(substring-after($end-node, $start-sigil))>string-length(substring-after($end-node, $end-sigil))"/>
-                               <choose>
-                                       <when test="$end-node and $has-start-node">
-                                               <variable name="preceding">
-                                                       <copy-of select="$end-node/preceding-sibling::node()"/>
-                                                       <value-of select="substring-before($end-node, $end-sigil)"/>
-                                               </variable>
-                                               <variable name="start-node" select="exsl:node-set($preceding)/text()[contains(., $start-sigil)][last()]"/>
-                                               <variable name="start-tokens" select="LesML:split($start-node, $start-sigil)"/>
-                                               <variable name="wrapped">
+                               <when test="self::*">
+                                       <variable name="start-node" select="text()[contains(., '⌦')][1]"/>
+                                       <variable name="after-start">
+                                               <if test="$start-node">
+                                                       <value-of select="substring-after($start-node, '⌦')"/>
+                                               </if>
+                                       </variable>
+                                       <variable name="has-end-node" select="contains($after-start, '⌫') or $start-node/following-sibling::text()[contains(., '⌫')]"/>
+                                       <choose>
+                                               <when test="$start-node and $has-end-node">
+                                                       <variable name="following">
+                                                               <value-of select="$after-start"/>
+                                                               <copy-of select="$start-node/following-sibling::node()"/>
+                                                       </variable>
+                                                       <variable name="end-node" select="exsl:node-set($following)/text()[contains(., '⌫')][last()]"/>
+                                                       <variable name="comment">
+                                                               <for-each select="$end-node/preceding-sibling::node()">
+                                                                       <value-of select="."/>
+                                                               </for-each>
+                                                               <value-of select="substring-before($end-node, '⌫')"/>
+                                                       </variable>
+                                                       <variable name="rest-fragment">
+                                                               <element name="span" namespace="&xhtml;">
+                                                                       <value-of select="substring-after($end-node, '⌫')"/>
+                                                                       <copy-of select="$end-node/following-sibling::node()"/>
+                                                               </element>
+                                                       </variable>
+                                                       <variable name="commented-rest-fragment">
+                                                               <apply-templates select="exsl:node-set($rest-fragment)/node()" mode="LesML:comment">
+                                                                       <with-param name="footnote-ids" select="$footnote-ids"/>
+                                                               </apply-templates>
+                                                       </variable>
+                                                       <copy>
+                                                               <copy-of select="@*"/>
+                                                               <copy-of select="$start-node/preceding-sibling::node()"/>
+                                                               <copy-of select="substring-before($start-node, '⌦')"/>
+                                                               <call-template name="LesML:comment-out">
+                                                                       <with-param name="source" select="string($comment)"/>
+                                                               </call-template>
+                                                               <copy-of select="exsl:node-set($commented-rest-fragment)/*/node()"/>
+                                                       </copy>
+                                               </when>
+                                               <when test="$start-node">
+                                                       <variable name="rest-fragment">
+                                                               <element name="div" namespace="&xhtml;">
+                                                                       <value-of select="substring-after($after-start, '⌦')"/>
+                                                                       <copy-of select="$start-node/following-sibling::node()"/>
+                                                               </element>
+                                                       </variable>
+                                                       <variable name="commented-rest-fragment">
+                                                               <apply-templates select="exsl:node-set($rest-fragment)/node()" mode="LesML:comment">
+                                                                       <with-param name="footnote-ids" select="$footnote-ids"/>
+                                                               </apply-templates>
+                                                       </variable>
                                                        <copy>
                                                                <copy-of select="@*"/>
                                                                <copy-of select="$start-node/preceding-sibling::node()"/>
-                                                               <for-each select="$start-tokens[position()!=last()]">
-                                                                       <value-of select="."/>
-                                                                       <if test="position()!=last()">
-                                                                               <value-of select="$start-sigil"/>
-                                                                       </if>
-                                                               </for-each>
-                                                               <element name="{$element-name}" namespace="{$element-namespace}">
-                                                                       <if test="string($role)!=''">
-                                                                               <attribute name="role">
-                                                                                       <value-of select="$role"/>
-                                                                               </attribute>
-                                                                       </if>
-                                                                       <if test="string($class)!=''">
-                                                                               <attribute name="class">
-                                                                                       <value-of select="$class"/>
-                                                                               </attribute>
-                                                                       </if>
-                                                                       <value-of select="$start-tokens[last()]"/>
-                                                                       <copy-of select="$start-node/following-sibling::node()"/>
-                                                               </element>
-                                                               <value-of select="substring-after($end-node, $end-sigil)"/>
-                                                               <copy-of select="$end-node/following-sibling::node()"/>
+                                                               <copy-of select="substring-before($start-node, '⌦')"/>
+                                                               <text>^</text>
+                                                               <copy-of select="exsl:node-set($commented-rest-fragment)/*/node()"/>
                                                        </copy>
-                                               </variable>
-                                               <apply-templates select="exsl:node-set($wrapped)/*" mode="LesML:inline">
-                                                       <with-param name="element-name" select="$element-name"/>
-                                                       <with-param name="element-namespace" select="$element-namespace"/>
-                                                       <with-param name="start-sigil" select="$start-sigil"/>
-                                                       <with-param name="end-sigil" select="$end-sigil"/>
-                                                       <with-param name="role" select="$role"/>
-                                               </apply-templates>
-                                       </when>
-                                       <otherwise>
-                                               <copy>
-                                                       <copy-of select="@*"/>
-                                                       <apply-templates select="node()" mode="LesML:inline">
-                                                               <with-param name="element-name" select="$element-name"/>
-                                                               <with-param name="element-namespace" select="$element-namespace"/>
-                                                               <with-param name="start-sigil" select="$start-sigil"/>
-                                                               <with-param name="end-sigil" select="$end-sigil"/>
-                                                               <with-param name="role" select="$role"/>
-                                                       </apply-templates>
-                                               </copy>
-                                       </otherwise>
-                               </choose>
-                       </when>
-                       <otherwise>
-                               <copy-of select="."/>
-                       </otherwise>
-               </choose>
+                                               </when>
+                                               <otherwise>
+                                                       <copy>
+                                                               <copy-of select="@*"/>
+                                                               <apply-templates select="node()" mode="LesML:comment">
+                                                                       <with-param name="footnote-ids" select="$footnote-ids"/>
+                                                               </apply-templates>
+                                                       </copy>
+                                               </otherwise>
+                                       </choose>
+                               </when>
+                               <when test="self::text()[contains(., '⌧')]">
+                                       <for-each select="LesML:split(., '⌧')">
+                                               <value-of select="."/>
+                                               <if test="position()!=last()">
+                                                       <call-template name="LesML:comment-out"/>
+                                               </if>
+                                       </for-each>
+                               </when>
+                               <otherwise>
+                                       <copy-of select="."/>
+                               </otherwise>
+                       </choose>
+               </variable>
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:attrify">
+                       <with-param name="footnote-ids" select="$footnote-ids"/>
+               </apply-templates>
        </template>
        <template match="*" mode="LesML:partition">
                <param name="start-sigil"/>
@@ -1132,11 +980,20 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                        <value-of select="substring-before($end-node, $end-sigil)"/>
                                </variable>
                                <variable name="preceding" select="exsl:node-set($preceding-fragment)/node()"/>
-                               <variable name="start-node" select="($preceding[self::text() and contains(., $start-sigil)])[last()][not($ncname-keys) or not(following-sibling::* or following-sibling::comment())]"/>
+                               <variable name="start-node" select="($preceding[self::text() and contains(., $start-sigil)])[last()][not($ncname-keys) or not(following-sibling::*[not(self::html:br)] or following-sibling::comment())]"/>
                                <variable name="start-tokens" select="LesML:split($start-node, $start-sigil)"/>
                                <variable name="innards-fragment">
                                        <value-of select="$start-tokens[last()]"/>
-                                       <copy-of select="$start-node/following-sibling::node()"/>
+                                       <for-each select="$start-node/following-sibling::node()">
+                                               <choose>
+                                                       <when test="$ncname-keys and self::html:br">
+                                                               <text>&#xA;</text>
+                                                       </when>
+                                                       <otherwise>
+                                                               <copy-of select="."/>
+                                                       </otherwise>
+                                               </choose>
+                                       </for-each>
                                </variable>
                                <variable name="innards" select="exsl:node-set($innards-fragment)/node()"/>
                                <variable name="separator-node" select="($innards[self::text() and contains(., $separator)])[not($ncname-keys)*(last()-1)+1]"/>
@@ -1278,102 +1135,9 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                        </otherwise>
                </choose>
        </template>
-       <template match="node()" mode="LesML:comment">
-               <param name="footnote-ids" select="/.."/>
-               <variable name="result">
-                       <choose>
-                               <when test="self::*">
-                                       <variable name="start-node" select="text()[contains(., '⌦')][1]"/>
-                                       <variable name="after-start">
-                                               <if test="$start-node">
-                                                       <value-of select="substring-after($start-node, '⌦')"/>
-                                               </if>
-                                       </variable>
-                                       <variable name="has-end-node" select="contains($after-start, '⌫') or $start-node/following-sibling::text()[contains(., '⌫')]"/>
-                                       <choose>
-                                               <when test="$start-node and $has-end-node">
-                                                       <variable name="following">
-                                                               <value-of select="$after-start"/>
-                                                               <copy-of select="$start-node/following-sibling::node()"/>
-                                                       </variable>
-                                                       <variable name="end-node" select="exsl:node-set($following)/text()[contains(., '⌫')][last()]"/>
-                                                       <variable name="comment">
-                                                               <for-each select="$end-node/preceding-sibling::node()">
-                                                                       <value-of select="."/>
-                                                               </for-each>
-                                                               <value-of select="substring-before($end-node, '⌫')"/>
-                                                       </variable>
-                                                       <variable name="rest-fragment">
-                                                               <element name="span" namespace="&xhtml;">
-                                                                       <value-of select="substring-after($end-node, '⌫')"/>
-                                                                       <copy-of select="$end-node/following-sibling::node()"/>
-                                                               </element>
-                                                       </variable>
-                                                       <variable name="commented-rest-fragment">
-                                                               <apply-templates select="exsl:node-set($rest-fragment)/node()" mode="LesML:comment">
-                                                                       <with-param name="footnote-ids" select="$footnote-ids"/>
-                                                               </apply-templates>
-                                                       </variable>
-                                                       <copy>
-                                                               <copy-of select="@*"/>
-                                                               <copy-of select="$start-node/preceding-sibling::node()"/>
-                                                               <copy-of select="substring-before($start-node, '⌦')"/>
-                                                               <call-template name="LesML:comment-out">
-                                                                       <with-param name="source" select="string($comment)"/>
-                                                               </call-template>
-                                                               <copy-of select="exsl:node-set($commented-rest-fragment)/*/node()"/>
-                                                       </copy>
-                                               </when>
-                                               <when test="$start-node">
-                                                       <variable name="rest-fragment">
-                                                               <element name="div" namespace="&xhtml;">
-                                                                       <value-of select="substring-after($after-start, '⌦')"/>
-                                                                       <copy-of select="$start-node/following-sibling::node()"/>
-                                                               </element>
-                                                       </variable>
-                                                       <variable name="commented-rest-fragment">
-                                                               <apply-templates select="exsl:node-set($rest-fragment)/node()" mode="LesML:comment">
-                                                                       <with-param name="footnote-ids" select="$footnote-ids"/>
-                                                               </apply-templates>
-                                                       </variable>
-                                                       <copy>
-                                                               <copy-of select="@*"/>
-                                                               <copy-of select="$start-node/preceding-sibling::node()"/>
-                                                               <copy-of select="substring-before($start-node, '⌦')"/>
-                                                               <text>^</text>
-                                                               <copy-of select="exsl:node-set($commented-rest-fragment)/*/node()"/>
-                                                       </copy>
-                                               </when>
-                                               <otherwise>
-                                                       <copy>
-                                                               <copy-of select="@*"/>
-                                                               <apply-templates select="node()" mode="LesML:comment">
-                                                                       <with-param name="footnote-ids" select="$footnote-ids"/>
-                                                               </apply-templates>
-                                                       </copy>
-                                               </otherwise>
-                                       </choose>
-                               </when>
-                               <when test="self::text()[contains(., '⌧')]">
-                                       <for-each select="LesML:split(., '⌧')">
-                                               <value-of select="."/>
-                                               <if test="position()!=last()">
-                                                       <call-template name="LesML:comment-out"/>
-                                               </if>
-                                       </for-each>
-                               </when>
-                               <otherwise>
-                                       <copy-of select="."/>
-                               </otherwise>
-                       </choose>
-               </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:attrify">
-                       <with-param name="footnote-ids" select="$footnote-ids"/>
-               </apply-templates>
-       </template>
        <template match="node()" mode="LesML:attrify">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <choose>
                                <when test="self::*">
                                        <variable name="partitioned-fragment">
@@ -1429,13 +1193,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                </otherwise>
                        </choose>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:linkify">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:linkify">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:linkify">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <choose>
                                <when test="processing-instruction()[local-name()='LesML-All-Done']">
                                        <copy>
@@ -1504,13 +1268,87 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                </otherwise>
                        </choose>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:strikethrough">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:strikethrough">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
+       <template match="node()" mode="LesML:inline">
+               <param name="element-name"/>
+               <param name="element-namespace" select="'http://www.w3.org/1999/xhtml'"/>
+               <param name="start-sigil"/>
+               <param name="end-sigil"/>
+               <param name="class"/>
+               <param name="role"/>
+               <choose>
+                       <when test="self::*">
+                               <variable name="end-node" select="text()[contains(., $end-sigil)][1]"/>
+                               <variable name="has-start-node" select="$end-node/preceding-sibling::text()[contains(., $start-sigil)] or string-length(substring-after($end-node, $start-sigil))>string-length(substring-after($end-node, $end-sigil))"/>
+                               <choose>
+                                       <when test="$end-node and $has-start-node">
+                                               <variable name="preceding">
+                                                       <copy-of select="$end-node/preceding-sibling::node()"/>
+                                                       <value-of select="substring-before($end-node, $end-sigil)"/>
+                                               </variable>
+                                               <variable name="start-node" select="exsl:node-set($preceding)/text()[contains(., $start-sigil)][last()]"/>
+                                               <variable name="start-tokens" select="LesML:split($start-node, $start-sigil)"/>
+                                               <variable name="wrapped">
+                                                       <copy>
+                                                               <copy-of select="@*"/>
+                                                               <copy-of select="$start-node/preceding-sibling::node()"/>
+                                                               <for-each select="$start-tokens[position()!=last()]">
+                                                                       <value-of select="."/>
+                                                                       <if test="position()!=last()">
+                                                                               <value-of select="$start-sigil"/>
+                                                                       </if>
+                                                               </for-each>
+                                                               <element name="{$element-name}" namespace="{$element-namespace}">
+                                                                       <if test="string($role)!=''">
+                                                                               <attribute name="role">
+                                                                                       <value-of select="$role"/>
+                                                                               </attribute>
+                                                                       </if>
+                                                                       <if test="string($class)!=''">
+                                                                               <attribute name="class">
+                                                                                       <value-of select="$class"/>
+                                                                               </attribute>
+                                                                       </if>
+                                                                       <value-of select="$start-tokens[last()]"/>
+                                                                       <copy-of select="$start-node/following-sibling::node()"/>
+                                                               </element>
+                                                               <value-of select="substring-after($end-node, $end-sigil)"/>
+                                                               <copy-of select="$end-node/following-sibling::node()"/>
+                                                       </copy>
+                                               </variable>
+                                               <apply-templates select="exsl:node-set($wrapped)/*" mode="LesML:inline">
+                                                       <with-param name="element-name" select="$element-name"/>
+                                                       <with-param name="element-namespace" select="$element-namespace"/>
+                                                       <with-param name="start-sigil" select="$start-sigil"/>
+                                                       <with-param name="end-sigil" select="$end-sigil"/>
+                                                       <with-param name="role" select="$role"/>
+                                               </apply-templates>
+                                       </when>
+                                       <otherwise>
+                                               <copy>
+                                                       <copy-of select="@*"/>
+                                                       <apply-templates select="node()" mode="LesML:inline">
+                                                               <with-param name="element-name" select="$element-name"/>
+                                                               <with-param name="element-namespace" select="$element-namespace"/>
+                                                               <with-param name="start-sigil" select="$start-sigil"/>
+                                                               <with-param name="end-sigil" select="$end-sigil"/>
+                                                               <with-param name="role" select="$role"/>
+                                                       </apply-templates>
+                                               </copy>
+                                       </otherwise>
+                               </choose>
+                       </when>
+                       <otherwise>
+                               <copy-of select="."/>
+                       </otherwise>
+               </choose>
+       </template>
        <template match="node()" mode="LesML:strikethrough">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'s'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1518,13 +1356,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="end-sigil" select="'⸡'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:underline">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:underline">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:underline">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'u'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1532,13 +1370,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="end-sigil" select="'⸥'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:noted">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:noted">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:noted">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'small'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1547,13 +1385,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="role" select="'note'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:parenthetical">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:parenthetical">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:parenthetical">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'small'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1561,13 +1399,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="end-sigil" select="'⸩'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:code">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:code">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:code">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'code'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1575,13 +1413,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="end-sigil" select="'´'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:titled">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:titled">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:titled">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'cite'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1589,13 +1427,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="end-sigil" select="'⟫'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:named">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:named">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:named">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'u'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1604,13 +1442,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="class" select="'name'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:offset">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:offset">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:offset">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'i'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1618,13 +1456,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="end-sigil" select="'⟩'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:bolded">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:bolded">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:bolded">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'b'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1632,13 +1470,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="end-sigil" select="'⦄'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:important">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:important">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:important">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'strong'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1646,13 +1484,13 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="end-sigil" select="'☜'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:emphasized">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:emphasized">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:emphasized">
                <param name="footnote-ids" select="/.."/>
-               <variable name="result">
+               <variable name="result-fragment">
                        <apply-templates select="." mode="LesML:inline">
                                <with-param name="element-name" select="'em'"/>
                                <with-param name="element-namespace" select="'&xhtml;'"/>
@@ -1660,87 +1498,294 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <with-param name="end-sigil" select="'⹑'"/>
                        </apply-templates>
                </variable>
-               <apply-templates select="exsl:node-set($result)/node()" mode="LesML:footnoted">
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:footnoted">
                        <with-param name="footnote-ids" select="$footnote-ids"/>
                </apply-templates>
        </template>
        <template match="node()" mode="LesML:footnoted">
                <param name="footnote-ids" select="/.."/>
+               <variable name="result-fragment">
+                       <choose>
+                               <when test="self::*">
+                                       <variable name="start-node" select="text()[contains(., '[^')][1]"/>
+                                       <variable name="after-start" select="substring-after($start-node, '[^')"/>
+                                       <variable name="footnote-id" select="substring-before($after-start, ']')"/>
+                                       <variable name="matched-footnote" select="$footnote-ids[.=$footnote-id]"/>
+                                       <choose>
+                                               <when test="$footnote-id!='' and $matched-footnote">
+                                                       <variable name="rest-fragment">
+                                                               <element name="div" namespace="&xhtml;">
+                                                                       <value-of select="substring-after($after-start, ']')"/>
+                                                                       <copy-of select="$start-node/following-sibling::node()"/>
+                                                               </element>
+                                                       </variable>
+                                                       <variable name="footnoted-rest-fragment">
+                                                               <apply-templates select="exsl:node-set($rest-fragment)/node()" mode="LesML:footnoted">
+                                                                       <with-param name="footnote-ids" select="$footnote-ids"/>
+                                                               </apply-templates>
+                                                       </variable>
+                                                       <copy>
+                                                               <copy-of select="@*"/>
+                                                               <copy-of select="$start-node/preceding-sibling::node()"/>
+                                                               <copy-of select="substring-before($start-node, '[^')"/>
+                                                               <element name="a" namespace="&xhtml;">
+                                                                       <attribute name="id">
+                                                                               <text>LesML.fnref.</text>
+                                                                               <value-of select="generate-id($start-node)"/>
+                                                                       </attribute>
+                                                                       <attribute name="role">
+                                                                               <text>doc-noteref</text>
+                                                                       </attribute>
+                                                                       <attribute name="href">
+                                                                               <text>#</text>
+                                                                               <value-of select="$footnote-id"/>
+                                                                       </attribute>
+                                                                       <attribute name="target">
+                                                                               <text>_self</text>
+                                                                       </attribute>
+                                                               </element>
+                                                               <copy-of select="exsl:node-set($footnoted-rest-fragment)/*/node()"/>
+                                                       </copy>
+                                               </when>
+                                               <when test="$start-node">
+                                                       <variable name="rest-fragment">
+                                                               <element name="div" namespace="&xhtml;">
+                                                                       <value-of select="substring-after($start-node, '[^')"/>
+                                                                       <copy-of select="$start-node/following-sibling::node()"/>
+                                                               </element>
+                                                       </variable>
+                                                       <variable name="footnoted-rest-fragment">
+                                                               <apply-templates select="exsl:node-set($rest-fragment)/node()" mode="LesML:footnoted">
+                                                                       <with-param name="footnote-ids" select="$footnote-ids"/>
+                                                               </apply-templates>
+                                                       </variable>
+                                                       <copy>
+                                                               <copy-of select="@*"/>
+                                                               <copy-of select="$start-node/preceding-sibling::node()"/>
+                                                               <copy-of select="substring-before($start-node, '[^')"/>
+                                                               <text>[^</text>
+                                                               <copy-of select="exsl:node-set($footnoted-rest-fragment)/*/node()"/>
+                                                       </copy>
+                                               </when>
+                                               <otherwise>
+                                                       <copy>
+                                                               <copy-of select="@*"/>
+                                                               <apply-templates select="node()" mode="LesML:footnoted">
+                                                                       <with-param name="footnote-ids" select="$footnote-ids"/>
+                                                               </apply-templates>
+                                                       </copy>
+                                               </otherwise>
+                                       </choose>
+                               </when>
+                               <otherwise>
+                                       <copy-of select="."/>
+                               </otherwise>
+                       </choose>
+               </variable>
+               <apply-templates select="exsl:node-set($result-fragment)/node()" mode="LesML:finish"/>
+       </template>
+       <template match="processing-instruction()[local-name()='LesML-All-Done']" mode="LesML:finish"/>
+       <template match="processing-instruction()[local-name()='LesML-Token-Escape']" mode="LesML:finish">
+               <value-of select="."/>
+       </template>
+       <template match="@*|node()" mode="LesML:finish" priority="-1">
+               <copy>
+                       <apply-templates select="@*|node()" mode="LesML:finish"/>
+               </copy>
+       </template>
+
+<!-->
+❦ Templates in the `LesML:finalize´ and related modes
+
+These templates finalize the resulting tree.
+</!-->
+
+       <template match="node()" mode="LesML:finalize-attributes">
+               <param name="exclude-level" select="false()"/>
+               <variable name="notattr" select="following-sibling::node()[not(self::LesML:attribute)]"/>
+               <variable name="div" select="self::html:div|self::*[&block-types;]/node()[not(self::processing-instruction())][position()=1 and self::html:div]"/>
+               <variable name="para" select="self::html:p|$div/node()[not(self::processing-instruction())][position()=1 and self::html:p]"/>
+               <variable name="emptypara" select="$para[not(@*|node()[not(self::processing-instruction())])]"/>
+               <for-each select="(.|$emptypara/..|exslset:leading(following-sibling::node(), $notattr)[self::LesML:attribute])/@*">
+                       <copy-of select="."/>
+                       <if test="local-name()='lang' and namespace-uri()=''">
+                               <attribute name="xml:lang">
+                                       <value-of select="."/>
+                               </attribute>
+                       </if>
+               </for-each>
+               <if test="not($exclude-level) and &level-pi;!=0">
+                       <attribute name="data-level">
+                               <value-of select="&level-pi;"/>
+                       </attribute>
+               </if>
+       </template>
+       <template match="html:li" mode="LesML:finalize-list">
+               <param name="used-footnotes" select="/.."/>
+               <variable name="current-class" select="string(@class)"/>
+               <variable name="current-level" select="number(&level-pi;)"/>
+               <variable name="wrapper">
+                       <choose>
+                               <when test="contains(concat(' ', @class, ' '), ' ordered ')">
+                                       <text>ol</text>
+                               </when>
+                               <otherwise>
+                                       <text>ul</text>
+                               </otherwise>
+                       </choose>
+               </variable>
+               <variable name="notinlist" select="following-sibling::node()[not(self::html:li and &level-pi;=$current-level and @class=$current-class)][1]"/>
+               <element name="{$wrapper}" namespace="&xhtml;">
+                       <for-each select=".|exslset:leading(following-sibling::node(), $notinlist)">
+                               <copy>
+                                       <apply-templates select="." mode="LesML:finalize-attributes"/>
+                                       <apply-templates select="node()" mode="LesML:finalize">
+                                               <with-param name="used-footnotes" select="$used-footnotes"/>
+                                       </apply-templates>
+                               </copy>
+                       </for-each>
+               </element>
+               <if test="$notinlist/self::html:li">
+                       <apply-templates select="$notinlist" mode="LesML:finalize-list">
+                               <with-param name="used-footnotes" select="$used-footnotes"/>
+                       </apply-templates>
+               </if>
+       </template>
+       <template match="*[processing-instruction()[local-name()='LesML-Footnote']]|html:div/node()[not(self::processing-instruction())][position()=1 and self::html:p and not(@*|node())]|LesML:attribute[preceding-sibling::node()[position()=1 and (self::text() or self::*)]]|processing-instruction()" mode="LesML:finalize" priority="2"/>
+       <template match="html:div[not((node()[not(self::processing-instruction())])/following-sibling::node()[not(self::processing-instruction())])]" mode="LesML:finalize" priority="1">
+               <param name="used-footnotes" select="/.."/>
+               <variable name="context" select="."/>
+               <variable name="result-fragment">
+                       <apply-templates select="node()" mode="LesML:finalize">
+                               <with-param name="used-footnotes" select="$used-footnotes"/>
+                       </apply-templates>
+               </variable>
+               <variable name="result" select="exsl:node-set($result-fragment)/node()"/>
                <choose>
-                       <when test="self::*">
-                               <variable name="start-node" select="text()[contains(., '^')][1]"/>
-                               <variable name="after-start" select="substring-after($start-node, '^')"/>
-                               <variable name="footnote-id" select="substring-before($after-start, '.')"/>
-                               <variable name="matched-footnote" select="$footnote-ids[.=$footnote-id]"/>
-                               <choose>
-                                       <when test="$footnote-id!='' and $matched-footnote">
-                                               <variable name="rest-fragment">
-                                                       <element name="div" namespace="&xhtml;">
-                                                               <value-of select="substring-after($after-start, '.')"/>
-                                                               <copy-of select="$start-node/following-sibling::node()"/>
-                                                       </element>
-                                               </variable>
-                                               <variable name="footnoted-rest-fragment">
-                                                       <apply-templates select="exsl:node-set($rest-fragment)/node()" mode="LesML:footnoted">
-                                                               <with-param name="footnote-ids" select="$footnote-ids"/>
-                                                       </apply-templates>
-                                               </variable>
-                                               <copy>
-                                                       <copy-of select="@*"/>
-                                                       <copy-of select="$start-node/preceding-sibling::node()"/>
-                                                       <copy-of select="substring-before($start-node, '^')"/>
-                                                       <element name="a" namespace="&xhtml;">
-                                                               <attribute name="id">
-                                                                       <text>LesML.fnref.</text>
-                                                                       <value-of select="generate-id($start-node)"/>
-                                                               </attribute>
-                                                               <attribute name="role">
-                                                                       <text>doc-noteref</text>
-                                                               </attribute>
-                                                               <attribute name="href">
-                                                                       <text>#</text>
-                                                                       <value-of select="$footnote-id"/>
-                                                               </attribute>
-                                                               <attribute name="target">
-                                                                       <text>_self</text>
-                                                               </attribute>
-                                                       </element>
-                                                       <copy-of select="exsl:node-set($footnoted-rest-fragment)/*/node()"/>
-                                               </copy>
-                                       </when>
-                                       <when test="$start-node">
-                                               <variable name="rest-fragment">
-                                                       <element name="div" namespace="&xhtml;">
-                                                               <value-of select="substring-after($after-start, '^')"/>
-                                                               <copy-of select="$start-node/following-sibling::node()"/>
-                                                       </element>
-                                               </variable>
-                                               <variable name="footnoted-rest-fragment">
-                                                       <apply-templates select="exsl:node-set($rest-fragment)/node()" mode="LesML:footnoted">
-                                                               <with-param name="footnote-ids" select="$footnote-ids"/>
-                                                       </apply-templates>
-                                               </variable>
-                                               <copy>
-                                                       <copy-of select="@*"/>
-                                                       <copy-of select="$start-node/preceding-sibling::node()"/>
-                                                       <copy-of select="substring-before($start-node, '^')"/>
-                                                       <text>^</text>
-                                                       <copy-of select="exsl:node-set($footnoted-rest-fragment)/*/node()"/>
-                                               </copy>
-                                       </when>
-                                       <otherwise>
-                                               <copy>
-                                                       <copy-of select="@*"/>
-                                                       <apply-templates select="node()" mode="LesML:footnoted">
-                                                               <with-param name="footnote-ids" select="$footnote-ids"/>
-                                                       </apply-templates>
-                                               </copy>
-                                       </otherwise>
-                               </choose>
+                       <when test="not(../&level-pi;) and &level-pi;!=0 or ../&level-pi; and &level-pi;-1!=../&level-pi;">
+                               <copy>
+                                       <apply-templates select="$context" mode="LesML:finalize-attributes"/>
+                                       <copy-of select="$result"/>
+                               </copy>
                        </when>
-                       <otherwise>
-                               <copy-of select="."/>
-                       </otherwise>
+                       <when test="$result">
+                               <for-each select="$result">
+                                       <copy>
+                                               <apply-templates select="$context" mode="LesML:finalize-attributes">
+                                                       <with-param name="exclude-level" select="true()"/>
+                                               </apply-templates>
+                                               <copy-of select="@*|node()"/>
+                                       </copy>
+                               </for-each>
+                       </when>
+                       <when test="* and (preceding-sibling::node()[not(self::processing-instruction())] or not(ancestor::*))">
+                               <for-each select="*">
+                                       <copy>
+                                               <apply-templates select="$context" mode="LesML:finalize-attributes">
+                                                       <with-param name="exclude-level" select="true()"/>
+                                               </apply-templates>
+                                               <copy-of select="@*|node()"/>
+                                       </copy>
+                               </for-each>
+                       </when>
+                       <otherwise/>
                </choose>
        </template>
+       <template match="LesML:attribute|text()[following-sibling::node()[position()=1 and self::LesML:attribute]]" mode="LesML:finalize" priority="1">
+               <element name="span" namespace="&xhtml;">
+                       <apply-templates select="." mode="LesML:finalize-attributes"/>
+                       <if test="self::text()">
+                               <copy/>
+                       </if>
+               </element>
+       </template>
+       <template match="html:blockquote[node()[position()=last() and self::html:footer]]" mode="LesML:finalize">
+               <param name="used-footnotes" select="/.."/>
+               <element name="figure" namespace="&xhtml;">
+                       <copy>
+                               <apply-templates select="." mode="LesML:finalize-attributes"/>
+                               <apply-templates select="node()[position()!=last()]" mode="LesML:finalize">
+                                       <with-param name="used-footnotes" select="$used-footnotes"/>
+                               </apply-templates>
+                       </copy>
+                       <for-each select="node()[last()]">
+                               <element name="figcaption" namespace="&xhtml;">
+                                       <apply-templates select="." mode="LesML:finalize-attributes">
+                                               <with-param name="exclude-level" select="true()"/>
+                                       </apply-templates>
+                                       <apply-templates select="node()" mode="LesML:finalize">
+                                               <with-param name="used-footnotes" select="$used-footnotes"/>
+                                       </apply-templates>
+                               </element>
+                       </for-each>
+               </element>
+       </template>
+       <template match="html:div[(self::*|html:div)[html:h1 or html:h2 or html:h3 or html:h4 or html:h5 or html:h6]]" mode="LesML:finalize">
+               <param name="used-footnotes" select="/.."/>
+               <element name="hgroup" namespace="&xhtml;">
+                       <apply-templates select="." mode="LesML:finalize-attributes"/>
+                       <apply-templates select="node()" mode="LesML:finalize">
+                               <with-param name="used-footnotes" select="$used-footnotes"/>
+                       </apply-templates>
+               </element>
+       </template>
+       <template match="html:li" mode="LesML:finalize">
+               <param name="used-footnotes" select="/.."/>
+               <if test="not(preceding-sibling::node()) or preceding-sibling::node()[position()=1 and not(self::html:li)]">
+                       <apply-templates select="." mode="LesML:finalize-list">
+                               <with-param name="used-footnotes" select="$used-footnotes"/>
+                       </apply-templates>
+               </if>
+       </template>
+       <template match="html:pre" mode="LesML:finalize">
+               <param name="used-footnotes" select="/.."/>
+               <copy>
+                       <apply-templates select="." mode="LesML:finalize-attributes"/>
+                       <choose>
+                               <when test="@class='code'">
+                                       <element name="code" namespace="&xhtml;">
+                                               <apply-templates select="node()" mode="LesML:finalize">
+                                                       <with-param name="used-footnotes" select="$used-footnotes"/>
+                                               </apply-templates>
+                                       </element>
+                               </when>
+                               <otherwise>
+                                       <apply-templates select="node()" mode="LesML:finalize">
+                                               <with-param name="used-footnotes" select="$used-footnotes"/>
+                                       </apply-templates>
+                               </otherwise>
+                       </choose>
+               </copy>
+       </template>
+       <template match="html:a[@role='doc-noteref']" mode="LesML:finalize">
+               <param name="used-footnotes" select="/.."/>
+               <variable name="matching-note" select="$used-footnotes[concat('#', @id)=current()/@href]"/>
+               <copy>
+                       <apply-templates select="." mode="LesML:finalize-attributes"/>
+                       <choose>
+                               <when test="$matching-note">
+                                       <value-of select="$matching-note/@value"/>
+                               </when>
+                               <otherwise>
+                                       <apply-templates select="node()" mode="LesML:finalize">
+                                               <with-param name="used-footnotes" select="$used-footnotes"/>
+                                       </apply-templates>
+                               </otherwise>
+                       </choose>
+               </copy>
+       </template>
+       <template match="text()" mode="LesML:finalize">
+               <call-template name="LesML:unescape">
+                       <with-param name="source" select="string()"/>
+               </call-template>
+       </template>
+       <template match="node()" mode="LesML:finalize" priority="-1">
+               <param name="used-footnotes" select="/.."/>
+               <copy>
+                       <apply-templates select="." mode="LesML:finalize-attributes"/>
+                       <apply-templates select="node()" mode="LesML:finalize">
+                               <with-param name="used-footnotes" select="$used-footnotes"/>
+                       </apply-templates>
+               </copy>
+       </template>
 </transform>
This page took 0.380974 seconds and 4 git commands to generate.