@bendyline/squisq-cli 2.3.2 → 2.4.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/README.md
CHANGED
|
@@ -121,6 +121,29 @@ squisq validate ./my-folder --strict
|
|
|
121
121
|
|
|
122
122
|
Diagnostics are reported at three severities — `error`, `warning`, and `info` (info is counted and shown separately). Exit codes depend on **errors** only: `0` clean, warnings-only, or info-only; `1` errors (or any warning with `--strict`); `2` input unreadable.
|
|
123
123
|
|
|
124
|
+
### `squisq transform <input>`
|
|
125
|
+
|
|
126
|
+
Apply one-time markdown **source** transforms to a `.md` file, in the order given: `unwrap` (remove forced line wrapping so each paragraph is one line — hard breaks kept), `wrap` (hard-wrap paragraph prose at a column width on word boundaries — code, tables, and headings untouched), and `cleanup` (canonical house-style normalization: bullets, emphasis, headings, table padding, spacing; annotations and frontmatter preserved). Not to be confused with the `--transform <style>` slideshow-style flag on `convert`/`video` — this command rewrites the markdown text itself.
|
|
127
|
+
|
|
128
|
+
The transformed markdown goes to stdout by default (status messages go to stderr, so it pipes cleanly).
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
squisq transform doc.md --ops unwrap
|
|
132
|
+
squisq transform doc.md --ops unwrap,cleanup > cleaned.md
|
|
133
|
+
squisq transform doc.md --ops wrap --width 100 --in-place
|
|
134
|
+
squisq transform doc.md --ops cleanup -o cleaned.md
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
| Option | Description |
|
|
138
|
+
| -------------- | -------------------------------------------------------------------------- |
|
|
139
|
+
| `--ops <list>` | Comma-separated transforms, applied in order (`unwrap`, `wrap`, `cleanup`) |
|
|
140
|
+
| `--width <n>` | Column width for `wrap` (20–500, default 80) |
|
|
141
|
+
| `-o <file>` | Write the result to a file (refuses to overwrite without `--overwrite`) |
|
|
142
|
+
| `--in-place` | Rewrite the input file (conflicts with `-o`) |
|
|
143
|
+
| `--overwrite` | Allow `-o` to replace an existing file |
|
|
144
|
+
|
|
145
|
+
Transforms run in strict mode: each one reparses its output and structurally compares it against the input document; if equivalence cannot be proven, the command exits `1` without emitting anything. Exit codes: `0` success, `1` transform/output failure, `2` input unreadable.
|
|
146
|
+
|
|
124
147
|
## Input Formats
|
|
125
148
|
|
|
126
149
|
All commands accept:
|
package/dist/api.js
CHANGED
|
@@ -298,6 +298,7 @@ var GIF_DEFAULTS = {
|
|
|
298
298
|
function mp4Format() {
|
|
299
299
|
return {
|
|
300
300
|
id: "mp4",
|
|
301
|
+
templateAnnotationHandling: "rendered",
|
|
301
302
|
label: "MP4 Video",
|
|
302
303
|
mimeType: "video/mp4",
|
|
303
304
|
extensions: [".mp4"],
|
|
@@ -339,6 +340,7 @@ function mp4Format() {
|
|
|
339
340
|
function gifFormat() {
|
|
340
341
|
return {
|
|
341
342
|
id: "gif",
|
|
343
|
+
templateAnnotationHandling: "rendered",
|
|
342
344
|
label: "Animated GIF",
|
|
343
345
|
mimeType: "image/gif",
|
|
344
346
|
extensions: [".gif"],
|
|
@@ -295,6 +295,7 @@ var GIF_DEFAULTS = {
|
|
|
295
295
|
function mp4Format() {
|
|
296
296
|
return {
|
|
297
297
|
id: "mp4",
|
|
298
|
+
templateAnnotationHandling: "rendered",
|
|
298
299
|
label: "MP4 Video",
|
|
299
300
|
mimeType: "video/mp4",
|
|
300
301
|
extensions: [".mp4"],
|
|
@@ -308,7 +309,7 @@ function mp4Format() {
|
|
|
308
309
|
const animationsEnabled = typeof mp4Opts.animationsEnabled === "boolean" ? mp4Opts.animationsEnabled : MP4_DEFAULTS.animationsEnabled;
|
|
309
310
|
const outputPath = join(tmpdir(), `squisq-mp4-${randomBytes(8).toString("hex")}.mp4`);
|
|
310
311
|
try {
|
|
311
|
-
const { renderDocToMp4: renderDocToMp42 } = await import("./api-
|
|
312
|
+
const { renderDocToMp4: renderDocToMp42 } = await import("./api-HBPJQ7MA.js");
|
|
312
313
|
await renderDocToMp42(input.doc, input.container, {
|
|
313
314
|
outputPath,
|
|
314
315
|
fps,
|
|
@@ -336,6 +337,7 @@ function mp4Format() {
|
|
|
336
337
|
function gifFormat() {
|
|
337
338
|
return {
|
|
338
339
|
id: "gif",
|
|
340
|
+
templateAnnotationHandling: "rendered",
|
|
339
341
|
label: "Animated GIF",
|
|
340
342
|
mimeType: "image/gif",
|
|
341
343
|
extensions: [".gif"],
|
|
@@ -348,7 +350,7 @@ function gifFormat() {
|
|
|
348
350
|
const defaultHeight = portrait ? GIF_DEFAULTS.width : GIF_DEFAULTS.height;
|
|
349
351
|
const outputPath = join(tmpdir(), `squisq-gif-${randomBytes(8).toString("hex")}.gif`);
|
|
350
352
|
try {
|
|
351
|
-
const { renderDocToGif: renderDocToGif2 } = await import("./api-
|
|
353
|
+
const { renderDocToGif: renderDocToGif2 } = await import("./api-HBPJQ7MA.js");
|
|
352
354
|
const result = await renderDocToGif2(input.doc, input.container, {
|
|
353
355
|
outputPath,
|
|
354
356
|
fps: typeof gifOpts.fps === "number" ? gifOpts.fps : GIF_DEFAULTS.fps,
|
package/dist/index.js
CHANGED
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
readInput,
|
|
8
8
|
renderDocToGif,
|
|
9
9
|
renderDocToMp4
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WR2BZJ77.js";
|
|
11
11
|
import "./chunk-GGVASRPG.js";
|
|
12
12
|
|
|
13
13
|
// src/index.ts
|
|
14
14
|
import { createRequire } from "module";
|
|
15
|
-
import { Command } from "commander";
|
|
15
|
+
import { Command as Command2 } from "commander";
|
|
16
16
|
|
|
17
17
|
// src/commands/convert.ts
|
|
18
18
|
import { mkdir } from "fs/promises";
|
|
@@ -627,6 +627,91 @@ async function runDoctor(runtime = defaultDoctorRuntime) {
|
|
|
627
627
|
return allPresent;
|
|
628
628
|
}
|
|
629
629
|
|
|
630
|
+
// src/commands/transform.ts
|
|
631
|
+
import { mkdir as mkdir3, readFile } from "fs/promises";
|
|
632
|
+
import { dirname as dirname4, resolve as resolve4 } from "path";
|
|
633
|
+
import { Option as Option2 } from "commander";
|
|
634
|
+
import {
|
|
635
|
+
DEFAULT_WRAP_WIDTH,
|
|
636
|
+
MARKDOWN_SOURCE_TRANSFORMS,
|
|
637
|
+
applyMarkdownSourceTransform
|
|
638
|
+
} from "@bendyline/squisq/markdown";
|
|
639
|
+
var VALID_OPS = MARKDOWN_SOURCE_TRANSFORMS.map((t) => t.id);
|
|
640
|
+
function registerTransformCommand(program2) {
|
|
641
|
+
program2.command("transform").description("Apply one-time markdown source transforms (unwrap, wrap, cleanup) to a document").argument("<input>", "Path to a markdown (.md) file").requiredOption(
|
|
642
|
+
"--ops <list>",
|
|
643
|
+
`Comma-separated transforms, applied in order. Valid: ${VALID_OPS.join(", ")}`
|
|
644
|
+
).option(
|
|
645
|
+
"--width <n>",
|
|
646
|
+
"Column width for the wrap transform (20\u2013500)",
|
|
647
|
+
String(DEFAULT_WRAP_WIDTH)
|
|
648
|
+
).addOption(
|
|
649
|
+
new Option2("-o, --output <file>", "Write the result to a file (default: stdout)").conflicts(
|
|
650
|
+
"inPlace"
|
|
651
|
+
)
|
|
652
|
+
).addOption(
|
|
653
|
+
new Option2("--in-place", "Rewrite the input file with the result").conflicts("output")
|
|
654
|
+
).option("--overwrite", "Replace an existing --output file (default: refuse and exit non-zero)").action(async (inputPath, opts) => {
|
|
655
|
+
try {
|
|
656
|
+
process.exitCode = await runTransform(inputPath, opts);
|
|
657
|
+
} catch (err) {
|
|
658
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
659
|
+
console.error(`Error: ${message}`);
|
|
660
|
+
process.exitCode = 1;
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
async function runTransform(inputPath, opts) {
|
|
665
|
+
const resolvedInput = resolve4(inputPath);
|
|
666
|
+
let source;
|
|
667
|
+
try {
|
|
668
|
+
source = await readFile(resolvedInput, { encoding: "utf-8" });
|
|
669
|
+
} catch (err) {
|
|
670
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
671
|
+
console.error(`Error: could not read input: ${message}`);
|
|
672
|
+
return 2;
|
|
673
|
+
}
|
|
674
|
+
const ids = opts.ops.split(",").map((id) => id.trim()).filter((id) => id.length > 0);
|
|
675
|
+
if (ids.length === 0) {
|
|
676
|
+
console.error(`Error: --ops needs at least one transform (valid: ${VALID_OPS.join(", ")})`);
|
|
677
|
+
return 1;
|
|
678
|
+
}
|
|
679
|
+
for (const id of ids) {
|
|
680
|
+
if (!VALID_OPS.includes(id)) {
|
|
681
|
+
console.error(`Error: unknown transform "${id}" (valid: ${VALID_OPS.join(", ")})`);
|
|
682
|
+
return 1;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
const width = Number.parseInt(opts.width, 10);
|
|
686
|
+
if (Number.isNaN(width)) {
|
|
687
|
+
console.error(`Error: --width must be a number (got "${opts.width}")`);
|
|
688
|
+
return 1;
|
|
689
|
+
}
|
|
690
|
+
let result = source;
|
|
691
|
+
const applied = [];
|
|
692
|
+
for (const id of ids) {
|
|
693
|
+
const step = applyMarkdownSourceTransform(id, result, { width, strict: true });
|
|
694
|
+
result = step.output;
|
|
695
|
+
applied.push(step.changed ? id : `${id} (no changes)`);
|
|
696
|
+
}
|
|
697
|
+
const summary = applied.join(", ");
|
|
698
|
+
const bytes = Buffer.from(result, "utf-8");
|
|
699
|
+
if (opts.inPlace) {
|
|
700
|
+
await writeFileGuarded(resolvedInput, bytes, true);
|
|
701
|
+
console.error(`\u2713 ${summary} \u2192 ${resolvedInput}`);
|
|
702
|
+
} else if (opts.output) {
|
|
703
|
+
const resolvedOutput = resolve4(opts.output);
|
|
704
|
+
await assertOutputsWritable([resolvedOutput], opts.overwrite);
|
|
705
|
+
await mkdir3(dirname4(resolvedOutput), { recursive: true });
|
|
706
|
+
await writeFileGuarded(resolvedOutput, bytes, opts.overwrite);
|
|
707
|
+
console.error(`\u2713 ${summary} \u2192 ${resolvedOutput}`);
|
|
708
|
+
} else {
|
|
709
|
+
process.stdout.write(result);
|
|
710
|
+
console.error(`\u2713 ${summary}`);
|
|
711
|
+
}
|
|
712
|
+
return 0;
|
|
713
|
+
}
|
|
714
|
+
|
|
630
715
|
// src/index.ts
|
|
631
716
|
var require2 = createRequire(import.meta.url);
|
|
632
717
|
var { version } = require2("../package.json");
|
|
@@ -635,10 +720,11 @@ if (process.stderr.isTTY) {
|
|
|
635
720
|
`\x1B[36m{[\x1B[0m \x1B[1msquiggly square\x1B[0m \x1B[2m\u2014\x1B[0m \x1B[1msquisq\x1B[0m \x1B[2m\u2014\x1B[0m \x1B[33mv${version}\x1B[0m \x1B[36m]}\x1B[0m`
|
|
636
721
|
);
|
|
637
722
|
}
|
|
638
|
-
var program = new
|
|
723
|
+
var program = new Command2();
|
|
639
724
|
program.name("squisq").description("Squisq CLI \u2014 convert and process markdown-based documents").version(version);
|
|
640
725
|
registerConvertCommand(program);
|
|
641
726
|
registerVideoCommand(program);
|
|
642
727
|
registerValidateCommand(program);
|
|
643
728
|
registerDoctorCommand(program);
|
|
729
|
+
registerTransformCommand(program);
|
|
644
730
|
program.parse();
|