X-Git-Url: https://git.ladys.computer/LesML/blobdiff_plain/e526f59ff5a5d988573ac855138645fe9394c4b7..889242706f6a51e5edcc3d515280200b754c078d:/parser.xslt?ds=sidebyside diff --git a/parser.xslt b/parser.xslt index 89ff594..8772693 100644 --- a/parser.xslt +++ b/parser.xslt @@ -1,16 +1,22 @@ <?xml version="1.0"?> <!-- -SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady> +SPDX-FileCopyrightText: 2024, 2025 Lady <https://www.ladys.computer/about/#lady> SPDX-License-Identifier: MPL-2.0 --> <!-- ⁌ 💄📝 Les·M·L ∷ parser.xslt -© 2024 Lady [@ Lady’s Computer] +© 2024–2025 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/>. --> +<!DOCTYPE transform [ + <!ENTITY section-break "*-.=_~·․‥…⁂⋯─━┄┅┈┉╌╍═╴╶╸╺☙❧ ・*-.=_~"> + <!ENTITY sigiled-text "(string-length($text)=1 or substring($text, 2, 1)=' ')"> + <!ENTITY unsigiled-text "substring($text, 3, string-length($text)-2)"> + <!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" @@ -43,14 +49,32 @@ 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"> + <param name="source"/> + <variable name="broken-fragment"> + <call-template name="LesML:split"> + <with-param name="source" select="$source"/> + <with-param name="separator" select="'
'"/> + </call-template> + </variable> + <variable name="broken" select="exsl:node-set($broken-fragment)/node()"/> + <for-each select="$broken"> + <call-template name="LesML:unescape"> + <with-param name="source" select="string()"/> + </call-template> + <if test="position()!=count($broken)"> + <element name="br" namespace="&xhtml;"/> + </if> + </for-each> + </template> <template name="LesML:unescape"> <param name="source"/> <choose> - <when test="contains($source, '<U+')"> - <variable name="after" select="substring-after($source, '<U+')"/> + <when test="contains($source, '{U+')"> + <variable name="after" select="substring-after($source, '{U+')"/> <choose> - <when test="contains($after, '>')"> - <variable name="inner" select="substring-before($after, '>')"/> + <when test="contains($after, '}')"> + <variable name="inner" select="substring-before($after, '}')"/> <variable name="components"> <call-template name="LesML:split"> <with-param name="source" select="$inner"/> @@ -58,14 +82,14 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one </call-template> </variable> <variable name="component-nodes" select="exsl:node-set($components)/node()"/> + <value-of select="substring-before($source, '{U+')"/> <choose> <when test="$component-nodes[string(.)='' or translate(., '0123456789ABCDEF', '')!='']"> - <value-of select="substring-before($source, '<U+')"/> - <text><U+</text> + <text>{U+</text> <value-of select="$inner"/> - <text>></text> + <text>}</text> <call-template name="LesML:unescape"> - <with-param name="source" select="substring-after($after, '>')"/> + <with-param name="source" select="substring-after($after, '}')"/> </call-template> </when> <otherwise> @@ -75,14 +99,14 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <text>;</text> </for-each> <call-template name="LesML:unescape"> - <with-param name="source" select="substring-after($after, '>')"/> + <with-param name="source" select="substring-after($after, '}')"/> </call-template> </otherwise> </choose> </when> <otherwise> - <value-of select="substring-before($source, '<U+')"/> - <text><U+</text> + <value-of select="substring-before($source, '{U+')"/> + <text>{U+</text> <call-template name="LesML:unescape"> <with-param name="source" select="$after"/> </call-template> @@ -100,9 +124,12 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <when test="starts-with($source, '¶')"> <choose> <when test="contains($source, ' ')"> - <attribute name="id"> - <value-of select="substring-before(substring-after($source, '¶'), ' ')"/> - </attribute> + <variable name="id" select="substring-before(substring-after($source, '¶'), ' ')"/> + <if test="$id!=''"> + <attribute name="id"> + <value-of select="$id"/> + </attribute> + </if> <value-of select="substring-after($source, ' ')"/> </when> <otherwise> @@ -118,287 +145,476 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one </choose> </template> <template name="LesML:parse"> - <param name="source"/> - <variable name="noshebang"> - <text>
</text> + <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($source, '#!')"> - <value-of select="substring-after($source, '
')"/> + <when test="starts-with($shebang, '#!lesml@')"> + <value-of select="substring-after($shebang, '$')"/> </when> <otherwise> - <value-of select="$source"/> + <value-of select="substring-after($shebang, '#!lesml')"/> </otherwise> </choose> </variable> - <variable name="records"> - <call-template name="LesML:split"> - <with-param name="source" select="$noshebang"/> - <with-param name="separator" select="'
%%'"/> - </call-template> + <variable name="params-fragment"> + <choose> + <when test="$shebang!=''"> + <html:dl> + <if test="starts-with($shebang, '#!lesml@') and contains($shebang, '$')"> + <html:div> + <html:dt> + <text> LANG </text> + </html:dt> + <html:dd> + <value-of select="substring-before(substring-after($shebang, '#!lesml@'), '$')"/> + </html:dd> + </html:div> + </if> + <for-each select="exslstr:tokenize($params-string)"> + <choose> + <when test="contains(., '=')"> + <html:div> + <html:dt> + <value-of select="substring-before(., '=')"/> + </html:dt> + <html:dd> + <value-of select="substring-after(., '=')"/> + </html:dd> + </html:div> + </when> + <otherwise> + <html:div> + <html:dt> + <value-of select="."/> + </html:dt> + <html:dd/> + </html:div> + </otherwise> + </choose> + </for-each> + </html:dl> + </when> + <when test="$parent-params"> + <copy-of select="$parent-params"/> + </when> + <otherwise> + <html:dl/> + </otherwise> + </choose> </variable> - <variable name="record-nodes" select="exsl:node-set($records)/*"/> - <html:article> - <if test="count($record-nodes)>1"> - <html:footer class="head"> - <for-each select="$record-nodes[not(position()=last() or normalize-space(.)='')]"> - <variable name="fields" select="exslstr:tokenize(., '
')"/> - <html:dl> - <for-each select="$fields"> - <choose> - <when test="starts-with(., ' ') and $fields[generate-id()=generate-id(current()/preceding-sibling::*[1])]"/> - <otherwise> - <variable name="next" select="following-sibling::*[not(starts-with(., ' '))]"/> - <html:div> - <html:dt> - <value-of select="normalize-space(substring-before(., ':'))"/> - </html:dt> - <html:dd> - <variable name="firstline"> - <choose> - <when test="contains(., ':')"> - <value-of select="normalize-space(substring-after(., ':'))"/> - </when> - <otherwise> - <value-of select="normalize-space(.)"/> - </otherwise> - </choose> - </variable> - <choose> - <when test="substring($firstline, string-length($firstline))='\' and following-sibling::*[position()=1 and starts-with(., ' ')]"> - <value-of select="substring($firstline, 1, string-length($firstline)-1)"/> - </when> - <otherwise> - <value-of select="$firstline"/> - </otherwise> - </choose> - <for-each select="following-sibling::*[starts-with(., ' ') and not(preceding-sibling::*[generate-id()=generate-id($next)])]"> - <variable name="nextline" select="normalize-space(.)"/> - <choose> - <when test="substring($nextline, string-length($nextline))='\' and following-sibling::*[position()=1 and starts-with(., ' ')]"> - <value-of select="substring($nextline, 1, string-length($nextline)-1)"/> - </when> - <otherwise> - <value-of select="$nextline"/> - </otherwise> - </choose> - </for-each> - </html:dd> - </html:div> - </otherwise> - </choose> - </for-each> - </html:dl> - </for-each> - </html:footer> - </if> - <html:div class="body"> - <call-template name="LesML:paragraphize"> - <with-param name="source" select="string($record-nodes[last()])"/> - </call-template> - </html:div> - </html:article> + <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="$noshebang[not($docsep) or following-sibling::*[generate-id()=generate-id($docsep)]]"/> + <if test="starts-with($first-line, '##') and $first-line!='##'"> + <comment> + <value-of select="substring-after($first-line, '##')"/> + </comment> + </if> + <if test="$shebang!='' or $doclines[normalize-space()!='']"> + <variable name="record-separators" select="$doclines[starts-with(., '%%')]"/> + <element name="article" namespace="&xhtml;"> + <for-each select="$params/html:div/html:dt[string()=' LANG ']"> + <attribute name="lang"> + <value-of select="following-sibling::html:dd"/> + </attribute> + <attribute name="xml:lang"> + <value-of select="following-sibling::html:dd"/> + </attribute> + </for-each> + <for-each select="$params/html:div/html:dt[string()='profile']"> + <attribute name="data-lesml-profile"> + <value-of select="following-sibling::html:dd"/> + </attribute> + </for-each> + <if test="$record-separators[preceding-sibling::*[normalize-space()!='']]"> + <element name="footer" namespace="&xhtml;"> + <attribute name="class"> + <text>head</text> + </attribute> + <for-each select="$record-separators"> + <variable name="position" select="position()"/> + <variable name="prev-separator" select="$record-separators[($position)-1]"/> + <variable name="fields" select="$noshebang[following-sibling::*[generate-id()=generate-id(current())] and (not($prev-separator) or preceding-sibling::*[generate-id()=generate-id($prev-separator)])]"/> + <if test="$fields"> + <element name="dl" namespace="&xhtml;"> + <for-each select="$fields"> + <choose> + <when test="starts-with(., ' ') and $fields[generate-id()=generate-id(current()/preceding-sibling::*[1])]"/> + <otherwise> + <variable name="next" select="following-sibling::*[not(starts-with(., ' '))]"/> + <element name="div" namespace="&xhtml;"> + <element name="dt" namespace="&xhtml;"> + <value-of select="normalize-space(substring-before(., ':'))"/> + </element> + <element name="dd" namespace="&xhtml;"> + <variable name="firstline"> + <choose> + <when test="contains(., ':')"> + <value-of select="normalize-space(substring-after(., ':'))"/> + </when> + <otherwise> + <value-of select="normalize-space(.)"/> + </otherwise> + </choose> + </variable> + <choose> + <when test="substring($firstline, string-length($firstline))='\' and following-sibling::*[position()=1 and starts-with(., ' ')]"> + <value-of select="substring($firstline, 1, string-length($firstline)-1)"/> + </when> + <otherwise> + <value-of select="$firstline"/> + </otherwise> + </choose> + <for-each select="following-sibling::*[starts-with(., ' ') and not(preceding-sibling::*[generate-id()=generate-id($next)])]"> + <variable name="nextline" select="normalize-space(.)"/> + <choose> + <when test="substring($nextline, string-length($nextline))='\' and following-sibling::*[position()=1 and starts-with(., ' ')]"> + <value-of select="substring($nextline, 1, string-length($nextline)-1)"/> + </when> + <otherwise> + <value-of select="$nextline"/> + </otherwise> + </choose> + </for-each> + </element> + </element> + </otherwise> + </choose> + </for-each> + </element> + </if> + <if test=".!='%%'"> + <comment> + <value-of select="substring-after(., '%%')"/> + </comment> + </if> + </for-each> + </element> + </if> + <element name="div" namespace="&xhtml;"> + <attribute name="class"> + <text>body</text> + </attribute> + <call-template name="LesML:paragraphize"> + <with-param name="lines" select="$doclines[not($record-separators) or preceding-sibling::*[generate-id()=generate-id($record-separators[last()])]]"/> + </call-template> + </element> + </element> + </if> + <if test="$docsep"> + <call-template name="LesML:parse"> + <with-param name="lines" select="$docsep|$lines[preceding-sibling::*[generate-id()=generate-id($docsep)]]"/> + <with-param name="parent-params" select="$params"/> + </call-template> + </if> </template> <template name="LesML:paragraphize"> - <param name="source"/> - <variable name="paragraphs"> - <call-template name="LesML:split"> - <with-param name="source" select="$source"/> - <with-param name="separator" select="'

'"/> - </call-template> - </variable> + <param name="lines" select="/.."/> + <variable name="last-lines" select="$lines[normalize-space()!='' and normalize-space(following-sibling::*[1])='']|$lines[last()]"/> <variable name="blocked"> - <for-each select="exsl:node-set($paragraphs)/*"> - <variable name="lines"> - <call-template name="LesML:split"> - <with-param name="source" select="string()"/> - </call-template> - </variable> - <variable name="linespans" select="exsl:node-set($lines)/*"/> + <for-each select="$last-lines"> + <variable name="position" select="position()"/> + <variable name="prev-last" select="$last-lines[($position)-1]"/> + <variable name="linespans" select="$lines[following-sibling::*[generate-id()=generate-id(current())] and (not($prev-last) or preceding-sibling::*[generate-id()=generate-id($prev-last)]) and normalize-space()!='']|."/> <variable name="quoted" select="not($linespans[not(starts-with(., ' ') or starts-with(., '	'))])"/> + <variable name="preformatted" select="not($linespans[not(starts-with(normalize-space(), '|'))])"/> <variable name="text"> <for-each select="$linespans"> - <if test="normalize-space()!=''"> - <value-of select="normalize-space()"/> - <if test="following-sibling::*[normalize-space()!='']"> - <text> </text> - </if> + <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>
</text> + </when> + <otherwise> + <text> </text> + </otherwise> + </choose> </if> </for-each> </variable> <if test="string($text)!=''"> <variable name="par"> <choose> - <when test="starts-with($text, '⁌ ')"> - <html:h1> + <when test="$preformatted"> + <element name="pre" namespace="&xhtml;"> <call-template name="LesML:id-and-contents"> - <with-param name="source" select="substring-after($text, '⁌ ')"/> + <with-param name="source" select="$text"/> </call-template> - </html:h1> + </element> </when> - <when test="starts-with($text, '§ ')"> - <html:h2> + <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="substring-after($text, '§ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:h2> + </element> </when> - <when test="starts-with($text, '✠ ')"> - <html:h3> + <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="substring-after($text, '✠ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:h3> + </element> </when> - <when test="starts-with($text, '❦ ')"> - <html:h4> + <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="substring-after($text, '❦ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:h4> + </element> </when> - <when test="starts-with($text, '• ')"> - <html:li class="unordered" data-level="1"> - <html:p> + <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="substring-after($text, '• ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:li> + </element> + </element> </when> - <when test="starts-with($text, '🔢 ')"> - <html:li class="ordered" data-level="1"> - <html:p> + <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="substring-after($text, '🔢 ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:li> + </element> + </element> </when> - <when test="starts-with($text, '◦ ')"> - <html:li class="unordered" data-level="2"> - <html:p> + <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="substring-after($text, '◦ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:li> + </element> + </element> </when> - <when test="starts-with($text, '🔠 ')"> - <html:li class="ordered" data-level="2"> - <html:p> + <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="substring-after($text, '🔠 ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:li> + </element> + </element> </when> - <when test="starts-with($text, '‣ ')"> - <html:li class="unordered" data-level="3"> - <html:p> + <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="substring-after($text, '‣ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:li> + </element> + </element> </when> - <when test="starts-with($text, '🔡 ')"> - <html:li class="ordered" data-level="3"> - <html:p> + <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="substring-after($text, '🔡 ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:li> + </element> + </element> </when> - <when test="starts-with($text, '⁃ ')"> - <html:li class="unordered" data-level="4"> - <html:p> + <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="substring-after($text, '⁃ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:li> + </element> + </element> </when> - <when test="starts-with($text, '🔣 ')"> - <html:li class="ordered" data-level="4"> - <html:p> + <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="substring-after($text, '🔣 ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:li> + </element> + </element> </when> - <when test="starts-with($text, '🛈 ')"> - <html:div role="note" class="info"> - <html:p> + <when test="starts-with($text, '🛈') and &sigiled-text;"> + <element name="div" namespace="&xhtml;"> + <attribute name="role"> + <text>note</text> + </attribute> + <attribute name="class"> + <text>info</text> + </attribute> + <element name="p" namespace="&xhtml;"> <call-template name="LesML:id-and-contents"> - <with-param name="source" select="substring-after($text, '🛈 ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:div> + </element> + </element> </when> - <when test="starts-with($text, '⯑ ')"> - <html:div role="note" class="query"> - <html:p> + <when test="starts-with($text, '⯑') and &sigiled-text;"> + <element name="div" 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="substring-after($text, '⯑ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:div> + </element> + </element> </when> - <when test="starts-with($text, '⚠︎ ')"> - <html:div role="note" class="warn"> - <html:p> + <when test="starts-with($text, '⚠︎') and &sigiled-text;"> + <element name="div" namespace="&xhtml;"> + <attribute name="role"> + <text>note</text> + </attribute> + <attribute name="class"> + <text>warn</text> + </attribute> + <element name="p" namespace="&xhtml;"> <call-template name="LesML:id-and-contents"> - <with-param name="source" select="substring-after($text, '⚠︎ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:div> + </element> + </element> </when> - <when test="starts-with($text, '※ ')"> - <html:div role="note" class="note"> - <html:p> + <when test="starts-with($text, '※') and &sigiled-text;"> + <element name="div" 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="substring-after($text, '※ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:div> + </element> + </element> </when> - <when test="starts-with($text, '☡ ')"> - <html:div role="note" class="caution"> - <html:p> + <when test="starts-with($text, '☡') and &sigiled-text;"> + <element name="div" 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="substring-after($text, '☡ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:div> + </element> + </element> </when> - <when test="starts-with($text, '⋯ ')"> - <html:div class="continuation"> - <html:p> + <when test="starts-with($text, '⋯') and &sigiled-text;"> + <element name="div" namespace="&xhtml;"> + <attribute name="class"> + <text>continuation</text> + </attribute> + <element name="p" namespace="&xhtml;"> <call-template name="LesML:id-and-contents"> - <with-param name="source" select="substring-after($text, '⋯ ')"/> + <with-param name="source" select="&unsigiled-text;"/> </call-template> - </html:p> - </html:div> + </element> + </element> + </when> + <when test="starts-with($text, '#') and &sigiled-text;"> + <comment> + <value-of select="&unsigiled-text;"/> + </comment> </when> <otherwise> - <html:p> + <element name="p" namespace="&xhtml;"> <call-template name="LesML:id-and-contents"> <with-param name="source" select="$text"/> </call-template> - </html:p> + </element> </otherwise> </choose> </variable> <choose> - <when test="translate(string($text), '#*-=_~⁂─━┄┅┈┉╌╍═╴╶╸╺☙❧ ', '')=''"> - <html:hr/> + <when test="translate(string($text), '§ion-break; ', '')=''"> + <element name="hr" namespace="&xhtml;"/> </when> <when test="$quoted"> - <html:blockquote> + <element name="blockquote" namespace="&xhtml;"> <copy-of select="$par"/> - </html:blockquote> + </element> </when> <otherwise> <copy-of select="$par"/> @@ -413,23 +629,17 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <apply-templates select="exsl:node-set($inlined)/node()" mode="LesML:finalize-tree"/> </template> <template match="html:script[@type='text/lesml']"> - <variable name="source"> - <for-each select=".//text()"> - <value-of select="."/> - </for-each> + <variable name="lines-fragment"> + <call-template name="LesML:split"> + <with-param name="source"> + <for-each select=".//text()"> + <value-of select="."/> + </for-each> + </with-param> + </call-template> </variable> <call-template name="LesML:parse"> - <with-param name="source" select="string($source)"/> - </call-template> - </template> - <template match="@*|node()" mode="LesML:finalize-tree" priority="-1"> - <copy> - <apply-templates select="@*|node()" mode="LesML:finalize-tree"/> - </copy> - </template> - <template match="text()" mode="LesML:finalize-tree"> - <call-template name="LesML:unescape"> - <with-param name="source" select="string(.)"/> + <with-param name="lines" select="exsl:node-set($lines-fragment)/*"/> </call-template> </template> <template match="html:blockquote" mode="LesML:finalize-tree"> @@ -450,18 +660,18 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <value-of select="substring-after($laststarttext, '— ')"/> <copy-of select="$laststarttext/following-sibling::node()"/> </variable> - <html:figure> + <element name="figure" namespace="&xhtml;"> <copy> <apply-templates select="@*|$content-nodes[position()!=last()]" mode="LesML:finalize-tree"/> </copy> - <html:figcaption> + <element name="figcaption" namespace="&xhtml;"> <for-each select="$content-nodes[last()]"> <copy> <apply-templates select="@*|exsl:node-set($caption)/node()" mode="LesML:finalize-tree"/> </copy> </for-each> - </html:figcaption> - </html:figure> + </element> + </element> </when> <otherwise> <copy> @@ -502,7 +712,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one </choose> </variable> <variable name="notinlist" select="following-sibling::node()[not(self::html:div and @class='continuation' or self::html:li and (@data-level>$current-level or @data-level=$current-level and @class=$current-class))][1]"/> - <element name="html:{$wrapper}" namespace="http://www.w3.org/1999/xhtml"> + <element name="{$wrapper}" namespace="&xhtml;"> <for-each select=".|following-sibling::html:li[@data-level=$current-level and (not($notinlist) or following-sibling::node()[generate-id()=generate-id($notinlist)])]"> <variable name="notcontinuation" select="following-sibling::node()[not(self::html:div and @class='continuation')][1]"/> <copy> @@ -524,6 +734,19 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one </apply-templates> </if> </template> + <template match="processing-instruction()[local-name()='LesML-Link-Escape']" mode="LesML:finalize-tree"> + <text>🔗</text> + </template> + <template match="text()" mode="LesML:finalize-tree"> + <call-template name="LesML:break-and-unescape"> + <with-param name="source" select="string(.)"/> + </call-template> + </template> + <template match="@*|node()" mode="LesML:finalize-tree" priority="-1"> + <copy> + <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'"/> @@ -533,88 +756,85 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <param name="langtag-supported" select="false()"/> <choose> <when test="self::*"> - <copy> - <copy-of select="@*"/> - <variable name="start-node" select="text()[contains(., $start-sigil)][1]"/> - <choose> - <when test="$start-node"> - <variable name="remaining"> - <value-of select="substring-after($start-node, $start-sigil)"/> - <copy-of select="$start-node/following-sibling::node()"/> - </variable> - <variable name="end-node" select="exsl:node-set($remaining)/node()[self::text() and contains(., $end-sigil)][1]"/> - <choose> - <when test="$end-node"> - <variable name="restoftext" select="substring-after($end-node, $end-sigil)"/> - <variable name="maybe-langtag"> - <if test="$langtag-supported and starts-with($restoftext, '@') and contains($restoftext, '$')"> - <value-of select="substring-before(substring-after($restoftext, '@'), '$')"/> - </if> - </variable> - <variable name="langtag"> - <if test="translate($maybe-langtag, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-', '')=''"> - <value-of select="$maybe-langtag"/> - </if> - </variable> - <variable name="rest"> - <html:div> - <choose> - <when test="string($langtag)!=''"> - <value-of select="substring-after($restoftext, '$')"/> - </when> - <otherwise> - <value-of select="$restoftext"/> - </otherwise> - </choose> - <copy-of select="$end-node/following-sibling::node()"/> - </html:div> - </variable> - <variable name="processed-rest"> - <apply-templates select="exsl:node-set($rest)/*" 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"/> - <with-param name="langtag-supported" select="$langtag-supported"/> - </apply-templates> - </variable> - <copy-of select="$start-node/preceding-sibling::node()"/> - <value-of select="substring-before($start-node, $start-sigil)"/> - <element name="{$element-name}" namespace="{$element-namespace}"> - <if test="string($role)!=''"> - <attribute name="role"> - <value-of select="$role"/> - </attribute> - </if> - <if test="string($langtag)!=''"> - <if test="$element-namespace='http://www.w3.org/1999/xhtml'"> - <attribute name="lang"> - <value-of select="$langtag"/> - </attribute> - </if> - <attribute name="xml:lang"> + <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="restoftext" select="substring-after($end-node, $end-sigil)"/> + <variable name="maybe-langtag"> + <if test="$langtag-supported and starts-with($restoftext, '@') and contains($restoftext, '$')"> + <value-of select="substring-before(substring-after($restoftext, '@'), '$')"/> + </if> + </variable> + <variable name="langtag"> + <if test="translate($maybe-langtag, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-', '')=''"> + <value-of select="$maybe-langtag"/> + </if> + </variable> + <variable name="start-tokens-fragment"> + <call-template name="LesML:split"> + <with-param name="source" select="string($start-node)"/> + <with-param name="separator" select="$start-sigil"/> + </call-template> + </variable> + <variable name="start-tokens" select="exsl:node-set($start-tokens-fragment)/*"/> + <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($langtag)!=''"> + <if test="$element-namespace='http://www.w3.org/1999/xhtml'"> + <attribute name="lang"> <value-of select="$langtag"/> </attribute> </if> - <copy-of select="$end-node/preceding-sibling::node()"/> - <value-of select="substring-before($end-node, $end-sigil)"/> - </element> - <copy-of select="exsl:node-set($processed-rest)/*/node()"/> - </when> - <otherwise> - <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"/> - <with-param name="langtag-supported" select="$langtag-supported"/> - </apply-templates> - </otherwise> - </choose> - </when> - <otherwise> + <attribute name="xml:lang"> + <value-of select="$langtag"/> + </attribute> + </if> + <value-of select="$start-tokens[last()]"/> + <copy-of select="$start-node/following-sibling::node()"/> + </element> + <choose> + <when test="string($langtag)!=''"> + <value-of select="substring-after($restoftext, '$')"/> + </when> + <otherwise> + <value-of select="$restoftext"/> + </otherwise> + </choose> + <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"/> + <with-param name="langtag-supported" select="$langtag-supported"/> + </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"/> @@ -623,9 +843,9 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <with-param name="role" select="$role"/> <with-param name="langtag-supported" select="$langtag-supported"/> </apply-templates> - </otherwise> - </choose> - </copy> + </copy> + </otherwise> + </choose> </when> <otherwise> <copy-of select="."/> @@ -636,79 +856,108 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <variable name="result"> <choose> <when test="self::*"> - <copy> - <copy-of select="@*"/> - <variable name="start-node" select="text()[contains(., '{🔗')][1]"/> - <choose> - <when test="$start-node"> - <variable name="remaining"> - <value-of select="substring-after($start-node, '{🔗')"/> - <copy-of select="$start-node/following-sibling::node()"/> - </variable> - <variable name="end-node" select="exsl:node-set($remaining)/node()[self::text() and contains(., '>}') and not(preceding-sibling::*)][1]"/> - <variable name="hyperlink"> - <for-each select="$end-node/preceding-sibling::node()"> - <value-of select="."/> - </for-each> - <value-of select="substring-before($end-node, '>}')"/> - </variable> - <choose> - <when test="contains($hyperlink, '<')"> - <variable name="ltcomponents"> - <call-template name="LesML:split"> - <with-param name="source" select="$hyperlink"/> - <with-param name="separator" select="'<'"/> - </call-template> - </variable> - <variable name="ltcomponent-nodes" select="exsl:node-set($ltcomponents)/*"/> - <variable name="rest"> - <html:div> - <value-of select="substring-after($end-node, '>}')"/> - <copy-of select="$end-node/following-sibling::node()"/> - </html:div> - </variable> - <variable name="processed-rest"> - <apply-templates select="exsl:node-set($rest)/*" mode="LesML:linkify"/> - </variable> - <copy-of select="$start-node/preceding-sibling::node()"/> - <value-of select="substring-before($start-node, '{🔗')"/> - <html:a href="{$ltcomponent-nodes[last()]}"> - <choose> - <when test="count($ltcomponent-nodes)>2 or normalize-space($ltcomponent-nodes[1])!=''"> - <value-of select="$ltcomponent-nodes[1]"/> - <for-each select="$ltcomponent-nodes[position()>1 and position()!=last()]"> - <text><</text> - <value-of select="."/> - </for-each> - </when> - <otherwise> - <value-of select="$ltcomponent-nodes[last()]"/> - </otherwise> - </choose> - </html:a> - <copy-of select="exsl:node-set($processed-rest)/*/node()"/> - </when> - <otherwise> - <variable name="rest"> - <html:div> - <copy-of select="$remaining"/> - </html:div> - </variable> - <variable name="processed-rest"> - <apply-templates select="exsl:node-set($rest)/*" mode="LesML:linkify"/> - </variable> - <copy-of select="$start-node/preceding-sibling::node()"/> - <value-of select="substring-before($start-node, '{🔗')"/> - <text>{🔗</text> - <copy-of select="exsl:node-set($processed-rest)/*/node()"/> - </otherwise> - </choose> - </when> - <otherwise> + <variable name="end-node" select="text()[contains(., '>}')][1]"/> + <variable name="has-start-node" select="$end-node/preceding-sibling::text()[contains(., '{🔗') and not(following-sibling::*)] or string-length(substring-after($end-node, '{🔗'))>string-length(substring-after($end-node, '>}'))"/> + <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, '>}')"/> + </variable> + <variable name="start-node" select="exsl:node-set($preceding)/text()[contains(., '{🔗') and not(following-sibling::*)][last()]"/> + <variable name="start-tokens-fragment"> + <call-template name="LesML:split"> + <with-param name="source" select="string($start-node)"/> + <with-param name="separator" select="'{🔗'"/> + </call-template> + </variable> + <variable name="start-tokens" select="exsl:node-set($start-tokens-fragment)/*"/> + <variable name="hyperlink"> + <value-of select="$start-tokens[last()]"/> + <for-each select="$start-node/following-sibling::node()"> + <choose> + <when test="self::text()"> + <value-of select="."/> + </when> + <when test="self::processing-instruction()[local-name()='LesML-Link-Escape']"> + <text>🔗</text> + </when> + </choose> + </for-each> + </variable> + <choose> + <when test="contains($hyperlink, '<')"> + <variable name="ltcomponents-fragment"> + <call-template name="LesML:split"> + <with-param name="source" select="$hyperlink"/> + <with-param name="separator" select="'<'"/> + </call-template> + </variable> + <variable name="ltcomponents" select="exsl:node-set($ltcomponents-fragment)/*"/> + <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()"> + <text>{🔗</text> + </if> + </for-each> + <element name="a" namespace="&xhtml;"> + <attribute name="href"> + <value-of select="$ltcomponents[last()]"/> + </attribute> + <choose> + <when test="count($ltcomponents)>2 or normalize-space($ltcomponents[1])!=''"> + <for-each select="$ltcomponents[position()!=last()]"> + <value-of select="."/> + <if test="position()!=last()"> + <text><</text> + </if> + </for-each> + </when> + <otherwise> + <value-of select="$ltcomponents[last()]"/> + </otherwise> + </choose> + </element> + <value-of select="substring-after($end-node, '>}')"/> + <copy-of select="$end-node/following-sibling::node()"/> + </copy> + </variable> + <apply-templates select="exsl:node-set($wrapped)/*" mode="LesML:linkify"/> + </when> + <otherwise> + <variable name="escaped"> + <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()"> + <text>{🔗</text> + </if> + </for-each> + <text>{</text> + <processing-instruction name="LesML-Link-Escape"/> + <copy-of select="$hyperlink"/> + <text>>}</text> + <value-of select="substring-after($end-node, '>}')"/> + <copy-of select="$end-node/following-sibling::node()"/> + </copy> + </variable> + <apply-templates select="exsl:node-set($escaped)/*" mode="LesML:linkify"/> + </otherwise> + </choose> + </when> + <otherwise> + <copy> + <copy-of select="@*"/> <apply-templates select="node()" mode="LesML:linkify"/> - </otherwise> - </choose> - </copy> + </copy> + </otherwise> + </choose> </when> <otherwise> <copy-of select="."/> @@ -720,7 +969,8 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <template match="node()" mode="LesML:strikethrough"> <variable name="result"> <apply-templates select="." mode="LesML:inline"> - <with-param name="element-name" select="'html:s'"/> + <with-param name="element-name" select="'s'"/> + <with-param name="element-namespace" select="'&xhtml;'"/> <with-param name="start-sigil" select="'⸠'"/> <with-param name="end-sigil" select="'⸡'"/> </apply-templates> @@ -730,7 +980,8 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <template match="node()" mode="LesML:underline"> <variable name="result"> <apply-templates select="." mode="LesML:inline"> - <with-param name="element-name" select="'html:u'"/> + <with-param name="element-name" select="'u'"/> + <with-param name="element-namespace" select="'&xhtml;'"/> <with-param name="start-sigil" select="'⸤'"/> <with-param name="end-sigil" select="'⸥'"/> </apply-templates> @@ -740,7 +991,8 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <template match="node()" mode="LesML:noted"> <variable name="result"> <apply-templates select="." mode="LesML:inline"> - <with-param name="element-name" select="'html:small'"/> + <with-param name="element-name" select="'small'"/> + <with-param name="element-namespace" select="'&xhtml;'"/> <with-param name="start-sigil" select="'⟦'"/> <with-param name="end-sigil" select="'⟧'"/> <with-param name="role" select="'note'"/> @@ -751,29 +1003,21 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <template match="node()" mode="LesML:parenthetical"> <variable name="result"> <apply-templates select="." mode="LesML:inline"> - <with-param name="element-name" select="'html:small'"/> + <with-param name="element-name" select="'small'"/> + <with-param name="element-namespace" select="'&xhtml;'"/> <with-param name="start-sigil" select="'⸨'"/> <with-param name="end-sigil" select="'⸩'"/> </apply-templates> </variable> - <apply-templates select="exsl:node-set($result)/node()" mode="LesML:important"/> - </template> - <template match="node()" mode="LesML:important"> - <variable name="result"> - <apply-templates select="." mode="LesML:inline"> - <with-param name="element-name" select="'html:strong'"/> - <with-param name="start-sigil" select="'☞'"/> - <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)/node()" mode="LesML:code"/> </template> - <template match="node()" mode="LesML:emphasized"> + <template match="node()" mode="LesML:code"> <variable name="result"> <apply-templates select="." mode="LesML:inline"> - <with-param name="element-name" select="'html:em'"/> - <with-param name="start-sigil" select="'⹐'"/> - <with-param name="end-sigil" select="'⹑'"/> + <with-param name="element-name" select="'code'"/> + <with-param name="element-namespace" select="'&xhtml;'"/> + <with-param name="start-sigil" select="'`'"/> + <with-param name="end-sigil" select="'´'"/> </apply-templates> </variable> <apply-templates select="exsl:node-set($result)/node()" mode="LesML:titled"/> @@ -781,7 +1025,8 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <template match="node()" mode="LesML:titled"> <variable name="result"> <apply-templates select="." mode="LesML:inline"> - <with-param name="element-name" select="'html:cite'"/> + <with-param name="element-name" select="'cite'"/> + <with-param name="element-namespace" select="'&xhtml;'"/> <with-param name="start-sigil" select="'⟪'"/> <with-param name="end-sigil" select="'⟫'"/> </apply-templates> @@ -791,7 +1036,8 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <template match="node()" mode="LesML:offset"> <variable name="result"> <apply-templates select="." mode="LesML:inline"> - <with-param name="element-name" select="'html:i'"/> + <with-param name="element-name" select="'i'"/> + <with-param name="element-namespace" select="'&xhtml;'"/> <with-param name="start-sigil" select="'⟨'"/> <with-param name="end-sigil" select="'⟩'"/> <with-param name="langtag-supported" select="true()"/> @@ -802,18 +1048,31 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one <template match="node()" mode="LesML:bolded"> <variable name="result"> <apply-templates select="." mode="LesML:inline"> - <with-param name="element-name" select="'html:b'"/> + <with-param name="element-name" select="'b'"/> + <with-param name="element-namespace" select="'&xhtml;'"/> <with-param name="start-sigil" select="'⦃'"/> <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)/node()" mode="LesML:important"/> </template> - <template match="node()" mode="LesML:code"> + <template match="node()" mode="LesML:important"> + <variable name="result"> + <apply-templates select="." mode="LesML:inline"> + <with-param name="element-name" select="'strong'"/> + <with-param name="element-namespace" select="'&xhtml;'"/> + <with-param name="start-sigil" select="'☞'"/> + <with-param name="end-sigil" select="'☜'"/> + </apply-templates> + </variable> + <apply-templates select="exsl:node-set($result)/node()" mode="LesML:emphasized"/> + </template> + <template match="node()" mode="LesML:emphasized"> <apply-templates select="." mode="LesML:inline"> - <with-param name="element-name" select="'html:code'"/> - <with-param name="start-sigil" select="'`'"/> - <with-param name="end-sigil" select="'´'"/> + <with-param name="element-name" select="'em'"/> + <with-param name="element-namespace" select="'&xhtml;'"/> + <with-param name="start-sigil" select="'⹐'"/> + <with-param name="end-sigil" select="'⹑'"/> </apply-templates> </template> </transform>