@patterkit/cli 1.0.0 → 1.1.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/cli.js +102 -7
- package/package.json +4 -4
package/dist/cli.js
CHANGED
|
@@ -59,6 +59,12 @@ import {
|
|
|
59
59
|
applySuggestionDecisions,
|
|
60
60
|
qualifierNamer,
|
|
61
61
|
scriptFontLicences,
|
|
62
|
+
planPlaceholderSpeech,
|
|
63
|
+
runPlaceholderSpeech,
|
|
64
|
+
resolveKeyFile,
|
|
65
|
+
readGoogleKey,
|
|
66
|
+
tokenSource,
|
|
67
|
+
describeSpeechError,
|
|
62
68
|
findProjectFile,
|
|
63
69
|
readProjectManifest,
|
|
64
70
|
detectMergeType
|
|
@@ -70,7 +76,7 @@ import { runMergetool } from "@wildwinter/toolkit/vcs";
|
|
|
70
76
|
// package.json
|
|
71
77
|
var package_default = {
|
|
72
78
|
name: "@patterkit/cli",
|
|
73
|
-
version: "1.
|
|
79
|
+
version: "1.1.0",
|
|
74
80
|
description: "The `patter` CLI: validate, format, export, play, test coverage, localise, and merge Patter projects.",
|
|
75
81
|
keywords: [
|
|
76
82
|
"patter",
|
|
@@ -112,10 +118,10 @@ var package_default = {
|
|
|
112
118
|
"build:standalone:others": "node scripts/build-standalone.mjs --targets=linux-x64,linux-arm64,windows-x64"
|
|
113
119
|
},
|
|
114
120
|
dependencies: {
|
|
115
|
-
"@patterkit/core": "1.
|
|
116
|
-
"@patterkit/ops": "1.
|
|
121
|
+
"@patterkit/core": "1.1.0",
|
|
122
|
+
"@patterkit/ops": "1.1.0",
|
|
117
123
|
"@wildwinter/simple-vc-lib": "^0.5.2",
|
|
118
|
-
"@wildwinter/toolkit": "^1.
|
|
124
|
+
"@wildwinter/toolkit": "^1.2.0"
|
|
119
125
|
}
|
|
120
126
|
};
|
|
121
127
|
|
|
@@ -192,6 +198,10 @@ Usage:
|
|
|
192
198
|
[--ids] IDs-only build: ship no strings; the game localises from beat IDs
|
|
193
199
|
[--source-debug] IDs-only but embed the source language for debug playback (not shippable)
|
|
194
200
|
[--allow-invalid] Build even when validate finds errors in the content (not shippable)
|
|
201
|
+
[--audio-manifest-out file] Write the audio manifest there instead of beside the audio
|
|
202
|
+
(a shipping manifest; its files stay relative to the audio root)
|
|
203
|
+
[--no-placeholder-speech] Leave Placeholder Speech out of that manifest (needs
|
|
204
|
+
--audio-manifest-out, so the development one keeps it)
|
|
195
205
|
patter export-html [path] [-o file] A single self-contained, playable .html (runtime + story inlined;
|
|
196
206
|
send it to anyone, opens in any browser; default: beside the bundle; -o - for stdout)
|
|
197
207
|
patter play [path] Play a project through Patterplay and print the transcript
|
|
@@ -216,6 +226,11 @@ Usage:
|
|
|
216
226
|
beside the bundle, as .pdf. The PDF embeds its fonts and covers any script or emoji.
|
|
217
227
|
patter voice-export [path] -o file.xlsx The voice (VO) recording script
|
|
218
228
|
[--all] Include every voiced line (else only "ready to record")
|
|
229
|
+
patter placeholder-speech [path] Make Placeholder Speech: stand-in speech for spoken lines, from Google,
|
|
230
|
+
into the project's placeholder status folder (needs a key: the project's key file, else
|
|
231
|
+
GOOGLE_APPLICATION_CREDENTIALS)
|
|
232
|
+
[--scene id|name] [--dry-run] [--force] (--force remakes every line, even unchanged)
|
|
233
|
+
[--soft] No key is a note and exit 0, not a failure (for shared CI)
|
|
219
234
|
patter export-editable [path] -o file.docx An editable script to send to an editor outside Patter
|
|
220
235
|
[--scene name]... (repeatable; default the whole project) [--recipient "Sam"]
|
|
221
236
|
[--status] [--cast] [--all-notes] [--by name] (writes a handoffs/<id>.json record too)
|
|
@@ -247,7 +262,7 @@ var FLAGS = {
|
|
|
247
262
|
init: { boolean: [], valued: ["name", "vcs", "bundle"], positionals: 1 },
|
|
248
263
|
validate: { boolean: [], valued: [], positionals: 1 },
|
|
249
264
|
format: { boolean: ["check"], valued: [], positionals: Infinity },
|
|
250
|
-
export: { boolean: ["ids", "source-debug", "allow-invalid"], valued: ["o"], positionals: 1 },
|
|
265
|
+
export: { boolean: ["ids", "source-debug", "allow-invalid", "no-placeholder-speech"], valued: ["o", "audio-manifest-out"], positionals: 1 },
|
|
251
266
|
"export-html": { boolean: [], valued: ["o"], positionals: 1 },
|
|
252
267
|
play: { boolean: [], valued: ["scene", "block", "choices", "seed"], positionals: 1 },
|
|
253
268
|
coverage: { boolean: ["json", "fail-on-gap", "propose"], valued: ["runs", "max-steps", "seed", "scene", "block", "order"], positionals: 1 },
|
|
@@ -258,6 +273,7 @@ var FLAGS = {
|
|
|
258
273
|
"loc-import": { boolean: ["force-locale"], valued: ["locale"], positionals: 2 },
|
|
259
274
|
"voice-export": { boolean: ["all"], valued: ["o"], positionals: 1 },
|
|
260
275
|
"export-script": { boolean: [], valued: ["o"], positionals: 1 },
|
|
276
|
+
"placeholder-speech": { boolean: ["dry-run", "force", "soft"], valued: ["scene"], positionals: 1 },
|
|
261
277
|
"export-editable": { boolean: ["status", "cast", "all-notes"], valued: ["o", "recipient", "by"], repeatable: ["scene"], positionals: 1 },
|
|
262
278
|
"import-editable": { boolean: ["dry-run", "direct", "strict-quotes"], valued: ["as", "by"], positionals: 2 },
|
|
263
279
|
suggestions: { boolean: ["accept-clean", "json"], valued: ["handoff"], positionals: 1 },
|
|
@@ -273,7 +289,7 @@ var SHORT = {
|
|
|
273
289
|
init: "init [dir] [--name X] [--vcs git|perforce|plastic|svn] [--bundle commit|ignore]",
|
|
274
290
|
validate: "validate [path]",
|
|
275
291
|
format: "format <paths...> [--check]",
|
|
276
|
-
export: "export [path] [-o FILE] [--ids | --source-debug] [--allow-invalid]",
|
|
292
|
+
export: "export [path] [-o FILE] [--ids | --source-debug] [--allow-invalid] [--audio-manifest-out FILE [--no-placeholder-speech]]",
|
|
277
293
|
"export-html": "export-html [path] [-o FILE]",
|
|
278
294
|
play: "play [path] [--scene id] [--block id] [--choices a,b,c] [--seed N]",
|
|
279
295
|
coverage: "coverage [path] [--runs N] [--max-steps M] [--seed S] [--scene id] [--block id] [--order least|script] [--json] [--fail-on-gap] [--propose]",
|
|
@@ -284,6 +300,7 @@ var SHORT = {
|
|
|
284
300
|
"loc-import": "loc-import <file> [path] [--locale xx] [--force-locale]",
|
|
285
301
|
"voice-export": "voice-export [path] -o FILE.xlsx [--all]",
|
|
286
302
|
"export-script": "export-script [path] [-o FILE.pdf|FILE.docx]",
|
|
303
|
+
"placeholder-speech": "placeholder-speech [path] [--scene id|name] [--dry-run] [--force] [--soft]",
|
|
287
304
|
"export-editable": "export-editable [path] -o FILE.docx [--scene name]... [--recipient X] [--status] [--cast] [--all-notes] [--by name]",
|
|
288
305
|
"import-editable": "import-editable <file.docx> [path] [--dry-run] [--direct] [--as name] [--by name] [--strict-quotes]",
|
|
289
306
|
suggestions: "suggestions [path] [--handoff H-XXXX] [--accept-clean | --json]",
|
|
@@ -542,7 +559,13 @@ ${count} issue(s)${advisory}`);
|
|
|
542
559
|
process.stdout.write(canonicalStringify(runExport(loaded, { allowInvalid }), { trailingComma: false }));
|
|
543
560
|
return 0;
|
|
544
561
|
}
|
|
545
|
-
|
|
562
|
+
if (flags["no-placeholder-speech"] === true && typeof flags["audio-manifest-out"] !== "string") return usage("export", "--no-placeholder-speech needs --audio-manifest-out, so the development manifest keeps its placeholder speech");
|
|
563
|
+
const plan = planBuild(loaded, {
|
|
564
|
+
allowInvalid,
|
|
565
|
+
...typeof flags.o === "string" ? { bundlePath: flags.o } : {},
|
|
566
|
+
...typeof flags["audio-manifest-out"] === "string" ? { audioManifestPath: resolve(flags["audio-manifest-out"]) } : {},
|
|
567
|
+
...flags["no-placeholder-speech"] === true ? { leaveOutPlaceholderSpeech: true } : {}
|
|
568
|
+
});
|
|
546
569
|
if (!commitWrites(plan.writes)) return 1;
|
|
547
570
|
for (const w of plan.writes) console.log(`wrote ${w.path}`);
|
|
548
571
|
return 0;
|
|
@@ -749,6 +772,78 @@ ${count} issue(s)${advisory}`);
|
|
|
749
772
|
console.log(`wrote ${flags.o} - ${n} line(s)${flags.all === true ? "" : " (ready to record)"}`);
|
|
750
773
|
return 0;
|
|
751
774
|
}
|
|
775
|
+
case "placeholder-speech": {
|
|
776
|
+
const loaded = loadProject(positionals[0] ?? ".");
|
|
777
|
+
const ps = loaded.project.placeholderSpeech;
|
|
778
|
+
let scene;
|
|
779
|
+
if (typeof flags.scene === "string") {
|
|
780
|
+
const found = loaded.scenes.find((sc) => sc.id === flags.scene || sc.name === flags.scene);
|
|
781
|
+
if (!found) {
|
|
782
|
+
console.error(`placeholder-speech: no scene called "${flags.scene}"`);
|
|
783
|
+
return 2;
|
|
784
|
+
}
|
|
785
|
+
scene = found.id;
|
|
786
|
+
}
|
|
787
|
+
const plan = planPlaceholderSpeech(loaded, { ...scene ? { scene } : {}, ...flags.force === true ? { force: "all" } : {} });
|
|
788
|
+
if (!ps || !plan) {
|
|
789
|
+
console.error("placeholder-speech: this project doesn't have Placeholder Speech on (Project settings > Placeholder Speech, which needs Audio Folders)");
|
|
790
|
+
return 2;
|
|
791
|
+
}
|
|
792
|
+
if (!plan.accent) {
|
|
793
|
+
console.error("placeholder-speech: choose an accent first (Project settings > Placeholder Speech): the main language doesn't say which");
|
|
794
|
+
return 2;
|
|
795
|
+
}
|
|
796
|
+
const skipped = Object.entries(plan.skipped).map(([why, n]) => `${n} ${why}`).join(", ");
|
|
797
|
+
console.log(`${plan.tasks.length} line(s) to make into ${plan.folder}${skipped ? ` (left alone: ${skipped})` : ""}`);
|
|
798
|
+
if (flags["dry-run"] === true) {
|
|
799
|
+
for (const t of plan.tasks) console.log(` ${t.beatId} ${t.character} ${t.request.voice}`);
|
|
800
|
+
return 0;
|
|
801
|
+
}
|
|
802
|
+
if (!plan.tasks.length) return 0;
|
|
803
|
+
const key = resolveKeyFile(loaded.root, ps.keyFile);
|
|
804
|
+
if (!key.path) {
|
|
805
|
+
const msg = `placeholder-speech: no Google key on this machine (${ps.keyFile ? `${ps.keyFile} isn't here, and ` : ""}GOOGLE_APPLICATION_CREDENTIALS isn't set, and there's no gcloud sign-in)`;
|
|
806
|
+
if (flags.soft === true) {
|
|
807
|
+
console.log(msg.replace("placeholder-speech: ", "note: "));
|
|
808
|
+
return 0;
|
|
809
|
+
}
|
|
810
|
+
console.error(msg);
|
|
811
|
+
return 1;
|
|
812
|
+
}
|
|
813
|
+
let account;
|
|
814
|
+
try {
|
|
815
|
+
account = readGoogleKey(key.path);
|
|
816
|
+
} catch (e) {
|
|
817
|
+
console.error(`placeholder-speech: ${describeSpeechError(e)}`);
|
|
818
|
+
return 1;
|
|
819
|
+
}
|
|
820
|
+
mkdirSync(plan.folder, { recursive: true });
|
|
821
|
+
const keepOut = ps.keepOutOfVersionControl === true;
|
|
822
|
+
const result = await runPlaceholderSpeech(plan.tasks, {
|
|
823
|
+
token: tokenSource(account),
|
|
824
|
+
write: async (path, bytes) => {
|
|
825
|
+
if (keepOut) {
|
|
826
|
+
writeFileSync(path, bytes);
|
|
827
|
+
return true;
|
|
828
|
+
}
|
|
829
|
+
const r = writeBinaryFile(path, bytes);
|
|
830
|
+
if (r.success) return true;
|
|
831
|
+
if (r.status === "locked") return false;
|
|
832
|
+
throw new Error(r.message);
|
|
833
|
+
},
|
|
834
|
+
onProgress: (done, total) => {
|
|
835
|
+
if (process.stdout.isTTY) process.stdout.write(`\r${done}/${total}`);
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
if (process.stdout.isTTY) process.stdout.write("\n");
|
|
839
|
+
console.log(`made ${result.made.length}${result.skippedLocked.length ? `, skipped ${result.skippedLocked.length} (open elsewhere)` : ""}${result.failed.length ? `, failed ${result.failed.length}` : ""}`);
|
|
840
|
+
for (const f of result.failed) console.error(` ${f.beatId}: ${f.error}`);
|
|
841
|
+
if (result.stopped) {
|
|
842
|
+
console.error(`placeholder-speech: stopped: ${result.stopped.message}${result.notTried ? ` (${result.notTried} not tried)` : ""}`);
|
|
843
|
+
return 1;
|
|
844
|
+
}
|
|
845
|
+
return result.failed.length ? 1 : 0;
|
|
846
|
+
}
|
|
752
847
|
case "loc-import": {
|
|
753
848
|
const file = positionals[0];
|
|
754
849
|
if (!file) return usage("loc-import", "no file given");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patterkit/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "The `patter` CLI: validate, format, export, play, test coverage, localise, and merge Patter projects.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"patter",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"build:standalone:others": "node scripts/build-standalone.mjs --targets=linux-x64,linux-arm64,windows-x64"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@patterkit/core": "1.
|
|
46
|
-
"@patterkit/ops": "1.
|
|
45
|
+
"@patterkit/core": "1.1.0",
|
|
46
|
+
"@patterkit/ops": "1.1.0",
|
|
47
47
|
"@wildwinter/simple-vc-lib": "^0.5.2",
|
|
48
|
-
"@wildwinter/toolkit": "^1.
|
|
48
|
+
"@wildwinter/toolkit": "^1.2.0"
|
|
49
49
|
}
|
|
50
50
|
}
|