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.
@@ -1223,6 +1223,9 @@ function createProject(config) {
1223
1223
  getType: getRuntime,
1224
1224
  listTypes() {
1225
1225
  return Array.from(runtimes.values());
1226
+ },
1227
+ listRoutableTypes() {
1228
+ return Array.from(runtimes.values()).filter((runtime) => isRoutableType(runtime.config));
1226
1229
  }
1227
1230
  };
1228
1231
  }
@@ -2168,11 +2171,12 @@ init_cjs_shims();
2168
2171
  function slugStrategyRules(slugStrategy, preserveTerms) {
2169
2172
  if (slugStrategy === "localized") {
2170
2173
  const rules = [
2171
- "Provide a URL slug in JSON field `slug` that is TRANSLATED into the target language.",
2174
+ "Provide a URL slug in JSON field `slug` that is Localized into the target language.",
2172
2175
  "Base the slug on the meaning of the translated title \u2014 do NOT reuse the English slug words.",
2173
2176
  "Slug MUST be ASCII only: a-z, 0-9, hyphens. No uppercase, accents, underscores, or spaces.",
2174
2177
  "For non-Latin languages, write the words in the target language and transliterate them into Latin script (e.g. Russian -> romanized Russian, not English).",
2175
- "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."
2178
+ "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.",
2179
+ '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 \\".'
2176
2180
  ];
2177
2181
  if (preserveTerms?.length) {
2178
2182
  rules.push(
@@ -2205,6 +2209,96 @@ function resolveTranslateConfig(config, type) {
2205
2209
  return mergeTranslateConfig(config.translate, type.translate, type.slugStrategy);
2206
2210
  }
2207
2211
 
2212
+ // src/translate/sanitize-mdx-jsx.ts
2213
+ init_cjs_shims();
2214
+ function sanitizeMdxJsxAttributeQuotes(body) {
2215
+ let adjusted = false;
2216
+ let out = "";
2217
+ let i = 0;
2218
+ while (i < body.length) {
2219
+ if (body[i] !== "<" || !/[\w.]/.test(body[i + 1] ?? "")) {
2220
+ out += body[i];
2221
+ i += 1;
2222
+ continue;
2223
+ }
2224
+ const tagStart = i;
2225
+ i += 1;
2226
+ while (i < body.length && /[\w.-]/.test(body[i] ?? "")) i += 1;
2227
+ const tagName = body.slice(tagStart + 1, i);
2228
+ let tagOut = `<${tagName}`;
2229
+ let tagAdjusted = false;
2230
+ while (i < body.length && body[i] !== ">" && body[i] !== "/") {
2231
+ while (i < body.length && /\s/.test(body[i] ?? "")) {
2232
+ tagOut += body[i];
2233
+ i += 1;
2234
+ }
2235
+ if (i >= body.length || body[i] === ">" || body[i] === "/") break;
2236
+ const attrStart = i;
2237
+ while (i < body.length && /[\w:.-]/.test(body[i] ?? "")) i += 1;
2238
+ body.slice(attrStart, i);
2239
+ while (i < body.length && /\s/.test(body[i] ?? "")) i += 1;
2240
+ if (body[i] !== "=") {
2241
+ tagOut += body.slice(attrStart, i);
2242
+ continue;
2243
+ }
2244
+ tagOut += body.slice(attrStart, i);
2245
+ tagOut += "=";
2246
+ i += 1;
2247
+ while (i < body.length && /\s/.test(body[i] ?? "")) i += 1;
2248
+ const quote = body[i];
2249
+ if (quote !== '"' && quote !== "'") {
2250
+ continue;
2251
+ }
2252
+ if (quote === "'") {
2253
+ const valStart2 = i + 1;
2254
+ i += 1;
2255
+ while (i < body.length) {
2256
+ if (body[i] === "\\") {
2257
+ i += 2;
2258
+ continue;
2259
+ }
2260
+ if (body[i] === "'") break;
2261
+ i += 1;
2262
+ }
2263
+ tagOut += body.slice(valStart2 - 1, i + 1);
2264
+ i += 1;
2265
+ continue;
2266
+ }
2267
+ const valStart = i + 1;
2268
+ i += 1;
2269
+ let closeIdx = -1;
2270
+ for (let scan = valStart; scan < body.length; scan += 1) {
2271
+ if (body[scan] !== '"') continue;
2272
+ let j = scan + 1;
2273
+ while (j < body.length && /\s/.test(body[j] ?? "")) j += 1;
2274
+ if (j < body.length && (body[j] === ">" || body[j] === "/" || /[a-zA-Z]/.test(body[j] ?? ""))) {
2275
+ closeIdx = scan;
2276
+ break;
2277
+ }
2278
+ }
2279
+ if (closeIdx === -1) {
2280
+ tagOut += body.slice(valStart - 1, i);
2281
+ break;
2282
+ }
2283
+ const value = body.slice(valStart, closeIdx);
2284
+ const hasInternalQuote = value.includes('"');
2285
+ if (hasInternalQuote) {
2286
+ const escaped = value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
2287
+ tagOut += `'${escaped}'`;
2288
+ tagAdjusted = true;
2289
+ } else {
2290
+ tagOut += `"${value}"`;
2291
+ }
2292
+ i = closeIdx + 1;
2293
+ }
2294
+ if (tagAdjusted) adjusted = true;
2295
+ tagOut += body[i] ?? "";
2296
+ out += tagOut;
2297
+ i += 1;
2298
+ }
2299
+ return { body: out, adjusted };
2300
+ }
2301
+
2208
2302
  // src/translate/validate-translation.ts
2209
2303
  init_cjs_shims();
2210
2304
  function formatZodIssues(error) {
@@ -2339,6 +2433,9 @@ async function translatePage(config, item, options = {}) {
2339
2433
  if (!validated.ok) {
2340
2434
  throw new Error(`Translation validation failed: ${validated.error}`);
2341
2435
  }
2436
+ const { body: translatedBody, adjusted: mdxAdjusted } = sanitizeMdxJsxAttributeQuotes(
2437
+ result.parsed.body
2438
+ );
2342
2439
  const writeDb = openStore(config, "readwrite");
2343
2440
  const snapshotId = recordEnSnapshot(
2344
2441
  config,
@@ -2357,7 +2454,7 @@ async function translatePage(config, item, options = {}) {
2357
2454
  locale: item.locale,
2358
2455
  slug,
2359
2456
  frontmatter: validated.frontmatter,
2360
- body: result.parsed.body,
2457
+ body: translatedBody,
2361
2458
  enHash: currentEnHash,
2362
2459
  translatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2363
2460
  model: result.model,
@@ -2376,7 +2473,8 @@ async function translatePage(config, item, options = {}) {
2376
2473
  usage: result.usage,
2377
2474
  estimatedCostUsd,
2378
2475
  durationMs: Date.now() - startedAt,
2379
- slugAdjusted
2476
+ slugAdjusted,
2477
+ mdxAdjusted: mdxAdjusted || void 0
2380
2478
  };
2381
2479
  } catch (error) {
2382
2480
  return {