@bendyline/squisq-formats 2.4.2 → 2.4.3

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.
@@ -0,0 +1,17 @@
1
+ // src/registry/types.ts
2
+ var BUILTIN_FORMAT_IDS = [
3
+ "md",
4
+ "docx",
5
+ "pdf",
6
+ "pptx",
7
+ "xlsx",
8
+ "csv",
9
+ "html",
10
+ "htmlzip",
11
+ "epub",
12
+ "dbk"
13
+ ];
14
+
15
+ export {
16
+ BUILTIN_FORMAT_IDS
17
+ };
@@ -0,0 +1,284 @@
1
+ import {
2
+ convert,
3
+ defaultRegistry
4
+ } from "./chunk-DNGNODJP.js";
5
+ import {
6
+ ConversionError
7
+ } from "./chunk-KXOZMWBS.js";
8
+
9
+ // src/outside-in/index.ts
10
+ import {
11
+ parseFrontmatter,
12
+ setFrontmatterValues,
13
+ splitFrontmatterBlock,
14
+ stringifyMarkdown
15
+ } from "@bendyline/squisq/markdown";
16
+ import { MemoryContentContainer } from "@bendyline/squisq/storage";
17
+ var OUTSIDE_IN_FORMAT_IDS = ["html", "docx", "pdf", "pptx", "xlsx"];
18
+ var OUTSIDE_IN_FORMAT_SET = new Set(OUTSIDE_IN_FORMAT_IDS);
19
+ var OUTSIDE_IN_VERSION_KEY = "squisq-outside-in";
20
+ var OUTSIDE_IN_OUTPUT_KEY = "squisq-output";
21
+ var OUTSIDE_IN_FORMAT_KEY = "squisq-output-format";
22
+ var OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY = "squisq-updatefrommarkdown";
23
+ function normalizePath(path) {
24
+ const slash = path.replace(/\\/g, "/");
25
+ const leading = slash.startsWith("/") ? "/" : "";
26
+ const parts = slash.split("/").filter((part) => part !== "");
27
+ if (parts.some((part) => part === "." || part === "..")) {
28
+ throw new Error(`Outside-in paths must be canonical workspace paths: ${path}`);
29
+ }
30
+ return leading + parts.join("/");
31
+ }
32
+ function joinPath(parent, child) {
33
+ if (!parent || parent === "/") return parent === "/" ? `/${child}` : child;
34
+ return `${parent}/${child}`;
35
+ }
36
+ function dirname(path) {
37
+ const slash = path.lastIndexOf("/");
38
+ if (slash < 0) return "";
39
+ if (slash === 0) return "/";
40
+ return path.slice(0, slash);
41
+ }
42
+ function basename(path) {
43
+ return path.slice(path.lastIndexOf("/") + 1);
44
+ }
45
+ function slugStem(stem) {
46
+ const slug = stem.normalize("NFKD").replace(/\p{Mark}+/gu, "").toLocaleLowerCase("en-US").replace(/[^\p{Letter}\p{Number}]+/gu, "-").replace(/^-+|-+$/g, "");
47
+ return slug || "document";
48
+ }
49
+ function formatFromExtension(extension) {
50
+ const normalized = extension.toLowerCase();
51
+ if (normalized === "htm") return "html";
52
+ return OUTSIDE_IN_FORMAT_SET.has(normalized) ? normalized : null;
53
+ }
54
+ function resolveOutsideInLayout(targetPath) {
55
+ const normalized = normalizePath(targetPath);
56
+ const filename = basename(normalized);
57
+ const dot = filename.lastIndexOf(".");
58
+ if (dot <= 0 || dot === filename.length - 1) return null;
59
+ const format = formatFromExtension(filename.slice(dot + 1));
60
+ if (!format) return null;
61
+ const stem = filename.slice(0, dot);
62
+ const parentDirectory = dirname(normalized);
63
+ const companionName = `${stem}_files`;
64
+ const companionDirectory = joinPath(parentDirectory, companionName);
65
+ const markdownFilename = `${slugStem(stem)}.md`;
66
+ const backupDirectory = joinPath(companionDirectory, ".original");
67
+ const backupFilename = `original.${format}`;
68
+ return {
69
+ targetPath: normalized,
70
+ format,
71
+ parentDirectory,
72
+ stem,
73
+ companionName,
74
+ companionDirectory,
75
+ markdownFilename,
76
+ markdownPath: joinPath(companionDirectory, markdownFilename),
77
+ relativeTargetPath: `../${filename}`,
78
+ backupDirectory,
79
+ backupFilename,
80
+ backupPath: joinPath(backupDirectory, backupFilename)
81
+ };
82
+ }
83
+ function isOutsideInTargetPath(path) {
84
+ return resolveOutsideInLayout(path) !== null;
85
+ }
86
+ function chooseOutsideInMarkdownPath(layout, paths) {
87
+ const canonical = normalizePath(layout.markdownPath);
88
+ const normalized = paths.map(normalizePath);
89
+ const exact = normalized.find((path) => path === canonical);
90
+ if (exact) return exact;
91
+ const canonicalFolded = canonical.toLocaleLowerCase("en-US");
92
+ const folded = normalized.find((path) => path.toLocaleLowerCase("en-US") === canonicalFolded);
93
+ if (folded) return folded;
94
+ const prefix = `${normalizePath(layout.companionDirectory).replace(/\/$/, "")}/`;
95
+ const markdown = normalized.filter((path) => {
96
+ if (!path.toLocaleLowerCase("en-US").endsWith(".md")) return false;
97
+ if (!path.startsWith(prefix)) return false;
98
+ return !path.slice(prefix.length).includes("/");
99
+ });
100
+ return markdown.length === 1 ? markdown[0] : null;
101
+ }
102
+ function rawFrontmatter(source) {
103
+ const block = splitFrontmatterBlock(source).frontmatter;
104
+ if (!block) return null;
105
+ const firstBreak = block.indexOf("\n");
106
+ if (firstBreak < 0) return null;
107
+ const withoutOpening = block.slice(firstBreak + 1);
108
+ return withoutOpening.replace(/\r?\n---(?:\r?\n)?$/, "");
109
+ }
110
+ function readOutsideInMetadata(source) {
111
+ const yaml = rawFrontmatter(source);
112
+ const frontmatter = yaml === null ? null : parseFrontmatter(yaml);
113
+ if (!frontmatter) return null;
114
+ const version = frontmatter[OUTSIDE_IN_VERSION_KEY];
115
+ const target = frontmatter[OUTSIDE_IN_OUTPUT_KEY];
116
+ const format = frontmatter[OUTSIDE_IN_FORMAT_KEY];
117
+ if (version !== 1 || typeof target !== "string" || typeof format !== "string") return null;
118
+ if (!OUTSIDE_IN_FORMAT_SET.has(format)) return null;
119
+ return {
120
+ version: 1,
121
+ target,
122
+ format,
123
+ updateFromMarkdown: frontmatter[OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY] === true
124
+ };
125
+ }
126
+ function withOutsideInMetadata(source, layout) {
127
+ return setFrontmatterValues(source, {
128
+ [OUTSIDE_IN_VERSION_KEY]: 1,
129
+ [OUTSIDE_IN_OUTPUT_KEY]: layout.relativeTargetPath,
130
+ [OUTSIDE_IN_FORMAT_KEY]: layout.format
131
+ });
132
+ }
133
+ function isOutsideInMarkdownEditingEnabled(source) {
134
+ if (typeof source !== "string") {
135
+ return source.frontmatter?.[OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY] === true;
136
+ }
137
+ const yaml = rawFrontmatter(source);
138
+ const frontmatter = yaml === null ? null : parseFrontmatter(yaml);
139
+ return frontmatter?.[OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY] === true;
140
+ }
141
+ function withOutsideInMarkdownEditing(source, layout, enabled = true) {
142
+ return setFrontmatterValues(withOutsideInMetadata(source, layout), {
143
+ [OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY]: enabled
144
+ });
145
+ }
146
+ function requireLayout(targetPath) {
147
+ const layout = resolveOutsideInLayout(targetPath);
148
+ if (layout) return layout;
149
+ throw new ConversionError(
150
+ "unknown-format",
151
+ `Outside-in editing does not support the target "${targetPath}".`
152
+ );
153
+ }
154
+ function arrayBufferOf(data) {
155
+ if (data instanceof ArrayBuffer) return data;
156
+ return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
157
+ }
158
+ async function importMarkdownDocument(data, layout, registry, options) {
159
+ const definition = registry.get(layout.format);
160
+ if (!definition || !definition.importContainer && !definition.importDoc) {
161
+ throw new ConversionError(
162
+ "unsupported-input",
163
+ `Format "${layout.format}" cannot be imported for outside-in editing.`,
164
+ { format: layout.format }
165
+ );
166
+ }
167
+ if (definition.importContainer) {
168
+ const container = await definition.importContainer(data, options);
169
+ const imported = await container.readDocument();
170
+ if (imported !== null) {
171
+ const { parseMarkdown } = await import("@bendyline/squisq/markdown");
172
+ return { markdownDoc: parseMarkdown(imported), container };
173
+ }
174
+ if (definition.importDoc) {
175
+ return { markdownDoc: await definition.importDoc(data, options), container };
176
+ }
177
+ throw new ConversionError("invalid-input", "Imported document did not contain Markdown.", {
178
+ format: layout.format
179
+ });
180
+ }
181
+ const markdownDoc = await definition.importDoc(data, options);
182
+ return { markdownDoc, container: new MemoryContentContainer() };
183
+ }
184
+ async function retainImportedOfficeTheme(data, layout, markdownDoc, options) {
185
+ if (layout.format !== "docx" && layout.format !== "xlsx") return [];
186
+ if (typeof markdownDoc.frontmatter?.["squisq-theme"] === "string") return [];
187
+ try {
188
+ const [{ inferThemeFromFile }, themeCodec] = await Promise.all([
189
+ import("./infer/index.js"),
190
+ import("@bendyline/squisq/doc")
191
+ ]);
192
+ const inferred = await inferThemeFromFile(data, {
193
+ format: layout.format,
194
+ nameHint: layout.stem,
195
+ signal: options.signal
196
+ });
197
+ const payload = themeCodec.writeCustomThemesToFrontmatter([inferred.theme]);
198
+ if (payload) {
199
+ markdownDoc.frontmatter = {
200
+ ...markdownDoc.frontmatter ?? {},
201
+ [themeCodec.FRONTMATTER_CUSTOM_THEMES_KEY]: payload,
202
+ "squisq-theme": inferred.theme.id
203
+ };
204
+ }
205
+ return inferred.warnings;
206
+ } catch (error) {
207
+ if (options.signal?.aborted) throw options.signal.reason ?? error;
208
+ return [
209
+ `The ${layout.format.toUpperCase()} content was imported, but its Office theme could not be retained: ${error instanceof Error ? error.message : String(error)}`
210
+ ];
211
+ }
212
+ }
213
+ async function importOutsideInDocument(source, options = {}) {
214
+ options.signal?.throwIfAborted();
215
+ const layout = requireLayout(source.targetPath);
216
+ const data = arrayBufferOf(source.data);
217
+ const registry = options.registry ?? defaultRegistry();
218
+ const imported = await importMarkdownDocument(data, layout, registry, {
219
+ ...options,
220
+ registry,
221
+ from: layout.format
222
+ });
223
+ const warnings = await retainImportedOfficeTheme(data, layout, imported.markdownDoc, options);
224
+ options.signal?.throwIfAborted();
225
+ const markdownOptions = options.formatOptions?.md;
226
+ const markdown = withOutsideInMetadata(
227
+ stringifyMarkdown(imported.markdownDoc, markdownOptions?.stringify),
228
+ layout
229
+ );
230
+ return { layout, markdown, container: imported.container, warnings };
231
+ }
232
+ async function renderOutsideInDocument(source, options = {}) {
233
+ const layout = requireLayout(source.targetPath);
234
+ if (!isOutsideInMarkdownEditingEnabled(source.markdown)) {
235
+ throw new ConversionError(
236
+ "invalid-input",
237
+ `Outside-in editing is read-only until ${OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY}: true is set.`,
238
+ { format: layout.format }
239
+ );
240
+ }
241
+ if (layout.format === "html" && !options.html?.playerScriptPath) {
242
+ throw new ConversionError(
243
+ "missing-dependency",
244
+ "Outside-in HTML export needs a shared Squisq player path.",
245
+ { format: "html" }
246
+ );
247
+ }
248
+ const formatOptions = { ...options.formatOptions ?? {} };
249
+ if (layout.format === "html" && options.html) {
250
+ formatOptions.html = {
251
+ ...formatOptions.html ?? {},
252
+ playerScriptPath: options.html.playerScriptPath,
253
+ basePath: options.html.basePath ?? layout.companionName
254
+ };
255
+ }
256
+ return convert(
257
+ {
258
+ kind: "markdown",
259
+ markdown: source.markdown,
260
+ container: source.container,
261
+ baseName: layout.stem
262
+ },
263
+ layout.format,
264
+ {
265
+ ...options,
266
+ title: options.title ?? layout.stem,
267
+ formatOptions
268
+ }
269
+ );
270
+ }
271
+
272
+ export {
273
+ OUTSIDE_IN_FORMAT_IDS,
274
+ OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY,
275
+ resolveOutsideInLayout,
276
+ isOutsideInTargetPath,
277
+ chooseOutsideInMarkdownPath,
278
+ readOutsideInMetadata,
279
+ withOutsideInMetadata,
280
+ isOutsideInMarkdownEditingEnabled,
281
+ withOutsideInMarkdownEditing,
282
+ importOutsideInDocument,
283
+ renderOutsideInDocument
284
+ };
@@ -7,20 +7,6 @@ import {
7
7
  resolveZipSafetyLimits
8
8
  } from "./chunk-7AWFHP5U.js";
