scribe-cms 0.0.7 → 0.0.9
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 +5 -5
- package/dist/cli/index.cjs +534 -388
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +534 -388
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +745 -516
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +744 -517
- package/dist/index.js.map +1 -1
- package/dist/runtime.cjs +292 -261
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +290 -261
- package/dist/runtime.js.map +1 -1
- package/dist/src/config/resolve-config.d.ts.map +1 -1
- package/dist/src/core/builtin-fields.d.ts +8 -8
- package/dist/src/core/builtin-fields.d.ts.map +1 -1
- package/dist/src/core/types.d.ts +14 -4
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/create-project.d.ts.map +1 -1
- package/dist/src/create-scribe.d.ts.map +1 -1
- package/dist/src/export/build-static-raw-exports.d.ts.map +1 -1
- package/dist/src/i18n/build-url.d.ts +16 -3
- package/dist/src/i18n/build-url.d.ts.map +1 -1
- package/dist/src/i18n/resolve-document.d.ts +3 -2
- package/dist/src/i18n/resolve-document.d.ts.map +1 -1
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/loader/create-loader.d.ts.map +1 -1
- package/dist/src/redirects/build-json-redirects.d.ts +6 -0
- package/dist/src/redirects/build-json-redirects.d.ts.map +1 -0
- package/dist/src/redirects/build-redirects.d.ts +9 -7
- package/dist/src/redirects/build-redirects.d.ts.map +1 -1
- package/dist/src/redirects/load-type-redirects.d.ts +14 -0
- package/dist/src/redirects/load-type-redirects.d.ts.map +1 -0
- package/dist/src/redirects/redirect-schema.d.ts +31 -0
- package/dist/src/redirects/redirect-schema.d.ts.map +1 -0
- package/dist/src/runtime.d.ts +3 -0
- package/dist/src/runtime.d.ts.map +1 -1
- package/dist/src/sitemap/generate-sitemap.d.ts.map +1 -1
- package/dist/src/translate/page-translator.d.ts +1 -0
- package/dist/src/translate/page-translator.d.ts.map +1 -1
- package/dist/src/translate/resolve-translate-config.d.ts.map +1 -1
- package/dist/src/translate/sanitize-mdx-jsx.d.ts +9 -0
- package/dist/src/translate/sanitize-mdx-jsx.d.ts.map +1 -0
- package/dist/src/validate/validate-project.d.ts.map +1 -1
- package/dist/src/validate/validate-redirects.d.ts +4 -0
- package/dist/src/validate/validate-redirects.d.ts.map +1 -0
- package/dist/studio/server.cjs +90 -61
- package/dist/studio/server.cjs.map +1 -1
- package/dist/studio/server.js +90 -61
- package/dist/studio/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/core/slug-aliases.d.ts +0 -27
- package/dist/src/core/slug-aliases.d.ts.map +0 -1
- package/dist/src/redirects/translation-index.d.ts +0 -4
- package/dist/src/redirects/translation-index.d.ts.map +0 -1
package/dist/studio/server.cjs
CHANGED
|
@@ -195,65 +195,93 @@ function pathSuffix(template) {
|
|
|
195
195
|
if (idx === -1) throw new Error(`Invalid path template (missing {slug}): ${template}`);
|
|
196
196
|
return template.slice(idx + SLUG_PLACEHOLDER.length);
|
|
197
197
|
}
|
|
198
|
-
function
|
|
199
|
-
|
|
200
|
-
if (locale === defaultLocale) return relative;
|
|
201
|
-
return `/${locale}${relative}`;
|
|
198
|
+
function resolveDefaultLocaleRouting() {
|
|
199
|
+
return { strategy: "path-prefix", prefixDefaultLocale: false };
|
|
202
200
|
}
|
|
203
|
-
function
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
|
|
201
|
+
function splitPathAndSearch(pathname) {
|
|
202
|
+
const q = pathname.indexOf("?");
|
|
203
|
+
if (q === -1) return { pathname, search: "" };
|
|
204
|
+
return { pathname: pathname.slice(0, q), search: pathname.slice(q) };
|
|
205
|
+
}
|
|
206
|
+
function createUrlBuilder(config) {
|
|
207
|
+
const localeRouting = config.localeRouting ?? resolveDefaultLocaleRouting();
|
|
208
|
+
const defaultLocale = config.defaultLocale;
|
|
209
|
+
const prefixedLocales = localeRouting.strategy === "path-prefix" ? localeRouting.prefixDefaultLocale ? [...config.locales] : config.locales.filter((locale) => locale !== defaultLocale) : config.locales.filter((locale) => locale !== defaultLocale);
|
|
210
|
+
function applyLocaleToPath(pathname, locale) {
|
|
211
|
+
if (locale === defaultLocale) {
|
|
212
|
+
if (localeRouting.strategy === "path-prefix" && localeRouting.prefixDefaultLocale) {
|
|
213
|
+
return `/${defaultLocale}${pathname}`;
|
|
214
|
+
}
|
|
215
|
+
return pathname;
|
|
216
|
+
}
|
|
217
|
+
if (localeRouting.strategy === "search-param") {
|
|
218
|
+
const { pathname: base, search } = splitPathAndSearch(pathname);
|
|
219
|
+
const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
|
|
220
|
+
params.set(localeRouting.param, locale);
|
|
221
|
+
const qs = params.toString();
|
|
222
|
+
return qs ? `${base}?${qs}` : base;
|
|
223
|
+
}
|
|
224
|
+
return `/${locale}${pathname}`;
|
|
225
|
+
}
|
|
226
|
+
function resolvePath(template, slug, locale) {
|
|
227
|
+
const relative = template.replace(SLUG_PLACEHOLDER, slug);
|
|
228
|
+
return applyLocaleToPath(relative, locale);
|
|
229
|
+
}
|
|
230
|
+
function extractSlugFromResolvedPath(template, resolvedPath) {
|
|
231
|
+
let pathname = resolvedPath;
|
|
232
|
+
if (localeRouting.strategy === "search-param") {
|
|
233
|
+
pathname = splitPathAndSearch(resolvedPath).pathname;
|
|
234
|
+
} else if (localeRouting.strategy === "path-prefix") {
|
|
235
|
+
for (const locale of config.locales) {
|
|
236
|
+
if (locale === defaultLocale && !localeRouting.prefixDefaultLocale) continue;
|
|
237
|
+
const prefix2 = `/${locale}`;
|
|
238
|
+
if (pathname === prefix2 || pathname.startsWith(`${prefix2}/`)) {
|
|
239
|
+
pathname = pathname.slice(prefix2.length) || "/";
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const prefix = pathPrefix(template);
|
|
245
|
+
const suffix = pathSuffix(template);
|
|
246
|
+
if (!pathname.startsWith(prefix)) return null;
|
|
247
|
+
if (suffix && !pathname.endsWith(suffix)) return null;
|
|
248
|
+
const slugEnd = suffix ? pathname.length - suffix.length : pathname.length;
|
|
249
|
+
const slug = pathname.slice(prefix.length, slugEnd);
|
|
250
|
+
return slug.length > 0 ? slug : null;
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
defaultLocale,
|
|
254
|
+
locales: config.locales,
|
|
255
|
+
localeRouting,
|
|
256
|
+
prefixedLocales,
|
|
257
|
+
resolvePath,
|
|
258
|
+
extractSlugFromResolvedPath,
|
|
259
|
+
applyLocaleToPath
|
|
260
|
+
};
|
|
211
261
|
}
|
|
212
262
|
|
|
213
263
|
// src/core/builtin-fields.ts
|
|
214
264
|
var SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
215
|
-
|
|
265
|
+
zod.z.string().regex(SLUG_PATTERN, "slug must be lowercase-kebab-case");
|
|
216
266
|
var isoDateSchema = zod.z.string().regex(/^\d{4}-\d{2}-\d{2}(T[\d:.Z+-]*)?$/, "Use ISO date YYYY-MM-DD or full ISO 8601");
|
|
217
267
|
var canonicalPathSchema = zod.z.string().regex(/^\//, "canonicalPath must start with /");
|
|
218
|
-
|
|
268
|
+
var DEPRECATED_REDIRECT_FIELDS = [
|
|
269
|
+
[
|
|
270
|
+
"aliases",
|
|
271
|
+
"aliases frontmatter is removed \u2014 add redirects to content/<type>/_redirects.json instead"
|
|
272
|
+
],
|
|
273
|
+
[
|
|
274
|
+
"redirect_to",
|
|
275
|
+
"redirect_to frontmatter is removed \u2014 add redirects to content/<type>/_redirects.json instead"
|
|
276
|
+
]
|
|
277
|
+
];
|
|
278
|
+
function extractBuiltinEnFields(data, _pathTemplate, _enSlug, _defaultLocale) {
|
|
219
279
|
const issues = [];
|
|
220
280
|
const rest = { ...data };
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
let redirectTo;
|
|
226
|
-
if (redirectRaw !== void 0 && redirectRaw !== null && redirectRaw !== "") {
|
|
227
|
-
if (typeof redirectRaw !== "string") {
|
|
228
|
-
issues.push({
|
|
229
|
-
field: "redirect_to",
|
|
230
|
-
message: "redirect_to must be a string path",
|
|
231
|
-
level: "error"
|
|
232
|
-
});
|
|
233
|
-
} else if (!pathTemplate) {
|
|
234
|
-
issues.push({
|
|
235
|
-
field: "redirect_to",
|
|
236
|
-
message: "redirect_to is not allowed on reference-only content types",
|
|
237
|
-
level: "error"
|
|
238
|
-
});
|
|
239
|
-
} else if (!extractSlugFromResolvedPath(pathTemplate, redirectRaw)) {
|
|
240
|
-
issues.push({
|
|
241
|
-
field: "redirect_to",
|
|
242
|
-
message: `redirect_to must match path template "${pathTemplate}" (prefix "${pathPrefix(pathTemplate)}"${pathSuffix(pathTemplate) ? `, suffix "${pathSuffix(pathTemplate)}"` : ""})`,
|
|
243
|
-
level: "error"
|
|
244
|
-
});
|
|
245
|
-
} else {
|
|
246
|
-
redirectTo = redirectRaw;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
const aliases = aliasesResult.success ? aliasesResult.data : [];
|
|
250
|
-
if (!aliasesResult.success) {
|
|
251
|
-
for (const issue of aliasesResult.error.issues) {
|
|
252
|
-
issues.push({
|
|
253
|
-
field: `aliases.${issue.path.join(".")}`,
|
|
254
|
-
message: issue.message,
|
|
255
|
-
level: "error"
|
|
256
|
-
});
|
|
281
|
+
for (const [field, message] of DEPRECATED_REDIRECT_FIELDS) {
|
|
282
|
+
if (rest[field] !== void 0) {
|
|
283
|
+
issues.push({ field, message, level: "error" });
|
|
284
|
+
delete rest[field];
|
|
257
285
|
}
|
|
258
286
|
}
|
|
259
287
|
let publishedAt;
|
|
@@ -315,8 +343,6 @@ function extractBuiltinEnFields(data, pathTemplate, enSlug, defaultLocale) {
|
|
|
315
343
|
}
|
|
316
344
|
return {
|
|
317
345
|
builtin: {
|
|
318
|
-
aliases,
|
|
319
|
-
redirectTo,
|
|
320
346
|
publishedAt,
|
|
321
347
|
updatedAt,
|
|
322
348
|
noindex,
|
|
@@ -326,20 +352,24 @@ function extractBuiltinEnFields(data, pathTemplate, enSlug, defaultLocale) {
|
|
|
326
352
|
issues
|
|
327
353
|
};
|
|
328
354
|
}
|
|
329
|
-
function resolveCanonicalPathname(type, doc, defaultLocale) {
|
|
355
|
+
function resolveCanonicalPathname(type, doc, defaultLocale, localeRouting) {
|
|
356
|
+
const urlBuilder = createUrlBuilder({
|
|
357
|
+
locales: [defaultLocale, ...doc.locale !== defaultLocale ? [doc.locale] : []],
|
|
358
|
+
defaultLocale,
|
|
359
|
+
localeRouting: localeRouting ?? { strategy: "path-prefix", prefixDefaultLocale: false }
|
|
360
|
+
});
|
|
330
361
|
if (doc.canonicalPathOverride) {
|
|
331
|
-
|
|
332
|
-
return `/${doc.locale}${doc.canonicalPathOverride}`;
|
|
362
|
+
return urlBuilder.applyLocaleToPath(doc.canonicalPathOverride, doc.locale);
|
|
333
363
|
}
|
|
334
364
|
if (!type.path) return `/${doc.slug}`;
|
|
335
|
-
return resolvePath(type.path, doc.slug, doc.locale
|
|
365
|
+
return urlBuilder.resolvePath(type.path, doc.slug, doc.locale);
|
|
336
366
|
}
|
|
337
|
-
function mergeBuiltinsIntoFrontmatter(frontmatter, doc, type, defaultLocale) {
|
|
367
|
+
function mergeBuiltinsIntoFrontmatter(frontmatter, doc, type, defaultLocale, localeRouting) {
|
|
338
368
|
const out = { ...frontmatter };
|
|
339
369
|
if (doc.publishedAt !== void 0) out.publishedAt = doc.publishedAt;
|
|
340
370
|
if (doc.updatedAt !== void 0) out.updatedAt = doc.updatedAt;
|
|
341
371
|
out.noindex = doc.noindex;
|
|
342
|
-
out.canonicalPath = resolveCanonicalPathname(type, doc, defaultLocale);
|
|
372
|
+
out.canonicalPath = resolveCanonicalPathname(type, doc, defaultLocale, localeRouting);
|
|
343
373
|
return out;
|
|
344
374
|
}
|
|
345
375
|
var SCHEMA_VERSION = 4;
|
|
@@ -512,7 +542,8 @@ function parseEnMdx(filePath, config, type) {
|
|
|
512
542
|
locale: config.defaultLocale
|
|
513
543
|
},
|
|
514
544
|
type,
|
|
515
|
-
config.defaultLocale
|
|
545
|
+
config.defaultLocale,
|
|
546
|
+
config.localeRouting
|
|
516
547
|
);
|
|
517
548
|
const crossIssues = type.crossValidate?.(result.data, {
|
|
518
549
|
locale: config.defaultLocale,
|
|
@@ -526,8 +557,6 @@ function parseEnMdx(filePath, config, type) {
|
|
|
526
557
|
slug,
|
|
527
558
|
enSlug: slug,
|
|
528
559
|
locale: config.defaultLocale,
|
|
529
|
-
aliases: builtin.aliases,
|
|
530
|
-
redirectTo: builtin.redirectTo,
|
|
531
560
|
publishedAt: builtin.publishedAt,
|
|
532
561
|
updatedAt: builtin.updatedAt,
|
|
533
562
|
noindex: builtin.noindex,
|