@caretcms/caretize 0.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/README.md +70 -0
- package/dist/backup.d.ts +30 -0
- package/dist/backup.d.ts.map +1 -0
- package/dist/backup.js +89 -0
- package/dist/backup.js.map +1 -0
- package/dist/bind-collection.d.ts +56 -0
- package/dist/bind-collection.d.ts.map +1 -0
- package/dist/bind-collection.js +140 -0
- package/dist/bind-collection.js.map +1 -0
- package/dist/bind-route.d.ts +40 -0
- package/dist/bind-route.d.ts.map +1 -0
- package/dist/bind-route.js +150 -0
- package/dist/bind-route.js.map +1 -0
- package/dist/cli-args.d.ts +30 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +118 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +356 -0
- package/dist/cli.js.map +1 -0
- package/dist/detect.d.ts +76 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +237 -0
- package/dist/detect.js.map +1 -0
- package/dist/discover.d.ts +13 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +84 -0
- package/dist/discover.js.map +1 -0
- package/dist/frontmatter.d.ts +26 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +52 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/identifiers.d.ts +26 -0
- package/dist/identifiers.d.ts.map +1 -0
- package/dist/identifiers.js +34 -0
- package/dist/identifiers.js.map +1 -0
- package/dist/import-wrap.d.ts +56 -0
- package/dist/import-wrap.d.ts.map +1 -0
- package/dist/import-wrap.js +149 -0
- package/dist/import-wrap.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/name.d.ts +49 -0
- package/dist/name.d.ts.map +1 -0
- package/dist/name.js +164 -0
- package/dist/name.js.map +1 -0
- package/dist/output.d.ts +30 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +110 -0
- package/dist/output.js.map +1 -0
- package/dist/parse.d.ts +86 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +92 -0
- package/dist/parse.js.map +1 -0
- package/dist/plan.d.ts +46 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +76 -0
- package/dist/plan.js.map +1 -0
- package/dist/preflight.d.ts +19 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +95 -0
- package/dist/preflight.js.map +1 -0
- package/dist/prop-hoist.d.ts +67 -0
- package/dist/prop-hoist.d.ts.map +1 -0
- package/dist/prop-hoist.js +232 -0
- package/dist/prop-hoist.js.map +1 -0
- package/dist/props.d.ts +38 -0
- package/dist/props.d.ts.map +1 -0
- package/dist/props.js +116 -0
- package/dist/props.js.map +1 -0
- package/dist/report.d.ts +42 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +35 -0
- package/dist/report.js.map +1 -0
- package/dist/resolve.d.ts +15 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +35 -0
- package/dist/resolve.js.map +1 -0
- package/dist/run.d.ts +52 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +213 -0
- package/dist/run.js.map +1 -0
- package/dist/splice.d.ts +43 -0
- package/dist/splice.d.ts.map +1 -0
- package/dist/splice.js +90 -0
- package/dist/splice.js.map +1 -0
- package/dist/usage.d.ts +90 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +249 -0
- package/dist/usage.js.map +1 -0
- package/dist/wrap.d.ts +72 -0
- package/dist/wrap.d.ts.map +1 -0
- package/dist/wrap.js +170 -0
- package/dist/wrap.js.map +1 -0
- package/dist/write.d.ts +28 -0
- package/dist/write.d.ts.map +1 -0
- package/dist/write.js +37 -0
- package/dist/write.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAgC,KAAK,KAAK,EAAE,MAAM,WAAW,CAAC;AAErE,MAAM,WAAW,IAAI;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,aAAa,EAAE,UAAU,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,oFAAoF;AACpF,qBAAa,aAAc,SAAQ,KAAK;CAAG;AAE3C,eAAO,MAAM,IAAI,o9CAwBhB,CAAC;AAEF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA2D9C"}
|
package/dist/cli-args.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Argument parsing + help text for the caretize CLI. Pure and process-free: on a
|
|
3
|
+
* bad flag it throws `CliUsageError` rather than calling process.exit, so the
|
|
4
|
+
* parser is unit-testable and cli.ts owns the actual exit. Keeping this out of
|
|
5
|
+
* cli.ts also keeps that file a thin orchestration shell.
|
|
6
|
+
*/
|
|
7
|
+
import { isValidCollection, isValidId } from "./name.js";
|
|
8
|
+
/** Thrown on an invalid invocation; cli.ts maps it to a stderr message + exit 2. */
|
|
9
|
+
export class CliUsageError extends Error {
|
|
10
|
+
}
|
|
11
|
+
export const HELP = `caretize · make an Astro project editable (data-caret + editable())
|
|
12
|
+
|
|
13
|
+
Usage: caretize [path] [options]
|
|
14
|
+
|
|
15
|
+
path file or directory to scan (default: src/)
|
|
16
|
+
--dry-run print the plan, write nothing
|
|
17
|
+
-y, --yes auto-accept all suggestions at/above min-confidence
|
|
18
|
+
--min-confidence <lvl> high (default) | medium | low
|
|
19
|
+
--no-images skip <img> elements
|
|
20
|
+
--no-props skip hoisting static component-prop strings to editable()
|
|
21
|
+
--bind-collections bind getCollection().map() loops in place — a leaf
|
|
22
|
+
element rendering {item.data.field} gets a per-row
|
|
23
|
+
data-caret (direct-render only; props stay flagged)
|
|
24
|
+
--bind-routes bind a dynamic collection-detail route to the current
|
|
25
|
+
entry — a leaf rendering {entry.data.field} (entry from
|
|
26
|
+
getStaticPaths props) gets a data-caret instead of the
|
|
27
|
+
page being skipped as a dynamic route
|
|
28
|
+
--rich also tag mixed-content blocks whose markup is
|
|
29
|
+
sanitizer-safe inline formatting (data-caret-rich)
|
|
30
|
+
--scope <collection::id> override the inferred scope
|
|
31
|
+
--report <file> write a JSON report
|
|
32
|
+
--restore restore the most recent backup, then exit
|
|
33
|
+
-h, --help show this help
|
|
34
|
+
-v, --version print version
|
|
35
|
+
`;
|
|
36
|
+
export function parseArgs(argv) {
|
|
37
|
+
const a = {
|
|
38
|
+
dryRun: false, yes: false, minConfidence: "high",
|
|
39
|
+
noImages: false, rich: false, noProps: false, bindCollections: false,
|
|
40
|
+
bindRoutes: false, restore: false, help: false, version: false,
|
|
41
|
+
};
|
|
42
|
+
for (let i = 0; i < argv.length; i++) {
|
|
43
|
+
const arg = argv[i];
|
|
44
|
+
switch (arg) {
|
|
45
|
+
case "--dry-run":
|
|
46
|
+
a.dryRun = true;
|
|
47
|
+
break;
|
|
48
|
+
case "-y":
|
|
49
|
+
case "--yes":
|
|
50
|
+
a.yes = true;
|
|
51
|
+
break;
|
|
52
|
+
case "--no-images":
|
|
53
|
+
a.noImages = true;
|
|
54
|
+
break;
|
|
55
|
+
case "--no-props":
|
|
56
|
+
a.noProps = true;
|
|
57
|
+
break;
|
|
58
|
+
case "--bind-collections":
|
|
59
|
+
a.bindCollections = true;
|
|
60
|
+
break;
|
|
61
|
+
case "--bind-routes":
|
|
62
|
+
a.bindRoutes = true;
|
|
63
|
+
break;
|
|
64
|
+
case "--rich":
|
|
65
|
+
a.rich = true;
|
|
66
|
+
break;
|
|
67
|
+
case "--restore":
|
|
68
|
+
a.restore = true;
|
|
69
|
+
break;
|
|
70
|
+
case "--help":
|
|
71
|
+
case "-h":
|
|
72
|
+
a.help = true;
|
|
73
|
+
break;
|
|
74
|
+
case "--version":
|
|
75
|
+
case "-v":
|
|
76
|
+
a.version = true;
|
|
77
|
+
break;
|
|
78
|
+
case "--min-confidence": {
|
|
79
|
+
const v = argv[++i];
|
|
80
|
+
if (v !== "high" && v !== "medium" && v !== "low")
|
|
81
|
+
throw new CliUsageError(`--min-confidence must be high|medium|low`);
|
|
82
|
+
a.minConfidence = v;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case "--scope": {
|
|
86
|
+
const v = argv[++i] ?? "";
|
|
87
|
+
const [collection, id] = v.split("::");
|
|
88
|
+
if (!collection || !id)
|
|
89
|
+
throw new CliUsageError(`--scope must be "collection::id"`);
|
|
90
|
+
// The scope becomes a permanent storage key: a label the runtime
|
|
91
|
+
// rejects would mint bindings that save but never render (and only
|
|
92
|
+
// case-insensitive dev filesystems would mask it).
|
|
93
|
+
if (!isValidCollection(collection)) {
|
|
94
|
+
throw new CliUsageError(`--scope collection "${collection}" is invalid — must match ^[a-z][a-z0-9_-]*$`);
|
|
95
|
+
}
|
|
96
|
+
if (!isValidId(id)) {
|
|
97
|
+
throw new CliUsageError(`--scope id "${id}" is invalid — must match ^[a-z0-9][a-z0-9_-]*$`);
|
|
98
|
+
}
|
|
99
|
+
a.scope = { collection, id };
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
case "--report": {
|
|
103
|
+
const v = argv[++i];
|
|
104
|
+
if (!v || v.startsWith("-")) {
|
|
105
|
+
throw new CliUsageError(`--report needs a file path`);
|
|
106
|
+
}
|
|
107
|
+
a.report = v;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
default:
|
|
111
|
+
if (arg.startsWith("-"))
|
|
112
|
+
throw new CliUsageError(`unknown flag: ${arg}`);
|
|
113
|
+
a.target = arg;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return a;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=cli-args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* caretize CLI — scan an Astro project and add `data-caret` attributes.
|
|
4
|
+
*
|
|
5
|
+
* Thin shell over the engine (discover → plan → prepare → commit). The
|
|
6
|
+
* load-bearing logic lives in the tested modules; this file is the interactive
|
|
7
|
+
* review loop plus orchestration. Argument parsing lives in ./cli-args, output
|
|
8
|
+
* formatting in ./output — both pure and unit-tested.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* caretize CLI — scan an Astro project and add `data-caret` attributes.
|
|
4
|
+
*
|
|
5
|
+
* Thin shell over the engine (discover → plan → prepare → commit). The
|
|
6
|
+
* load-bearing logic lives in the tested modules; this file is the interactive
|
|
7
|
+
* review loop plus orchestration. Argument parsing lives in ./cli-args, output
|
|
8
|
+
* formatting in ./output — both pure and unit-tested.
|
|
9
|
+
*/
|
|
10
|
+
import { createInterface } from "node:readline";
|
|
11
|
+
import { writeFileSync } from "node:fs";
|
|
12
|
+
import { relative } from "node:path";
|
|
13
|
+
import { parseAstro } from "./parse.js";
|
|
14
|
+
import { discoverAstroFiles } from "./discover.js";
|
|
15
|
+
import { preflight } from "./preflight.js";
|
|
16
|
+
import { planFile } from "./plan.js";
|
|
17
|
+
import { prepareFileFull, commitRun, readSource } from "./run.js";
|
|
18
|
+
import { detectWrapTargetsSafe } from "./wrap.js";
|
|
19
|
+
import { detectImportWrapTargetsSafe } from "./import-wrap.js";
|
|
20
|
+
import { detectPropWrapTargets } from "./props.js";
|
|
21
|
+
import { detectPropHoistTargets } from "./prop-hoist.js";
|
|
22
|
+
import { detectCollectionBindTargets } from "./bind-collection.js";
|
|
23
|
+
import { detectRouteBindTargets } from "./bind-route.js";
|
|
24
|
+
import { restoreLatest } from "./backup.js";
|
|
25
|
+
import { buildReport } from "./report.js";
|
|
26
|
+
import { isValidField } from "./name.js";
|
|
27
|
+
import { parseArgs, CliUsageError, HELP } from "./cli-args.js";
|
|
28
|
+
import { tagLine, formatScanSummary, formatPlan, formatSummary, formatHints } from "./output.js";
|
|
29
|
+
const VERSION = "0.1.0";
|
|
30
|
+
function fail(msg) {
|
|
31
|
+
process.stderr.write(`caretize: ${msg}\n`);
|
|
32
|
+
process.exit(2);
|
|
33
|
+
}
|
|
34
|
+
function ask(rl, q) {
|
|
35
|
+
return new Promise((res) => rl.question(q, (ans) => res(ans.trim())));
|
|
36
|
+
}
|
|
37
|
+
/** Prompt for a replacement field name on one tag. Returns the tag to keep: the
|
|
38
|
+
* edited tag for a valid name, the original when the prompt is left blank, or
|
|
39
|
+
* null when a non-empty name is invalid (the candidate is dropped). */
|
|
40
|
+
async function editField(rl, t) {
|
|
41
|
+
const field = await ask(rl, ` new field name (${t.field}): `);
|
|
42
|
+
if (field && isValidField(field)) {
|
|
43
|
+
return { ...t, field, binding: `${t.collection}::${t.id}::${field}`, attribute: `data-caret="${t.collection}::${t.id}::${field}"` };
|
|
44
|
+
}
|
|
45
|
+
process.stdout.write(field ? " invalid field name; skipped\n" : " kept original\n");
|
|
46
|
+
return field ? null : t;
|
|
47
|
+
}
|
|
48
|
+
/** Per-candidate prompt for one file. Returns the accepted tags plus control
|
|
49
|
+
* signals: `quit` aborts the whole run, `skipFile` skips this file's wrap/hoist
|
|
50
|
+
* prompts, and `acceptAll` carries the sticky [A]ll choice on to later files. */
|
|
51
|
+
async function reviewFileTags(rl, plan, acceptAll) {
|
|
52
|
+
const take = [];
|
|
53
|
+
let skipFile = false;
|
|
54
|
+
for (let i = 0; i < plan.tags.length && !skipFile; i++) {
|
|
55
|
+
const t = plan.tags[i];
|
|
56
|
+
if (acceptAll) {
|
|
57
|
+
take.push(t);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
process.stdout.write(`\n${plan.relPath}\n ${tagLine(t)}\n + data-caret="${t.binding}" (${t.confidence})\n`);
|
|
61
|
+
// Only explicit answers act; anything unrecognized re-prompts. The old
|
|
62
|
+
// fall-through-to-accept made a typo — including the natural "n" — mint a
|
|
63
|
+
// permanent storage key.
|
|
64
|
+
let answered = false;
|
|
65
|
+
while (!answered) {
|
|
66
|
+
const ans = (await ask(rl, " [a]ccept [s]kip [e]dit [A]ll [S]kip-file [q]uit > ")) || "a";
|
|
67
|
+
answered = true;
|
|
68
|
+
if (ans === "q")
|
|
69
|
+
return { take, skipFile, quit: true, acceptAll };
|
|
70
|
+
else if (ans === "S")
|
|
71
|
+
skipFile = true;
|
|
72
|
+
else if (ans === "A") {
|
|
73
|
+
acceptAll = true;
|
|
74
|
+
take.push(t);
|
|
75
|
+
}
|
|
76
|
+
else if (ans === "s" || ans === "n" || ans === "N") { /* skip */ }
|
|
77
|
+
else if (ans === "e") {
|
|
78
|
+
const edited = await editField(rl, t);
|
|
79
|
+
if (edited)
|
|
80
|
+
take.push(edited);
|
|
81
|
+
}
|
|
82
|
+
else if (ans === "a" || ans === "y" || ans === "Y")
|
|
83
|
+
take.push(t);
|
|
84
|
+
else {
|
|
85
|
+
process.stdout.write(" unrecognized — a(ccept) s(kip) e(dit) A(ll) S(kip-file) q(uit)\n");
|
|
86
|
+
answered = false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { take, skipFile, quit: false, acceptAll };
|
|
91
|
+
}
|
|
92
|
+
/** Confirm wrapping a file's data array(s) with editable(). */
|
|
93
|
+
async function confirmWraps(rl, relPath, fileWraps) {
|
|
94
|
+
const names = fileWraps.map((w) => w.varName).join(", ");
|
|
95
|
+
const ans = (await ask(rl, `\n${relPath}\n wrap ${fileWraps.length} data array(s) [${names}] with editable()? [Y/n] `)) || "y";
|
|
96
|
+
return ans.toLowerCase() !== "n";
|
|
97
|
+
}
|
|
98
|
+
/** Per-component confirm for hoisting static prop string(s) to editable(). */
|
|
99
|
+
async function confirmHoists(rl, relPath, fileHoists) {
|
|
100
|
+
const take = [];
|
|
101
|
+
for (const h of fileHoists) {
|
|
102
|
+
const lines = h.props
|
|
103
|
+
.map((p) => {
|
|
104
|
+
const v = p.literalValue.replace(/\s+/g, " ").slice(0, 40);
|
|
105
|
+
const rich = p.isRich ? " [rich]" : "";
|
|
106
|
+
return ` ${p.propName}="${v}"${rich} → ${p.propName}={${p.constName}} (editable "${p.key}")`;
|
|
107
|
+
})
|
|
108
|
+
.join("\n");
|
|
109
|
+
const ans = (await ask(rl, `\n${relPath}\n <${h.componentName}> — hoist ${h.props.length} prop(s) to editable()?\n${lines}\n [Y/n] `)) || "y";
|
|
110
|
+
if (ans.toLowerCase() !== "n")
|
|
111
|
+
take.push(h);
|
|
112
|
+
}
|
|
113
|
+
return take;
|
|
114
|
+
}
|
|
115
|
+
/** Interactive review: per-candidate tags, then per-file wrap + prop-hoist confirms.
|
|
116
|
+
* Collection bindings (opt-in via --bind-collections) are auto-accepted per file
|
|
117
|
+
* — the flag is the consent — unless the file is skipped or the run is quit. */
|
|
118
|
+
async function review(plans, wrapsByFile, hoistsByFile, bindsByFile) {
|
|
119
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
120
|
+
// Without a listener, readline swallows Ctrl-C and the process hangs at the
|
|
121
|
+
// prompt. Nothing is written until commitRun (after the review), so exiting
|
|
122
|
+
// here is always safe.
|
|
123
|
+
rl.on("SIGINT", () => {
|
|
124
|
+
process.stdout.write("\naborted — nothing written\n");
|
|
125
|
+
process.exit(130);
|
|
126
|
+
});
|
|
127
|
+
const tags = new Map();
|
|
128
|
+
const wraps = new Map();
|
|
129
|
+
const hoists = new Map();
|
|
130
|
+
const binds = new Map();
|
|
131
|
+
let acceptAll = false;
|
|
132
|
+
try {
|
|
133
|
+
for (const plan of plans) {
|
|
134
|
+
const fileWraps = wrapsByFile.get(plan.relPath) ?? [];
|
|
135
|
+
const fileHoists = hoistsByFile.get(plan.relPath) ?? [];
|
|
136
|
+
const fileBinds = bindsByFile.get(plan.relPath) ?? [];
|
|
137
|
+
if (plan.tags.length === 0 && fileWraps.length === 0 && fileHoists.length === 0 && fileBinds.length === 0)
|
|
138
|
+
continue;
|
|
139
|
+
const res = await reviewFileTags(rl, plan, acceptAll);
|
|
140
|
+
acceptAll = res.acceptAll;
|
|
141
|
+
if (res.quit) {
|
|
142
|
+
tags.clear();
|
|
143
|
+
wraps.clear();
|
|
144
|
+
hoists.clear();
|
|
145
|
+
binds.clear();
|
|
146
|
+
return { tags, wraps, hoists, binds, quit: true };
|
|
147
|
+
}
|
|
148
|
+
if (res.take.length)
|
|
149
|
+
tags.set(plan.relPath, res.take);
|
|
150
|
+
if (res.skipFile)
|
|
151
|
+
continue;
|
|
152
|
+
if (fileWraps.length > 0 && (await confirmWraps(rl, plan.relPath, fileWraps))) {
|
|
153
|
+
wraps.set(plan.relPath, fileWraps);
|
|
154
|
+
}
|
|
155
|
+
if (fileHoists.length > 0) {
|
|
156
|
+
const take = await confirmHoists(rl, plan.relPath, fileHoists);
|
|
157
|
+
if (take.length)
|
|
158
|
+
hoists.set(plan.relPath, take);
|
|
159
|
+
}
|
|
160
|
+
if (fileBinds.length > 0)
|
|
161
|
+
binds.set(plan.relPath, fileBinds);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
rl.close();
|
|
166
|
+
}
|
|
167
|
+
return { tags, wraps, hoists, binds, quit: false };
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Parse each file ONCE, then drive all detection passes off that single AST:
|
|
171
|
+
* - planFile: the data-caret tag plan
|
|
172
|
+
* - detectWrapTargetsSafe: same-file data-array loops (Tier-1), dropped when a
|
|
173
|
+
* field would land in a native attribute
|
|
174
|
+
* - detectPropWrapTargets: literals passed to a component whose child provably
|
|
175
|
+
* renders them as text (Tier-2, cross-file)
|
|
176
|
+
* - detectImportWrapTargetsSafe: arrays pulled in from a data import (Tier-3)
|
|
177
|
+
* - detectPropHoistTargets: static component-prop strings (unless --no-props)
|
|
178
|
+
*/
|
|
179
|
+
async function analyzeFiles(root, files, planOpts, readFileSafe, noProps, bindCollections, bindRoutes) {
|
|
180
|
+
const plans = [];
|
|
181
|
+
const wrapsByFile = new Map();
|
|
182
|
+
const hoistsByFile = new Map();
|
|
183
|
+
const bindsByFile = new Map();
|
|
184
|
+
for (const rel of files) {
|
|
185
|
+
const src = readSource(root, rel);
|
|
186
|
+
const ast = await parseAstro(src);
|
|
187
|
+
const plan = await planFile(src, rel, planOpts, ast);
|
|
188
|
+
plans.push(plan);
|
|
189
|
+
const loops = await detectWrapTargetsSafe(src, rel, ast);
|
|
190
|
+
const props = await detectPropWrapTargets(src, rel, readFileSafe, ast);
|
|
191
|
+
const imports = await detectImportWrapTargetsSafe(src, rel, ast);
|
|
192
|
+
const byName = new Map();
|
|
193
|
+
for (const t of [...loops, ...props, ...imports])
|
|
194
|
+
byName.set(t.varName, t);
|
|
195
|
+
if (byName.size)
|
|
196
|
+
wrapsByFile.set(rel, [...byName.values()]);
|
|
197
|
+
// Tier-5 (--bind-collections): bind direct-render getCollection().map() loops.
|
|
198
|
+
// Tier-6 (--bind-routes): bind a dynamic detail page to its current entry.
|
|
199
|
+
const binds = [
|
|
200
|
+
...(bindCollections ? detectCollectionBindTargets(src, ast) : []),
|
|
201
|
+
...(bindRoutes ? detectRouteBindTargets(src, ast) : []),
|
|
202
|
+
];
|
|
203
|
+
if (binds.length)
|
|
204
|
+
bindsByFile.set(rel, binds);
|
|
205
|
+
const boundReceivers = new Set(binds.map((b) => b.receiver));
|
|
206
|
+
// A loop whose receiver a wrap tier (Tier-1/Tier-3) OR a bind tier (Tier-5)
|
|
207
|
+
// just made editable no longer warrants the "consider a dynamic collection"
|
|
208
|
+
// flag — suppress it so we don't tell the user to rethink a covered loop.
|
|
209
|
+
plan.flags = plan.flags.filter((f) => !f.receiver || (!byName.has(f.receiver) && !boundReceivers.has(f.receiver)));
|
|
210
|
+
if (!noProps) {
|
|
211
|
+
const hoists = await detectPropHoistTargets(src, rel, readFileSafe, ast);
|
|
212
|
+
if (hoists.length)
|
|
213
|
+
hoistsByFile.set(rel, hoists);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return { plans, wrapsByFile, hoistsByFile, bindsByFile };
|
|
217
|
+
}
|
|
218
|
+
/** Decide what to apply: everything (dry-run / -y), the interactive review, or
|
|
219
|
+
* nothing (report-only). Errors out on a non-interactive run with no directive. */
|
|
220
|
+
async function selectChanges(args, a) {
|
|
221
|
+
if (args.dryRun || args.yes) {
|
|
222
|
+
const allTags = new Map(a.plans.map((p) => [p.relPath, p.tags]));
|
|
223
|
+
return { tags: allTags, wraps: a.wrapsByFile, hoists: a.hoistsByFile, binds: a.bindsByFile, quit: false };
|
|
224
|
+
}
|
|
225
|
+
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
226
|
+
return review(a.plans, a.wrapsByFile, a.hoistsByFile, a.bindsByFile);
|
|
227
|
+
}
|
|
228
|
+
if (args.report)
|
|
229
|
+
return { tags: new Map(), wraps: new Map(), hoists: new Map(), binds: new Map(), quit: false };
|
|
230
|
+
fail("non-interactive terminal: pass --dry-run, -y, or --report");
|
|
231
|
+
}
|
|
232
|
+
/** Prepare (verify) every touched file in memory — tags + binds + wraps + hoists. */
|
|
233
|
+
async function prepareTouched(root, sel) {
|
|
234
|
+
const touched = new Set([
|
|
235
|
+
...sel.tags.keys(), ...sel.wraps.keys(), ...sel.hoists.keys(), ...sel.binds.keys(),
|
|
236
|
+
]);
|
|
237
|
+
const prepared = [];
|
|
238
|
+
for (const rel of touched) {
|
|
239
|
+
const tags = sel.tags.get(rel) ?? [];
|
|
240
|
+
const targets = sel.wraps.get(rel) ?? [];
|
|
241
|
+
const hoistTargets = sel.hoists.get(rel) ?? [];
|
|
242
|
+
const fileBinds = sel.binds.get(rel) ?? [];
|
|
243
|
+
if (tags.length === 0 && targets.length === 0 && hoistTargets.length === 0 && fileBinds.length === 0)
|
|
244
|
+
continue;
|
|
245
|
+
// Collection bindings are dynamic data-caret attributes — they splice exactly
|
|
246
|
+
// like data-caret tags, so they ride the same offset-ordered tag pass.
|
|
247
|
+
const tagSplices = [
|
|
248
|
+
...tags.map((t) => ({ startOffset: t.startOffset, attribute: t.attribute })),
|
|
249
|
+
...fileBinds.map((b) => ({ startOffset: b.startOffset, attribute: b.attribute })),
|
|
250
|
+
];
|
|
251
|
+
prepared.push(await prepareFileFull(rel, readSource(root, rel), tagSplices, targets, hoistTargets));
|
|
252
|
+
}
|
|
253
|
+
return prepared;
|
|
254
|
+
}
|
|
255
|
+
/** Tally what was actually written and print the closing summary. */
|
|
256
|
+
function printCommit(written, hadBackups, prepared, sel, plans) {
|
|
257
|
+
const changes = prepared
|
|
258
|
+
.filter((p) => written.includes(p.relPath))
|
|
259
|
+
.reduce((n, p) => n + p.tagCount, 0);
|
|
260
|
+
const wrapped = written.reduce((n, rel) => n + (sel.wraps.get(rel)?.length ?? 0), 0);
|
|
261
|
+
const hoisted = written.reduce((n, rel) => n + (sel.hoists.get(rel)?.reduce((m, t) => m + t.props.length, 0) ?? 0), 0);
|
|
262
|
+
const bound = written.reduce((n, rel) => n + (sel.binds.get(rel)?.length ?? 0), 0);
|
|
263
|
+
const flagged = plans.reduce((n, p) => n + p.flags.length, 0);
|
|
264
|
+
process.stdout.write(formatSummary(written.length, changes, wrapped, hoisted, flagged, hadBackups, bound));
|
|
265
|
+
}
|
|
266
|
+
/** Restore the most recent backup, reporting how many files came back. */
|
|
267
|
+
function runRestore(root) {
|
|
268
|
+
const restored = restoreLatest(root);
|
|
269
|
+
process.stdout.write(restored.length
|
|
270
|
+
? `✓ restored ${restored.length} file(s):\n${restored.map((f) => ` ${f}`).join("\n")}\n`
|
|
271
|
+
: "no backups found.\n");
|
|
272
|
+
}
|
|
273
|
+
async function main() {
|
|
274
|
+
let args;
|
|
275
|
+
try {
|
|
276
|
+
args = parseArgs(process.argv.slice(2));
|
|
277
|
+
}
|
|
278
|
+
catch (e) {
|
|
279
|
+
if (e instanceof CliUsageError)
|
|
280
|
+
fail(e.message);
|
|
281
|
+
throw e;
|
|
282
|
+
}
|
|
283
|
+
if (args.help) {
|
|
284
|
+
process.stdout.write(HELP);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
if (args.version) {
|
|
288
|
+
process.stdout.write(`${VERSION}\n`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const root = process.cwd();
|
|
292
|
+
if (args.restore) {
|
|
293
|
+
runRestore(root);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const pf = preflight(root);
|
|
297
|
+
for (const w of pf.warnings)
|
|
298
|
+
process.stdout.write(`⚠ ${w}\n`);
|
|
299
|
+
if (pf.errors.length) {
|
|
300
|
+
for (const e of pf.errors)
|
|
301
|
+
process.stderr.write(`✗ ${e}\n`);
|
|
302
|
+
process.exit(1);
|
|
303
|
+
}
|
|
304
|
+
const files = discoverAstroFiles(root, args.target);
|
|
305
|
+
const planOpts = {
|
|
306
|
+
minConfidence: args.minConfidence,
|
|
307
|
+
noImages: args.noImages,
|
|
308
|
+
rich: args.rich,
|
|
309
|
+
scope: args.scope,
|
|
310
|
+
};
|
|
311
|
+
process.stdout.write(`caretize · scanning ${args.target ?? "src/"}\n`);
|
|
312
|
+
// A child file that can't be read (any reason) conservatively yields null, so
|
|
313
|
+
// the cross-file prop pass simply skips that hand-off rather than guessing.
|
|
314
|
+
const readFileSafe = (rel) => {
|
|
315
|
+
try {
|
|
316
|
+
return readSource(root, rel);
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
const analysis = await analyzeFiles(root, files, planOpts, readFileSafe, args.noProps, args.bindCollections, args.bindRoutes);
|
|
323
|
+
process.stdout.write(formatScanSummary(files.length, analysis.plans, analysis.wrapsByFile, analysis.hoistsByFile, analysis.bindsByFile));
|
|
324
|
+
const sel = await selectChanges(args, analysis);
|
|
325
|
+
const hintOpts = { bindCollections: args.bindCollections, bindRoutes: args.bindRoutes };
|
|
326
|
+
if (sel.quit) {
|
|
327
|
+
process.stdout.write("\naborted — nothing written\n");
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const prepared = await prepareTouched(root, sel);
|
|
331
|
+
if (args.report) {
|
|
332
|
+
writeFileSync(args.report, JSON.stringify(buildReport(analysis.plans, prepared), null, 2));
|
|
333
|
+
process.stdout.write(`⤓ report → ${relative(root, args.report) || args.report}\n`);
|
|
334
|
+
}
|
|
335
|
+
if (args.dryRun) {
|
|
336
|
+
process.stdout.write(formatPlan(analysis.plans, analysis.wrapsByFile, analysis.hoistsByFile, analysis.bindsByFile));
|
|
337
|
+
process.stdout.write(formatHints(analysis.plans, args.rich, hintOpts));
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
341
|
+
const { written, backups } = commitRun(root, prepared, stamp);
|
|
342
|
+
if (written.length === 0) {
|
|
343
|
+
// Don't print the "click to edit" success footer for a no-op run — say
|
|
344
|
+
// why nothing matched and which flag unlocks the skipped candidates.
|
|
345
|
+
process.stdout.write("\nno changes written.\n");
|
|
346
|
+
process.stdout.write(formatHints(analysis.plans, args.rich, hintOpts));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
printCommit(written, backups.length > 0, prepared, sel, analysis.plans);
|
|
350
|
+
process.stdout.write(formatHints(analysis.plans, args.rich, hintOpts));
|
|
351
|
+
}
|
|
352
|
+
main().catch((err) => {
|
|
353
|
+
process.stderr.write(`caretize: ${err.message}\n`);
|
|
354
|
+
process.exit(1);
|
|
355
|
+
});
|
|
356
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/detect.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detection: decide which tag nodes are edit candidates.
|
|
3
|
+
*
|
|
4
|
+
* The guiding rule — proven necessary by real-world fixtures — is that the
|
|
5
|
+
* candidate set must equal *what the CaretCMS rewrite engine can actually
|
|
6
|
+
* round-trip*. The engine only swaps the text content of a pure text-leaf
|
|
7
|
+
* element (no child markup, unless `data-caret-rich`) and the `src` of an
|
|
8
|
+
* `<img>`. So we tag exactly those and nothing else; anything we can't faithfully
|
|
9
|
+
* edit is skipped (with a reason) rather than tagged into an inert binding.
|
|
10
|
+
*/
|
|
11
|
+
import { type AstroNode, type TagNode } from "./parse.js";
|
|
12
|
+
export type Confidence = "high" | "medium" | "low";
|
|
13
|
+
export type CandidateKind = "text" | "image";
|
|
14
|
+
export interface Candidate {
|
|
15
|
+
decision: "tag";
|
|
16
|
+
kind: CandidateKind;
|
|
17
|
+
node: TagNode;
|
|
18
|
+
tag: string;
|
|
19
|
+
startOffset: number;
|
|
20
|
+
confidence: Confidence;
|
|
21
|
+
/** The static text content (text candidates) or current src (image). */
|
|
22
|
+
text: string;
|
|
23
|
+
/**
|
|
24
|
+
* True for a rich candidate: the element has child markup, but all of it is
|
|
25
|
+
* sanitizer-safe inline formatting, so it's tagged `data-caret-rich`. Only
|
|
26
|
+
* emitted when `detect` runs with `{ rich: true }`.
|
|
27
|
+
*/
|
|
28
|
+
rich?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface DetectOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Enable rich promotion: tag a mixed-content element as `data-caret-rich`
|
|
33
|
+
* when every descendant is sanitizer-safe inline markup (no classes/attrs,
|
|
34
|
+
* no components, no expressions). Off by default — promotion is a judgment
|
|
35
|
+
* call, so it's opt-in via the CLI `--rich` flag.
|
|
36
|
+
*/
|
|
37
|
+
rich?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface Skipped {
|
|
40
|
+
decision: "skip";
|
|
41
|
+
node: TagNode;
|
|
42
|
+
tag: string;
|
|
43
|
+
startOffset: number;
|
|
44
|
+
reason: SkipReason;
|
|
45
|
+
}
|
|
46
|
+
export type SkipReason = "already-tagged" | "component" | "inside-expression" | "inside-iterator" | "dynamic-content" | "inside-rich" | "mixed-children" | "rich-eligible" | "rich-unsafe-attrs" | "empty" | "not-content";
|
|
47
|
+
export interface IteratorFlag {
|
|
48
|
+
/** Byte offset of the enclosing expression. */
|
|
49
|
+
startOffset: number;
|
|
50
|
+
/** The iterator method that triggered the flag (map/filter/...). */
|
|
51
|
+
method: string;
|
|
52
|
+
/** The variable being iterated (`faqs` in `faqs.map(...)`), when a plain
|
|
53
|
+
* identifier — lets the CLI drop the flag for a loop a wrap tier covered. */
|
|
54
|
+
receiver?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface DetectResult {
|
|
57
|
+
candidates: Candidate[];
|
|
58
|
+
skipped: Skipped[];
|
|
59
|
+
/** ".map()"-style blocks to surface as "consider a dynamic collection". */
|
|
60
|
+
flags: IteratorFlag[];
|
|
61
|
+
}
|
|
62
|
+
export declare const CONFIDENCE: Record<string, Confidence>;
|
|
63
|
+
/** Can the rewrite engine swap this tag's text content? Gate for every tier
|
|
64
|
+
* that emits a text binding (tag pass via CONFIDENCE, bind tiers directly). */
|
|
65
|
+
export declare function isRewritableTextTag(tag: string): boolean;
|
|
66
|
+
export declare const RICH_INLINE_TAGS: Set<string>;
|
|
67
|
+
export declare const RICH_SAFE_ATTRS: Record<string, Set<string>>;
|
|
68
|
+
export declare const SAFE_HREF_RE: RegExp;
|
|
69
|
+
/**
|
|
70
|
+
* Walk a parsed root and classify every tag node.
|
|
71
|
+
*
|
|
72
|
+
* `walk` is injected (the caller passes `walkTags`) so this module stays a pure
|
|
73
|
+
* classifier with no parse dependency beyond the node shape.
|
|
74
|
+
*/
|
|
75
|
+
export declare function detect(root: AstroNode, walk: (root: AstroNode, visit: (n: TagNode, ancestors: AstroNode[]) => void) => void, options?: DetectOptions): DetectResult;
|
|
76
|
+
//# sourceMappingURL=detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAa,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AACnD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7C,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,KAAK,CAAC;IAChB,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,MAAM,UAAU,GAClB,gBAAgB,GAChB,WAAW,GACX,mBAAmB,GACnB,iBAAiB,GACjB,iBAAiB,GACjB,aAAa,GACb,gBAAgB,GAChB,eAAe,GACf,mBAAmB,GACnB,OAAO,GACP,aAAa,CAAC;AAElB,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf;kFAC8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,2EAA2E;IAC3E,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AASD,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAOjD,CAAC;AAEF;gFACgF;AAChF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAExD;AAcD,eAAO,MAAM,gBAAgB,aAE3B,CAAC;AAOH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAEvD,CAAC;AACF,eAAO,MAAM,YAAY,QAAkC,CAAC;AA+F5D;;;;;GAKG;AACH,wBAAgB,MAAM,CACpB,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,IAAI,KAAK,IAAI,EACpF,OAAO,GAAE,aAAkB,GAC1B,YAAY,CAmFd"}
|