@bettercms-ai/convert 0.24.0 → 0.25.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/index.d.ts CHANGED
@@ -955,7 +955,7 @@ declare function attrsFor(path: string, kind: string, props?: AttrBinding[], sco
955
955
  declare function propsAttribute(props: AttrBinding[]): string;
956
956
 
957
957
  /** Bumped whenever the emitted source changes. `isKnownHelper` upgrades anything older. */
958
- declare const HELPER_VERSION = 12;
958
+ declare const HELPER_VERSION = 13;
959
959
  /** Where each dialect's helper lives. Null = this dialect reads nothing at build time. */
960
960
  declare const HELPER_PATH: Record<Dialect, string | null>;
961
961
  /** The directory the snapshots live in, at the repository root. */
@@ -1853,6 +1853,36 @@ declare function readBrief(value: unknown): Brief;
1853
1853
  */
1854
1854
  declare function readPlan(value: unknown): ComponentizePlan;
1855
1855
 
1856
+ /**
1857
+ * `build:bcms` — the build BetterCMS runs instead of `build`, when a repository declares one.
1858
+ *
1859
+ * The builder runs `build:bcms` in place of `build` (as Vercel runs `vercel-build`), and never edits
1860
+ * a project's build script itself. A converted repository's `build` usually chains the checks its
1861
+ * own CI wants in front of the build — `astro check && astro build` — and every BetterCMS deploy
1862
+ * paid for them: the type check alone was 8–10 s of a warm ScrewFast build. This writes the same
1863
+ * build without those checks, once, beside the script it came from. `build` is left exactly as it
1864
+ * was, so the project's own CI still checks everything.
1865
+ *
1866
+ * Only a script it can read with certainty: steps joined by `&&` and nothing else. A `;`, `||`,
1867
+ * pipe, background `&` or substitution means the steps do not simply run in order, and that script
1868
+ * is left alone. `prebuild` and `postbuild` are folded in (minus their own checks), because a run
1869
+ * of `build:bcms` triggers `prebuild:bcms`, not `prebuild` — dropping them would lose a step the
1870
+ * build needs (ScrewFast splits its content snapshot in `prebuild`).
1871
+ */
1872
+ interface BcmsBuild {
1873
+ /** The new package.json, formatted as the original was. */
1874
+ content: string;
1875
+ /** The `build:bcms` it adds. */
1876
+ script: string;
1877
+ /** The steps of `build` (and its pre/post hooks) left out of it. */
1878
+ dropped: string[];
1879
+ }
1880
+ /**
1881
+ * The package.json with a `build:bcms` added, or null when there is nothing to add: one already
1882
+ * exists, no `build` chains a check, or a script is not one it can read with certainty.
1883
+ */
1884
+ declare function bcmsBuildScript(packageJson: string): BcmsBuild | null;
1885
+
1856
1886
  /** The plan's own file shape, restated rather than imported to keep `index.ts` acyclic. */
1857
1887
  interface UpgradeFile {
1858
1888
  path: string;
@@ -1965,4 +1995,4 @@ declare function convertSources(briefIn: Brief, sources: SourceFile[], options?:
1965
1995
  receipt: ConversionReceipt;
1966
1996
  }>;
1967
1997
 
1968
- export { ASTRO_LANE_PENDING, type AstNode, type AttrBinding, type Brief, type BriefForm, type BriefPage, type BriefPath, COMPONENT_DIR, CONTENT_DIR, type CanvasResult, type CanvasSource, type Carried, type ComponentizeOptions, type ComponentizePlan, type ComponentizePlanComponent, type ComponentizePlanField, type ComponentizePlanPage, type ComponentizePlanSection, type ComponentizeReceipt, type ConversionReceipt, ConvertError, type ConvertErrorCode, type ConvertOptions, DIALECT_RULES, type DataMember, type DataResult, type DeclaredPath, type Dialect, type DynamicBinding, FORM_SCRIPT, type FileDeclaration, type FindSitesResult, type FixAction, FormInvariantError, type FormPendingReason, type FormsReceipt, HELPER_PATH, HELPER_VERSION, type HelperUpgrade, type ImageResult, type ImageTarget, type ImportedFrom, type LlmFallback, type LocatedPath, type Node, PARSE_FILE, type ParsedFile, type ParserError, type PathLocator, type PendingFix, type PendingForm, type PendingPath, type PendingReason, type PendingSection, type PlanFile, REGISTRY_MARKER, type ReceiptFile, ReceiptInvariantError, type ReceiptNote, type Rewrite, SECTIONS_LIB, SECTION_MARKER, SKIP_DIRS, SKIP_FILES, SOURCE_EXTENSIONS, SSR_DRAFT_RECIPE, STUB_CONTENT, SectionInvariantError, type SectionPendingReason, type SectionUpgradeReceipt, type SectionsReceipt, type Site, type SiteWhere, type SkippedRoot, type SourceFile, type Splice, type TargetIdentity, type UnlocatedPath, UpgradeError, type UpgradeOptions, type UpgradeRootRef, type UpgradeSkipReason, type UpgradedRoot, type ValidationCode, ValidationError, type Xray, type XrayBucket, aliasesFrom, assertForms, assertReceipt, assertSections, assetCandidates, assetImport, attrsFor, bindDataLiterals, bindImages, briefDigest, canvasBridge, carryFor, componentizeSources, convertSources, convertedHere, coverageOf, declaringElements, dialectOf, exportedFunction, extendedConfigs, findLiteral, findSites, findSitesTolerant, fixFor, flat, helperSource, helperUpgrades, importsIn, isDecorativeGlyph, isDynamicRoute, isKnownHelper, isSourceCandidate, locate, measureUnaddressable, overlapping, pageFilesFor, parseFile, propsAttribute, readBrief, readComponentizePlan, readDeclarations, readExpr, readPlan, relativeImport, resolveSpecifier, rewriteFile, routeCounts, routeOfFile, stripTags, unreadableConfigs, upgradeSections, walkAst, wireForms };
1998
+ export { ASTRO_LANE_PENDING, type AstNode, type AttrBinding, type BcmsBuild, type Brief, type BriefForm, type BriefPage, type BriefPath, COMPONENT_DIR, CONTENT_DIR, type CanvasResult, type CanvasSource, type Carried, type ComponentizeOptions, type ComponentizePlan, type ComponentizePlanComponent, type ComponentizePlanField, type ComponentizePlanPage, type ComponentizePlanSection, type ComponentizeReceipt, type ConversionReceipt, ConvertError, type ConvertErrorCode, type ConvertOptions, DIALECT_RULES, type DataMember, type DataResult, type DeclaredPath, type Dialect, type DynamicBinding, FORM_SCRIPT, type FileDeclaration, type FindSitesResult, type FixAction, FormInvariantError, type FormPendingReason, type FormsReceipt, HELPER_PATH, HELPER_VERSION, type HelperUpgrade, type ImageResult, type ImageTarget, type ImportedFrom, type LlmFallback, type LocatedPath, type Node, PARSE_FILE, type ParsedFile, type ParserError, type PathLocator, type PendingFix, type PendingForm, type PendingPath, type PendingReason, type PendingSection, type PlanFile, REGISTRY_MARKER, type ReceiptFile, ReceiptInvariantError, type ReceiptNote, type Rewrite, SECTIONS_LIB, SECTION_MARKER, SKIP_DIRS, SKIP_FILES, SOURCE_EXTENSIONS, SSR_DRAFT_RECIPE, STUB_CONTENT, SectionInvariantError, type SectionPendingReason, type SectionUpgradeReceipt, type SectionsReceipt, type Site, type SiteWhere, type SkippedRoot, type SourceFile, type Splice, type TargetIdentity, type UnlocatedPath, UpgradeError, type UpgradeOptions, type UpgradeRootRef, type UpgradeSkipReason, type UpgradedRoot, type ValidationCode, ValidationError, type Xray, type XrayBucket, aliasesFrom, assertForms, assertReceipt, assertSections, assetCandidates, assetImport, attrsFor, bcmsBuildScript, bindDataLiterals, bindImages, briefDigest, canvasBridge, carryFor, componentizeSources, convertSources, convertedHere, coverageOf, declaringElements, dialectOf, exportedFunction, extendedConfigs, findLiteral, findSites, findSitesTolerant, fixFor, flat, helperSource, helperUpgrades, importsIn, isDecorativeGlyph, isDynamicRoute, isKnownHelper, isSourceCandidate, locate, measureUnaddressable, overlapping, pageFilesFor, parseFile, propsAttribute, readBrief, readComponentizePlan, readDeclarations, readExpr, readPlan, relativeImport, resolveSpecifier, rewriteFile, routeCounts, routeOfFile, stripTags, unreadableConfigs, upgradeSections, walkAst, wireForms };
package/dist/index.js CHANGED
@@ -4187,7 +4187,7 @@ async function bindImages(ctx, targets) {
4187
4187
 
4188
4188
  // src/helper.ts
4189
4189
  import { createHash as createHash2 } from "crypto";
4190
- var HELPER_VERSION = 12;
4190
+ var HELPER_VERSION = 13;
4191
4191
  var HEADER = "// @bettercms-ai/convert helper v";
4192
4192
  var HELPER_PATH = Object.fromEntries(
4193
4193
  Object.keys(DIALECT_RULES).map((d) => [d, DIALECT_RULES[d].helper])
@@ -4233,9 +4233,16 @@ function readPath(root: unknown, path: string): unknown {
4233
4233
  return cursor;
4234
4234
  }
4235
4235
 
4236
+ /**
4237
+ * A repository image path \u2014 \`@/images/x.avif\`, \`~/assets/x.png\`, \`../assets/x.jpg\`, \`/src/x.png\`.
4238
+ * The bundler resolves one at build and nothing else can, so as a value it is never rendered: the
4239
+ * template's own fallback (the picture the build already imported) shows instead of a broken image.
4240
+ */
4241
+ const REPO_IMAGE_PATH = /^(?:@[\\w-]*|~|\\.{1,2}|\\/?src)\\/[^\\s?#"'<>]*\\.(?:avif|png|jpe?g|webp|gif|svg|bmp|ico|tiff?|jxl|heic)(?:[?#]\\S*)?$/i;
4242
+
4236
4243
  /** A stored value as a template renders it: richtext is its html, an image is its url. */
4237
4244
  function render(value: unknown): string | undefined {
4238
- if (typeof value === "string") return value;
4245
+ if (typeof value === "string") return REPO_IMAGE_PATH.test(value.trim()) ? undefined : value;
4239
4246
  if (typeof value === "number" || typeof value === "boolean") return String(value);
4240
4247
  if (isRecord(value)) {
4241
4248
  if (typeof value.html === "string") return value.html;
@@ -4729,7 +4736,8 @@ var HISTORICAL = {
4729
4736
  8: "484e72852d2b496e016a1f2a2b1a77bb993f8a163b290781522d6114b6519bb9",
4730
4737
  9: "d6441db2ff4578c3c5d4b7d461f3374b89247ef6ba9e0d535791e840d803e4f3",
4731
4738
  10: "ffcb59862972b15a67c5951e9f3b94ce5b8b50345e6aac2bfa5789cfc3136910",
4732
- 11: "ceb2a932d4c2761a5045ff35032e0b45130a0b5034547ff37579c72c9ce3594e"
4739
+ 11: "ceb2a932d4c2761a5045ff35032e0b45130a0b5034547ff37579c72c9ce3594e",
4740
+ 12: "10f71724484c84af12aa3eb90db44bf6acbf71fcf8ddff5b6361c1190ba16528"
4733
4741
  },
4734
4742
  "src/lib/bcms-content.ts": {
4735
4743
  1: "ae72ae14d706943d481c880d70da5789b4816ba1ba319a10fbc63ded4d0b42f2",
@@ -4742,7 +4750,8 @@ var HISTORICAL = {
4742
4750
  8: "1a6f669d76d42effe77f082436e9d21c0efa6fc499e919e3d116bc3a27a7f3d5",
4743
4751
  9: "eee9fb1635ae7d6f8f33676a1f390600ca24a62ee992775252273c73a011c494",
4744
4752
  10: "35bb7c0e30f5c41fe68e52259ec4764de6de2734064fa0e1521f3338eef0a09e",
4745
- 11: "818784f2088150d64d91b42eac944dc9503f104d32a0e7a18c753d2982a5adc0"
4753
+ 11: "818784f2088150d64d91b42eac944dc9503f104d32a0e7a18c753d2982a5adc0",
4754
+ 12: "79dafc525a541feae55ada5dbe2ea966cac82acd741a4b41d61fe9e0cdfaa208"
4746
4755
  },
4747
4756
  "composables/bcms-content.ts": {
4748
4757
  1: "c272412532efed7db64b6cf313b2bed4291f9951430412289c8a588b7f565407",
@@ -4755,7 +4764,8 @@ var HISTORICAL = {
4755
4764
  8: "484e72852d2b496e016a1f2a2b1a77bb993f8a163b290781522d6114b6519bb9",
4756
4765
  9: "d6441db2ff4578c3c5d4b7d461f3374b89247ef6ba9e0d535791e840d803e4f3",
4757
4766
  10: "ffcb59862972b15a67c5951e9f3b94ce5b8b50345e6aac2bfa5789cfc3136910",
4758
- 11: "ceb2a932d4c2761a5045ff35032e0b45130a0b5034547ff37579c72c9ce3594e"
4767
+ 11: "ceb2a932d4c2761a5045ff35032e0b45130a0b5034547ff37579c72c9ce3594e",
4768
+ 12: "10f71724484c84af12aa3eb90db44bf6acbf71fcf8ddff5b6361c1190ba16528"
4759
4769
  }
4760
4770
  };
4761
4771
  var sha256 = (value) => createHash2("sha256").update(value, "utf8").digest("hex");
@@ -7680,6 +7690,54 @@ function moduleScope(parsed, content) {
7680
7690
  return out;
7681
7691
  }
7682
7692
 
7693
+ // src/build-script.ts
7694
+ var CHECK = /^(?:npx\s+|pnpm\s+(?:exec\s+)?|yarn\s+|bunx\s+)?(?:astro\s+check|svelte-check|vue-tsc|tsc(?:\s|$)|eslint|next\s+lint|biome\s+(?:check|lint|ci)|prettier\s+(?:--check|-c)\b|stylelint|oxlint)/;
7695
+ var RUN_CHECK = /^(?:npm\s+run|pnpm(?:\s+run)?|yarn(?:\s+run)?|bun\s+run)\s+(?:lint|typecheck|type-check|check|check:types|types|format:check|test)(?::[\w-]+)?\s*$/;
7696
+ var UNSAFE = /;|\|\||\||(?:^|[^&])&(?:[^&]|$)|\$\(|`|\n/;
7697
+ var isCheck = (step) => CHECK.test(step) || RUN_CHECK.test(step);
7698
+ function steps(script) {
7699
+ if (UNSAFE.test(script)) return null;
7700
+ const out = script.split("&&").map((s) => s.trim());
7701
+ return out.some((s) => s === "") ? null : out;
7702
+ }
7703
+ function bcmsBuildScript(packageJson) {
7704
+ let pkg;
7705
+ try {
7706
+ pkg = JSON.parse(packageJson);
7707
+ } catch {
7708
+ return null;
7709
+ }
7710
+ const scripts = pkg?.scripts;
7711
+ if (!scripts || typeof scripts !== "object" || "build:bcms" in scripts) return null;
7712
+ const build = scripts.build;
7713
+ if (typeof build !== "string") return null;
7714
+ const parts = [];
7715
+ for (const name of ["prebuild", "build", "postbuild"]) {
7716
+ const value = scripts[name];
7717
+ if (value === void 0) continue;
7718
+ if (typeof value !== "string") return null;
7719
+ const s = steps(value);
7720
+ if (!s) return null;
7721
+ parts.push(s);
7722
+ }
7723
+ const all = parts.flat();
7724
+ const dropped = all.filter(isCheck);
7725
+ const kept = all.filter((s) => !isCheck(s));
7726
+ if (dropped.length === 0 || kept.length === 0) return null;
7727
+ const script = kept.join(" && ");
7728
+ const next = {};
7729
+ for (const [key, value] of Object.entries(scripts)) {
7730
+ next[key] = value;
7731
+ if (key === "build") next["build:bcms"] = script;
7732
+ }
7733
+ const indent = /^[ \t]+(?=")/m.exec(packageJson)?.[0] ?? " ";
7734
+ const eol = packageJson.includes("\r\n") ? "\r\n" : "\n";
7735
+ let content = JSON.stringify({ ...pkg, scripts: next }, null, indent);
7736
+ if (eol !== "\n") content = content.replace(/\n/g, eol);
7737
+ if (/\r?\n$/.test(packageJson)) content += eol;
7738
+ return { content, script, dropped };
7739
+ }
7740
+
7683
7741
  // src/componentize.ts
7684
7742
  import MagicString5 from "magic-string";
7685
7743
  var SectionInvariantError = class extends Error {
@@ -10778,6 +10836,7 @@ export {
10778
10836
  assetCandidates,
10779
10837
  assetImport,
10780
10838
  attrsFor,
10839
+ bcmsBuildScript,
10781
10840
  bindDataLiterals,
10782
10841
  bindImages,
10783
10842
  briefDigest,