9
9
 
10
- // src/registry/types.ts
11
- var BUILTIN_FORMAT_IDS = [
12
- "md",
13
- "docx",
14
- "pdf",
15
- "pptx",
16
- "xlsx",
17
- "csv",
18
- "html",
19
- "htmlzip",
20
- "epub",
21
- "dbk"
22
- ];
23
-
24
10
  // src/registry/limits.ts
25
11
  var DEFAULT_CONVERSION_LIMITS = Object.freeze({
26
12
  maxInputBytes: 256 * 1024 * 1024,
@@ -481,9 +467,21 @@ function defaultFormats() {
481
467
  // importContainer omitted: HTML import already inlines images as data URIs,
482
468
  // so there is nothing to extract into a container this wave.
483
469
  async exportDoc(input, options) {
470
+ const raw = optionsFor(options, "html");
471
+ if (raw.playerScriptPath) {
472
+ const { generateExternalHtml } = await import("./html/index.js");
473
+ const htmlText2 = generateExternalHtml(input.doc, {
474
+ ...raw,
475
+ playerScriptPath: raw.playerScriptPath,
476
+ title: options.title ?? input.baseName,
477
+ mode: raw.mode ?? "static",
478
+ themeId: resolveThemeId(input, options),
479
+ themeRegistry: options.themeRegistry ?? raw.themeRegistry
480
+ });
481
+ return ok(new TextEncoder().encode(htmlText2), MIME.html);
482
+ }
484
483
  const playerScript = await requirePlayerScript(options, "html");
485
484
  const { docToHtml } = await import("./html/index.js");
486
- const raw = optionsFor(options, "html");
487
485
  const containerImages = await collectContainerImages(input.container, options.signal);
488
486
  const images = new Map([...containerImages, ...raw.images ?? /* @__PURE__ */ new Map()]);
489
487
  const htmlText = docToHtml(input.doc, {
@@ -925,7 +923,6 @@ async function convert(source, to, options = {}) {
925
923
  }
926
924
 
927
925
  export {
928
- BUILTIN_FORMAT_IDS,
929
926
  DEFAULT_CONVERSION_LIMITS,
930
927
  resolveConversionLimits,
931
928
  defaultFormats,
@@ -140,6 +140,7 @@ function buildInlineImageMaps(images) {
140
140
  function generateInlineHtml(doc, options) {
141
141
  const {
142
142
  playerScript,
143
+ basePath = ".",
143
144
  images,
144
145
  mode = "slideshow",
145
146
  title = "Squisq Document",
@@ -189,7 +190,7 @@ ${mode === "static" ? "#squisq-root{display:block}" : ""}
189
190
  autoPlay: ${JSON.stringify(autoPlay)},${captionStyle ? `
190
191
  captionStyle: ${JSON.stringify(captionStyle)},` : ""}
191
192
  showCodeCopyButton: ${JSON.stringify(showCodeCopyButton)},
192
- basePath: "."
193
+ basePath: ${JSON.stringify(basePath)}
193
194
  });
194
195
  })();
195
196
  </script>
@@ -207,7 +208,8 @@ function generateExternalHtml(doc, options) {
207
208
  showCodeCopyButton = false,
208
209
  captionStyle,
209
210
  themeId,
210
- themeRegistry
211
+ themeRegistry,
212
+ basePath = "."
211
213
  } = options;
212
214
  doc = applyThemeSelection(doc, themeId, themeRegistry);
213
215
  const docJson = escapeForScript(JSON.stringify(doc));
@@ -242,7 +244,7 @@ ${mode === "static" ? "#squisq-root{display:block}" : ""}
242
244
  autoPlay: ${JSON.stringify(autoPlay)},${captionStyle ? `
243
245
  captionStyle: ${JSON.stringify(captionStyle)},` : ""}
244
246
  showCodeCopyButton: ${JSON.stringify(showCodeCopyButton)},
245
- basePath: "."
247
+ basePath: ${JSON.stringify(basePath)}
246
248
  });
247
249
  })();
248
250
  </script>
@@ -1,6 +1,6 @@
1
1
  import { Theme, ThemeRegistry, Doc } from '@bendyline/squisq/schemas';
2
- import { H as HtmlExportOptions } from '../import-BQFf0iEG.js';
3
- export { a as HtmlImportOptions, c as collectImagePaths, g as generateExternalHtml, h as htmlToMarkdown, b as htmlToMarkdownDoc, d as htmlToMarkdownDocSync } from '../import-BQFf0iEG.js';
2
+ import { H as HtmlExportOptions } from '../import-B0gBYUmd.js';
3
+ export { a as HtmlImportOptions, c as collectImagePaths, g as generateExternalHtml, h as htmlToMarkdown, b as htmlToMarkdownDoc, d as htmlToMarkdownDocSync } from '../import-B0gBYUmd.js';
4
4
  import { HtmlPolicy, MarkdownDocument } from '@bendyline/squisq/markdown';
5
5
 
6
6
  /**
@@ -10,7 +10,7 @@ import {
10
10
  markdownDocToPlainHtml,
11
11
  markdownDocsToHtmlBundle,
12
12
  markdownDocsToPlainHtmlBundle
13
- } from "../chunk-A5Y23TAF.js";
13
+ } from "../chunk-N2ZN3MQN.js";
14
14
  import {
15
15
  arrayBufferToBase64DataUrl,
16
16
  extractFilename,
@@ -18,6 +18,17 @@ interface HtmlExportOptions {
18
18
  signal?: AbortSignal;
19
19
  /** The IIFE player bundle source code (from @bendyline/squisq-react/standalone-source) */
20
20
  playerScript: string;
21
+ /**
22
+ * Reference an existing standalone player instead of embedding
23
+ * {@link playerScript}. Used by outside-in documents that share one
24
+ * `_squisq/squisq-player.js` runtime across a folder hierarchy.
25
+ */
26
+ playerScriptPath?: string;
27
+ /**
28
+ * Base URL used to resolve relative document media. Defaults to `.`.
29
+ * Outside-in HTML points this at the document's companion `_files` folder.
30
+ */
31
+ basePath?: string;
21
32
  /**
22
33
  * Map of relative image paths (as they appear in the Doc) to binary image data.
23
34
  * For inline HTML export, these are converted to base64 data URIs.
@@ -67,7 +78,7 @@ declare function collectImagePaths(doc: Doc): Set<string>;
67
78
  * @param options - Export options (playerScript is not embedded, referenced via src)
68
79
  * @returns Complete HTML string
69
80
  */
70
- declare function generateExternalHtml(doc: Doc, options: Pick<HtmlExportOptions, 'mode' | 'title' | 'autoPlay' | 'showCodeCopyButton' | 'captionStyle' | 'themeId' | 'themeRegistry'> & {
81
+ declare function generateExternalHtml(doc: Doc, options: Pick<HtmlExportOptions, 'mode' | 'title' | 'autoPlay' | 'showCodeCopyButton' | 'captionStyle' | 'themeId' | 'themeRegistry' | 'basePath'> & {
71
82
  /** Relative path to the player JS file (e.g., 'squisq-player.js') */
72
83
  playerScriptPath: string;
73
84
  /** Map of original image paths to their rewritten relative paths in the ZIP */
package/dist/index.d.ts CHANGED
@@ -6,9 +6,11 @@ export { PdfExportOptions, PdfImportOptions, configurePdfWorker, docToPdf, markd
6
6
  export { HtmlZipExportOptions, docToHtml, docToHtmlZip } from './html/index.js';
7
7
  export { EpubExportOptions, docToEpub, markdownDocToEpub } from './epub/index.js';
8
8
  export { ExtractedFileTheme, InferSourceFormat, InferThemeOptions, InferredFileTheme, compileExtractedTheme, inferThemeFromFile } from './infer/index.js';
9
- export { BUILTIN_FORMAT_IDS, BuiltinFormatOptions, ConversionError, ConversionErrorCode, ConversionErrorOptions, ConversionLimits, ConversionResult, ConvertOptions, ConvertSource, DEFAULT_CONVERSION_LIMITS, DbkFormatOptions, FormatDefinition, FormatId, FormatRegistry, MarkdownFormatOptions, NormalizedInput, PreparedConversion, PreparedExportOptions, convert, createRegistry, defaultFormats, defaultRegistry, prepareConversion, resolveConversionLimits } from './registry/index.js';
9
+ export { B as BUILTIN_FORMAT_IDS, a as BuiltinFormatOptions, C as ConversionLimits, b as ConversionResult, c as ConvertOptions, d as ConvertSource, D as DEFAULT_CONVERSION_LIMITS, e as DbkFormatOptions, F as FormatDefinition, f as FormatId, g as FormatRegistry, M as MarkdownFormatOptions, N as NormalizedInput, P as PreparedConversion, h as PreparedExportOptions, r as resolveConversionLimits } from './types-HDLauUoa.js';
10
+ export { ConversionError, ConversionErrorCode, ConversionErrorOptions, convert, createRegistry, defaultFormats, defaultRegistry, prepareConversion } from './registry/index.js';
11
+ export { ImportedOutsideInDocument, OUTSIDE_IN_FORMAT_IDS, OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY, OutsideInFormatId, OutsideInLayout, OutsideInMetadata, RenderOutsideInOptions, chooseOutsideInMarkdownPath, importOutsideInDocument, isOutsideInMarkdownEditingEnabled, isOutsideInTargetPath, readOutsideInMetadata, renderOutsideInDocument, resolveOutsideInLayout, withOutsideInMarkdownEditing, withOutsideInMetadata } from './outside-in/index.js';
10
12
  export { Z as ZipSafetyError, a as ZipSafetyErrorCode, b as ZipSafetyErrorOptions, c as ZipSafetyLimits } from './zipLimits-BOKCB7qk.js';
11
- export { H as HtmlExportOptions, a as HtmlImportOptions, c as collectImagePaths, h as htmlToMarkdown, b as htmlToMarkdownDoc, d as htmlToMarkdownDocSync } from './import-BQFf0iEG.js';
13
+ export { H as HtmlExportOptions, a as HtmlImportOptions, c as collectImagePaths, h as htmlToMarkdown, b as htmlToMarkdownDoc, d as htmlToMarkdownDocSync } from './import-B0gBYUmd.js';
12
14
  export { P as PptxExportOptions, a as PptxImportOptions, d as docToPptx, m as markdownDocToPptx, p as pptxToMarkdownDoc } from './import-C16E8Y4X.js';
13
15
  export { X as XlsxExportOptions, a as XlsxImportOptions, d as docToXlsx, m as markdownDocToXlsx, x as xlsxToMarkdownDoc } from './export-D9msROJS.js';
14
16
  import '@bendyline/squisq/schemas';
package/dist/index.js CHANGED
@@ -3,7 +3,25 @@ import {
3
3
  markdownDocToEpub
4
4
  } from "./chunk-KN62QJYK.js";
5
5
  import {
6
- BUILTIN_FORMAT_IDS,
6
+ BUILTIN_FORMAT_IDS
7
+ } from "./chunk-2P5HJAQL.js";
8
+ import {
9
+ inferThemeFromFile
10
+ } from "./chunk-KMBBO5H7.js";
11
+ import {
12
+ OUTSIDE_IN_FORMAT_IDS,
13
+ OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY,
14
+ chooseOutsideInMarkdownPath,
15
+ importOutsideInDocument,
16
+ isOutsideInMarkdownEditingEnabled,
17
+ isOutsideInTargetPath,
18
+ readOutsideInMetadata,
19
+ renderOutsideInDocument,
20
+ resolveOutsideInLayout,
21
+ withOutsideInMarkdownEditing,
22
+ withOutsideInMetadata
23
+ } from "./chunk-BVGJ54NV.js";
24
+ import {
7
25
  DEFAULT_CONVERSION_LIMITS,
8
26
  convert,
9
27
  createRegistry,
@@ -11,10 +29,7 @@ import {
11
29
  defaultRegistry,
12
30
  prepareConversion,
13
31
  resolveConversionLimits
14
- } from "./chunk-24VREWAZ.js";
15
- import {
16
- inferThemeFromFile
17
- } from "./chunk-KMBBO5H7.js";
32
+ } from "./chunk-DNGNODJP.js";
18
33
  import {
19
34
  ConversionError
20
35
  } from "./chunk-KXOZMWBS.js";
@@ -33,7 +48,7 @@ import {
33
48
  markdownDocToPptx,
34
49
  pptxToDoc,
35
50
  pptxToMarkdownDoc
36
- } from "./chunk-RVGOYKVW.js";
51
+ } from "./chunk-XCV242AO.js";
37
52
  import "./chunk-6N2J7C2B.js";
38
53
  import "./chunk-DWNNYO5H.js";
39
54
  import {
@@ -72,14 +87,17 @@ import {
72
87
  htmlToMarkdown,
73
88
  htmlToMarkdownDoc,
74
89
  htmlToMarkdownDocSync
75
- } from "./chunk-A5Y23TAF.js";
90
+ } from "./chunk-N2ZN3MQN.js";
76
91
  import "./chunk-6RQOV3B3.js";
77
92
  import "./chunk-AONELFLA.js";
78
93
  export {
79
94
  BUILTIN_FORMAT_IDS,
80
95
  ConversionError,
81
96
  DEFAULT_CONVERSION_LIMITS,
97
+ OUTSIDE_IN_FORMAT_IDS,
98
+ OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY,
82
99
  ZipSafetyError,
100
+ chooseOutsideInMarkdownPath,
83
101
  collectImagePaths,
84
102
  compileExtractedTheme,
85
103
  configurePdfWorker,
@@ -101,7 +119,10 @@ export {
101
119
  htmlToMarkdown,
102
120
  htmlToMarkdownDoc,
103
121
  htmlToMarkdownDocSync,
122
+ importOutsideInDocument,
104
123
  inferThemeFromFile,
124
+ isOutsideInMarkdownEditingEnabled,
125
+ isOutsideInTargetPath,
105
126
  markdownDocToCsv,
106
127
  markdownDocToDocx,
107
128
  markdownDocToEpub,
@@ -114,7 +135,12 @@ export {
114
135
  pptxToDoc,
115
136
  pptxToMarkdownDoc,
116
137
  prepareConversion,
138
+ readOutsideInMetadata,
139
+ renderOutsideInDocument,
117
140
  resolveConversionLimits,
141
+ resolveOutsideInLayout,
142
+ withOutsideInMarkdownEditing,
143
+ withOutsideInMetadata,
118
144
  xlsxToDoc,
119
145
  xlsxToMarkdownDoc
120
146
  };
@@ -0,0 +1,117 @@
1
+ import { MarkdownDocument } from '@bendyline/squisq/markdown';
2
+ import { ContentContainer } from '@bendyline/squisq/storage';
3
+ import { c as ConvertOptions, b as ConversionResult } from '../types-HDLauUoa.js';
4
+ import '@bendyline/squisq/schemas';
5
+ import '@bendyline/squisq/transform';
6
+ import '../docx/index.js';
7
+ import '../reader-B_m1aKZC.js';
8
+ import '../zipLimits-BOKCB7qk.js';
9
+ import '../import-C16E8Y4X.js';
10
+ import '../export-D9msROJS.js';
11
+ import '../csv/index.js';
12
+ import '../pdf/index.js';
13
+ import '../import-B0gBYUmd.js';
14
+ import '../epub/index.js';
15
+ import '../container/index.js';
16
+
17
+ /**
18
+ * Outside-in document editing.
19
+ *
20
+ * A rendered document remains the user-facing file while its editable
21
+ * Markdown source and media live in a hidden sibling companion directory:
22
+ *
23
+ * Tucson.pptx
24
+ * Tucson_files/
25
+ * tucson.md
26
+ * hero.png
27
+ * .versions/
28
+ *
29
+ * Hosts own filesystem authority and transaction ordering. This module owns
30
+ * the portable path/frontmatter contract plus registry-backed import/export.
31
+ */
32
+
33
+ declare const OUTSIDE_IN_FORMAT_IDS: readonly ["html", "docx", "pdf", "pptx", "xlsx"];
34
+ type OutsideInFormatId = (typeof OUTSIDE_IN_FORMAT_IDS)[number];
35
+ declare const OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY = "squisq-updatefrommarkdown";
36
+ interface OutsideInLayout {
37
+ /** User-facing rendered file, relative to the host's workspace root. */
38
+ targetPath: string;
39
+ /** Registry format used to import and regenerate the target. */
40
+ format: OutsideInFormatId;
41
+ /** Parent directory of the rendered file. Empty at workspace root. */
42
+ parentDirectory: string;
43
+ /** Case-preserving rendered filename without its final extension. */
44
+ stem: string;
45
+ /** Case-preserving `<stem>_files` folder name. */
46
+ companionName: string;
47
+ /** Full workspace-relative companion directory. */
48
+ companionDirectory: string;
49
+ /** Slugged Markdown filename inside the companion directory. */
50
+ markdownFilename: string;
51
+ /** Full workspace-relative Markdown source path. */
52
+ markdownPath: string;
53
+ /** Rendered target path as stored relative to the Markdown source. */
54
+ relativeTargetPath: string;
55
+ /** Hidden directory containing the immutable pre-edit rendered file. */
56
+ backupDirectory: string;
57
+ /** Stable filename for the pre-edit rendered file. */
58
+ backupFilename: string;
59
+ /** Full workspace-relative path to the pre-edit rendered file. */
60
+ backupPath: string;
61
+ }
62
+ interface OutsideInMetadata {
63
+ version: 1;
64
+ format: OutsideInFormatId;
65
+ target: string;
66
+ /** Only an exact boolean true authorizes Markdown-driven regeneration. */
67
+ updateFromMarkdown: boolean;
68
+ }
69
+ interface ImportedOutsideInDocument {
70
+ layout: OutsideInLayout;
71
+ markdown: string;
72
+ /** Imported media container. Hosts copy its non-Markdown members into the companion folder. */
73
+ container: ContentContainer;
74
+ /** Non-fatal fidelity notes from theme/layout inference. */
75
+ warnings: string[];
76
+ }
77
+ interface RenderOutsideInOptions extends ConvertOptions {
78
+ /** Required for HTML targets, which intentionally reference a shared runtime. */
79
+ html?: {
80
+ /** URL from the rendered HTML file to `_squisq/squisq-player.js`. */
81
+ playerScriptPath: string;
82
+ /** URL from the rendered HTML file to its companion media folder. */
83
+ basePath?: string;
84
+ };
85
+ }
86
+ /** Resolve the canonical companion/source layout for a supported rendered file. */
87
+ declare function resolveOutsideInLayout(targetPath: string): OutsideInLayout | null;
88
+ declare function isOutsideInTargetPath(path: string): boolean;
89
+ /**
90
+ * Pick an existing source inside the companion directory. Canonical slug wins;
91
+ * a sole root-level Markdown file is accepted for older/manual layouts.
92
+ */
93
+ declare function chooseOutsideInMarkdownPath(layout: OutsideInLayout, paths: readonly string[]): string | null;
94
+ /** Read outside-in metadata without interpreting the output path as authority. */
95
+ declare function readOutsideInMetadata(source: string): OutsideInMetadata | null;
96
+ /** Add or refresh the portable relationship while preserving unrelated frontmatter. */
97
+ declare function withOutsideInMetadata(source: string, layout: OutsideInLayout): string;
98
+ /** True only when the companion explicitly opts into rendered-file updates. */
99
+ declare function isOutsideInMarkdownEditingEnabled(source: string | MarkdownDocument): boolean;
100
+ /**
101
+ * Opt a companion into or out of Markdown-driven regeneration while keeping
102
+ * the portable target relationship current.
103
+ */
104
+ declare function withOutsideInMarkdownEditing(source: string, layout: OutsideInLayout, enabled?: boolean): string;
105
+ /** Import a rendered target into editable Markdown plus any extracted media. */
106
+ declare function importOutsideInDocument(source: {
107
+ data: ArrayBuffer | Uint8Array;
108
+ targetPath: string;
109
+ }, options?: ConvertOptions): Promise<ImportedOutsideInDocument>;
110
+ /** Regenerate the user-facing target from its Markdown source. */
111
+ declare function renderOutsideInDocument(source: {
112
+ markdown: string | MarkdownDocument;
113
+ targetPath: string;
114
+ container?: ContentContainer;
115
+ }, options?: RenderOutsideInOptions): Promise<ConversionResult>;
116
+
117
+ export { type ImportedOutsideInDocument, OUTSIDE_IN_FORMAT_IDS, OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY, type OutsideInFormatId, type OutsideInLayout, type OutsideInMetadata, type RenderOutsideInOptions, chooseOutsideInMarkdownPath, importOutsideInDocument, isOutsideInMarkdownEditingEnabled, isOutsideInTargetPath, readOutsideInMetadata, renderOutsideInDocument, resolveOutsideInLayout, withOutsideInMarkdownEditing, withOutsideInMetadata };
@@ -0,0 +1,29 @@
1
+ import {
2
+ OUTSIDE_IN_FORMAT_IDS,
3
+ OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY,
4
+ chooseOutsideInMarkdownPath,
5
+ importOutsideInDocument,
6
+ isOutsideInMarkdownEditingEnabled,
7
+ isOutsideInTargetPath,
8
+ readOutsideInMetadata,
9
+ renderOutsideInDocument,
10
+ resolveOutsideInLayout,
11
+ withOutsideInMarkdownEditing,
12
+ withOutsideInMetadata
13
+ } from "../chunk-BVGJ54NV.js";
14
+ import "../chunk-DNGNODJP.js";
15
+ import "../chunk-KXOZMWBS.js";
16
+ import "../chunk-7AWFHP5U.js";
17
+ export {
18
+ OUTSIDE_IN_FORMAT_IDS,
19
+ OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY,
20
+ chooseOutsideInMarkdownPath,
21
+ importOutsideInDocument,
22
+ isOutsideInMarkdownEditingEnabled,
23
+ isOutsideInTargetPath,
24
+ readOutsideInMetadata,
25
+ renderOutsideInDocument,
26
+ resolveOutsideInLayout,
27
+ withOutsideInMarkdownEditing,
28
+ withOutsideInMetadata
29
+ };
@@ -4,7 +4,7 @@ import {
4
4
  pptxToContainer,
5
5
  pptxToDoc,
6
6
  pptxToMarkdownDoc
7
- } from "../chunk-RVGOYKVW.js";
7
+ } from "../chunk-XCV242AO.js";
8
8
  import {
9
9
  analyzePptxLayouts,
10
10
  inspectPptxLayouts
@@ -1,173 +1,19 @@
1
- import { Doc, ThemeRegistry } from '@bendyline/squisq/schemas';
2
- import { TransformStyleInput, TransformStyleRegistry } from '@bendyline/squisq/transform';
3
- import { ParseOptions, StringifyOptions, MarkdownDocument } from '@bendyline/squisq/markdown';
4
- import { ContentContainer } from '@bendyline/squisq/storage';
5
- import { DocxImportOptions, DocxExportOptions } from '../docx/index.js';
6
- import { a as PptxImportOptions, P as PptxExportOptions } from '../import-C16E8Y4X.js';
7
- import { a as XlsxImportOptions, X as XlsxExportOptions } from '../export-D9msROJS.js';
8
- import { CsvImportOptions, CsvExportOptions } from '../csv/index.js';
9
- import { PdfImportOptions, PdfExportOptions } from '../pdf/index.js';
10
- import { a as HtmlImportOptions, H as HtmlExportOptions } from '../import-BQFf0iEG.js';
11
- import { EpubExportOptions } from '../epub/index.js';
12
- import { ContainerToZipOptions } from '../container/index.js';
13
- import { c as ZipSafetyLimits } from '../zipLimits-BOKCB7qk.js';
1
+ import { f as FormatId, g as FormatRegistry, F as FormatDefinition, d as ConvertSource, c as ConvertOptions, b as ConversionResult, P as PreparedConversion } from '../types-HDLauUoa.js';
2
+ export { B as BUILTIN_FORMAT_IDS, a as BuiltinFormatOptions, C as ConversionLimits, D as DEFAULT_CONVERSION_LIMITS, e as DbkFormatOptions, M as MarkdownFormatOptions, N as NormalizedInput, h as PreparedExportOptions, r as resolveConversionLimits } from '../types-HDLauUoa.js';
3
+ import '@bendyline/squisq/schemas';
4
+ import '@bendyline/squisq/transform';
5
+ import '@bendyline/squisq/markdown';
6
+ import '@bendyline/squisq/storage';
7
+ import '../docx/index.js';
14
8
  import '../reader-B_m1aKZC.js';
15
-
16
- interface ConversionLimits {
17
- maxInputBytes: number;
18
- maxMarkdownBytes: number;
19
- maxMarkdownNodes: number;
20
- maxMarkdownDepth: number;
21
- maxTableCells: number;
22
- maxBlocks: number;
23
- maxBlockDepth: number;
24
- maxDurationSeconds: number;
25
- maxAudioSegments: number;
26
- }
27
- declare const DEFAULT_CONVERSION_LIMITS: Readonly<ConversionLimits>;
28
- declare function resolveConversionLimits(limits?: Partial<ConversionLimits>): ConversionLimits;
29
-
30
- /**
31
- * Format registry — shared types.
32
- *
33
- * The registry is the programmatic heart of `convert()`: it maps a small set of
34
- * format ids (`md`, `docx`, `pdf`, …) to `FormatDefinition`s, each of which
35
- * knows how to import to / export from squisq's markdown + Doc model. Every
36
- * converter module is loaded lazily via `import()` inside the definition
37
- * methods, so pulling in the registry never eagerly bundles heavy converters.
38
- */
39
-
40
- /** A format identifier (e.g. `'docx'`). Strings so hosts can register their own. */
41
- type FormatId = string;
42
- /** The built-in formats the default registry ships with. */
43
- declare const BUILTIN_FORMAT_IDS: readonly ["md", "docx", "pdf", "pptx", "xlsx", "csv", "html", "htmlzip", "epub", "dbk"];
44
- /** The bytes + metadata produced by a successful export. */
45
- interface ConversionResult {
46
- /** Encoded output bytes. */
47
- bytes: Uint8Array;
48
- /** MIME type of the output. */
49
- mimeType: string;
50
- /** A sensible download filename (`<baseName>.<ext>`). */
51
- suggestedFilename: string;
52
- /** Non-fatal notes accumulated during conversion (may be empty). */
53
- warnings: string[];
54
- }
55
- interface MarkdownFormatOptions {
56
- parse?: ParseOptions;
57
- stringify?: StringifyOptions;
58
- }
59
- /** Resource limits applied when importing a DBK/ZIP container. */
60
- type DbkFormatOptions = ZipSafetyLimits & ContainerToZipOptions;
61
- /**
62
- * Strongly typed option bags for built-in formats. Import and export options
63
- * share a bag because a single conversion may use the format on either side.
64
- * Custom registries may add arbitrary keys through the intersection used by
65
- * {@link ConvertOptions.formatOptions}.
66
- */
67
- interface BuiltinFormatOptions {
68
- md: MarkdownFormatOptions;
69
- docx: DocxImportOptions & DocxExportOptions;
70
- pptx: PptxImportOptions & PptxExportOptions;
71
- xlsx: XlsxImportOptions & XlsxExportOptions;
72
- csv: CsvImportOptions & CsvExportOptions;
73
- pdf: PdfImportOptions & PdfExportOptions;
74
- html: HtmlImportOptions & Partial<Omit<HtmlExportOptions, 'playerScript'>>;
75
- htmlzip: Partial<Omit<HtmlExportOptions, 'playerScript'>>;
76
- epub: EpubExportOptions;
77
- dbk: DbkFormatOptions;
78
- }
79
- /**
80
- * A source normalized into every shape an exporter might need. `doc` is always
81
- * present; `markdownDoc` is present when the source was markdown-shaped (an
82
- * exporter that wants markdown but finds none derives it from `doc`).
83
- */
84
- interface NormalizedInput {
85
- doc: Doc;
86
- markdownDoc?: MarkdownDocument;
87
- container: ContentContainer;
88
- baseName: string;
89
- }
90
- /** Options threaded through `convert()` and into every format method. */
91
- interface ConvertOptions {
92
- /** Cancel normalization, transformation, or export at the next bounded work boundary. */
93
- signal?: AbortSignal;
94
- /** Cross-format safety limits. Pass false only for explicitly trusted input. */
95
- limits?: Partial<ConversionLimits> | false;
96
- /** Registry to resolve formats against. Defaults to `defaultRegistry()`. */
97
- registry?: FormatRegistry;
98
- /** Explicit source format id (skips extension/byte sniffing). */
99
- from?: FormatId;
100
- /** Theme id to apply to the exported document. */
101
- themeId?: string;
102
- /** Explicit caller-owned registry for non-document custom themes. */
103
- themeRegistry?: ThemeRegistry;
104
- /** Built-in/registry id or call-scoped style to apply before export. */
105
- transformStyle?: TransformStyleInput;
106
- /** Explicit caller-owned registry used to resolve transform style ids. */
107
- transformRegistry?: TransformStyleRegistry;
108
- /** Content-aware auto-templating when deriving a Doc from markdown. */
109
- autoTemplates?: boolean;
110
- /** Title hint for exporters that expose document metadata. */
111
- title?: string;
112
- /** Lazily resolve the standalone player IIFE bundle (required for HTML export). */
113
- resolvePlayerScript?: () => Promise<string>;
114
- /** Typed per-format options for built-ins; custom format ids remain extensible. */
115
- formatOptions?: Partial<BuiltinFormatOptions> & Record<FormatId, unknown>;
116
- }
117
- /** Target-only options accepted after a source has already been normalized and transformed. */
118
- type PreparedExportOptions = Pick<ConvertOptions, 'signal' | 'title' | 'resolvePlayerScript' | 'formatOptions'>;
119
- /**
120
- * An opaque normalized conversion snapshot. The source and transform pipeline
121
- * has already completed; each call exports that same snapshot to one target.
122
- */
123
- interface PreparedConversion {
124
- convert(to: FormatId, options?: PreparedExportOptions): Promise<ConversionResult>;
125
- }
126
- /**
127
- * How a format's exporter treats Squisq template annotations: `rendered`
128
- * materializes template visuals into the output, `preserved` keeps annotations
129
- * intact for round-tripping, and `ignored` flattens blocks to semantic content
130
- * so annotations have no effect on the exported result.
131
- */
132
- type TemplateAnnotationHandling = 'rendered' | 'preserved' | 'ignored';
133
- /** Describes how a single format imports to / exports from the squisq model. */
134
- interface FormatDefinition {
135
- id: FormatId;
136
- label: string;
137
- mimeType: string;
138
- extensions: readonly string[];
139
- /** Exporter treatment of template annotations. Absent means unspecified. */
140
- templateAnnotationHandling?: TemplateAnnotationHandling;
141
- /** Import raw bytes to a MarkdownDocument. */
142
- importDoc?(data: ArrayBuffer, options: ConvertOptions): Promise<MarkdownDocument>;
143
- /** Import raw bytes to a ContentContainer (markdown + extracted media). */
144
- importContainer?(data: ArrayBuffer, options: ConvertOptions): Promise<ContentContainer>;
145
- /** Export a normalized input to bytes. */
146
- exportDoc?(input: NormalizedInput, options: ConvertOptions): Promise<ConversionResult>;
147
- }
148
- /** A mutable collection of format definitions keyed by id. */
149
- interface FormatRegistry {
150
- register(def: FormatDefinition): void;
151
- get(id: FormatId): FormatDefinition | undefined;
152
- byExtension(ext: string): FormatDefinition | undefined;
153
- list(): FormatDefinition[];
154
- }
155
- /** The three shapes `convert()` accepts as a source. */
156
- type ConvertSource = {
157
- kind: 'bytes';
158
- data: ArrayBuffer | Uint8Array;
159
- filename?: string;
160
- } | {
161
- kind: 'markdown';
162
- markdown: string | MarkdownDocument;
163
- container?: ContentContainer;
164
- baseName?: string;
165
- } | {
166
- kind: 'doc';
167
- doc: Doc;
168
- container?: ContentContainer;
169
- baseName?: string;
170
- };
9
+ import '../zipLimits-BOKCB7qk.js';
10
+ import '../import-C16E8Y4X.js';
11
+ import '../export-D9msROJS.js';
12
+ import '../csv/index.js';
13
+ import '../pdf/index.js';
14
+ import '../import-B0gBYUmd.js';
15
+ import '../epub/index.js';
16
+ import '../container/index.js';
171
17
 
172
18
  /**
173
19
  * Structured error for the format registry / `convert()` pipeline.
@@ -241,4 +87,4 @@ declare function prepareConversion(source: ConvertSource, options?: ConvertOptio
241
87
  */
242
88
  declare function convert(source: ConvertSource, to: FormatId, options?: ConvertOptions): Promise<ConversionResult>;
243
89
 
244
- export { BUILTIN_FORMAT_IDS, type BuiltinFormatOptions, ConversionError, type ConversionErrorCode, type ConversionErrorOptions, type ConversionLimits, type ConversionResult, type ConvertOptions, type ConvertSource, DEFAULT_CONVERSION_LIMITS, type DbkFormatOptions, type FormatDefinition, type FormatId, type FormatRegistry, type MarkdownFormatOptions, type NormalizedInput, type PreparedConversion, type PreparedExportOptions, convert, createRegistry, defaultFormats, defaultRegistry, prepareConversion, resolveConversionLimits };
90
+ export { ConversionError, type ConversionErrorCode, type ConversionErrorOptions, ConversionResult, ConvertOptions, ConvertSource, FormatDefinition, FormatId, FormatRegistry, PreparedConversion, convert, createRegistry, defaultFormats, defaultRegistry, prepareConversion };
@@ -1,5 +1,7 @@
1
1
  import {
2
- BUILTIN_FORMAT_IDS,
2
+ BUILTIN_FORMAT_IDS
3
+ } from "../chunk-2P5HJAQL.js";
4
+ import {
3
5
  DEFAULT_CONVERSION_LIMITS,
4
6
  convert,
5
7
  createRegistry,
@@ -7,7 +9,7 @@ import {
7
9
  defaultRegistry,
8
10
  prepareConversion,
9
11
  resolveConversionLimits
10
- } from "../chunk-24VREWAZ.js";
12
+ } from "../chunk-DNGNODJP.js";
11
13
  import {
12
14
  ConversionError
13
15
  } from "../chunk-KXOZMWBS.js";
@@ -0,0 +1,171 @@
1
+ import { Doc, ThemeRegistry } from '@bendyline/squisq/schemas';
2
+ import { TransformStyleInput, TransformStyleRegistry } from '@bendyline/squisq/transform';
3
+ import { ParseOptions, StringifyOptions, MarkdownDocument } from '@bendyline/squisq/markdown';
4
+ import { ContentContainer } from '@bendyline/squisq/storage';
5
+ import { DocxImportOptions, DocxExportOptions } from './docx/index.js';
6
+ import { a as PptxImportOptions, P as PptxExportOptions } from './import-C16E8Y4X.js';
7
+ import { a as XlsxImportOptions, X as XlsxExportOptions } from './export-D9msROJS.js';
8
+ import { CsvImportOptions, CsvExportOptions } from './csv/index.js';
9
+ import { PdfImportOptions, PdfExportOptions } from './pdf/index.js';
10
+ import { a as HtmlImportOptions, H as HtmlExportOptions } from './import-B0gBYUmd.js';
11
+ import { EpubExportOptions } from './epub/index.js';
12
+ import { ContainerToZipOptions } from './container/index.js';
13
+ import { c as ZipSafetyLimits } from './zipLimits-BOKCB7qk.js';
14
+
15
+ interface ConversionLimits {
16
+ maxInputBytes: number;
17
+ maxMarkdownBytes: number;
18
+ maxMarkdownNodes: number;
19
+ maxMarkdownDepth: number;
20
+ maxTableCells: number;
21
+ maxBlocks: number;
22
+ maxBlockDepth: number;
23
+ maxDurationSeconds: number;
24
+ maxAudioSegments: number;
25
+ }
26
+ declare const DEFAULT_CONVERSION_LIMITS: Readonly<ConversionLimits>;
27
+ declare function resolveConversionLimits(limits?: Partial<ConversionLimits>): ConversionLimits;
28
+
29
+ /**
30
+ * Format registry — shared types.
31
+ *
32
+ * The registry is the programmatic heart of `convert()`: it maps a small set of
33
+ * format ids (`md`, `docx`, `pdf`, …) to `FormatDefinition`s, each of which
34
+ * knows how to import to / export from squisq's markdown + Doc model. Every
35
+ * converter module is loaded lazily via `import()` inside the definition
36
+ * methods, so pulling in the registry never eagerly bundles heavy converters.
37
+ */
38
+
39
+ /** A format identifier (e.g. `'docx'`). Strings so hosts can register their own. */
40
+ type FormatId = string;
41
+ /** The built-in formats the default registry ships with. */
42
+ declare const BUILTIN_FORMAT_IDS: readonly ["md", "docx", "pdf", "pptx", "xlsx", "csv", "html", "htmlzip", "epub", "dbk"];
43
+ /** The bytes + metadata produced by a successful export. */
44
+ interface ConversionResult {
45
+ /** Encoded output bytes. */
46
+ bytes: Uint8Array;
47
+ /** MIME type of the output. */
48
+ mimeType: string;
49
+ /** A sensible download filename (`<baseName>.<ext>`). */
50
+ suggestedFilename: string;
51
+ /** Non-fatal notes accumulated during conversion (may be empty). */
52
+ warnings: string[];
53
+ }
54
+ interface MarkdownFormatOptions {
55
+ parse?: ParseOptions;
56
+ stringify?: StringifyOptions;
57
+ }
58
+ /** Resource limits applied when importing a DBK/ZIP container. */
59
+ type DbkFormatOptions = ZipSafetyLimits & ContainerToZipOptions;
60
+ /**
61
+ * Strongly typed option bags for built-in formats. Import and export options
62
+ * share a bag because a single conversion may use the format on either side.
63
+ * Custom registries may add arbitrary keys through the intersection used by
64
+ * {@link ConvertOptions.formatOptions}.
65
+ */
66
+ interface BuiltinFormatOptions {
67
+ md: MarkdownFormatOptions;
68
+ docx: DocxImportOptions & DocxExportOptions;
69
+ pptx: PptxImportOptions & PptxExportOptions;
70
+ xlsx: XlsxImportOptions & XlsxExportOptions;
71
+ csv: CsvImportOptions & CsvExportOptions;
72
+ pdf: PdfImportOptions & PdfExportOptions;
73
+ html: HtmlImportOptions & Partial<Omit<HtmlExportOptions, 'playerScript'>>;
74
+ htmlzip: Partial<Omit<HtmlExportOptions, 'playerScript'>>;
75
+ epub: EpubExportOptions;
76
+ dbk: DbkFormatOptions;
77
+ }
78
+ /**
79
+ * A source normalized into every shape an exporter might need. `doc` is always
80
+ * present; `markdownDoc` is present when the source was markdown-shaped (an
81
+ * exporter that wants markdown but finds none derives it from `doc`).
82
+ */
83
+ interface NormalizedInput {
84
+ doc: Doc;
85
+ markdownDoc?: MarkdownDocument;
86
+ container: ContentContainer;
87
+ baseName: string;
88
+ }
89
+ /** Options threaded through `convert()` and into every format method. */
90
+ interface ConvertOptions {
91
+ /** Cancel normalization, transformation, or export at the next bounded work boundary. */
92
+ signal?: AbortSignal;
93
+ /** Cross-format safety limits. Pass false only for explicitly trusted input. */
94
+ limits?: Partial<ConversionLimits> | false;
95
+ /** Registry to resolve formats against. Defaults to `defaultRegistry()`. */
96
+ registry?: FormatRegistry;
97
+ /** Explicit source format id (skips extension/byte sniffing). */
98
+ from?: FormatId;
99
+ /** Theme id to apply to the exported document. */
100
+ themeId?: string;
101
+ /** Explicit caller-owned registry for non-document custom themes. */
102
+ themeRegistry?: ThemeRegistry;
103
+ /** Built-in/registry id or call-scoped style to apply before export. */
104
+ transformStyle?: TransformStyleInput;
105
+ /** Explicit caller-owned registry used to resolve transform style ids. */
106
+ transformRegistry?: TransformStyleRegistry;
107
+ /** Content-aware auto-templating when deriving a Doc from markdown. */
108
+ autoTemplates?: boolean;
109
+ /** Title hint for exporters that expose document metadata. */
110
+ title?: string;
111
+ /** Lazily resolve the standalone player IIFE bundle (required for HTML export). */
112
+ resolvePlayerScript?: () => Promise<string>;
113
+ /** Typed per-format options for built-ins; custom format ids remain extensible. */
114
+ formatOptions?: Partial<BuiltinFormatOptions> & Record<FormatId, unknown>;
115
+ }
116
+ /** Target-only options accepted after a source has already been normalized and transformed. */
117
+ type PreparedExportOptions = Pick<ConvertOptions, 'signal' | 'title' | 'resolvePlayerScript' | 'formatOptions'>;
118
+ /**
119
+ * An opaque normalized conversion snapshot. The source and transform pipeline
120
+ * has already completed; each call exports that same snapshot to one target.
121
+ */
122
+ interface PreparedConversion {
123
+ convert(to: FormatId, options?: PreparedExportOptions): Promise<ConversionResult>;
124
+ }
125
+ /**
126
+ * How a format's exporter treats Squisq template annotations: `rendered`
127
+ * materializes template visuals into the output, `preserved` keeps annotations
128
+ * intact for round-tripping, and `ignored` flattens blocks to semantic content
129
+ * so annotations have no effect on the exported result.
130
+ */
131
+ type TemplateAnnotationHandling = 'rendered' | 'preserved' | 'ignored';
132
+ /** Describes how a single format imports to / exports from the squisq model. */
133
+ interface FormatDefinition {
134
+ id: FormatId;
135
+ label: string;
136
+ mimeType: string;
137
+ extensions: readonly string[];
138
+ /** Exporter treatment of template annotations. Absent means unspecified. */
139
+ templateAnnotationHandling?: TemplateAnnotationHandling;
140
+ /** Import raw bytes to a MarkdownDocument. */
141
+ importDoc?(data: ArrayBuffer, options: ConvertOptions): Promise<MarkdownDocument>;
142
+ /** Import raw bytes to a ContentContainer (markdown + extracted media). */
143
+ importContainer?(data: ArrayBuffer, options: ConvertOptions): Promise<ContentContainer>;
144
+ /** Export a normalized input to bytes. */
145
+ exportDoc?(input: NormalizedInput, options: ConvertOptions): Promise<ConversionResult>;
146
+ }
147
+ /** A mutable collection of format definitions keyed by id. */
148
+ interface FormatRegistry {
149
+ register(def: FormatDefinition): void;
150
+ get(id: FormatId): FormatDefinition | undefined;
151
+ byExtension(ext: string): FormatDefinition | undefined;
152
+ list(): FormatDefinition[];
153
+ }
154
+ /** The three shapes `convert()` accepts as a source. */
155
+ type ConvertSource = {
156
+ kind: 'bytes';
157
+ data: ArrayBuffer | Uint8Array;
158
+ filename?: string;
159
+ } | {
160
+ kind: 'markdown';
161
+ markdown: string | MarkdownDocument;
162
+ container?: ContentContainer;
163
+ baseName?: string;
164
+ } | {
165
+ kind: 'doc';
166
+ doc: Doc;
167
+ container?: ContentContainer;
168
+ baseName?: string;
169
+ };
170
+
171
+ export { BUILTIN_FORMAT_IDS as B, type ConversionLimits as C, DEFAULT_CONVERSION_LIMITS as D, type FormatDefinition as F, type MarkdownFormatOptions as M, type NormalizedInput as N, type PreparedConversion as P, type BuiltinFormatOptions as a, type ConversionResult as b, type ConvertOptions as c, type ConvertSource as d, type DbkFormatOptions as e, type FormatId as f, type FormatRegistry as g, type PreparedExportOptions as h, resolveConversionLimits as r };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bendyline/squisq-formats",
3
- "version": "2.4.2",
3
+ "version": "2.4.3",
4
4
  "description": "Document format converters — DOCX, PDF, OOXML import/export",
5
5
  "license": "MIT",
6
6
  "author": "Bendyline",
@@ -97,6 +97,11 @@
97
97
  "types": "./dist/infer/index.d.ts",
98
98
  "import": "./dist/infer/index.js",
99
99
  "default": "./dist/infer/index.js"
100
+ },
101
+ "./outside-in": {
102
+ "types": "./dist/outside-in/index.d.ts",
103
+ "import": "./dist/outside-in/index.js",
104
+ "default": "./dist/outside-in/index.js"
100
105
  }
101
106
  },
102
107
  "scripts": {
File without changes