@pipelex/mthds-form 0.23.2 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-CM4KVG53.js → chunk-JSPF4BQP.js} +63 -3
- package/dist/chunk-JSPF4BQP.js.map +1 -0
- package/dist/{chunk-W5MYXDLO.js → chunk-NA7SIQOH.js} +1349 -135
- package/dist/chunk-NA7SIQOH.js.map +1 -0
- package/dist/{chunk-O2VIVDHO.js → chunk-NSHGLM6A.js} +26 -3
- package/dist/chunk-NSHGLM6A.js.map +1 -0
- package/dist/{chunk-RRTI7AIR.js → chunk-QINLJ5RM.js} +3 -3
- package/dist/{chunk-RRTI7AIR.js.map → chunk-QINLJ5RM.js.map} +1 -1
- package/dist/{chunk-ICUEHNEH.js → chunk-QWHUUMSB.js} +4 -4
- package/dist/{chunk-ICUEHNEH.js.map → chunk-QWHUUMSB.js.map} +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +4 -4
- package/dist/core/native-content.d.ts +103 -6
- package/dist/core/native-content.js +1 -1
- package/dist/core/save-plan.js +3 -3
- package/dist/core/sources.d.ts +40 -1
- package/dist/core/sources.js +1 -1
- package/dist/core/stuff-files.js +2 -2
- package/dist/generative/index.js +5 -5
- package/dist/react/index.d.ts +53 -4
- package/dist/react/index.js +5 -5
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/dist/chunk-CM4KVG53.js.map +0 -1
- package/dist/chunk-O2VIVDHO.js.map +0 -1
- package/dist/chunk-W5MYXDLO.js.map +0 -1
|
@@ -24,6 +24,29 @@ function addChosenFiles(held, chosen) {
|
|
|
24
24
|
}
|
|
25
25
|
return items;
|
|
26
26
|
}
|
|
27
|
+
function placeDroppedFiles(held, count, maxItemCount, isFree = () => true) {
|
|
28
|
+
const items = [...held ?? []];
|
|
29
|
+
const targets = [];
|
|
30
|
+
for (let index = 0; index < items.length && targets.length < count; index += 1) {
|
|
31
|
+
if (heldUrl(items[index]) === void 0 && isFree(index)) targets.push(index);
|
|
32
|
+
}
|
|
33
|
+
let appended = 0;
|
|
34
|
+
while (targets.length < count && (maxItemCount === void 0 || items.length < maxItemCount)) {
|
|
35
|
+
targets.push(items.length);
|
|
36
|
+
items.push(void 0);
|
|
37
|
+
appended += 1;
|
|
38
|
+
}
|
|
39
|
+
return { items, appended, targets, leftOut: count - targets.length };
|
|
40
|
+
}
|
|
41
|
+
function roomForDroppedFiles(held, maxItemCount, isFree = () => true) {
|
|
42
|
+
if (maxItemCount === void 0) return void 0;
|
|
43
|
+
const items = held ?? [];
|
|
44
|
+
let free = 0;
|
|
45
|
+
for (let index = 0; index < items.length; index += 1) {
|
|
46
|
+
if (heldUrl(items[index]) === void 0 && isFree(index)) free += 1;
|
|
47
|
+
}
|
|
48
|
+
return free + Math.max(0, maxItemCount - items.length);
|
|
49
|
+
}
|
|
27
50
|
function chosenFilesAdded(held, chosen) {
|
|
28
51
|
const urls = heldUrls(held ?? []);
|
|
29
52
|
const before = urls.size;
|
|
@@ -36,6 +59,6 @@ function roomForChosenFiles(held, maxItemCount) {
|
|
|
36
59
|
return Math.max(0, maxItemCount - files);
|
|
37
60
|
}
|
|
38
61
|
|
|
39
|
-
export { addChosenFiles, chosenFilesAdded, roomForChosenFiles, sourceFileValue };
|
|
40
|
-
//# sourceMappingURL=chunk-
|
|
41
|
-
//# sourceMappingURL=chunk-
|
|
62
|
+
export { addChosenFiles, chosenFilesAdded, placeDroppedFiles, roomForChosenFiles, roomForDroppedFiles, sourceFileValue };
|
|
63
|
+
//# sourceMappingURL=chunk-NSHGLM6A.js.map
|
|
64
|
+
//# sourceMappingURL=chunk-NSHGLM6A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/sources.ts"],"names":[],"mappings":"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","file":"chunk-NSHGLM6A.js","sourcesContent":["/**\n * The two optional host seams beside the upload: a **file source**, which lets\n * a file field take a file the host already stores, and an **example source**,\n * which lets a whole form take a set of values someone saved for the method.\n *\n * The kernel states the shapes and applies the answers; the host answers. It\n * knows nothing of any platform's routes, records or permissions: a host maps\n * its own list onto these shapes, and a host that gives neither seam gets the\n * form it had before. The controls that use them are `./react`'s\n * (`FilePicker`, `FillWithExample`), and docs/sources.md is the contract.\n *\n * Shapes and pure functions only, so a host's server can import the types it\n * answers with, and the rules that write an answer into a value are tested in\n * node. No React, no fetch. What a row SAYS is data here (`SourceFile`'s\n * `typeLabel` and `origin` are the host's words); how a row DRAWS is a\n * rendering, so the glyph a host draws on a row is `./react`'s\n * (`FilePickerSource.renderGlyph`), never a field of these shapes.\n */\n\n/** Whose files a file source lists: the person's own, or the whole team's. */\nexport type FileSourceScope = 'mine' | 'everyone';\n\n/** One page of a file source's list, as the picker asks for it. */\nexport interface FileSourceQuery {\n /** What the person searched for, trimmed; empty when they searched for nothing. */\n search: string;\n /** Whose files to list. */\n scope: FileSourceScope;\n /**\n * The MIME types the field accepts, after any narrowing a host applied\n * (`narrowFileFormats`), in the field's own order. The list must hold only\n * files of these types: the picker writes what is chosen straight into the\n * field, and a field that refuses a dropped file of another type must not\n * be handed one this way.\n */\n mediaTypes: readonly string[];\n /** Where to continue: absent for the first page, else the previous page's `nextCursor`. */\n cursor?: string;\n /** Aborted when the answer is no longer wanted: a newer search, a closed picker. */\n signal: AbortSignal;\n}\n\n/** One row of a file source's list: a file the host already stores. */\nexport interface SourceFile {\n /** The row's identity in the host's list, which a choice is kept by. */\n id: string;\n /**\n * The stored file's address, written into the field as its `url`, exactly as\n * an upload's result is. Several rows may share one address.\n */\n url: string;\n /** The file's name, shown on the row and written into the field as its `filename`. */\n name: string;\n /**\n * The file's MIME type, which picks the field's format the row's file is:\n * the row names that format's label (\"PNG\") unless `typeLabel` words the\n * type, and draws an image's glyph or a document's from it unless the\n * host draws its own.\n */\n mediaType?: string;\n /**\n * The file's type in the host's own words (\"Picture\", \"PDF document\"), said\n * on the row's second line in place of the format's label, so a row reads\n * as the host's own list of files does. An empty string counts as none.\n */\n typeLabel?: string;\n /** The file's size in bytes. */\n size?: number;\n /** How the file came to be. A `test` file is marked \"Test file\" at the head of its row's second line. */\n kind?: 'uploaded' | 'generated' | 'test';\n /** When the file was stored, as an ISO 8601 timestamp; the row says it as a date. */\n createdAt?: string;\n /**\n * Where the file came from, in the host's own words (\"Uploaded by Ana\",\n * \"Made by Invoice extraction\"), shown on the row's second line as it is.\n */\n origin?: string;\n}\n\n/** One page of a file source's answer. */\nexport interface FileSourcePage {\n /** The page's files, newest first. A page may be empty and still carry a cursor. */\n files: readonly SourceFile[];\n /** Where the next page starts, or nothing when this page is the last. */\n nextCursor?: string | null;\n}\n\n/**\n * Where a file field can take a file the host already stores. When a form has\n * one, every file field offers \"Choose from your team's files\", and a list of\n * files offers it for several at once.\n */\nexport interface FileSource {\n /** Lists one page of files for a query. Rejecting shows the failure with Try again. */\n list: (query: FileSourceQuery) => Promise<FileSourcePage>;\n /** Which of Mine and Everyone the picker opens on. */\n initialScope: FileSourceScope;\n}\n\n/** One example of a method: a name and the inputs a run of it sends. */\nexport interface FormExample {\n /** The example's identity in the host's list. */\n id: string;\n /** The example's name, shown on its row. */\n name: string;\n /**\n * The inputs as a run takes them: each input `{ concept, content }`, an\n * optional input left out, an empty plural input a bare `[]`. It is the\n * shape `apiInputsFromRunValues` produces, so a host saves an example from\n * `form.inputs` and hands it back as it is.\n */\n inputs: Readonly<Record<string, unknown>>;\n}\n\n/** One page of an example source's list. */\nexport interface ExampleSourceQuery {\n /** Where to continue: absent for the first page, else the previous page's `nextCursor`. */\n cursor?: string;\n /** Aborted when the answer is no longer wanted. */\n signal: AbortSignal;\n}\n\n/** One page of an example source's answer. */\nexport interface ExampleSourcePage {\n /** The page's examples, in the order the list shows them. */\n examples: readonly FormExample[];\n /** Where the next page starts, or nothing when this page is the last. */\n nextCursor?: string | null;\n}\n\n/**\n * Where a form can take a whole set of values. When a form has one, it offers\n * \"Fill with an example\". `rename` and `delete` are capabilities: each is\n * offered on a row's menu only when given, so a host gives them only to a\n * person allowed to change examples.\n */\nexport interface ExampleSource {\n /** Lists one page of the method's examples. Rejecting shows the failure with Try again. */\n list: (query: ExampleSourceQuery) => Promise<ExampleSourcePage>;\n /**\n * Renames an example. Resolving to the example as stored replaces the row;\n * resolving to nothing keeps the row under the new name.\n */\n rename?: (example: FormExample, name: string) => Promise<FormExample | void>;\n /** Deletes an example. Asked for only after the person confirmed it. */\n delete?: (example: FormExample) => Promise<void>;\n /**\n * Whether \"Fill with an example\" is left out while the method has no\n * example. `false` by default, when the empty list says how to make one.\n * A host sets it for a person who cannot save an example, to whom an empty\n * list has nothing to offer; the form then asks for the first page as it\n * mounts, to know whether to offer the control.\n */\n hideWhenEmpty?: boolean;\n}\n\n/** What a chosen file writes into its field: the same `{ url, filename }` an upload writes. */\nexport function sourceFileValue(file: SourceFile): { url: string; filename: string } {\n return { url: file.url, filename: file.name };\n}\n\n/** The `url` a list item holds, when it is a file value holding one. */\nfunction heldUrl(item: unknown): string | undefined {\n if (!item || typeof item !== 'object') return undefined;\n const url = (item as { url?: unknown }).url;\n return typeof url === 'string' && url !== '' ? url : undefined;\n}\n\n/** The addresses a list's items hold, each once. */\nfunction heldUrls(items: readonly unknown[]): Set<string> {\n return new Set(items.map(heldUrl).filter((url): url is string => url !== undefined));\n}\n\n/**\n * A list of files with the chosen files written into it, in the order they\n * were chosen: first into the rows that hold no file yet (a row the person\n * added and left empty), then as new rows after the last. A file whose address\n * the list already holds is not written again, and neither is a second choice\n * of one address: two rows of a source may name the same stored file. Returns\n * a new array and leaves `held` as it was.\n */\nexport function addChosenFiles(\n held: readonly unknown[] | undefined,\n chosen: readonly SourceFile[],\n): unknown[] {\n const items = [...(held ?? [])];\n const urls = heldUrls(items);\n let free = 0;\n for (const file of chosen) {\n if (urls.has(file.url)) continue;\n urls.add(file.url);\n while (free < items.length && heldUrl(items[free]) !== undefined) free += 1;\n if (free < items.length) items[free] = sourceFileValue(file);\n else items.push(sourceFileValue(file));\n free += 1;\n }\n return items;\n}\n\n/** Where `placeDroppedFiles` puts a batch of files, and what it leaves out. */\nexport interface DroppedFilesPlacement {\n /**\n * The list once the rows the batch needs are appended: `held` as it was,\n * then one empty row (`undefined`) per file that did not go into a free row.\n * A new array whenever rows are appended, and a copy of `held` otherwise.\n */\n items: unknown[];\n /** How many rows were appended, so a caller writes the list only when it grew. */\n appended: number;\n /** The row each placed file goes to, in the order the files were given. */\n targets: number[];\n /** How many files, from the end of the batch, found no room. */\n leftOut: number;\n}\n\n/**\n * Where a batch of `count` files dropped on a list of files goes: first into\n * the rows that are free, in index order, then into new rows after the last,\n * as far as `maxItemCount` allows. The files keep the order they were given,\n * and those beyond the room are left out from the end of the batch.\n *\n * A row is free when it holds no file (its value carries no `url`) and\n * `isFree` says so too. The caller's predicate is where it adds what only it\n * knows of a row: that a file is still arriving there, whose write-back the row\n * must be kept for, or that the host reports a failure there, the only record\n * that one of the person's files did not arrive. Without one, every row holding\n * no file is free.\n *\n * It mirrors `addChosenFiles`, so the two ways several files enter a list fill\n * it alike, and it knows nothing of `File`: the caller judges each file and\n * hands over how many it accepted.\n */\nexport function placeDroppedFiles(\n held: readonly unknown[] | undefined,\n count: number,\n maxItemCount: number | undefined,\n isFree: (index: number) => boolean = () => true,\n): DroppedFilesPlacement {\n const items = [...(held ?? [])];\n const targets: number[] = [];\n for (let index = 0; index < items.length && targets.length < count; index += 1) {\n if (heldUrl(items[index]) === undefined && isFree(index)) targets.push(index);\n }\n let appended = 0;\n while (targets.length < count && (maxItemCount === undefined || items.length < maxItemCount)) {\n targets.push(items.length);\n items.push(undefined);\n appended += 1;\n }\n return { items, appended, targets, leftOut: count - targets.length };\n}\n\n/**\n * How many files `placeDroppedFiles` can place in `held`: its free rows, by the\n * same test, and the rows its bound still allows after the last. `undefined`\n * when the list has no bound, since appending then never runs out.\n */\nexport function roomForDroppedFiles(\n held: readonly unknown[] | undefined,\n maxItemCount: number | undefined,\n isFree: (index: number) => boolean = () => true,\n): number | undefined {\n if (maxItemCount === undefined) return undefined;\n const items = held ?? [];\n let free = 0;\n for (let index = 0; index < items.length; index += 1) {\n if (heldUrl(items[index]) === undefined && isFree(index)) free += 1;\n }\n return free + Math.max(0, maxItemCount - items.length);\n}\n\n/**\n * How many files `addChosenFiles` writes for `chosen` into `held`: the choices\n * whose address the list does not hold yet, each address once. This is what a\n * choice spends of `roomForChosenFiles`, so a held file chosen again, or a\n * second row naming a chosen file, takes no room.\n */\nexport function chosenFilesAdded(\n held: readonly unknown[] | undefined,\n chosen: readonly SourceFile[],\n): number {\n const urls = heldUrls(held ?? []);\n const before = urls.size;\n for (const file of chosen) urls.add(file.url);\n return urls.size - before;\n}\n\n/**\n * How many files a list may still take from a source: its bound less the files\n * it holds, since `addChosenFiles` writes into its empty rows before adding\n * any. `undefined` when the list has no bound.\n */\nexport function roomForChosenFiles(\n held: readonly unknown[] | undefined,\n maxItemCount: number | undefined,\n): number | undefined {\n if (maxItemCount === undefined) return undefined;\n const files = (held ?? []).filter((item) => heldUrl(item) !== undefined).length;\n return Math.max(0, maxItemCount - files);\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readHtmlContent, readImageContent, readDocumentContent, isNativeHtmlNode } from './chunk-
|
|
1
|
+
import { readHtmlContent, readImageContent, readDocumentContent, isNativeHtmlNode } from './chunk-JSPF4BQP.js';
|
|
2
2
|
import { ownProp } from './chunk-V3OV2XQT.js';
|
|
3
3
|
|
|
4
4
|
// src/core/stuff-files.ts
|
|
@@ -63,5 +63,5 @@ function unwrapContent(field, value) {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
export { collectStuffFiles, readStuffFile };
|
|
66
|
-
//# sourceMappingURL=chunk-
|
|
67
|
-
//# sourceMappingURL=chunk-
|
|
66
|
+
//# sourceMappingURL=chunk-QINLJ5RM.js.map
|
|
67
|
+
//# sourceMappingURL=chunk-QINLJ5RM.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/stuff-files.ts"],"names":["content"],"mappings":"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","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/core/stuff-files.ts"],"names":["content"],"mappings":"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","file":"chunk-QINLJ5RM.js","sourcesContent":["import { ownProp } from './own-property';\nimport {\n isNativeHtmlNode,\n readDocumentContent,\n readHtmlContent,\n readImageContent,\n} from './native-content';\nimport type { RunField } from './descriptor';\n\n/**\n * One file a stuff carries: what to fetch, and what to call it once saved.\n */\nexport interface StuffFile {\n /**\n * The durable reference or URL the value states, for a file held BY\n * REFERENCE. Absent for inline content, which needs no fetch.\n */\n url?: string;\n /**\n * The content itself, for a file the stuff carries INLINE — markup, today.\n * Exactly one of `url` and `text` is set.\n */\n text?: string;\n /** The extension to save inline content under, without the dot. */\n extension?: string;\n /**\n * The URL that works outside this session, when the value carries one. A host\n * whose display URL is session-scoped (an owner-checked proxy route) needs\n * this for anything that leaves the browser.\n */\n publicUrl?: string;\n /** The file's own name when it states one — otherwise the caller derives it. */\n filename?: string;\n mimeType?: string;\n /**\n * Where it sat, dotted, starting at the root's name:\n * `report.attachments.2.scan`. A saved file with no name of its own is named\n * by the base name and the segments after the first (`report-attachments-2-scan`),\n * since the base name stands for the root, so a hand-built path must start at\n * the root's name too, or its first real segment is lost.\n */\n path: string;\n kind: StuffFileKind;\n}\n\n/**\n * What a file is: a picture, a document, or a page of markup the stuff carries\n * inline. It is the descriptor's statement (the node's kind, or its concept for\n * `native.Html`), never a reading of the bytes.\n */\nexport type StuffFileKind = 'image' | 'document' | 'markup';\n\n/**\n * One file value, read as the file it is declared to be — or `undefined` when\n * the value holds nothing to save (no URL, no markup).\n *\n * The walk below calls this for every file node it reaches, and the result view\n * calls it for the one file a control is drawn beside, so a file's own download\n * button and the whole-result download read the value the same way. `kind` is\n * the caller's statement from the descriptor; this never inspects the value to\n * decide what it is.\n */\nexport function readStuffFile(\n kind: StuffFileKind,\n value: unknown,\n path: string,\n): StuffFile | undefined {\n if (kind === 'markup') {\n const content = readHtmlContent(value);\n return content?.innerHtml\n ? { text: content.innerHtml, extension: 'html', path, kind }\n : undefined;\n }\n const content = kind === 'image' ? readImageContent(value) : readDocumentContent(value);\n if (!content?.url) return undefined;\n return {\n url: content.url,\n publicUrl: content.publicUrl,\n filename: content.filename,\n mimeType: content.mimeType,\n path,\n kind,\n };\n}\n\n/**\n * Every file inside a stuff, found by walking the DESCRIPTOR — never the value.\n *\n * The distinction is the whole point. A payload walk would have to decide what\n * a file is by looking at it: an object with a `url`, a string that ends in\n * `.pdf`. That is the guessing this package exists to remove, and it is wrong in\n * both directions — a method whose output legitimately has a `url` field of its\n * own is not a document, and a stored image whose reference carries no extension\n * is. The descriptor already states `kind: \"image\"` or `kind: \"document\"`, so\n * the walk reads the declaration and consults the value only for the members\n * that declaration promises.\n *\n * Ordering is the authored one, depth-first, which is the order the rendered\n * view puts them in — so a download of three images numbers them the way the\n * reader saw them.\n */\nexport function collectStuffFiles(field: RunField, value: unknown): StuffFile[] {\n const found: StuffFile[] = [];\n walk(field, value, [], found);\n return found;\n}\n\nfunction walk(field: RunField, raw: unknown, path: string[], out: StuffFile[]): void {\n const value = unwrapContent(field, raw);\n const here = path.length > 0 ? path : [field.name];\n\n // Markup, before the kind switch, exactly as the renderer takes it: a\n // `native.Html` node's KIND is `object` (its content model has two members),\n // so the switch below would walk into it looking for files and find none.\n //\n // It is a file even though nothing stores it as one. The stuff IS a page —\n // the reader is looking at a rendered report — and handing them a JSON\n // envelope with the page inside it as a string is the same mistake as handing\n // them a URL instead of a picture. `isNativeHtmlNode` asks the descriptor\n // whether the concept refines `native.Html`, which is the standard's own way\n // to ask; it never looks at the value to decide.\n if (isNativeHtmlNode(field)) {\n const file = readStuffFile('markup', value, here.join('.'));\n if (file) out.push(file);\n return;\n }\n\n switch (field.kind) {\n case 'image':\n case 'document': {\n const file = readStuffFile(field.kind, value, here.join('.'));\n if (file) out.push(file);\n return;\n }\n case 'object': {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return;\n const record = value as Record<string, unknown>;\n for (const child of field.fields) {\n walk(child, ownProp(record, child.name), [...here, child.name], out);\n }\n return;\n }\n case 'list': {\n if (!Array.isArray(value)) return;\n // The element descriptor's own `name` is unused by the standard, so the\n // index is what identifies an entry — the same thing the rendered list\n // shows beside each row.\n value.forEach((entry, index) => walk(field.item, entry, [...here, String(index)], out));\n return;\n }\n default:\n // Every other kind is a scalar. It cannot contain a file, and a `native`\n // node with no declared members (an `unknown` kind — a composite, say)\n // states nothing a walk could follow, so there is nothing to look at.\n return;\n }\n}\n\n/**\n * The one unwrap path, matching the renderer's: a content model is opened by\n * the property the schema named, and by nothing else.\n */\nfunction unwrapContent(field: RunField, value: unknown): unknown {\n if (!field.contentKey) return value;\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return value;\n const unwrapped = ownProp(value as Record<string, unknown>, field.contentKey);\n return unwrapped === undefined ? value : unwrapped;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { collectStuffFiles } from './chunk-
|
|
2
|
-
import { viewableUrl, readDataUrl, dataUrlExtensions } from './chunk-
|
|
1
|
+
import { collectStuffFiles } from './chunk-QINLJ5RM.js';
|
|
2
|
+
import { viewableUrl, readDataUrl, dataUrlExtensions } from './chunk-JSPF4BQP.js';
|
|
3
3
|
|
|
4
4
|
// src/core/save-plan.ts
|
|
5
5
|
function planStuffSave(field, value, options) {
|
|
@@ -136,5 +136,5 @@ function jsonCopy(value) {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
export { planFileSave, planStuffSave, splitFileName, typedFileStem };
|
|
139
|
-
//# sourceMappingURL=chunk-
|
|
140
|
-
//# sourceMappingURL=chunk-
|
|
139
|
+
//# sourceMappingURL=chunk-QWHUUMSB.js.map
|
|
140
|
+
//# sourceMappingURL=chunk-QWHUUMSB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/save-plan.ts"],"names":["extension"],"mappings":"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","file":"chunk-ICUEHNEH.js","sourcesContent":["import { dataUrlExtensions, readDataUrl, viewableUrl } from './native-content';\nimport { collectStuffFiles, type StuffFile, type StuffFileKind } from './stuff-files';\nimport type { RunField } from './descriptor';\n\n/**\n * What saving a result MEANS, decided with no DOM: which files, what each is\n * called, what type it is, and where its bytes are.\n *\n * ## Why the plan is separate from the delivery\n *\n * Handing bytes to a reader is the part that depends on where the view runs.\n * An ordinary browser tab saves through an object URL and a clicked link; a\n * view inside a sandboxed frame is refused all of that and has to ask its host\n * to do it, typically by passing links and inline contents across a bridge that\n * fetches the links itself. What to save is the same answer in both places, so\n * it is computed once, here, and a delivery only has to carry it out. The\n * default browser delivery lives in `./react`; a host supplies its own through\n * `ResultEnvProvider`'s `saveFiles`. See docs/result-view.md § \"Saving a\n * result\".\n *\n * ## Why a planned file carries a URL rather than bytes\n *\n * A host's download bridge takes links and fetches them itself, which is also\n * what keeps a cross-origin fetch out of a frame that cannot make one. So a\n * stored file is planned as the URL the gate admitted, and only the default\n * browser delivery fetches it. Content the stuff carries inline (the JSON copy\n * of the data, an HTML page) is planned as its text.\n */\n\n/** What a planned file is: one of the stuff's own files, or the JSON copy of its data. */\nexport type SaveFileKind = StuffFileKind | 'data';\n\ninterface SaveFileCommon {\n /**\n * What to save it as: a bare file name, never a path. The file's own\n * `filename` when it states one, else the base name and the file's place\n * below the result's root (`report-figures-0-image.png`), or the base name\n * alone for a file that is the whole result (`output.png`). No two files in\n * one plan share a name, compared without case.\n */\n name: string;\n /**\n * The media type. For a `data:` URL it is the type the gate admitted; for any\n * other URL it is what the payload states, or what the name's extension\n * implies, or `application/octet-stream` when nothing says.\n */\n mimeType: string;\n kind: SaveFileKind;\n /** Where it sat in the result, dotted (`output.figures.0.image`); the root's name for the JSON copy. */\n path: string;\n}\n\n/**\n * One file to hand to the reader: exactly one of `url` and `text` is set.\n *\n * `url` is the string the URL gate returned, after the host's resolver was\n * asked first, so a delivery never acts on a member nothing judged. It may be a\n * root-relative path, which a planner with no document cannot resolve; the\n * result view makes one absolute against its own document before a delivery\n * sees it. `text` is content the result carries inline.\n */\nexport type SaveFile =\n | (SaveFileCommon & { url: string; text?: undefined })\n | (SaveFileCommon & { text: string; url?: undefined });\n\n/** A file the result holds that cannot be saved, because no URL the gate admits was found for it. */\nexport interface UnavailableFile {\n /** What it would have been saved as, so the reader can be told which one. */\n name: string;\n kind: StuffFileKind;\n path: string;\n}\n\n/** Everything saving a whole result involves. */\nexport interface SavePlan {\n /** What to deliver, in the order the result shows it, the JSON copy last. */\n files: SaveFile[];\n /**\n * What the result holds and cannot be delivered. The JSON copy still carries\n * each one's reference, so the reader keeps it even without the bytes.\n */\n unavailable: UnavailableFile[];\n}\n\n/** A file a delivery did not hand over, and why when it knows. */\nexport interface SaveFailure {\n file: SaveFile;\n reason?: string;\n}\n\n/**\n * What a delivery reports. Every planned file not listed in `failed` was\n * delivered, so an empty list means everything went out.\n */\nexport interface SaveResult {\n failed: SaveFailure[];\n}\n\n/**\n * How files reach the reader. The default saves them in the browser; a host\n * whose view runs in a sandboxed frame supplies one that asks the host to.\n *\n * It resolves rather than rejects when a file does not go out, and names that\n * file in `failed`, so the control that asked can tell the reader. A throw or\n * a rejection is read as every file having failed.\n */\nexport type SaveFiles = (files: readonly SaveFile[]) => Promise<SaveResult>;\n\nexport interface SavePlanOptions {\n /**\n * Names the whole stuff: the JSON copy is `<baseName>.json`, a file with no\n * name of its own below the root is `<baseName>-<place>`, and a file that is\n * the whole stuff is `<baseName>.<ext>`.\n */\n baseName: string;\n /** The same resolver the result view paints through, asked before the payload's own URLs. */\n resolveUrl?: (url: string) => string | undefined;\n}\n\n/**\n * Everything a stuff contains, planned for saving.\n *\n * The data goes down as JSON, and any image, document or HTML page inside it\n * goes down as ITSELF: a JSON file holding a URL to a picture is not the\n * picture, and a reader who saves a report with three attachments wants the\n * three attachments.\n *\n * The JSON copy is planned whenever the stuff is anything more than one file. A\n * result that IS one image has nothing left over once the image is saved, so\n * `{\"url\": …}` beside it would be a second file saying less than the first. That\n * holds only when the image can be saved: a bare file the gate refuses leaves\n * the JSON copy as the one thing the reader gets, because it still carries the\n * reference.\n */\nexport function planStuffSave(field: RunField, value: unknown, options: SavePlanOptions): SavePlan {\n const found = collectStuffFiles(field, value);\n const files: SaveFile[] = [];\n const unavailable: UnavailableFile[] = [];\n for (const file of found) {\n const planned = planFileSave(file, options);\n if (planned) files.push(planned);\n else\n unavailable.push({ name: nameFor(file, options.baseName), kind: file.kind, path: file.path });\n }\n\n // A stuff that is nothing BUT one file, read from the collector rather than\n // from `field.kind`: a `native.Html` node's kind is `object`, and the whole\n // stuff is still the page.\n const isBareFile = found.length === 1 && found[0]?.path === field.name;\n if (isBareFile && files.length === 1) return { files, unavailable };\n\n const jsonName = `${safeName(options.baseName) || 'result'}.json`;\n return {\n files: [\n ...distinctNames(files, jsonName),\n {\n name: jsonName,\n mimeType: 'application/json',\n kind: 'data',\n path: field.name,\n text: jsonCopy(value),\n },\n ],\n unavailable,\n };\n}\n\n/**\n * The plan's files with no two sharing a name, and none taking the JSON copy's.\n *\n * A name derived from a file's place is unique by construction, but a name the\n * payload states is not: two documents a method wrote as `scan.pdf`, or one it\n * called `report.json` beside the JSON copy of `report`. A browser suffixes a\n * duplicate download itself, but a host's delivery may write the names as given,\n * into a folder or an archive, where the second file silently replaces the\n * first. So the first file keeps its name and each later one gets a number\n * before its extension (`scan-2.pdf`), compared without case, as the file\n * systems readers mostly use compare them.\n *\n * That is the whole plan's concern: a file's own button saves one file, which\n * collides with nothing, under its own name.\n */\nfunction distinctNames(files: readonly SaveFile[], reserved: string): SaveFile[] {\n const taken = new Set([reserved.toLowerCase()]);\n return files.map((file) => {\n let name = file.name;\n for (let count = 2; taken.has(name.toLowerCase()); count += 1) {\n name = numbered(file.name, count);\n }\n taken.add(name.toLowerCase());\n return name === file.name ? file : { ...file, name };\n });\n}\n\n/** `scan.pdf` as `scan-2.pdf`: the number before the extension, so the type still reads. */\nfunction numbered(name: string, count: number): string {\n const extension = extensionOf(name);\n return extension\n ? `${name.slice(0, -(extension.length + 1))}-${count}.${name.slice(-extension.length)}`\n : `${name}-${count}`;\n}\n\n/**\n * One file, planned on its own — what a file's own download button saves.\n *\n * The file's `path` starts at the root's name, as `collectStuffFiles` builds\n * it: the name leaves that first segment out, because the base name already\n * stands for the root.\n *\n * `undefined` when the file cannot be saved: a stored reference the host's\n * resolver does not answer and no URL the gate admits beside it. The button is\n * not drawn then, so a reader is never offered a download that cannot happen.\n */\nexport function planFileSave(file: StuffFile, options: SavePlanOptions): SaveFile | undefined {\n const common = { kind: file.kind, path: file.path };\n if (file.text !== undefined) {\n return {\n ...common,\n name: nameFor(file, options.baseName),\n mimeType: 'text/html',\n text: file.text,\n };\n }\n // Judged by the same gate the result view paints through, in the same\n // durability order: the host's resolver over the durable reference first,\n // then `public_url`, then the reference itself. What the gate returns is what\n // is planned, never the raw member.\n const url =\n viewableUrl(options.resolveUrl?.(file.url ?? '')) ??\n viewableUrl(file.publicUrl) ??\n viewableUrl(file.url);\n if (!url) return undefined;\n const encoded = readDataUrl(url);\n if (encoded) {\n // A `data:` URL is its own file, and the gate admitted it for its declared\n // type alone. That type names it: the payload's `filename` and the tail of\n // the payload are both the payload's say, and a `data:image/png` URL saved\n // under `image.html` is a page that runs when the reader opens it.\n return {\n ...common,\n name: nameFor(file, options.baseName, dataUrlExtensions(encoded.mediaType)),\n mimeType: encoded.mediaType,\n url,\n };\n }\n const name = nameFor(file, options.baseName);\n return { ...common, name, mimeType: file.mimeType ?? typeForName(name), url };\n}\n\n/** The type a name's extension implies, for a stored file whose payload states none. */\nconst TYPE_FOR_EXTENSION: Readonly<Record<string, string>> = {\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n webp: 'image/webp',\n avif: 'image/avif',\n svg: 'image/svg+xml',\n pdf: 'application/pdf',\n html: 'text/html',\n};\n\nfunction typeForName(name: string): string {\n const extension = name.match(/\\.([A-Za-z0-9]{1,8})$/)?.[1]?.toLowerCase();\n return (extension && TYPE_FOR_EXTENSION[extension]) || 'application/octet-stream';\n}\n\n/**\n * What a saved file is called.\n *\n * The file's own `filename` wins when it has one: it is the name the producer\n * chose and the reader recognises. Otherwise the base name and the file's place\n * below the root name it (`report-attachments-2`), which is unlovely but\n * unambiguous, since two images from one result must not both land as\n * `image.png` and overwrite each other in the download folder.\n *\n * The path's first segment is left out because it is always the root's name,\n * and the base name already stands for the root, as it does in `<base>.json`:\n * keeping it would save the one image a pipe outputs as `output-output.png`. A\n * file that IS the root has no place below it and is named by the base name\n * alone. Every segment is a field's name or an index, neither of which holds a\n * dot, so splitting on dots recovers them.\n *\n * `allowed` is set for a `data:` URL, whose admitted type is the only thing\n * allowed to decide the extension: a name carrying one of those extensions\n * keeps it, and any other extension is replaced by the type's own.\n */\nfunction nameFor(file: StuffFile, base: string, allowed?: readonly string[]): string {\n const own = file.filename ? safeName(file.filename) : '';\n const place = file.path.split('.').slice(1).join('-');\n const named = safeName(base) || 'result';\n const stem = own || (place ? `${named}-${place}` : named);\n const stated = own ? extensionOf(own) : '';\n if (allowed) {\n if (stated && allowed.includes(stated)) return stem;\n const bare = stated ? stem.slice(0, -(stated.length + 1)) : stem;\n const extension = allowed[0];\n return extension ? `${bare}.${extension}` : bare;\n }\n if (own) return own;\n const extension = file.extension ?? extensionOf(pathOf(file.url ?? ''));\n return extension ? `${stem}.${extension}` : stem;\n}\n\n/** The extension a name ends in, lowercased, or none. Never guessed from the bytes. */\nfunction extensionOf(name: string): string {\n return name.match(/\\.([A-Za-z0-9]{1,8})$/)?.[1]?.toLowerCase() ?? '';\n}\n\n/** A URL without its query and fragment, so `x.png?sig=…` still ends in `.png`. */\nfunction pathOf(url: string): string {\n return url.split(/[?#]/)[0] ?? url;\n}\n\n/**\n * A name safe to hand a delivery: its last path segment, without control\n * characters, trimmed. A browser sanitises a download name itself, but a host's\n * bridge may write it to disk as given, and a payload's `filename` is the\n * payload's say. Empty when nothing is left.\n */\nfunction safeName(name: string): string {\n const trimmed = (printable(name).split(/[/\\\\]/).pop() ?? '').trim();\n return trimmed === '.' || trimmed === '..' ? '' : trimmed;\n}\n\n/** The name without its control characters, which no file system wants in a name. */\nfunction printable(name: string): string {\n return Array.from(name)\n .filter((character) => {\n const code = character.charCodeAt(0);\n return code > 0x1f && code !== 0x7f;\n })\n .join('');\n}\n\n/**\n * A planned name split at its extension, the way the plan reads one:\n * `devis.pdf` is `devis` and `.pdf`, `report.final.html` is `report.final` and\n * `.html`, and a name with no extension of one to eight letters and digits is\n * all stem. The extension keeps its dot, so a name rebuilt from the two halves\n * is the name.\n */\nexport function splitFileName(name: string): { stem: string; extension: string } {\n const extension = name.match(/\\.[A-Za-z0-9]{1,8}$/)?.[0] ?? '';\n return extension && extension.length < name.length\n ? { stem: name.slice(0, -extension.length), extension }\n : { stem: name, extension: '' };\n}\n\n/**\n * The name a reader typed for a file, made safe the way a planned name is, and\n * a little stricter, since this one is typed rather than produced.\n *\n * Control characters go, as from every planned name. A path separator is\n * REPLACED rather than cut at: a planned name keeps its last path segment\n * because a payload's `filename` may be a path, but a reader who types\n * `Devis 12/2026` means a name, and keeping `2026` alone would throw away what\n * they wrote. The characters a common file system refuses in a name\n * (`: * ? \" < > |`) are replaced the same way, with a hyphen, because a host's\n * bridge may write the name to disk as given. Leading dots go, so the file is\n * not hidden, and trailing dots and spaces, which one file system drops\n * silently. A copy of the extension the reader typed at the end is dropped,\n * since the extension is added back after it: `devis.pdf` stays `devis.pdf`\n * rather than becoming `devis.pdf.pdf`.\n *\n * Empty when nothing is left, which the caller reads as \"keep the planned name\".\n */\nexport function typedFileStem(typed: string, extension: string): string {\n let stem = printable(typed)\n .replace(/[/\\\\:*?\"<>|]/g, '-')\n .trim();\n if (extension && stem.toLowerCase().endsWith(extension.toLowerCase())) {\n stem = stem.slice(0, -extension.length);\n }\n return stem\n .replace(/^[.\\s]+/, '')\n .replace(/[.\\s]+$/, '')\n .trim();\n}\n\n/**\n * The data as JSON, the way the JSON view shows it. A BigInt, which a JSON\n * parser configured to produce one can hand over, is written as its digits\n * rather than failing the whole save.\n */\nfunction jsonCopy(value: unknown): string {\n const text = JSON.stringify(\n value,\n (_key, member: unknown) => (typeof member === 'bigint' ? member.toString() : member),\n 2,\n );\n return text ?? 'null';\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/save-plan.ts"],"names":["extension"],"mappings":"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","file":"chunk-QWHUUMSB.js","sourcesContent":["import { dataUrlExtensions, readDataUrl, viewableUrl } from './native-content';\nimport { collectStuffFiles, type StuffFile, type StuffFileKind } from './stuff-files';\nimport type { RunField } from './descriptor';\n\n/**\n * What saving a result MEANS, decided with no DOM: which files, what each is\n * called, what type it is, and where its bytes are.\n *\n * ## Why the plan is separate from the delivery\n *\n * Handing bytes to a reader is the part that depends on where the view runs.\n * An ordinary browser tab saves through an object URL and a clicked link; a\n * view inside a sandboxed frame is refused all of that and has to ask its host\n * to do it, typically by passing links and inline contents across a bridge that\n * fetches the links itself. What to save is the same answer in both places, so\n * it is computed once, here, and a delivery only has to carry it out. The\n * default browser delivery lives in `./react`; a host supplies its own through\n * `ResultEnvProvider`'s `saveFiles`. See docs/result-view.md § \"Saving a\n * result\".\n *\n * ## Why a planned file carries a URL rather than bytes\n *\n * A host's download bridge takes links and fetches them itself, which is also\n * what keeps a cross-origin fetch out of a frame that cannot make one. So a\n * stored file is planned as the URL the gate admitted, and only the default\n * browser delivery fetches it. Content the stuff carries inline (the JSON copy\n * of the data, an HTML page) is planned as its text.\n */\n\n/** What a planned file is: one of the stuff's own files, or the JSON copy of its data. */\nexport type SaveFileKind = StuffFileKind | 'data';\n\ninterface SaveFileCommon {\n /**\n * What to save it as: a bare file name, never a path. The file's own\n * `filename` when it states one, else the base name and the file's place\n * below the result's root (`report-figures-0-image.png`), or the base name\n * alone for a file that is the whole result (`output.png`). No two files in\n * one plan share a name, compared without case.\n */\n name: string;\n /**\n * The media type. For a `data:` URL it is the type the gate admitted; for any\n * other URL it is what the payload states, or what the name's extension\n * implies, or `application/octet-stream` when nothing says.\n */\n mimeType: string;\n kind: SaveFileKind;\n /** Where it sat in the result, dotted (`output.figures.0.image`); the root's name for the JSON copy. */\n path: string;\n}\n\n/**\n * One file to hand to the reader: exactly one of `url` and `text` is set.\n *\n * `url` is the string the URL gate returned, after the host's resolver was\n * asked first, so a delivery never acts on a member nothing judged. It may be a\n * root-relative path, which a planner with no document cannot resolve; the\n * result view makes one absolute against its own document before a delivery\n * sees it. `text` is content the result carries inline.\n */\nexport type SaveFile =\n | (SaveFileCommon & { url: string; text?: undefined })\n | (SaveFileCommon & { text: string; url?: undefined });\n\n/** A file the result holds that cannot be saved, because no URL the gate admits was found for it. */\nexport interface UnavailableFile {\n /** What it would have been saved as, so the reader can be told which one. */\n name: string;\n kind: StuffFileKind;\n path: string;\n}\n\n/** Everything saving a whole result involves. */\nexport interface SavePlan {\n /** What to deliver, in the order the result shows it, the JSON copy last. */\n files: SaveFile[];\n /**\n * What the result holds and cannot be delivered. The JSON copy still carries\n * each one's reference, so the reader keeps it even without the bytes.\n */\n unavailable: UnavailableFile[];\n}\n\n/** A file a delivery did not hand over, and why when it knows. */\nexport interface SaveFailure {\n file: SaveFile;\n reason?: string;\n}\n\n/**\n * What a delivery reports. Every planned file not listed in `failed` was\n * delivered, so an empty list means everything went out.\n */\nexport interface SaveResult {\n failed: SaveFailure[];\n}\n\n/**\n * How files reach the reader. The default saves them in the browser; a host\n * whose view runs in a sandboxed frame supplies one that asks the host to.\n *\n * It resolves rather than rejects when a file does not go out, and names that\n * file in `failed`, so the control that asked can tell the reader. A throw or\n * a rejection is read as every file having failed.\n */\nexport type SaveFiles = (files: readonly SaveFile[]) => Promise<SaveResult>;\n\nexport interface SavePlanOptions {\n /**\n * Names the whole stuff: the JSON copy is `<baseName>.json`, a file with no\n * name of its own below the root is `<baseName>-<place>`, and a file that is\n * the whole stuff is `<baseName>.<ext>`.\n */\n baseName: string;\n /** The same resolver the result view paints through, asked before the payload's own URLs. */\n resolveUrl?: (url: string) => string | undefined;\n}\n\n/**\n * Everything a stuff contains, planned for saving.\n *\n * The data goes down as JSON, and any image, document or HTML page inside it\n * goes down as ITSELF: a JSON file holding a URL to a picture is not the\n * picture, and a reader who saves a report with three attachments wants the\n * three attachments.\n *\n * The JSON copy is planned whenever the stuff is anything more than one file. A\n * result that IS one image has nothing left over once the image is saved, so\n * `{\"url\": …}` beside it would be a second file saying less than the first. That\n * holds only when the image can be saved: a bare file the gate refuses leaves\n * the JSON copy as the one thing the reader gets, because it still carries the\n * reference.\n */\nexport function planStuffSave(field: RunField, value: unknown, options: SavePlanOptions): SavePlan {\n const found = collectStuffFiles(field, value);\n const files: SaveFile[] = [];\n const unavailable: UnavailableFile[] = [];\n for (const file of found) {\n const planned = planFileSave(file, options);\n if (planned) files.push(planned);\n else\n unavailable.push({ name: nameFor(file, options.baseName), kind: file.kind, path: file.path });\n }\n\n // A stuff that is nothing BUT one file, read from the collector rather than\n // from `field.kind`: a `native.Html` node's kind is `object`, and the whole\n // stuff is still the page.\n const isBareFile = found.length === 1 && found[0]?.path === field.name;\n if (isBareFile && files.length === 1) return { files, unavailable };\n\n const jsonName = `${safeName(options.baseName) || 'result'}.json`;\n return {\n files: [\n ...distinctNames(files, jsonName),\n {\n name: jsonName,\n mimeType: 'application/json',\n kind: 'data',\n path: field.name,\n text: jsonCopy(value),\n },\n ],\n unavailable,\n };\n}\n\n/**\n * The plan's files with no two sharing a name, and none taking the JSON copy's.\n *\n * A name derived from a file's place is unique by construction, but a name the\n * payload states is not: two documents a method wrote as `scan.pdf`, or one it\n * called `report.json` beside the JSON copy of `report`. A browser suffixes a\n * duplicate download itself, but a host's delivery may write the names as given,\n * into a folder or an archive, where the second file silently replaces the\n * first. So the first file keeps its name and each later one gets a number\n * before its extension (`scan-2.pdf`), compared without case, as the file\n * systems readers mostly use compare them.\n *\n * That is the whole plan's concern: a file's own button saves one file, which\n * collides with nothing, under its own name.\n */\nfunction distinctNames(files: readonly SaveFile[], reserved: string): SaveFile[] {\n const taken = new Set([reserved.toLowerCase()]);\n return files.map((file) => {\n let name = file.name;\n for (let count = 2; taken.has(name.toLowerCase()); count += 1) {\n name = numbered(file.name, count);\n }\n taken.add(name.toLowerCase());\n return name === file.name ? file : { ...file, name };\n });\n}\n\n/** `scan.pdf` as `scan-2.pdf`: the number before the extension, so the type still reads. */\nfunction numbered(name: string, count: number): string {\n const extension = extensionOf(name);\n return extension\n ? `${name.slice(0, -(extension.length + 1))}-${count}.${name.slice(-extension.length)}`\n : `${name}-${count}`;\n}\n\n/**\n * One file, planned on its own — what a file's own download button saves.\n *\n * The file's `path` starts at the root's name, as `collectStuffFiles` builds\n * it: the name leaves that first segment out, because the base name already\n * stands for the root.\n *\n * `undefined` when the file cannot be saved: a stored reference the host's\n * resolver does not answer and no URL the gate admits beside it. The button is\n * not drawn then, so a reader is never offered a download that cannot happen.\n */\nexport function planFileSave(file: StuffFile, options: SavePlanOptions): SaveFile | undefined {\n const common = { kind: file.kind, path: file.path };\n if (file.text !== undefined) {\n return {\n ...common,\n name: nameFor(file, options.baseName),\n mimeType: 'text/html',\n text: file.text,\n };\n }\n // Judged by the same gate the result view paints through, in the same\n // durability order: the host's resolver over the durable reference first,\n // then `public_url`, then the reference itself. What the gate returns is what\n // is planned, never the raw member.\n const url =\n viewableUrl(options.resolveUrl?.(file.url ?? '')) ??\n viewableUrl(file.publicUrl) ??\n viewableUrl(file.url);\n if (!url) return undefined;\n const encoded = readDataUrl(url);\n if (encoded) {\n // A `data:` URL is its own file, and the gate admitted it for its declared\n // type alone. That type names it: the payload's `filename` and the tail of\n // the payload are both the payload's say, and a `data:image/png` URL saved\n // under `image.html` is a page that runs when the reader opens it.\n return {\n ...common,\n name: nameFor(file, options.baseName, dataUrlExtensions(encoded.mediaType)),\n mimeType: encoded.mediaType,\n url,\n };\n }\n const name = nameFor(file, options.baseName);\n return { ...common, name, mimeType: file.mimeType ?? typeForName(name), url };\n}\n\n/** The type a name's extension implies, for a stored file whose payload states none. */\nconst TYPE_FOR_EXTENSION: Readonly<Record<string, string>> = {\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n gif: 'image/gif',\n webp: 'image/webp',\n avif: 'image/avif',\n svg: 'image/svg+xml',\n pdf: 'application/pdf',\n html: 'text/html',\n};\n\nfunction typeForName(name: string): string {\n const extension = name.match(/\\.([A-Za-z0-9]{1,8})$/)?.[1]?.toLowerCase();\n return (extension && TYPE_FOR_EXTENSION[extension]) || 'application/octet-stream';\n}\n\n/**\n * What a saved file is called.\n *\n * The file's own `filename` wins when it has one: it is the name the producer\n * chose and the reader recognises. Otherwise the base name and the file's place\n * below the root name it (`report-attachments-2`), which is unlovely but\n * unambiguous, since two images from one result must not both land as\n * `image.png` and overwrite each other in the download folder.\n *\n * The path's first segment is left out because it is always the root's name,\n * and the base name already stands for the root, as it does in `<base>.json`:\n * keeping it would save the one image a pipe outputs as `output-output.png`. A\n * file that IS the root has no place below it and is named by the base name\n * alone. Every segment is a field's name or an index, neither of which holds a\n * dot, so splitting on dots recovers them.\n *\n * `allowed` is set for a `data:` URL, whose admitted type is the only thing\n * allowed to decide the extension: a name carrying one of those extensions\n * keeps it, and any other extension is replaced by the type's own.\n */\nfunction nameFor(file: StuffFile, base: string, allowed?: readonly string[]): string {\n const own = file.filename ? safeName(file.filename) : '';\n const place = file.path.split('.').slice(1).join('-');\n const named = safeName(base) || 'result';\n const stem = own || (place ? `${named}-${place}` : named);\n const stated = own ? extensionOf(own) : '';\n if (allowed) {\n if (stated && allowed.includes(stated)) return stem;\n const bare = stated ? stem.slice(0, -(stated.length + 1)) : stem;\n const extension = allowed[0];\n return extension ? `${bare}.${extension}` : bare;\n }\n if (own) return own;\n const extension = file.extension ?? extensionOf(pathOf(file.url ?? ''));\n return extension ? `${stem}.${extension}` : stem;\n}\n\n/** The extension a name ends in, lowercased, or none. Never guessed from the bytes. */\nfunction extensionOf(name: string): string {\n return name.match(/\\.([A-Za-z0-9]{1,8})$/)?.[1]?.toLowerCase() ?? '';\n}\n\n/** A URL without its query and fragment, so `x.png?sig=…` still ends in `.png`. */\nfunction pathOf(url: string): string {\n return url.split(/[?#]/)[0] ?? url;\n}\n\n/**\n * A name safe to hand a delivery: its last path segment, without control\n * characters, trimmed. A browser sanitises a download name itself, but a host's\n * bridge may write it to disk as given, and a payload's `filename` is the\n * payload's say. Empty when nothing is left.\n */\nfunction safeName(name: string): string {\n const trimmed = (printable(name).split(/[/\\\\]/).pop() ?? '').trim();\n return trimmed === '.' || trimmed === '..' ? '' : trimmed;\n}\n\n/** The name without its control characters, which no file system wants in a name. */\nfunction printable(name: string): string {\n return Array.from(name)\n .filter((character) => {\n const code = character.charCodeAt(0);\n return code > 0x1f && code !== 0x7f;\n })\n .join('');\n}\n\n/**\n * A planned name split at its extension, the way the plan reads one:\n * `devis.pdf` is `devis` and `.pdf`, `report.final.html` is `report.final` and\n * `.html`, and a name with no extension of one to eight letters and digits is\n * all stem. The extension keeps its dot, so a name rebuilt from the two halves\n * is the name.\n */\nexport function splitFileName(name: string): { stem: string; extension: string } {\n const extension = name.match(/\\.[A-Za-z0-9]{1,8}$/)?.[0] ?? '';\n return extension && extension.length < name.length\n ? { stem: name.slice(0, -extension.length), extension }\n : { stem: name, extension: '' };\n}\n\n/**\n * The name a reader typed for a file, made safe the way a planned name is, and\n * a little stricter, since this one is typed rather than produced.\n *\n * Control characters go, as from every planned name. A path separator is\n * REPLACED rather than cut at: a planned name keeps its last path segment\n * because a payload's `filename` may be a path, but a reader who types\n * `Devis 12/2026` means a name, and keeping `2026` alone would throw away what\n * they wrote. The characters a common file system refuses in a name\n * (`: * ? \" < > |`) are replaced the same way, with a hyphen, because a host's\n * bridge may write the name to disk as given. Leading dots go, so the file is\n * not hidden, and trailing dots and spaces, which one file system drops\n * silently. A copy of the extension the reader typed at the end is dropped,\n * since the extension is added back after it: `devis.pdf` stays `devis.pdf`\n * rather than becoming `devis.pdf.pdf`.\n *\n * Empty when nothing is left, which the caller reads as \"keep the planned name\".\n */\nexport function typedFileStem(typed: string, extension: string): string {\n let stem = printable(typed)\n .replace(/[/\\\\:*?\"<>|]/g, '-')\n .trim();\n if (extension && stem.toLowerCase().endsWith(extension.toLowerCase())) {\n stem = stem.slice(0, -extension.length);\n }\n return stem\n .replace(/^[.\\s]+/, '')\n .replace(/[.\\s]+$/, '')\n .trim();\n}\n\n/**\n * The data as JSON, the way the JSON view shows it. A BigInt, which a JSON\n * parser configured to produce one can hand over, is written as its digits\n * rather than failing the whole save.\n */\nfunction jsonCopy(value: unknown): string {\n const text = JSON.stringify(\n value,\n (_key, member: unknown) => (typeof member === 'bigint' ? member.toString() : member),\n 2,\n );\n return text ?? 'null';\n}\n"]}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { StuffFile, StuffFileKind, collectStuffFiles } from './stuff-files.js';
|
|
|
6
6
|
export { SaveFailure, SaveFile, SaveFileKind, SaveFiles, SavePlan, SavePlanOptions, SaveResult, UnavailableFile, planFileSave, planStuffSave } from './save-plan.js';
|
|
7
7
|
export { DOCUMENT_FORMATS, FileFormat, IMAGE_FORMATS, acceptLabel, acceptMap, formatsForKind, isAcceptedFile } from './file-formats.js';
|
|
8
8
|
export { narrowFileFormats } from './narrow-file-formats.js';
|
|
9
|
-
export { CompositeMember, DataUrlView, DateContentView, DocumentContentView, HtmlContentView, ImageContentView, NATIVE_COMPOSITE_CONCEPT_REF, NATIVE_DATE_CONCEPT_REF, NATIVE_HTML_CONCEPT_REF, TYPED_SCALAR_MARKERS, formatDateContent, hasTypedScalarMarkers, isNativeCompositeNode, isNativeDateNode, isNativeHtmlNode, isViewableUrl, readCompositeContent, readDataUrl, readDateContent, readDocumentContent, readHtmlContent, readImageContent, viewableUrl } from './native-content.js';
|
|
9
|
+
export { ChoiceContentView, CompositeMember, DataUrlView, DateContentView, DocumentContentView, HtmlContentView, ImageContentView, NATIVE_CHOICE_CONCEPT_REF, NATIVE_COMPOSITE_CONCEPT_REF, NATIVE_DATE_CONCEPT_REF, NATIVE_HTML_CONCEPT_REF, NATIVE_PAGE_CONCEPT_REF, NATIVE_RATING_CONCEPT_REF, NATIVE_YES_NO_CONCEPT_REF, PageContentView, RatingContentView, TYPED_SCALAR_MARKERS, YesNoContentView, formatDateContent, hasTypedScalarMarkers, isNativeCompositeNode, isNativeDateNode, isNativeHtmlNode, isNativePageNode, isViewableUrl, nativeVerdictOf, readChoiceContent, readCompositeContent, readDataUrl, readDateContent, readDocumentContent, readHtmlContent, readImageContent, readPageContent, readRatingContent, readYesNoContent, viewableUrl } from './native-content.js';
|
|
10
10
|
export { Readiness, anyOptionalStructureOpen, computeReadiness, fieldFilled, foldsBehindOptionalDisclosure, isFilled, isFoldedOptional, isOptionalStructure, mustBeFilled, optionalStructureOpen, shownAsOptional } from './readiness.js';
|
|
11
11
|
export { closeOptionalStructures, openOptionalStructures, seedInputs, seedObjectValue } from './seed.js';
|
|
12
12
|
export { InputPresence, buildPipeRef, getPipeIOContract, inputMustBeFilled, isFixedCountInput, isOptionalInput, isPluralInput } from './contracts.js';
|
package/dist/core/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { planFileSave, planStuffSave } from '../chunk-
|
|
1
|
+
export { planFileSave, planStuffSave } from '../chunk-QWHUUMSB.js';
|
|
2
2
|
export { closeOptionalStructures, openOptionalStructures, seedInputs, seedObjectValue } from '../chunk-VH5CDQDR.js';
|
|
3
|
-
export { addChosenFiles, chosenFilesAdded, roomForChosenFiles, sourceFileValue } from '../chunk-
|
|
4
|
-
export { collectStuffFiles } from '../chunk-
|
|
3
|
+
export { addChosenFiles, chosenFilesAdded, roomForChosenFiles, sourceFileValue } from '../chunk-NSHGLM6A.js';
|
|
4
|
+
export { collectStuffFiles } from '../chunk-QINLJ5RM.js';
|
|
5
5
|
export { describeValidationError, displayValue, valueAtProperty } from '../chunk-RPA7DNSK.js';
|
|
6
6
|
export { apiInputsFromRunValues, fieldsForContract, inputDataFromWorkingMemory, outputsFromPipeOutput, rjsfDataFromRunValues, runValuesFromInputs, runValuesFromStore, sameRunValues, setValueAtPath, storeInputDataFromRunValues } from '../chunk-ZX52CQJ4.js';
|
|
7
7
|
export { narrowFileFormats } from '../chunk-CAKQ5VFT.js';
|
|
8
|
-
export { NATIVE_COMPOSITE_CONCEPT_REF, NATIVE_DATE_CONCEPT_REF, NATIVE_HTML_CONCEPT_REF, TYPED_SCALAR_MARKERS, formatDateContent, hasTypedScalarMarkers, isNativeCompositeNode, isNativeDateNode, isNativeHtmlNode, isViewableUrl, readCompositeContent, readDataUrl, readDateContent, readDocumentContent, readHtmlContent, readImageContent, viewableUrl } from '../chunk-
|
|
8
|
+
export { NATIVE_CHOICE_CONCEPT_REF, NATIVE_COMPOSITE_CONCEPT_REF, NATIVE_DATE_CONCEPT_REF, NATIVE_HTML_CONCEPT_REF, NATIVE_PAGE_CONCEPT_REF, NATIVE_RATING_CONCEPT_REF, NATIVE_YES_NO_CONCEPT_REF, TYPED_SCALAR_MARKERS, formatDateContent, hasTypedScalarMarkers, isNativeCompositeNode, isNativeDateNode, isNativeHtmlNode, isNativePageNode, isViewableUrl, nativeVerdictOf, readChoiceContent, readCompositeContent, readDataUrl, readDateContent, readDocumentContent, readHtmlContent, readImageContent, readPageContent, readRatingContent, readYesNoContent, viewableUrl } from '../chunk-JSPF4BQP.js';
|
|
9
9
|
export { getPipeOutputForm } from '../chunk-JIGRWJTV.js';
|
|
10
10
|
export { buildResultField, buildRunFields, getPipeInputForm } from '../chunk-ZB4RYUKV.js';
|
|
11
11
|
export { conceptCategory } from '../chunk-FABY3DEY.js';
|
|
@@ -108,6 +108,78 @@ declare function readHtmlContent(value: unknown): HtmlContentView | undefined;
|
|
|
108
108
|
declare const NATIVE_HTML_CONCEPT_REF = "native.Html";
|
|
109
109
|
declare const NATIVE_DATE_CONCEPT_REF = "native.Date";
|
|
110
110
|
declare const NATIVE_COMPOSITE_CONCEPT_REF = "native.Composite";
|
|
111
|
+
declare const NATIVE_PAGE_CONCEPT_REF = "native.Page";
|
|
112
|
+
declare const NATIVE_YES_NO_CONCEPT_REF = "native.YesNo";
|
|
113
|
+
declare const NATIVE_RATING_CONCEPT_REF = "native.Rating";
|
|
114
|
+
declare const NATIVE_CHOICE_CONCEPT_REF = "native.Choice";
|
|
115
|
+
/**
|
|
116
|
+
* `native.Page`, read: what one page of an extracted document holds.
|
|
117
|
+
*
|
|
118
|
+
* The model is `{text_and_images: {text, images, raw_html}, page_view}`, where
|
|
119
|
+
* `text` is a `TextContent` (`{text}`) and the images and the page view are
|
|
120
|
+
* `ImageContent`s. A reader of a page wants its TEXT first, and the structural
|
|
121
|
+
* renderer never reached it: the descriptor states the page as an `object`
|
|
122
|
+
* over two members, and the text sits two levels down, under a member named
|
|
123
|
+
* `text` inside a member named `text_and_images`. Keyed by the concept, this
|
|
124
|
+
* reads the documented model and nothing else.
|
|
125
|
+
*/
|
|
126
|
+
interface PageContentView {
|
|
127
|
+
/** The page's extracted text, as the extractor wrote it, when it wrote any. */
|
|
128
|
+
text?: string;
|
|
129
|
+
/** The images extracted from the page, each an `ImageContent`, unread. */
|
|
130
|
+
images: readonly unknown[];
|
|
131
|
+
/**
|
|
132
|
+
* The page's markup as the extractor fetched it, when it kept any. It is the
|
|
133
|
+
* page's content a second time when the page has text, and its only content
|
|
134
|
+
* when it has none, which is when a renderer shows it, framed, never injected.
|
|
135
|
+
*/
|
|
136
|
+
rawHtml?: string;
|
|
137
|
+
/** The rendering of the whole page, an `ImageContent`, when one was made. */
|
|
138
|
+
pageView?: unknown;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Read a `native.Page` value. `undefined` for anything that is not a record,
|
|
142
|
+
* so the caller renders its own absence.
|
|
143
|
+
*/
|
|
144
|
+
declare function readPageContent(value: unknown): PageContentView | undefined;
|
|
145
|
+
/** `native.YesNo`, read. */
|
|
146
|
+
interface YesNoContentView {
|
|
147
|
+
/** The answer: yes is `true`. */
|
|
148
|
+
yesNo: boolean;
|
|
149
|
+
/** The probability that the answer is yes, from 0 to 1, when the producer reported one. */
|
|
150
|
+
probability?: number;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Read a `native.YesNo` value: `{yes_no, probability}`, or the bare boolean a
|
|
154
|
+
* single-member YesNo is unwrapped to by its content key. Both are the model
|
|
155
|
+
* the concept states, so reading either is reading the standard.
|
|
156
|
+
*/
|
|
157
|
+
declare function readYesNoContent(value: unknown): YesNoContentView | undefined;
|
|
158
|
+
/** `native.Rating`, read. */
|
|
159
|
+
interface RatingContentView {
|
|
160
|
+
/** The index of the selected level, 0 being the first level declared. */
|
|
161
|
+
level: number;
|
|
162
|
+
/** The name the scale gives the selected level, when it names its levels. */
|
|
163
|
+
label?: string;
|
|
164
|
+
/** The producer's confidence in the level, from 0 to 1, when it reported one. */
|
|
165
|
+
confidence?: number;
|
|
166
|
+
}
|
|
167
|
+
/** Read a `native.Rating` value. `undefined` when it carries no whole `level`. */
|
|
168
|
+
declare function readRatingContent(value: unknown): RatingContentView | undefined;
|
|
169
|
+
/** `native.Choice`, read. */
|
|
170
|
+
interface ChoiceContentView {
|
|
171
|
+
/** The key of the selected option, as the method declared it. */
|
|
172
|
+
choice: string;
|
|
173
|
+
/** The producer's confidence in the choice, from 0 to 1, when it reported one. */
|
|
174
|
+
confidence?: number;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Read a `native.Choice` value. `undefined` when it carries no `choice`, or an
|
|
178
|
+
* empty one: the content model types `choice` as any text, but a choice
|
|
179
|
+
* question's options are keyed by non-empty strings and its `Choice` names one
|
|
180
|
+
* of them, so an empty key names no option and leaves no answer to draw.
|
|
181
|
+
*/
|
|
182
|
+
declare function readChoiceContent(value: unknown): ChoiceContentView | undefined;
|
|
111
183
|
/** One member of a composite: the name it was composed under, and its content. */
|
|
112
184
|
interface CompositeMember {
|
|
113
185
|
name: string;
|
|
@@ -164,15 +236,40 @@ declare function isNativeDateNode(node: NativeNode): boolean;
|
|
|
164
236
|
*/
|
|
165
237
|
declare function isNativeCompositeNode(node: NativeNode): boolean;
|
|
166
238
|
/**
|
|
167
|
-
* Whether a node is
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* node
|
|
239
|
+
* Whether a node is a `native.Page`, or a concept refining it — one page of an
|
|
240
|
+
* extracted document.
|
|
241
|
+
*
|
|
242
|
+
* Its node is an `object` over `{text_and_images, page_view}`, which the
|
|
243
|
+
* structural renderer laid out as a record: in a list, a table whose
|
|
244
|
+
* "Text and images" column was named by the first `text` member it found,
|
|
245
|
+
* `raw_html`, which an extractor leaves empty, so a page holding a whole
|
|
246
|
+
* report read as a row of dashes. Keyed by concept, the result view reads the
|
|
247
|
+
* page's text instead. See `readPageContent`.
|
|
248
|
+
*/
|
|
249
|
+
declare function isNativePageNode(node: NativeNode): boolean;
|
|
250
|
+
/**
|
|
251
|
+
* Whether a node is one of the verdicts a judge returns — a yes or no
|
|
252
|
+
* (`native.YesNo`), a rating (`native.Rating`) or a choice (`native.Choice`),
|
|
253
|
+
* or a concept refining one — and which.
|
|
254
|
+
*
|
|
255
|
+
* Their nodes are `object`s over the verdict and its measures (a `YesNo` from
|
|
256
|
+
* an older runtime, whose model had one member, is a `boolean` node unwrapped
|
|
257
|
+
* by its content key), so the structural renderer printed the measures as a
|
|
258
|
+
* record: "Yes no: Yes / Probability: 1". The concept is what says the record
|
|
259
|
+
* is a verdict, read off `concept_ref` and `refines` like every other native
|
|
260
|
+
* predicate here, never off which keys the value happens to hold.
|
|
261
|
+
*/
|
|
262
|
+
declare function nativeVerdictOf(node: NativeNode): 'yes_no' | 'rating' | 'choice' | undefined;
|
|
263
|
+
/**
|
|
264
|
+
* Whether a node is one of the natives the kind vocabulary cannot name that a
|
|
265
|
+
* list draws one value per line — a date, an HTML page, a composite — which a
|
|
266
|
+
* renderer reads by CONCEPT before it reads the kind. A list of one answers no
|
|
267
|
+
* (the predicates refuse a `list` node), and its item answers yes.
|
|
171
268
|
*
|
|
172
269
|
* One answer, read twice: the result view renders a list whose item answers yes
|
|
173
270
|
* one value per line rather than as a table, and the generative layer delegates
|
|
174
271
|
* that list to the kernel, because no catalog component reads a native value.
|
|
175
|
-
* Not re-exported: a host asks the
|
|
272
|
+
* Not re-exported: a host asks the predicates it needs.
|
|
176
273
|
*/
|
|
177
274
|
declare function isNativeValueNode(node: NativeNode): boolean;
|
|
178
275
|
/** What the native predicates read off a node: its stated kind and its concept. */
|
|
@@ -277,4 +374,4 @@ declare const TYPED_SCALAR_MARKERS: readonly ["__class__", "__module__"];
|
|
|
277
374
|
/** Whether a record carries the typed-scalar markers. Informational. */
|
|
278
375
|
declare function hasTypedScalarMarkers(value: unknown): boolean;
|
|
279
376
|
|
|
280
|
-
export { type CompositeMember, type DataUrlView, type DateContentView, type DocumentContentView, type HtmlContentView, type ImageContentView, NATIVE_COMPOSITE_CONCEPT_REF, NATIVE_DATE_CONCEPT_REF, NATIVE_HTML_CONCEPT_REF, TYPED_SCALAR_MARKERS, dataUrlExtensions, formatDateContent, hasTypedScalarMarkers, isNativeCompositeNode, isNativeDateNode, isNativeHtmlNode, isNativeValueNode, isViewableUrl, readCompositeContent, readDataUrl, readDateContent, readDocumentContent, readHtmlContent, readImageContent, viewableUrl };
|
|
377
|
+
export { type ChoiceContentView, type CompositeMember, type DataUrlView, type DateContentView, type DocumentContentView, type HtmlContentView, type ImageContentView, NATIVE_CHOICE_CONCEPT_REF, NATIVE_COMPOSITE_CONCEPT_REF, NATIVE_DATE_CONCEPT_REF, NATIVE_HTML_CONCEPT_REF, NATIVE_PAGE_CONCEPT_REF, NATIVE_RATING_CONCEPT_REF, NATIVE_YES_NO_CONCEPT_REF, type PageContentView, type RatingContentView, TYPED_SCALAR_MARKERS, type YesNoContentView, dataUrlExtensions, formatDateContent, hasTypedScalarMarkers, isNativeCompositeNode, isNativeDateNode, isNativeHtmlNode, isNativePageNode, isNativeValueNode, isViewableUrl, nativeVerdictOf, readChoiceContent, readCompositeContent, readDataUrl, readDateContent, readDocumentContent, readHtmlContent, readImageContent, readPageContent, readRatingContent, readYesNoContent, viewableUrl };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { NATIVE_COMPOSITE_CONCEPT_REF, NATIVE_DATE_CONCEPT_REF, NATIVE_HTML_CONCEPT_REF, TYPED_SCALAR_MARKERS, dataUrlExtensions, formatDateContent, hasTypedScalarMarkers, isNativeCompositeNode, isNativeDateNode, isNativeHtmlNode, isNativeValueNode, isViewableUrl, readCompositeContent, readDataUrl, readDateContent, readDocumentContent, readHtmlContent, readImageContent, viewableUrl } from '../chunk-
|
|
1
|
+
export { NATIVE_CHOICE_CONCEPT_REF, NATIVE_COMPOSITE_CONCEPT_REF, NATIVE_DATE_CONCEPT_REF, NATIVE_HTML_CONCEPT_REF, NATIVE_PAGE_CONCEPT_REF, NATIVE_RATING_CONCEPT_REF, NATIVE_YES_NO_CONCEPT_REF, TYPED_SCALAR_MARKERS, dataUrlExtensions, formatDateContent, hasTypedScalarMarkers, isNativeCompositeNode, isNativeDateNode, isNativeHtmlNode, isNativePageNode, isNativeValueNode, isViewableUrl, nativeVerdictOf, readChoiceContent, readCompositeContent, readDataUrl, readDateContent, readDocumentContent, readHtmlContent, readImageContent, readPageContent, readRatingContent, readYesNoContent, viewableUrl } from '../chunk-JSPF4BQP.js';
|
|
2
2
|
import '../chunk-V3OV2XQT.js';
|
|
3
3
|
//# sourceMappingURL=native-content.js.map
|
|
4
4
|
//# sourceMappingURL=native-content.js.map
|
package/dist/core/save-plan.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { planFileSave, planStuffSave, splitFileName, typedFileStem } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { planFileSave, planStuffSave, splitFileName, typedFileStem } from '../chunk-QWHUUMSB.js';
|
|
2
|
+
import '../chunk-QINLJ5RM.js';
|
|
3
|
+
import '../chunk-JSPF4BQP.js';
|
|
4
4
|
import '../chunk-V3OV2XQT.js';
|
|
5
5
|
//# sourceMappingURL=save-plan.js.map
|
|
6
6
|
//# sourceMappingURL=save-plan.js.map
|
package/dist/core/sources.d.ts
CHANGED
|
@@ -158,6 +158,45 @@ declare function sourceFileValue(file: SourceFile): {
|
|
|
158
158
|
* a new array and leaves `held` as it was.
|
|
159
159
|
*/
|
|
160
160
|
declare function addChosenFiles(held: readonly unknown[] | undefined, chosen: readonly SourceFile[]): unknown[];
|
|
161
|
+
/** Where `placeDroppedFiles` puts a batch of files, and what it leaves out. */
|
|
162
|
+
interface DroppedFilesPlacement {
|
|
163
|
+
/**
|
|
164
|
+
* The list once the rows the batch needs are appended: `held` as it was,
|
|
165
|
+
* then one empty row (`undefined`) per file that did not go into a free row.
|
|
166
|
+
* A new array whenever rows are appended, and a copy of `held` otherwise.
|
|
167
|
+
*/
|
|
168
|
+
items: unknown[];
|
|
169
|
+
/** How many rows were appended, so a caller writes the list only when it grew. */
|
|
170
|
+
appended: number;
|
|
171
|
+
/** The row each placed file goes to, in the order the files were given. */
|
|
172
|
+
targets: number[];
|
|
173
|
+
/** How many files, from the end of the batch, found no room. */
|
|
174
|
+
leftOut: number;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Where a batch of `count` files dropped on a list of files goes: first into
|
|
178
|
+
* the rows that are free, in index order, then into new rows after the last,
|
|
179
|
+
* as far as `maxItemCount` allows. The files keep the order they were given,
|
|
180
|
+
* and those beyond the room are left out from the end of the batch.
|
|
181
|
+
*
|
|
182
|
+
* A row is free when it holds no file (its value carries no `url`) and
|
|
183
|
+
* `isFree` says so too. The caller's predicate is where it adds what only it
|
|
184
|
+
* knows of a row: that a file is still arriving there, whose write-back the row
|
|
185
|
+
* must be kept for, or that the host reports a failure there, the only record
|
|
186
|
+
* that one of the person's files did not arrive. Without one, every row holding
|
|
187
|
+
* no file is free.
|
|
188
|
+
*
|
|
189
|
+
* It mirrors `addChosenFiles`, so the two ways several files enter a list fill
|
|
190
|
+
* it alike, and it knows nothing of `File`: the caller judges each file and
|
|
191
|
+
* hands over how many it accepted.
|
|
192
|
+
*/
|
|
193
|
+
declare function placeDroppedFiles(held: readonly unknown[] | undefined, count: number, maxItemCount: number | undefined, isFree?: (index: number) => boolean): DroppedFilesPlacement;
|
|
194
|
+
/**
|
|
195
|
+
* How many files `placeDroppedFiles` can place in `held`: its free rows, by the
|
|
196
|
+
* same test, and the rows its bound still allows after the last. `undefined`
|
|
197
|
+
* when the list has no bound, since appending then never runs out.
|
|
198
|
+
*/
|
|
199
|
+
declare function roomForDroppedFiles(held: readonly unknown[] | undefined, maxItemCount: number | undefined, isFree?: (index: number) => boolean): number | undefined;
|
|
161
200
|
/**
|
|
162
201
|
* How many files `addChosenFiles` writes for `chosen` into `held`: the choices
|
|
163
202
|
* whose address the list does not hold yet, each address once. This is what a
|
|
@@ -172,4 +211,4 @@ declare function chosenFilesAdded(held: readonly unknown[] | undefined, chosen:
|
|
|
172
211
|
*/
|
|
173
212
|
declare function roomForChosenFiles(held: readonly unknown[] | undefined, maxItemCount: number | undefined): number | undefined;
|
|
174
213
|
|
|
175
|
-
export { type ExampleSource, type ExampleSourcePage, type ExampleSourceQuery, type FileSource, type FileSourcePage, type FileSourceQuery, type FileSourceScope, type FormExample, type SourceFile, addChosenFiles, chosenFilesAdded, roomForChosenFiles, sourceFileValue };
|
|
214
|
+
export { type DroppedFilesPlacement, type ExampleSource, type ExampleSourcePage, type ExampleSourceQuery, type FileSource, type FileSourcePage, type FileSourceQuery, type FileSourceScope, type FormExample, type SourceFile, addChosenFiles, chosenFilesAdded, placeDroppedFiles, roomForChosenFiles, roomForDroppedFiles, sourceFileValue };
|
package/dist/core/sources.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { addChosenFiles, chosenFilesAdded, roomForChosenFiles, sourceFileValue } from '../chunk-
|
|
1
|
+
export { addChosenFiles, chosenFilesAdded, placeDroppedFiles, roomForChosenFiles, roomForDroppedFiles, sourceFileValue } from '../chunk-NSHGLM6A.js';
|
|
2
2
|
//# sourceMappingURL=sources.js.map
|
|
3
3
|
//# sourceMappingURL=sources.js.map
|
package/dist/core/stuff-files.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { collectStuffFiles, readStuffFile } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
1
|
+
export { collectStuffFiles, readStuffFile } from '../chunk-QINLJ5RM.js';
|
|
2
|
+
import '../chunk-JSPF4BQP.js';
|
|
3
3
|
import '../chunk-V3OV2XQT.js';
|
|
4
4
|
//# sourceMappingURL=stuff-files.js.map
|
|
5
5
|
//# sourceMappingURL=stuff-files.js.map
|
package/dist/generative/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { cn, checkedAccentClass, focusOutlineClass, linkTextClass, selectedBorderClass, selectedFillClass, fieldControlClass, ResultRoot, ResultField, FieldRenderer, ToggleGroup, ToggleGroupItem, selectedFillStrongClass, Switch, Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
2
|
+
import { cn, checkedAccentClass, focusOutlineClass, linkTextClass, selectedBorderClass, selectedFillClass, fieldControlClass, ResultRoot, ResultField, FieldRenderer, ToggleGroup, ToggleGroupItem, selectedFillStrongClass, Switch, Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '../chunk-NA7SIQOH.js';
|
|
3
|
+
import '../chunk-QWHUUMSB.js';
|
|
4
4
|
export { seedInputs } from '../chunk-VH5CDQDR.js';
|
|
5
|
-
import '../chunk-
|
|
6
|
-
import '../chunk-
|
|
5
|
+
import '../chunk-NSHGLM6A.js';
|
|
6
|
+
import '../chunk-QINLJ5RM.js';
|
|
7
7
|
import '../chunk-ZX52CQJ4.js';
|
|
8
|
-
import { isNativeValueNode, readDateContent, formatDateContent, isNativeHtmlNode, isNativeDateNode, isNativeCompositeNode } from '../chunk-
|
|
8
|
+
import { isNativeValueNode, readDateContent, formatDateContent, isNativeHtmlNode, isNativeDateNode, isNativeCompositeNode } from '../chunk-JSPF4BQP.js';
|
|
9
9
|
export { brandManifestSchema } from '../chunk-QFX332LE.js';
|
|
10
10
|
import '../chunk-ZB4RYUKV.js';
|
|
11
11
|
import '../chunk-FABY3DEY.js';
|