@pretextbook/import 0.2.0 → 0.4.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 +79 -8
- package/dist/import-mode-DlOXwZkx.cjs +115 -0
- package/dist/import-mode-G2KcSH17.js +4774 -0
- package/dist/import.css +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.ts +10 -5
- package/dist/index.js +130 -87
- package/dist/lib/clean/latex-includes.d.ts +19 -0
- package/dist/lib/clean/pretext-includes.d.ts +8 -0
- package/dist/lib/import-mode.d.ts +9 -1
- package/dist/lib/layout/shared.d.ts +5 -1
- package/dist/lib/layout/xml-scan.d.ts +1 -0
- package/dist/lib/pool/division-pool.d.ts +18 -9
- package/dist/lib/pool/index.d.ts +2 -1
- package/dist/lib/pool/native-pool.d.ts +20 -0
- package/dist/lib/pool/refs.d.ts +39 -0
- package/dist/lib/pool/serialize-plus.d.ts +1 -6
- package/dist/lib/pretext-divisions.d.ts +9 -0
- package/dist/lib/project/analyze.d.ts +46 -0
- package/dist/lib/project/attach-roots.d.ts +46 -0
- package/dist/lib/project/existing-project.d.ts +40 -0
- package/dist/lib/project/manifest.d.ts +50 -0
- package/dist/lib/project/paths.d.ts +19 -0
- package/dist/lib/types.d.ts +70 -20
- package/dist/lib/upload.d.ts +40 -1
- package/dist/react/import-wizard.d.ts +21 -0
- package/dist/react/index.d.ts +1 -1
- package/dist/react.cjs +2 -2
- package/dist/react.js +577 -343
- package/package.json +66 -66
- package/dist/import-mode-BDY8WcYJ.js +0 -3873
- package/dist/import-mode-CSZlmUxw.cjs +0 -66
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Root elements of a PreTeXt document. */
|
|
2
|
+
export declare const PRETEXT_ROOT_TAGS: readonly ["book", "article"];
|
|
3
|
+
/** Divisions that may be split into their own file, in rough outline order. */
|
|
4
|
+
export declare const PRETEXT_DIVISION_TAGS: readonly ["frontmatter", "preface", "acknowledgement", "dedication", "biography", "contributors", "part", "chapter", "section", "subsection", "subsubsection", "exercises", "worksheet", "reading-questions", "references", "solutions", "glossary", "backmatter", "appendix", "index", "colophon"];
|
|
5
|
+
export type PretextRootTag = (typeof PRETEXT_ROOT_TAGS)[number];
|
|
6
|
+
export type PretextDivisionTag = (typeof PRETEXT_DIVISION_TAGS)[number];
|
|
7
|
+
export declare function isDivisionTag(name: string): name is PretextDivisionTag;
|
|
8
|
+
export declare function filePrefixForDivision(type: string): string;
|
|
9
|
+
export declare function isSingletonDivision(type: string): boolean;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { SourceFormat } from '../types';
|
|
2
|
+
import { ProjectManifest } from './manifest';
|
|
3
|
+
/** Why a file is offered as a possible document root. */
|
|
4
|
+
export type RootReason = "manifest-target" | "latex-root" | "pretext-root" | "markdown-root" | "fallback";
|
|
5
|
+
export interface RootCandidate {
|
|
6
|
+
/** Path within the uploaded file set. */
|
|
7
|
+
path: string;
|
|
8
|
+
format: SourceFormat;
|
|
9
|
+
reason: RootReason;
|
|
10
|
+
/** Title mined from the file, when it declares one. */
|
|
11
|
+
title?: string;
|
|
12
|
+
/** `project.ptx` target this candidate came from. */
|
|
13
|
+
targetName?: string;
|
|
14
|
+
/** That target's output format (`html`, `pdf`, …). */
|
|
15
|
+
targetFormat?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface UploadAnalysis {
|
|
18
|
+
/** The `project.ptx` governing the upload, when it has one. */
|
|
19
|
+
manifest: ProjectManifest | null;
|
|
20
|
+
/** Every file that could serve as a root, best first. */
|
|
21
|
+
candidates: RootCandidate[];
|
|
22
|
+
/** Formats represented among the candidates, in the order they are preferred. */
|
|
23
|
+
formats: SourceFormat[];
|
|
24
|
+
/** The candidate the import will use unless overridden. */
|
|
25
|
+
primary: RootCandidate | null;
|
|
26
|
+
/**
|
|
27
|
+
* Other roots of the *same* format as `primary` — a multi-root upload
|
|
28
|
+
* (several `\documentclass` files, several stray Markdown files). These are
|
|
29
|
+
* the files the caller can offer to attach as chapters or sections.
|
|
30
|
+
*/
|
|
31
|
+
extraRoots: RootCandidate[];
|
|
32
|
+
}
|
|
33
|
+
export interface AnalyzeOptions {
|
|
34
|
+
/** Restrict candidates to one format (the host's format dropdown). */
|
|
35
|
+
sourceFormat?: SourceFormat;
|
|
36
|
+
/** Force a specific file as the root, whatever the heuristics prefer. */
|
|
37
|
+
mainFile?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Survey an uploaded file set for possible document roots.
|
|
41
|
+
*
|
|
42
|
+
* Preference order, highest first: a `project.ptx` target (an existing PreTeXt
|
|
43
|
+
* project always knows its own root), then LaTeX, Markdown, and finally loose
|
|
44
|
+
* PreTeXt files — matching the pre-manifest behaviour of the pipeline.
|
|
45
|
+
*/
|
|
46
|
+
export declare function analyzeImportSources(files: Record<string, string>, options?: AnalyzeOptions): UploadAnalysis;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CleaningWarning } from '../clean/warnings';
|
|
2
|
+
/** Division level an extra root is attached at. */
|
|
3
|
+
export type AttachLevel = "chapter" | "section";
|
|
4
|
+
/** A caller's instruction for one extra root. */
|
|
5
|
+
export interface RootAttachment {
|
|
6
|
+
/** Path of the extra root within the uploaded file set. */
|
|
7
|
+
path: string;
|
|
8
|
+
/** Level to attach at; defaults to the main document's own top level. */
|
|
9
|
+
level?: AttachLevel;
|
|
10
|
+
/** Heading text; defaults to the file's `\title`, else its filename. */
|
|
11
|
+
title?: string;
|
|
12
|
+
/** Set false to leave this root out of the import entirely. */
|
|
13
|
+
include?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface AttachedRootRecord {
|
|
16
|
+
path: string;
|
|
17
|
+
title: string;
|
|
18
|
+
level: AttachLevel;
|
|
19
|
+
}
|
|
20
|
+
export interface AttachRootsResult {
|
|
21
|
+
/** The combined source, ready for the normal conversion pipeline. */
|
|
22
|
+
source: string;
|
|
23
|
+
attached: AttachedRootRecord[];
|
|
24
|
+
warnings: CleaningWarning[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The level extra roots attach at when the caller does not say: a chapter when
|
|
28
|
+
* the main document is book-like, a section otherwise.
|
|
29
|
+
*/
|
|
30
|
+
export declare function defaultAttachLevel(mainSource: string): AttachLevel;
|
|
31
|
+
/**
|
|
32
|
+
* Splice the extra LaTeX roots into the main document.
|
|
33
|
+
*
|
|
34
|
+
* Each attached file contributes its body (what lies between
|
|
35
|
+
* `\begin{document}` and `\end{document}`, or the whole file when it declares
|
|
36
|
+
* neither) plus any macro definitions from its preamble, which are hoisted
|
|
37
|
+
* into the main preamble so the attached content's own commands still resolve.
|
|
38
|
+
*/
|
|
39
|
+
export declare function attachLatexRoots(mainSource: string, attachments: RootAttachment[], files: Record<string, string>): AttachRootsResult;
|
|
40
|
+
/**
|
|
41
|
+
* Markdown counterpart. Extra roots are appended under a depth-1 heading,
|
|
42
|
+
* which `remark-pretext` maps to the document's top-level division — so this
|
|
43
|
+
* currently only supports top-level attachment, not the chapter/section choice
|
|
44
|
+
* the LaTeX path offers.
|
|
45
|
+
*/
|
|
46
|
+
export declare function attachMarkdownRoots(mainSource: string, attachments: RootAttachment[], files: Record<string, string>): AttachRootsResult;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ManifestTarget, ProjectManifest } from './manifest';
|
|
2
|
+
export interface CarryOverOptions {
|
|
3
|
+
manifest: ProjectManifest;
|
|
4
|
+
/** The target the import followed. */
|
|
5
|
+
target: ManifestTarget;
|
|
6
|
+
/** All uploaded text files, keyed by archive path. */
|
|
7
|
+
files: Record<string, string>;
|
|
8
|
+
/** All uploaded binaries, keyed by archive path. */
|
|
9
|
+
assets: Record<string, Uint8Array>;
|
|
10
|
+
/** Archive paths whose content was folded into the imported document. */
|
|
11
|
+
consumedPaths: Iterable<string>;
|
|
12
|
+
}
|
|
13
|
+
export interface CarryOverResult {
|
|
14
|
+
/** Text files to write, keyed by project-relative path. */
|
|
15
|
+
files: Record<string, string>;
|
|
16
|
+
/** Binaries to write, keyed by project-relative path. */
|
|
17
|
+
assets: Record<string, Uint8Array>;
|
|
18
|
+
/** Project-relative paths that were deliberately not carried over. */
|
|
19
|
+
skipped: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Split an existing project's uploaded files into "copy through" and
|
|
23
|
+
* "deliberately dropped". Paths on the result are relative to the project root
|
|
24
|
+
* (the directory holding `project.ptx`), so an archive that nests everything
|
|
25
|
+
* under `my-book-main/` imports as a project, not as a folder containing one.
|
|
26
|
+
*/
|
|
27
|
+
export declare function carryOverProjectFiles(options: CarryOverOptions): CarryOverResult;
|
|
28
|
+
/**
|
|
29
|
+
* Regenerate `project.ptx` for an imported project, preserving the original
|
|
30
|
+
* targets (their names, formats, and output directories) while pointing the
|
|
31
|
+
* imported target at the layout we actually wrote.
|
|
32
|
+
*
|
|
33
|
+
* Targets are emitted in the v2 child-element form, whose paths are relative
|
|
34
|
+
* to the project root — the same form `renderProjectPtx` uses for brand-new
|
|
35
|
+
* projects, so every project this package produces reads the same way.
|
|
36
|
+
*/
|
|
37
|
+
export declare function renderProjectPtxFromManifest(manifest: ProjectManifest, importedTarget: ManifestTarget, layout: {
|
|
38
|
+
mainSource: string;
|
|
39
|
+
publication?: string;
|
|
40
|
+
}): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface ManifestTarget {
|
|
2
|
+
name: string;
|
|
3
|
+
/** `html`, `pdf`, `latex`, … — `""` when the manifest declares none. */
|
|
4
|
+
format: string;
|
|
5
|
+
/** Project-root-relative path to the target's main source file. */
|
|
6
|
+
source: string;
|
|
7
|
+
/** Project-root-relative path to the target's publication file, if any. */
|
|
8
|
+
publication?: string;
|
|
9
|
+
/** Project-root-relative output directory, if declared. */
|
|
10
|
+
outputDir?: string;
|
|
11
|
+
/** A `standalone` attribute that is present and not `"no"`. */
|
|
12
|
+
standalone: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface ProjectManifest {
|
|
15
|
+
/** Path of the `project.ptx` file within the uploaded file set. */
|
|
16
|
+
manifestPath: string;
|
|
17
|
+
/** Directory the manifest lives in — the project root ("" at top level). */
|
|
18
|
+
projectRoot: string;
|
|
19
|
+
/** The `ptx-version` attribute, when present. */
|
|
20
|
+
ptxVersion?: string;
|
|
21
|
+
/** Project-level source directory (default `source`). */
|
|
22
|
+
sourceDir: string;
|
|
23
|
+
/** Project-level publication directory (default `publication`). */
|
|
24
|
+
publicationDir: string;
|
|
25
|
+
targets: ManifestTarget[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse a `project.ptx` manifest. `manifestPath` is the file's path within the
|
|
29
|
+
* uploaded file set; every path on the result is relative to the manifest's
|
|
30
|
+
* own directory (the project root), so callers can join it back onto the
|
|
31
|
+
* upload's paths.
|
|
32
|
+
*
|
|
33
|
+
* Returns `null` when the text has no `<project>` root — a `project.ptx` that
|
|
34
|
+
* is really something else should not hijack the import.
|
|
35
|
+
*/
|
|
36
|
+
export declare function parseProjectManifest(contents: string, manifestPath: string): ProjectManifest | null;
|
|
37
|
+
/**
|
|
38
|
+
* Find the `project.ptx` governing an uploaded file set: the shallowest one
|
|
39
|
+
* that really has a `<project>` root. Archives commonly nest everything under
|
|
40
|
+
* a single directory (`my-book-main/`), so depth — not alphabetical order —
|
|
41
|
+
* decides.
|
|
42
|
+
*/
|
|
43
|
+
export declare function findProjectManifest(files: Record<string, string>): ProjectManifest | null;
|
|
44
|
+
/**
|
|
45
|
+
* The target an import should follow by default. The CLI builds the first
|
|
46
|
+
* declared target when none is named, so that is the default here too —
|
|
47
|
+
* except that `standalone` targets (single-division previews) are skipped
|
|
48
|
+
* while a non-standalone one exists.
|
|
49
|
+
*/
|
|
50
|
+
export declare function defaultManifestTarget(manifest: ProjectManifest): ManifestTarget | undefined;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Normalize separators, drop a leading `./`, and collapse `.`/`..` segments. */
|
|
2
|
+
export declare function normalizePath(value: string): string;
|
|
3
|
+
/** The directory part of a path (`""` for a bare filename). */
|
|
4
|
+
export declare function dirname(pathName: string): string;
|
|
5
|
+
/** The final segment of a path. */
|
|
6
|
+
export declare function basename(pathName: string): string;
|
|
7
|
+
/** Lowercased extension without the dot (`""` when there is none). */
|
|
8
|
+
export declare function extension(pathName: string): string;
|
|
9
|
+
/** A basename with its extension removed. */
|
|
10
|
+
export declare function stem(pathName: string): string;
|
|
11
|
+
/** Join path segments and normalize the result; empty segments are ignored. */
|
|
12
|
+
export declare function joinPath(...parts: Array<string | undefined | null>): string;
|
|
13
|
+
/**
|
|
14
|
+
* Re-express `pathName` relative to `base`, when it lives inside it. Used to
|
|
15
|
+
* turn archive paths (`my-book-main/source/main.ptx`) into project-relative
|
|
16
|
+
* ones (`source/main.ptx`). Returns `pathName` unchanged when it is outside
|
|
17
|
+
* `base`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function relativeToDirectory(base: string, pathName: string): string;
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { CleaningWarning } from './clean/warnings';
|
|
2
2
|
import { DocumentKind } from './layout/document-kind';
|
|
3
|
+
import { PretextDivisionTag, PretextRootTag } from './pretext-divisions';
|
|
4
|
+
import { UploadAnalysis } from './project/analyze';
|
|
5
|
+
import { AttachedRootRecord } from './project/attach-roots';
|
|
3
6
|
export type SourceFormat = "latex" | "markdown" | "pretext";
|
|
4
7
|
export interface ConversionContext {
|
|
5
8
|
sourceFormat: SourceFormat;
|
|
@@ -23,10 +26,10 @@ export interface UploadStatusMessage {
|
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
25
28
|
* The PreTeXt element type of an imported division. Values match the XML tag
|
|
26
|
-
* name
|
|
27
|
-
*
|
|
29
|
+
* name: either a document root (`book`/`article`) or any division the splitter
|
|
30
|
+
* can lift into its own file (see `pretext-divisions.ts`).
|
|
28
31
|
*/
|
|
29
|
-
export type ImportedDivisionType =
|
|
32
|
+
export type ImportedDivisionType = PretextRootTag | PretextDivisionTag;
|
|
30
33
|
/**
|
|
31
34
|
* One division record in the intermediate model (SPEC §4.1): a flat pool of
|
|
32
35
|
* divisions whose hierarchy is expressed by `<plus:TYPE ref="…"/>`
|
|
@@ -70,35 +73,63 @@ export interface ImportedProject {
|
|
|
70
73
|
divisions: ImportedDivision[];
|
|
71
74
|
assets: ImportedAsset[];
|
|
72
75
|
}
|
|
73
|
-
/**
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
/**
|
|
77
|
+
* One division row of the pretext-plus import payload (`divisions_attributes`
|
|
78
|
+
* on `POST /projects/import`). New rows only — `ProjectsController#import_params`
|
|
79
|
+
* permits no `id`/`_destroy` there (imports never edit or delete existing rows).
|
|
80
|
+
*/
|
|
81
|
+
export interface PlusDivisionAttributes {
|
|
77
82
|
/** The division's `xml:id` (Rails column `ref`). */
|
|
78
83
|
ref: string;
|
|
79
84
|
source: string;
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
source_format: SourceFormat;
|
|
86
|
+
is_root: boolean;
|
|
82
87
|
}
|
|
83
|
-
/**
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
/**
|
|
89
|
+
* An asset's file upload. Bytes travel base64-encoded, since the whole import
|
|
90
|
+
* posts as one JSON body — `import_params` decodes `data` back into an
|
|
91
|
+
* ActiveStorage attachable server-side.
|
|
92
|
+
*/
|
|
93
|
+
export interface PlusAssetFile {
|
|
94
|
+
filename: string;
|
|
95
|
+
content_type: string;
|
|
96
|
+
data: string;
|
|
97
|
+
}
|
|
98
|
+
/** One asset row of the pretext-plus import payload (`assets_attributes`). */
|
|
99
|
+
export interface PlusAssetAttributes {
|
|
86
100
|
ref: string;
|
|
87
101
|
kind: "file";
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
title: string;
|
|
103
|
+
short_description: string;
|
|
104
|
+
file: PlusAssetFile;
|
|
91
105
|
}
|
|
92
106
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
107
|
+
* Wire shape of `POST /projects/import`
|
|
108
|
+
* (`ProjectsController#create_from_import` / `import_params`) — a direct
|
|
109
|
+
* snake_case mirror, since the endpoint permits no `id` on either nested
|
|
110
|
+
* attribute.
|
|
95
111
|
*/
|
|
96
112
|
export interface PlusProjectPayload {
|
|
97
113
|
title: string;
|
|
98
114
|
docinfo: string;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
115
|
+
document_type: DocumentKind;
|
|
116
|
+
divisions_attributes: PlusDivisionAttributes[];
|
|
117
|
+
assets_attributes: PlusAssetAttributes[];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Where the imported project's own scaffolding files live. For an upload that
|
|
121
|
+
* carried a `project.ptx`, these are the paths that project already used, so
|
|
122
|
+
* its publication file and image references keep resolving.
|
|
123
|
+
*/
|
|
124
|
+
export interface ProjectLayout {
|
|
125
|
+
/** Path of the root source file within the written project. */
|
|
126
|
+
mainSourcePath: string;
|
|
127
|
+
/** Path of the publication file within the written project. */
|
|
128
|
+
publicationPath: string;
|
|
129
|
+
/** Path of the manifest within the written project. */
|
|
130
|
+
projectFilePath: string;
|
|
131
|
+
/** True when an existing project's layout and publication file were kept. */
|
|
132
|
+
preserved: boolean;
|
|
102
133
|
}
|
|
103
134
|
export interface ImportedProjectSuccess extends ConversionContext {
|
|
104
135
|
pretextSource: string;
|
|
@@ -106,8 +137,27 @@ export interface ImportedProjectSuccess extends ConversionContext {
|
|
|
106
137
|
sourceName: string;
|
|
107
138
|
sourceType: UploadSourceType;
|
|
108
139
|
documentKind: DocumentKind;
|
|
140
|
+
/**
|
|
141
|
+
* The survey of the upload that drove this import — the manifest it found,
|
|
142
|
+
* every root it could have used, and the formats on offer. Hosts render
|
|
143
|
+
* their format/main-file pickers from this and re-run the import with the
|
|
144
|
+
* user's choices as `ImportProjectOptions`.
|
|
145
|
+
*/
|
|
146
|
+
analysis: UploadAnalysis;
|
|
147
|
+
/** Extra roots folded into the main document (SPEC §3.3). */
|
|
148
|
+
attachedRoots: AttachedRootRecord[];
|
|
149
|
+
/** Scaffolding paths used for the written project. */
|
|
150
|
+
projectLayout: ProjectLayout;
|
|
109
151
|
/** Intermediate model of the imported project (SPEC §4.1). */
|
|
110
152
|
project: ImportedProject;
|
|
153
|
+
/**
|
|
154
|
+
* Native-format (LaTeX/Markdown) projection of the same import, split into
|
|
155
|
+
* divisions joined by `\plus{…}{…}` / `::…{ref="…"}` placeholders (SPEC
|
|
156
|
+
* §4.3). Present only when the source was LaTeX or Markdown; the pretext-plus
|
|
157
|
+
* host serializes this instead of `project` when the user keeps the native
|
|
158
|
+
* format. `undefined` for PreTeXt input.
|
|
159
|
+
*/
|
|
160
|
+
nativeProject?: ImportedProject;
|
|
111
161
|
files: Record<string, string>;
|
|
112
162
|
assets: Record<string, Uint8Array>;
|
|
113
163
|
outputFiles: Record<string, string>;
|
package/dist/lib/upload.d.ts
CHANGED
|
@@ -1,10 +1,49 @@
|
|
|
1
1
|
import { BuildProjectFilesOptions } from './layout';
|
|
2
|
-
import {
|
|
2
|
+
import { RootAttachment } from './project/attach-roots';
|
|
3
|
+
import { ImportedProjectResult, SourceFormat } from './types';
|
|
3
4
|
export interface ImportProjectOptions extends BuildProjectFilesOptions {
|
|
4
5
|
/** When true (default), the layout splitter runs and outputFiles is populated. */
|
|
5
6
|
buildLayout?: boolean;
|
|
6
7
|
/** Raw binary assets keyed by their source path (e.g. images, PDFs). */
|
|
7
8
|
assets?: Record<string, Uint8Array>;
|
|
9
|
+
/**
|
|
10
|
+
* Force the source format, overriding detection — the format dropdown a host
|
|
11
|
+
* shows when an upload contains more than one kind of source.
|
|
12
|
+
*/
|
|
13
|
+
sourceFormat?: SourceFormat;
|
|
14
|
+
/** Force which uploaded file is the document root (a path in `files`). */
|
|
15
|
+
mainFile?: string;
|
|
16
|
+
/**
|
|
17
|
+
* How many levels of division to split into separate files/records.
|
|
18
|
+
* Overrides `splitChapters`/`splitSections`; see `resolveSplitLevel`.
|
|
19
|
+
*/
|
|
20
|
+
splitLevel?: number;
|
|
21
|
+
/**
|
|
22
|
+
* What to do with roots other than the main one (SPEC §3.3). Defaults to
|
|
23
|
+
* attaching every detected extra root as a division of the main document;
|
|
24
|
+
* pass `false` to import the main file alone, or a list to choose the level,
|
|
25
|
+
* heading, and order per file.
|
|
26
|
+
*/
|
|
27
|
+
attachRoots?: RootAttachment[] | false;
|
|
28
|
+
/**
|
|
29
|
+
* For an upload with a `project.ptx`: keep the project's own publication
|
|
30
|
+
* file, assets, and directory layout (default). Set false to import it as
|
|
31
|
+
* loose source into this package's standard layout instead.
|
|
32
|
+
*/
|
|
33
|
+
preserveProjectLayout?: boolean;
|
|
8
34
|
}
|
|
35
|
+
export interface ExtractedUpload {
|
|
36
|
+
files: Record<string, string>;
|
|
37
|
+
assets: Record<string, Uint8Array>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Unpack an upload into text files and binaries, without converting anything.
|
|
41
|
+
*
|
|
42
|
+
* Exported so a host can run the two-phase flow the pickers need: extract
|
|
43
|
+
* once, `analyzeImportSources` to populate a format dropdown and main-file
|
|
44
|
+
* list, then `importProjectFromFiles` with the user's answers — instead of
|
|
45
|
+
* re-reading and re-unzipping the file for every choice the user changes.
|
|
46
|
+
*/
|
|
47
|
+
export declare function extractUpload(file: File): Promise<ExtractedUpload>;
|
|
9
48
|
export declare function importProjectFromFiles(files: Record<string, string>, options?: ImportProjectOptions): ImportedProjectResult;
|
|
10
49
|
export declare function handleImportUploadFile(file: File, options?: ImportProjectOptions): Promise<ImportedProjectResult>;
|
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
import { ImportProjectOptions } from '../lib/upload';
|
|
2
2
|
import { ImportMode } from '../lib/import-mode';
|
|
3
3
|
import { DocumentKind } from '../lib/layout/document-kind';
|
|
4
|
+
import { UploadAnalysis } from '../lib/project/analyze';
|
|
4
5
|
import { ImportedProjectResult, ImportedProjectSuccess } from '../lib/types';
|
|
5
6
|
export type { ImportMode };
|
|
7
|
+
/**
|
|
8
|
+
* An upload that has been unpacked and surveyed but not yet converted. Holding
|
|
9
|
+
* this lets the wizard offer source choices (format, main file, extra roots)
|
|
10
|
+
* and re-run the conversion as the user changes them, without unzipping the
|
|
11
|
+
* upload again each time.
|
|
12
|
+
*/
|
|
13
|
+
export interface PreparedUpload {
|
|
14
|
+
fileName: string;
|
|
15
|
+
files: Record<string, string>;
|
|
16
|
+
assets: Record<string, Uint8Array>;
|
|
17
|
+
analysis: UploadAnalysis;
|
|
18
|
+
}
|
|
6
19
|
/**
|
|
7
20
|
* A pluggable conversion engine. The wizard owns the whole UI (upload, review,
|
|
8
21
|
* preview, confirm) and only delegates the source → result step to the selected
|
|
9
22
|
* engine, so hosts can inject their own converters (e.g. a VS Code-only pandoc
|
|
10
23
|
* engine that round-trips to the extension host) without touching this package.
|
|
24
|
+
*
|
|
25
|
+
* An engine that implements the optional `prepare`/`convertPrepared` pair also
|
|
26
|
+
* gets the source-selection step; one that only implements `convertFile` keeps
|
|
27
|
+
* the original single-shot flow.
|
|
11
28
|
*/
|
|
12
29
|
export interface ImportEngine {
|
|
13
30
|
/** Stable identifier, used as the radio value. */
|
|
@@ -20,6 +37,10 @@ export interface ImportEngine {
|
|
|
20
37
|
acceptExtensions?: string[];
|
|
21
38
|
/** Convert an uploaded file into an import result. */
|
|
22
39
|
convertFile: (file: File, options: ImportProjectOptions) => Promise<ImportedProjectResult>;
|
|
40
|
+
/** Unpack and survey an upload without converting it. */
|
|
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;
|
|
23
44
|
}
|
|
24
45
|
export interface ImportWizardProps {
|
|
25
46
|
/** Called when the user confirms the import. */
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ImportWizard } from './import-wizard';
|
|
2
|
-
export type { ImportWizardProps, ImportMode, ImportEngine, } from './import-wizard';
|
|
2
|
+
export type { ImportWizardProps, ImportMode, ImportEngine, PreparedUpload, } from './import-wizard';
|
|
3
3
|
export { ImportSourceForm } from './import-source-form';
|
|
4
4
|
export { ImportUploadPanel } from './import-upload-panel';
|
|
5
5
|
export type { ImportSourceFormProps, ImportSourceFormLabels, } from './import-source-form';
|
package/dist/react.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("react"),_=require("./import-mode-DlOXwZkx.cjs");var re={exports:{}},q={};var se;function ce(){if(se)return q;se=1;var o=Symbol.for("react.transitional.element"),h=Symbol.for("react.fragment");function v(T,b,c){var j=null;if(c!==void 0&&(j=""+c),b.key!==void 0&&(j=""+b.key),"key"in b){c={};for(var g in b)g!=="key"&&(c[g]=b[g])}else c=b;return b=c.ref,{$$typeof:o,type:T,key:j,ref:b!==void 0?b:null,props:c}}return q.Fragment=h,q.jsx=v,q.jsxs=v,q}var J={};var ae;function ie(){return ae||(ae=1,process.env.NODE_ENV!=="production"&&(function(){function o(t){if(t==null)return null;if(typeof t=="function")return t.$$typeof===Z?null:t.displayName||t.name||null;if(typeof t=="string")return t;switch(t){case I:return"Fragment";case L:return"Profiler";case N:return"StrictMode";case Y:return"Suspense";case V:return"SuspenseList";case H:return"Activity"}if(typeof t=="object")switch(typeof t.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),t.$$typeof){case R:return"Portal";case y:return t.displayName||"Context";case x:return(t._context.displayName||"Context")+".Consumer";case $:var n=t.render;return t=t.displayName,t||(t=n.displayName||n.name||"",t=t!==""?"ForwardRef("+t+")":"ForwardRef"),t;case G:return n=t.displayName||null,n!==null?n:o(t.type)||"Memo";case C:n=t._payload,t=t._init;try{return o(t(n))}catch{}}return null}function h(t){return""+t}function v(t){try{h(t);var n=!1}catch{n=!0}if(n){n=console;var u=n.error,f=typeof Symbol=="function"&&Symbol.toStringTag&&t[Symbol.toStringTag]||t.constructor.name||"Object";return u.call(n,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",f),h(t)}}function T(t){if(t===I)return"<>";if(typeof t=="object"&&t!==null&&t.$$typeof===C)return"<...>";try{var n=o(t);return n?"<"+n+">":"<...>"}catch{return"<...>"}}function b(){var t=D.A;return t===null?null:t.getOwner()}function c(){return Error("react-stack-top-frame")}function j(t){if(X.call(t,"key")){var n=Object.getOwnPropertyDescriptor(t,"key").get;if(n&&n.isReactWarning)return!1}return t.key!==void 0}function g(t,n){function u(){B||(B=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",n))}u.isReactWarning=!0,Object.defineProperty(t,"key",{get:u,configurable:!0})}function p(){var t=o(this.type);return z[t]||(z[t]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),t=this.props.ref,t!==void 0?t:null}function A(t,n,u,f,r,s){var a=u.ref;return t={$$typeof:k,type:t,key:n,props:u,_owner:f},(a!==void 0?a:null)!==null?Object.defineProperty(t,"ref",{enumerable:!1,get:p}):Object.defineProperty(t,"ref",{enumerable:!1,value:null}),t._store={},Object.defineProperty(t._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(t,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(t,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:r}),Object.defineProperty(t,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:s}),Object.freeze&&(Object.freeze(t.props),Object.freeze(t)),t}function S(t,n,u,f,r,s){var a=n.children;if(a!==void 0)if(f)if(M(a)){for(f=0;f<a.length;f++)w(a[f]);Object.freeze&&Object.freeze(a)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else w(a);if(X.call(n,"key")){a=o(t);var m=Object.keys(n).filter(function(O){return O!=="key"});f=0<m.length?"{key: someKey, "+m.join(": ..., ")+": ...}":"{key: someKey}",K[a+f]||(m=0<m.length?"{"+m.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
2
2
|
let props = %s;
|
|
3
3
|
<%s {...props} />
|
|
4
4
|
React keys must be passed directly to JSX without using spread:
|
|
5
5
|
let props = %s;
|
|
6
|
-
<%s key={someKey} {...props} />`,u,m,L,m),K[m+u]=!0)}if(m=null,o!==void 0&&(g(o),m=""+o),d(r)&&(g(r.key),m=""+r.key),"key"in r){o={};for(var H in r)H!=="key"&&(o[H]=r[H])}else o=r;return m&&f(o,typeof t=="function"?t.displayName||t.name||"Unknown":t),P(t,m,o,i(),J,G)}function k(t){R(t)?t._store&&(t._store.validated=1):typeof t=="object"&&t!==null&&t.$$typeof===F&&(t._payload.status==="fulfilled"?R(t._payload.value)&&t._payload.value._store&&(t._payload.value._store.validated=1):t._store&&(t._store.validated=1))}function R(t){return typeof t=="object"&&t!==null&&t.$$typeof===E}var S=c,E=Symbol.for("react.transitional.element"),_=Symbol.for("react.portal"),w=Symbol.for("react.fragment"),p=Symbol.for("react.strict_mode"),C=Symbol.for("react.profiler"),l=Symbol.for("react.consumer"),j=Symbol.for("react.context"),O=Symbol.for("react.forward_ref"),$=Symbol.for("react.suspense"),X=Symbol.for("react.suspense_list"),Y=Symbol.for("react.memo"),F=Symbol.for("react.lazy"),B=Symbol.for("react.activity"),W=Symbol.for("react.client.reference"),D=S.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,q=Object.prototype.hasOwnProperty,s=Array.isArray,n=console.createTask?console.createTask:function(){return null};S={react_stack_bottom_frame:function(t){return t()}};var x,y={},A=S.react_stack_bottom_frame.bind(S,a)(),I=n(N(a)),K={};U.Fragment=w,U.jsx=function(t,r,o){var u=1e4>D.recentlyCreatedOwnerStacks++;return v(t,r,o,!1,u?Error("react-stack-top-frame"):A,u?n(N(t)):I)},U.jsxs=function(t,r,o){var u=1e4>D.recentlyCreatedOwnerStacks++;return v(t,r,o,!0,u?Error("react-stack-top-frame"):A,u?n(N(t)):I)}})()),U}var ee;function ae(){return ee||(ee=1,process.env.NODE_ENV==="production"?V.exports=se():V.exports=ne()),V.exports}var e=ae();const te=[".tex",".md",".markdown",".ptx",".xml",".zip",".gz",".tar.gz",".tgz"],oe={id:"builtin",label:"Built-in converter",description:"Create a new project starting with LaTeX, Markdown, or PreTeXt files.",acceptExtensions:te,convertFile:M.handleImportUploadFile};function le({onConfirm:b,onCancel:T,importOptions:g,defaultDocumentKind:N="auto",engines:i}){const a=i&&i.length>0?i:[oe],d=c.useRef(null),[f,h]=c.useState({name:"upload"}),[P,v]=c.useState(!1),[k,R]=c.useState(N),[S,E]=c.useState(!1),[_,w]=c.useState(a[0].id),[p,C]=c.useState("converted"),[l,j]=c.useState(!1),[O,$]=c.useState(new Set),X=a.find(s=>s.id===_)??a[0],Y=X.acceptExtensions??te,F=async s=>{h({name:"processing"});try{const n=g??{documentKind:k==="auto"?void 0:k,splitSections:S},x=await X.convertFile(s,n);"pretextError"in x?h({name:"error",message:x.pretextError}):h({name:"review",result:x})}catch(n){h({name:"error",message:n instanceof Error?n.message:"An unexpected error occurred."})}},B=()=>{h({name:"upload"}),C("converted"),j(!1),$(new Set)};function W(s,n){return[...s].sort((x,y)=>x===n?-1:y===n?1:x.localeCompare(y))}function D(s,n){const x=M.filesForImportMode(s,n),y=n==="converted"?"source/main.ptx":s.sourcePath,A=W(Object.keys(x),y)[0];$(A?new Set([A]):new Set)}function q(s){$(n=>{const x=new Set(n);return x.has(s)?x.delete(s):x.add(s),x})}if(f.name==="processing")return e.jsxs("div",{className:"flex flex-col items-center justify-center gap-3 py-16 text-slate-600",children:[e.jsx("div",{className:"h-8 w-8 animate-spin rounded-full border-2 border-blue-700 border-t-transparent"}),e.jsx("p",{className:"text-sm",children:"Processing your file…"})]});if(f.name==="error")return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-800",children:[e.jsx("p",{className:"font-semibold",children:"Import failed"}),e.jsx("p",{className:"mt-1",children:f.message})]}),e.jsx("div",{className:"flex justify-end",children:e.jsx("button",{type:"button",onClick:B,className:"rounded bg-blue-700 px-4 py-2 text-sm font-medium text-white hover:bg-blue-600",children:"Try Another File"})})]});if(f.name==="review"){let s=function(r){C(r),l&&D(n,r)};const{result:n}=f,x=n.detectedSourceFormat==="latex",y=n.warnings.length,A=Object.keys(n.outputFiles).length,I=M.filesForImportMode(n,p),K=p==="converted"?"source/main.ptx":n.sourcePath,t=W(Object.keys(I),K);return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"rounded-lg border border-slate-200 bg-slate-50 p-4",children:[e.jsx("h3",{className:"mb-3 text-sm font-semibold text-slate-700",children:"Import Summary"}),e.jsxs("dl",{className:"grid grid-cols-2 gap-x-6 gap-y-2 text-sm",children:[e.jsx("dt",{className:"text-slate-500",children:"Source"}),e.jsx("dd",{className:"font-medium text-slate-900",children:n.sourceName}),e.jsx("dt",{className:"text-slate-500",children:"Detected format"}),e.jsx("dd",{className:"font-medium text-slate-900 capitalize",children:n.detectedSourceFormat}),e.jsx("dt",{className:"text-slate-500",children:"Document kind"}),e.jsx("dd",{className:"font-medium text-slate-900 capitalize",children:n.documentKind}),e.jsx("dt",{className:"text-slate-500",children:"Output files"}),e.jsx("dd",{className:"font-medium text-slate-900",children:A})]})]}),y>0?e.jsxs("details",{className:"rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm",children:[e.jsxs("summary",{className:"cursor-pointer font-semibold text-amber-800",children:[y," conversion"," ",y===1?"warning":"warnings"]}),e.jsx("ul",{className:"mt-3 space-y-1.5 text-amber-700",children:n.warnings.map((r,o)=>e.jsxs("li",{children:[e.jsx("code",{className:"rounded bg-amber-100 px-1 py-0.5 text-xs",children:r.macro})," — ",r.action==="replace"||r.action==="rewrite"?`replaced with \`${r.replacement}\``:r.message??r.action,r.occurrences>1?` (×${r.occurrences})`:null]},o))})]}):e.jsx("p",{className:"text-sm text-green-700",children:"No conversion warnings."}),x?e.jsxs("fieldset",{className:"rounded-lg border border-slate-200 p-4",children:[e.jsx("legend",{className:"px-1 text-sm font-semibold text-slate-700",children:"Import mode"}),e.jsxs("div",{className:"mt-2 flex flex-col gap-3",children:[e.jsxs("label",{className:"flex cursor-pointer items-start gap-3 text-sm",children:[e.jsx("input",{type:"radio",name:"import-mode",value:"converted",checked:p==="converted",onChange:()=>s("converted"),className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium text-slate-900",children:"Convert to PreTeXt"}),e.jsx("span",{className:"block text-slate-500",children:"Use the converted PreTeXt output. Recommended for new PreTeXt projects."})]})]}),e.jsxs("label",{className:"flex cursor-pointer items-start gap-3 text-sm",children:[e.jsx("input",{type:"radio",name:"import-mode",value:"native",checked:p==="native",onChange:()=>s("native"),className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium text-slate-900",children:"Keep as LaTeX"}),e.jsx("span",{className:"block text-slate-500",children:"Preserve the original LaTeX source. The conversion will not be applied."})]})]})]})]}):null,l?e.jsx("div",{className:"overflow-hidden rounded-lg border border-slate-200 text-sm",children:t.map(r=>{const o=O.has(r);return e.jsxs("div",{className:"border-b border-slate-200 last:border-b-0",children:[e.jsxs("button",{type:"button",onClick:()=>q(r),className:"flex w-full items-center gap-2 bg-slate-100 px-4 py-2 text-left font-mono text-xs text-slate-700 hover:bg-slate-200",children:[e.jsx("span",{className:"shrink-0 text-slate-400",children:o?"▾":"▸"}),e.jsx("span",{className:"flex-1 truncate",children:r}),e.jsxs("span",{className:"shrink-0 text-slate-400",children:[(I[r].length/1024).toFixed(1)," KB"]})]}),o?e.jsx("pre",{className:"m-0 max-h-72 overflow-auto bg-white p-4 font-mono text-xs leading-relaxed text-slate-800",children:I[r]}):null]},r)})}):null,e.jsxs("div",{className:"flex items-center justify-between gap-3 pt-1",children:[e.jsx("button",{type:"button",onClick:T??B,className:"px-4 py-2 text-sm text-slate-600 hover:text-slate-900",children:T?"Cancel":"Start Over"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{type:"button",onClick:()=>{l||D(n,p),j(r=>!r)},className:"rounded border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50",children:l?"Hide Preview":"Preview"}),e.jsx("button",{type:"button",onClick:()=>b(n,p),className:"rounded bg-blue-700 px-4 py-2 text-sm font-medium text-white hover:bg-blue-600",children:"Confirm Import"})]})]})]})}return e.jsxs("div",{className:"flex flex-col gap-4",children:[a.length>1?e.jsxs("fieldset",{className:"rounded-lg border border-slate-200 p-4",children:[e.jsx("legend",{className:"px-1 text-sm font-semibold text-slate-700",children:"Converter"}),e.jsx("div",{className:"mt-2 flex flex-col gap-3",children:a.map(s=>e.jsxs("label",{className:"flex cursor-pointer items-start gap-3 text-sm",children:[e.jsx("input",{type:"radio",name:"import-engine",value:s.id,checked:_===s.id,onChange:()=>w(s.id),className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium text-slate-900",children:s.label}),s.description?e.jsx("span",{className:"block text-slate-500",children:s.description}):null]})]},s.id))})]}):null,g?null:e.jsxs("div",{className:"flex flex-wrap gap-4 text-sm",children:[e.jsxs("label",{className:"flex items-center gap-2 text-slate-700",children:[e.jsx("span",{className:"text-slate-500",children:"Document kind"}),e.jsxs("select",{value:k,onChange:s=>R(s.currentTarget.value),className:"rounded border border-slate-300 px-2 py-1 text-sm",children:[e.jsx("option",{value:"auto",children:"Auto detect"}),e.jsx("option",{value:"article",children:"Article"}),e.jsx("option",{value:"book",children:"Book"})]})]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm text-slate-700",children:[e.jsx("input",{type:"checkbox",checked:S,onChange:s=>E(s.currentTarget.checked)}),"Split sections into separate files"]})]}),e.jsxs("div",{role:"button",tabIndex:0,onKeyDown:s=>s.key==="Enter"&&d.current?.click(),onClick:()=>d.current?.click(),onDragOver:s=>{s.preventDefault(),v(!0)},onDragLeave:()=>v(!1),onDrop:s=>{s.preventDefault(),v(!1);const n=s.dataTransfer.files?.[0];n&&F(n)},className:`flex cursor-pointer flex-col items-center gap-3 rounded-lg border-2 border-dashed p-10 text-center transition-colors ${P?"border-blue-500 bg-blue-50":"border-slate-300 bg-slate-50 hover:border-slate-400"}`,children:[e.jsx("p",{className:"text-slate-600",children:"Drop a file here, or click to select."}),e.jsx("button",{type:"button",onClick:s=>{s.stopPropagation(),d.current?.click()},className:"rounded bg-blue-700 px-4 py-2 text-sm font-medium text-white hover:bg-blue-600",children:"Select File"}),e.jsxs("p",{className:"text-xs text-slate-400",children:["Supports ",Y.join(", ")]}),e.jsx("input",{ref:d,type:"file",hidden:!0,accept:Y.join(","),onChange:s=>{const n=s.currentTarget.files?.[0];n&&F(n),s.currentTarget.value=""}})]})]})}const ce={title:"Import Source Content",description:"Paste LaTeX, Markdown, or PreTeXt source to convert into PreTeXt.",sourceLabel:"Source",sourcePlaceholder:"Paste source content here...",formatLabel:"Source format",convertButton:"Convert to PreTeXt",detectedFormatPrefix:"Detected",successPrefix:"Ready",errorPrefix:"Error"};function ie({initialSource:b="",initialSourceFormat:T,labels:g,disabled:N=!1,onImport:i}){const a=c.useMemo(()=>({...ce,...g??{}}),[g]),[d,f]=c.useState(b),[h,P]=c.useState(T??"auto"),[v,k]=c.useState(null),R=c.useMemo(()=>M.detectSourceFormat(d),[d]),S=N||!d.trim();return e.jsx("form",{onSubmit:E=>{E.preventDefault();const _=M.convertSourceToPretext(d,h==="auto"?void 0:h);k(_),i(_)},"aria-label":"Import source form",children:e.jsxs("fieldset",{disabled:N,children:[e.jsx("legend",{children:a.title}),e.jsx("p",{children:a.description}),e.jsxs("label",{children:[a.sourceLabel,e.jsx("textarea",{value:d,onChange:E=>f(E.currentTarget.value),placeholder:a.sourcePlaceholder,rows:12})]}),e.jsxs("label",{children:[a.formatLabel,e.jsxs("select",{value:h,onChange:E=>P(E.currentTarget.value),children:[e.jsx("option",{value:"auto",children:"Auto detect"}),e.jsx("option",{value:"latex",children:"LaTeX"}),e.jsx("option",{value:"markdown",children:"Markdown"}),e.jsx("option",{value:"pretext",children:"PreTeXt"})]})]}),e.jsxs("p",{children:[a.detectedFormatPrefix,": ",e.jsx("strong",{children:R})]}),e.jsx("button",{type:"submit",disabled:S,children:a.convertButton}),v?"pretextError"in v?e.jsxs("p",{role:"alert",children:[a.errorPrefix,": ",v.pretextError]}):e.jsxs("p",{children:[a.successPrefix,": ",v.pretextSource.length," characters of PreTeXt generated."]}):null]})})}const de={title:"Upload Source File",hint:"Supports .tex, .md, .ptx, .xml, .zip, and .tar.gz files.",selectButton:"Select File",dropHint:"Drop a file here, or click Select File.",documentKindLabel:"Document kind",splitSectionsLabel:"Split each chapter into sections"};function ue({labels:b,disabled:T=!1,defaultDocumentKind:g="auto",importOptions:N,onImport:i}){const a=c.useMemo(()=>({...de,...b??{}}),[b]),d=c.useRef(null),[f,h]=c.useState(!1),[P,v]=c.useState(!1),[k,R]=c.useState([]),[S,E]=c.useState(g),[_,w]=c.useState(!1),p=T||P,C=async l=>{v(!0);try{const j=N??{documentKind:S==="auto"?void 0:S,splitSections:_},O=await M.handleImportUploadFile(l,j);R(O.statusMessages),i(O)}finally{v(!1)}};return e.jsxs("section",{"aria-label":"Import upload panel",children:[e.jsx("h3",{children:a.title}),e.jsx("p",{children:a.hint}),N?null:e.jsxs("div",{className:"import-options",children:[e.jsxs("label",{children:[a.documentKindLabel,e.jsxs("select",{value:S,disabled:p,onChange:l=>E(l.currentTarget.value),children:[e.jsx("option",{value:"auto",children:"Auto detect"}),e.jsx("option",{value:"article",children:"Article"}),e.jsx("option",{value:"book",children:"Book"})]})]}),e.jsxs("label",{children:[e.jsx("input",{type:"checkbox",checked:_,disabled:p,onChange:l=>w(l.currentTarget.checked)}),a.splitSectionsLabel]})]}),e.jsxs("div",{onDragOver:l=>{l.preventDefault(),p||h(!0)},onDragLeave:()=>h(!1),onDrop:l=>{if(l.preventDefault(),h(!1),p)return;const j=l.dataTransfer.files?.[0];j&&C(j)},children:[e.jsx("p",{children:a.dropHint}),e.jsx("button",{type:"button",disabled:p,onClick:()=>d.current?.click(),children:P?"Processing...":a.selectButton}),e.jsx("input",{ref:d,type:"file",hidden:!0,disabled:p,accept:".tex,.md,.markdown,.ptx,.xml,.zip,.gz,.tar.gz,.tgz",onChange:l=>{const j=l.currentTarget.files?.[0];j&&C(j),l.currentTarget.value=""}})]}),k.length>0?e.jsx("ul",{"aria-live":"polite",children:k.map((l,j)=>e.jsx("li",{children:l.message},`${l.type}-${j}`))}):null,f&&!p?e.jsx("p",{children:"Release to upload the file."}):null]})}exports.ImportSourceForm=ie;exports.ImportUploadPanel=ue;exports.ImportWizard=le;
|
|
6
|
+
<%s key={someKey} {...props} />`,f,a,m,a),K[a+f]=!0)}if(a=null,u!==void 0&&(v(u),a=""+u),j(n)&&(v(n.key),a=""+n.key),"key"in n){u={};for(var l in n)l!=="key"&&(u[l]=n[l])}else u=n;return a&&g(u,typeof t=="function"?t.displayName||t.name||"Unknown":t),A(t,a,u,b(),r,s)}function w(t){F(t)?t._store&&(t._store.validated=1):typeof t=="object"&&t!==null&&t.$$typeof===C&&(t._payload.status==="fulfilled"?F(t._payload.value)&&t._payload.value._store&&(t._payload.value._store.validated=1):t._store&&(t._store.validated=1))}function F(t){return typeof t=="object"&&t!==null&&t.$$typeof===k}var E=d,k=Symbol.for("react.transitional.element"),R=Symbol.for("react.portal"),I=Symbol.for("react.fragment"),N=Symbol.for("react.strict_mode"),L=Symbol.for("react.profiler"),x=Symbol.for("react.consumer"),y=Symbol.for("react.context"),$=Symbol.for("react.forward_ref"),Y=Symbol.for("react.suspense"),V=Symbol.for("react.suspense_list"),G=Symbol.for("react.memo"),C=Symbol.for("react.lazy"),H=Symbol.for("react.activity"),Z=Symbol.for("react.client.reference"),D=E.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,X=Object.prototype.hasOwnProperty,M=Array.isArray,P=console.createTask?console.createTask:function(){return null};E={react_stack_bottom_frame:function(t){return t()}};var B,z={},W=E.react_stack_bottom_frame.bind(E,c)(),Q=P(T(c)),K={};J.Fragment=I,J.jsx=function(t,n,u){var f=1e4>D.recentlyCreatedOwnerStacks++;return S(t,n,u,!1,f?Error("react-stack-top-frame"):W,f?P(T(t)):Q)},J.jsxs=function(t,n,u){var f=1e4>D.recentlyCreatedOwnerStacks++;return S(t,n,u,!0,f?Error("react-stack-top-frame"):W,f?P(T(t)):Q)}})()),J}var ne;function de(){return ne||(ne=1,process.env.NODE_ENV==="production"?re.exports=ce():re.exports=ie()),re.exports}var e=de();const oe=[".tex",".md",".markdown",".ptx",".xml",".zip",".gz",".tar.gz",".tgz"],ue={id:"builtin",label:"Built-in converter",description:"Create a new project starting with LaTeX, Markdown, or PreTeXt files.",acceptExtensions:oe,convertFile:_.handleImportUploadFile,prepare:async o=>{const{files:h,assets:v}=await _.extractUpload(o);return{fileName:o.name,files:h,assets:v,analysis:_.analyzeImportSources(h)}},convertPrepared:(o,h)=>_.importProjectFromFiles(o.files,{...h,assets:o.assets})},le={pretext:"PreTeXt",latex:"LaTeX",markdown:"Markdown"};function me(o){const h=o.reason==="manifest-target"?`project.ptx target “${o.targetName}”`:o.reason==="latex-root"?"LaTeX document":o.reason==="pretext-root"?"PreTeXt document":o.reason==="markdown-root"?"Markdown document":"possible document";return o.title?`${o.title} — ${h}`:h}function xe(o){return o.candidates.filter(v=>v.reason==="manifest-target").length>1?!0:o.manifest&&o.primary?.reason==="manifest-target"?!1:o.formats.length>1||o.candidates.length>1||o.extraRoots.length>0}function pe({onConfirm:o,onCancel:h,importOptions:v,defaultDocumentKind:T="auto",engines:b}){const c=b&&b.length>0?b:[ue],j=d.useRef(null),[g,p]=d.useState({name:"upload"}),[A,S]=d.useState(!1),[w,F]=d.useState(T),[E,k]=d.useState(!1),[R,I]=d.useState(c[0].id),[N,L]=d.useState("converted"),[x,y]=d.useState(!1),[$,Y]=d.useState(new Set),[V,G]=d.useState(null),[C,H]=d.useState("auto"),[Z,D]=d.useState(null),[X,M]=d.useState({}),P=c.find(r=>r.id===R)??c[0],B=P.acceptExtensions??oe,z=()=>v??{documentKind:w==="auto"?void 0:w,splitSections:E},W=r=>_.analyzeImportSources(r.files,{sourceFormat:C==="auto"?void 0:C,mainFile:Z??void 0}),Q=r=>{p({name:"processing"});try{const a=W(r).extraRoots.map(l=>({path:l.path,include:X[l.path]?.include??!0,level:X[l.path]?.level})),m=P.convertPrepared(r,{...z(),sourceFormat:C==="auto"?void 0:C,mainFile:Z??void 0,attachRoots:a});"pretextError"in m?p({name:"error",message:m.pretextError}):p({name:"review",result:m})}catch(s){p({name:"error",message:s instanceof Error?s.message:"An unexpected error occurred."})}},K=async r=>{p({name:"processing"});try{if(P.prepare&&P.convertPrepared){const a=await P.prepare(r);if(G(a),H("auto"),D(null),M({}),xe(a.analysis)){p({name:"sources",prepared:a});return}const m=P.convertPrepared(a,z());p("pretextError"in m?{name:"error",message:m.pretextError}:{name:"review",result:m});return}const s=await P.convertFile(r,z());"pretextError"in s?p({name:"error",message:s.pretextError}):p({name:"review",result:s})}catch(s){p({name:"error",message:s instanceof Error?s.message:"An unexpected error occurred."})}},t=()=>{p({name:"upload"}),L("converted"),y(!1),Y(new Set),G(null)};function n(r,s){return[...r].sort((a,m)=>a===s?-1:m===s?1:a.localeCompare(m))}function u(r,s){const a=_.filesForImportMode(r,s),m=s==="converted"?r.projectLayout.mainSourcePath:r.sourcePath,l=n(Object.keys(a),m)[0];Y(l?new Set([l]):new Set)}function f(r){Y(s=>{const a=new Set(s);return a.has(r)?a.delete(r):a.add(r),a})}if(g.name==="processing")return e.jsxs("div",{className:"flex flex-col items-center justify-center gap-3 py-16 text-slate-600",children:[e.jsx("div",{className:"h-8 w-8 animate-spin rounded-full border-2 border-blue-700 border-t-transparent"}),e.jsx("p",{className:"text-sm",children:"Processing your file…"})]});if(g.name==="error")return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-800",children:[e.jsx("p",{className:"font-semibold",children:"Import failed"}),e.jsx("p",{className:"mt-1",children:g.message})]}),e.jsx("div",{className:"flex justify-end",children:e.jsx("button",{type:"button",onClick:t,className:"rounded bg-blue-700 px-4 py-2 text-sm font-medium text-white hover:bg-blue-600",children:"Try Another File"})})]});if(g.name==="sources"){const r=g.prepared,s=W(r),a=s.manifest,m=s.primary?.path??"";return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold text-slate-700",children:"Choose what to import"}),e.jsxs("p",{className:"mt-1 text-sm text-slate-500",children:[r.fileName," contains more than one possible starting point."]})]}),a?e.jsxs("div",{className:"rounded-lg border border-blue-200 bg-blue-50 p-4 text-sm text-blue-900",children:[e.jsxs("p",{className:"font-medium",children:["Found ",a.manifestPath," — an existing PreTeXt project."]}),e.jsxs("p",{className:"mt-1 text-blue-800",children:["Its publication file, assets, and directory layout will be kept as they are. Targets:"," ",a.targets.map(l=>l.name).join(", "),"."]})]}):null,e.jsx("div",{className:"flex flex-wrap gap-4 text-sm",children:e.jsxs("label",{className:"flex items-center gap-2 text-slate-700",children:[e.jsx("span",{className:"text-slate-500",children:"Source format"}),e.jsxs("select",{value:C,onChange:l=>{H(l.currentTarget.value),D(null),M({})},className:"rounded border border-slate-300 px-2 py-1 text-sm",children:[e.jsxs("option",{value:"auto",children:["Auto detect",s.primary?` (${le[s.primary.format]})`:""]}),s.formats.map(l=>e.jsx("option",{value:l,children:le[l]},l))]})]})}),s.candidates.length>1?e.jsxs("fieldset",{className:"rounded-lg border border-slate-200 p-4",children:[e.jsx("legend",{className:"px-1 text-sm font-semibold text-slate-700",children:"Main document"}),e.jsx("div",{className:"mt-2 flex flex-col gap-2",children:s.candidates.map(l=>e.jsxs("label",{className:"flex cursor-pointer items-start gap-3 text-sm",children:[e.jsx("input",{type:"radio",name:"main-file",value:l.path,checked:m===l.path,onChange:()=>{D(l.path),M({})},className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-mono text-xs text-slate-900",children:l.path}),e.jsx("span",{className:"block text-slate-500",children:me(l)})]})]},l.path))})]}):null,s.extraRoots.length>0?e.jsxs("fieldset",{className:"rounded-lg border border-slate-200 p-4",children:[e.jsx("legend",{className:"px-1 text-sm font-semibold text-slate-700",children:"Other documents"}),e.jsx("p",{className:"mt-1 text-sm text-slate-500",children:"These files also stand on their own. Attach them to the main document, or leave them out."}),e.jsx("div",{className:"mt-3 flex flex-col gap-2",children:s.extraRoots.map(l=>{const O=X[l.path],ee=O?.include??!0;return e.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-sm",children:[e.jsxs("label",{className:"flex flex-1 cursor-pointer items-center gap-2",children:[e.jsx("input",{type:"checkbox",checked:ee,onChange:U=>M(i=>({...i,[l.path]:{...i[l.path],include:U.currentTarget.checked}}))}),e.jsx("span",{className:"font-mono text-xs text-slate-900",children:l.path}),l.title?e.jsxs("span",{className:"text-slate-500",children:["— ",l.title]}):null]}),e.jsxs("label",{className:"flex items-center gap-2 text-slate-700",children:[e.jsx("span",{className:"text-slate-500",children:"Attach as"}),e.jsxs("select",{value:O?.level??"auto",disabled:!ee,onChange:U=>M(i=>({...i,[l.path]:{include:i[l.path]?.include??!0,level:U.currentTarget.value==="auto"?void 0:U.currentTarget.value}})),className:"rounded border border-slate-300 px-2 py-1 text-sm disabled:opacity-50",children:[e.jsx("option",{value:"auto",children:"Auto"}),e.jsx("option",{value:"chapter",children:"Chapter"}),e.jsx("option",{value:"section",children:"Section"})]})]})]},l.path)})})]}):null,e.jsxs("div",{className:"flex items-center justify-between gap-3 pt-1",children:[e.jsx("button",{type:"button",onClick:t,className:"px-4 py-2 text-sm text-slate-600 hover:text-slate-900",children:"Start Over"}),e.jsx("button",{type:"button",onClick:()=>Q(r),className:"rounded bg-blue-700 px-4 py-2 text-sm font-medium text-white hover:bg-blue-600",children:"Continue"})]})]})}if(g.name==="review"){let r=function(i){L(i),x&&u(s,i)};const{result:s}=g,a=s.detectedSourceFormat==="latex",m=s.warnings.length,l=Object.keys(s.outputFiles).length,O=_.filesForImportMode(s,N),ee=N==="converted"?s.projectLayout.mainSourcePath:s.sourcePath,U=n(Object.keys(O),ee);return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"rounded-lg border border-slate-200 bg-slate-50 p-4",children:[e.jsx("h3",{className:"mb-3 text-sm font-semibold text-slate-700",children:"Import Summary"}),e.jsxs("dl",{className:"grid grid-cols-2 gap-x-6 gap-y-2 text-sm",children:[e.jsx("dt",{className:"text-slate-500",children:"Source"}),e.jsx("dd",{className:"font-medium text-slate-900",children:s.sourceName}),e.jsx("dt",{className:"text-slate-500",children:"Detected format"}),e.jsx("dd",{className:"font-medium text-slate-900 capitalize",children:s.detectedSourceFormat}),e.jsx("dt",{className:"text-slate-500",children:"Document kind"}),e.jsx("dd",{className:"font-medium text-slate-900 capitalize",children:s.documentKind}),e.jsx("dt",{className:"text-slate-500",children:"Output files"}),e.jsx("dd",{className:"font-medium text-slate-900",children:l}),s.projectLayout.preserved?e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-slate-500",children:"Existing project"}),e.jsx("dd",{className:"font-medium text-slate-900",children:"Kept publication file, assets, and layout"})]}):null,s.attachedRoots.length>0?e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-slate-500",children:"Attached"}),e.jsx("dd",{className:"font-medium text-slate-900",children:s.attachedRoots.map(i=>`${i.title} (${i.level})`).join(", ")})]}):null]})]}),m>0?e.jsxs("details",{className:"rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm",children:[e.jsxs("summary",{className:"cursor-pointer font-semibold text-amber-800",children:[m," conversion"," ",m===1?"warning":"warnings"]}),e.jsx("ul",{className:"mt-3 space-y-1.5 text-amber-700",children:s.warnings.map((i,te)=>e.jsxs("li",{children:[e.jsx("code",{className:"rounded bg-amber-100 px-1 py-0.5 text-xs",children:i.macro})," — ",i.action==="replace"||i.action==="rewrite"?`replaced with \`${i.replacement}\``:i.message??i.action,i.occurrences>1?` (×${i.occurrences})`:null]},te))})]}):e.jsx("p",{className:"text-sm text-green-700",children:"No conversion warnings."}),a?e.jsxs("fieldset",{className:"rounded-lg border border-slate-200 p-4",children:[e.jsx("legend",{className:"px-1 text-sm font-semibold text-slate-700",children:"Import mode"}),e.jsxs("div",{className:"mt-2 flex flex-col gap-3",children:[e.jsxs("label",{className:"flex cursor-pointer items-start gap-3 text-sm",children:[e.jsx("input",{type:"radio",name:"import-mode",value:"converted",checked:N==="converted",onChange:()=>r("converted"),className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium text-slate-900",children:"Convert to PreTeXt"}),e.jsx("span",{className:"block text-slate-500",children:"Use the converted PreTeXt output. Recommended for new PreTeXt projects."})]})]}),e.jsxs("label",{className:"flex cursor-pointer items-start gap-3 text-sm",children:[e.jsx("input",{type:"radio",name:"import-mode",value:"native",checked:N==="native",onChange:()=>r("native"),className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium text-slate-900",children:"Keep as LaTeX"}),e.jsx("span",{className:"block text-slate-500",children:"Preserve the original LaTeX source. The conversion will not be applied."})]})]})]})]}):null,x?e.jsx("div",{className:"overflow-hidden rounded-lg border border-slate-200 text-sm",children:U.map(i=>{const te=$.has(i);return e.jsxs("div",{className:"border-b border-slate-200 last:border-b-0",children:[e.jsxs("button",{type:"button",onClick:()=>f(i),className:"flex w-full items-center gap-2 bg-slate-100 px-4 py-2 text-left font-mono text-xs text-slate-700 hover:bg-slate-200",children:[e.jsx("span",{className:"shrink-0 text-slate-400",children:te?"▾":"▸"}),e.jsx("span",{className:"flex-1 truncate",children:i}),e.jsxs("span",{className:"shrink-0 text-slate-400",children:[(O[i].length/1024).toFixed(1)," KB"]})]}),te?e.jsx("pre",{className:"m-0 max-h-72 overflow-auto bg-white p-4 font-mono text-xs leading-relaxed text-slate-800",children:O[i]}):null]},i)})}):null,e.jsxs("div",{className:"flex items-center justify-between gap-3 pt-1",children:[e.jsx("button",{type:"button",onClick:h??t,className:"px-4 py-2 text-sm text-slate-600 hover:text-slate-900",children:h?"Cancel":"Start Over"}),e.jsxs("div",{className:"flex gap-2",children:[V?e.jsx("button",{type:"button",onClick:()=>p({name:"sources",prepared:V}),className:"rounded border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50",children:"Change Sources"}):null,e.jsx("button",{type:"button",onClick:()=>{x||u(s,N),y(i=>!i)},className:"rounded border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50",children:x?"Hide Preview":"Preview"}),e.jsx("button",{type:"button",onClick:()=>o(s,N),className:"rounded bg-blue-700 px-4 py-2 text-sm font-medium text-white hover:bg-blue-600",children:"Confirm Import"})]})]})]})}return e.jsxs("div",{className:"flex flex-col gap-4",children:[c.length>1?e.jsxs("fieldset",{className:"rounded-lg border border-slate-200 p-4",children:[e.jsx("legend",{className:"px-1 text-sm font-semibold text-slate-700",children:"Converter"}),e.jsx("div",{className:"mt-2 flex flex-col gap-3",children:c.map(r=>e.jsxs("label",{className:"flex cursor-pointer items-start gap-3 text-sm",children:[e.jsx("input",{type:"radio",name:"import-engine",value:r.id,checked:R===r.id,onChange:()=>I(r.id),className:"mt-0.5"}),e.jsxs("span",{children:[e.jsx("span",{className:"font-medium text-slate-900",children:r.label}),r.description?e.jsx("span",{className:"block text-slate-500",children:r.description}):null]})]},r.id))})]}):null,v?null:e.jsxs("div",{className:"flex flex-wrap gap-4 text-sm",children:[e.jsxs("label",{className:"flex items-center gap-2 text-slate-700",children:[e.jsx("span",{className:"text-slate-500",children:"Document kind"}),e.jsxs("select",{value:w,onChange:r=>F(r.currentTarget.value),className:"rounded border border-slate-300 px-2 py-1 text-sm",children:[e.jsx("option",{value:"auto",children:"Auto detect"}),e.jsx("option",{value:"article",children:"Article"}),e.jsx("option",{value:"book",children:"Book"})]})]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm text-slate-700",children:[e.jsx("input",{type:"checkbox",checked:E,onChange:r=>k(r.currentTarget.checked)}),"Split sections into separate files"]})]}),e.jsxs("div",{role:"button",tabIndex:0,onKeyDown:r=>r.key==="Enter"&&j.current?.click(),onClick:()=>j.current?.click(),onDragOver:r=>{r.preventDefault(),S(!0)},onDragLeave:()=>S(!1),onDrop:r=>{r.preventDefault(),S(!1);const s=r.dataTransfer.files?.[0];s&&K(s)},className:`flex cursor-pointer flex-col items-center gap-3 rounded-lg border-2 border-dashed p-10 text-center transition-colors ${A?"border-blue-500 bg-blue-50":"border-slate-300 bg-slate-50 hover:border-slate-400"}`,children:[e.jsx("p",{className:"text-slate-600",children:"Drop a file here, or click to select."}),e.jsx("button",{type:"button",onClick:r=>{r.stopPropagation(),j.current?.click()},className:"rounded bg-blue-700 px-4 py-2 text-sm font-medium text-white hover:bg-blue-600",children:"Select File"}),e.jsxs("p",{className:"text-xs text-slate-400",children:["Supports ",B.join(", ")]}),e.jsx("input",{ref:j,type:"file",hidden:!0,accept:B.join(","),onChange:r=>{const s=r.currentTarget.files?.[0];s&&K(s),r.currentTarget.value=""}})]})]})}const fe={title:"Import Source Content",description:"Paste LaTeX, Markdown, or PreTeXt source to convert into PreTeXt.",sourceLabel:"Source",sourcePlaceholder:"Paste source content here...",formatLabel:"Source format",convertButton:"Convert to PreTeXt",detectedFormatPrefix:"Detected",successPrefix:"Ready",errorPrefix:"Error"};function he({initialSource:o="",initialSourceFormat:h,labels:v,disabled:T=!1,onImport:b}){const c=d.useMemo(()=>({...fe,...v??{}}),[v]),[j,g]=d.useState(o),[p,A]=d.useState(h??"auto"),[S,w]=d.useState(null),F=d.useMemo(()=>_.detectSourceFormat(j),[j]),E=T||!j.trim();return e.jsx("form",{onSubmit:k=>{k.preventDefault();const R=_.convertSourceToPretext(j,p==="auto"?void 0:p);w(R),b(R)},"aria-label":"Import source form",children:e.jsxs("fieldset",{disabled:T,children:[e.jsx("legend",{children:c.title}),e.jsx("p",{children:c.description}),e.jsxs("label",{children:[c.sourceLabel,e.jsx("textarea",{value:j,onChange:k=>g(k.currentTarget.value),placeholder:c.sourcePlaceholder,rows:12})]}),e.jsxs("label",{children:[c.formatLabel,e.jsxs("select",{value:p,onChange:k=>A(k.currentTarget.value),children:[e.jsx("option",{value:"auto",children:"Auto detect"}),e.jsx("option",{value:"latex",children:"LaTeX"}),e.jsx("option",{value:"markdown",children:"Markdown"}),e.jsx("option",{value:"pretext",children:"PreTeXt"})]})]}),e.jsxs("p",{children:[c.detectedFormatPrefix,": ",e.jsx("strong",{children:F})]}),e.jsx("button",{type:"submit",disabled:E,children:c.convertButton}),S?"pretextError"in S?e.jsxs("p",{role:"alert",children:[c.errorPrefix,": ",S.pretextError]}):e.jsxs("p",{children:[c.successPrefix,": ",S.pretextSource.length," characters of PreTeXt generated."]}):null]})})}const be={title:"Upload Source File",hint:"Supports .tex, .md, .ptx, .xml, .zip, and .tar.gz files.",selectButton:"Select File",dropHint:"Drop a file here, or click Select File.",documentKindLabel:"Document kind",splitSectionsLabel:"Split each chapter into sections"};function je({labels:o,disabled:h=!1,defaultDocumentKind:v="auto",importOptions:T,onImport:b}){const c=d.useMemo(()=>({...be,...o??{}}),[o]),j=d.useRef(null),[g,p]=d.useState(!1),[A,S]=d.useState(!1),[w,F]=d.useState([]),[E,k]=d.useState(v),[R,I]=d.useState(!1),N=h||A,L=async x=>{S(!0);try{const y=T??{documentKind:E==="auto"?void 0:E,splitSections:R},$=await _.handleImportUploadFile(x,y);F($.statusMessages),b($)}finally{S(!1)}};return e.jsxs("section",{"aria-label":"Import upload panel",children:[e.jsx("h3",{children:c.title}),e.jsx("p",{children:c.hint}),T?null:e.jsxs("div",{className:"import-options",children:[e.jsxs("label",{children:[c.documentKindLabel,e.jsxs("select",{value:E,disabled:N,onChange:x=>k(x.currentTarget.value),children:[e.jsx("option",{value:"auto",children:"Auto detect"}),e.jsx("option",{value:"article",children:"Article"}),e.jsx("option",{value:"book",children:"Book"})]})]}),e.jsxs("label",{children:[e.jsx("input",{type:"checkbox",checked:R,disabled:N,onChange:x=>I(x.currentTarget.checked)}),c.splitSectionsLabel]})]}),e.jsxs("div",{onDragOver:x=>{x.preventDefault(),N||p(!0)},onDragLeave:()=>p(!1),onDrop:x=>{if(x.preventDefault(),p(!1),N)return;const y=x.dataTransfer.files?.[0];y&&L(y)},children:[e.jsx("p",{children:c.dropHint}),e.jsx("button",{type:"button",disabled:N,onClick:()=>j.current?.click(),children:A?"Processing...":c.selectButton}),e.jsx("input",{ref:j,type:"file",hidden:!0,disabled:N,accept:".tex,.md,.markdown,.ptx,.xml,.zip,.gz,.tar.gz,.tgz",onChange:x=>{const y=x.currentTarget.files?.[0];y&&L(y),x.currentTarget.value=""}})]}),w.length>0?e.jsx("ul",{"aria-live":"polite",children:w.map((x,y)=>e.jsx("li",{children:x.message},`${x.type}-${y}`))}):null,g&&!N?e.jsx("p",{children:"Release to upload the file."}):null]})}exports.ImportSourceForm=he;exports.ImportUploadPanel=je;exports.ImportWizard=pe;
|