canopycms 0.0.25 → 0.0.27
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/ai/generate.d.ts +3 -0
- package/dist/ai/generate.d.ts.map +1 -1
- package/dist/ai/generate.js +17 -6
- package/dist/ai/generate.js.map +1 -1
- package/dist/ai/handler.d.ts.map +1 -1
- package/dist/ai/handler.js +1 -0
- package/dist/ai/handler.js.map +1 -1
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/json-to-markdown.d.ts.map +1 -1
- package/dist/ai/json-to-markdown.js +10 -2
- package/dist/ai/json-to-markdown.js.map +1 -1
- package/dist/ai/transform-components.d.ts +27 -0
- package/dist/ai/transform-components.d.ts.map +1 -0
- package/dist/ai/transform-components.js +168 -0
- package/dist/ai/transform-components.js.map +1 -0
- package/dist/ai/types.d.ts +50 -0
- package/dist/ai/types.d.ts.map +1 -1
- package/dist/ai/types.js.map +1 -1
- package/dist/api/content.d.ts +6 -0
- package/dist/api/content.d.ts.map +1 -1
- package/dist/api/content.js +18 -1
- package/dist/api/content.js.map +1 -1
- package/dist/api/schema.d.ts +20 -20
- package/dist/build/generate-ai-content.d.ts.map +1 -1
- package/dist/build/generate-ai-content.js +1 -0
- package/dist/build/generate-ai-content.js.map +1 -1
- package/dist/cli/generate-ai-content.js +383 -124
- package/dist/cli/init.js +2 -1
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -0
- package/dist/client.js.map +1 -1
- package/dist/config/helpers.d.ts.map +1 -1
- package/dist/config/helpers.js +2 -1
- package/dist/config/helpers.js.map +1 -1
- package/dist/config/schemas/collection.d.ts +6 -6
- package/dist/config/schemas/config.d.ts +10 -6
- package/dist/config/schemas/config.d.ts.map +1 -1
- package/dist/config/schemas/config.js +1 -0
- package/dist/config/schemas/config.js.map +1 -1
- package/dist/config/types.d.ts +6 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/content-reader.d.ts +2 -0
- package/dist/content-reader.d.ts.map +1 -1
- package/dist/content-reader.js +13 -4
- package/dist/content-reader.js.map +1 -1
- package/dist/editor/CanopyEditor.d.ts.map +1 -1
- package/dist/editor/CanopyEditor.js +1 -1
- package/dist/editor/CanopyEditor.js.map +1 -1
- package/dist/editor/Editor.d.ts +1 -0
- package/dist/editor/Editor.d.ts.map +1 -1
- package/dist/editor/Editor.js +32 -9
- package/dist/editor/Editor.js.map +1 -1
- package/dist/editor/fields/MarkdownField.d.ts.map +1 -1
- package/dist/editor/fields/MarkdownField.js +8 -2
- package/dist/editor/fields/MarkdownField.js.map +1 -1
- package/dist/editor/fields/entry-link/EntryLinkContext.d.ts +20 -0
- package/dist/editor/fields/entry-link/EntryLinkContext.d.ts.map +1 -0
- package/dist/editor/fields/entry-link/EntryLinkContext.js +12 -0
- package/dist/editor/fields/entry-link/EntryLinkContext.js.map +1 -0
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +16 -0
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts.map +1 -0
- package/dist/editor/fields/entry-link/InsertEntryLink.js +62 -0
- package/dist/editor/fields/entry-link/InsertEntryLink.js.map +1 -0
- package/dist/editor/fields/entry-link/index.d.ts +3 -0
- package/dist/editor/fields/entry-link/index.d.ts.map +1 -0
- package/dist/editor/fields/entry-link/index.js +3 -0
- package/dist/editor/fields/entry-link/index.js.map +1 -0
- package/dist/editor/hooks/useEntryLinkResolution.d.ts +26 -0
- package/dist/editor/hooks/useEntryLinkResolution.d.ts.map +1 -0
- package/dist/editor/hooks/useEntryLinkResolution.js +96 -0
- package/dist/editor/hooks/useEntryLinkResolution.js.map +1 -0
- package/dist/entry-link-resolver.d.ts +67 -0
- package/dist/entry-link-resolver.d.ts.map +1 -0
- package/dist/entry-link-resolver.js +226 -0
- package/dist/entry-link-resolver.js.map +1 -0
- package/dist/schema/schema-store.d.ts +10 -10
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -1
- package/dist/utils/entry-url.d.ts +21 -0
- package/dist/utils/entry-url.d.ts.map +1 -0
- package/dist/utils/entry-url.js +41 -0
- package/dist/utils/entry-url.js.map +1 -0
- package/dist/validation/entry-link-validator.d.ts +27 -0
- package/dist/validation/entry-link-validator.d.ts.map +1 -0
- package/dist/validation/entry-link-validator.js +49 -0
- package/dist/validation/entry-link-validator.js.map +1 -0
- package/package.json +1 -1
|
@@ -23,6 +23,15 @@ function createLogicalPath(...segments) {
|
|
|
23
23
|
}
|
|
24
24
|
return normalized;
|
|
25
25
|
}
|
|
26
|
+
function trimSlashes(path13) {
|
|
27
|
+
let start = 0;
|
|
28
|
+
let end = path13.length;
|
|
29
|
+
while (start < end && path13[start] === "/")
|
|
30
|
+
start++;
|
|
31
|
+
while (end > start && path13[end - 1] === "/")
|
|
32
|
+
end--;
|
|
33
|
+
return path13.slice(start, end);
|
|
34
|
+
}
|
|
26
35
|
var init_normalize = __esm({
|
|
27
36
|
"dist/paths/normalize.js"() {
|
|
28
37
|
"use strict";
|
|
@@ -348,7 +357,8 @@ var init_config = __esm({
|
|
|
348
357
|
contentRoot: contentRootSchema.default("content"),
|
|
349
358
|
sourceRoot: sourceRootSchema.optional(),
|
|
350
359
|
editor: editorConfigSchema.optional(),
|
|
351
|
-
authPlugin: z4.custom().optional()
|
|
360
|
+
authPlugin: z4.custom().optional(),
|
|
361
|
+
entryLinkUrl: z4.custom().optional()
|
|
352
362
|
});
|
|
353
363
|
DEFAULT_PROD_WORKSPACE = "/mnt/efs/workspace";
|
|
354
364
|
}
|
|
@@ -1974,6 +1984,119 @@ function stripMdxImports(body) {
|
|
|
1974
1984
|
return result.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
1975
1985
|
}
|
|
1976
1986
|
|
|
1987
|
+
// dist/ai/transform-components.js
|
|
1988
|
+
function parseComponentProps(attrString) {
|
|
1989
|
+
const props = {};
|
|
1990
|
+
if (!attrString)
|
|
1991
|
+
return props;
|
|
1992
|
+
const attrRegex = /(\w+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|\{([^}]*)\}))?/g;
|
|
1993
|
+
let match;
|
|
1994
|
+
while ((match = attrRegex.exec(attrString)) !== null) {
|
|
1995
|
+
const name = match[1];
|
|
1996
|
+
const value = match[2] ?? match[3] ?? match[4] ?? "true";
|
|
1997
|
+
props[name] = value;
|
|
1998
|
+
}
|
|
1999
|
+
return props;
|
|
2000
|
+
}
|
|
2001
|
+
var ATTR_CONTENT = `(?:[^>"']|"[^"]*"|'[^']*')*`;
|
|
2002
|
+
var BLOCK_PREFIX = "<<CODEBLOCK";
|
|
2003
|
+
var BLOCK_SUFFIX = ">>";
|
|
2004
|
+
var BLOCK_RESTORE_RE = /<<CODEBLOCK(\d+)>>/g;
|
|
2005
|
+
var INLINE_PREFIX = "<<INLINECODE";
|
|
2006
|
+
var INLINE_SUFFIX = ">>";
|
|
2007
|
+
var INLINE_RESTORE_RE = /<<INLINECODE(\d+)>>/g;
|
|
2008
|
+
function maskCodeBlocks(body) {
|
|
2009
|
+
const blocks = [];
|
|
2010
|
+
const inlines = [];
|
|
2011
|
+
let masked = body.replace(/^(```|~~~).*\n[\s\S]*?\n\1\s*$/gm, (block) => {
|
|
2012
|
+
const idx = blocks.length;
|
|
2013
|
+
blocks.push(block);
|
|
2014
|
+
return `${BLOCK_PREFIX}${idx}${BLOCK_SUFFIX}`;
|
|
2015
|
+
});
|
|
2016
|
+
masked = masked.replace(/``[^`]+``|`[^`]+`/g, (span) => {
|
|
2017
|
+
const idx = inlines.length;
|
|
2018
|
+
inlines.push(span);
|
|
2019
|
+
return `${INLINE_PREFIX}${idx}${INLINE_SUFFIX}`;
|
|
2020
|
+
});
|
|
2021
|
+
return {
|
|
2022
|
+
masked,
|
|
2023
|
+
restore: (s) => {
|
|
2024
|
+
s = s.replace(INLINE_RESTORE_RE, (_, i) => inlines[Number(i)]);
|
|
2025
|
+
s = s.replace(BLOCK_RESTORE_RE, (_, i) => blocks[Number(i)]);
|
|
2026
|
+
return s;
|
|
2027
|
+
}
|
|
2028
|
+
};
|
|
2029
|
+
}
|
|
2030
|
+
function applyComponentTransforms(body, transforms) {
|
|
2031
|
+
const names = Object.keys(transforms);
|
|
2032
|
+
if (names.length === 0)
|
|
2033
|
+
return body;
|
|
2034
|
+
const { masked, restore } = maskCodeBlocks(body);
|
|
2035
|
+
let result = masked;
|
|
2036
|
+
const MAX_PASSES = 10;
|
|
2037
|
+
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
2038
|
+
let changed = false;
|
|
2039
|
+
for (const name of names) {
|
|
2040
|
+
const transform = transforms[name];
|
|
2041
|
+
const selfClosingRegex = new RegExp(`<${escapeRegex(name)}(\\s${ATTR_CONTENT}?)?\\s*/>`, "g");
|
|
2042
|
+
result = result.replace(selfClosingRegex, (raw, attrStr) => {
|
|
2043
|
+
const props = parseComponentProps(attrStr?.trim() ?? "");
|
|
2044
|
+
const replacement = transform(props, "");
|
|
2045
|
+
if (replacement === void 0)
|
|
2046
|
+
return raw;
|
|
2047
|
+
changed = true;
|
|
2048
|
+
return replacement;
|
|
2049
|
+
});
|
|
2050
|
+
const openRegex = new RegExp(`<${escapeRegex(name)}(\\s${ATTR_CONTENT})?>`, "g");
|
|
2051
|
+
let openMatch;
|
|
2052
|
+
while ((openMatch = openRegex.exec(result)) !== null) {
|
|
2053
|
+
const openStart = openMatch.index;
|
|
2054
|
+
const openEnd = openStart + openMatch[0].length;
|
|
2055
|
+
const attrStr = openMatch[1]?.trim() ?? "";
|
|
2056
|
+
const closeTag = `</${name}>`;
|
|
2057
|
+
const closeIdx = findMatchingClose(result, openEnd, name, closeTag);
|
|
2058
|
+
if (closeIdx === -1)
|
|
2059
|
+
break;
|
|
2060
|
+
const children = result.slice(openEnd, closeIdx);
|
|
2061
|
+
const fullEnd = closeIdx + closeTag.length;
|
|
2062
|
+
const props = parseComponentProps(attrStr);
|
|
2063
|
+
const replacement = transform(props, children);
|
|
2064
|
+
if (replacement === void 0) {
|
|
2065
|
+
openRegex.lastIndex = fullEnd;
|
|
2066
|
+
continue;
|
|
2067
|
+
}
|
|
2068
|
+
result = result.slice(0, openStart) + replacement + result.slice(fullEnd);
|
|
2069
|
+
changed = true;
|
|
2070
|
+
openRegex.lastIndex = openStart + replacement.length;
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
if (!changed)
|
|
2074
|
+
break;
|
|
2075
|
+
}
|
|
2076
|
+
return restore(result);
|
|
2077
|
+
}
|
|
2078
|
+
function findMatchingClose(body, startFrom, name, closeTag) {
|
|
2079
|
+
let depth = 1;
|
|
2080
|
+
const pos = startFrom;
|
|
2081
|
+
const tagRegex = new RegExp(`<${escapeRegex(name)}(?:\\s${ATTR_CONTENT})?>|<${escapeRegex(name)}(?:\\s${ATTR_CONTENT})?\\s*/>|${escapeRegex(closeTag)}`, "g");
|
|
2082
|
+
tagRegex.lastIndex = pos;
|
|
2083
|
+
let match;
|
|
2084
|
+
while ((match = tagRegex.exec(body)) !== null) {
|
|
2085
|
+
const tag = match[0];
|
|
2086
|
+
if (tag === closeTag) {
|
|
2087
|
+
depth--;
|
|
2088
|
+
if (depth === 0)
|
|
2089
|
+
return match.index;
|
|
2090
|
+
} else if (!tag.endsWith("/>")) {
|
|
2091
|
+
depth++;
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
return -1;
|
|
2095
|
+
}
|
|
2096
|
+
function escapeRegex(s) {
|
|
2097
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2098
|
+
}
|
|
2099
|
+
|
|
1977
2100
|
// dist/ai/json-to-markdown.js
|
|
1978
2101
|
function entryToMarkdown(entry, config) {
|
|
1979
2102
|
const parts = [];
|
|
@@ -2017,7 +2140,14 @@ function renderMarkdownEntry(entry, config, skipFields) {
|
|
|
2017
2140
|
parts.push("");
|
|
2018
2141
|
}
|
|
2019
2142
|
if (entry.body) {
|
|
2020
|
-
|
|
2143
|
+
let body = entry.format === "mdx" ? stripMdxImports(entry.body) : entry.body;
|
|
2144
|
+
if (config?.componentTransforms && Object.keys(config.componentTransforms).length > 0) {
|
|
2145
|
+
body = applyComponentTransforms(body, config.componentTransforms);
|
|
2146
|
+
}
|
|
2147
|
+
const bodyTransformFn = config?.bodyTransforms?.[entry.entryType];
|
|
2148
|
+
if (bodyTransformFn) {
|
|
2149
|
+
body = bodyTransformFn(body, entry);
|
|
2150
|
+
}
|
|
2021
2151
|
parts.push(body.trim());
|
|
2022
2152
|
parts.push("");
|
|
2023
2153
|
}
|
|
@@ -2246,10 +2376,223 @@ function yamlValue(value) {
|
|
|
2246
2376
|
return value;
|
|
2247
2377
|
}
|
|
2248
2378
|
|
|
2379
|
+
// dist/utils/debug.js
|
|
2380
|
+
var LOG_LEVELS = {
|
|
2381
|
+
DEBUG: 0,
|
|
2382
|
+
INFO: 1,
|
|
2383
|
+
WARN: 2,
|
|
2384
|
+
ERROR: 3
|
|
2385
|
+
};
|
|
2386
|
+
var DebugLogger = class {
|
|
2387
|
+
constructor(options = {}) {
|
|
2388
|
+
this.timers = /* @__PURE__ */ new Map();
|
|
2389
|
+
this.options = options;
|
|
2390
|
+
}
|
|
2391
|
+
shouldLog(level) {
|
|
2392
|
+
const enabled = this.options.enabled ?? process.env.CANOPYCMS_DEBUG === "true";
|
|
2393
|
+
if (!enabled)
|
|
2394
|
+
return false;
|
|
2395
|
+
const minLevel = this.options.minLevel ?? "DEBUG";
|
|
2396
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[minLevel];
|
|
2397
|
+
}
|
|
2398
|
+
formatMessage(level, category, message) {
|
|
2399
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2400
|
+
const prefix = this.options.prefix ?? "CanopyCMS";
|
|
2401
|
+
return `[${timestamp}] [${prefix}:${category}] [${level}] ${message}`;
|
|
2402
|
+
}
|
|
2403
|
+
debug(category, message, data) {
|
|
2404
|
+
if (this.shouldLog("DEBUG")) {
|
|
2405
|
+
console.log(this.formatMessage("DEBUG", category, message), data ?? "");
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
info(category, message, data) {
|
|
2409
|
+
if (this.shouldLog("INFO")) {
|
|
2410
|
+
console.log(this.formatMessage("INFO", category, message), data ?? "");
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
warn(category, message, data) {
|
|
2414
|
+
if (this.shouldLog("WARN")) {
|
|
2415
|
+
console.warn(this.formatMessage("WARN", category, message), data ?? "");
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
error(category, message, data) {
|
|
2419
|
+
const msg = this.formatMessage("ERROR", category, message);
|
|
2420
|
+
if (this.shouldLog("ERROR")) {
|
|
2421
|
+
console.error(msg, data ?? "");
|
|
2422
|
+
}
|
|
2423
|
+
const throwOnError = this.options.throwOnError ?? false;
|
|
2424
|
+
if (throwOnError) {
|
|
2425
|
+
const errorMsg = data ? `${message}: ${JSON.stringify(data)}` : message;
|
|
2426
|
+
throw new Error(errorMsg);
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
/**
|
|
2430
|
+
* Start timing an operation
|
|
2431
|
+
*/
|
|
2432
|
+
time(label) {
|
|
2433
|
+
this.timers.set(label, Date.now());
|
|
2434
|
+
}
|
|
2435
|
+
/**
|
|
2436
|
+
* End timing an operation and log the duration
|
|
2437
|
+
*/
|
|
2438
|
+
timeEnd(category, label) {
|
|
2439
|
+
const start = this.timers.get(label);
|
|
2440
|
+
if (start === void 0) {
|
|
2441
|
+
this.warn(category, `Timer '${label}' does not exist`);
|
|
2442
|
+
return;
|
|
2443
|
+
}
|
|
2444
|
+
const duration = Date.now() - start;
|
|
2445
|
+
this.timers.delete(label);
|
|
2446
|
+
this.debug(category, `${label} completed`, { durationMs: duration });
|
|
2447
|
+
return duration;
|
|
2448
|
+
}
|
|
2449
|
+
/**
|
|
2450
|
+
* Wrap an async function with automatic timing
|
|
2451
|
+
*/
|
|
2452
|
+
async timed(category, label, fn) {
|
|
2453
|
+
this.time(label);
|
|
2454
|
+
try {
|
|
2455
|
+
return await fn();
|
|
2456
|
+
} finally {
|
|
2457
|
+
this.timeEnd(category, label);
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
};
|
|
2461
|
+
function createDebugLogger(options) {
|
|
2462
|
+
return new DebugLogger(options);
|
|
2463
|
+
}
|
|
2464
|
+
var testLogger = createDebugLogger({
|
|
2465
|
+
enabled: process.env.E2E_DEBUG === "true",
|
|
2466
|
+
prefix: "E2E",
|
|
2467
|
+
throwOnError: false
|
|
2468
|
+
});
|
|
2469
|
+
|
|
2470
|
+
// dist/utils/entry-url.js
|
|
2471
|
+
init_normalize();
|
|
2472
|
+
function computeEntryUrl(collection, slug, contentRoot) {
|
|
2473
|
+
const root = trimSlashes(contentRoot);
|
|
2474
|
+
let stripped = collection;
|
|
2475
|
+
if (root && collection.startsWith(`${root}/`)) {
|
|
2476
|
+
stripped = collection.slice(root.length + 1);
|
|
2477
|
+
} else if (collection === root) {
|
|
2478
|
+
stripped = "";
|
|
2479
|
+
}
|
|
2480
|
+
const segments = stripped.split("/").filter(Boolean);
|
|
2481
|
+
if (slug && slug !== "index") {
|
|
2482
|
+
segments.push(slug);
|
|
2483
|
+
}
|
|
2484
|
+
const path13 = segments.length > 0 ? `/${segments.join("/")}` : "/";
|
|
2485
|
+
return path13.toLowerCase();
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
// dist/entry-link-resolver.js
|
|
2489
|
+
var log = createDebugLogger({ prefix: "EntryLinks" });
|
|
2490
|
+
var BASE58_CHAR = "[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]";
|
|
2491
|
+
var ENTRY_LINK_PATTERN = new RegExp(`entry:(${BASE58_CHAR}{12})(#[^\\s)>"']*)?`, "g");
|
|
2492
|
+
function resolveEntryUrl(location, contentRoot) {
|
|
2493
|
+
return computeEntryUrl(location.collection ?? "", location.slug ?? "", contentRoot);
|
|
2494
|
+
}
|
|
2495
|
+
function resolveEntryLinksInText(text, idIndex, contentRoot, customResolver) {
|
|
2496
|
+
const parts = splitByCodeRegions(text);
|
|
2497
|
+
return parts.map((part) => {
|
|
2498
|
+
if (part.isCode)
|
|
2499
|
+
return part.text;
|
|
2500
|
+
return part.text.replace(ENTRY_LINK_PATTERN, (_match, id, anchor) => {
|
|
2501
|
+
const location = idIndex.findById(id);
|
|
2502
|
+
if (!location || location.type !== "entry" || !location.collection || !location.slug) {
|
|
2503
|
+
log.warn("resolve", `Entry link target not found: entry:${id}`);
|
|
2504
|
+
return anchor ?? "#";
|
|
2505
|
+
}
|
|
2506
|
+
let url;
|
|
2507
|
+
if (customResolver) {
|
|
2508
|
+
url = customResolver({
|
|
2509
|
+
collection: location.collection,
|
|
2510
|
+
slug: location.slug,
|
|
2511
|
+
id
|
|
2512
|
+
});
|
|
2513
|
+
} else {
|
|
2514
|
+
url = resolveEntryUrl(location, contentRoot);
|
|
2515
|
+
}
|
|
2516
|
+
return `${url}${anchor ?? ""}`;
|
|
2517
|
+
});
|
|
2518
|
+
}).join("");
|
|
2519
|
+
}
|
|
2520
|
+
function splitByCodeRegions(text) {
|
|
2521
|
+
const parts = [];
|
|
2522
|
+
let current = "";
|
|
2523
|
+
let i = 0;
|
|
2524
|
+
while (i < text.length) {
|
|
2525
|
+
if ((text[i] === "`" || text[i] === "~") && i + 2 < text.length && text[i + 1] === text[i] && text[i + 2] === text[i]) {
|
|
2526
|
+
const fence = text[i];
|
|
2527
|
+
let fenceLen = 0;
|
|
2528
|
+
while (i + fenceLen < text.length && text[i + fenceLen] === fence)
|
|
2529
|
+
fenceLen++;
|
|
2530
|
+
const lineEnd = text.indexOf("\n", i + fenceLen);
|
|
2531
|
+
if (lineEnd === -1) {
|
|
2532
|
+
if (current)
|
|
2533
|
+
parts.push({ text: current, isCode: false });
|
|
2534
|
+
parts.push({ text: text.slice(i), isCode: true });
|
|
2535
|
+
return parts;
|
|
2536
|
+
}
|
|
2537
|
+
const closingPattern = fence.repeat(fenceLen);
|
|
2538
|
+
let closeStart = lineEnd + 1;
|
|
2539
|
+
let found = false;
|
|
2540
|
+
while (closeStart < text.length) {
|
|
2541
|
+
const nextNewline = text.indexOf("\n", closeStart);
|
|
2542
|
+
const lineContent = nextNewline === -1 ? text.slice(closeStart) : text.slice(closeStart, nextNewline);
|
|
2543
|
+
if (lineContent.trim().startsWith(closingPattern)) {
|
|
2544
|
+
const endPos = nextNewline === -1 ? text.length : nextNewline + 1;
|
|
2545
|
+
if (current)
|
|
2546
|
+
parts.push({ text: current, isCode: false });
|
|
2547
|
+
current = "";
|
|
2548
|
+
parts.push({ text: text.slice(i, endPos), isCode: true });
|
|
2549
|
+
i = endPos;
|
|
2550
|
+
found = true;
|
|
2551
|
+
break;
|
|
2552
|
+
}
|
|
2553
|
+
if (nextNewline === -1)
|
|
2554
|
+
break;
|
|
2555
|
+
closeStart = nextNewline + 1;
|
|
2556
|
+
}
|
|
2557
|
+
if (!found) {
|
|
2558
|
+
if (current)
|
|
2559
|
+
parts.push({ text: current, isCode: false });
|
|
2560
|
+
parts.push({ text: text.slice(i), isCode: true });
|
|
2561
|
+
return parts;
|
|
2562
|
+
}
|
|
2563
|
+
continue;
|
|
2564
|
+
}
|
|
2565
|
+
if (text[i] === "`") {
|
|
2566
|
+
let ticks = 0;
|
|
2567
|
+
while (i + ticks < text.length && text[i + ticks] === "`")
|
|
2568
|
+
ticks++;
|
|
2569
|
+
const closer = "`".repeat(ticks);
|
|
2570
|
+
const closeIdx = text.indexOf(closer, i + ticks);
|
|
2571
|
+
if (closeIdx !== -1) {
|
|
2572
|
+
if (current)
|
|
2573
|
+
parts.push({ text: current, isCode: false });
|
|
2574
|
+
current = "";
|
|
2575
|
+
parts.push({ text: text.slice(i, closeIdx + ticks), isCode: true });
|
|
2576
|
+
i = closeIdx + ticks;
|
|
2577
|
+
continue;
|
|
2578
|
+
}
|
|
2579
|
+
current += text.slice(i, i + ticks);
|
|
2580
|
+
i += ticks;
|
|
2581
|
+
continue;
|
|
2582
|
+
}
|
|
2583
|
+
current += text[i];
|
|
2584
|
+
i++;
|
|
2585
|
+
}
|
|
2586
|
+
if (current)
|
|
2587
|
+
parts.push({ text: current, isCode: false });
|
|
2588
|
+
return parts;
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2249
2591
|
// dist/ai/generate.js
|
|
2250
2592
|
async function generateAIContent(options) {
|
|
2251
|
-
const { store, flatSchema, contentRoot, config } = options;
|
|
2593
|
+
const { store, flatSchema, contentRoot, config, entryLinkUrl } = options;
|
|
2252
2594
|
const files = /* @__PURE__ */ new Map();
|
|
2595
|
+
const idIndex = await store.idIndex();
|
|
2253
2596
|
const collections = flatSchema.filter((item) => item.type === "collection");
|
|
2254
2597
|
const allEntries = [];
|
|
2255
2598
|
const manifestCollections = [];
|
|
@@ -2261,7 +2604,7 @@ async function generateAIContent(options) {
|
|
|
2261
2604
|
continue;
|
|
2262
2605
|
if (collection.parentPath && collection.parentPath !== contentRoot)
|
|
2263
2606
|
continue;
|
|
2264
|
-
const collectionResult = await processCollection(store, collection, flatSchema, contentRoot, config);
|
|
2607
|
+
const collectionResult = await processCollection(store, collection, flatSchema, contentRoot, config, idIndex, entryLinkUrl);
|
|
2265
2608
|
allEntries.push(...collectionResult.entries);
|
|
2266
2609
|
for (const [filePath, content] of collectionResult.files) {
|
|
2267
2610
|
files.set(filePath, content);
|
|
@@ -2270,7 +2613,7 @@ async function generateAIContent(options) {
|
|
|
2270
2613
|
}
|
|
2271
2614
|
const rootCollection = collections.find((c) => c.logicalPath === contentRoot);
|
|
2272
2615
|
if (rootCollection?.entries) {
|
|
2273
|
-
const rootResult = await processRootEntries(store, rootCollection, contentRoot, config);
|
|
2616
|
+
const rootResult = await processRootEntries(store, rootCollection, contentRoot, config, idIndex, entryLinkUrl);
|
|
2274
2617
|
allEntries.push(...rootResult.entries);
|
|
2275
2618
|
for (const [filePath, content] of rootResult.files) {
|
|
2276
2619
|
files.set(filePath, content);
|
|
@@ -2306,7 +2649,7 @@ async function generateAIContent(options) {
|
|
|
2306
2649
|
files.set("manifest.json", JSON.stringify(manifest, null, 2));
|
|
2307
2650
|
return { manifest, files };
|
|
2308
2651
|
}
|
|
2309
|
-
async function processCollection(store, collection, flatSchema, contentRoot, config) {
|
|
2652
|
+
async function processCollection(store, collection, flatSchema, contentRoot, config, idIndex, entryLinkUrl) {
|
|
2310
2653
|
const files = /* @__PURE__ */ new Map();
|
|
2311
2654
|
const entries = [];
|
|
2312
2655
|
const cleanPath = stripContentRoot(collection.logicalPath, contentRoot);
|
|
@@ -2327,6 +2670,9 @@ async function processCollection(store, collection, flatSchema, contentRoot, con
|
|
|
2327
2670
|
resolveReferences: false
|
|
2328
2671
|
});
|
|
2329
2672
|
const aiEntry = docToAIEntry(doc, listEntry.slug, entryTypeName, entryTypeConfig, cleanPath);
|
|
2673
|
+
if (aiEntry.body && idIndex) {
|
|
2674
|
+
aiEntry.body = resolveEntryLinksInText(aiEntry.body, idIndex, contentRoot, entryLinkUrl);
|
|
2675
|
+
}
|
|
2330
2676
|
if (config?.exclude?.where?.(aiEntry))
|
|
2331
2677
|
continue;
|
|
2332
2678
|
entries.push(aiEntry);
|
|
@@ -2348,7 +2694,7 @@ async function processCollection(store, collection, flatSchema, contentRoot, con
|
|
|
2348
2694
|
for (const sub of subcollections) {
|
|
2349
2695
|
if (isCollectionExcluded(sub.logicalPath, contentRoot, config))
|
|
2350
2696
|
continue;
|
|
2351
|
-
const subResult = await processCollection(store, sub, flatSchema, contentRoot, config);
|
|
2697
|
+
const subResult = await processCollection(store, sub, flatSchema, contentRoot, config, idIndex, entryLinkUrl);
|
|
2352
2698
|
entries.push(...subResult.entries);
|
|
2353
2699
|
for (const [filePath, content] of subResult.files) {
|
|
2354
2700
|
files.set(filePath, content);
|
|
@@ -2372,7 +2718,7 @@ async function processCollection(store, collection, flatSchema, contentRoot, con
|
|
|
2372
2718
|
};
|
|
2373
2719
|
return { entries, files, manifestCollection };
|
|
2374
2720
|
}
|
|
2375
|
-
async function processRootEntries(store, rootCollection, contentRoot, config) {
|
|
2721
|
+
async function processRootEntries(store, rootCollection, contentRoot, config, idIndex, entryLinkUrl) {
|
|
2376
2722
|
const files = /* @__PURE__ */ new Map();
|
|
2377
2723
|
const entries = [];
|
|
2378
2724
|
const manifestEntries = [];
|
|
@@ -2392,6 +2738,9 @@ async function processRootEntries(store, rootCollection, contentRoot, config) {
|
|
|
2392
2738
|
resolveReferences: false
|
|
2393
2739
|
});
|
|
2394
2740
|
const aiEntry = docToAIEntry(doc, listEntry.slug, entryTypeName, entryTypeConfig, "");
|
|
2741
|
+
if (aiEntry.body && idIndex) {
|
|
2742
|
+
aiEntry.body = resolveEntryLinksInText(aiEntry.body, idIndex, contentRoot, entryLinkUrl);
|
|
2743
|
+
}
|
|
2395
2744
|
if (config?.exclude?.where?.(aiEntry))
|
|
2396
2745
|
continue;
|
|
2397
2746
|
entries.push(aiEntry);
|
|
@@ -2782,97 +3131,6 @@ import fs9 from "node:fs/promises";
|
|
|
2782
3131
|
import path10 from "node:path";
|
|
2783
3132
|
import { simpleGit as simpleGit2 } from "simple-git";
|
|
2784
3133
|
|
|
2785
|
-
// dist/utils/debug.js
|
|
2786
|
-
var LOG_LEVELS = {
|
|
2787
|
-
DEBUG: 0,
|
|
2788
|
-
INFO: 1,
|
|
2789
|
-
WARN: 2,
|
|
2790
|
-
ERROR: 3
|
|
2791
|
-
};
|
|
2792
|
-
var DebugLogger = class {
|
|
2793
|
-
constructor(options = {}) {
|
|
2794
|
-
this.timers = /* @__PURE__ */ new Map();
|
|
2795
|
-
this.options = options;
|
|
2796
|
-
}
|
|
2797
|
-
shouldLog(level) {
|
|
2798
|
-
const enabled = this.options.enabled ?? process.env.CANOPYCMS_DEBUG === "true";
|
|
2799
|
-
if (!enabled)
|
|
2800
|
-
return false;
|
|
2801
|
-
const minLevel = this.options.minLevel ?? "DEBUG";
|
|
2802
|
-
return LOG_LEVELS[level] >= LOG_LEVELS[minLevel];
|
|
2803
|
-
}
|
|
2804
|
-
formatMessage(level, category, message) {
|
|
2805
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2806
|
-
const prefix = this.options.prefix ?? "CanopyCMS";
|
|
2807
|
-
return `[${timestamp}] [${prefix}:${category}] [${level}] ${message}`;
|
|
2808
|
-
}
|
|
2809
|
-
debug(category, message, data) {
|
|
2810
|
-
if (this.shouldLog("DEBUG")) {
|
|
2811
|
-
console.log(this.formatMessage("DEBUG", category, message), data ?? "");
|
|
2812
|
-
}
|
|
2813
|
-
}
|
|
2814
|
-
info(category, message, data) {
|
|
2815
|
-
if (this.shouldLog("INFO")) {
|
|
2816
|
-
console.log(this.formatMessage("INFO", category, message), data ?? "");
|
|
2817
|
-
}
|
|
2818
|
-
}
|
|
2819
|
-
warn(category, message, data) {
|
|
2820
|
-
if (this.shouldLog("WARN")) {
|
|
2821
|
-
console.warn(this.formatMessage("WARN", category, message), data ?? "");
|
|
2822
|
-
}
|
|
2823
|
-
}
|
|
2824
|
-
error(category, message, data) {
|
|
2825
|
-
const msg = this.formatMessage("ERROR", category, message);
|
|
2826
|
-
if (this.shouldLog("ERROR")) {
|
|
2827
|
-
console.error(msg, data ?? "");
|
|
2828
|
-
}
|
|
2829
|
-
const throwOnError = this.options.throwOnError ?? false;
|
|
2830
|
-
if (throwOnError) {
|
|
2831
|
-
const errorMsg = data ? `${message}: ${JSON.stringify(data)}` : message;
|
|
2832
|
-
throw new Error(errorMsg);
|
|
2833
|
-
}
|
|
2834
|
-
}
|
|
2835
|
-
/**
|
|
2836
|
-
* Start timing an operation
|
|
2837
|
-
*/
|
|
2838
|
-
time(label) {
|
|
2839
|
-
this.timers.set(label, Date.now());
|
|
2840
|
-
}
|
|
2841
|
-
/**
|
|
2842
|
-
* End timing an operation and log the duration
|
|
2843
|
-
*/
|
|
2844
|
-
timeEnd(category, label) {
|
|
2845
|
-
const start = this.timers.get(label);
|
|
2846
|
-
if (start === void 0) {
|
|
2847
|
-
this.warn(category, `Timer '${label}' does not exist`);
|
|
2848
|
-
return;
|
|
2849
|
-
}
|
|
2850
|
-
const duration = Date.now() - start;
|
|
2851
|
-
this.timers.delete(label);
|
|
2852
|
-
this.debug(category, `${label} completed`, { durationMs: duration });
|
|
2853
|
-
return duration;
|
|
2854
|
-
}
|
|
2855
|
-
/**
|
|
2856
|
-
* Wrap an async function with automatic timing
|
|
2857
|
-
*/
|
|
2858
|
-
async timed(category, label, fn) {
|
|
2859
|
-
this.time(label);
|
|
2860
|
-
try {
|
|
2861
|
-
return await fn();
|
|
2862
|
-
} finally {
|
|
2863
|
-
this.timeEnd(category, label);
|
|
2864
|
-
}
|
|
2865
|
-
}
|
|
2866
|
-
};
|
|
2867
|
-
function createDebugLogger(options) {
|
|
2868
|
-
return new DebugLogger(options);
|
|
2869
|
-
}
|
|
2870
|
-
var testLogger = createDebugLogger({
|
|
2871
|
-
enabled: process.env.E2E_DEBUG === "true",
|
|
2872
|
-
prefix: "E2E",
|
|
2873
|
-
throwOnError: false
|
|
2874
|
-
});
|
|
2875
|
-
|
|
2876
3134
|
// dist/utils/git.js
|
|
2877
3135
|
import { simpleGit } from "simple-git";
|
|
2878
3136
|
async function detectHeadBranch(repoRoot, fallback = "main") {
|
|
@@ -2886,7 +3144,7 @@ async function detectHeadBranch(repoRoot, fallback = "main") {
|
|
|
2886
3144
|
}
|
|
2887
3145
|
|
|
2888
3146
|
// dist/git-manager.js
|
|
2889
|
-
var
|
|
3147
|
+
var log2 = createDebugLogger({ prefix: "GitManager" });
|
|
2890
3148
|
var remoteInitLocks = /* @__PURE__ */ new Map();
|
|
2891
3149
|
var GitManager = class _GitManager {
|
|
2892
3150
|
constructor(options, gitOptions) {
|
|
@@ -2897,14 +3155,14 @@ var GitManager = class _GitManager {
|
|
|
2897
3155
|
this.git.env("GIT_CEILING_DIRECTORIES", path10.dirname(this.repoPath));
|
|
2898
3156
|
}
|
|
2899
3157
|
static async cloneRepo(remoteUrl, targetPath, baseBranch = "main") {
|
|
2900
|
-
|
|
3158
|
+
log2.debug("git", "Cloning repository", {
|
|
2901
3159
|
remoteUrl,
|
|
2902
3160
|
targetPath,
|
|
2903
3161
|
baseBranch
|
|
2904
3162
|
});
|
|
2905
3163
|
const git = simpleGit2();
|
|
2906
3164
|
await git.clone(remoteUrl, targetPath, ["--branch", baseBranch, "--single-branch"]);
|
|
2907
|
-
|
|
3165
|
+
log2.debug("git", "Clone complete");
|
|
2908
3166
|
}
|
|
2909
3167
|
/**
|
|
2910
3168
|
* Initializes a local bare git repository to simulate a remote for dev mode.
|
|
@@ -2920,32 +3178,32 @@ var GitManager = class _GitManager {
|
|
|
2920
3178
|
static async ensureLocalSimulatedRemote(options) {
|
|
2921
3179
|
const existingLock = remoteInitLocks.get(options.remotePath);
|
|
2922
3180
|
if (existingLock) {
|
|
2923
|
-
|
|
3181
|
+
log2.debug("git", "Waiting for existing remote initialization", {
|
|
2924
3182
|
remotePath: options.remotePath
|
|
2925
3183
|
});
|
|
2926
3184
|
await existingLock;
|
|
2927
3185
|
try {
|
|
2928
3186
|
const stat = await fs9.stat(options.remotePath);
|
|
2929
3187
|
if (stat.isDirectory()) {
|
|
2930
|
-
|
|
3188
|
+
log2.debug("git", "Remote exists after waiting for lock");
|
|
2931
3189
|
return;
|
|
2932
3190
|
}
|
|
2933
3191
|
} catch (err) {
|
|
2934
3192
|
if (!isNotFoundError(err))
|
|
2935
3193
|
throw err;
|
|
2936
|
-
|
|
3194
|
+
log2.debug("git", "Remote does not exist after lock, will retry initialization");
|
|
2937
3195
|
}
|
|
2938
3196
|
}
|
|
2939
|
-
const lockPromise =
|
|
3197
|
+
const lockPromise = log2.timed("git", "ensureLocalSimulatedRemote", async () => {
|
|
2940
3198
|
try {
|
|
2941
|
-
|
|
3199
|
+
log2.debug("git", "Initializing local simulated remote", {
|
|
2942
3200
|
remotePath: options.remotePath,
|
|
2943
3201
|
baseBranch: options.baseBranch
|
|
2944
3202
|
});
|
|
2945
3203
|
try {
|
|
2946
3204
|
const stat = await fs9.stat(options.remotePath);
|
|
2947
3205
|
if (stat.isDirectory()) {
|
|
2948
|
-
|
|
3206
|
+
log2.debug("git", "Remote already exists, skipping");
|
|
2949
3207
|
return;
|
|
2950
3208
|
}
|
|
2951
3209
|
} catch (err) {
|
|
@@ -2968,8 +3226,8 @@ var GitManager = class _GitManager {
|
|
|
2968
3226
|
}
|
|
2969
3227
|
let hasCommits = false;
|
|
2970
3228
|
try {
|
|
2971
|
-
const
|
|
2972
|
-
hasCommits =
|
|
3229
|
+
const log4 = await sourceGit.log(["-1"]);
|
|
3230
|
+
hasCommits = log4.total > 0;
|
|
2973
3231
|
} catch {
|
|
2974
3232
|
hasCommits = false;
|
|
2975
3233
|
}
|
|
@@ -2980,7 +3238,7 @@ var GitManager = class _GitManager {
|
|
|
2980
3238
|
if (!branches.all.includes(options.baseBranch)) {
|
|
2981
3239
|
throw new Error(`Cannot initialize local simulated remote: base branch '${options.baseBranch}' does not exist locally. Please checkout '${options.baseBranch}' first or provide an explicit remoteUrl.`);
|
|
2982
3240
|
}
|
|
2983
|
-
|
|
3241
|
+
log2.debug("git", "Creating bare remote repository");
|
|
2984
3242
|
await fs9.mkdir(path10.dirname(options.remotePath), { recursive: true });
|
|
2985
3243
|
await simpleGit2().raw([
|
|
2986
3244
|
"init",
|
|
@@ -3020,7 +3278,7 @@ var GitManager = class _GitManager {
|
|
|
3020
3278
|
} catch {
|
|
3021
3279
|
}
|
|
3022
3280
|
}
|
|
3023
|
-
|
|
3281
|
+
log2.debug("git", "Remote initialization complete");
|
|
3024
3282
|
} finally {
|
|
3025
3283
|
remoteInitLocks.delete(options.remotePath);
|
|
3026
3284
|
}
|
|
@@ -3089,7 +3347,7 @@ var GitManager = class _GitManager {
|
|
|
3089
3347
|
try {
|
|
3090
3348
|
const stat = await fs9.stat(config.autoDetectRemotePath);
|
|
3091
3349
|
if (stat.isDirectory()) {
|
|
3092
|
-
|
|
3350
|
+
log2.debug("git", "Auto-detected local remote", {
|
|
3093
3351
|
path: config.autoDetectRemotePath
|
|
3094
3352
|
});
|
|
3095
3353
|
return config.autoDetectRemotePath;
|
|
@@ -3142,7 +3400,7 @@ var GitManager = class _GitManager {
|
|
|
3142
3400
|
try {
|
|
3143
3401
|
const stat = await fs9.stat(gitPath);
|
|
3144
3402
|
if (stat.isDirectory()) {
|
|
3145
|
-
|
|
3403
|
+
log2.debug("git", "Removing corrupt .git directory", {
|
|
3146
3404
|
workspacePath: options.workspacePath
|
|
3147
3405
|
});
|
|
3148
3406
|
await fs9.rm(gitPath, { recursive: true });
|
|
@@ -3180,7 +3438,7 @@ var GitManager = class _GitManager {
|
|
|
3180
3438
|
await git.git.addConfig("canopycms.managed", "true");
|
|
3181
3439
|
await git.git.addConfig("user.name", options.gitBotAuthorName);
|
|
3182
3440
|
await git.git.addConfig("user.email", options.gitBotAuthorEmail);
|
|
3183
|
-
|
|
3441
|
+
log2.debug("git", "Marked workspace as CanopyCMS-managed", {
|
|
3184
3442
|
workspacePath: options.workspacePath
|
|
3185
3443
|
});
|
|
3186
3444
|
if (!justCloned) {
|
|
@@ -3343,13 +3601,13 @@ var GitManager = class _GitManager {
|
|
|
3343
3601
|
}
|
|
3344
3602
|
const lines = content.split("\n");
|
|
3345
3603
|
if (lines.some((line) => line.trim() === pattern)) {
|
|
3346
|
-
|
|
3604
|
+
log2.debug("git", "Pattern already in .git/info/exclude", { pattern });
|
|
3347
3605
|
return;
|
|
3348
3606
|
}
|
|
3349
3607
|
const needsLeadingNewline = content.length > 0 && !content.endsWith("\n");
|
|
3350
3608
|
const newContent = content + (needsLeadingNewline ? "\n" : "") + pattern + "\n";
|
|
3351
3609
|
await fs9.writeFile(excludePath, newContent, "utf-8");
|
|
3352
|
-
|
|
3610
|
+
log2.debug("git", "Added pattern to .git/info/exclude", { pattern });
|
|
3353
3611
|
}
|
|
3354
3612
|
/**
|
|
3355
3613
|
* Create an orphan branch for settings (permissions/groups).
|
|
@@ -3363,10 +3621,10 @@ var GitManager = class _GitManager {
|
|
|
3363
3621
|
* @param initialFiles - Files to commit to the new branch (e.g., { 'permissions.json': '{}', 'groups.json': '{}' })
|
|
3364
3622
|
*/
|
|
3365
3623
|
async createOrphanSettingsBranch(branchName, initialFiles) {
|
|
3366
|
-
|
|
3624
|
+
log2.debug("git", "Creating orphan settings branch", { branchName });
|
|
3367
3625
|
const branches = await this.git.branch();
|
|
3368
3626
|
if (branches.all.includes(branchName)) {
|
|
3369
|
-
|
|
3627
|
+
log2.debug("git", "Orphan branch already exists", { branchName });
|
|
3370
3628
|
await this.git.checkout(branchName);
|
|
3371
3629
|
return;
|
|
3372
3630
|
}
|
|
@@ -3382,19 +3640,19 @@ var GitManager = class _GitManager {
|
|
|
3382
3640
|
await this.git.add(filePath);
|
|
3383
3641
|
}
|
|
3384
3642
|
await this.git.commit("Initialize settings branch", ["--allow-empty"]);
|
|
3385
|
-
|
|
3643
|
+
log2.debug("git", "Orphan settings branch created", { branchName });
|
|
3386
3644
|
}
|
|
3387
3645
|
};
|
|
3388
3646
|
|
|
3389
3647
|
// dist/branch-workspace.js
|
|
3390
|
-
var
|
|
3648
|
+
var log3 = createDebugLogger({ prefix: "BranchWorkspace" });
|
|
3391
3649
|
var workspaceInitLocks = /* @__PURE__ */ new Map();
|
|
3392
3650
|
var BranchWorkspaceManager = class {
|
|
3393
3651
|
constructor(config) {
|
|
3394
3652
|
this.config = config;
|
|
3395
3653
|
}
|
|
3396
3654
|
async ensureGitWorkspace(options) {
|
|
3397
|
-
return
|
|
3655
|
+
return log3.timed("workspace", "ensureGitWorkspace", async () => {
|
|
3398
3656
|
const existingLock = workspaceInitLocks.get(options.branchRoot);
|
|
3399
3657
|
if (existingLock) {
|
|
3400
3658
|
await existingLock;
|
|
@@ -3402,7 +3660,7 @@ var BranchWorkspaceManager = class {
|
|
|
3402
3660
|
}
|
|
3403
3661
|
const lockPromise = (async () => {
|
|
3404
3662
|
try {
|
|
3405
|
-
|
|
3663
|
+
log3.debug("workspace", "Ensuring git workspace", {
|
|
3406
3664
|
branchName: options.branchName,
|
|
3407
3665
|
mode: options.mode
|
|
3408
3666
|
});
|
|
@@ -3531,7 +3789,8 @@ async function generateAIContentFiles(options) {
|
|
|
3531
3789
|
store,
|
|
3532
3790
|
flatSchema,
|
|
3533
3791
|
contentRoot: contentRootName,
|
|
3534
|
-
config: aiConfig
|
|
3792
|
+
config: aiConfig,
|
|
3793
|
+
entryLinkUrl: config.entryLinkUrl
|
|
3535
3794
|
});
|
|
3536
3795
|
const absoluteOutputDir = path11.resolve(outputDir) + path11.sep;
|
|
3537
3796
|
let fileCount = 0;
|