@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.
Files changed (102) hide show
  1. package/README.md +70 -0
  2. package/dist/backup.d.ts +30 -0
  3. package/dist/backup.d.ts.map +1 -0
  4. package/dist/backup.js +89 -0
  5. package/dist/backup.js.map +1 -0
  6. package/dist/bind-collection.d.ts +56 -0
  7. package/dist/bind-collection.d.ts.map +1 -0
  8. package/dist/bind-collection.js +140 -0
  9. package/dist/bind-collection.js.map +1 -0
  10. package/dist/bind-route.d.ts +40 -0
  11. package/dist/bind-route.d.ts.map +1 -0
  12. package/dist/bind-route.js +150 -0
  13. package/dist/bind-route.js.map +1 -0
  14. package/dist/cli-args.d.ts +30 -0
  15. package/dist/cli-args.d.ts.map +1 -0
  16. package/dist/cli-args.js +118 -0
  17. package/dist/cli-args.js.map +1 -0
  18. package/dist/cli.d.ts +11 -0
  19. package/dist/cli.d.ts.map +1 -0
  20. package/dist/cli.js +356 -0
  21. package/dist/cli.js.map +1 -0
  22. package/dist/detect.d.ts +76 -0
  23. package/dist/detect.d.ts.map +1 -0
  24. package/dist/detect.js +237 -0
  25. package/dist/detect.js.map +1 -0
  26. package/dist/discover.d.ts +13 -0
  27. package/dist/discover.d.ts.map +1 -0
  28. package/dist/discover.js +84 -0
  29. package/dist/discover.js.map +1 -0
  30. package/dist/frontmatter.d.ts +26 -0
  31. package/dist/frontmatter.d.ts.map +1 -0
  32. package/dist/frontmatter.js +52 -0
  33. package/dist/frontmatter.js.map +1 -0
  34. package/dist/identifiers.d.ts +26 -0
  35. package/dist/identifiers.d.ts.map +1 -0
  36. package/dist/identifiers.js +34 -0
  37. package/dist/identifiers.js.map +1 -0
  38. package/dist/import-wrap.d.ts +56 -0
  39. package/dist/import-wrap.d.ts.map +1 -0
  40. package/dist/import-wrap.js +149 -0
  41. package/dist/import-wrap.js.map +1 -0
  42. package/dist/index.d.ts +18 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +18 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/name.d.ts +49 -0
  47. package/dist/name.d.ts.map +1 -0
  48. package/dist/name.js +164 -0
  49. package/dist/name.js.map +1 -0
  50. package/dist/output.d.ts +30 -0
  51. package/dist/output.d.ts.map +1 -0
  52. package/dist/output.js +110 -0
  53. package/dist/output.js.map +1 -0
  54. package/dist/parse.d.ts +86 -0
  55. package/dist/parse.d.ts.map +1 -0
  56. package/dist/parse.js +92 -0
  57. package/dist/parse.js.map +1 -0
  58. package/dist/plan.d.ts +46 -0
  59. package/dist/plan.d.ts.map +1 -0
  60. package/dist/plan.js +76 -0
  61. package/dist/plan.js.map +1 -0
  62. package/dist/preflight.d.ts +19 -0
  63. package/dist/preflight.d.ts.map +1 -0
  64. package/dist/preflight.js +95 -0
  65. package/dist/preflight.js.map +1 -0
  66. package/dist/prop-hoist.d.ts +67 -0
  67. package/dist/prop-hoist.d.ts.map +1 -0
  68. package/dist/prop-hoist.js +232 -0
  69. package/dist/prop-hoist.js.map +1 -0
  70. package/dist/props.d.ts +38 -0
  71. package/dist/props.d.ts.map +1 -0
  72. package/dist/props.js +116 -0
  73. package/dist/props.js.map +1 -0
  74. package/dist/report.d.ts +42 -0
  75. package/dist/report.d.ts.map +1 -0
  76. package/dist/report.js +35 -0
  77. package/dist/report.js.map +1 -0
  78. package/dist/resolve.d.ts +15 -0
  79. package/dist/resolve.d.ts.map +1 -0
  80. package/dist/resolve.js +35 -0
  81. package/dist/resolve.js.map +1 -0
  82. package/dist/run.d.ts +52 -0
  83. package/dist/run.d.ts.map +1 -0
  84. package/dist/run.js +213 -0
  85. package/dist/run.js.map +1 -0
  86. package/dist/splice.d.ts +43 -0
  87. package/dist/splice.d.ts.map +1 -0
  88. package/dist/splice.js +90 -0
  89. package/dist/splice.js.map +1 -0
  90. package/dist/usage.d.ts +90 -0
  91. package/dist/usage.d.ts.map +1 -0
  92. package/dist/usage.js +249 -0
  93. package/dist/usage.js.map +1 -0
  94. package/dist/wrap.d.ts +72 -0
  95. package/dist/wrap.d.ts.map +1 -0
  96. package/dist/wrap.js +170 -0
  97. package/dist/wrap.js.map +1 -0
  98. package/dist/write.d.ts +28 -0
  99. package/dist/write.d.ts.map +1 -0
  100. package/dist/write.js +37 -0
  101. package/dist/write.js.map +1 -0
  102. 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"}
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -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"}