@koda-sl/baker-cli 0.245.0 → 0.246.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 +2 -4
- package/dist/cli.js +189 -356
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -9408,8 +9408,8 @@ function countStaccato(text2) {
|
|
|
9408
9408
|
let first = "";
|
|
9409
9409
|
let runStart = 0;
|
|
9410
9410
|
for (const [i, s] of sentences.entries()) {
|
|
9411
|
-
const
|
|
9412
|
-
if (
|
|
9411
|
+
const words2 = s.split(/\s+/).filter(Boolean).length;
|
|
9412
|
+
if (words2 > 0 && words2 <= STACCATO_MAX_WORDS) {
|
|
9413
9413
|
if (run === 0) runStart = i;
|
|
9414
9414
|
run++;
|
|
9415
9415
|
if (run === STACCATO_RUN) {
|
|
@@ -9427,10 +9427,10 @@ function countTitleCaseHeadings(text2) {
|
|
|
9427
9427
|
let first = "";
|
|
9428
9428
|
for (const m of text2.matchAll(/^\s{0,3}#{1,6}\s+(.+)$/gm)) {
|
|
9429
9429
|
const heading = (m[1] ?? "").trim();
|
|
9430
|
-
const
|
|
9431
|
-
if (
|
|
9432
|
-
const capitalized =
|
|
9433
|
-
if (capitalized /
|
|
9430
|
+
const words2 = heading.split(/\s+/).filter((w) => new RegExp("\\p{L}", "u").test(w));
|
|
9431
|
+
if (words2.length < 4) continue;
|
|
9432
|
+
const capitalized = words2.filter((w) => new RegExp("^\\p{Lu}", "u").test(w)).length;
|
|
9433
|
+
if (capitalized / words2.length < 0.8) continue;
|
|
9434
9434
|
count++;
|
|
9435
9435
|
if (!first) first = heading;
|
|
9436
9436
|
}
|
|
@@ -9779,11 +9779,11 @@ function rawTextEntries(value) {
|
|
|
9779
9779
|
const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
|
|
9780
9780
|
return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
9781
9781
|
}
|
|
9782
|
-
function rawFileEntries(
|
|
9783
|
-
if (typeof
|
|
9782
|
+
function rawFileEntries(path38) {
|
|
9783
|
+
if (typeof path38 !== "string" || path38.length === 0) {
|
|
9784
9784
|
return [];
|
|
9785
9785
|
}
|
|
9786
|
-
return readFileSync2(
|
|
9786
|
+
return readFileSync2(path38, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
9787
9787
|
}
|
|
9788
9788
|
function keywordEntries(args) {
|
|
9789
9789
|
const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
|
|
@@ -9806,19 +9806,19 @@ function keywordEntries(args) {
|
|
|
9806
9806
|
}
|
|
9807
9807
|
return entries;
|
|
9808
9808
|
}
|
|
9809
|
-
function loadJsonFileArg(
|
|
9810
|
-
if (typeof
|
|
9809
|
+
function loadJsonFileArg(path38) {
|
|
9810
|
+
if (typeof path38 !== "string" || path38.length === 0) {
|
|
9811
9811
|
return {};
|
|
9812
9812
|
}
|
|
9813
9813
|
try {
|
|
9814
|
-
const parsed = JSON.parse(readFileSync2(
|
|
9814
|
+
const parsed = JSON.parse(readFileSync2(path38, "utf8"));
|
|
9815
9815
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
9816
|
-
failWriteValidation(`${
|
|
9816
|
+
failWriteValidation(`${path38} must contain a JSON object`);
|
|
9817
9817
|
}
|
|
9818
9818
|
return parsed;
|
|
9819
9819
|
} catch (err) {
|
|
9820
9820
|
if (err instanceof SyntaxError) {
|
|
9821
|
-
failWriteValidation(`${
|
|
9821
|
+
failWriteValidation(`${path38} is not valid JSON: ${err.message}`);
|
|
9822
9822
|
}
|
|
9823
9823
|
throw err;
|
|
9824
9824
|
}
|
|
@@ -9948,10 +9948,10 @@ async function stageUpdate(kind, customerId, target, payload, hints) {
|
|
|
9948
9948
|
async function stageTarget(kind, customerId, target, hints) {
|
|
9949
9949
|
await stageGoogleOp({ kind, customerId, target }, hints);
|
|
9950
9950
|
}
|
|
9951
|
-
async function draftAction(
|
|
9951
|
+
async function draftAction(path38, body, chat) {
|
|
9952
9952
|
try {
|
|
9953
9953
|
const chatId = resolveChatId(chat);
|
|
9954
|
-
const response = await apiPost(
|
|
9954
|
+
const response = await apiPost(path38, { chatId, ...body });
|
|
9955
9955
|
writeJsonEnvelope(response);
|
|
9956
9956
|
} catch (err) {
|
|
9957
9957
|
handleGoogleError(err);
|
|
@@ -15136,19 +15136,19 @@ function failWriteValidation2(message) {
|
|
|
15136
15136
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
15137
15137
|
process.exit(1);
|
|
15138
15138
|
}
|
|
15139
|
-
function loadJsonFileArg2(
|
|
15140
|
-
if (typeof
|
|
15139
|
+
function loadJsonFileArg2(path38) {
|
|
15140
|
+
if (typeof path38 !== "string" || path38.length === 0) {
|
|
15141
15141
|
return {};
|
|
15142
15142
|
}
|
|
15143
15143
|
try {
|
|
15144
|
-
const parsed = JSON.parse(readFileSync4(
|
|
15144
|
+
const parsed = JSON.parse(readFileSync4(path38, "utf8"));
|
|
15145
15145
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
15146
|
-
failWriteValidation2(`${
|
|
15146
|
+
failWriteValidation2(`${path38} must contain a JSON object`);
|
|
15147
15147
|
}
|
|
15148
15148
|
return parsed;
|
|
15149
15149
|
} catch (err) {
|
|
15150
15150
|
if (err instanceof SyntaxError) {
|
|
15151
|
-
failWriteValidation2(`${
|
|
15151
|
+
failWriteValidation2(`${path38} is not valid JSON: ${err.message}`);
|
|
15152
15152
|
}
|
|
15153
15153
|
throw err;
|
|
15154
15154
|
}
|
|
@@ -15233,15 +15233,15 @@ function parseLocaleFlag(value) {
|
|
|
15233
15233
|
}
|
|
15234
15234
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
15235
15235
|
}
|
|
15236
|
-
function loadTargetingFileArg(
|
|
15237
|
-
if (typeof
|
|
15236
|
+
function loadTargetingFileArg(path38) {
|
|
15237
|
+
if (typeof path38 !== "string" || path38.length === 0) {
|
|
15238
15238
|
return void 0;
|
|
15239
15239
|
}
|
|
15240
|
-
const parsed = loadJsonFileArg2(
|
|
15240
|
+
const parsed = loadJsonFileArg2(path38);
|
|
15241
15241
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
15242
15242
|
if (!criteria.include) {
|
|
15243
15243
|
failWriteValidation2(
|
|
15244
|
-
`${
|
|
15244
|
+
`${path38} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
15245
15245
|
);
|
|
15246
15246
|
}
|
|
15247
15247
|
return criteria;
|
|
@@ -15276,14 +15276,14 @@ function parseCsvLine(line) {
|
|
|
15276
15276
|
cells.push(current);
|
|
15277
15277
|
return cells.map((cell2) => cell2.trim());
|
|
15278
15278
|
}
|
|
15279
|
-
function parseListFileArg(
|
|
15280
|
-
if (typeof
|
|
15279
|
+
function parseListFileArg(path38, maxRows) {
|
|
15280
|
+
if (typeof path38 !== "string" || path38.length === 0) {
|
|
15281
15281
|
return void 0;
|
|
15282
15282
|
}
|
|
15283
|
-
const raw = readFileSync4(
|
|
15283
|
+
const raw = readFileSync4(path38, "utf8");
|
|
15284
15284
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
15285
15285
|
if (lines.length < 2) {
|
|
15286
|
-
failWriteValidation2(`${
|
|
15286
|
+
failWriteValidation2(`${path38} needs a header row and at least one data row`);
|
|
15287
15287
|
}
|
|
15288
15288
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
15289
15289
|
const rows = [];
|
|
@@ -15302,7 +15302,7 @@ function parseListFileArg(path40, maxRows) {
|
|
|
15302
15302
|
}
|
|
15303
15303
|
}
|
|
15304
15304
|
if (rows.length > maxRows) {
|
|
15305
|
-
failWriteValidation2(`${
|
|
15305
|
+
failWriteValidation2(`${path38} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
15306
15306
|
}
|
|
15307
15307
|
return { columns, rows };
|
|
15308
15308
|
}
|
|
@@ -15398,11 +15398,11 @@ function readPositionals(args) {
|
|
|
15398
15398
|
function splitIdList(raw) {
|
|
15399
15399
|
return raw.split(",").map((id) => id.trim()).filter(Boolean);
|
|
15400
15400
|
}
|
|
15401
|
-
function idsFileEntries(
|
|
15402
|
-
if (typeof
|
|
15401
|
+
function idsFileEntries(path38) {
|
|
15402
|
+
if (typeof path38 !== "string" || path38.length === 0) {
|
|
15403
15403
|
return [];
|
|
15404
15404
|
}
|
|
15405
|
-
return readFileSync4(
|
|
15405
|
+
return readFileSync4(path38, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).flatMap(splitIdList);
|
|
15406
15406
|
}
|
|
15407
15407
|
function requireTargets(args, entity) {
|
|
15408
15408
|
const positionals = readPositionals(args);
|
|
@@ -18023,9 +18023,9 @@ function compactRow(row) {
|
|
|
18023
18023
|
...destination.postUrn ? { postUrn: destination.postUrn } : {}
|
|
18024
18024
|
};
|
|
18025
18025
|
}
|
|
18026
|
-
function readPath(row,
|
|
18026
|
+
function readPath(row, path38) {
|
|
18027
18027
|
let current = row;
|
|
18028
|
-
for (const segment of
|
|
18028
|
+
for (const segment of path38.split(".")) {
|
|
18029
18029
|
const record = asRecord2(current);
|
|
18030
18030
|
if (!record) return void 0;
|
|
18031
18031
|
current = record[segment];
|
|
@@ -18035,10 +18035,10 @@ function readPath(row, path40) {
|
|
|
18035
18035
|
function projectFields(rows, paths) {
|
|
18036
18036
|
return rows.map((row) => {
|
|
18037
18037
|
const projected = {};
|
|
18038
|
-
for (const
|
|
18039
|
-
const value = readPath(row,
|
|
18038
|
+
for (const path38 of paths) {
|
|
18039
|
+
const value = readPath(row, path38);
|
|
18040
18040
|
if (value !== void 0) {
|
|
18041
|
-
projected[
|
|
18041
|
+
projected[path38] = value;
|
|
18042
18042
|
}
|
|
18043
18043
|
}
|
|
18044
18044
|
return projected;
|
|
@@ -19338,11 +19338,11 @@ var updateStatusSchema = z25.enum(UPDATE_STATUSES);
|
|
|
19338
19338
|
function currencyMinimums2(currencyCode) {
|
|
19339
19339
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
19340
19340
|
}
|
|
19341
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
19341
|
+
function validateDailyBudgetFloor(money, ctx, path38) {
|
|
19342
19342
|
if (money?.currencyCode) {
|
|
19343
19343
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
19344
19344
|
if (Number(money.amount) < min) {
|
|
19345
|
-
ctx.addIssue({ code: "custom", path:
|
|
19345
|
+
ctx.addIssue({ code: "custom", path: path38, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
19346
19346
|
}
|
|
19347
19347
|
}
|
|
19348
19348
|
}
|
|
@@ -20011,19 +20011,19 @@ function failWriteValidation3(message) {
|
|
|
20011
20011
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
20012
20012
|
process.exit(1);
|
|
20013
20013
|
}
|
|
20014
|
-
function loadJsonFileArg3(
|
|
20015
|
-
if (typeof
|
|
20014
|
+
function loadJsonFileArg3(path38) {
|
|
20015
|
+
if (typeof path38 !== "string" || path38.length === 0) {
|
|
20016
20016
|
return {};
|
|
20017
20017
|
}
|
|
20018
20018
|
try {
|
|
20019
|
-
const parsed = JSON.parse(readFileSync8(
|
|
20019
|
+
const parsed = JSON.parse(readFileSync8(path38, "utf8"));
|
|
20020
20020
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
20021
|
-
failWriteValidation3(`${
|
|
20021
|
+
failWriteValidation3(`${path38} must contain a JSON object`);
|
|
20022
20022
|
}
|
|
20023
20023
|
return parsed;
|
|
20024
20024
|
} catch (err) {
|
|
20025
20025
|
if (err instanceof SyntaxError) {
|
|
20026
|
-
failWriteValidation3(`${
|
|
20026
|
+
failWriteValidation3(`${path38} is not valid JSON: ${err.message}`);
|
|
20027
20027
|
}
|
|
20028
20028
|
throw err;
|
|
20029
20029
|
}
|
|
@@ -24621,11 +24621,11 @@ function unwrap(response) {
|
|
|
24621
24621
|
}
|
|
24622
24622
|
return response.data;
|
|
24623
24623
|
}
|
|
24624
|
-
async function readAvatars(
|
|
24625
|
-
return unwrap(await apiGet(
|
|
24624
|
+
async function readAvatars(path38, params) {
|
|
24625
|
+
return unwrap(await apiGet(path38, params));
|
|
24626
24626
|
}
|
|
24627
|
-
async function writeAvatars(
|
|
24628
|
-
return unwrap(await apiPost(
|
|
24627
|
+
async function writeAvatars(path38, body) {
|
|
24628
|
+
return unwrap(await apiPost(path38, body));
|
|
24629
24629
|
}
|
|
24630
24630
|
|
|
24631
24631
|
// src/commands/avatars/create.ts
|
|
@@ -25371,14 +25371,14 @@ function suggestFamilies(wanted, catalogue, limit = 5) {
|
|
|
25371
25371
|
const key = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
25372
25372
|
const target = key(wanted);
|
|
25373
25373
|
if (!target) return [];
|
|
25374
|
-
const
|
|
25374
|
+
const words2 = target.split(" ");
|
|
25375
25375
|
const scored = catalogue.map((family) => {
|
|
25376
25376
|
const candidate = key(family);
|
|
25377
25377
|
if (candidate === target) return { family, score: 0 };
|
|
25378
25378
|
if (candidate.startsWith(target)) return { family, score: 1 };
|
|
25379
25379
|
if (candidate.includes(target)) return { family, score: 2 };
|
|
25380
|
-
const shared =
|
|
25381
|
-
return { family, score: shared > 0 ? 3 + (
|
|
25380
|
+
const shared = words2.filter((w) => w.length > 2 && candidate.includes(w)).length;
|
|
25381
|
+
return { family, score: shared > 0 ? 3 + (words2.length - shared) : Number.POSITIVE_INFINITY };
|
|
25382
25382
|
}).filter((c) => Number.isFinite(c.score)).sort((a, b) => a.score - b.score || a.family.localeCompare(b.family));
|
|
25383
25383
|
return scored.slice(0, limit).map((c) => c.family);
|
|
25384
25384
|
}
|
|
@@ -25459,12 +25459,12 @@ function missingFontFiles(urls, available) {
|
|
|
25459
25459
|
function planFontAdoption(sources, families) {
|
|
25460
25460
|
const wanted = new Map(families.map((family) => [normalizeFamily(family), family]));
|
|
25461
25461
|
const byFamily = /* @__PURE__ */ new Map();
|
|
25462
|
-
for (const { path:
|
|
25463
|
-
const dir = posix.dirname(
|
|
25462
|
+
for (const { path: path38, source } of sources) {
|
|
25463
|
+
const dir = posix.dirname(path38);
|
|
25464
25464
|
for (const face of declaredFontFaces(source)) {
|
|
25465
25465
|
if (!wanted.has(face.family)) continue;
|
|
25466
25466
|
const perFile = byFamily.get(face.family) ?? /* @__PURE__ */ new Map();
|
|
25467
|
-
perFile.set(
|
|
25467
|
+
perFile.set(path38, [...perFile.get(path38) ?? [], rebaseFontFaceSrc(face.block, dir)]);
|
|
25468
25468
|
byFamily.set(face.family, perFile);
|
|
25469
25469
|
}
|
|
25470
25470
|
}
|
|
@@ -26872,10 +26872,10 @@ function estSpeechS(text2) {
|
|
|
26872
26872
|
var OBSERVED_WPS_MIN = 1;
|
|
26873
26873
|
var OBSERVED_WPS_MAX = 6;
|
|
26874
26874
|
function estSpeechWindowS(text2, startS, endS) {
|
|
26875
|
-
const
|
|
26875
|
+
const words2 = wordCount(text2);
|
|
26876
26876
|
const window2 = (endS ?? 0) - (startS ?? 0);
|
|
26877
|
-
if (
|
|
26878
|
-
const wps =
|
|
26877
|
+
if (words2 > 0 && window2 > 0.3) {
|
|
26878
|
+
const wps = words2 / window2;
|
|
26879
26879
|
if (wps >= OBSERVED_WPS_MIN && wps <= OBSERVED_WPS_MAX) return window2;
|
|
26880
26880
|
}
|
|
26881
26881
|
return estSpeechS(text2);
|
|
@@ -27731,10 +27731,10 @@ function scrubFloatSentences(text2, floatDescs) {
|
|
|
27731
27731
|
if (floatDescs.length === 0 || !text2) return text2;
|
|
27732
27732
|
const tokenSets = floatDescs.map((d) => new Set(floatTokens(d)));
|
|
27733
27733
|
const kept = text2.split(/(?<=[.!?])\s+/).filter((sentence) => {
|
|
27734
|
-
const
|
|
27734
|
+
const words2 = new Set(floatTokens(sentence));
|
|
27735
27735
|
return !tokenSets.some((ts) => {
|
|
27736
27736
|
let hits = 0;
|
|
27737
|
-
for (const w of
|
|
27737
|
+
for (const w of words2) if (ts.has(w)) hits++;
|
|
27738
27738
|
return hits >= 2;
|
|
27739
27739
|
});
|
|
27740
27740
|
}).join(" ").trim();
|
|
@@ -33659,12 +33659,12 @@ function collectSideEffects(tree) {
|
|
|
33659
33659
|
);
|
|
33660
33660
|
}
|
|
33661
33661
|
function readFlowTree(slug) {
|
|
33662
|
-
const
|
|
33663
|
-
if (!existsSync5(
|
|
33662
|
+
const path38 = join3(flowsDir(), slug, "_data.json");
|
|
33663
|
+
if (!existsSync5(path38)) {
|
|
33664
33664
|
failLocal(`No form "${slug}". Run "baker flows list" to see the forms in this workspace.`);
|
|
33665
33665
|
}
|
|
33666
33666
|
try {
|
|
33667
|
-
return JSON.parse(readFileSync9(
|
|
33667
|
+
return JSON.parse(readFileSync9(path38, "utf-8"));
|
|
33668
33668
|
} catch (error) {
|
|
33669
33669
|
failLocal(`Could not read form "${slug}": ${error instanceof Error ? error.message : String(error)}`);
|
|
33670
33670
|
}
|
|
@@ -34056,10 +34056,10 @@ function parseValueExpression(raw) {
|
|
|
34056
34056
|
return parts.map(parsePart);
|
|
34057
34057
|
}
|
|
34058
34058
|
function trackingFieldIds() {
|
|
34059
|
-
const
|
|
34060
|
-
if (!existsSync6(
|
|
34059
|
+
const path38 = join4(flowsDir(), "..", "tracking.ts");
|
|
34060
|
+
if (!existsSync6(path38)) return null;
|
|
34061
34061
|
try {
|
|
34062
|
-
const source = readFileSync10(
|
|
34062
|
+
const source = readFileSync10(path38, "utf-8");
|
|
34063
34063
|
const block2 = source.match(/TRACKING_FIELD_IDS\s*=\s*\[([\s\S]*?)\]\s*as const/)?.[1];
|
|
34064
34064
|
if (!block2) return null;
|
|
34065
34065
|
const ids = [...block2.matchAll(/"(tracking\.[a-z0-9_]+)"/g)].map((match) => match[1]);
|
|
@@ -34611,13 +34611,13 @@ function specsFromFile(parsed) {
|
|
|
34611
34611
|
return `${destField}${type}=${entry?.value ?? ""}`;
|
|
34612
34612
|
});
|
|
34613
34613
|
}
|
|
34614
|
-
function readSpecFile(
|
|
34614
|
+
function readSpecFile(path38) {
|
|
34615
34615
|
let raw;
|
|
34616
34616
|
try {
|
|
34617
|
-
raw =
|
|
34617
|
+
raw = path38 === "-" ? readFileSync11(0, "utf-8") : readFileSync11(path38, "utf-8");
|
|
34618
34618
|
} catch (error) {
|
|
34619
34619
|
refuse(
|
|
34620
|
-
`Could not read ${
|
|
34620
|
+
`Could not read ${path38 === "-" ? "the mapping from stdin" : `"${path38}"`}: ${error instanceof Error ? error.message : String(error)}`
|
|
34621
34621
|
);
|
|
34622
34622
|
}
|
|
34623
34623
|
let parsed;
|
|
@@ -34625,7 +34625,7 @@ function readSpecFile(path40) {
|
|
|
34625
34625
|
parsed = JSON.parse(raw);
|
|
34626
34626
|
} catch (error) {
|
|
34627
34627
|
refuse(
|
|
34628
|
-
`${
|
|
34628
|
+
`${path38 === "-" ? "stdin" : `"${path38}"`} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
34629
34629
|
'Expected { "map": { "<destField>": "<value>", \u2026 } }'
|
|
34630
34630
|
);
|
|
34631
34631
|
}
|
|
@@ -34879,18 +34879,18 @@ var ARRAY_FIELDS = [
|
|
|
34879
34879
|
"tagIds"
|
|
34880
34880
|
];
|
|
34881
34881
|
var ARRAY_OWNERS = ["", "body"];
|
|
34882
|
-
function dropUnsetOptionals(sideEffect,
|
|
34882
|
+
function dropUnsetOptionals(sideEffect, path38) {
|
|
34883
34883
|
return OPTIONAL_STRINGS.flatMap((key) => {
|
|
34884
34884
|
if (!(key in sideEffect) || sideEffect[key] !== null && sideEffect[key] !== "") return [];
|
|
34885
34885
|
delete sideEffect[key];
|
|
34886
|
-
return [{ path:
|
|
34886
|
+
return [{ path: path38, change: `dropped \`${key}\` (an optional string is absent, never null)` }];
|
|
34887
34887
|
});
|
|
34888
34888
|
}
|
|
34889
|
-
function fillNulledArrays(target, prefix,
|
|
34889
|
+
function fillNulledArrays(target, prefix, path38) {
|
|
34890
34890
|
return ARRAY_FIELDS.flatMap((key) => {
|
|
34891
34891
|
if (!(key in target) || target[key] !== null) return [];
|
|
34892
34892
|
target[key] = [];
|
|
34893
|
-
return [{ path:
|
|
34893
|
+
return [{ path: path38, change: `\`${prefix}${key}: null\` \u2192 \`[]\`` }];
|
|
34894
34894
|
});
|
|
34895
34895
|
}
|
|
34896
34896
|
function sideEffectsOf(node) {
|
|
@@ -34900,13 +34900,13 @@ function sideEffectsOf(node) {
|
|
|
34900
34900
|
);
|
|
34901
34901
|
}
|
|
34902
34902
|
function normalizeSideEffect(sideEffect, where) {
|
|
34903
|
-
const
|
|
34903
|
+
const path38 = `${where} \u2192 ${String(sideEffect.id ?? "side effect")}`;
|
|
34904
34904
|
const arrays = ARRAY_OWNERS.flatMap((owner) => {
|
|
34905
34905
|
const target = owner ? sideEffect[owner] : sideEffect;
|
|
34906
34906
|
if (!target || typeof target !== "object") return [];
|
|
34907
|
-
return fillNulledArrays(target, owner ? `${owner}.` : "",
|
|
34907
|
+
return fillNulledArrays(target, owner ? `${owner}.` : "", path38);
|
|
34908
34908
|
});
|
|
34909
|
-
return [...dropUnsetOptionals(sideEffect,
|
|
34909
|
+
return [...dropUnsetOptionals(sideEffect, path38), ...arrays];
|
|
34910
34910
|
}
|
|
34911
34911
|
function normalizeFlowTree(tree) {
|
|
34912
34912
|
const changes = [];
|
|
@@ -35444,10 +35444,10 @@ async function stageOps(ops) {
|
|
|
35444
35444
|
handleError2(err);
|
|
35445
35445
|
}
|
|
35446
35446
|
}
|
|
35447
|
-
async function draftAction2(
|
|
35447
|
+
async function draftAction2(path38, body, chat) {
|
|
35448
35448
|
const chatId = resolveChatId(chat);
|
|
35449
35449
|
try {
|
|
35450
|
-
const data = await apiPost(
|
|
35450
|
+
const data = await apiPost(path38, { chatId, ...body });
|
|
35451
35451
|
writeJsonEnvelope({ ok: true, data });
|
|
35452
35452
|
return data;
|
|
35453
35453
|
} catch (err) {
|
|
@@ -37879,9 +37879,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
37879
37879
|
}
|
|
37880
37880
|
return readFile20(pathOrUrl);
|
|
37881
37881
|
}
|
|
37882
|
-
async function isDirectory(
|
|
37882
|
+
async function isDirectory(path38) {
|
|
37883
37883
|
try {
|
|
37884
|
-
const s = await stat4(
|
|
37884
|
+
const s = await stat4(path38);
|
|
37885
37885
|
return s.isDirectory();
|
|
37886
37886
|
} catch {
|
|
37887
37887
|
return false;
|
|
@@ -38183,13 +38183,13 @@ function resolveDownloadPath({ baseName, extension, out, outIsDirectory: outIsDi
|
|
|
38183
38183
|
}
|
|
38184
38184
|
function disambiguate(paths) {
|
|
38185
38185
|
const taken = /* @__PURE__ */ new Set();
|
|
38186
|
-
return paths.map((
|
|
38187
|
-
if (!taken.has(
|
|
38188
|
-
taken.add(
|
|
38189
|
-
return
|
|
38186
|
+
return paths.map((path38) => {
|
|
38187
|
+
if (!taken.has(path38)) {
|
|
38188
|
+
taken.add(path38);
|
|
38189
|
+
return path38;
|
|
38190
38190
|
}
|
|
38191
|
-
const ext = extname3(
|
|
38192
|
-
const stem =
|
|
38191
|
+
const ext = extname3(path38);
|
|
38192
|
+
const stem = path38.slice(0, path38.length - ext.length);
|
|
38193
38193
|
let n = 2;
|
|
38194
38194
|
while (taken.has(`${stem}-${n}${ext}`)) n += 1;
|
|
38195
38195
|
const unique = `${stem}-${n}${ext}`;
|
|
@@ -38316,10 +38316,10 @@ async function runDownloads(plan) {
|
|
|
38316
38316
|
const paths = disambiguate(fetched.map((item) => item.path));
|
|
38317
38317
|
const downloaded = [];
|
|
38318
38318
|
for (const [index, item] of fetched.entries()) {
|
|
38319
|
-
const
|
|
38319
|
+
const path38 = paths[index] ?? item.path;
|
|
38320
38320
|
try {
|
|
38321
|
-
await atomicWrite(
|
|
38322
|
-
downloaded.push({ input: item.input, output:
|
|
38321
|
+
await atomicWrite(path38, item.buffer);
|
|
38322
|
+
downloaded.push({ input: item.input, output: path38, bytes: item.buffer.length, contentType: item.contentType });
|
|
38323
38323
|
} catch (err) {
|
|
38324
38324
|
failed.push({ input: item.input, error: failureMessage(err, "Write failed") });
|
|
38325
38325
|
}
|
|
@@ -41279,7 +41279,7 @@ import { defineCommand as defineCommand166 } from "citty";
|
|
|
41279
41279
|
|
|
41280
41280
|
// src/commands/landing/critique.ts
|
|
41281
41281
|
import { readdir as readdir9, stat as stat6 } from "fs/promises";
|
|
41282
|
-
import
|
|
41282
|
+
import path28 from "path";
|
|
41283
41283
|
import { defineCommand as defineCommand156 } from "citty";
|
|
41284
41284
|
|
|
41285
41285
|
// src/engine/landing/lib/constants.ts
|
|
@@ -41482,11 +41482,6 @@ var RULE_META = {
|
|
|
41482
41482
|
severity: "block",
|
|
41483
41483
|
note: "Gradient text is a top AI tell. Emphasis comes from weight or size, not a clipped gradient fill."
|
|
41484
41484
|
},
|
|
41485
|
-
"copied-reference-copy": {
|
|
41486
|
-
family: "originality",
|
|
41487
|
-
severity: "block",
|
|
41488
|
-
note: "This line is lifted from a section you consulted in the inspiration library. Reference sections are for structure and mechanism, never words \u2014 a visitor who has seen the original reads this as a clone, and the claim is not yours to make. Rewrite it from the client's own offer."
|
|
41489
|
-
},
|
|
41490
41485
|
"broken-image": {
|
|
41491
41486
|
family: "integrity",
|
|
41492
41487
|
severity: "block",
|
|
@@ -41667,64 +41662,6 @@ var SEVERITY_WEIGHT = {
|
|
|
41667
41662
|
advisory: 0.05
|
|
41668
41663
|
};
|
|
41669
41664
|
|
|
41670
|
-
// src/engine/landing/lib/originality.ts
|
|
41671
|
-
var MIN_COMPARABLE_LENGTH = 12;
|
|
41672
|
-
var NEAR_MATCH_RATIO = 0.8;
|
|
41673
|
-
function normalize(value) {
|
|
41674
|
-
return value.toLowerCase().replace(/[‘’“”]/g, "'").replace(/[^a-z0-9']+/g, " ").trim();
|
|
41675
|
-
}
|
|
41676
|
-
function words2(value) {
|
|
41677
|
-
return normalize(value).split(" ").filter(Boolean);
|
|
41678
|
-
}
|
|
41679
|
-
function copyOverlapRatio(candidate, reference) {
|
|
41680
|
-
const referenceWords = words2(reference);
|
|
41681
|
-
if (referenceWords.length === 0) return 0;
|
|
41682
|
-
const candidateWords = new Set(words2(candidate));
|
|
41683
|
-
const shared = referenceWords.filter((word) => candidateWords.has(word)).length;
|
|
41684
|
-
return shared / referenceWords.length;
|
|
41685
|
-
}
|
|
41686
|
-
function isVerbatimReuse(candidate, reference) {
|
|
41687
|
-
const normalizedCandidate = normalize(candidate);
|
|
41688
|
-
const normalizedReference = normalize(reference);
|
|
41689
|
-
if (normalizedReference.length < MIN_COMPARABLE_LENGTH) return false;
|
|
41690
|
-
if (normalizedCandidate.includes(normalizedReference)) return true;
|
|
41691
|
-
return copyOverlapRatio(candidate, reference) >= NEAR_MATCH_RATIO;
|
|
41692
|
-
}
|
|
41693
|
-
function extractVisibleStrings(text2) {
|
|
41694
|
-
const found = [];
|
|
41695
|
-
const lines = text2.split("\n");
|
|
41696
|
-
for (const [index, line] of lines.entries()) {
|
|
41697
|
-
for (const match of line.matchAll(/>([^<>{}]{12,200})</g)) {
|
|
41698
|
-
const value = match[1]?.trim();
|
|
41699
|
-
if (value && /[a-zA-Z]{3}/.test(value)) found.push({ value, line: index + 1 });
|
|
41700
|
-
}
|
|
41701
|
-
}
|
|
41702
|
-
return found;
|
|
41703
|
-
}
|
|
41704
|
-
function detectOriginality(sources, references) {
|
|
41705
|
-
if (references.length === 0) return [];
|
|
41706
|
-
const findings = [];
|
|
41707
|
-
const seen = /* @__PURE__ */ new Set();
|
|
41708
|
-
for (const source of sources) {
|
|
41709
|
-
for (const { value, line } of extractVisibleStrings(source.text)) {
|
|
41710
|
-
for (const reference of references) {
|
|
41711
|
-
const hit = reference.copyStrings.find((copy) => isVerbatimReuse(value, copy));
|
|
41712
|
-
if (!hit) continue;
|
|
41713
|
-
const key = `${source.path}:${line}:${normalize(hit)}`;
|
|
41714
|
-
if (seen.has(key)) continue;
|
|
41715
|
-
seen.add(key);
|
|
41716
|
-
findings.push({
|
|
41717
|
-
id: "copied-reference-copy",
|
|
41718
|
-
snippet: value.slice(0, 120),
|
|
41719
|
-
file: source.path,
|
|
41720
|
-
line
|
|
41721
|
-
});
|
|
41722
|
-
}
|
|
41723
|
-
}
|
|
41724
|
-
}
|
|
41725
|
-
return findings;
|
|
41726
|
-
}
|
|
41727
|
-
|
|
41728
41665
|
// src/engine/landing/lib/rules.ts
|
|
41729
41666
|
var cap2 = (m, i) => m[i] ?? "";
|
|
41730
41667
|
var num2 = (m, i) => Number(m[i] ?? 0);
|
|
@@ -42252,16 +42189,7 @@ function dedupe(findings) {
|
|
|
42252
42189
|
}
|
|
42253
42190
|
|
|
42254
42191
|
// src/engine/landing/lib/critique.ts
|
|
42255
|
-
var FAMILIES = [
|
|
42256
|
-
"typography",
|
|
42257
|
-
"color",
|
|
42258
|
-
"borders_depth",
|
|
42259
|
-
"motion",
|
|
42260
|
-
"spacing",
|
|
42261
|
-
"copy",
|
|
42262
|
-
"integrity",
|
|
42263
|
-
"originality"
|
|
42264
|
-
];
|
|
42192
|
+
var FAMILIES = ["typography", "color", "borders_depth", "motion", "spacing", "copy", "integrity"];
|
|
42265
42193
|
function round4(n) {
|
|
42266
42194
|
return Math.round(n * 100) / 100;
|
|
42267
42195
|
}
|
|
@@ -42280,7 +42208,6 @@ function critiqueLanding(input) {
|
|
|
42280
42208
|
const raws = [];
|
|
42281
42209
|
for (const source of sources) raws.push(...detectSource(source));
|
|
42282
42210
|
raws.push(...detectPage(sources));
|
|
42283
|
-
raws.push(...detectOriginality(sources, input.references ?? []));
|
|
42284
42211
|
for (const raw of raws) {
|
|
42285
42212
|
const meta = RULE_META[raw.id];
|
|
42286
42213
|
if (!meta) continue;
|
|
@@ -42318,82 +42245,41 @@ function describeCounts(findings) {
|
|
|
42318
42245
|
return [b ? `${b} block` : "", w ? `${w} warn` : "", a ? `${a} advisory` : ""].filter(Boolean).join(", ");
|
|
42319
42246
|
}
|
|
42320
42247
|
|
|
42321
|
-
// src/engine/landing/lib/referenceStore.ts
|
|
42322
|
-
import { mkdir as mkdir8, readFile as readFile21, writeFile as writeFile12 } from "fs/promises";
|
|
42323
|
-
import path26 from "path";
|
|
42324
|
-
var REFERENCES_FILE = ".cache/inspiration-refs.json";
|
|
42325
|
-
var REFERENCE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
42326
|
-
async function readReferences(projectRoot) {
|
|
42327
|
-
try {
|
|
42328
|
-
const raw = await readFile21(path26.join(projectRoot, REFERENCES_FILE), "utf8");
|
|
42329
|
-
const parsed = JSON.parse(raw);
|
|
42330
|
-
if (!Array.isArray(parsed)) return [];
|
|
42331
|
-
const cutoff = Date.now() - REFERENCE_TTL_MS;
|
|
42332
|
-
return parsed.filter((entry) => {
|
|
42333
|
-
if (typeof entry !== "object" || entry === null) return false;
|
|
42334
|
-
const candidate = entry;
|
|
42335
|
-
if (typeof candidate.sectionId !== "string" || !Array.isArray(candidate.copyStrings)) return false;
|
|
42336
|
-
const at = Date.parse(candidate.consultedAt ?? "");
|
|
42337
|
-
return Number.isNaN(at) ? true : at >= cutoff;
|
|
42338
|
-
});
|
|
42339
|
-
} catch {
|
|
42340
|
-
return [];
|
|
42341
|
-
}
|
|
42342
|
-
}
|
|
42343
|
-
async function recordReference(projectRoot, reference) {
|
|
42344
|
-
return await recordReferences(projectRoot, [reference]);
|
|
42345
|
-
}
|
|
42346
|
-
async function recordReferences(projectRoot, references) {
|
|
42347
|
-
if (references.length === 0) return true;
|
|
42348
|
-
try {
|
|
42349
|
-
const existing = await readReferences(projectRoot);
|
|
42350
|
-
const replaced = new Set(references.map((reference) => reference.sectionId));
|
|
42351
|
-
const merged = [...existing.filter((entry) => !replaced.has(entry.sectionId)), ...references];
|
|
42352
|
-
const file = path26.join(projectRoot, REFERENCES_FILE);
|
|
42353
|
-
await mkdir8(path26.dirname(file), { recursive: true });
|
|
42354
|
-
await writeFile12(file, `${JSON.stringify(merged, null, 2)}
|
|
42355
|
-
`);
|
|
42356
|
-
return true;
|
|
42357
|
-
} catch {
|
|
42358
|
-
return false;
|
|
42359
|
-
}
|
|
42360
|
-
}
|
|
42361
|
-
|
|
42362
42248
|
// src/commands/landing/snapshot.ts
|
|
42363
|
-
import { mkdir as
|
|
42364
|
-
import
|
|
42249
|
+
import { mkdir as mkdir8, rename as rename2, writeFile as writeFile12 } from "fs/promises";
|
|
42250
|
+
import path26 from "path";
|
|
42365
42251
|
var CRITIC_VERSION = "2";
|
|
42366
42252
|
function critiqueCacheDir(projectRoot) {
|
|
42367
|
-
return
|
|
42253
|
+
return path26.join(projectRoot, ".cache", "landing-critique");
|
|
42368
42254
|
}
|
|
42369
42255
|
function snapshotPath(projectRoot, slug) {
|
|
42370
|
-
return
|
|
42256
|
+
return path26.join(critiqueCacheDir(projectRoot), `${slug}.json`);
|
|
42371
42257
|
}
|
|
42372
42258
|
async function writeCritiqueSnapshot(projectRoot, snapshot) {
|
|
42373
|
-
await
|
|
42259
|
+
await mkdir8(critiqueCacheDir(projectRoot), { recursive: true });
|
|
42374
42260
|
const dest = snapshotPath(projectRoot, snapshot.slug);
|
|
42375
42261
|
const tmp = `${dest}.tmp`;
|
|
42376
|
-
await
|
|
42262
|
+
await writeFile12(tmp, `${JSON.stringify(snapshot, null, 2)}
|
|
42377
42263
|
`, "utf8");
|
|
42378
42264
|
await rename2(tmp, dest);
|
|
42379
42265
|
}
|
|
42380
42266
|
|
|
42381
42267
|
// src/commands/landing/source-version.ts
|
|
42382
|
-
import { readdir as readdir8, readFile as
|
|
42383
|
-
import
|
|
42268
|
+
import { readdir as readdir8, readFile as readFile21, stat as stat5 } from "fs/promises";
|
|
42269
|
+
import path27 from "path";
|
|
42384
42270
|
async function landingSourceRelPaths(landingDir) {
|
|
42385
42271
|
const rel = [];
|
|
42386
|
-
if (await isFile(
|
|
42387
|
-
const componentsDir =
|
|
42272
|
+
if (await isFile(path27.join(landingDir, "index.astro"))) rel.push("index.astro");
|
|
42273
|
+
const componentsDir = path27.join(landingDir, "_components");
|
|
42388
42274
|
for (const abs of await walkAstro(componentsDir)) {
|
|
42389
|
-
rel.push(
|
|
42275
|
+
rel.push(path27.relative(landingDir, abs).split(path27.sep).join("/"));
|
|
42390
42276
|
}
|
|
42391
42277
|
return rel.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
42392
42278
|
}
|
|
42393
42279
|
async function readLandingSources(landingDir) {
|
|
42394
42280
|
const rel = await landingSourceRelPaths(landingDir);
|
|
42395
42281
|
const out = [];
|
|
42396
|
-
for (const r of rel) out.push({ path: r, text: await
|
|
42282
|
+
for (const r of rel) out.push({ path: r, text: await readFile21(path27.join(landingDir, r), "utf8") });
|
|
42397
42283
|
return out;
|
|
42398
42284
|
}
|
|
42399
42285
|
async function computeLandingSourceSha(landingDir) {
|
|
@@ -42402,7 +42288,7 @@ async function computeLandingSourceSha(landingDir) {
|
|
|
42402
42288
|
for (const r of rel) {
|
|
42403
42289
|
let bytes;
|
|
42404
42290
|
try {
|
|
42405
|
-
bytes = await
|
|
42291
|
+
bytes = await readFile21(path27.join(landingDir, r));
|
|
42406
42292
|
} catch {
|
|
42407
42293
|
bytes = Buffer.alloc(0);
|
|
42408
42294
|
}
|
|
@@ -42426,7 +42312,7 @@ async function walkAstro(dir) {
|
|
|
42426
42312
|
}
|
|
42427
42313
|
const out = [];
|
|
42428
42314
|
for (const entry of entries) {
|
|
42429
|
-
const abs =
|
|
42315
|
+
const abs = path27.join(dir, entry.name);
|
|
42430
42316
|
if (entry.isDirectory()) out.push(...await walkAstro(abs));
|
|
42431
42317
|
else if (entry.isFile() && entry.name.endsWith(".astro")) out.push(abs);
|
|
42432
42318
|
}
|
|
@@ -42487,14 +42373,14 @@ var critiqueCommand2 = defineCommand156({
|
|
|
42487
42373
|
{ availableSlugs: await listLandingSlugs(projectRoot) }
|
|
42488
42374
|
);
|
|
42489
42375
|
}
|
|
42490
|
-
if (!await isDir(
|
|
42376
|
+
if (!await isDir(path28.resolve(projectRoot, "src", "pages", slug))) {
|
|
42491
42377
|
fail5("NOT_FOUND", `No landing at src/pages/${slug}/`, {
|
|
42492
42378
|
availableSlugs: await listLandingSlugs(projectRoot)
|
|
42493
42379
|
});
|
|
42494
42380
|
}
|
|
42495
42381
|
}
|
|
42496
|
-
const
|
|
42497
|
-
const results = await Promise.all(slugs.map((slug) => critiqueOne(projectRoot, slug, brand
|
|
42382
|
+
const brand = await loadBrandTokens(projectRoot);
|
|
42383
|
+
const results = await Promise.all(slugs.map((slug) => critiqueOne(projectRoot, slug, brand)));
|
|
42498
42384
|
const landings = results.map(({ slug, report }) => ({
|
|
42499
42385
|
slug,
|
|
42500
42386
|
overall: report.overall,
|
|
@@ -42525,10 +42411,10 @@ var critiqueCommand2 = defineCommand156({
|
|
|
42525
42411
|
);
|
|
42526
42412
|
}
|
|
42527
42413
|
});
|
|
42528
|
-
async function critiqueOne(projectRoot, slug, brand
|
|
42529
|
-
const landingDir =
|
|
42414
|
+
async function critiqueOne(projectRoot, slug, brand) {
|
|
42415
|
+
const landingDir = path28.resolve(projectRoot, "src", "pages", slug);
|
|
42530
42416
|
const [sources, sourceSha] = await Promise.all([readLandingSources(landingDir), computeLandingSourceSha(landingDir)]);
|
|
42531
|
-
const report = critiqueLanding({ slug, sources, brand
|
|
42417
|
+
const report = critiqueLanding({ slug, sources, brand });
|
|
42532
42418
|
let snapshotFailed = false;
|
|
42533
42419
|
try {
|
|
42534
42420
|
await writeCritiqueSnapshot(projectRoot, {
|
|
@@ -42546,7 +42432,7 @@ async function critiqueOne(projectRoot, slug, brand, references) {
|
|
|
42546
42432
|
}
|
|
42547
42433
|
async function listLandingSlugs(projectRoot) {
|
|
42548
42434
|
try {
|
|
42549
|
-
const entries = await readdir9(
|
|
42435
|
+
const entries = await readdir9(path28.join(projectRoot, "src", "pages"), { withFileTypes: true });
|
|
42550
42436
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
42551
42437
|
} catch {
|
|
42552
42438
|
return [];
|
|
@@ -42579,7 +42465,7 @@ import { defineCommand as defineCommand157 } from "citty";
|
|
|
42579
42465
|
|
|
42580
42466
|
// src/commands/landing/inspiration/shared.ts
|
|
42581
42467
|
var INSPIRATION_HINTS = {
|
|
42582
|
-
adapt: "Reference only. Re-express this in the client's BRAND.md palette, type and imagery register. Reusing a headline, subhead or CTA verbatim is a Tier 0 message-match failure (references/gotchas.md)
|
|
42468
|
+
adapt: "Reference only. Re-express this in the client's BRAND.md palette, type and imagery register. Reusing a headline, subhead or CTA verbatim is a Tier 0 message-match failure (references/gotchas.md).",
|
|
42583
42469
|
structureNotCopy: "Take the structural decision, not the furniture: what the eye hits first, the grid ratio, what was deliberately left out. Your copy must come from the client's own offer."
|
|
42584
42470
|
};
|
|
42585
42471
|
function favoritesScopeHints(health, resultCount) {
|
|
@@ -42697,12 +42583,12 @@ var addCommand = defineCommand157({
|
|
|
42697
42583
|
});
|
|
42698
42584
|
|
|
42699
42585
|
// src/commands/landing/inspiration/code.ts
|
|
42700
|
-
import { mkdir as
|
|
42701
|
-
import
|
|
42586
|
+
import { mkdir as mkdir9, writeFile as writeFile13 } from "fs/promises";
|
|
42587
|
+
import path29 from "path";
|
|
42702
42588
|
import { defineCommand as defineCommand158 } from "citty";
|
|
42703
42589
|
registerSchema({
|
|
42704
42590
|
command: "landing.inspiration.code",
|
|
42705
|
-
description: "Write a reference section's standalone HTML+CSS to .baker/inspiration/<id>/ so you can read how it is built. Reference only \u2014 the structure is the lesson, the words are not yours to reuse.
|
|
42591
|
+
description: "Write a reference section's standalone HTML+CSS to .baker/inspiration/<id>/ so you can read how it is built. Reference only \u2014 the structure is the lesson, the words are not yours to reuse.",
|
|
42706
42592
|
args: {
|
|
42707
42593
|
id: { type: "string", description: "Section id from search", required: true },
|
|
42708
42594
|
full: { type: "boolean", description: "Print the markup inline as well as writing it", required: false }
|
|
@@ -42721,30 +42607,19 @@ var codeCommand = defineCommand158({
|
|
|
42721
42607
|
try {
|
|
42722
42608
|
const id = args.id;
|
|
42723
42609
|
const data = await apiGet("/api/landing-inspiration/section-code", { id });
|
|
42724
|
-
const dir =
|
|
42725
|
-
await
|
|
42726
|
-
const file =
|
|
42727
|
-
await
|
|
42728
|
-
const recorded = await recordReference(process.cwd(), {
|
|
42729
|
-
sectionId: id,
|
|
42730
|
-
sourceUrl: data.sourceUrl,
|
|
42731
|
-
copyStrings: data.copyStrings,
|
|
42732
|
-
consultedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
42733
|
-
});
|
|
42610
|
+
const dir = path29.join(process.cwd(), ".baker", "inspiration", id);
|
|
42611
|
+
await mkdir9(dir, { recursive: true });
|
|
42612
|
+
const file = path29.join(dir, "section.html");
|
|
42613
|
+
await writeFile13(file, data.html);
|
|
42734
42614
|
const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
|
|
42735
42615
|
const fidelity = fidelityHint(data.fidelity);
|
|
42736
42616
|
if (fidelity) hints.push(fidelity);
|
|
42737
42617
|
if (data.fidelityNote) hints.push(data.fidelityNote);
|
|
42738
|
-
if (!recorded) {
|
|
42739
|
-
hints.push(
|
|
42740
|
-
"Could not record this reference (.cache/ not writable?) \u2014 the originality check at publish will not be able to see it, so be especially careful not to reuse its copy."
|
|
42741
|
-
);
|
|
42742
|
-
}
|
|
42743
42618
|
writeJson({
|
|
42744
42619
|
ok: true,
|
|
42745
42620
|
data: {
|
|
42746
42621
|
id,
|
|
42747
|
-
file:
|
|
42622
|
+
file: path29.relative(process.cwd(), file),
|
|
42748
42623
|
bytes: data.html.length,
|
|
42749
42624
|
fidelity: data.fidelity,
|
|
42750
42625
|
reproduction_notes: data.reproductionNotes,
|
|
@@ -42999,25 +42874,8 @@ var pageCommand2 = defineCommand160({
|
|
|
42999
42874
|
});
|
|
43000
42875
|
|
|
43001
42876
|
// src/commands/landing/inspiration/scrape.ts
|
|
43002
|
-
import { readFile as readFile23 } from "fs/promises";
|
|
43003
|
-
import path34 from "path";
|
|
43004
42877
|
import { defineCommand as defineCommand161 } from "citty";
|
|
43005
42878
|
|
|
43006
|
-
// src/engine/landing/lib/capturedReferences.ts
|
|
43007
|
-
var MAX_STRINGS_PER_SECTION = 40;
|
|
43008
|
-
function bodyOf(markup) {
|
|
43009
|
-
const body = markup.indexOf("<body");
|
|
43010
|
-
return body === -1 ? markup : markup.slice(body);
|
|
43011
|
-
}
|
|
43012
|
-
function capturedCopyStrings(markup) {
|
|
43013
|
-
const seen = /* @__PURE__ */ new Set();
|
|
43014
|
-
for (const { value } of extractVisibleStrings(bodyOf(markup))) {
|
|
43015
|
-
seen.add(value);
|
|
43016
|
-
if (seen.size >= MAX_STRINGS_PER_SECTION) break;
|
|
43017
|
-
}
|
|
43018
|
-
return [...seen];
|
|
43019
|
-
}
|
|
43020
|
-
|
|
43021
42879
|
// src/engine/landing-library/proxyFailure.ts
|
|
43022
42880
|
var PROXY_STATUS = 407;
|
|
43023
42881
|
var PROXY_NET_ERRORS = [
|
|
@@ -43192,8 +43050,8 @@ function classifyCaptureFailure(error) {
|
|
|
43192
43050
|
}
|
|
43193
43051
|
|
|
43194
43052
|
// src/engine/landing-library/run.ts
|
|
43195
|
-
import { mkdir as
|
|
43196
|
-
import
|
|
43053
|
+
import { mkdir as mkdir10, writeFile as writeFile15 } from "fs/promises";
|
|
43054
|
+
import path31 from "path";
|
|
43197
43055
|
|
|
43198
43056
|
// ../proxy/src/preflight.ts
|
|
43199
43057
|
import http from "http";
|
|
@@ -44608,11 +44466,11 @@ async function renderBundleToPng(browser, html, viewportWidth, options = {}) {
|
|
|
44608
44466
|
}
|
|
44609
44467
|
|
|
44610
44468
|
// src/engine/landing-library/report.ts
|
|
44611
|
-
import { writeFile as
|
|
44612
|
-
import
|
|
44469
|
+
import { writeFile as writeFile14 } from "fs/promises";
|
|
44470
|
+
import path30 from "path";
|
|
44613
44471
|
async function writeCaptureReport(manifest, outDir) {
|
|
44614
|
-
const file =
|
|
44615
|
-
await
|
|
44472
|
+
const file = path30.join(outDir, "report.html");
|
|
44473
|
+
await writeFile14(file, renderReport(manifest));
|
|
44616
44474
|
return file;
|
|
44617
44475
|
}
|
|
44618
44476
|
function escapeHtml3(value) {
|
|
@@ -44790,32 +44648,32 @@ async function reproducePage(args) {
|
|
|
44790
44648
|
const { browser, page, outDir, pageUrl, livePageShot } = args;
|
|
44791
44649
|
const built = await buildSectionBundle(page, "body", pageUrl).catch(() => null);
|
|
44792
44650
|
if (!built) return { bundle: null, fidelity: null };
|
|
44793
|
-
await
|
|
44651
|
+
await writeFile15(path31.join(outDir, "page.html"), built.html);
|
|
44794
44652
|
const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width, {
|
|
44795
44653
|
wholePage: true,
|
|
44796
44654
|
timeoutMs: 6e4
|
|
44797
44655
|
});
|
|
44798
44656
|
if (!rendered || !livePageShot) return { bundle: "page.html", fidelity: null };
|
|
44799
|
-
await
|
|
44657
|
+
await writeFile15(path31.join(outDir, "page-rendered.png"), rendered);
|
|
44800
44658
|
const { score, note } = await scoreFidelity(livePageShot, rendered);
|
|
44801
44659
|
return { bundle: "page.html", fidelity: score, ...note ? { fidelityNote: note } : {} };
|
|
44802
44660
|
}
|
|
44803
44661
|
async function captureOneSection(args) {
|
|
44804
44662
|
const { browser, page, candidate, sectionsDir, outDir, pageUrl, withCode } = args;
|
|
44805
|
-
const dir =
|
|
44806
|
-
await
|
|
44663
|
+
const dir = path31.join(sectionsDir, String(candidate.index).padStart(2, "0"));
|
|
44664
|
+
await mkdir10(dir, { recursive: true });
|
|
44807
44665
|
const desktop = await captureSection(page, candidate);
|
|
44808
|
-
if (desktop) await
|
|
44666
|
+
if (desktop) await writeFile15(path31.join(dir, "desktop.png"), desktop);
|
|
44809
44667
|
const visualHash = desktop ? await perceptualHash(desktop) : null;
|
|
44810
44668
|
const motion = await collectMotion(page, candidate.selector);
|
|
44811
44669
|
const built = withCode ? await buildSectionBundle(page, candidate.selector, pageUrl) : null;
|
|
44812
44670
|
let fidelity = null;
|
|
44813
44671
|
let fidelityNote;
|
|
44814
44672
|
if (built) {
|
|
44815
|
-
await
|
|
44673
|
+
await writeFile15(path31.join(dir, "section.html"), built.html);
|
|
44816
44674
|
const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width);
|
|
44817
44675
|
if (rendered && desktop) {
|
|
44818
|
-
await
|
|
44676
|
+
await writeFile15(path31.join(dir, "section-rendered.png"), rendered);
|
|
44819
44677
|
const result = await scoreFidelity(desktop, rendered);
|
|
44820
44678
|
fidelity = result.score;
|
|
44821
44679
|
fidelityNote = result.note;
|
|
@@ -44823,9 +44681,9 @@ async function captureOneSection(args) {
|
|
|
44823
44681
|
}
|
|
44824
44682
|
return {
|
|
44825
44683
|
...candidate,
|
|
44826
|
-
desktopShot: desktop ?
|
|
44684
|
+
desktopShot: desktop ? path31.relative(outDir, path31.join(dir, "desktop.png")) : null,
|
|
44827
44685
|
mobileShot: null,
|
|
44828
|
-
bundle: built ?
|
|
44686
|
+
bundle: built ? path31.relative(outDir, path31.join(dir, "section.html")) : null,
|
|
44829
44687
|
fidelity,
|
|
44830
44688
|
...fidelityNote ? { fidelityNote } : {},
|
|
44831
44689
|
...built ? { cssStats: built.stats } : {},
|
|
@@ -44844,9 +44702,9 @@ async function captureMobileShots(args) {
|
|
|
44844
44702
|
for (const section of sections) {
|
|
44845
44703
|
const shot = await captureSectionOnMobile(mobile.page, section);
|
|
44846
44704
|
if (!shot) continue;
|
|
44847
|
-
const file =
|
|
44848
|
-
await
|
|
44849
|
-
section.mobileShot =
|
|
44705
|
+
const file = path31.join(sectionsDir, String(section.index).padStart(2, "0"), "mobile.png");
|
|
44706
|
+
await writeFile15(file, shot);
|
|
44707
|
+
section.mobileShot = path31.relative(outDir, file);
|
|
44850
44708
|
}
|
|
44851
44709
|
} finally {
|
|
44852
44710
|
await mobile.context.close();
|
|
@@ -44861,10 +44719,10 @@ async function captureMotionTakes(args) {
|
|
|
44861
44719
|
const filmOne = async (section) => {
|
|
44862
44720
|
const take = await captureMotionTake(browser, pageUrl, section.selector).catch(() => null);
|
|
44863
44721
|
if (!take) return;
|
|
44864
|
-
const dir =
|
|
44865
|
-
const file =
|
|
44866
|
-
await
|
|
44867
|
-
section.motionFilmstrip =
|
|
44722
|
+
const dir = path31.join(sectionsDir, String(section.index).padStart(2, "0"));
|
|
44723
|
+
const file = path31.join(dir, "motion-filmstrip.png");
|
|
44724
|
+
await writeFile15(file, take.filmstrip);
|
|
44725
|
+
section.motionFilmstrip = path31.relative(outDir, file);
|
|
44868
44726
|
log(` [${section.index}] ${section.motion.summary}`);
|
|
44869
44727
|
};
|
|
44870
44728
|
const queue = [...moving];
|
|
@@ -44921,7 +44779,7 @@ async function captureAlternateViews(args) {
|
|
|
44921
44779
|
async function reproduceWholePage(args) {
|
|
44922
44780
|
const { browser, page, outDir, pageUrl, withCode, log } = args;
|
|
44923
44781
|
const fullPage = await page.screenshot({ type: "png", fullPage: true }).catch(() => null);
|
|
44924
|
-
if (fullPage) await
|
|
44782
|
+
if (fullPage) await writeFile15(path31.join(outDir, "full-page.png"), fullPage);
|
|
44925
44783
|
if (!withCode) return { bundle: null, fidelity: null };
|
|
44926
44784
|
const reproduction = await reproducePage({ browser, page, outDir, pageUrl, livePageShot: fullPage });
|
|
44927
44785
|
log(`page reproduction: ${reproduction.fidelity === null ? "unavailable" : reproduction.fidelity.toFixed(2)}`);
|
|
@@ -44992,7 +44850,7 @@ async function openViaLadder(args) {
|
|
|
44992
44850
|
async function scrapeLanding(options) {
|
|
44993
44851
|
const timeoutMs = options.timeoutMs ?? 45e3;
|
|
44994
44852
|
const log = options.onProgress ?? (() => void 0);
|
|
44995
|
-
const sectionsDir =
|
|
44853
|
+
const sectionsDir = path31.join(options.outDir, "sections");
|
|
44996
44854
|
const nonPublic = refuseNonPublicUrl(options.url);
|
|
44997
44855
|
if (nonPublic) {
|
|
44998
44856
|
throw new BlockedPageError({
|
|
@@ -45012,7 +44870,7 @@ async function scrapeLanding(options) {
|
|
|
45012
44870
|
const withMotion = options.motion !== false && !escalated;
|
|
45013
44871
|
const renderBrowser = options.code === false ? null : await launchBrowser();
|
|
45014
44872
|
try {
|
|
45015
|
-
await
|
|
44873
|
+
await mkdir10(sectionsDir, { recursive: true });
|
|
45016
44874
|
const sections = await captureSections({
|
|
45017
44875
|
browser: renderBrowser ?? browser,
|
|
45018
44876
|
page,
|
|
@@ -45054,7 +44912,7 @@ async function scrapeLanding(options) {
|
|
|
45054
44912
|
security: prepared.security,
|
|
45055
44913
|
captureTier: tier
|
|
45056
44914
|
};
|
|
45057
|
-
await
|
|
44915
|
+
await writeFile15(path31.join(options.outDir, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
45058
44916
|
`);
|
|
45059
44917
|
if (options.report !== false) {
|
|
45060
44918
|
const reportPath = await writeCaptureReport(manifest, options.outDir);
|
|
@@ -45069,28 +44927,28 @@ async function scrapeLanding(options) {
|
|
|
45069
44927
|
|
|
45070
44928
|
// src/commands/landing/inspiration/captureOut.ts
|
|
45071
44929
|
import { existsSync as existsSync9 } from "fs";
|
|
45072
|
-
import
|
|
44930
|
+
import path32 from "path";
|
|
45073
44931
|
var SCRATCH_DIR = ".baker";
|
|
45074
44932
|
function isWithin(parent, target) {
|
|
45075
|
-
const relative =
|
|
45076
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
44933
|
+
const relative = path32.relative(parent, target);
|
|
44934
|
+
return relative === "" || !relative.startsWith("..") && !path32.isAbsolute(relative);
|
|
45077
44935
|
}
|
|
45078
44936
|
function findRepoRoot(from) {
|
|
45079
|
-
let dir =
|
|
44937
|
+
let dir = path32.resolve(from);
|
|
45080
44938
|
for (; ; ) {
|
|
45081
|
-
if (existsSync9(
|
|
45082
|
-
const parent =
|
|
44939
|
+
if (existsSync9(path32.join(dir, ".git"))) return dir;
|
|
44940
|
+
const parent = path32.dirname(dir);
|
|
45083
44941
|
if (parent === dir) return null;
|
|
45084
44942
|
dir = parent;
|
|
45085
44943
|
}
|
|
45086
44944
|
}
|
|
45087
44945
|
function checkCaptureOut(out, options) {
|
|
45088
44946
|
const { cwd, repoRoot } = options;
|
|
45089
|
-
const resolved =
|
|
44947
|
+
const resolved = path32.resolve(cwd, out);
|
|
45090
44948
|
if (repoRoot === null || !isWithin(repoRoot, resolved)) return { ok: true };
|
|
45091
|
-
const scratch =
|
|
44949
|
+
const scratch = path32.join(repoRoot, SCRATCH_DIR);
|
|
45092
44950
|
if (isWithin(scratch, resolved)) return { ok: true };
|
|
45093
|
-
const suggestion =
|
|
44951
|
+
const suggestion = path32.posix.join(SCRATCH_DIR, "teardowns", path32.basename(resolved) || "capture");
|
|
45094
44952
|
return {
|
|
45095
44953
|
ok: false,
|
|
45096
44954
|
error: {
|
|
@@ -45113,29 +44971,8 @@ var RETRYABLE_FAILURES = /* @__PURE__ */ new Set([
|
|
|
45113
44971
|
// would blacklist a page that was never actually judged.
|
|
45114
44972
|
"PROXY_UNAVAILABLE"
|
|
45115
44973
|
]);
|
|
45116
|
-
async function recordCapture(manifest, outDir) {
|
|
45117
|
-
const consultedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
45118
|
-
const references = [];
|
|
45119
|
-
for (const section of manifest.sections) {
|
|
45120
|
-
if (!section.bundle) continue;
|
|
45121
|
-
try {
|
|
45122
|
-
const markup = await readFile23(path34.join(outDir, section.bundle), "utf8");
|
|
45123
|
-
const copyStrings = capturedCopyStrings(markup);
|
|
45124
|
-
if (copyStrings.length === 0) continue;
|
|
45125
|
-
references.push({
|
|
45126
|
-
sectionId: `local:${manifest.finalUrl}#${section.index}`,
|
|
45127
|
-
sourceUrl: manifest.finalUrl,
|
|
45128
|
-
copyStrings,
|
|
45129
|
-
consultedAt
|
|
45130
|
-
});
|
|
45131
|
-
} catch {
|
|
45132
|
-
}
|
|
45133
|
-
}
|
|
45134
|
-
const written = await recordReferences(process.cwd(), references);
|
|
45135
|
-
return written ? references.length : 0;
|
|
45136
|
-
}
|
|
45137
44974
|
function captureHints(args) {
|
|
45138
|
-
const { manifest, outDir, report
|
|
44975
|
+
const { manifest, outDir, report } = args;
|
|
45139
44976
|
const shots = manifest.sections.filter((section) => section.desktopShot !== null).length;
|
|
45140
44977
|
const anyScored = manifest.sections.some((section) => section.fidelity !== null);
|
|
45141
44978
|
const hints = [];
|
|
@@ -45155,14 +44992,11 @@ function captureHints(args) {
|
|
|
45155
44992
|
);
|
|
45156
44993
|
}
|
|
45157
44994
|
hints.push(INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt);
|
|
45158
|
-
hints.push(
|
|
45159
|
-
recorded > 0 ? `${recorded} sections are recorded for the originality check \u2014 \`baker landing critique\` will block a publish that ships their copy.` : "Nothing from this capture is recorded for the originality check, so it cannot see this page. Be especially careful not to reuse its copy."
|
|
45160
|
-
);
|
|
45161
44995
|
return hints;
|
|
45162
44996
|
}
|
|
45163
44997
|
registerSchema({
|
|
45164
44998
|
command: "landing.inspiration.scrape",
|
|
45165
|
-
description: "Start here when the user points at a specific page and wants it now: capture one landing page into a directory of section screenshots, standalone HTML bundles, a whole-page reproduction and motion filmstrips. Returns when the capture is done, unlike `add`. Read the screenshots.
|
|
44999
|
+
description: "Start here when the user points at a specific page and wants it now: capture one landing page into a directory of section screenshots, standalone HTML bundles, a whole-page reproduction and motion filmstrips. Returns when the capture is done, unlike `add`. Read the screenshots.",
|
|
45166
45000
|
args: {
|
|
45167
45001
|
url: { type: "string", description: "Page to capture", required: true },
|
|
45168
45002
|
out: { type: "string", description: "Output directory under .baker/", required: true },
|
|
@@ -45230,7 +45064,6 @@ var scrapeCommand = defineCommand161({
|
|
|
45230
45064
|
`)
|
|
45231
45065
|
});
|
|
45232
45066
|
const scored = manifest.sections.map((section) => section.fidelity).filter((value) => value !== null).sort((a, b) => a - b);
|
|
45233
|
-
const recorded = await recordCapture(manifest, args.out);
|
|
45234
45067
|
writeJson({
|
|
45235
45068
|
ok: true,
|
|
45236
45069
|
data: {
|
|
@@ -45251,7 +45084,7 @@ var scrapeCommand = defineCommand161({
|
|
|
45251
45084
|
certificate_verified: false,
|
|
45252
45085
|
...manifest.security.certificateNotes.length > 0 ? { certificate_notes: manifest.security.certificateNotes } : {}
|
|
45253
45086
|
},
|
|
45254
|
-
hints: captureHints({ manifest, outDir: args.out, report: args.report
|
|
45087
|
+
hints: captureHints({ manifest, outDir: args.out, report: args.report })
|
|
45255
45088
|
});
|
|
45256
45089
|
} catch (error) {
|
|
45257
45090
|
const failure = classifyCaptureFailure(error);
|
|
@@ -45289,12 +45122,12 @@ var scrapeCommand = defineCommand161({
|
|
|
45289
45122
|
});
|
|
45290
45123
|
|
|
45291
45124
|
// src/commands/landing/inspiration/search.ts
|
|
45292
|
-
import
|
|
45125
|
+
import path34 from "path";
|
|
45293
45126
|
import { defineCommand as defineCommand162 } from "citty";
|
|
45294
45127
|
|
|
45295
45128
|
// src/commands/landing/inspiration/shot.ts
|
|
45296
|
-
import { mkdir as
|
|
45297
|
-
import
|
|
45129
|
+
import { mkdir as mkdir11, writeFile as writeFile16 } from "fs/promises";
|
|
45130
|
+
import path33 from "path";
|
|
45298
45131
|
import sharp6 from "sharp";
|
|
45299
45132
|
var READABLE_SHOT = {
|
|
45300
45133
|
maxWidth: 1440,
|
|
@@ -45320,9 +45153,9 @@ async function downloadReadableShot(url, file) {
|
|
|
45320
45153
|
const response = await fetch(url);
|
|
45321
45154
|
if (!response.ok) return null;
|
|
45322
45155
|
const shot = await toReadableShot(Buffer.from(await response.arrayBuffer()));
|
|
45323
|
-
await
|
|
45324
|
-
await
|
|
45325
|
-
return
|
|
45156
|
+
await mkdir11(path33.dirname(file), { recursive: true });
|
|
45157
|
+
await writeFile16(file, shot);
|
|
45158
|
+
return path33.relative(process.cwd(), file);
|
|
45326
45159
|
} catch {
|
|
45327
45160
|
return null;
|
|
45328
45161
|
}
|
|
@@ -45414,13 +45247,13 @@ function buildSearchBody(args) {
|
|
|
45414
45247
|
return body;
|
|
45415
45248
|
}
|
|
45416
45249
|
async function downloadShots(results) {
|
|
45417
|
-
const dir =
|
|
45250
|
+
const dir = path34.join(process.cwd(), ".baker", "inspiration");
|
|
45418
45251
|
const saved = /* @__PURE__ */ new Map();
|
|
45419
45252
|
await Promise.all(
|
|
45420
45253
|
results.map(async (result) => {
|
|
45421
45254
|
const file = await downloadReadableShot(
|
|
45422
45255
|
result.desktopShotUrl,
|
|
45423
|
-
|
|
45256
|
+
path34.join(dir, `${result.id}.${READABLE_SHOT.extension}`)
|
|
45424
45257
|
);
|
|
45425
45258
|
if (file) saved.set(result.id, file);
|
|
45426
45259
|
})
|
|
@@ -45648,7 +45481,7 @@ var sequencesCommand = defineCommand163({
|
|
|
45648
45481
|
});
|
|
45649
45482
|
|
|
45650
45483
|
// src/commands/landing/inspiration/view.ts
|
|
45651
|
-
import
|
|
45484
|
+
import path35 from "path";
|
|
45652
45485
|
import { defineCommand as defineCommand164 } from "citty";
|
|
45653
45486
|
registerSchema({
|
|
45654
45487
|
command: "landing.inspiration.view",
|
|
@@ -45681,12 +45514,12 @@ var viewCommand2 = defineCommand164({
|
|
|
45681
45514
|
const id = args.id;
|
|
45682
45515
|
const data = await apiGet("/api/landing-inspiration/section", { id });
|
|
45683
45516
|
const section = data.section;
|
|
45684
|
-
const dir =
|
|
45517
|
+
const dir = path35.join(process.cwd(), ".baker", "inspiration", id);
|
|
45685
45518
|
const ext = READABLE_SHOT.extension;
|
|
45686
45519
|
const [desktop, mobile, filmstrip] = await Promise.all([
|
|
45687
|
-
downloadReadableShot(section.desktopShotUrl,
|
|
45688
|
-
downloadReadableShot(section.mobileShotUrl,
|
|
45689
|
-
downloadReadableShot(section.motionFilmstripUrl,
|
|
45520
|
+
downloadReadableShot(section.desktopShotUrl, path35.join(dir, `desktop.${ext}`)),
|
|
45521
|
+
downloadReadableShot(section.mobileShotUrl, path35.join(dir, `mobile.${ext}`)),
|
|
45522
|
+
downloadReadableShot(section.motionFilmstripUrl, path35.join(dir, `motion-filmstrip.${ext}`))
|
|
45690
45523
|
]);
|
|
45691
45524
|
const full = args.full;
|
|
45692
45525
|
const hints = [INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt];
|
|
@@ -45753,7 +45586,7 @@ var inspirationCommand = defineCommand165({
|
|
|
45753
45586
|
|
|
45754
45587
|
Start here: \`baker landing inspiration search "<what you want to see>"\` during research, BEFORE you write the Direction Contract.
|
|
45755
45588
|
|
|
45756
|
-
This is inspiration, never a clipboard. Take the mechanism \u2014 what the eye hits first, what proof arrives before the ask, how the grid is split. The words are never yours to reuse: shipping a reference's headline is a Tier 0 message-match failure
|
|
45589
|
+
This is inspiration, never a clipboard. Take the mechanism \u2014 what the eye hits first, what proof arrives before the ask, how the grid is split. The words are never yours to reuse: shipping a reference's headline is a Tier 0 message-match failure.
|
|
45757
45590
|
|
|
45758
45591
|
Subcommands:
|
|
45759
45592
|
baker landing inspiration search "<query>" \u2014 search by look, section type, composition, register or motion; saves screenshots you can Read
|
|
@@ -47535,8 +47368,8 @@ var listCommand15 = defineCommand183({
|
|
|
47535
47368
|
});
|
|
47536
47369
|
|
|
47537
47370
|
// src/commands/scheduled-actions/templates.ts
|
|
47538
|
-
import { readFile as
|
|
47539
|
-
import
|
|
47371
|
+
import { readFile as readFile22 } from "fs/promises";
|
|
47372
|
+
import path36 from "path";
|
|
47540
47373
|
import { defineCommand as defineCommand184 } from "citty";
|
|
47541
47374
|
registerSchema({
|
|
47542
47375
|
command: "scheduled-actions.templates",
|
|
@@ -47639,7 +47472,7 @@ Full guide: __tooling__/docs/tools/baker/scheduled-actions.md`
|
|
|
47639
47472
|
}
|
|
47640
47473
|
if (save.length > 0) {
|
|
47641
47474
|
const briefFile = flag("brief-file");
|
|
47642
|
-
const brief = briefFile.length > 0 ? await
|
|
47475
|
+
const brief = briefFile.length > 0 ? await readFile22(path36.resolve(briefFile), "utf8") : flag("brief");
|
|
47643
47476
|
if (brief.trim().length === 0) {
|
|
47644
47477
|
failValidation4("--brief-file (preferred) or --brief is required: the brief is the recipe.");
|
|
47645
47478
|
}
|
|
@@ -48110,7 +47943,7 @@ function parseImageRefs(spec) {
|
|
|
48110
47943
|
}
|
|
48111
47944
|
var defaultDeps = {
|
|
48112
47945
|
ingest: (url) => apiPost("/api/images/ingest", { url, source: "uploaded" }),
|
|
48113
|
-
upload: (
|
|
47946
|
+
upload: (path38) => uploadLocalImage({ file: path38, contentType: detectImageContentType(path38), source: "uploaded" })
|
|
48114
47947
|
};
|
|
48115
47948
|
async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
48116
47949
|
const refs = parseImageRefs(spec);
|
|
@@ -48130,10 +47963,10 @@ async function resolveLibraryImageIds(spec, limit, deps = defaultDeps) {
|
|
|
48130
47963
|
}
|
|
48131
47964
|
return { imageIds, added };
|
|
48132
47965
|
}
|
|
48133
|
-
function uploadFailure(
|
|
47966
|
+
function uploadFailure(path38) {
|
|
48134
47967
|
return (error) => {
|
|
48135
47968
|
if (error instanceof ApiError) throw error;
|
|
48136
|
-
throw new ApiError("VALIDATION_ERROR", `Could not read "${
|
|
47969
|
+
throw new ApiError("VALIDATION_ERROR", `Could not read "${path38}" as an image.`);
|
|
48137
47970
|
};
|
|
48138
47971
|
}
|
|
48139
47972
|
|
|
@@ -49195,10 +49028,10 @@ async function stageOp4(op) {
|
|
|
49195
49028
|
handleError5(err);
|
|
49196
49029
|
}
|
|
49197
49030
|
}
|
|
49198
|
-
async function draftAction3(
|
|
49031
|
+
async function draftAction3(path38, body, chat) {
|
|
49199
49032
|
const chatId = resolveChatId(chat);
|
|
49200
49033
|
try {
|
|
49201
|
-
const data = await apiPost(
|
|
49034
|
+
const data = await apiPost(path38, { chatId, ...body });
|
|
49202
49035
|
writeJsonEnvelope({ ok: true, data });
|
|
49203
49036
|
return data;
|
|
49204
49037
|
} catch (err) {
|
|
@@ -50305,7 +50138,7 @@ var groupCommand2 = defineCommand209({
|
|
|
50305
50138
|
// src/commands/videos/ingest.ts
|
|
50306
50139
|
import { mkdtemp as mkdtemp2, rm as rm7, stat as stat7 } from "fs/promises";
|
|
50307
50140
|
import { tmpdir as tmpdir3 } from "os";
|
|
50308
|
-
import
|
|
50141
|
+
import path37 from "path";
|
|
50309
50142
|
import { defineCommand as defineCommand210 } from "citty";
|
|
50310
50143
|
|
|
50311
50144
|
// src/lib/streamUpload.ts
|
|
@@ -50656,7 +50489,7 @@ function ingestUrl(args) {
|
|
|
50656
50489
|
}
|
|
50657
50490
|
async function downloadThenIngest(args, country) {
|
|
50658
50491
|
const vimeoCookie = captureVimeoCookie();
|
|
50659
|
-
const workDir = await mkdtemp2(
|
|
50492
|
+
const workDir = await mkdtemp2(path37.join(tmpdir3(), "videos-ingest-"));
|
|
50660
50493
|
try {
|
|
50661
50494
|
const probe = await probeYtDlp({ url: args.url, country, vimeoCookie, cookieDir: workDir });
|
|
50662
50495
|
if (isAudioOnly(probe.info)) {
|
|
@@ -50792,7 +50625,7 @@ var searchCommand4 = defineCommand211({
|
|
|
50792
50625
|
var tagsCommand6 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
50793
50626
|
|
|
50794
50627
|
// src/commands/videos/upload.ts
|
|
50795
|
-
import { readFile as
|
|
50628
|
+
import { readFile as readFile23, stat as stat8 } from "fs/promises";
|
|
50796
50629
|
import { basename as basename3, extname as extname4 } from "path";
|
|
50797
50630
|
import { defineCommand as defineCommand212 } from "citty";
|
|
50798
50631
|
var MIME_MAP = {
|
|
@@ -50889,7 +50722,7 @@ var uploadCommand2 = defineCommand212({
|
|
|
50889
50722
|
originalFilename,
|
|
50890
50723
|
descriptionContext
|
|
50891
50724
|
});
|
|
50892
|
-
const fileBuffer = await
|
|
50725
|
+
const fileBuffer = await readFile23(filePath);
|
|
50893
50726
|
const uploadResponse = await fetch(uploadUrl, {
|
|
50894
50727
|
method: "PUT",
|
|
50895
50728
|
headers: { "Content-Type": contentType },
|
|
@@ -52276,7 +52109,7 @@ function unknownFlagEnvelope(unknown, commandPath, suggestion) {
|
|
|
52276
52109
|
};
|
|
52277
52110
|
}
|
|
52278
52111
|
function commandPathOf(root, argv) {
|
|
52279
|
-
const
|
|
52112
|
+
const path38 = [];
|
|
52280
52113
|
let command = root;
|
|
52281
52114
|
for (const token of argv) {
|
|
52282
52115
|
if (token === "--" || token.startsWith("-")) {
|
|
@@ -52287,10 +52120,10 @@ function commandPathOf(root, argv) {
|
|
|
52287
52120
|
if (next === void 0 || typeof next !== "object") {
|
|
52288
52121
|
break;
|
|
52289
52122
|
}
|
|
52290
|
-
|
|
52123
|
+
path38.push(token);
|
|
52291
52124
|
command = next;
|
|
52292
52125
|
}
|
|
52293
|
-
return
|
|
52126
|
+
return path38.join(" ");
|
|
52294
52127
|
}
|
|
52295
52128
|
function refuseUnknownFlags(root, argv) {
|
|
52296
52129
|
const unknown = findUnknownFlags(root, argv);
|