@farming-labs/svelte 0.1.125 → 0.1.126
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/markdown.js +81 -5
- package/package.json +2 -2
package/dist/markdown.js
CHANGED
|
@@ -348,20 +348,60 @@ function highlightCode(hl, code, lang) {
|
|
|
348
348
|
}
|
|
349
349
|
}
|
|
350
350
|
function parseMeta(meta) {
|
|
351
|
-
const
|
|
352
|
-
const
|
|
351
|
+
const trimmed = meta.trim();
|
|
352
|
+
const lang = (trimmed.split(/\s/)[0] || "text").toLowerCase();
|
|
353
|
+
const titleMatch = trimmed.match(/\b(?:title|filename|file|name|label)=["']([^"']+)["']/);
|
|
353
354
|
return { lang, title: titleMatch ? titleMatch[1] : null };
|
|
354
355
|
}
|
|
356
|
+
const ignoredCodeGroupBareTitleTokens = new Set([
|
|
357
|
+
"copy",
|
|
358
|
+
"no-copy",
|
|
359
|
+
"nocopy",
|
|
360
|
+
"line-numbers",
|
|
361
|
+
"linenumbers",
|
|
362
|
+
"runnable",
|
|
363
|
+
"show-line-numbers",
|
|
364
|
+
"showlinenumbers",
|
|
365
|
+
"wrap",
|
|
366
|
+
]);
|
|
367
|
+
function parseCodeGroupMeta(meta) {
|
|
368
|
+
const parsed = parseMeta(meta);
|
|
369
|
+
if (parsed.title)
|
|
370
|
+
return parsed;
|
|
371
|
+
const trimmed = meta.trim();
|
|
372
|
+
const language = trimmed.split(/\s+/, 1)[0] ?? "";
|
|
373
|
+
const bareTitle = trimmed
|
|
374
|
+
.slice(language.length)
|
|
375
|
+
.trim()
|
|
376
|
+
.replace(/\{[^}]*\}/g, " ")
|
|
377
|
+
.split(/\s+/)
|
|
378
|
+
.find((part) => part && !part.includes("=") && !ignoredCodeGroupBareTitleTokens.has(part.toLowerCase()));
|
|
379
|
+
return {
|
|
380
|
+
...parsed,
|
|
381
|
+
title: bareTitle ? bareTitle.replace(/^["']|["']$/g, "") : null,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function createCodeGroupTabValue(label, used) {
|
|
385
|
+
const slug = slugify(label) || `code-${used.size + 1}`;
|
|
386
|
+
let value = slug;
|
|
387
|
+
let suffix = 2;
|
|
388
|
+
while (used.has(value)) {
|
|
389
|
+
value = `${slug}-${suffix}`;
|
|
390
|
+
suffix += 1;
|
|
391
|
+
}
|
|
392
|
+
used.add(value);
|
|
393
|
+
return value;
|
|
394
|
+
}
|
|
355
395
|
function wrapCodeWithCopy(html, rawCode, title, language) {
|
|
356
396
|
const escapedRaw = rawCode
|
|
357
397
|
.replace(/&/g, "&")
|
|
358
398
|
.replace(/"/g, """)
|
|
359
399
|
.replace(/</g, "<")
|
|
360
400
|
.replace(/>/g, ">");
|
|
361
|
-
const dataLang = language ? ` data-language="${String(language)
|
|
401
|
+
const dataLang = language ? ` data-language="${escapeHtml(String(language))}"` : "";
|
|
362
402
|
const copyBtn = `<button class="fd-copy-btn" data-code="${escapedRaw}" title="Copy code"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg></button>`;
|
|
363
403
|
if (title) {
|
|
364
|
-
return `<div class="fd-codeblock fd-codeblock--titled"${dataLang}><div class="fd-codeblock-title"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg><span class="fd-codeblock-title-text">${title}</span>${copyBtn}</div><div class="fd-codeblock-content">${html}</div></div>`;
|
|
404
|
+
return `<div class="fd-codeblock fd-codeblock--titled"${dataLang}><div class="fd-codeblock-title"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg><span class="fd-codeblock-title-text">${escapeHtml(title)}</span>${copyBtn}</div><div class="fd-codeblock-content">${html}</div></div>`;
|
|
365
405
|
}
|
|
366
406
|
return `<div class="fd-codeblock"${dataLang}>${copyBtn}<div class="fd-codeblock-content">${html}</div></div>`;
|
|
367
407
|
}
|
|
@@ -389,8 +429,44 @@ export async function renderMarkdown(content, options = {}) {
|
|
|
389
429
|
return "";
|
|
390
430
|
const hl = await getHighlighter();
|
|
391
431
|
let result = resolveDocsAgentMdxContent(content, "human");
|
|
392
|
-
// ──
|
|
432
|
+
// ── Mintlify-style code groups: <CodeGroup> fenced code blocks </CodeGroup> ──
|
|
393
433
|
const tabsBlocks = [];
|
|
434
|
+
result = result.replace(/<CodeGroup(?:\s+([^>]*?))?>([\s\S]*?)<\/CodeGroup>/g, (_, attrSource, body) => {
|
|
435
|
+
const attrs = parseJsxAttributes(attrSource ?? "");
|
|
436
|
+
const dropdown = toBoolean(attrs.dropdown, false);
|
|
437
|
+
const usedValues = new Set();
|
|
438
|
+
const panels = [];
|
|
439
|
+
const codeRegex = /```([^\n]*)\n([\s\S]*?)```/g;
|
|
440
|
+
let codeMatch;
|
|
441
|
+
while ((codeMatch = codeRegex.exec(body)) !== null) {
|
|
442
|
+
const { lang, title } = parseCodeGroupMeta(codeMatch[1]);
|
|
443
|
+
const label = title || lang || `Code ${panels.length + 1}`;
|
|
444
|
+
const value = createCodeGroupTabValue(label, usedValues);
|
|
445
|
+
const dedented = dedentCode(codeMatch[2]);
|
|
446
|
+
const { html, raw } = highlightCode(hl, dedented, lang);
|
|
447
|
+
panels.push({
|
|
448
|
+
label,
|
|
449
|
+
value,
|
|
450
|
+
html: wrapCodeWithCopy(html, raw, null, lang),
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
if (panels.length === 0)
|
|
454
|
+
return body;
|
|
455
|
+
let tabsHtml = `<div class="fd-tabs" data-tabs data-code-group${dropdown ? ' data-dropdown="true"' : ""}>`;
|
|
456
|
+
tabsHtml += `<div class="fd-tabs-list" role="tablist">`;
|
|
457
|
+
for (let i = 0; i < panels.length; i++) {
|
|
458
|
+
tabsHtml += `<button role="tab" class="fd-tab-trigger${i === 0 ? " fd-tab-active" : ""}" data-tab-value="${escapeHtml(panels[i].value)}" aria-selected="${i === 0}">${escapeHtml(panels[i].label)}</button>`;
|
|
459
|
+
}
|
|
460
|
+
tabsHtml += `</div>`;
|
|
461
|
+
for (let i = 0; i < panels.length; i++) {
|
|
462
|
+
tabsHtml += `<div class="fd-tab-panel${i === 0 ? " fd-tab-panel-active" : ""}" data-tab-panel="${escapeHtml(panels[i].value)}" role="tabpanel">${panels[i].html}</div>`;
|
|
463
|
+
}
|
|
464
|
+
tabsHtml += `</div>`;
|
|
465
|
+
const placeholder = `%%TABS_${tabsBlocks.length}%%`;
|
|
466
|
+
tabsBlocks.push(tabsHtml);
|
|
467
|
+
return placeholder;
|
|
468
|
+
});
|
|
469
|
+
// ── Tabs blocks: <Tabs items={[...]}> ... </Tabs> ──
|
|
394
470
|
result = result.replace(/<Tabs\s+items=\{?\[([^\]]+)\]\}?>([\s\S]*?)<\/Tabs>/g, (_, itemsStr, body) => {
|
|
395
471
|
const items = itemsStr.split(",").map((s) => s.trim().replace(/^["']|["']$/g, ""));
|
|
396
472
|
const panels = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/svelte",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.126",
|
|
4
4
|
"description": "SvelteKit adapter for @farming-labs/docs — content loading and navigation utilities",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/node": "^22.10.0",
|
|
58
58
|
"typescript": "^5.9.3",
|
|
59
|
-
"@farming-labs/docs": "0.1.
|
|
59
|
+
"@farming-labs/docs": "0.1.126"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"@farming-labs/docs": "*"
|