@rohal12/twee-ts 1.9.0 → 1.11.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/bin/twee-ts.js +52 -14
- package/dist/bin/twee-ts.js.map +1 -1
- package/dist/{chunk-FSZ5FD3P.js → chunk-KCLV5CYO.js} +30 -13
- package/dist/chunk-KCLV5CYO.js.map +1 -0
- package/dist/index.cjs +36 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +36 -12
- package/dist/index.js.map +1 -1
- package/dist/plugins/rollup.d.ts +1 -1
- package/dist/plugins/rollup.js +1 -1
- package/dist/plugins/vite.d.ts +1 -1
- package/dist/plugins/vite.js +1 -1
- package/dist/{types-BbEu2Szm.d.ts → types-FHZ3rZD6.d.ts} +3 -0
- package/package.json +3 -2
- package/schemas/twee-ts.config.schema.json +103 -0
- package/dist/chunk-FSZ5FD3P.js.map +0 -1
package/dist/bin/twee-ts.js
CHANGED
|
@@ -236,15 +236,32 @@ function passageToTiddler(p, pid, obfuscateRot13 = false) {
|
|
|
236
236
|
const nameComment = obfuscateRot13 ? `<!-- ${commentSanitize(p.name)} -->` : "";
|
|
237
237
|
return `<div tiddler=${quote(attrEscape(p.name))} tags=${quote(attrEscape(p.tags.join(" ")))} created=${quote(created)} modifier=${quote("twee")} twine-position=${quote(attrEscape(position))}>${nameComment}${content}</div>`;
|
|
238
238
|
}
|
|
239
|
-
function countWords(p) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
239
|
+
function countWords(p, method = "tweego") {
|
|
240
|
+
switch (method) {
|
|
241
|
+
case "tweego": {
|
|
242
|
+
let text = p.text;
|
|
243
|
+
text = text.replace(/\n/g, "");
|
|
244
|
+
text = text.replace(/(?:\/%.+?%\/|\/\*.+?\*\/|<!--.+?-->)/gs, "");
|
|
245
|
+
const normalized = text.normalize("NFKD");
|
|
246
|
+
const count = [...normalized].length;
|
|
247
|
+
if (count === 0) return 0;
|
|
248
|
+
const words = Math.floor(count / 5);
|
|
249
|
+
return count % 5 > 0 ? words + 1 : words;
|
|
250
|
+
}
|
|
251
|
+
case "whitespace": {
|
|
252
|
+
let text = p.text;
|
|
253
|
+
text = text.replace(/(?:\/%.+?%\/|\/\*.+?\*\/|<!--.+?-->)/gs, "");
|
|
254
|
+
text = text.replace(/<<[^>]*>>/g, "");
|
|
255
|
+
text = text.replace(/\[\[([^\]|]*?)(?:\|[^\]]*?)?\]\]/g, "$1");
|
|
256
|
+
text = text.replace(/<[^>]+>/g, "");
|
|
257
|
+
const tokens = text.split(/\s+/).filter((t) => t.length > 0);
|
|
258
|
+
return tokens.length;
|
|
259
|
+
}
|
|
260
|
+
default: {
|
|
261
|
+
const _exhaustive = method;
|
|
262
|
+
throw new Error(`Unhandled word count method: ${_exhaustive}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
248
265
|
}
|
|
249
266
|
function applyTagAliases(passages, aliases) {
|
|
250
267
|
const entries = Object.entries(aliases);
|
|
@@ -462,13 +479,13 @@ function storyAdd(story, p, diagnostics) {
|
|
|
462
479
|
}
|
|
463
480
|
storyAppend(story, processed, diagnostics);
|
|
464
481
|
}
|
|
465
|
-
function getStoryStats(story) {
|
|
482
|
+
function getStoryStats(story, wordCountMethod = "tweego") {
|
|
466
483
|
let storyPassages = 0;
|
|
467
484
|
let words = 0;
|
|
468
485
|
for (const p of story.passages) {
|
|
469
486
|
if (isStoryPassage(p)) {
|
|
470
487
|
storyPassages++;
|
|
471
|
-
words += countWords(p);
|
|
488
|
+
words += countWords(p, wordCountMethod);
|
|
472
489
|
}
|
|
473
490
|
}
|
|
474
491
|
return { passages: story.passages.length, storyPassages, words };
|
|
@@ -2293,7 +2310,7 @@ async function buildOutput(options, cache, changedFiles) {
|
|
|
2293
2310
|
}
|
|
2294
2311
|
}
|
|
2295
2312
|
const stats = {
|
|
2296
|
-
...getStoryStats(story),
|
|
2313
|
+
...getStoryStats(story, options.wordCountMethod),
|
|
2297
2314
|
files: [...processedFiles]
|
|
2298
2315
|
};
|
|
2299
2316
|
return { output, story, format, diagnostics, stats };
|
|
@@ -2514,6 +2531,7 @@ import { readFileSync as readFileSync4, existsSync as existsSync2 } from "fs";
|
|
|
2514
2531
|
import { join as join5 } from "path";
|
|
2515
2532
|
var CONFIG_FILENAME = "twee-ts.config.json";
|
|
2516
2533
|
var VALID_OUTPUT_MODES = ["html", "twee3", "twee1", "twine2-archive", "twine1-archive", "json"];
|
|
2534
|
+
var VALID_WORD_COUNT_METHODS = ["tweego", "whitespace"];
|
|
2517
2535
|
function loadConfig(dir) {
|
|
2518
2536
|
const base = dir ?? process.cwd();
|
|
2519
2537
|
const configPath = join5(base, CONFIG_FILENAME);
|
|
@@ -2600,10 +2618,16 @@ function validateConfig(data) {
|
|
|
2600
2618
|
errors.push(`"outputMode" must be one of: ${VALID_OUTPUT_MODES.join(", ")}.`);
|
|
2601
2619
|
}
|
|
2602
2620
|
}
|
|
2621
|
+
if ("wordCountMethod" in obj) {
|
|
2622
|
+
if (typeof obj["wordCountMethod"] !== "string" || !VALID_WORD_COUNT_METHODS.includes(obj["wordCountMethod"])) {
|
|
2623
|
+
errors.push(`"wordCountMethod" must be one of: ${VALID_WORD_COUNT_METHODS.join(", ")}.`);
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2603
2626
|
return errors;
|
|
2604
2627
|
}
|
|
2605
2628
|
function scaffoldConfig() {
|
|
2606
2629
|
const config = {
|
|
2630
|
+
$schema: "https://unpkg.com/@rohal12/twee-ts/schemas/twee-ts.config.schema.json",
|
|
2607
2631
|
sources: ["src/"],
|
|
2608
2632
|
output: "story.html"
|
|
2609
2633
|
};
|
|
@@ -2641,6 +2665,7 @@ var { values, positionals } = parseArgs({
|
|
|
2641
2665
|
"no-remote": { type: "boolean" },
|
|
2642
2666
|
"tag-alias": { type: "string", multiple: true },
|
|
2643
2667
|
"source-info": { type: "boolean" },
|
|
2668
|
+
"word-count-method": { type: "string" },
|
|
2644
2669
|
config: { type: "string", short: "c" },
|
|
2645
2670
|
"no-config": { type: "boolean" }
|
|
2646
2671
|
}
|
|
@@ -2698,6 +2723,16 @@ async function main() {
|
|
|
2698
2723
|
tagAliases[pair.slice(0, eq)] = pair.slice(eq + 1);
|
|
2699
2724
|
}
|
|
2700
2725
|
}
|
|
2726
|
+
const VALID_WORD_COUNT_METHODS2 = ["tweego", "whitespace"];
|
|
2727
|
+
const wordCountMethod = (() => {
|
|
2728
|
+
const raw = values["word-count-method"] ?? config?.wordCountMethod;
|
|
2729
|
+
if (raw === void 0) return void 0;
|
|
2730
|
+
if (!VALID_WORD_COUNT_METHODS2.includes(raw)) {
|
|
2731
|
+
console.error(`Error: Invalid --word-count-method "${raw}". Expected: ${VALID_WORD_COUNT_METHODS2.join(", ")}`);
|
|
2732
|
+
process.exit(1);
|
|
2733
|
+
}
|
|
2734
|
+
return raw;
|
|
2735
|
+
})();
|
|
2701
2736
|
if (values.lint) {
|
|
2702
2737
|
const lintResult = await lint({
|
|
2703
2738
|
sources,
|
|
@@ -2713,7 +2748,8 @@ async function main() {
|
|
|
2713
2748
|
formatUrls: values["format-url"] ?? config?.formatUrls,
|
|
2714
2749
|
noRemote: values["no-remote"] ?? config?.noRemote ?? false,
|
|
2715
2750
|
tagAliases,
|
|
2716
|
-
sourceInfo: values["source-info"] ?? config?.sourceInfo ?? false
|
|
2751
|
+
sourceInfo: values["source-info"] ?? config?.sourceInfo ?? false,
|
|
2752
|
+
wordCountMethod
|
|
2717
2753
|
});
|
|
2718
2754
|
console.log(formatLintReport(lintResult));
|
|
2719
2755
|
const hasErrors = lintResult.brokenLinks.length > 0 || lintResult.diagnostics.some((d) => d.level === "error");
|
|
@@ -2735,7 +2771,8 @@ async function main() {
|
|
|
2735
2771
|
formatUrls: values["format-url"] ?? config?.formatUrls,
|
|
2736
2772
|
noRemote: values["no-remote"] ?? config?.noRemote ?? false,
|
|
2737
2773
|
tagAliases,
|
|
2738
|
-
sourceInfo: values["source-info"] ?? config?.sourceInfo ?? false
|
|
2774
|
+
sourceInfo: values["source-info"] ?? config?.sourceInfo ?? false,
|
|
2775
|
+
wordCountMethod
|
|
2739
2776
|
};
|
|
2740
2777
|
const outFile = values.output ?? config?.output ?? "-";
|
|
2741
2778
|
if (values.watch) {
|
|
@@ -2920,6 +2957,7 @@ Options:
|
|
|
2920
2957
|
--format-url <url> Direct format.js URL (repeatable)
|
|
2921
2958
|
--tag-alias <alias=target> Map a tag to a special tag (repeatable)
|
|
2922
2959
|
--source-info Emit source file/line as data- attributes on passages
|
|
2960
|
+
--word-count-method <m> Word counting method: tweego (default), whitespace
|
|
2923
2961
|
--no-remote Disable remote format fetching
|
|
2924
2962
|
-c, --config <file> Config file path (default: ${CONFIG_FILENAME})
|
|
2925
2963
|
--no-config Skip config file loading
|