@pretextbook/import 0.5.0 → 0.7.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/dist/convert-worker.cjs +1 -0
- package/dist/convert-worker.js +29 -0
- package/dist/import-mode-GqdypBfV.js +112 -0
- package/dist/import-mode-YW6Lr4SU.cjs +3 -0
- package/dist/import.css +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.ts +11 -3
- package/dist/index.js +256 -150
- package/dist/lib/clean/clean-chunks.d.ts +47 -0
- package/dist/lib/clean/clean-latex.d.ts +35 -1
- package/dist/lib/convert.d.ts +7 -0
- package/dist/lib/diff.d.ts +36 -0
- package/dist/lib/file-changes.d.ts +22 -0
- package/dist/lib/latex-split.d.ts +86 -0
- package/dist/lib/pool/native-pool.d.ts +6 -0
- package/dist/lib/pool/serialize-files.d.ts +6 -0
- package/dist/lib/types.d.ts +14 -0
- package/dist/lib/upload.d.ts +27 -1
- package/dist/react/import-wizard.d.ts +22 -4
- package/dist/react/index.d.ts +2 -0
- package/dist/react/processing-panel.d.ts +6 -0
- package/dist/react.cjs +2 -2
- package/dist/react.js +592 -436
- package/dist/upload-BBHV4rXJ.js +7102 -0
- package/dist/upload-CGxfSSDN.cjs +135 -0
- package/dist/worker/convert-worker.d.ts +1 -0
- package/dist/worker/protocol.d.ts +30 -0
- package/dist/worker/worker-engine.d.ts +52 -0
- package/package.json +11 -5
- package/dist/import-mode-C8xFGO8j.cjs +0 -115
- package/dist/import-mode-Dc8qmZP6.js +0 -4787
- package/dist/lib/clean/latex-clean.d.ts +0 -10
- package/dist/lib/clean/latex-data.d.ts +0 -38
- package/dist/lib/clean/latex-scan.d.ts +0 -11
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { d as
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { d as w, r as I, a as _, f as E, b as T, w as x, s as v, e as C, c as k, p as y, g as b, h as A } from "./upload-BBHV4rXJ.js";
|
|
2
|
+
import { C as q, L as V, i as Y, M as J, j as Q, P as Z, k as ee, l as te, m as se, n as ne, o as ae, q as oe, t as re, u as ie, v as ce, x as le, y as ue, z as pe, A as fe, B as me, D as de, E as ge, F as Pe, G as he, H as xe, I as be, J as Ee, K as Te, N as ve, O as Se, Q as Le, R as Fe, S as we, T as Ie, U as _e, V as Ce, W as ke, X as ye, Y as Ae, Z as Me, _ as je, $ as Re, a0 as $e, a1 as De, a2 as Ne, a3 as Oe, a4 as Be, a5 as We } from "./upload-BBHV4rXJ.js";
|
|
3
|
+
import { a as Ke, d as ze, b as Ue, c as Ge, f as He, e as qe, g as Ve, p as Ye } from "./import-mode-GqdypBfV.js";
|
|
4
|
+
const M = {
|
|
4
5
|
png: "image/png",
|
|
5
6
|
jpg: "image/jpeg",
|
|
6
7
|
jpeg: "image/jpeg",
|
|
@@ -14,103 +15,103 @@ const k = {
|
|
|
14
15
|
webp: "image/webp",
|
|
15
16
|
ico: "image/vnd.microsoft.icon"
|
|
16
17
|
};
|
|
17
|
-
function
|
|
18
|
-
const
|
|
19
|
-
return
|
|
18
|
+
function j(e) {
|
|
19
|
+
const s = e.split(".").pop()?.toLowerCase() ?? "";
|
|
20
|
+
return M[s] ?? "application/octet-stream";
|
|
20
21
|
}
|
|
21
|
-
const
|
|
22
|
-
function
|
|
23
|
-
const
|
|
24
|
-
for (let
|
|
25
|
-
const
|
|
26
|
-
|
|
22
|
+
const P = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
23
|
+
function R(e) {
|
|
24
|
+
const s = e.length, o = [];
|
|
25
|
+
for (let t = 0; t < s; t += 3) {
|
|
26
|
+
const n = e[t], c = t + 1 < s, r = t + 2 < s, l = c ? e[t + 1] : 0, i = r ? e[t + 2] : 0;
|
|
27
|
+
o.push(P[n >> 2]), o.push(P[(n & 3) << 4 | l >> 4]), o.push(c ? P[(l & 15) << 2 | i >> 6] : "="), o.push(r ? P[i & 63] : "=");
|
|
27
28
|
}
|
|
28
|
-
return
|
|
29
|
+
return o.join("");
|
|
29
30
|
}
|
|
30
|
-
function
|
|
31
|
+
function $(e) {
|
|
31
32
|
return {
|
|
32
|
-
ref:
|
|
33
|
+
ref: e.ref,
|
|
33
34
|
kind: "file",
|
|
34
|
-
title:
|
|
35
|
-
short_description:
|
|
35
|
+
title: e.fileName,
|
|
36
|
+
short_description: e.fileName,
|
|
36
37
|
file: {
|
|
37
|
-
filename:
|
|
38
|
-
content_type:
|
|
39
|
-
data:
|
|
38
|
+
filename: e.fileName,
|
|
39
|
+
content_type: j(e.fileName),
|
|
40
|
+
data: R(e.data)
|
|
40
41
|
}
|
|
41
42
|
};
|
|
42
43
|
}
|
|
43
|
-
function
|
|
44
|
+
function K(e) {
|
|
44
45
|
return {
|
|
45
|
-
title:
|
|
46
|
-
docinfo:
|
|
47
|
-
document_type:
|
|
48
|
-
divisions_attributes:
|
|
49
|
-
ref:
|
|
50
|
-
source:
|
|
51
|
-
source_format:
|
|
52
|
-
is_root:
|
|
46
|
+
title: e.title,
|
|
47
|
+
docinfo: e.docinfo,
|
|
48
|
+
document_type: e.documentKind,
|
|
49
|
+
divisions_attributes: e.divisions.map((s) => ({
|
|
50
|
+
ref: s.xmlId,
|
|
51
|
+
source: s.content,
|
|
52
|
+
source_format: s.sourceFormat,
|
|
53
|
+
is_root: s.isRoot
|
|
53
54
|
})),
|
|
54
|
-
assets_attributes:
|
|
55
|
+
assets_attributes: e.assets.map($)
|
|
55
56
|
};
|
|
56
57
|
}
|
|
57
|
-
const
|
|
58
|
+
const h = {
|
|
58
59
|
mainSourcePath: "source/main.ptx",
|
|
59
60
|
publicationPath: "publication/publication.ptx",
|
|
60
61
|
projectFilePath: "project.ptx",
|
|
61
62
|
docinfoPath: "source/docinfo.ptx"
|
|
62
63
|
};
|
|
63
|
-
function
|
|
64
|
-
return
|
|
65
|
-
${
|
|
64
|
+
function S(e) {
|
|
65
|
+
return E(e, "pretext") ? e : `<pretext>
|
|
66
|
+
${e}
|
|
66
67
|
</pretext>`;
|
|
67
68
|
}
|
|
68
|
-
function
|
|
69
|
-
const
|
|
70
|
-
return
|
|
71
|
-
const
|
|
72
|
-
let
|
|
73
|
-
if (
|
|
74
|
-
const
|
|
75
|
-
|
|
69
|
+
function L(e, s, o) {
|
|
70
|
+
const t = /* @__PURE__ */ new Map(), n = [], c = `${s}-`;
|
|
71
|
+
return e.forEach((r, l) => {
|
|
72
|
+
const i = r.attributes["xml:id"];
|
|
73
|
+
let u;
|
|
74
|
+
if (i) {
|
|
75
|
+
const m = k(i);
|
|
76
|
+
u = m.startsWith(c) ? m : `${c}${m}`;
|
|
76
77
|
} else
|
|
77
|
-
|
|
78
|
+
u = `${c}${y(l + 1, e.length)}`, o.push({
|
|
78
79
|
action: "anomaly",
|
|
79
80
|
severity: "info",
|
|
80
81
|
kind: "structure",
|
|
81
82
|
category: "missing_xml_id",
|
|
82
|
-
macro:
|
|
83
|
+
macro: r.name,
|
|
83
84
|
occurrences: 1,
|
|
84
|
-
message: `<${
|
|
85
|
+
message: `<${r.name}> at position ${l + 1} has no xml:id; using \`${u}\` as filename.`
|
|
85
86
|
});
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
span:
|
|
91
|
-
slug:
|
|
92
|
-
filename: `${
|
|
87
|
+
const p = t.get(u) ?? 0;
|
|
88
|
+
t.set(u, p + 1);
|
|
89
|
+
const a = p === 0 ? u : `${u}-${p + 1}`;
|
|
90
|
+
n.push({
|
|
91
|
+
span: r,
|
|
92
|
+
slug: a,
|
|
93
|
+
filename: `${a}.ptx`
|
|
93
94
|
});
|
|
94
|
-
}),
|
|
95
|
+
}), n;
|
|
95
96
|
}
|
|
96
|
-
function
|
|
97
|
-
const
|
|
98
|
-
if (
|
|
99
|
-
return
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
return
|
|
103
|
-
start:
|
|
104
|
-
end:
|
|
105
|
-
replacement: `<xi:include href="${
|
|
97
|
+
function D(e, s, o, t) {
|
|
98
|
+
const n = T(e, "section");
|
|
99
|
+
if (n.length === 0)
|
|
100
|
+
return e;
|
|
101
|
+
const r = L(n, "sec", t).map((l) => {
|
|
102
|
+
const i = `source/${s}/${l.filename}`;
|
|
103
|
+
return o[i] = x(l.span.outer), {
|
|
104
|
+
start: l.span.start,
|
|
105
|
+
end: l.span.end,
|
|
106
|
+
replacement: `<xi:include href="${s}/${l.filename}"/>`
|
|
106
107
|
};
|
|
107
108
|
});
|
|
108
|
-
return
|
|
109
|
+
return v(e, r);
|
|
109
110
|
}
|
|
110
|
-
function
|
|
111
|
-
const
|
|
112
|
-
if (!
|
|
113
|
-
return
|
|
111
|
+
function N(e, s, o) {
|
|
112
|
+
const t = E(e, "book");
|
|
113
|
+
if (!t)
|
|
114
|
+
return o.push({
|
|
114
115
|
action: "anomaly",
|
|
115
116
|
severity: "warning",
|
|
116
117
|
kind: "structure",
|
|
@@ -118,95 +119,200 @@ function D(t, e, s) {
|
|
|
118
119
|
macro: "book",
|
|
119
120
|
occurrences: 1,
|
|
120
121
|
message: "Document was treated as a book but no <book> element found; emitting as a single file."
|
|
121
|
-
}), F(
|
|
122
|
-
const
|
|
123
|
-
let
|
|
124
|
-
if (
|
|
125
|
-
const
|
|
126
|
-
let
|
|
127
|
-
if (
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
122
|
+
}), F(e, s);
|
|
123
|
+
const n = {}, c = T(t.inner, "chapter");
|
|
124
|
+
let r = t.inner;
|
|
125
|
+
if (s.splitChapters && c.length > 0) {
|
|
126
|
+
const p = L(c, "ch", o).map((a) => {
|
|
127
|
+
let m = a.span.outer;
|
|
128
|
+
if (s.splitSections) {
|
|
129
|
+
const f = a.span.inner, d = D(
|
|
130
|
+
f,
|
|
131
|
+
a.slug,
|
|
132
|
+
n,
|
|
133
|
+
o
|
|
133
134
|
);
|
|
134
|
-
|
|
135
|
+
m = a.span.outer.slice(0, a.span.startTagEnd - a.span.start) + d + a.span.outer.slice(a.span.contentEnd - a.span.start);
|
|
135
136
|
}
|
|
136
|
-
const
|
|
137
|
-
return
|
|
138
|
-
start:
|
|
139
|
-
end:
|
|
140
|
-
replacement: `<xi:include href="${
|
|
137
|
+
const g = `source/${a.filename}`;
|
|
138
|
+
return n[g] = x(m), {
|
|
139
|
+
start: a.span.start,
|
|
140
|
+
end: a.span.end,
|
|
141
|
+
replacement: `<xi:include href="${a.filename}"/>`
|
|
141
142
|
};
|
|
142
143
|
});
|
|
143
|
-
|
|
144
|
+
r = v(t.inner, p);
|
|
144
145
|
}
|
|
145
|
-
const
|
|
146
|
-
return
|
|
147
|
-
|
|
148
|
-
), a;
|
|
149
|
-
}
|
|
150
|
-
function F(t, e, s) {
|
|
151
|
-
const n = {};
|
|
152
|
-
return n[e.mainSourcePath] = P(
|
|
153
|
-
x(t.trim())
|
|
146
|
+
const l = e.slice(t.start, t.startTagEnd) + r + e.slice(t.contentEnd, t.end), i = e.slice(0, t.start) + l + e.slice(t.end);
|
|
147
|
+
return n[s.mainSourcePath] = x(
|
|
148
|
+
C(S(i.trim()))
|
|
154
149
|
), n;
|
|
155
150
|
}
|
|
156
|
-
function
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
151
|
+
function F(e, s, o) {
|
|
152
|
+
const t = {};
|
|
153
|
+
return t[s.mainSourcePath] = x(
|
|
154
|
+
S(e.trim())
|
|
155
|
+
), t;
|
|
156
|
+
}
|
|
157
|
+
function z(e, s = {}) {
|
|
158
|
+
const o = [], t = s.documentKind ?? w(e), n = {
|
|
159
|
+
splitChapters: s.splitChapters ?? t === "book",
|
|
160
|
+
splitSections: s.splitSections ?? !1,
|
|
161
|
+
mainSourcePath: s.mainSourcePath ?? h.mainSourcePath,
|
|
162
|
+
publicationPath: s.publicationPath ?? h.publicationPath,
|
|
163
|
+
projectFilePath: s.projectFilePath ?? h.projectFilePath,
|
|
164
|
+
docinfoPath: s.docinfoPath ?? h.docinfoPath
|
|
165
|
+
}, c = t === "book" ? N(e, n, o) : F(e, n);
|
|
166
|
+
return c[n.projectFilePath] = I({
|
|
167
|
+
mainSource: n.mainSourcePath,
|
|
168
|
+
publication: n.publicationPath
|
|
169
|
+
}), c[n.publicationPath] = _(), { files: c, documentKind: t, warnings: o };
|
|
170
|
+
}
|
|
171
|
+
class O extends Error {
|
|
172
|
+
constructor() {
|
|
173
|
+
super("Import cancelled."), this.name = "ConversionCancelledError";
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
let B = 0;
|
|
177
|
+
function W(e, s, o = {}) {
|
|
178
|
+
const t = `convert-${B++}`, n = e(), { assets: c = {}, ...r } = o;
|
|
179
|
+
let l;
|
|
180
|
+
const i = new Promise((p, a) => {
|
|
181
|
+
let m = !1;
|
|
182
|
+
const g = (f) => {
|
|
183
|
+
m || (m = !0, n.terminate(), f());
|
|
184
|
+
};
|
|
185
|
+
l = () => g(() => a(new O())), n.addEventListener("message", (f) => {
|
|
186
|
+
const d = f.data;
|
|
187
|
+
if (!(!d || d.requestId !== t)) {
|
|
188
|
+
if (d.type === "result") {
|
|
189
|
+
g(() => p(d.result));
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
g(() => a(new Error(d.message)));
|
|
193
|
+
}
|
|
194
|
+
}), n.addEventListener("error", (f) => {
|
|
195
|
+
const d = typeof f == "object" && f && "message" in f ? String(f.message) : "The import worker failed to start.";
|
|
196
|
+
g(() => a(new Error(d)));
|
|
197
|
+
});
|
|
198
|
+
}), u = [
|
|
199
|
+
...new Set(
|
|
200
|
+
Object.values(c).map((p) => p.buffer).filter(
|
|
201
|
+
(p) => p instanceof ArrayBuffer
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
];
|
|
205
|
+
return n.postMessage(
|
|
206
|
+
{ type: "convert", requestId: t, files: s, assets: c, options: r },
|
|
207
|
+
u
|
|
208
|
+
), { result: i, cancel: () => l?.() };
|
|
209
|
+
}
|
|
210
|
+
function U(e) {
|
|
211
|
+
const {
|
|
212
|
+
createWorker: s,
|
|
213
|
+
id: o = "worker",
|
|
214
|
+
label: t = "Built-in converter",
|
|
215
|
+
description: n = "Create a new project starting with LaTeX, Markdown, or PreTeXt files.",
|
|
216
|
+
acceptExtensions: c
|
|
217
|
+
} = e;
|
|
218
|
+
let r = null;
|
|
219
|
+
const l = async (i, u) => {
|
|
220
|
+
r?.cancel(), r = W(s, i, u);
|
|
221
|
+
try {
|
|
222
|
+
return await r.result;
|
|
223
|
+
} finally {
|
|
224
|
+
r = null;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
return {
|
|
228
|
+
id: o,
|
|
229
|
+
label: t,
|
|
230
|
+
description: n,
|
|
231
|
+
acceptExtensions: c,
|
|
232
|
+
prepare: async (i) => {
|
|
233
|
+
const { files: u, assets: p } = await b(i);
|
|
234
|
+
return {
|
|
235
|
+
fileName: i.name,
|
|
236
|
+
files: u,
|
|
237
|
+
assets: p,
|
|
238
|
+
analysis: A(u)
|
|
239
|
+
};
|
|
240
|
+
},
|
|
241
|
+
convertPrepared: (i, u) => l(i.files, { ...u, assets: i.assets }),
|
|
242
|
+
convertFile: async (i, u) => {
|
|
243
|
+
const { files: p, assets: a } = await b(i);
|
|
244
|
+
return l(p, { ...u, assets: a });
|
|
245
|
+
},
|
|
246
|
+
cancel: () => {
|
|
247
|
+
r?.cancel(), r = null;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
169
250
|
}
|
|
170
251
|
export {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
252
|
+
q as CLEAN_RULES,
|
|
253
|
+
O as ConversionCancelledError,
|
|
254
|
+
V as LATEX_DIVISION_COMMANDS,
|
|
255
|
+
Y as LATEX_FORMAT_MARKERS,
|
|
256
|
+
J as MARKDOWN_FORMAT_MARKERS,
|
|
257
|
+
Q as MAX_SUGGESTED_SPLIT_LEVEL,
|
|
258
|
+
Z as PRETEXT_DIVISION_TAGS,
|
|
259
|
+
ee as PRETEXT_ROOT_TAGS,
|
|
260
|
+
A as analyzeImportSources,
|
|
261
|
+
te as applyLatexFixes,
|
|
262
|
+
Ke as assetsForImportMode,
|
|
263
|
+
se as attachLatexRoots,
|
|
264
|
+
ne as attachMarkdownRoots,
|
|
265
|
+
ae as buildDivisionPool,
|
|
266
|
+
oe as buildNativeDivisionPool,
|
|
267
|
+
z as buildPretextProjectFiles,
|
|
268
|
+
re as carryOverProjectFiles,
|
|
269
|
+
ie as cleanLatex,
|
|
270
|
+
ce as cleanLatexInChunks,
|
|
271
|
+
le as cleanLatexText,
|
|
272
|
+
ue as convertLatexToPretext,
|
|
273
|
+
pe as convertMarkdownToPretext,
|
|
274
|
+
fe as convertSourceToPretext,
|
|
275
|
+
U as createWorkerEngine,
|
|
276
|
+
me as defaultAttachLevel,
|
|
277
|
+
de as defaultManifestTarget,
|
|
278
|
+
w as detectDocumentKind,
|
|
279
|
+
ge as detectSourceFormat,
|
|
280
|
+
ze as diffHunks,
|
|
281
|
+
Ue as diffLines,
|
|
282
|
+
Ge as diffStats,
|
|
283
|
+
Pe as divisionChildRefs,
|
|
284
|
+
he as divisionsAtLevel,
|
|
285
|
+
xe as expandPretextIncludes,
|
|
286
|
+
b as extractUpload,
|
|
287
|
+
He as fileChangesForImport,
|
|
288
|
+
be as filePrefixForDivision,
|
|
289
|
+
qe as filesForImportMode,
|
|
290
|
+
Ee as findLatexFixes,
|
|
291
|
+
Te as findLatexHeaders,
|
|
292
|
+
ve as findProjectManifest,
|
|
293
|
+
Se as fixesToWarnings,
|
|
294
|
+
Ve as formatWarningLine,
|
|
295
|
+
Le as getConversionErrorMessage,
|
|
296
|
+
Fe as getLatexCleanDiagnostics,
|
|
297
|
+
we as handleImportUploadFile,
|
|
298
|
+
Ie as importProjectFromFiles,
|
|
299
|
+
_e as isDivisionTag,
|
|
300
|
+
Ce as latexDivisionHierarchy,
|
|
301
|
+
ke as latexFixesToCodeActions,
|
|
302
|
+
ye as mergeChunksAtLevel,
|
|
303
|
+
Ae as normalizePretextSource,
|
|
304
|
+
Me as parseLatexDivisions,
|
|
305
|
+
je as parseProjectManifest,
|
|
306
|
+
Ye as projectForImportMode,
|
|
307
|
+
Re as relayoutImport,
|
|
308
|
+
I as renderProjectPtx,
|
|
309
|
+
$e as renderProjectPtxFromManifest,
|
|
310
|
+
_ as renderPublicationPtx,
|
|
311
|
+
De as resolveImportSplitLevel,
|
|
312
|
+
Ne as resolveSplitLevel,
|
|
313
|
+
W as runConversionInWorker,
|
|
314
|
+
Oe as sanitizeRef,
|
|
315
|
+
Be as serializeProjectToFiles,
|
|
316
|
+
K as serializeProjectToPlusPayload,
|
|
317
|
+
We as suggestSplitLevel
|
|
212
318
|
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { LatexFix } from '@pretextbook/latex-style-pretext';
|
|
2
|
+
import { CleaningWarning } from './warnings';
|
|
3
|
+
export interface CleanedChunk {
|
|
4
|
+
/**
|
|
5
|
+
* Heading path from the document root — `["Limits", "One-sided limits"]`.
|
|
6
|
+
* Empty for the preamble and for body text ahead of the first heading.
|
|
7
|
+
*/
|
|
8
|
+
path: string[];
|
|
9
|
+
/** The chunk's own heading, or `""` when it has none. */
|
|
10
|
+
title: string;
|
|
11
|
+
/** `"preamble"`, a LaTeX sectioning command, or `null` for the lead-in text. */
|
|
12
|
+
kind: "preamble" | "lead" | "division";
|
|
13
|
+
/** Sectioning command that opened this chunk, when `kind` is `"division"`. */
|
|
14
|
+
command?: string;
|
|
15
|
+
/** Depth in the document's own hierarchy; 0 for preamble and lead-in. */
|
|
16
|
+
level: number;
|
|
17
|
+
before: string;
|
|
18
|
+
after: string;
|
|
19
|
+
fixes: LatexFix[];
|
|
20
|
+
}
|
|
21
|
+
export interface CleanLatexChunksResult {
|
|
22
|
+
/** The cleaned document, chunks rejoined in source order. */
|
|
23
|
+
output: string;
|
|
24
|
+
chunks: CleanedChunk[];
|
|
25
|
+
/** Aggregate over every chunk — the document-level summary. */
|
|
26
|
+
warnings: CleaningWarning[];
|
|
27
|
+
fixes: LatexFix[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Clean `source`, cutting it at every division header so each piece carries its
|
|
31
|
+
* own before/after text and fix list.
|
|
32
|
+
*
|
|
33
|
+
* Chunks are cut at the *deepest* level the document has, not at a requested
|
|
34
|
+
* split depth. A shallower view is a matter of concatenating consecutive chunks
|
|
35
|
+
* (`mergeChunksAtLevel`), which lets the wizard change split depth without
|
|
36
|
+
* re-cleaning or re-converting anything.
|
|
37
|
+
*/
|
|
38
|
+
export declare function cleanLatexInChunks(source: string): CleanLatexChunksResult;
|
|
39
|
+
/**
|
|
40
|
+
* Collapse chunks to the view a given split depth produces: one entry per file
|
|
41
|
+
* that depth would generate, with the chunks below it concatenated in.
|
|
42
|
+
*
|
|
43
|
+
* `level` 0 gives a single entry for the whole body; 1 one per top-level
|
|
44
|
+
* division; and so on. The preamble is always its own entry, since it never
|
|
45
|
+
* becomes a file of its own.
|
|
46
|
+
*/
|
|
47
|
+
export declare function mergeChunksAtLevel(chunks: CleanedChunk[], level: number): CleanedChunk[];
|
|
@@ -1,6 +1,40 @@
|
|
|
1
|
+
import { CleanScope, LatexFix } from '@pretextbook/latex-style-pretext';
|
|
1
2
|
import { CleaningWarning } from './warnings';
|
|
3
|
+
export interface CleanLatexOptions {
|
|
4
|
+
/**
|
|
5
|
+
* What the text is. Defaults to `"auto"`, which detects `\begin{document}`.
|
|
6
|
+
* Per-division cleaning (SPEC §3.8) passes `"body"`.
|
|
7
|
+
*/
|
|
8
|
+
scope?: CleanScope;
|
|
9
|
+
/** Rule ids to skip. */
|
|
10
|
+
disable?: string[];
|
|
11
|
+
}
|
|
2
12
|
export interface CleanLatexResult {
|
|
3
13
|
output: string;
|
|
14
|
+
/** Aggregate, one row per rule — what the wizard's summary list renders. */
|
|
4
15
|
warnings: CleaningWarning[];
|
|
16
|
+
/**
|
|
17
|
+
* Positioned fixes, in application order. The before/after diff and any
|
|
18
|
+
* per-file report read these; `warnings` is the rolled-up view of the same
|
|
19
|
+
* data.
|
|
20
|
+
*/
|
|
21
|
+
fixes: LatexFix[];
|
|
5
22
|
}
|
|
6
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Clean a piece of LaTeX: strip comments and trailing junk, then apply every
|
|
25
|
+
* cleaning rule to a fixpoint.
|
|
26
|
+
*
|
|
27
|
+
* `trimJunk` runs first and stays on this side of the boundary deliberately.
|
|
28
|
+
* Deleting every comment is right for an import (they are authoring notes about
|
|
29
|
+
* LaTeX, not content) but wrong for an editor, where the author is looking at
|
|
30
|
+
* their own comments and would not expect a cleanup to eat them.
|
|
31
|
+
*/
|
|
32
|
+
export declare function cleanLatex(source: string, options?: CleanLatexOptions): CleanLatexResult;
|
|
33
|
+
/**
|
|
34
|
+
* Roll positioned fixes up into one `CleaningWarning` per rule.
|
|
35
|
+
*
|
|
36
|
+
* A rule with `reportMatch` emits two rows, matching what the cleaner has always
|
|
37
|
+
* produced: a `save` carrying the matched text (so the author can reconstruct
|
|
38
|
+
* what a `\def` meant) and a `delete` recording that it went away.
|
|
39
|
+
*/
|
|
40
|
+
export declare function fixesToWarnings(fixes: LatexFix[]): CleaningWarning[];
|
package/dist/lib/convert.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CleanedChunk } from './clean/clean-chunks';
|
|
1
2
|
import { CleaningWarning } from './clean/warnings';
|
|
2
3
|
import { ConvertedPretextResult, SourceFormat } from './types';
|
|
3
4
|
export declare function normalizePretextSource(pretextSource: string): string;
|
|
@@ -5,6 +6,12 @@ export interface LatexConversionResult {
|
|
|
5
6
|
pretext: string;
|
|
6
7
|
cleanedLatex: string;
|
|
7
8
|
warnings: CleaningWarning[];
|
|
9
|
+
/**
|
|
10
|
+
* The cleaned source cut at its division headers, each piece carrying its own
|
|
11
|
+
* before/after text. The wizard's per-file diff reads these; see
|
|
12
|
+
* `clean-chunks.ts` for why cleaning is partitioned rather than global.
|
|
13
|
+
*/
|
|
14
|
+
cleanChunks: CleanedChunk[];
|
|
8
15
|
}
|
|
9
16
|
export declare function convertLatexToPretext(latexSource: string): LatexConversionResult;
|
|
10
17
|
export interface MarkdownConversionResult {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type DiffOp = "keep" | "add" | "remove";
|
|
2
|
+
export interface DiffLine {
|
|
3
|
+
op: DiffOp;
|
|
4
|
+
text: string;
|
|
5
|
+
/** 1-based line number in the "before" text; absent for added lines. */
|
|
6
|
+
beforeLine?: number;
|
|
7
|
+
/** 1-based line number in the "after" text; absent for removed lines. */
|
|
8
|
+
afterLine?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface DiffHunk {
|
|
11
|
+
/** Lines in this hunk, including the surrounding context. */
|
|
12
|
+
lines: DiffLine[];
|
|
13
|
+
}
|
|
14
|
+
export interface DiffStats {
|
|
15
|
+
added: number;
|
|
16
|
+
removed: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Longest common subsequence of two line arrays, as a diff.
|
|
20
|
+
*
|
|
21
|
+
* The classic O(n·m) dynamic program. A division is at most a few thousand
|
|
22
|
+
* lines, so the table is small enough not to matter; anything larger is guarded
|
|
23
|
+
* by `MAX_DIFF_LINES` below, which falls back to a whole-file replacement
|
|
24
|
+
* rather than allocating a table nobody will read.
|
|
25
|
+
*/
|
|
26
|
+
export declare function diffLines(before: string, after: string): DiffLine[];
|
|
27
|
+
/** Above this combined line count, the LCS table is not worth building. */
|
|
28
|
+
export declare const MAX_DIFF_LINES = 20000;
|
|
29
|
+
export declare function diffStats(lines: DiffLine[]): DiffStats;
|
|
30
|
+
/**
|
|
31
|
+
* Group a diff into hunks of changed lines with `context` unchanged lines
|
|
32
|
+
* around each, dropping the long runs of untouched text between them. A
|
|
33
|
+
* cleaning pass usually touches a handful of scattered lines, so showing the
|
|
34
|
+
* whole file would bury them.
|
|
35
|
+
*/
|
|
36
|
+
export declare function diffHunks(lines: DiffLine[], context?: number): DiffHunk[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DiffHunk, DiffStats } from './diff';
|
|
2
|
+
import { ImportedProjectSuccess } from './types';
|
|
3
|
+
export interface FileChangeRecord {
|
|
4
|
+
path: string;
|
|
5
|
+
/** Division title this file holds, or `""` for the main file. */
|
|
6
|
+
title: string;
|
|
7
|
+
before: string;
|
|
8
|
+
after: string;
|
|
9
|
+
stats: DiffStats;
|
|
10
|
+
hunks: DiffHunk[];
|
|
11
|
+
/** Number of cleaning fixes applied within this file's source. */
|
|
12
|
+
fixCount: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A before/after record for each generated source file at `splitLevel`.
|
|
16
|
+
*
|
|
17
|
+
* Files with no matching chunk are omitted rather than shown with an empty
|
|
18
|
+
* diff: a title that did not survive conversion means the join is unreliable
|
|
19
|
+
* for that file, and an empty diff would read as "nothing changed here" when
|
|
20
|
+
* the truth is "we do not know".
|
|
21
|
+
*/
|
|
22
|
+
export declare function fileChangesForImport(result: ImportedProjectSuccess, splitLevel?: number): FileChangeRecord[];
|