@pretextbook/pretext-html 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -4
- package/assets/preview-html.xsl +230 -230
- package/assets/upstream.json +7 -7
- package/assets/xsl/entities.ent +154 -154
- package/assets/xsl/extract-asymptote.xsl +68 -68
- package/assets/xsl/extract-biblio-csl.xsl +327 -327
- package/assets/xsl/extract-datafile.xsl +71 -71
- package/assets/xsl/extract-dynamic.xsl +139 -139
- package/assets/xsl/extract-identity.xsl +136 -136
- package/assets/xsl/extract-interactive.xsl +81 -81
- package/assets/xsl/extract-latex-image.xsl +118 -118
- package/assets/xsl/extract-mermaid.xsl +58 -58
- package/assets/xsl/extract-mom.xsl +63 -63
- package/assets/xsl/extract-pg.xsl +2897 -2897
- package/assets/xsl/extract-prefigure.xsl +157 -157
- package/assets/xsl/extract-qrcode.xsl +100 -100
- package/assets/xsl/extract-runestone-page-template.xsl +139 -139
- package/assets/xsl/extract-sageplot.xsl +166 -166
- package/assets/xsl/extract-stack.xsl +56 -56
- package/assets/xsl/extract-trace.xsl +134 -134
- package/assets/xsl/extract-youtube.xsl +63 -63
- package/assets/xsl/html-symbols.xsl +3344 -3344
- package/assets/xsl/latex/pretext-latex-AIM.xsl +56 -56
- package/assets/xsl/latex/pretext-latex-CLP.xsl +148 -148
- package/assets/xsl/latex/pretext-latex-chaos.xsl +317 -317
- package/assets/xsl/latex/pretext-latex-dyslexic-font.xsl +76 -76
- package/assets/xsl/latex/pretext-latex-guide.xsl +104 -104
- package/assets/xsl/latex/pretext-latex-texstyle.xsl +862 -862
- package/assets/xsl/localizations/af-ZA.xml +276 -276
- package/assets/xsl/localizations/bg-BG.xml +276 -276
- package/assets/xsl/localizations/ca-ES.xml +285 -285
- package/assets/xsl/localizations/cs-CZ.xml +280 -280
- package/assets/xsl/localizations/de-DE.xml +281 -281
- package/assets/xsl/localizations/en-US.xml +427 -427
- package/assets/xsl/localizations/es-ES.xml +287 -287
- package/assets/xsl/localizations/fi-FI.xml +275 -275
- package/assets/xsl/localizations/fr-CA.xml +276 -276
- package/assets/xsl/localizations/fr-FR.xml +280 -280
- package/assets/xsl/localizations/hu-HU.xml +280 -280
- package/assets/xsl/localizations/it-IT.xml +276 -276
- package/assets/xsl/localizations/ku-CKB.xml +275 -275
- package/assets/xsl/localizations/localizations.xml +48 -48
- package/assets/xsl/localizations/nl-NL.xml +275 -275
- package/assets/xsl/localizations/pt-BR.xml +288 -288
- package/assets/xsl/localizations/pt-PT.xml +292 -292
- package/assets/xsl/localizations/zh-HANS.xml +269 -269
- package/assets/xsl/pretext-assembly.xsl +4795 -4795
- package/assets/xsl/pretext-basic-html.xsl +86 -86
- package/assets/xsl/pretext-beamer.xsl +662 -662
- package/assets/xsl/pretext-braille-preprint.xsl +2249 -2249
- package/assets/xsl/pretext-common.xsl +12018 -12018
- package/assets/xsl/pretext-dynamic.xsl +65 -65
- package/assets/xsl/pretext-epub.xsl +1483 -1483
- package/assets/xsl/pretext-fo.xsl +4593 -4593
- package/assets/xsl/pretext-html.xsl +14791 -14791
- package/assets/xsl/pretext-json-manifest.xsl +150 -150
- package/assets/xsl/pretext-jupyter.xsl +868 -868
- package/assets/xsl/pretext-latex-classic.xsl +952 -952
- package/assets/xsl/pretext-latex-common.xsl +11563 -11563
- package/assets/xsl/pretext-latex.xsl +47 -47
- package/assets/xsl/pretext-litprog.xsl +105 -105
- package/assets/xsl/pretext-merge.xsl +41 -41
- package/assets/xsl/pretext-numbers.xsl +875 -875
- package/assets/xsl/pretext-revealjs.xsl +522 -522
- package/assets/xsl/pretext-runestone-fitb.xsl +1233 -1233
- package/assets/xsl/pretext-runestone-static.xsl +1438 -1438
- package/assets/xsl/pretext-runestone.xsl +3083 -3083
- package/assets/xsl/pretext-sage-doctest.xsl +289 -289
- package/assets/xsl/pretext-smc.xsl +492 -492
- package/assets/xsl/pretext-solution-manual-latex.xsl +323 -323
- package/assets/xsl/pretext-text-utilities.xsl +1217 -1217
- package/assets/xsl/pretext-text.xsl +392 -392
- package/assets/xsl/pretext-units.xsl +195 -195
- package/assets/xsl/pretext-view-source.xsl +157 -157
- package/assets/xsl/pretext-ww-problem-sets.xsl +391 -391
- package/assets/xsl/publisher-variables.xsl +4756 -4756
- package/assets/xsl/support/extract-math.xsl +256 -256
- package/assets/xsl/support/package-math.xsl +141 -141
- package/assets/xsl/support/play-button/play-button.svg +3 -3
- package/assets/xsl/support/pretext-pg-macros.xsl +110 -110
- package/assets/xsl/support/webpack_static_imports.xml +14 -14
- package/assets/xsl/tests/null.xml +3 -3
- package/assets/xsl/tests/pretext-text-utilities-test.xsl +333 -333
- package/assets/xsl/utilities/author-report.xsl +107 -107
- package/assets/xsl/utilities/deprecate-autoname.sed +18 -18
- package/assets/xsl/utilities/deprecate-index.sed +33 -33
- package/assets/xsl/utilities/fix-deprecations.xsl +663 -663
- package/assets/xsl/utilities/pretext-enhanced-source.xsl +112 -112
- package/assets/xsl/utilities/report-publisher-variables.xsl +162 -162
- package/assets/xsl/xml-to-json.xsl +326 -326
- package/assets/xsl/xml-to-string.xsl +328 -328
- package/assets/xsl-bundle.json +1 -0
- package/dist/{cli-C6tfAVvi.js → cli-B2LiKunq.js} +268 -233
- package/dist/cli.js +1 -1
- package/dist/host.browser.d.ts +29 -0
- package/dist/host.d.ts +41 -0
- package/dist/index.browser.d.ts +29 -0
- package/dist/index.browser.js +650 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +16 -8
- package/dist/internal/posix-path.d.ts +59 -0
- package/dist/mounts.d.ts +18 -0
- package/dist/renderer.d.ts +14 -1
- package/dist/theme.d.ts +68 -0
- package/dist/theme.js +93 -0
- package/package.json +22 -4
|
@@ -1,326 +1,326 @@
|
|
|
1
|
-
<?xml version="1.0"?>
|
|
2
|
-
|
|
3
|
-
<!--********************************************************************
|
|
4
|
-
Copyright 2023 Jason Siefken
|
|
5
|
-
|
|
6
|
-
This file is part of MathBook XML.
|
|
7
|
-
|
|
8
|
-
MathBook XML is free software: you can redistribute it and/or modify
|
|
9
|
-
it under the terms of the GNU General Public License as published by
|
|
10
|
-
the Free Software Foundation, either version 2 or version 3 of the
|
|
11
|
-
License (at your option).
|
|
12
|
-
|
|
13
|
-
MathBook XML is distributed in the hope that it will be useful,
|
|
14
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
-
GNU General Public License for more details.
|
|
17
|
-
|
|
18
|
-
You should have received a copy of the GNU General Public License
|
|
19
|
-
along with MathBook XML. If not, see <http://www.gnu.org/licenses/>.
|
|
20
|
-
*********************************************************************-->
|
|
21
|
-
|
|
22
|
-
<!--
|
|
23
|
-
A basic recreation of the XSLT3.0 xml-to-json conversion.
|
|
24
|
-
Valid JSON nodes are: <map>, <array>, <number>, <string>, <boolean>, <null>.
|
|
25
|
-
Each node may have an optional @key (but only if the node is a child of <map>.
|
|
26
|
-
Nodes must be in the namespace http://www.w3.org/2005/xpath-functions
|
|
27
|
-
|
|
28
|
-
See https://www.w3.org/TR/xslt-30/#json-to-xml-mapping for some examples.
|
|
29
|
-
|
|
30
|
-
In addition to the usual JSON elements, a <raw> tag has been added. Contents of the <raw> tag
|
|
31
|
-
are passed directly through and printed (though leading indentation is still applied).
|
|
32
|
-
|
|
33
|
-
Example:
|
|
34
|
-
```
|
|
35
|
-
<map xmlns="http://www.w3.org/2005/xpath-functions">
|
|
36
|
-
<number key="Sunday">
|
|
37
|
-
1
|
|
38
|
-
</number>
|
|
39
|
-
<boolean key="Wednesday">
|
|
40
|
-
true
|
|
41
|
-
</boolean>
|
|
42
|
-
<boolean key="Wednesday">
|
|
43
|
-
</boolean>
|
|
44
|
-
<null key="Monday" />
|
|
45
|
-
<array key="content">
|
|
46
|
-
<map>
|
|
47
|
-
<number key="id">
|
|
48
|
-
70805774
|
|
49
|
-
</number>
|
|
50
|
-
<string key="value">1 0\"01"fo\o >
bar</string>
|
|
51
|
-
<array key="position">
|
|
52
|
-
<number>
|
|
53
|
-
1004.0
|
|
54
|
-
</number>
|
|
55
|
-
<number>
|
|
56
|
-
288.0
|
|
57
|
-
</number>
|
|
58
|
-
<number>
|
|
59
|
-
1050.0
|
|
60
|
-
</number>
|
|
61
|
-
<number>
|
|
62
|
-
324.0
|
|
63
|
-
</number>
|
|
64
|
-
</array>
|
|
65
|
-
</map>
|
|
66
|
-
</array>
|
|
67
|
-
</map>
|
|
68
|
-
```
|
|
69
|
-
will produce in the document
|
|
70
|
-
```
|
|
71
|
-
{
|
|
72
|
-
"Sunday": 1,
|
|
73
|
-
"Wednesday": true,
|
|
74
|
-
"Wednesday": false,
|
|
75
|
-
"Monday": null,
|
|
76
|
-
"content": [
|
|
77
|
-
{
|
|
78
|
-
"id": 70805774,
|
|
79
|
-
"value": "1 0\\\"01\"fo\\o >\nbar",
|
|
80
|
-
"position": [
|
|
81
|
-
1004.0,
|
|
82
|
-
288.0,
|
|
83
|
-
1050.0,
|
|
84
|
-
324.0
|
|
85
|
-
]
|
|
86
|
-
}
|
|
87
|
-
]
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
For debuggining, it can be helpful to have xsltproc run whenever this file changes. If you
|
|
92
|
-
are on linux and have inotifywait installed, you can run
|
|
93
|
-
`while inotifywait -e close_write xml-to-json.xsl; do xsltproc xml-to-json.xsl sample-data.xml;
|
|
94
|
-
done`
|
|
95
|
-
where `sample-data.xml` is the JSON data you're converting.
|
|
96
|
-
-->
|
|
97
|
-
|
|
98
|
-
<xsl:stylesheet version="1.0"
|
|
99
|
-
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
100
|
-
xmlns:fn="http://www.w3.org/2005/xpath-functions"
|
|
101
|
-
xmlns:exsl="http://exslt.org/common"
|
|
102
|
-
>
|
|
103
|
-
<xsl:output method="text" encoding="utf-8" />
|
|
104
|
-
<xsl:preserve-space elements="fn:string" />
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
<!-- This is the main template that should be called to output
|
|
108
|
-
JSON from the structured XML content. -->
|
|
109
|
-
<xsl:template name="json">
|
|
110
|
-
<xsl:param name="content" />
|
|
111
|
-
<xsl:param name="indentDepth" select="0" />
|
|
112
|
-
<xsl:variable name="output">
|
|
113
|
-
<xsl:apply-templates select="exsl:node-set($content)/*" />
|
|
114
|
-
</xsl:variable>
|
|
115
|
-
<xsl:variable name="indentation">
|
|
116
|
-
<xsl:call-template name="indent">
|
|
117
|
-
<xsl:with-param name="depth" select="$indentDepth" />
|
|
118
|
-
</xsl:call-template></xsl:variable>
|
|
119
|
-
<xsl:call-template name="printIndented">
|
|
120
|
-
<xsl:with-param name="indent" select="$indentation" />
|
|
121
|
-
<xsl:with-param name="text" select="$output" />
|
|
122
|
-
</xsl:call-template>
|
|
123
|
-
</xsl:template>
|
|
124
|
-
|
|
125
|
-
<xsl:template match="fn:raw">
|
|
126
|
-
<xsl:apply-templates select="@key" mode="attr" />
|
|
127
|
-
<xsl:value-of select="." />
|
|
128
|
-
</xsl:template>
|
|
129
|
-
|
|
130
|
-
<xsl:template match="fn:null">
|
|
131
|
-
<xsl:apply-templates select="@key" mode="attr" />
|
|
132
|
-
<xsl:text>null</xsl:text>
|
|
133
|
-
</xsl:template>
|
|
134
|
-
|
|
135
|
-
<xsl:template match="fn:boolean">
|
|
136
|
-
<xsl:apply-templates select="@key" mode="attr" />
|
|
137
|
-
<xsl:choose>
|
|
138
|
-
<xsl:when test="normalize-space(text()) = 'false'">
|
|
139
|
-
<xsl:text>false</xsl:text>
|
|
140
|
-
</xsl:when>
|
|
141
|
-
<xsl:when test="normalize-space(text()) = '0'">
|
|
142
|
-
<xsl:text>false</xsl:text>
|
|
143
|
-
</xsl:when>
|
|
144
|
-
<xsl:otherwise>
|
|
145
|
-
<xsl:text>true</xsl:text>
|
|
146
|
-
</xsl:otherwise>
|
|
147
|
-
</xsl:choose>
|
|
148
|
-
</xsl:template>
|
|
149
|
-
|
|
150
|
-
<xsl:template match="fn:number">
|
|
151
|
-
<xsl:apply-templates select="@key" mode="attr" />
|
|
152
|
-
<xsl:value-of select="normalize-space(text())" />
|
|
153
|
-
</xsl:template>
|
|
154
|
-
|
|
155
|
-
<xsl:template match="fn:string">
|
|
156
|
-
<xsl:apply-templates select="@key" mode="attr" />
|
|
157
|
-
<xsl:text>"</xsl:text>
|
|
158
|
-
<xsl:call-template name="escape-for-json" />
|
|
159
|
-
<xsl:text>"</xsl:text>
|
|
160
|
-
</xsl:template>
|
|
161
|
-
|
|
162
|
-
<xsl:template match="fn:array">
|
|
163
|
-
<xsl:variable name="depth" select="count(ancestor::*)" />
|
|
164
|
-
<xsl:apply-templates
|
|
165
|
-
select="@key"
|
|
166
|
-
mode="attr" />
|
|
167
|
-
<xsl:text>[
</xsl:text>
|
|
168
|
-
<xsl:for-each select="./*">
|
|
169
|
-
<xsl:call-template name="indent">
|
|
170
|
-
<xsl:with-param name="depth" select="$depth+1"></xsl:with-param>
|
|
171
|
-
</xsl:call-template>
|
|
172
|
-
<xsl:apply-templates select="." />
|
|
173
|
-
<xsl:if test="not(position() = last())">
|
|
174
|
-
<xsl:text>,
</xsl:text>
|
|
175
|
-
</xsl:if>
|
|
176
|
-
</xsl:for-each>
|
|
177
|
-
<xsl:text>
</xsl:text>
|
|
178
|
-
<xsl:call-template name="indent">
|
|
179
|
-
<xsl:with-param name="depth" select="$depth"></xsl:with-param>
|
|
180
|
-
</xsl:call-template>
|
|
181
|
-
<xsl:text>]</xsl:text>
|
|
182
|
-
</xsl:template>
|
|
183
|
-
|
|
184
|
-
<xsl:template match="fn:map">
|
|
185
|
-
<xsl:variable name="depth" select="count(ancestor::*)" />
|
|
186
|
-
<xsl:apply-templates select="@key" mode="attr" />
|
|
187
|
-
<xsl:text>{
</xsl:text>
|
|
188
|
-
<xsl:for-each select="./*">
|
|
189
|
-
<xsl:call-template name="indent">
|
|
190
|
-
<xsl:with-param name="depth" select="$depth+1"></xsl:with-param>
|
|
191
|
-
</xsl:call-template>
|
|
192
|
-
<xsl:apply-templates select="." />
|
|
193
|
-
<xsl:if test="not(position() = last())">
|
|
194
|
-
<xsl:text>,
</xsl:text>
|
|
195
|
-
</xsl:if>
|
|
196
|
-
</xsl:for-each>
|
|
197
|
-
<xsl:text>
</xsl:text>
|
|
198
|
-
<xsl:call-template name="indent">
|
|
199
|
-
<xsl:with-param name="depth" select="$depth"></xsl:with-param>
|
|
200
|
-
</xsl:call-template>
|
|
201
|
-
<xsl:text>}</xsl:text>
|
|
202
|
-
</xsl:template>
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
<!-- Wrap any @key in quotes. No special care is taken to escape the key name,
|
|
206
|
-
so make it sensible right from the get-go! -->
|
|
207
|
-
<xsl:template match="@key" mode="attr">
|
|
208
|
-
<xsl:text>"</xsl:text>
|
|
209
|
-
<xsl:value-of select="." />
|
|
210
|
-
<xsl:text>": </xsl:text>
|
|
211
|
-
</xsl:template>
|
|
212
|
-
|
|
213
|
-
<!-- 2 paces of indentation for each $depth -->
|
|
214
|
-
<xsl:template name="indent">
|
|
215
|
-
<xsl:param name="depth" select="'0'" />
|
|
216
|
-
|
|
217
|
-
<xsl:call-template name="duplicate-string">
|
|
218
|
-
<xsl:with-param name="text" select="' '"/>
|
|
219
|
-
<xsl:with-param name="count" select="$depth" />
|
|
220
|
-
</xsl:call-template>
|
|
221
|
-
</xsl:template>
|
|
222
|
-
|
|
223
|
-
<!-- Escape strings for JSON. This process first escapes backslashes,
|
|
224
|
-
then escapes quotes (") and finally escapes newlines. Other characters
|
|
225
|
-
should be valid JSON -->
|
|
226
|
-
<xsl:template name="escape-for-json">
|
|
227
|
-
<xsl:param name="pText" select="." />
|
|
228
|
-
<xsl:variable name="escaped1">
|
|
229
|
-
<xsl:call-template name="escapeBackslash">
|
|
230
|
-
<xsl:with-param name="pText" select="$pText" />
|
|
231
|
-
</xsl:call-template>
|
|
232
|
-
</xsl:variable>
|
|
233
|
-
<xsl:variable name="escaped2">
|
|
234
|
-
<xsl:call-template name="escapeQuotes">
|
|
235
|
-
<xsl:with-param name="pText" select="$escaped1" />
|
|
236
|
-
</xsl:call-template>
|
|
237
|
-
</xsl:variable>
|
|
238
|
-
<xsl:variable name="escaped3">
|
|
239
|
-
<xsl:call-template name="escapeNewlines">
|
|
240
|
-
<xsl:with-param name="pText" select="$escaped2" />
|
|
241
|
-
</xsl:call-template>
|
|
242
|
-
</xsl:variable>
|
|
243
|
-
<xsl:value-of select="$escaped3" />
|
|
244
|
-
</xsl:template>
|
|
245
|
-
|
|
246
|
-
<xsl:template name="escapeBackslash">
|
|
247
|
-
<xsl:param name="pText" select="." />
|
|
248
|
-
<xsl:variable name="head" select="substring-before($pText, '\')" />
|
|
249
|
-
<xsl:variable name="tail" select="substring-after($pText, '\')" />
|
|
250
|
-
<xsl:choose>
|
|
251
|
-
<xsl:when test="$head or $tail">
|
|
252
|
-
<xsl:value-of select="$head" />
|
|
253
|
-
<xsl:text>\\</xsl:text>
|
|
254
|
-
<xsl:call-template name="escapeBackslash">
|
|
255
|
-
<xsl:with-param name="pText" select="$tail" />
|
|
256
|
-
</xsl:call-template>
|
|
257
|
-
</xsl:when>
|
|
258
|
-
<xsl:otherwise>
|
|
259
|
-
<xsl:value-of select="$pText" />
|
|
260
|
-
</xsl:otherwise>
|
|
261
|
-
</xsl:choose>
|
|
262
|
-
</xsl:template>
|
|
263
|
-
|
|
264
|
-
<xsl:template name="escapeQuotes">
|
|
265
|
-
<xsl:param name="pText" select="." />
|
|
266
|
-
<xsl:variable name="head" select="substring-before($pText, '"')" />
|
|
267
|
-
<xsl:variable name="tail" select="substring-after($pText, '"')" />
|
|
268
|
-
<xsl:choose>
|
|
269
|
-
<xsl:when test="$head or $tail">
|
|
270
|
-
<xsl:value-of select="$head" />
|
|
271
|
-
<xsl:text>\"</xsl:text>
|
|
272
|
-
<xsl:call-template name="escapeQuotes">
|
|
273
|
-
<xsl:with-param name="pText" select="$tail" />
|
|
274
|
-
</xsl:call-template>
|
|
275
|
-
</xsl:when>
|
|
276
|
-
<xsl:otherwise>
|
|
277
|
-
<xsl:value-of select="$pText" />
|
|
278
|
-
</xsl:otherwise>
|
|
279
|
-
</xsl:choose>
|
|
280
|
-
</xsl:template>
|
|
281
|
-
|
|
282
|
-
<xsl:template name="escapeNewlines">
|
|
283
|
-
<xsl:param name="pText" select="." />
|
|
284
|
-
<xsl:variable name="head" select="substring-before($pText, '
')" />
|
|
285
|
-
<xsl:variable name="tail" select="substring-after($pText, '
')" />
|
|
286
|
-
<xsl:choose>
|
|
287
|
-
<xsl:when test="$head or $tail">
|
|
288
|
-
<xsl:value-of select="$head" />
|
|
289
|
-
<xsl:text>\n</xsl:text>
|
|
290
|
-
<xsl:call-template name="escapeNewlines">
|
|
291
|
-
<xsl:with-param name="pText" select="$tail" />
|
|
292
|
-
</xsl:call-template>
|
|
293
|
-
</xsl:when>
|
|
294
|
-
<xsl:otherwise>
|
|
295
|
-
<xsl:value-of select="$pText" />
|
|
296
|
-
</xsl:otherwise>
|
|
297
|
-
</xsl:choose>
|
|
298
|
-
</xsl:template>
|
|
299
|
-
|
|
300
|
-
<!-- This function is from Stack Overflow
|
|
301
|
-
https://stackoverflow.com/questions/24513266/indent-multi-line-blocks-of-xsltext
|
|
302
|
-
CC-BY-SA license -->
|
|
303
|
-
<xsl:template name="printIndented">
|
|
304
|
-
<xsl:param name="text" />
|
|
305
|
-
<xsl:param name="indent" />
|
|
306
|
-
|
|
307
|
-
<xsl:if test="$text">
|
|
308
|
-
<xsl:value-of select="$indent" />
|
|
309
|
-
<xsl:variable name="thisLine" select="substring-before($text, ' ')" />
|
|
310
|
-
<xsl:choose>
|
|
311
|
-
<xsl:when test="$thisLine"><!-- $text contains at least one newline -->
|
|
312
|
-
<!-- print this line -->
|
|
313
|
-
<xsl:value-of select="concat($thisLine, ' ')" />
|
|
314
|
-
<!-- and recurse to process the rest -->
|
|
315
|
-
<xsl:call-template name="printIndented">
|
|
316
|
-
<xsl:with-param name="text" select="substring-after($text, ' ')" />
|
|
317
|
-
<xsl:with-param name="indent" select="$indent" />
|
|
318
|
-
</xsl:call-template>
|
|
319
|
-
</xsl:when>
|
|
320
|
-
<xsl:otherwise>
|
|
321
|
-
<xsl:value-of select="$text" />
|
|
322
|
-
</xsl:otherwise>
|
|
323
|
-
</xsl:choose>
|
|
324
|
-
</xsl:if>
|
|
325
|
-
</xsl:template>
|
|
326
|
-
</xsl:stylesheet>
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
|
|
3
|
+
<!--********************************************************************
|
|
4
|
+
Copyright 2023 Jason Siefken
|
|
5
|
+
|
|
6
|
+
This file is part of MathBook XML.
|
|
7
|
+
|
|
8
|
+
MathBook XML is free software: you can redistribute it and/or modify
|
|
9
|
+
it under the terms of the GNU General Public License as published by
|
|
10
|
+
the Free Software Foundation, either version 2 or version 3 of the
|
|
11
|
+
License (at your option).
|
|
12
|
+
|
|
13
|
+
MathBook XML is distributed in the hope that it will be useful,
|
|
14
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
GNU General Public License for more details.
|
|
17
|
+
|
|
18
|
+
You should have received a copy of the GNU General Public License
|
|
19
|
+
along with MathBook XML. If not, see <http://www.gnu.org/licenses/>.
|
|
20
|
+
*********************************************************************-->
|
|
21
|
+
|
|
22
|
+
<!--
|
|
23
|
+
A basic recreation of the XSLT3.0 xml-to-json conversion.
|
|
24
|
+
Valid JSON nodes are: <map>, <array>, <number>, <string>, <boolean>, <null>.
|
|
25
|
+
Each node may have an optional @key (but only if the node is a child of <map>.
|
|
26
|
+
Nodes must be in the namespace http://www.w3.org/2005/xpath-functions
|
|
27
|
+
|
|
28
|
+
See https://www.w3.org/TR/xslt-30/#json-to-xml-mapping for some examples.
|
|
29
|
+
|
|
30
|
+
In addition to the usual JSON elements, a <raw> tag has been added. Contents of the <raw> tag
|
|
31
|
+
are passed directly through and printed (though leading indentation is still applied).
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
```
|
|
35
|
+
<map xmlns="http://www.w3.org/2005/xpath-functions">
|
|
36
|
+
<number key="Sunday">
|
|
37
|
+
1
|
|
38
|
+
</number>
|
|
39
|
+
<boolean key="Wednesday">
|
|
40
|
+
true
|
|
41
|
+
</boolean>
|
|
42
|
+
<boolean key="Wednesday">
|
|
43
|
+
</boolean>
|
|
44
|
+
<null key="Monday" />
|
|
45
|
+
<array key="content">
|
|
46
|
+
<map>
|
|
47
|
+
<number key="id">
|
|
48
|
+
70805774
|
|
49
|
+
</number>
|
|
50
|
+
<string key="value">1 0\"01"fo\o >
bar</string>
|
|
51
|
+
<array key="position">
|
|
52
|
+
<number>
|
|
53
|
+
1004.0
|
|
54
|
+
</number>
|
|
55
|
+
<number>
|
|
56
|
+
288.0
|
|
57
|
+
</number>
|
|
58
|
+
<number>
|
|
59
|
+
1050.0
|
|
60
|
+
</number>
|
|
61
|
+
<number>
|
|
62
|
+
324.0
|
|
63
|
+
</number>
|
|
64
|
+
</array>
|
|
65
|
+
</map>
|
|
66
|
+
</array>
|
|
67
|
+
</map>
|
|
68
|
+
```
|
|
69
|
+
will produce in the document
|
|
70
|
+
```
|
|
71
|
+
{
|
|
72
|
+
"Sunday": 1,
|
|
73
|
+
"Wednesday": true,
|
|
74
|
+
"Wednesday": false,
|
|
75
|
+
"Monday": null,
|
|
76
|
+
"content": [
|
|
77
|
+
{
|
|
78
|
+
"id": 70805774,
|
|
79
|
+
"value": "1 0\\\"01\"fo\\o >\nbar",
|
|
80
|
+
"position": [
|
|
81
|
+
1004.0,
|
|
82
|
+
288.0,
|
|
83
|
+
1050.0,
|
|
84
|
+
324.0
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
For debuggining, it can be helpful to have xsltproc run whenever this file changes. If you
|
|
92
|
+
are on linux and have inotifywait installed, you can run
|
|
93
|
+
`while inotifywait -e close_write xml-to-json.xsl; do xsltproc xml-to-json.xsl sample-data.xml;
|
|
94
|
+
done`
|
|
95
|
+
where `sample-data.xml` is the JSON data you're converting.
|
|
96
|
+
-->
|
|
97
|
+
|
|
98
|
+
<xsl:stylesheet version="1.0"
|
|
99
|
+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
|
100
|
+
xmlns:fn="http://www.w3.org/2005/xpath-functions"
|
|
101
|
+
xmlns:exsl="http://exslt.org/common"
|
|
102
|
+
>
|
|
103
|
+
<xsl:output method="text" encoding="utf-8" />
|
|
104
|
+
<xsl:preserve-space elements="fn:string" />
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
<!-- This is the main template that should be called to output
|
|
108
|
+
JSON from the structured XML content. -->
|
|
109
|
+
<xsl:template name="json">
|
|
110
|
+
<xsl:param name="content" />
|
|
111
|
+
<xsl:param name="indentDepth" select="0" />
|
|
112
|
+
<xsl:variable name="output">
|
|
113
|
+
<xsl:apply-templates select="exsl:node-set($content)/*" />
|
|
114
|
+
</xsl:variable>
|
|
115
|
+
<xsl:variable name="indentation">
|
|
116
|
+
<xsl:call-template name="indent">
|
|
117
|
+
<xsl:with-param name="depth" select="$indentDepth" />
|
|
118
|
+
</xsl:call-template></xsl:variable>
|
|
119
|
+
<xsl:call-template name="printIndented">
|
|
120
|
+
<xsl:with-param name="indent" select="$indentation" />
|
|
121
|
+
<xsl:with-param name="text" select="$output" />
|
|
122
|
+
</xsl:call-template>
|
|
123
|
+
</xsl:template>
|
|
124
|
+
|
|
125
|
+
<xsl:template match="fn:raw">
|
|
126
|
+
<xsl:apply-templates select="@key" mode="attr" />
|
|
127
|
+
<xsl:value-of select="." />
|
|
128
|
+
</xsl:template>
|
|
129
|
+
|
|
130
|
+
<xsl:template match="fn:null">
|
|
131
|
+
<xsl:apply-templates select="@key" mode="attr" />
|
|
132
|
+
<xsl:text>null</xsl:text>
|
|
133
|
+
</xsl:template>
|
|
134
|
+
|
|
135
|
+
<xsl:template match="fn:boolean">
|
|
136
|
+
<xsl:apply-templates select="@key" mode="attr" />
|
|
137
|
+
<xsl:choose>
|
|
138
|
+
<xsl:when test="normalize-space(text()) = 'false'">
|
|
139
|
+
<xsl:text>false</xsl:text>
|
|
140
|
+
</xsl:when>
|
|
141
|
+
<xsl:when test="normalize-space(text()) = '0'">
|
|
142
|
+
<xsl:text>false</xsl:text>
|
|
143
|
+
</xsl:when>
|
|
144
|
+
<xsl:otherwise>
|
|
145
|
+
<xsl:text>true</xsl:text>
|
|
146
|
+
</xsl:otherwise>
|
|
147
|
+
</xsl:choose>
|
|
148
|
+
</xsl:template>
|
|
149
|
+
|
|
150
|
+
<xsl:template match="fn:number">
|
|
151
|
+
<xsl:apply-templates select="@key" mode="attr" />
|
|
152
|
+
<xsl:value-of select="normalize-space(text())" />
|
|
153
|
+
</xsl:template>
|
|
154
|
+
|
|
155
|
+
<xsl:template match="fn:string">
|
|
156
|
+
<xsl:apply-templates select="@key" mode="attr" />
|
|
157
|
+
<xsl:text>"</xsl:text>
|
|
158
|
+
<xsl:call-template name="escape-for-json" />
|
|
159
|
+
<xsl:text>"</xsl:text>
|
|
160
|
+
</xsl:template>
|
|
161
|
+
|
|
162
|
+
<xsl:template match="fn:array">
|
|
163
|
+
<xsl:variable name="depth" select="count(ancestor::*)" />
|
|
164
|
+
<xsl:apply-templates
|
|
165
|
+
select="@key"
|
|
166
|
+
mode="attr" />
|
|
167
|
+
<xsl:text>[
</xsl:text>
|
|
168
|
+
<xsl:for-each select="./*">
|
|
169
|
+
<xsl:call-template name="indent">
|
|
170
|
+
<xsl:with-param name="depth" select="$depth+1"></xsl:with-param>
|
|
171
|
+
</xsl:call-template>
|
|
172
|
+
<xsl:apply-templates select="." />
|
|
173
|
+
<xsl:if test="not(position() = last())">
|
|
174
|
+
<xsl:text>,
</xsl:text>
|
|
175
|
+
</xsl:if>
|
|
176
|
+
</xsl:for-each>
|
|
177
|
+
<xsl:text>
</xsl:text>
|
|
178
|
+
<xsl:call-template name="indent">
|
|
179
|
+
<xsl:with-param name="depth" select="$depth"></xsl:with-param>
|
|
180
|
+
</xsl:call-template>
|
|
181
|
+
<xsl:text>]</xsl:text>
|
|
182
|
+
</xsl:template>
|
|
183
|
+
|
|
184
|
+
<xsl:template match="fn:map">
|
|
185
|
+
<xsl:variable name="depth" select="count(ancestor::*)" />
|
|
186
|
+
<xsl:apply-templates select="@key" mode="attr" />
|
|
187
|
+
<xsl:text>{
</xsl:text>
|
|
188
|
+
<xsl:for-each select="./*">
|
|
189
|
+
<xsl:call-template name="indent">
|
|
190
|
+
<xsl:with-param name="depth" select="$depth+1"></xsl:with-param>
|
|
191
|
+
</xsl:call-template>
|
|
192
|
+
<xsl:apply-templates select="." />
|
|
193
|
+
<xsl:if test="not(position() = last())">
|
|
194
|
+
<xsl:text>,
</xsl:text>
|
|
195
|
+
</xsl:if>
|
|
196
|
+
</xsl:for-each>
|
|
197
|
+
<xsl:text>
</xsl:text>
|
|
198
|
+
<xsl:call-template name="indent">
|
|
199
|
+
<xsl:with-param name="depth" select="$depth"></xsl:with-param>
|
|
200
|
+
</xsl:call-template>
|
|
201
|
+
<xsl:text>}</xsl:text>
|
|
202
|
+
</xsl:template>
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
<!-- Wrap any @key in quotes. No special care is taken to escape the key name,
|
|
206
|
+
so make it sensible right from the get-go! -->
|
|
207
|
+
<xsl:template match="@key" mode="attr">
|
|
208
|
+
<xsl:text>"</xsl:text>
|
|
209
|
+
<xsl:value-of select="." />
|
|
210
|
+
<xsl:text>": </xsl:text>
|
|
211
|
+
</xsl:template>
|
|
212
|
+
|
|
213
|
+
<!-- 2 paces of indentation for each $depth -->
|
|
214
|
+
<xsl:template name="indent">
|
|
215
|
+
<xsl:param name="depth" select="'0'" />
|
|
216
|
+
|
|
217
|
+
<xsl:call-template name="duplicate-string">
|
|
218
|
+
<xsl:with-param name="text" select="' '"/>
|
|
219
|
+
<xsl:with-param name="count" select="$depth" />
|
|
220
|
+
</xsl:call-template>
|
|
221
|
+
</xsl:template>
|
|
222
|
+
|
|
223
|
+
<!-- Escape strings for JSON. This process first escapes backslashes,
|
|
224
|
+
then escapes quotes (") and finally escapes newlines. Other characters
|
|
225
|
+
should be valid JSON -->
|
|
226
|
+
<xsl:template name="escape-for-json">
|
|
227
|
+
<xsl:param name="pText" select="." />
|
|
228
|
+
<xsl:variable name="escaped1">
|
|
229
|
+
<xsl:call-template name="escapeBackslash">
|
|
230
|
+
<xsl:with-param name="pText" select="$pText" />
|
|
231
|
+
</xsl:call-template>
|
|
232
|
+
</xsl:variable>
|
|
233
|
+
<xsl:variable name="escaped2">
|
|
234
|
+
<xsl:call-template name="escapeQuotes">
|
|
235
|
+
<xsl:with-param name="pText" select="$escaped1" />
|
|
236
|
+
</xsl:call-template>
|
|
237
|
+
</xsl:variable>
|
|
238
|
+
<xsl:variable name="escaped3">
|
|
239
|
+
<xsl:call-template name="escapeNewlines">
|
|
240
|
+
<xsl:with-param name="pText" select="$escaped2" />
|
|
241
|
+
</xsl:call-template>
|
|
242
|
+
</xsl:variable>
|
|
243
|
+
<xsl:value-of select="$escaped3" />
|
|
244
|
+
</xsl:template>
|
|
245
|
+
|
|
246
|
+
<xsl:template name="escapeBackslash">
|
|
247
|
+
<xsl:param name="pText" select="." />
|
|
248
|
+
<xsl:variable name="head" select="substring-before($pText, '\')" />
|
|
249
|
+
<xsl:variable name="tail" select="substring-after($pText, '\')" />
|
|
250
|
+
<xsl:choose>
|
|
251
|
+
<xsl:when test="$head or $tail">
|
|
252
|
+
<xsl:value-of select="$head" />
|
|
253
|
+
<xsl:text>\\</xsl:text>
|
|
254
|
+
<xsl:call-template name="escapeBackslash">
|
|
255
|
+
<xsl:with-param name="pText" select="$tail" />
|
|
256
|
+
</xsl:call-template>
|
|
257
|
+
</xsl:when>
|
|
258
|
+
<xsl:otherwise>
|
|
259
|
+
<xsl:value-of select="$pText" />
|
|
260
|
+
</xsl:otherwise>
|
|
261
|
+
</xsl:choose>
|
|
262
|
+
</xsl:template>
|
|
263
|
+
|
|
264
|
+
<xsl:template name="escapeQuotes">
|
|
265
|
+
<xsl:param name="pText" select="." />
|
|
266
|
+
<xsl:variable name="head" select="substring-before($pText, '"')" />
|
|
267
|
+
<xsl:variable name="tail" select="substring-after($pText, '"')" />
|
|
268
|
+
<xsl:choose>
|
|
269
|
+
<xsl:when test="$head or $tail">
|
|
270
|
+
<xsl:value-of select="$head" />
|
|
271
|
+
<xsl:text>\"</xsl:text>
|
|
272
|
+
<xsl:call-template name="escapeQuotes">
|
|
273
|
+
<xsl:with-param name="pText" select="$tail" />
|
|
274
|
+
</xsl:call-template>
|
|
275
|
+
</xsl:when>
|
|
276
|
+
<xsl:otherwise>
|
|
277
|
+
<xsl:value-of select="$pText" />
|
|
278
|
+
</xsl:otherwise>
|
|
279
|
+
</xsl:choose>
|
|
280
|
+
</xsl:template>
|
|
281
|
+
|
|
282
|
+
<xsl:template name="escapeNewlines">
|
|
283
|
+
<xsl:param name="pText" select="." />
|
|
284
|
+
<xsl:variable name="head" select="substring-before($pText, '
')" />
|
|
285
|
+
<xsl:variable name="tail" select="substring-after($pText, '
')" />
|
|
286
|
+
<xsl:choose>
|
|
287
|
+
<xsl:when test="$head or $tail">
|
|
288
|
+
<xsl:value-of select="$head" />
|
|
289
|
+
<xsl:text>\n</xsl:text>
|
|
290
|
+
<xsl:call-template name="escapeNewlines">
|
|
291
|
+
<xsl:with-param name="pText" select="$tail" />
|
|
292
|
+
</xsl:call-template>
|
|
293
|
+
</xsl:when>
|
|
294
|
+
<xsl:otherwise>
|
|
295
|
+
<xsl:value-of select="$pText" />
|
|
296
|
+
</xsl:otherwise>
|
|
297
|
+
</xsl:choose>
|
|
298
|
+
</xsl:template>
|
|
299
|
+
|
|
300
|
+
<!-- This function is from Stack Overflow
|
|
301
|
+
https://stackoverflow.com/questions/24513266/indent-multi-line-blocks-of-xsltext
|
|
302
|
+
CC-BY-SA license -->
|
|
303
|
+
<xsl:template name="printIndented">
|
|
304
|
+
<xsl:param name="text" />
|
|
305
|
+
<xsl:param name="indent" />
|
|
306
|
+
|
|
307
|
+
<xsl:if test="$text">
|
|
308
|
+
<xsl:value-of select="$indent" />
|
|
309
|
+
<xsl:variable name="thisLine" select="substring-before($text, ' ')" />
|
|
310
|
+
<xsl:choose>
|
|
311
|
+
<xsl:when test="$thisLine"><!-- $text contains at least one newline -->
|
|
312
|
+
<!-- print this line -->
|
|
313
|
+
<xsl:value-of select="concat($thisLine, ' ')" />
|
|
314
|
+
<!-- and recurse to process the rest -->
|
|
315
|
+
<xsl:call-template name="printIndented">
|
|
316
|
+
<xsl:with-param name="text" select="substring-after($text, ' ')" />
|
|
317
|
+
<xsl:with-param name="indent" select="$indent" />
|
|
318
|
+
</xsl:call-template>
|
|
319
|
+
</xsl:when>
|
|
320
|
+
<xsl:otherwise>
|
|
321
|
+
<xsl:value-of select="$text" />
|
|
322
|
+
</xsl:otherwise>
|
|
323
|
+
</xsl:choose>
|
|
324
|
+
</xsl:if>
|
|
325
|
+
</xsl:template>
|
|
326
|
+
</xsl:stylesheet>
|