scribe-cms 0.0.7 → 0.0.8

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/cli/index.js CHANGED
@@ -1208,6 +1208,9 @@ function createProject(config) {
1208
1208
  getType: getRuntime,
1209
1209
  listTypes() {
1210
1210
  return Array.from(runtimes.values());
1211
+ },
1212
+ listRoutableTypes() {
1213
+ return Array.from(runtimes.values()).filter((runtime) => isRoutableType(runtime.config));
1211
1214
  }
1212
1215
  };
1213
1216
  }
@@ -2153,11 +2156,12 @@ init_esm_shims();
2153
2156
  function slugStrategyRules(slugStrategy, preserveTerms) {
2154
2157
  if (slugStrategy === "localized") {
2155
2158
  const rules = [
2156
- "Provide a URL slug in JSON field `slug` that is TRANSLATED into the target language.",
2159
+ "Provide a URL slug in JSON field `slug` that is Localized into the target language.",
2157
2160
  "Base the slug on the meaning of the translated title \u2014 do NOT reuse the English slug words.",
2158
2161
  "Slug MUST be ASCII only: a-z, 0-9, hyphens. No uppercase, accents, underscores, or spaces.",
2159
2162
  "For non-Latin languages, write the words in the target language and transliterate them into Latin script (e.g. Russian -> romanized Russian, not English).",
2160
- "Do NOT append locale codes to the slug (e.g. -fr, -he, -zh-cn). Locale routing is handled by the URL prefix, not the slug."
2163
+ "Do NOT append locale codes to the slug (e.g. -fr, -he, -zh-cn). Locale routing is handled by the URL prefix, not the slug.",
2164
+ 'In JSX attributes (e.g. FaqItem question="..."), use single quotes when the value contains double-quote characters (e.g. Hebrew \u05D3\u05D5\u05D0"\u05DC), or escape them as \\".'
2161
2165
  ];
2162
2166
  if (preserveTerms?.length) {
2163
2167
  rules.push(
@@ -2190,6 +2194,96 @@ function resolveTranslateConfig(config, type) {
2190
2194
  return mergeTranslateConfig(config.translate, type.translate, type.slugStrategy);
2191
2195
  }
2192
2196
 
2197
+ // src/translate/sanitize-mdx-jsx.ts
2198
+ init_esm_shims();
2199
+ function sanitizeMdxJsxAttributeQuotes(body) {
2200
+ let adjusted = false;
2201
+ let out = "";
2202
+ let i = 0;
2203
+ while (i < body.length) {
2204
+ if (body[i] !== "<" || !/[\w.]/.test(body[i + 1] ?? "")) {
2205
+ out += body[i];
2206
+ i += 1;
2207
+ continue;
2208
+ }
2209
+ const tagStart = i;
2210
+ i += 1;
2211
+ while (i < body.length && /[\w.-]/.test(body[i] ?? "")) i += 1;
2212
+ const tagName = body.slice(tagStart + 1, i);
2213
+ let tagOut = `<${tagName}`;
2214
+ let tagAdjusted = false;
2215
+ while (i < body.length && body[i] !== ">" && body[i] !== "/") {
2216
+ while (i < body.length && /\s/.test(body[i] ?? "")) {
2217
+ tagOut += body[i];
2218
+ i += 1;
2219
+ }
2220
+ if (i >= body.length || body[i] === ">" || body[i] === "/") break;
2221
+ const attrStart = i;
2222
+ while (i < body.length && /[\w:.-]/.test(body[i] ?? "")) i += 1;
2223
+ body.slice(attrStart, i);
2224
+ while (i < body.length && /\s/.test(body[i] ?? "")) i += 1;
2225
+ if (body[i] !== "=") {
2226
+ tagOut += body.slice(attrStart, i);
2227
+ continue;
2228
+ }
2229
+ tagOut += body.slice(attrStart, i);
2230
+ tagOut += "=";
2231
+ i += 1;
2232
+ while (i < body.length && /\s/.test(body[i] ?? "")) i += 1;
2233
+ const quote = body[i];
2234
+ if (quote !== '"' && quote !== "'") {
2235
+ continue;
2236
+ }
2237
+ if (quote === "'") {
2238
+ const valStart2 = i + 1;
2239
+ i += 1;
2240
+ while (i < body.length) {
2241
+ if (body[i] === "\\") {
2242
+ i += 2;
2243
+ continue;
2244
+ }
2245
+ if (body[i] === "'") break;
2246
+ i += 1;
2247
+ }
2248
+ tagOut += body.slice(valStart2 - 1, i + 1);
2249
+ i += 1;
2250
+ continue;
2251
+ }
2252
+ const valStart = i + 1;
2253
+ i += 1;
2254
+ let closeIdx = -1;
2255
+ for (let scan = valStart; scan < body.length; scan += 1) {
2256
+ if (body[scan] !== '"') continue;
2257
+ let j = scan + 1;
2258
+ while (j < body.length && /\s/.test(body[j] ?? "")) j += 1;
2259
+ if (j < body.length && (body[j] === ">" || body[j] === "/" || /[a-zA-Z]/.test(body[j] ?? ""))) {
2260
+ closeIdx = scan;
2261
+ break;
2262
+ }
2263
+ }
2264
+ if (closeIdx === -1) {
2265
+ tagOut += body.slice(valStart - 1, i);
2266
+ break;
2267
+ }
2268
+ const value = body.slice(valStart, closeIdx);
2269
+ const hasInternalQuote = value.includes('"');
2270
+ if (hasInternalQuote) {
2271
+ const escaped = value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
2272
+ tagOut += `'${escaped}'`;
2273
+ tagAdjusted = true;
2274
+ } else {
2275
+ tagOut += `"${value}"`;
2276
+ }
2277
+ i = closeIdx + 1;
2278
+ }
2279
+ if (tagAdjusted) adjusted = true;
2280
+ tagOut += body[i] ?? "";
2281
+ out += tagOut;
2282
+ i += 1;
2283
+ }
2284
+ return { body: out, adjusted };
2285
+ }
2286
+
2193
2287
  // src/translate/validate-translation.ts
2194
2288
  init_esm_shims();
2195
2289
  function formatZodIssues(error) {
@@ -2324,6 +2418,9 @@ async function translatePage(config, item, options = {}) {
2324
2418
  if (!validated.ok) {
2325
2419
  throw new Error(`Translation validation failed: ${validated.error}`);
2326
2420
  }
2421
+ const { body: translatedBody, adjusted: mdxAdjusted } = sanitizeMdxJsxAttributeQuotes(
2422
+ result.parsed.body
2423
+ );
2327
2424
  const writeDb = openStore(config, "readwrite");
2328
2425
  const snapshotId = recordEnSnapshot(
2329
2426
  config,
@@ -2342,7 +2439,7 @@ async function translatePage(config, item, options = {}) {
2342
2439
  locale: item.locale,
2343
2440
  slug,
2344
2441
  frontmatter: validated.frontmatter,
2345
- body: result.parsed.body,
2442
+ body: translatedBody,
2346
2443
  enHash: currentEnHash,
2347
2444
  translatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2348
2445
  model: result.model,
@@ -2361,7 +2458,8 @@ async function translatePage(config, item, options = {}) {
2361
2458
  usage: result.usage,
2362
2459
  estimatedCostUsd,
2363
2460
  durationMs: Date.now() - startedAt,
2364
- slugAdjusted
2461
+ slugAdjusted,
2462
+ mdxAdjusted: mdxAdjusted || void 0
2365
2463
  };
2366
2464
  } catch (error) {
2367
2465
  return {