@particle-academy/holy-sheet 2.10.2 → 2.11.1
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/CHANGELOG.md +49 -0
- package/README.md +27 -0
- package/dist/chunk-NQRZFV32.js +6839 -0
- package/dist/chunk-NQRZFV32.js.map +1 -0
- package/dist/cli.cjs +6920 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +82 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +565 -177
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -4
- package/dist/index.d.ts +55 -4
- package/dist/index.js +9 -6455
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/cli.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Agent, readFileBounded, OfficeTemplateRefused, ArchiveRefused, UnsupportedFormatException, sourceKind, SourceArchive } from './chunk-NQRZFV32.js';
|
|
3
|
+
import { existsSync, realpathSync, statSync, writeFileSync, renameSync, unlinkSync } from 'fs';
|
|
4
|
+
import { randomBytes } from 'crypto';
|
|
5
|
+
|
|
6
|
+
var USAGE = "Usage: holy-sheet template:convert <input> <output> [--to=document|template] [--force]\n Converts an .xltx/.ots template to its .xlsx/.ods twin, or back.\n Without --to it flips whichever the input is.\n";
|
|
7
|
+
async function run(args, io) {
|
|
8
|
+
const [command, ...rest] = args;
|
|
9
|
+
const positional = [];
|
|
10
|
+
let to = null;
|
|
11
|
+
let force = false;
|
|
12
|
+
for (const arg of rest) {
|
|
13
|
+
if (arg.startsWith("--to=")) to = arg.slice(5);
|
|
14
|
+
else if (arg === "--force") force = true;
|
|
15
|
+
else if (arg.startsWith("--")) {
|
|
16
|
+
io.stderr(`Unknown option ${arg}
|
|
17
|
+
${USAGE}`);
|
|
18
|
+
return 2;
|
|
19
|
+
} else positional.push(arg);
|
|
20
|
+
}
|
|
21
|
+
if (command !== "template:convert" || positional.length !== 2) {
|
|
22
|
+
io.stderr(USAGE);
|
|
23
|
+
return 2;
|
|
24
|
+
}
|
|
25
|
+
const [input, output] = positional;
|
|
26
|
+
if (existsSync(output) && !force) {
|
|
27
|
+
io.stderr(`Refused: ${output} already exists (pass --force to replace it).
|
|
28
|
+
`);
|
|
29
|
+
return 1;
|
|
30
|
+
}
|
|
31
|
+
if (existsSync(input) && existsSync(output) && realpathSync(input) === realpathSync(output)) {
|
|
32
|
+
io.stderr("Refused: the output is the input.\n");
|
|
33
|
+
return 1;
|
|
34
|
+
}
|
|
35
|
+
if (!existsSync(input) || !statSync(input).isFile()) {
|
|
36
|
+
io.stderr(`Refused: ${input} is not a file.
|
|
37
|
+
`);
|
|
38
|
+
return 1;
|
|
39
|
+
}
|
|
40
|
+
let converted;
|
|
41
|
+
try {
|
|
42
|
+
converted = Agent.convertTemplate(await readFileBounded(input), to);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error instanceof OfficeTemplateRefused || error instanceof ArchiveRefused) {
|
|
45
|
+
io.stderr(`Refused (${error.reason}): ${error.message}
|
|
46
|
+
`);
|
|
47
|
+
return 1;
|
|
48
|
+
}
|
|
49
|
+
if (error instanceof UnsupportedFormatException) {
|
|
50
|
+
io.stderr(`Refused (unsupported): ${error.message}
|
|
51
|
+
`);
|
|
52
|
+
return 1;
|
|
53
|
+
}
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
const temp = `${output}.tmp-${randomBytes(4).toString("hex")}`;
|
|
57
|
+
try {
|
|
58
|
+
writeFileSync(temp, converted);
|
|
59
|
+
renameSync(temp, output);
|
|
60
|
+
} catch {
|
|
61
|
+
try {
|
|
62
|
+
unlinkSync(temp);
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
65
|
+
io.stderr(`Could not write ${output}.
|
|
66
|
+
`);
|
|
67
|
+
return 1;
|
|
68
|
+
}
|
|
69
|
+
io.stdout(`Wrote ${output} (${sourceKind(SourceArchive.open(converted))}).
|
|
70
|
+
`);
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/cli.ts
|
|
75
|
+
run(process.argv.slice(2), {
|
|
76
|
+
stdout: (text) => process.stdout.write(text),
|
|
77
|
+
stderr: (text) => process.stderr.write(text)
|
|
78
|
+
}).then((code) => {
|
|
79
|
+
process.exitCode = code;
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=cli.js.map
|
|
82
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-run.ts","../src/cli.ts"],"names":[],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * `npx holy-sheet` (the `bin`). One command today, mirroring PHP `bin/holy-sheet`:\n *\n * holy-sheet template:convert <input> <output> [--to=document|template] [--force]\n *\n * Exit codes: 0 converted, 1 refused (the reason is printed), 2 usage.\n *\n * Node-only, and never imported by the isomorphic index.\n *\n * @internal\n */\nimport { existsSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { randomBytes } from \"node:crypto\";\nimport { Agent } from \"./agent\";\nimport { ArchiveRefused, OfficeTemplateRefused, UnsupportedFormatException } from \"./exceptions\";\nimport { readFileBounded } from \"./reader/file-input\";\nimport { SourceArchive } from \"./zip/source-archive\";\nimport { sourceKind, type SourceKind } from \"./zip/office-template\";\n\nexport interface CliIo {\n stdout: (text: string) => void;\n stderr: (text: string) => void;\n}\n\nconst USAGE = \"Usage: holy-sheet template:convert <input> <output> [--to=document|template] [--force]\\n\"\n + \" Converts an .xltx/.ots template to its .xlsx/.ods twin, or back.\\n\"\n + \" Without --to it flips whichever the input is.\\n\";\n\nexport async function run(args: string[], io: CliIo): Promise<number> {\n const [command, ...rest] = args;\n const positional: string[] = [];\n let to: string | null = null;\n let force = false;\n for (const arg of rest) {\n if (arg.startsWith(\"--to=\")) to = arg.slice(5);\n else if (arg === \"--force\") force = true;\n else if (arg.startsWith(\"--\")) {\n io.stderr(`Unknown option ${arg}\\n${USAGE}`);\n return 2;\n } else positional.push(arg);\n }\n if (command !== \"template:convert\" || positional.length !== 2) {\n io.stderr(USAGE);\n return 2;\n }\n const [input, output] = positional as [string, string];\n\n if (existsSync(output) && !force) {\n io.stderr(`Refused: ${output} already exists (pass --force to replace it).\\n`);\n return 1;\n }\n if (existsSync(input) && existsSync(output) && realpathSync(input) === realpathSync(output)) {\n io.stderr(\"Refused: the output is the input.\\n\");\n return 1;\n }\n if (!existsSync(input) || !statSync(input).isFile()) {\n io.stderr(`Refused: ${input} is not a file.\\n`);\n return 1;\n }\n\n let converted: Uint8Array;\n try {\n converted = Agent.convertTemplate(await readFileBounded(input), to as SourceKind | null);\n } catch (error) {\n if (error instanceof OfficeTemplateRefused || error instanceof ArchiveRefused) {\n io.stderr(`Refused (${error.reason}): ${error.message}\\n`);\n return 1;\n }\n if (error instanceof UnsupportedFormatException) {\n io.stderr(`Refused (unsupported): ${error.message}\\n`);\n return 1;\n }\n throw error;\n }\n\n // Written beside the target and renamed, so a failure leaves no half file.\n const temp = `${output}.tmp-${randomBytes(4).toString(\"hex\")}`;\n try {\n writeFileSync(temp, converted);\n renameSync(temp, output);\n } catch {\n try { unlinkSync(temp); } catch { /* already gone */ }\n io.stderr(`Could not write ${output}.\\n`);\n return 1;\n }\n io.stdout(`Wrote ${output} (${sourceKind(SourceArchive.open(converted))}).\\n`);\n return 0;\n}\n","#!/usr/bin/env node\n/** The `holy-sheet` bin. All behaviour lives in `cli-run.ts`, which the tests import. */\nimport { run } from \"./cli-run\";\n\nrun(process.argv.slice(2), {\n stdout: (text) => process.stdout.write(text),\n stderr: (text) => process.stderr.write(text),\n}).then((code) => {\n process.exitCode = code;\n});\n"]}
|