3 SPDX-FileCopyrightText: 2024, 2025 Lady <https://www.ladys.computer/about/#lady>
4 SPDX-License-Identifier: MPL-2.0
7 ⁌ 💄📝 Les·M·L ∷ parser.xslt
9 © 2024–2025 Lady [@ Ladys Computer]
11 This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
12 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/>.
15 <!ENTITY LesML "urn:fdc:ladys.computer:20240512:LesML">
16 <!ENTITY section-break "*-.=_~·․‥…⁂⋯─━┄┅┈┉╌╍═╴╶╸╺☙❧ ・*-.=_~">
17 <!ENTITY sigiled-text "(string-length($text)=1 or substring($text, 2, 1)=' ' or substring($text, 2, 1)='¶')">
18 <!ENTITY unsigiled-text "concat(translate(substring($text, 2, 1), ' ', ''), substring($text, 3, string-length($text)-2))">
19 <!ENTITY xhtml "http://www.w3.org/1999/xhtml">
22 xmlns="http://www.w3.org/1999/XSL/Transform"
23 xmlns:LesML="urn:fdc:ladys.computer:20240512:LesML"
24 xmlns:exsl="http://exslt.org/common"
25 xmlns:exsldyn="http://exslt.org/dynamic"
26 xmlns:exslset="http://exslt.org/sets"
27 xmlns:exslstr="http://exslt.org/strings"
28 xmlns:html="http://www.w3.org/1999/xhtml"
29 xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
30 exclude-result-prefixes="LesML"
31 extension-element-prefixes="exsl exsldyn exslset exslstr"
34 <书社:id>urn:fdc:ladys.computer:20240512:LesML:parser.xslt</书社:id>
35 <template name="LesML:split">
36 <param name="source"/>
37 <param name="separator" select="'
'"/>
39 <when test="contains($source, $separator)">
41 <value-of select="substring-before($source, $separator)"/>
43 <call-template name="LesML:split">
44 <with-param name="source" select="substring-after($source, $separator)"/>
45 <with-param name="separator" select="$separator"/>
50 <value-of select="$source"/>
55 <template name="LesML:break-and-unescape">
56 <param name="source"/>
57 <variable name="broken-fragment">
58 <call-template name="LesML:split">
59 <with-param name="source" select="$source"/>
60 <with-param name="separator" select="'
'"/>
63 <variable name="broken" select="exsl:node-set($broken-fragment)/node()"/>
64 <for-each select="$broken">
65 <call-template name="LesML:unescape">
66 <with-param name="source" select="string()"/>
68 <if test="position()!=count($broken)">
69 <element name="br" namespace="&xhtml;"/>
73 <template name="LesML:unescape">
74 <param name="source"/>
76 <when test="contains($source, '{U+')">
77 <variable name="after" select="substring-after($source, '{U+')"/>
79 <when test="contains($after, '}')">
80 <variable name="inner" select="substring-before($after, '}')"/>
81 <variable name="components">
82 <call-template name="LesML:split">
83 <with-param name="source" select="$inner"/>
84 <with-param name="separator" select="'.'"/>
87 <variable name="component-nodes" select="exsl:node-set($components)/node()"/>
88 <value-of select="substring-before($source, '{U+')"/>
90 <when test="$component-nodes[string(.)='' or translate(., '0123456789ABCDEF', '')!='']">
92 <value-of select="$inner"/>
94 <call-template name="LesML:unescape">
95 <with-param name="source" select="substring-after($after, '}')"/>
99 <for-each select="$component-nodes">
100 <text disable-output-escaping="yes">&#x</text>
101 <value-of select="."/>
104 <call-template name="LesML:unescape">
105 <with-param name="source" select="substring-after($after, '}')"/>
111 <value-of select="substring-before($source, '{U+')"/>
113 <call-template name="LesML:unescape">
114 <with-param name="source" select="$after"/>
120 <value-of select="$source"/>
124 <template name="LesML:comment-out">
125 <param name="source"/>
126 <variable name="comment-split-fragment">
127 <call-template name="LesML:split">
128 <with-param name="source" select="$source"/>
129 <with-param name="separator" select="'--'"/>
133 <for-each select="exsl:node-set($comment-split-fragment)/*">
134 <if test="string()='' or starts-with(., '‐')">
135 <text>͏</text>
137 <value-of select="."/>
138 <if test="substring(., string-length(.), 1)='‐'">
139 <text>͏</text>
142 <when test="position()!=last()">
143 <text>-͏-</text>
149 <template name="LesML:id-and-contents">
150 <param name="source"/>
151 <variable name="id-and-lang">
152 <if test="starts-with($source, '¶')">
154 <when test="contains($source, ' ')">
155 <value-of select="substring-before(substring-after($source, '¶'), ' ')"/>
158 <value-of select="substring-after($source, '¶')"/>
163 <variable name="restoftext">
165 <when test="starts-with($source, '¶') and contains($source, ' ')">
166 <value-of select="substring-after($source, ' ')"/>
168 <when test="starts-with($source, '¶')"/>
170 <value-of select="$source"/>
174 <variable name="maybe-langtag">
175 <if test="substring($id-and-lang, string-length($id-and-lang), 1)='$' and contains($id-and-lang, '@')">
176 <variable name="split-tag-fragment">
177 <call-template name="LesML:split">
178 <with-param name="source" select="substring($id-and-lang, 2, string-length($id-and-lang)-2)"/>
179 <with-param name="separator" select="'@'"/>
182 <value-of select="exsl:node-set($split-tag-fragment)/*[last()]"/>
185 <variable name="langtag">
186 <if test="translate($maybe-langtag, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-', '')=''">
187 <value-of select="$maybe-langtag"/>
192 <when test="string($langtag)!=''">
193 <value-of select="substring($id-and-lang, 1, string-length($id-and-lang)-(string-length($langtag)+2))"/>
196 <value-of select="$id-and-lang"/>
200 <if test="string($id)!=''">
201 <attribute name="id">
202 <value-of select="$id"/>
205 <if test="string($langtag)!=''">
206 <attribute name="lang">
207 <value-of select="$langtag"/>
209 <attribute name="xml:lang">
210 <value-of select="$langtag"/>
213 <value-of select="$restoftext"/>
215 <template name="LesML:parse">
216 <param name="lines" select="/.."/>
217 <param name="parent-params" select="/.."/>
218 <variable name="first-line" select="$lines[1]"/>
219 <variable name="shebang">
220 <if test="starts-with($first-line, '#!lesml')">
221 <value-of select="$first-line"/>
224 <variable name="params-string">
226 <when test="starts-with($shebang, '#!lesml@')">
227 <value-of select="substring-after($shebang, '$')"/>
230 <value-of select="substring-after($shebang, '#!lesml')"/>
234 <variable name="params-fragment">
236 <when test="$shebang!=''">
238 <if test="starts-with($shebang, '#!lesml@') and contains($shebang, '$')">
244 <value-of select="substring-before(substring-after($shebang, '#!lesml@'), '$')"/>
248 <for-each select="exslstr:tokenize($params-string)">
250 <when test="contains(., '=')">
253 <value-of select="substring-before(., '=')"/>
256 <value-of select="substring-after(., '=')"/>
263 <value-of select="."/>
272 <when test="$parent-params">
273 <copy-of select="$parent-params"/>
280 <variable name="params" select="exsl:node-set($params-fragment)/*"/>
281 <variable name="noshebang" select="$lines[position()>1 or not(starts-with(., '#!lesml') or starts-with(., '##'))]"/>
282 <variable name="docsep" select="$noshebang[starts-with(., '#!lesml') or starts-with(., '##')][1]"/>
283 <variable name="doclines" select="exslset:leading($noshebang, $docsep)"/>
284 <if test="starts-with($first-line, '##') and $first-line!='##'">
285 <call-template name="LesML:comment-out">
286 <with-param name="source" select="substring-after($first-line, '##')"/>
289 <if test="$doclines[normalize-space()!='']">
290 <variable name="record-separators" select="$doclines[starts-with(., '%%')]"/>
291 <element name="article" namespace="&xhtml;">
292 <for-each select="$params/html:div/html:dt[string()=' LANG ']">
293 <attribute name="lang">
294 <value-of select="following-sibling::html:dd"/>
296 <attribute name="xml:lang">
297 <value-of select="following-sibling::html:dd"/>
300 <for-each select="$params/html:div/html:dt[string()='profile']">
301 <attribute name="data-lesml-profile">
302 <value-of select="following-sibling::html:dd"/>
305 <if test="$record-separators[preceding-sibling::*[normalize-space()!='']]">
306 <element name="footer" namespace="&xhtml;">
307 <attribute name="class">
310 <for-each select="$record-separators">
311 <variable name="position" select="position()"/>
312 <variable name="prev-separator" select="$record-separators[($position)-1]"/>
313 <variable name="fields" select="exslset:leading(exslset:trailing($doclines, $prev-separator), .)"/>
315 <element name="dl" namespace="&xhtml;">
316 <for-each select="$fields">
318 <when test="starts-with(., ' ') and exslset:leading($fields, .)"/>
320 <variable name="next" select="exslset:intersection(following-sibling::*[not(starts-with(., ' '))][1], $fields)"/>
321 <element name="div" namespace="&xhtml;">
322 <element name="dt" namespace="&xhtml;">
323 <value-of select="normalize-space(substring-before(., ':'))"/>
325 <element name="dd" namespace="&xhtml;">
326 <variable name="firstline">
328 <when test="contains(., ':')">
329 <value-of select="normalize-space(substring-after(., ':'))"/>
332 <value-of select="normalize-space(.)"/>
337 <when test="substring($firstline, string-length($firstline))='\' and following-sibling::*[position()=1 and starts-with(., ' ')]">
338 <value-of select="substring($firstline, 1, string-length($firstline)-1)"/>
341 <value-of select="$firstline"/>
344 <for-each select="exslset:intersection(following-sibling::*[starts-with(., ' ')], exslset:leading($fields, $next))">
345 <variable name="nextline" select="normalize-space(.)"/>
347 <when test="substring($nextline, string-length($nextline))='\' and following-sibling::*[position()=1 and starts-with(., ' ')]">
348 <value-of select="substring($nextline, 1, string-length($nextline)-1)"/>
351 <value-of select="$nextline"/>
363 <call-template name="LesML:comment-out">
364 <with-param name="source" select="substring-after(., '%%')"/>
370 <element name="div" namespace="&xhtml;">
371 <attribute name="class">
374 <call-template name="LesML:paragraphize">
375 <with-param name="lines" select="exslset:trailing($doclines, $record-separators[last()])"/>
381 <call-template name="LesML:parse">
382 <with-param name="lines" select="$docsep|exslset:trailing($lines, $docsep)"/>
383 <with-param name="parent-params" select="$params"/>
387 <template name="LesML:paragraphize">
388 <param name="lines" select="/.."/>
389 <variable name="last-lines" select="$lines[normalize-space()!='' and normalize-space(following-sibling::*[1])='']|$lines[last()]"/>
390 <variable name="blocked">
391 <for-each select="$last-lines">
392 <variable name="position" select="position()"/>
393 <variable name="prev-last" select="$last-lines[($position)-1]"/>
394 <variable name="linespans" select="(exslset:intersection(exslset:trailing($lines, $prev-last), exslset:leading($lines, .))|.)[normalize-space()!='']"/>
395 <variable name="quoted" select="not($linespans[not(starts-with(., ' ') or starts-with(., '	'))])"/>
396 <variable name="preformatted" select="not($linespans[not(starts-with(normalize-space(), '|'))])"/>
397 <variable name="text">
398 <for-each select="$linespans">
400 <when test="$preformatted">
401 <value-of select="substring-after(., '|')"/>
404 <value-of select="normalize-space()"/>
407 <if test="position()!=count($linespans)">
409 <when test="$preformatted">
419 <if test="string($text)!=''">
420 <variable name="par">
422 <when test="$preformatted">
423 <element name="pre" namespace="&xhtml;">
424 <call-template name="LesML:id-and-contents">
425 <with-param name="source" select="$text"/>
429 <when test="starts-with($text, '⁌') and &sigiled-text;">
430 <element name="h1" namespace="&xhtml;">
431 <call-template name="LesML:id-and-contents">
432 <with-param name="source" select="&unsigiled-text;"/>
436 <when test="starts-with($text, '§') and &sigiled-text;">
437 <element name="h2" namespace="&xhtml;">
438 <call-template name="LesML:id-and-contents">
439 <with-param name="source" select="&unsigiled-text;"/>
443 <when test="starts-with($text, '❦') and &sigiled-text;">
444 <element name="h3" namespace="&xhtml;">
445 <call-template name="LesML:id-and-contents">
446 <with-param name="source" select="&unsigiled-text;"/>
450 <when test="starts-with($text, '✠') and &sigiled-text;">
451 <element name="h4" namespace="&xhtml;">
452 <call-template name="LesML:id-and-contents">
453 <with-param name="source" select="&unsigiled-text;"/>
457 <when test="starts-with($text, '•') and &sigiled-text;">
458 <element name="li" namespace="&xhtml;">
459 <attribute name="class">
460 <text>unordered</text>
462 <attribute name="data-level">
465 <element name="p" namespace="&xhtml;">
466 <call-template name="LesML:id-and-contents">
467 <with-param name="source" select="&unsigiled-text;"/>
472 <when test="starts-with($text, '🔢') and &sigiled-text;">
473 <element name="li" namespace="&xhtml;">
474 <attribute name="class">
477 <attribute name="data-level">
480 <element name="p" namespace="&xhtml;">
481 <call-template name="LesML:id-and-contents">
482 <with-param name="source" select="&unsigiled-text;"/>
487 <when test="starts-with($text, '◦') and &sigiled-text;">
488 <element name="li" namespace="&xhtml;">
489 <attribute name="class">
490 <text>unordered</text>
492 <attribute name="data-level">
495 <element name="p" namespace="&xhtml;">
496 <call-template name="LesML:id-and-contents">
497 <with-param name="source" select="&unsigiled-text;"/>
502 <when test="starts-with($text, '🔠') and &sigiled-text;">
503 <element name="li" namespace="&xhtml;">
504 <attribute name="class">
507 <attribute name="data-level">
510 <element name="p" namespace="&xhtml;">
511 <call-template name="LesML:id-and-contents">
512 <with-param name="source" select="&unsigiled-text;"/>
517 <when test="starts-with($text, '▪') and &sigiled-text;">
518 <element name="li" namespace="&xhtml;">
519 <attribute name="class">
520 <text>unordered</text>
522 <attribute name="data-level">
525 <element name="p" namespace="&xhtml;">
526 <call-template name="LesML:id-and-contents">
527 <with-param name="source" select="&unsigiled-text;"/>
532 <when test="starts-with($text, '🔡') and &sigiled-text;">
533 <element name="li" namespace="&xhtml;">
534 <attribute name="class">
537 <attribute name="data-level">
540 <element name="p" namespace="&xhtml;">
541 <call-template name="LesML:id-and-contents">
542 <with-param name="source" select="&unsigiled-text;"/>
547 <when test="starts-with($text, '⁃') and &sigiled-text;">
548 <element name="li" namespace="&xhtml;">
549 <attribute name="class">
550 <text>unordered</text>
552 <attribute name="data-level">
555 <element name="p" namespace="&xhtml;">
556 <call-template name="LesML:id-and-contents">
557 <with-param name="source" select="&unsigiled-text;"/>
562 <when test="starts-with($text, '🔣') and &sigiled-text;">
563 <element name="li" namespace="&xhtml;">
564 <attribute name="class">
567 <attribute name="data-level">
570 <element name="p" namespace="&xhtml;">
571 <call-template name="LesML:id-and-contents">
572 <with-param name="source" select="&unsigiled-text;"/>
577 <when test="starts-with($text, '🛈') and &sigiled-text;">
578 <element name="div" namespace="&xhtml;">
579 <attribute name="role">
582 <attribute name="class">
585 <element name="p" namespace="&xhtml;">
586 <call-template name="LesML:id-and-contents">
587 <with-param name="source" select="&unsigiled-text;"/>
592 <when test="starts-with($text, '⯑') and &sigiled-text;">
593 <element name="div" namespace="&xhtml;">
594 <attribute name="role">
597 <attribute name="class">
600 <element name="p" namespace="&xhtml;">
601 <call-template name="LesML:id-and-contents">
602 <with-param name="source" select="&unsigiled-text;"/>
607 <when test="starts-with($text, '⚠︎') and &sigiled-text;">
608 <element name="div" namespace="&xhtml;">
609 <attribute name="role">
612 <attribute name="class">
615 <element name="p" namespace="&xhtml;">
616 <call-template name="LesML:id-and-contents">
617 <with-param name="source" select="&unsigiled-text;"/>
622 <when test="starts-with($text, '※') and &sigiled-text;">
623 <element name="div" namespace="&xhtml;">
624 <attribute name="role">
627 <attribute name="class">
630 <element name="p" namespace="&xhtml;">
631 <call-template name="LesML:id-and-contents">
632 <with-param name="source" select="&unsigiled-text;"/>
637 <when test="starts-with($text, '☡') and &sigiled-text;">
638 <element name="div" namespace="&xhtml;">
639 <attribute name="role">
642 <attribute name="class">
645 <element name="p" namespace="&xhtml;">
646 <call-template name="LesML:id-and-contents">
647 <with-param name="source" select="&unsigiled-text;"/>
652 <when test="starts-with($text, '⋯') and &sigiled-text;">
653 <element name="div" namespace="&xhtml;">
654 <attribute name="class">
655 <text>continuation</text>
657 <element name="p" namespace="&xhtml;">
658 <call-template name="LesML:id-and-contents">
659 <with-param name="source" select="&unsigiled-text;"/>
664 <when test="starts-with($text, '#') and &sigiled-text;">
665 <call-template name="LesML:comment-out">
666 <with-param name="source" select="&unsigiled-text;"/>
670 <element name="p" namespace="&xhtml;">
671 <call-template name="LesML:id-and-contents">
672 <with-param name="source" select="$text"/>
679 <when test="translate(string($text), '§ion-break; ', '')=''">
680 <element name="hr" namespace="&xhtml;"/>
682 <when test="$quoted">
683 <element name="blockquote" namespace="&xhtml;">
684 <copy-of select="$par"/>
688 <copy-of select="$par"/>
694 <variable name="inlined">
695 <apply-templates select="exsl:node-set($blocked)/node()" mode="LesML:comment"/>
697 <apply-templates select="exsl:node-set($inlined)/node()" mode="LesML:finalize-tree"/>
699 <template match="html:script[@type='text/lesml']">
700 <variable name="lines-fragment">
701 <call-template name="LesML:split">
702 <with-param name="source">
703 <for-each select=".//text()">
704 <value-of select="."/>
709 <element name="div" namespace="&xhtml;">
710 <call-template name="LesML:parse">
711 <with-param name="lines" select="exsl:node-set($lines-fragment)/*"/>
715 <template match="node()" mode="LesML:finalize-attributes">
716 <variable name="notattr" select="following-sibling::node()[not(self::text() and translate(., ' 	', '')='' or self::LesML:attribute)]"/>
717 <for-each select="(.|exslset:leading(following-sibling::node(), $notattr)[self::LesML:attribute])/@*">
718 <copy-of select="."/>
719 <if test="local-name()='lang' and namespace-uri()=''">
720 <attribute name="xml:lang">
721 <value-of select="."/>
726 <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(., ' 	', '')='']" mode="LesML:finalize-tree" priority="2"/>
727 <template match="LesML:attribute|text()[following-sibling::node()[position()=1 and self::LesML:attribute]]" mode="LesML:finalize-tree" priority="1">
728 <element name="span" namespace="&xhtml;">
729 <apply-templates select="." mode="LesML:finalize-attributes"/>
730 <if test="self::text()">
731 <call-template name="LesML:break-and-unescape">
732 <with-param name="source" select="string(.)"/>
737 <template match="html:blockquote" mode="LesML:finalize-tree">
738 <if test="not(preceding-sibling::node()) or preceding-sibling::node()[position()=1 and not(self::html:blockquote)]">
739 <variable name="notquote" select="following-sibling::node()[not(self::html:blockquote)][1]"/>
740 <variable name="contents">
741 <copy-of select="node()"/>
742 <for-each select="exslset:leading(following-sibling::node(), $notquote)">
743 <copy-of select="node()"/>
746 <variable name="content-nodes" select="exsl:node-set($contents)/node()"/>
747 <variable name="laststarttext" select="$content-nodes[last()]/self::html:p[not(@class) and not(@role)]/node()[self::text() or self::*][position()=1 and self::text()]"/>
749 <when test="starts-with($laststarttext, '— ')">
750 <variable name="caption">
751 <copy-of select="$laststarttext/preceding-sibling::node()"/>
752 <value-of select="substring-after($laststarttext, '— ')"/>
753 <copy-of select="$laststarttext/following-sibling::node()"/>
755 <element name="figure" namespace="&xhtml;">
757 <apply-templates select="@*|$content-nodes[position()!=last()]" mode="LesML:finalize-tree"/>
759 <element name="figcaption" namespace="&xhtml;">
760 <for-each select="$content-nodes[last()]">
762 <apply-templates select="@*|exsl:node-set($caption)/node()" mode="LesML:finalize-tree"/>
770 <apply-templates select="@*|$content-nodes" mode="LesML:finalize-tree"/>
776 <template match="html:div" mode="LesML:finalize-tree">
777 <if test="not(@class='continuation') or not(preceding-sibling::node()) or preceding-sibling::node()[position()=1 and not(self::html:div or self::html:li)]">
778 <variable name="notcontinuation" select="following-sibling::node()[not(self::html:div and @class='continuation')][1]"/>
780 <apply-templates select="@*|node()" mode="LesML:finalize-tree"/>
781 <for-each select="exslset:leading(following-sibling::node(), $notcontinuation)">
782 <apply-templates select="node()" mode="LesML:finalize-tree"/>
787 <template match="html:li" mode="LesML:finalize-tree">
788 <if test="not(preceding-sibling::node()) or preceding-sibling::node()[not(preceding-sibling::* and self::html:div and @class='continuation')][position()=1 and not(self::html:li)]">
789 <apply-templates select="." mode="LesML:finalize-list"/>
792 <template match="html:li" mode="LesML:finalize-list">
793 <param name="parent-level" select="0"/>
794 <variable name="current-class" select="string(@class)"/>
795 <variable name="current-level" select="number(@data-level)"/>
796 <variable name="wrapper">
798 <when test="@class='ordered'">
806 <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]"/>
807 <element name="{$wrapper}" namespace="&xhtml;">
808 <for-each select=".|exslset:leading(following-sibling::node(), $notinlist)[self::html:li and @data-level=$current-level]">
809 <variable name="notcontinuation" select="following-sibling::node()[not(self::html:div and @class='continuation')][1]"/>
811 <apply-templates select="@*|node()" mode="LesML:finalize-tree"/>
812 <for-each select="exslset:leading(following-sibling::node(), $notcontinuation)">
813 <apply-templates select="node()" mode="LesML:finalize-tree"/>
815 <if test="$notcontinuation/self::html:li[@data-level>$current-level]">
816 <apply-templates select="$notcontinuation" mode="LesML:finalize-list">
817 <with-param name="parent-level" select="$current-level"/>
823 <if test="$notinlist/self::html:li[@data-level>$parent-level]">
824 <apply-templates select="$notinlist" mode="LesML:finalize-list">
825 <with-param name="parent-level" select="$parent-level"/>
829 <template match="processing-instruction()[local-name()='LesML-Token-Escape']" mode="LesML:finalize-tree">
830 <value-of select="."/>
832 <template match="text()" mode="LesML:finalize-tree">
833 <call-template name="LesML:break-and-unescape">
834 <with-param name="source" select="string(.)"/>
837 <template match="@*|node()" mode="LesML:finalize-tree" priority="-1">
839 <apply-templates select="." mode="LesML:finalize-attributes"/>
840 <apply-templates select="node()" mode="LesML:finalize-tree"/>
843 <template match="node()" mode="LesML:comment">
844 <variable name="result">
846 <when test="self::*">
847 <variable name="start-node" select="text()[contains(., '⌦')][1]"/>
848 <variable name="after-start">
849 <if test="$start-node">
850 <value-of select="substring-after($start-node, '⌦')"/>
853 <variable name="has-end-node" select="contains($after-start, '⌫') or $start-node/following-sibling::text()[contains(., '⌫')]"/>
855 <when test="$start-node and $has-end-node">
856 <variable name="following">
857 <value-of select="$after-start"/>
858 <copy-of select="$start-node/following-sibling::node()"/>
860 <variable name="end-node" select="exsl:node-set($following)/text()[contains(., '⌫')][last()]"/>
861 <variable name="comment">
862 <for-each select="$end-node/preceding-sibling::node()">
863 <value-of select="."/>
865 <value-of select="substring-before($end-node, '⌫')"/>
867 <variable name="rest-fragment">
868 <element name="span" namespace="&xhtml;">
869 <value-of select="substring-after($end-node, '⌫')"/>
870 <copy-of select="$end-node/following-sibling::node()"/>
873 <variable name="commented-rest-fragment">
874 <apply-templates select="exsl:node-set($rest-fragment)/node()" mode="LesML:comment"/>
877 <copy-of select="@*"/>
878 <copy-of select="$start-node/preceding-sibling::node()"/>
879 <copy-of select="substring-before($start-node, '⌦')"/>
880 <call-template name="LesML:comment-out">
881 <with-param name="source" select="string($comment)"/>
883 <copy-of select="exsl:node-set($commented-rest-fragment)/*/node()"/>
888 <copy-of select="@*"/>
889 <apply-templates select="node()" mode="LesML:comment"/>
894 <when test="self::text()[contains(., '⌧')]">
895 <variable name="split-fragment">
896 <call-template name="LesML:split">
897 <with-param name="source" select="string()"/>
898 <with-param name="separator" select="'⌧'"/>
901 <for-each select="exsl:node-set($split-fragment)/node()">
902 <value-of select="."/>
903 <if test="position()!=last()">
904 <call-template name="LesML:comment-out"/>
909 <copy-of select="."/>
913 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:attrify"/>
915 <template match="node()" mode="LesML:inline">
916 <param name="element-name"/>
917 <param name="element-namespace" select="'http://www.w3.org/1999/xhtml'"/>
918 <param name="start-sigil"/>
919 <param name="end-sigil"/>
920 <param name="class"/>
923 <when test="self::*">
924 <variable name="end-node" select="text()[contains(., $end-sigil)][1]"/>
925 <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))"/>
927 <when test="$end-node and $has-start-node">
928 <variable name="preceding">
929 <copy-of select="$end-node/preceding-sibling::node()"/>
930 <value-of select="substring-before($end-node, $end-sigil)"/>
932 <variable name="start-node" select="exsl:node-set($preceding)/text()[contains(., $start-sigil)][last()]"/>
933 <variable name="start-tokens-fragment">
934 <call-template name="LesML:split">
935 <with-param name="source" select="string($start-node)"/>
936 <with-param name="separator" select="$start-sigil"/>
939 <variable name="start-tokens" select="exsl:node-set($start-tokens-fragment)/*"/>
940 <variable name="wrapped">
942 <copy-of select="@*"/>
943 <copy-of select="$start-node/preceding-sibling::node()"/>
944 <for-each select="$start-tokens[position()!=last()]">
945 <value-of select="."/>
946 <if test="position()!=last()">
947 <value-of select="$start-sigil"/>
950 <element name="{$element-name}" namespace="{$element-namespace}">
951 <if test="string($role)!=''">
952 <attribute name="role">
953 <value-of select="$role"/>
956 <if test="string($class)!=''">
957 <attribute name="class">
958 <value-of select="$class"/>
961 <value-of select="$start-tokens[last()]"/>
962 <copy-of select="$start-node/following-sibling::node()"/>
964 <value-of select="substring-after($end-node, $end-sigil)"/>
965 <copy-of select="$end-node/following-sibling::node()"/>
968 <apply-templates select="exsl:node-set($wrapped)/*" mode="LesML:inline">
969 <with-param name="element-name" select="$element-name"/>
970 <with-param name="element-namespace" select="$element-namespace"/>
971 <with-param name="start-sigil" select="$start-sigil"/>
972 <with-param name="end-sigil" select="$end-sigil"/>
973 <with-param name="role" select="$role"/>
978 <copy-of select="@*"/>
979 <apply-templates select="node()" mode="LesML:inline">
980 <with-param name="element-name" select="$element-name"/>
981 <with-param name="element-namespace" select="$element-namespace"/>
982 <with-param name="start-sigil" select="$start-sigil"/>
983 <with-param name="end-sigil" select="$end-sigil"/>
984 <with-param name="role" select="$role"/>
991 <copy-of select="."/>
995 <template match="*" mode="LesML:partition">
996 <param name="start-sigil"/>
997 <param name="end-sigil"/>
998 <param name="separator"/>
999 <param name="ncname-keys" select="false()"/>
1000 <variable name="end-node" select="text()[contains(., $end-sigil)][1]"/>
1001 <variable name="has-start-node" select="$end-node/preceding-sibling::text()[contains(., $start-sigil) and not(following-sibling::* or following-sibling::comment())] or string-length(substring-after($end-node, $start-sigil))>string-length(substring-after($end-node, $end-sigil))"/>
1003 <when test="$end-node and $has-start-node">
1004 <variable name="preceding">
1005 <copy-of select="$end-node/preceding-sibling::node()"/>
1006 <value-of select="substring-before($end-node, $end-sigil)"/>
1008 <variable name="start-node" select="exsl:node-set($preceding)/text()[contains(., $start-sigil) and not(following-sibling::*)][last()]"/>
1009 <variable name="start-tokens-fragment">
1010 <call-template name="LesML:split">
1011 <with-param name="source" select="string($start-node)"/>
1012 <with-param name="separator" select="$start-sigil"/>
1015 <variable name="start-tokens" select="exsl:node-set($start-tokens-fragment)/*"/>
1016 <variable name="innards">
1017 <value-of select="$start-tokens[last()]"/>
1018 <for-each select="$start-node/following-sibling::node()">
1019 <value-of select="."/>
1023 <when test="contains($innards, $separator)">
1024 <variable name="keyval-fragment">
1025 <call-template name="LesML:split">
1026 <with-param name="source" select="$innards"/>
1027 <with-param name="separator" select="$separator"/>
1030 <variable name="keyval" select="exsl:node-set($keyval-fragment)/*"/>
1031 <variable name="key">
1033 <when test="$ncname-keys">
1034 <value-of select="$keyval[1]"/>
1037 <for-each select="$keyval[position()!=last()]">
1038 <value-of select="."/>
1039 <if test="position()!=last()">
1040 <value-of select="$separator"/>
1046 <variable name="value">
1048 <when test="$ncname-keys">
1049 <for-each select="$keyval[position()!=1]">
1050 <value-of select="."/>
1051 <if test="position()!=last()">
1052 <value-of select="$separator"/>
1057 <value-of select="$keyval[last()]"/>
1062 <when test="not($ncname-keys) or /self::node()[translate(normalize-space($key), ' /([,*', '')=string($key) and exsldyn:evaluate(concat('not(self::html:', $key, ')'))]">
1063 <element name="span" namespace="&xhtml;">
1064 <copy-of select="$start-node/preceding-sibling::node()"/>
1065 <for-each select="$start-tokens[position()!=last()]">
1066 <value-of select="."/>
1067 <if test="position()!=last()">
1068 <value-of select="$start-sigil"/>
1072 <element name="span" namespace="&xhtml;">
1073 <value-of select="$key"/>
1075 <element name="span" namespace="&xhtml;">
1076 <value-of select="$value"/>
1078 <element name="span" namespace="&xhtml;">
1079 <value-of select="substring-after($end-node, $end-sigil)"/>
1080 <copy-of select="$end-node/following-sibling::node()"/>
1084 <element name="span" namespace="&xhtml;">
1085 <copy-of select="$start-node/preceding-sibling::node()"/>
1086 <for-each select="$start-tokens[position()!=last()]">
1087 <value-of select="."/>
1088 <if test="position()!=last()">
1089 <value-of select="$start-sigil"/>
1092 <processing-instruction name="LesML-Token-Escape">
1093 <value-of select="$start-sigil"/>
1094 </processing-instruction>
1095 <value-of select="$start-tokens[last()]"/>
1096 <value-of select="$start-node/following-sibling::node()"/>
1097 <value-of select="$end-sigil"/>
1098 <value-of select="substring-after($end-node, $end-sigil)"/>
1099 <copy-of select="$end-node/following-sibling::node()"/>
1105 <element name="span" namespace="&xhtml;">
1106 <copy-of select="$start-node/preceding-sibling::node()"/>
1107 <for-each select="$start-tokens[position()!=last()]">
1108 <value-of select="."/>
1109 <if test="position()!=last()">
1110 <value-of select="$start-sigil"/>
1113 <processing-instruction name="LesML-Token-Escape">
1114 <value-of select="$start-sigil"/>
1115 </processing-instruction>
1116 <value-of select="$start-tokens[last()]"/>
1117 <value-of select="$start-node/following-sibling::node()"/>
1118 <value-of select="$end-sigil"/>
1119 <value-of select="substring-after($end-node, $end-sigil)"/>
1120 <copy-of select="$end-node/following-sibling::node()"/>
1125 <when test="$end-node">
1126 <element name="span" namespace="&xhtml;">
1127 <copy-of select="$end-node/preceding-sibling::node()"/>
1128 <value-of select="substring-before($end-node, $end-sigil)"/>
1129 <processing-instruction name="LesML-Token-Escape">
1130 <value-of select="$end-sigil"/>
1131 </processing-instruction>
1132 <value-of select="substring-after($end-node, $end-sigil)"/>
1133 <copy-of select="$end-node/following-sibling::node()"/>
1137 <processing-instruction name="LesML-All-Done"/>
1141 <template match="node()" mode="LesML:attrify">
1142 <variable name="result">
1144 <when test="self::*">
1145 <variable name="partitioned-fragment">
1146 <apply-templates mode="LesML:partition" select=".">
1147 <with-param name="start-sigil" select="'{@'"/>
1148 <with-param name="end-sigil" select="'"}'"/>
1149 <with-param name="separator" select="'="'"/>
1150 <with-param name="ncname-keys" select="true()"/>
1153 <variable name="partitioned" select="exsl:node-set($partitioned-fragment)/node()"/>
1155 <when test="count($partitioned)>1">
1156 <variable name="processed">
1158 <copy-of select="@*"/>
1159 <copy-of select="$partitioned[1]/node()"/>
1160 <element name="LesML:attribute" namespace="&LesML;">
1161 <attribute name="{$partitioned[2]}">
1162 <value-of select="$partitioned[3]"/>
1165 <copy-of select="$partitioned[4]/node()"/>
1168 <apply-templates select="exsl:node-set($processed)/node()" mode="LesML:attrify"/>
1170 <when test="$partitioned[self::processing-instruction() and local-name()='LesML-All-Done']">
1172 <copy-of select="@*"/>
1173 <apply-templates select="node()" mode="LesML:attrify"/>
1177 <variable name="processed">
1179 <copy-of select="@*"/>
1180 <copy-of select="$partitioned/node()"/>
1183 <apply-templates select="exsl:node-set($processed)/node()" mode="LesML:attrify"/>
1188 <copy-of select="."/>
1192 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:linkify"/>
1194 <template match="node()" mode="LesML:linkify">
1195 <variable name="result">
1197 <when test="processing-instruction()[local-name()='LesML-All-Done']">
1199 <copy-of select="@*|node()[not(self::processing-instruction() and local-name()='LesML-All-Done')]"/>
1202 <when test="self::*">
1203 <variable name="partitioned-fragment">
1204 <apply-templates mode="LesML:partition" select=".">
1205 <with-param name="start-sigil" select="'{🔗'"/>
1206 <with-param name="end-sigil" select="'>}'"/>
1207 <with-param name="separator" select="'<'"/>
1210 <variable name="partitioned" select="exsl:node-set($partitioned-fragment)/node()"/>
1212 <when test="count($partitioned)>1">
1213 <variable name="processed">
1215 <copy-of select="@*"/>
1216 <copy-of select="$partitioned[1]/node()"/>
1217 <element name="a" namespace="&xhtml;">
1218 <attribute name="href">
1219 <value-of select="$partitioned[3]"/>
1221 <processing-instruction name="LesML-All-Done"/>
1223 <when test="string($partitioned[2])=''">
1224 <value-of select="$partitioned[3]"/>
1227 <value-of select="$partitioned[2]"/>
1231 <copy-of select="$partitioned[4]/node()"/>
1234 <apply-templates select="exsl:node-set($processed)/node()" mode="LesML:linkify"/>
1236 <when test="$partitioned[self::processing-instruction() and local-name()='LesML-All-Done']">
1238 <copy-of select="@*"/>
1239 <apply-templates select="node()" mode="LesML:linkify"/>
1243 <variable name="processed">
1245 <copy-of select="@*"/>
1246 <copy-of select="$partitioned/node()"/>
1249 <apply-templates select="exsl:node-set($processed)/node()" mode="LesML:linkify"/>
1254 <copy-of select="."/>
1258 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:strikethrough"/>
1260 <template match="node()" mode="LesML:strikethrough">
1261 <variable name="result">
1262 <apply-templates select="." mode="LesML:inline">
1263 <with-param name="element-name" select="'s'"/>
1264 <with-param name="element-namespace" select="'&xhtml;'"/>
1265 <with-param name="start-sigil" select="'⸠'"/>
1266 <with-param name="end-sigil" select="'⸡'"/>
1269 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:underline"/>
1271 <template match="node()" mode="LesML:underline">
1272 <variable name="result">
1273 <apply-templates select="." mode="LesML:inline">
1274 <with-param name="element-name" select="'u'"/>
1275 <with-param name="element-namespace" select="'&xhtml;'"/>
1276 <with-param name="start-sigil" select="'⸤'"/>
1277 <with-param name="end-sigil" select="'⸥'"/>
1280 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:noted"/>
1282 <template match="node()" mode="LesML:noted">
1283 <variable name="result">
1284 <apply-templates select="." mode="LesML:inline">
1285 <with-param name="element-name" select="'small'"/>
1286 <with-param name="element-namespace" select="'&xhtml;'"/>
1287 <with-param name="start-sigil" select="'⟦'"/>
1288 <with-param name="end-sigil" select="'⟧'"/>
1289 <with-param name="role" select="'note'"/>
1292 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:parenthetical"/>
1294 <template match="node()" mode="LesML:parenthetical">
1295 <variable name="result">
1296 <apply-templates select="." mode="LesML:inline">
1297 <with-param name="element-name" select="'small'"/>
1298 <with-param name="element-namespace" select="'&xhtml;'"/>
1299 <with-param name="start-sigil" select="'⸨'"/>
1300 <with-param name="end-sigil" select="'⸩'"/>
1303 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:code"/>
1305 <template match="node()" mode="LesML:code">
1306 <variable name="result">
1307 <apply-templates select="." mode="LesML:inline">
1308 <with-param name="element-name" select="'code'"/>
1309 <with-param name="element-namespace" select="'&xhtml;'"/>
1310 <with-param name="start-sigil" select="'`'"/>
1311 <with-param name="end-sigil" select="'´'"/>
1314 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:titled"/>
1316 <template match="node()" mode="LesML:titled">
1317 <variable name="result">
1318 <apply-templates select="." mode="LesML:inline">
1319 <with-param name="element-name" select="'cite'"/>
1320 <with-param name="element-namespace" select="'&xhtml;'"/>
1321 <with-param name="start-sigil" select="'⟪'"/>
1322 <with-param name="end-sigil" select="'⟫'"/>
1325 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:named"/>
1327 <template match="node()" mode="LesML:named">
1328 <variable name="result">
1329 <apply-templates select="." mode="LesML:inline">
1330 <with-param name="element-name" select="'u'"/>
1331 <with-param name="element-namespace" select="'&xhtml;'"/>
1332 <with-param name="start-sigil" select="'⸶'"/>
1333 <with-param name="end-sigil" select="'⸷'"/>
1334 <with-param name="class" select="'name'"/>
1337 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:offset"/>
1339 <template match="node()" mode="LesML:offset">
1340 <variable name="result">
1341 <apply-templates select="." mode="LesML:inline">
1342 <with-param name="element-name" select="'i'"/>
1343 <with-param name="element-namespace" select="'&xhtml;'"/>
1344 <with-param name="start-sigil" select="'⟨'"/>
1345 <with-param name="end-sigil" select="'⟩'"/>
1348 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:bolded"/>
1350 <template match="node()" mode="LesML:bolded">
1351 <variable name="result">
1352 <apply-templates select="." mode="LesML:inline">
1353 <with-param name="element-name" select="'b'"/>
1354 <with-param name="element-namespace" select="'&xhtml;'"/>
1355 <with-param name="start-sigil" select="'⦃'"/>
1356 <with-param name="end-sigil" select="'⦄'"/>
1359 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:important"/>
1361 <template match="node()" mode="LesML:important">
1362 <variable name="result">
1363 <apply-templates select="." mode="LesML:inline">
1364 <with-param name="element-name" select="'strong'"/>
1365 <with-param name="element-namespace" select="'&xhtml;'"/>
1366 <with-param name="start-sigil" select="'☞'"/>
1367 <with-param name="end-sigil" select="'☜'"/>
1370 <apply-templates select="exsl:node-set($result)/node()" mode="LesML:emphasized"/>
1372 <template match="node()" mode="LesML:emphasized">
1373 <apply-templates select="." mode="LesML:inline">
1374 <with-param name="element-name" select="'em'"/>
1375 <with-param name="element-namespace" select="'&xhtml;'"/>
1376 <with-param name="start-sigil" select="'⹐'"/>
1377 <with-param name="end-sigil" select="'⹑'"/>