@pretextbook/import 0.6.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/index.js CHANGED
@@ -1,5 +1,6 @@
1
- import { d as _, r as v, a as A, f as g, b as h, w as P, s as x, e as I, c as C, p as j } from "./import-mode-C0KIll3S.js";
2
- import { C as B, L as X, g as U, M as W, h as G, P as H, i as V, j as Y, k as q, l as J, m as Q, n as Z, o as ee, q as te, t as ae, u as se, v as ne, x as ie, y as oe, z as re, A as ce, B as le, D as pe, E as ue, F as fe, G as me, H as de, I as Pe, J as ge, K as he, N as xe, O as be, Q as Se, R as Te, S as Ee, T as Fe, U as Le, V as _e, W as ve, X as Ae, Y as Ie, Z as Ce, _ as je, $ as Me, a0 as Re, a1 as ke, a2 as $e, a3 as De, a4 as ye, a5 as we, a6 as Ne, a7 as Oe, a8 as Ke, a9 as ze, aa as Be, ab as Xe, ac as Ue, ad as We } from "./import-mode-C0KIll3S.js";
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";
3
4
  const M = {
4
5
  png: "image/png",
5
6
  jpg: "image/jpeg",
@@ -14,18 +15,18 @@ const M = {
14
15
  webp: "image/webp",
15
16
  ico: "image/vnd.microsoft.icon"
16
17
  };
17
- function R(e) {
18
- const t = e.split(".").pop()?.toLowerCase() ?? "";
19
- return M[t] ?? "application/octet-stream";
18
+ function j(e) {
19
+ const s = e.split(".").pop()?.toLowerCase() ?? "";
20
+ return M[s] ?? "application/octet-stream";
20
21
  }
21
- const m = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
22
- function k(e) {
23
- const t = e.length, n = [];
24
- for (let a = 0; a < t; a += 3) {
25
- const s = e[a], o = a + 1 < t, c = a + 2 < t, r = o ? e[a + 1] : 0, l = c ? e[a + 2] : 0;
26
- n.push(m[s >> 2]), n.push(m[(s & 3) << 4 | r >> 4]), n.push(o ? m[(r & 15) << 2 | l >> 6] : "="), n.push(c ? m[l & 63] : "=");
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 n.join("");
29
+ return o.join("");
29
30
  }
30
31
  function $(e) {
31
32
  return {
@@ -35,82 +36,82 @@ function $(e) {
35
36
  short_description: e.fileName,
36
37
  file: {
37
38
  filename: e.fileName,
38
- content_type: R(e.fileName),
39
- data: k(e.data)
39
+ content_type: j(e.fileName),
40
+ data: R(e.data)
40
41
  }
41
42
  };
42
43
  }
43
- function N(e) {
44
+ function K(e) {
44
45
  return {
45
46
  title: e.title,
46
47
  docinfo: e.docinfo,
47
48
  document_type: e.documentKind,
48
- divisions_attributes: e.divisions.map((t) => ({
49
- ref: t.xmlId,
50
- source: t.content,
51
- source_format: t.sourceFormat,
52
- is_root: t.isRoot
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
55
  assets_attributes: e.assets.map($)
55
56
  };
56
57
  }
57
- const d = {
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 b(e) {
64
- return g(e, "pretext") ? e : `<pretext>
64
+ function S(e) {
65
+ return E(e, "pretext") ? e : `<pretext>
65
66
  ${e}
66
67
  </pretext>`;
67
68
  }
68
- function S(e, t, n) {
69
- const a = /* @__PURE__ */ new Map(), s = [], o = `${t}-`;
70
- return e.forEach((c, r) => {
71
- const l = c.attributes["xml:id"];
72
- let p;
73
- if (l) {
74
- const u = C(l);
75
- p = u.startsWith(o) ? u : `${o}${u}`;
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
- p = `${o}${j(r + 1, e.length)}`, n.push({
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: c.name,
83
+ macro: r.name,
83
84
  occurrences: 1,
84
- message: `<${c.name}> at position ${r + 1} has no xml:id; using \`${p}\` as filename.`
85
+ message: `<${r.name}> at position ${l + 1} has no xml:id; using \`${u}\` as filename.`
85
86
  });
86
- const f = a.get(p) ?? 0;
87
- a.set(p, f + 1);
88
- const i = f === 0 ? p : `${p}-${f + 1}`;
89
- s.push({
90
- span: c,
91
- slug: i,
92
- filename: `${i}.ptx`
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
- }), s;
95
+ }), n;
95
96
  }
96
- function D(e, t, n, a) {
97
- const s = h(e, "section");
98
- if (s.length === 0)
97
+ function D(e, s, o, t) {
98
+ const n = T(e, "section");
99
+ if (n.length === 0)
99
100
  return e;
100
- const c = S(s, "sec", a).map((r) => {
101
- const l = `source/${t}/${r.filename}`;
102
- return n[l] = P(r.span.outer), {
103
- start: r.span.start,
104
- end: r.span.end,
105
- replacement: `<xi:include href="${t}/${r.filename}"/>`
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 x(e, c);
109
+ return v(e, r);
109
110
  }
110
- function y(e, t, n) {
111
- const a = g(e, "book");
112
- if (!a)
113
- return n.push({
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,117 +119,200 @@ function y(e, t, n) {
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
- }), T(e, t);
122
- const s = {}, o = h(a.inner, "chapter");
123
- let c = a.inner;
124
- if (t.splitChapters && o.length > 0) {
125
- const f = S(o, "ch", n).map((i) => {
126
- let u = i.span.outer;
127
- if (t.splitSections) {
128
- const F = i.span.inner, L = D(
129
- F,
130
- i.slug,
131
- s,
132
- n
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
- u = i.span.outer.slice(0, i.span.startTagEnd - i.span.start) + L + i.span.outer.slice(i.span.contentEnd - i.span.start);
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 E = `source/${i.filename}`;
137
- return s[E] = P(u), {
138
- start: i.span.start,
139
- end: i.span.end,
140
- replacement: `<xi:include href="${i.filename}"/>`
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
- c = x(a.inner, f);
144
+ r = v(t.inner, p);
144
145
  }
145
- const r = e.slice(a.start, a.startTagEnd) + c + e.slice(a.contentEnd, a.end), l = e.slice(0, a.start) + r + e.slice(a.end);
146
- return s[t.mainSourcePath] = P(
147
- I(b(l.trim()))
148
- ), s;
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()))
149
+ ), n;
150
+ }
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 };
149
170
  }
150
- function T(e, t, n) {
151
- const a = {};
152
- return a[t.mainSourcePath] = P(
153
- b(e.trim())
154
- ), a;
171
+ class O extends Error {
172
+ constructor() {
173
+ super("Import cancelled."), this.name = "ConversionCancelledError";
174
+ }
155
175
  }
156
- function O(e, t = {}) {
157
- const n = [], a = t.documentKind ?? _(e), s = {
158
- splitChapters: t.splitChapters ?? a === "book",
159
- splitSections: t.splitSections ?? !1,
160
- mainSourcePath: t.mainSourcePath ?? d.mainSourcePath,
161
- publicationPath: t.publicationPath ?? d.publicationPath,
162
- projectFilePath: t.projectFilePath ?? d.projectFilePath,
163
- docinfoPath: t.docinfoPath ?? d.docinfoPath
164
- }, o = a === "book" ? y(e, s, n) : T(e, s);
165
- return o[s.projectFilePath] = v({
166
- mainSource: s.mainSourcePath,
167
- publication: s.publicationPath
168
- }), o[s.publicationPath] = A(), { files: o, documentKind: a, warnings: n };
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
- B as CLEAN_RULES,
172
- X as LATEX_DIVISION_COMMANDS,
173
- U as LATEX_FORMAT_MARKERS,
174
- W as MARKDOWN_FORMAT_MARKERS,
175
- G as MAX_SUGGESTED_SPLIT_LEVEL,
176
- H as PRETEXT_DIVISION_TAGS,
177
- V as PRETEXT_ROOT_TAGS,
178
- Y as analyzeImportSources,
179
- q as applyLatexFixes,
180
- J as assetsForImportMode,
181
- Q as attachLatexRoots,
182
- Z as attachMarkdownRoots,
183
- ee as buildDivisionPool,
184
- te as buildNativeDivisionPool,
185
- O as buildPretextProjectFiles,
186
- ae as carryOverProjectFiles,
187
- se as cleanLatex,
188
- ne as cleanLatexInChunks,
189
- ie as cleanLatexText,
190
- oe as convertLatexToPretext,
191
- re as convertMarkdownToPretext,
192
- ce as convertSourceToPretext,
193
- le as defaultAttachLevel,
194
- pe as defaultManifestTarget,
195
- _ as detectDocumentKind,
196
- ue as detectSourceFormat,
197
- fe as diffHunks,
198
- me as diffLines,
199
- de as diffStats,
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,
200
283
  Pe as divisionChildRefs,
201
- ge as divisionsAtLevel,
202
- he as expandPretextIncludes,
203
- xe as extractUpload,
204
- be as fileChangesForImport,
205
- Se as filePrefixForDivision,
206
- Te as filesForImportMode,
284
+ he as divisionsAtLevel,
285
+ xe as expandPretextIncludes,
286
+ b as extractUpload,
287
+ He as fileChangesForImport,
288
+ be as filePrefixForDivision,
289
+ qe as filesForImportMode,
207
290
  Ee as findLatexFixes,
208
- Fe as findLatexHeaders,
209
- Le as findProjectManifest,
210
- _e as fixesToWarnings,
211
- ve as formatWarningLine,
212
- Ae as getConversionErrorMessage,
213
- Ie as getLatexCleanDiagnostics,
214
- Ce as handleImportUploadFile,
215
- je as importProjectFromFiles,
216
- Me as isDivisionTag,
217
- Re as latexDivisionHierarchy,
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,
218
301
  ke as latexFixesToCodeActions,
219
- $e as mergeChunksAtLevel,
220
- De as normalizePretextSource,
221
- ye as parseLatexDivisions,
222
- we as parseProjectManifest,
223
- Ne as projectForImportMode,
224
- Oe as relayoutImport,
225
- v as renderProjectPtx,
226
- Ke as renderProjectPtxFromManifest,
227
- A as renderPublicationPtx,
228
- ze as resolveImportSplitLevel,
229
- Be as resolveSplitLevel,
230
- Xe as sanitizeRef,
231
- Ue as serializeProjectToFiles,
232
- N as serializeProjectToPlusPayload,
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,
233
317
  We as suggestSplitLevel
234
318
  };
@@ -39,12 +39,30 @@ export interface ImportEngine {
39
39
  convertFile: (file: File, options: ImportProjectOptions) => Promise<ImportedProjectResult>;
40
40
  /** Unpack and survey an upload without converting it. */
41
41
  prepare?: (file: File) => Promise<PreparedUpload>;
42
- /** Convert an already-prepared upload with the user's source choices. */
43
- convertPrepared?: (prepared: PreparedUpload, options: ImportProjectOptions) => ImportedProjectResult;
42
+ /**
43
+ * Convert an already-prepared upload with the user's source choices.
44
+ *
45
+ * May return synchronously (the built-in engine does) or a promise (the
46
+ * worker engine does). The wizard always awaits, which is what lets the
47
+ * processing screen paint and its timer tick before the work starts.
48
+ */
49
+ convertPrepared?: (prepared: PreparedUpload, options: ImportProjectOptions) => ImportedProjectResult | Promise<ImportedProjectResult>;
50
+ /**
51
+ * Stop an in-flight conversion. Engines that run the pipeline in-process
52
+ * cannot honour this — the pipeline has no yield points — so only the worker
53
+ * engine supplies it, and the processing screen shows Cancel only when it is
54
+ * present.
55
+ */
56
+ cancel?: () => void;
44
57
  }
45
58
  export interface ImportWizardProps {
46
- /** Called when the user confirms the import. */
47
- onConfirm: (result: ImportedProjectSuccess, mode: ImportMode) => void;
59
+ /**
60
+ * Called when the user confirms the import. May return a promise — writing
61
+ * the file map out is the host's slow step (VS Code writes to disk,
62
+ * pretext-plus uploads), so the wizard awaits it and holds the button in a
63
+ * pending state until it settles rather than appearing to do nothing.
64
+ */
65
+ onConfirm: (result: ImportedProjectSuccess, mode: ImportMode) => void | Promise<void>;
48
66
  /** Called when the user cancels at the review step. */
49
67
  onCancel?: () => void;
50
68
  /** Pass fixed options to skip the document-kind / split-sections controls. */
@@ -1,5 +1,7 @@
1
1
  export { ImportWizard } from './import-wizard';
2
2
  export type { ImportWizardProps, ImportMode, ImportEngine, PreparedUpload, } from './import-wizard';
3
+ export { ProcessingPanel } from './processing-panel';
4
+ export type { ProcessingPanelProps } from './processing-panel';
3
5
  export { ImportSourceForm } from './import-source-form';
4
6
  export { ImportUploadPanel } from './import-upload-panel';
5
7
  export type { ImportSourceFormProps, ImportSourceFormLabels, } from './import-source-form';
@@ -0,0 +1,6 @@
1
+ export interface ProcessingPanelProps {
2
+ message?: string;
3
+ /** Omitted when the work cannot be interrupted (e.g. a host write). */
4
+ onCancel?: () => void;
5
+ }
6
+ export declare function ProcessingPanel({ message, onCancel, }: ProcessingPanelProps): import("react").JSX.Element;