sourcey 3.4.3 → 3.4.4

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.
@@ -61,7 +61,7 @@ function ContentFooter() {
61
61
  editUrl = `${repoBase}/edit/${site.editBranch}/${basePath}${page.markdown.sourcePath}`;
62
62
  }
63
63
  const linkStyle = "hover:text-[rgb(var(--color-gray-600))] dark:hover:text-[rgb(var(--color-gray-300))] transition-colors";
64
- return (_jsxs("div", { class: "mt-16 mb-8 flex items-center justify-between border-t border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-gray-800)/0.5)] pt-6 text-xs text-[rgb(var(--color-gray-500))] dark:text-[rgb(var(--color-gray-400))]", children: [_jsxs("a", { href: "https://sourcey.com", target: "_blank", rel: "noopener noreferrer", class: `flex items-center gap-1.5 ${linkStyle}`, children: ["Built with", _jsx("span", { class: "font-medium text-[rgb(var(--color-gray-700))] dark:text-[rgb(var(--color-gray-300))]", children: "Sourcey" })] }), _jsxs("div", { class: "flex items-center gap-4", children: [editUrl && (_jsxs("a", { href: editUrl, target: "_blank", rel: "noopener noreferrer", class: `${linkStyle} flex items-center gap-1`, children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", "stroke-width": "1.5", stroke: "currentColor", class: "w-3 h-3 mr-0.5", children: _jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" }) }), "Edit this page"] })), links.map((link) => (_jsx("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", "aria-label": link.label ?? socialLabels[link.type] ?? link.href, class: linkStyle, children: link.type === "link"
64
+ return (_jsxs("div", { class: "mt-16 mb-8 flex items-center justify-between border-t border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-gray-800)/0.5)] pt-6 text-xs text-[rgb(var(--color-gray-500))] dark:text-[rgb(var(--color-gray-400))]", children: [_jsxs("a", { href: "https://sourcey.com", target: "_blank", rel: "noopener noreferrer", class: `flex items-center gap-1.5 ${linkStyle}`, children: ["Built with", _jsx("img", { src: "https://sourcey.com/sourcey-logo.png", alt: "Sourcey", class: "h-4 w-4" })] }), _jsxs("div", { class: "flex items-center gap-4", children: [editUrl && (_jsxs("a", { href: editUrl, target: "_blank", rel: "noopener noreferrer", class: `${linkStyle} flex items-center gap-1`, children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", "stroke-width": "1.5", stroke: "currentColor", class: "w-3 h-3 mr-0.5", children: _jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" }) }), "Edit this page"] })), links.map((link) => (_jsx("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", "aria-label": link.label ?? socialLabels[link.type] ?? link.href, class: linkStyle, children: link.type === "link"
65
65
  ? (link.label ?? link.href)
66
66
  : (_jsxs(_Fragment, { children: [_jsx(SocialIcon, { type: link.type }), link.label && _jsx("span", { class: "ml-1", children: link.label })] })) }, link.href)))] })] }));
67
67
  }
@@ -9,5 +9,5 @@ import { Markdown } from "../ui/Markdown.js";
9
9
  export function Introduction() {
10
10
  const spec = useContext(SpecContext);
11
11
  const { info, servers } = spec;
12
- return (_jsxs("div", { id: "introduction", "data-traverse-target": "introduction", class: "mb-8", children: [info.description && (_jsx(Markdown, { content: info.description, class: "max-w-none" })), info.termsOfService && (_jsx("p", { class: "mt-4 text-sm text-[rgb(var(--color-gray-500))]", children: _jsx("a", { href: info.termsOfService, class: "text-[rgb(var(--color-primary-ink))] dark:text-[rgb(var(--color-primary-light))]", children: "Terms of Service" }) })), info.contact?.email && (_jsxs("p", { class: "mt-2 text-sm text-[rgb(var(--color-gray-500))]", children: ["Contact: ", _jsx("a", { href: `mailto:${info.contact.email}`, class: "text-[rgb(var(--color-primary-ink))] dark:text-[rgb(var(--color-primary-light))]", children: info.contact.email })] })), servers.length > 0 && (_jsxs("div", { class: "mt-6 rounded-[var(--radius)] border border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-border-dark-subtle)/0.1)] overflow-x-auto", children: [_jsxs("div", { class: "px-4 py-2.5 text-xs font-semibold text-[rgb(var(--color-gray-600))] dark:text-[rgb(var(--color-gray-300))] border-b border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-border-dark-subtle)/0.1)]", children: ["Base URL", servers.length > 1 ? "s" : ""] }), servers.map((s, i) => (_jsxs("div", { class: `flex items-baseline gap-3 px-4 py-2 ${i > 0 ? "border-t border-[rgb(var(--color-gray-100))] dark:border-[rgb(var(--color-gray-800))]" : ""}`, children: [_jsx("code", { class: "font-mono text-sm text-[rgb(var(--color-gray-800))] dark:text-[rgb(var(--color-gray-200))]", children: s.url }), s.description && (_jsx("span", { class: "text-xs text-[rgb(var(--color-gray-500))]", children: s.description }))] }, i)))] }))] }));
12
+ return (_jsxs("div", { id: "introduction", "data-traverse-target": "introduction", class: "mb-8", children: [info.termsOfService && (_jsx("p", { class: "mt-4 text-sm text-[rgb(var(--color-gray-500))]", children: _jsx("a", { href: info.termsOfService, class: "text-[rgb(var(--color-primary-ink))] dark:text-[rgb(var(--color-primary-light))]", children: "Terms of Service" }) })), info.contact?.email && (_jsxs("p", { class: "mt-2 text-sm text-[rgb(var(--color-gray-500))]", children: ["Contact: ", _jsx("a", { href: `mailto:${info.contact.email}`, class: "text-[rgb(var(--color-primary-ink))] dark:text-[rgb(var(--color-primary-light))]", children: info.contact.email })] })), servers.length > 0 && (_jsxs("div", { class: "mt-6 rounded-[var(--radius)] border border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-border-dark-subtle)/0.1)] overflow-x-auto", children: [_jsxs("div", { class: "px-4 py-2.5 text-xs font-semibold text-[rgb(var(--color-gray-600))] dark:text-[rgb(var(--color-gray-300))] border-b border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-border-dark-subtle)/0.1)]", children: ["Base URL", servers.length > 1 ? "s" : ""] }), servers.map((s, i) => (_jsxs("div", { class: `flex items-baseline gap-3 px-4 py-2 ${i > 0 ? "border-t border-[rgb(var(--color-gray-100))] dark:border-[rgb(var(--color-gray-800))]" : ""}`, children: [_jsx("code", { class: "font-mono text-sm text-[rgb(var(--color-gray-800))] dark:text-[rgb(var(--color-gray-200))]", children: s.url }), s.description && (_jsx("span", { class: "text-xs text-[rgb(var(--color-gray-500))]", children: s.description }))] }, i)))] })), info.description && (_jsx(Markdown, { content: info.description, class: "max-w-none mt-8" }))] }));
13
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Security.d.ts","sourceRoot":"","sources":["../../../src/components/openapi/Security.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAI/D,UAAU,aAAa;IACrB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE,aAAa,uCA8CvD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,wCAkElC"}
1
+ {"version":3,"file":"Security.d.ts","sourceRoot":"","sources":["../../../src/components/openapi/Security.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAI/D,UAAU,aAAa;IACrB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE,aAAa,uCA8CvD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,wCA+ElC"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "preact/jsx-runtime";
2
2
  import { useContext } from "preact/hooks";
3
3
  import { SpecContext } from "../../renderer/context.js";
4
4
  import { SectionLabel } from "../ui/SectionLabel.js";
@@ -26,7 +26,5 @@ export function SecurityDefinitions() {
26
26
  const schemes = Object.entries(spec.securitySchemes);
27
27
  if (!schemes.length)
28
28
  return null;
29
- return (_jsxs("div", { id: "authentication", class: "py-8 border-t border-[rgb(var(--color-gray-100))] dark:border-[rgb(var(--color-gray-800))]", "data-traverse-target": "authentication", children: [_jsx("h2", { class: "text-xl font-bold text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))] mb-4", children: "Authentication" }), _jsx("div", { class: "params-list", children: schemes.map(([name, scheme]) => (_jsxs("div", { class: "param-item", children: [_jsxs("div", { class: "param-header", children: [_jsx("code", { class: "param-name", children: name }), _jsx("span", { class: "param-type", children: _jsx("span", { class: "json-property-type", children: scheme.type }) })] }), _jsxs("div", { class: "param-description", children: [scheme.description && _jsx(Markdown, { content: scheme.description }), scheme.type === "apiKey" && (_jsxs("p", { class: "mt-1", children: ["API Key: ", _jsx("code", { class: "text-xs font-medium", children: scheme.name }), " in ", scheme.in] })), scheme.type === "http" && (_jsxs("p", { class: "mt-1", children: ["Scheme: ", scheme.scheme, scheme.bearerFormat && ` (${scheme.bearerFormat})`] })), scheme.type === "oauth2" && scheme.flows && (_jsx("div", { class: "mt-2 space-y-2", children: Object.entries(scheme.flows).map(([flowType, flow]) => (_jsxs("div", { children: [_jsx("strong", { class: "text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))]", children: flowType }), flow?.authorizationUrl && (_jsxs("p", { class: "mt-1", children: ["Authorization: ", _jsx("code", { class: "text-xs", children: flow.authorizationUrl })] })), flow?.tokenUrl && (_jsxs("p", { class: "mt-1", children: ["Token: ", _jsx("code", { class: "text-xs", children: flow.tokenUrl })] })), flow?.scopes && Object.keys(flow.scopes).length > 0 && (_jsxs("p", { class: "mt-1", children: ["Scopes:", " ", Object.entries(flow.scopes)
30
- .map(([s, desc]) => `${s} — ${desc}`)
31
- .join(", ")] }))] }, flowType))) })), scheme.type === "openIdConnect" && scheme.openIdConnectUrl && (_jsxs("p", { class: "mt-1", children: ["OpenID Connect:", " ", _jsx("a", { href: scheme.openIdConnectUrl, class: "text-[rgb(var(--color-primary-ink))] dark:text-[rgb(var(--color-primary-light))]", children: scheme.openIdConnectUrl })] }))] })] }, name))) })] }));
29
+ return (_jsxs("div", { id: "authentication", class: "py-8 border-t border-[rgb(var(--color-gray-100))] dark:border-[rgb(var(--color-gray-800))]", "data-traverse-target": "authentication", children: [_jsx("h2", { class: "text-xl font-bold text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))] mb-4", children: "Authentication" }), _jsx("div", { class: "params-list", children: schemes.map(([name, scheme]) => (_jsxs("div", { class: "param-item", children: [_jsxs("div", { class: "param-header", children: [_jsx("code", { class: "param-name", children: name }), _jsx("span", { class: "param-type", children: _jsx("span", { class: "json-property-type", children: scheme.type }) })] }), _jsxs("div", { class: "param-description", children: [scheme.description && _jsx(Markdown, { content: scheme.description }), scheme.type === "apiKey" && (_jsxs("p", { class: "mt-1", children: ["API Key: ", _jsx("code", { class: "text-xs font-medium", children: scheme.name }), " in ", scheme.in] })), scheme.type === "http" && (_jsxs("p", { class: "mt-1", children: ["Scheme: ", scheme.scheme, scheme.bearerFormat && ` (${scheme.bearerFormat})`] })), scheme.type === "oauth2" && scheme.flows && (_jsx("div", { class: "mt-2 space-y-4", children: Object.entries(scheme.flows).map(([flowType, flow]) => (_jsxs("div", { children: [_jsx("strong", { class: "text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))]", children: flowType }), _jsxs("dl", { class: "mt-2 text-sm", children: [flow?.authorizationUrl && (_jsxs(_Fragment, { children: [_jsx("dt", { class: "text-[rgb(var(--color-gray-500))] mt-2", children: "Authorization URL" }), _jsx("dd", { children: _jsx("code", { class: "text-xs", children: flow.authorizationUrl }) })] })), flow?.tokenUrl && (_jsxs(_Fragment, { children: [_jsx("dt", { class: "text-[rgb(var(--color-gray-500))] mt-2", children: "Token URL" }), _jsx("dd", { children: _jsx("code", { class: "text-xs", children: flow.tokenUrl }) })] }))] }), flow?.scopes && Object.keys(flow.scopes).length > 0 && (_jsxs("div", { class: "mt-3", children: [_jsx("span", { class: "text-sm text-[rgb(var(--color-gray-500))]", children: "Scopes" }), _jsx("ul", { class: "mt-1 space-y-1", children: Object.entries(flow.scopes).map(([s, desc]) => (_jsxs("li", { class: "text-sm", children: [_jsx("code", { class: "text-xs font-medium text-[rgb(var(--color-gray-800))] dark:text-[rgb(var(--color-gray-200))]", children: s }), _jsxs("span", { class: "text-[rgb(var(--color-gray-500))] ml-2", children: ["\u2014 ", desc] })] }, s))) })] }))] }, flowType))) })), scheme.type === "openIdConnect" && scheme.openIdConnectUrl && (_jsxs("p", { class: "mt-1", children: ["OpenID Connect:", " ", _jsx("a", { href: scheme.openIdConnectUrl, class: "text-[rgb(var(--color-primary-ink))] dark:text-[rgb(var(--color-primary-light))]", children: scheme.openIdConnectUrl })] }))] })] }, name))) })] }));
32
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-loader.d.ts","sourceRoot":"","sources":["../../src/core/markdown-loader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmC,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMzF,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAwXxD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,CAmBvB;AAUD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIrD"}
1
+ {"version":3,"file":"markdown-loader.d.ts","sourceRoot":"","sources":["../../src/core/markdown-loader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmC,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMzF,MAAM,WAAW,YAAY;IAC3B,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAmcxD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,CAAC,CAmBvB;AAUD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIrD"}
@@ -16,6 +16,47 @@ function parseFrontmatter(raw) {
16
16
  const meta = parseYaml(match[1]) ?? {};
17
17
  return { meta, body: match[2] };
18
18
  }
19
+ const FENCED_BLOCK_TOKEN = "@@SOURCEY_FENCED_BLOCK_";
20
+ function protectFencedCodeBlocks(input) {
21
+ const blocks = [];
22
+ const output = [];
23
+ const lines = input.split("\n");
24
+ let fence = null;
25
+ let buffer = [];
26
+ const pushProtectedBlock = () => {
27
+ const index = blocks.push(buffer.join("\n")) - 1;
28
+ output.push(`${FENCED_BLOCK_TOKEN}${index}@@`);
29
+ buffer = [];
30
+ };
31
+ for (const line of lines) {
32
+ const stripped = line.replace(/^ {1,3}/, "");
33
+ const fenceMatch = stripped.match(/^(`{3,}|~{3,})(.*)$/);
34
+ if (!fence) {
35
+ if (!fenceMatch) {
36
+ output.push(line);
37
+ continue;
38
+ }
39
+ fence = { char: fenceMatch[1][0], length: fenceMatch[1].length };
40
+ buffer.push(line);
41
+ continue;
42
+ }
43
+ buffer.push(line);
44
+ if (fenceMatch &&
45
+ fenceMatch[1][0] === fence.char &&
46
+ fenceMatch[1].length >= fence.length &&
47
+ !fenceMatch[2].trim()) {
48
+ pushProtectedBlock();
49
+ fence = null;
50
+ }
51
+ }
52
+ if (buffer.length > 0) {
53
+ output.push(...buffer);
54
+ }
55
+ return { text: output.join("\n"), blocks };
56
+ }
57
+ function restoreFencedCodeBlocks(input, blocks) {
58
+ return blocks.reduce((text, block, index) => text.replaceAll(`${FENCED_BLOCK_TOKEN}${index}@@`, block), input);
59
+ }
19
60
  // ---------------------------------------------------------------------------
20
61
  // Component preprocessor: transforms MDX-style JSX components into HTML
21
62
  // ---------------------------------------------------------------------------
@@ -24,7 +65,8 @@ function parseFrontmatter(raw) {
24
65
  * a single rendering path in preprocessDirectives.
25
66
  */
26
67
  function preprocessComponents(body) {
27
- let html = body;
68
+ const { text, blocks } = protectFencedCodeBlocks(body);
69
+ let html = text;
28
70
  // <Steps> <Step title="...">content</Step> ... </Steps> → :::steps numbered list
29
71
  html = html.replace(/<Steps>\s*([\s\S]*?)\s*<\/Steps>/g, (_m, inner) => {
30
72
  const steps = [];
@@ -95,7 +137,7 @@ function preprocessComponents(body) {
95
137
  const attrStr = parts.length ? `{${parts.join(" ")}}` : "";
96
138
  return `::iframe[${src}]${attrStr}`;
97
139
  });
98
- return html;
140
+ return restoreFencedCodeBlocks(html, blocks);
99
141
  }
100
142
  // ---------------------------------------------------------------------------
101
143
  // Directive preprocessor: transforms :::directive blocks into HTML
@@ -167,7 +209,8 @@ function splitChildren(content, marker) {
167
209
  * from other directive types cannot collide.
168
210
  */
169
211
  function preprocessDirectives(body) {
170
- let html = body;
212
+ const { text, blocks } = protectFencedCodeBlocks(body);
213
+ let html = text;
171
214
  // Callouts: :::note, :::warning, :::tip, :::info (optional title)
172
215
  html = html.replace(/^:::(note|warning|tip|info)(?:[^\S\n]+(.+))?\s*\n([\s\S]*?)^:::\s*$/gm, (_m, type, title, content) => {
173
216
  const label = title?.trim() || type.charAt(0).toUpperCase() + type.slice(1);
@@ -181,14 +224,30 @@ ${body ? `<div class="callout-content">\n\n${body}\n\n</div>` : ""}
181
224
  html = html.replace(/^:::steps\s*\n([\s\S]*?)^:::\s*$/gm, (_m, content) => {
182
225
  const lines = content.trim().split("\n");
183
226
  const steps = [];
227
+ let fenceMarker = "";
184
228
  for (const line of lines) {
185
- const sm = line.match(/^\d+\.\s+(.+)/);
229
+ // Track fenced code blocks so we don't mis-detect numbered
230
+ // lines inside them as step titles. A closing fence must use
231
+ // the same character, at least as many repeats, and no info string.
232
+ const stripped = line.replace(/^ {1,3}/, "");
233
+ const fm = stripped.match(/^(`{3,}|~{3,})(.*)/);
234
+ if (fm) {
235
+ if (!fenceMarker) {
236
+ fenceMarker = fm[1];
237
+ }
238
+ else if (fm[1][0] === fenceMarker[0] &&
239
+ fm[1].length >= fenceMarker.length &&
240
+ !fm[2].trim()) {
241
+ fenceMarker = "";
242
+ }
243
+ }
244
+ const sm = !fenceMarker && line.match(/^\d+\.\s+(.+)/);
186
245
  if (sm) {
187
246
  steps.push({ title: sm[1], body: [] });
188
247
  }
189
248
  else if (steps.length > 0) {
190
249
  // Strip up to 3 leading spaces (markdown list indent)
191
- steps[steps.length - 1].body.push(line.replace(/^ {1,3}/, ""));
250
+ steps[steps.length - 1].body.push(stripped);
192
251
  }
193
252
  }
194
253
  const items = steps
@@ -216,15 +275,16 @@ ${s.body.join("\n").trim()}
216
275
  });
217
276
  // Code Group: :::code-group with titled fenced code blocks
218
277
  html = html.replace(/^:::code-group\s*\n([\s\S]*?)^:::\s*$/gm, (_m, content) => {
219
- const blocks = [];
278
+ const restoredContent = restoreFencedCodeBlocks(content, blocks);
279
+ const codeBlocks = [];
220
280
  const re = /```(\w+)\s+title="([^"]*)"\s*\n([\s\S]*?)```/g;
221
281
  let match;
222
- while ((match = re.exec(content)) !== null) {
223
- blocks.push({ title: match[2], body: `\`\`\`${match[1]}\n${match[3]}\`\`\`` });
282
+ while ((match = re.exec(restoredContent)) !== null) {
283
+ codeBlocks.push({ title: match[2], body: `\`\`\`${match[1]}\n${match[3]}\`\`\`` });
224
284
  }
225
- if (blocks.length === 0)
226
- return content;
227
- return `\n\n${buildTabbedHtml(blocks, nextId("cg"), "directive-code-group")}\n\n`;
285
+ if (codeBlocks.length === 0)
286
+ return restoredContent;
287
+ return `\n\n${buildTabbedHtml(codeBlocks, nextId("cg"), "directive-code-group")}\n\n`;
228
288
  });
229
289
  // Card Group: :::card-group{cols="N"} with ::card children
230
290
  html = html.replace(/^:::card-group(?:\{([^}]*)\})?\s*\n([\s\S]*?)^:::\s*$/gm, (_m, attrsRaw, content) => {
@@ -266,7 +326,7 @@ ${content.trim()}
266
326
  return match;
267
327
  return `<div class="accordion-group not-prose">\n${match.trim()}\n</div>`;
268
328
  });
269
- return html;
329
+ return restoreFencedCodeBlocks(html, blocks);
270
330
  }
271
331
  // ---------------------------------------------------------------------------
272
332
  // Public API
@@ -459,6 +459,7 @@ async function loadCustomCSS(paths) {
459
459
  const MIME_TYPES = {
460
460
  ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg",
461
461
  ".gif": "image/gif", ".svg": "image/svg+xml", ".webp": "image/webp",
462
+ ".ico": "image/x-icon",
462
463
  };
463
464
  async function resolveAssetUrl(pathOrUrl) {
464
465
  if (!pathOrUrl || pathOrUrl.startsWith("http://") || pathOrUrl.startsWith("https://") || pathOrUrl.startsWith("data:")) {
@@ -90,6 +90,12 @@ h1[id], h2[id], h3[id], h4[id], h5[id], h6[id] {
90
90
  overflow-x: auto;
91
91
  -webkit-overflow-scrolling: touch;
92
92
  }
93
+ #sourcey .table-wrap table {
94
+ margin: 0;
95
+ }
96
+ #sourcey .prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)) {
97
+ padding-top: .571429em;
98
+ }
93
99
 
94
100
  /* ── Prose Video (::video directive) ──────────────────────────────── */
95
101
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sourcey",
3
- "version": "3.4.3",
3
+ "version": "3.4.4",
4
4
  "description": "Open source documentation platform. API references, guides, static output.",
5
5
  "type": "module",
6
6
  "engines": {