@farming-labs/svelte 0.0.48 → 0.0.51
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.d.ts +6 -1
- package/dist/markdown.js +130 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
package/dist/markdown.d.ts
CHANGED
|
@@ -8,10 +8,15 @@
|
|
|
8
8
|
* - Callouts / admonitions (GitHub `[!NOTE]` and `**Note:**` styles)
|
|
9
9
|
* - Tables, lists, inline formatting, headings with anchor IDs
|
|
10
10
|
*/
|
|
11
|
+
import type { DocsTheme } from "@farming-labs/docs";
|
|
12
|
+
interface RenderMarkdownOptions {
|
|
13
|
+
theme?: DocsTheme;
|
|
14
|
+
}
|
|
11
15
|
/**
|
|
12
16
|
* Render a markdown string to HTML with full syntax highlighting,
|
|
13
17
|
* callouts, tables, tabs, and copy-to-clipboard support.
|
|
14
18
|
*
|
|
15
19
|
* Designed for server-side use in SvelteKit `+page.server` loaders.
|
|
16
20
|
*/
|
|
17
|
-
export declare function renderMarkdown(content: string): Promise<string>;
|
|
21
|
+
export declare function renderMarkdown(content: string, options?: RenderMarkdownOptions): Promise<string>;
|
|
22
|
+
export {};
|
package/dist/markdown.js
CHANGED
|
@@ -43,6 +43,126 @@ function slugify(text) {
|
|
|
43
43
|
.replace(/-+/g, "-")
|
|
44
44
|
.trim();
|
|
45
45
|
}
|
|
46
|
+
const hoverLinkDefaults = {
|
|
47
|
+
linkLabel: "Open page",
|
|
48
|
+
showIndicator: false,
|
|
49
|
+
align: "center",
|
|
50
|
+
side: "bottom",
|
|
51
|
+
sideOffset: 12,
|
|
52
|
+
};
|
|
53
|
+
function escapeHtml(value) {
|
|
54
|
+
return value
|
|
55
|
+
.replace(/&/g, "&")
|
|
56
|
+
.replace(/</g, "<")
|
|
57
|
+
.replace(/>/g, ">")
|
|
58
|
+
.replace(/"/g, """);
|
|
59
|
+
}
|
|
60
|
+
function parseJsxAttributes(source) {
|
|
61
|
+
const attrs = {};
|
|
62
|
+
const pattern = /([A-Za-z_:][-.\w:]*)(?:=(?:"([^"]*)"|'([^']*)'|\{([^}]*)\}))?/g;
|
|
63
|
+
let match;
|
|
64
|
+
while ((match = pattern.exec(source)) !== null) {
|
|
65
|
+
const [, name, doubleQuoted, singleQuoted, braced] = match;
|
|
66
|
+
const rawValue = doubleQuoted ?? singleQuoted ?? braced;
|
|
67
|
+
attrs[name] = rawValue === undefined ? true : rawValue.trim();
|
|
68
|
+
}
|
|
69
|
+
return attrs;
|
|
70
|
+
}
|
|
71
|
+
function toBoolean(value, fallback) {
|
|
72
|
+
if (typeof value === "boolean")
|
|
73
|
+
return value;
|
|
74
|
+
if (typeof value === "string") {
|
|
75
|
+
if (value === "true")
|
|
76
|
+
return true;
|
|
77
|
+
if (value === "false")
|
|
78
|
+
return false;
|
|
79
|
+
return fallback;
|
|
80
|
+
}
|
|
81
|
+
return fallback;
|
|
82
|
+
}
|
|
83
|
+
function toStringValue(value) {
|
|
84
|
+
return typeof value === "string" ? value : undefined;
|
|
85
|
+
}
|
|
86
|
+
function toNumberValue(value) {
|
|
87
|
+
if (typeof value === "number")
|
|
88
|
+
return Number.isFinite(value) ? value : undefined;
|
|
89
|
+
if (typeof value !== "string")
|
|
90
|
+
return undefined;
|
|
91
|
+
const parsed = Number(value);
|
|
92
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
93
|
+
}
|
|
94
|
+
function normalizeHoverAlign(value) {
|
|
95
|
+
if (value === "start" || value === "end")
|
|
96
|
+
return value;
|
|
97
|
+
return "center";
|
|
98
|
+
}
|
|
99
|
+
function normalizeHoverSide(value) {
|
|
100
|
+
if (value === "top" || value === "right" || value === "left")
|
|
101
|
+
return value;
|
|
102
|
+
return "bottom";
|
|
103
|
+
}
|
|
104
|
+
function resolveHoverLinkOptions(theme) {
|
|
105
|
+
const configured = theme?.ui?.components?.HoverLink;
|
|
106
|
+
const base = { ...hoverLinkDefaults };
|
|
107
|
+
if (typeof configured === "function") {
|
|
108
|
+
const resolved = configured(base);
|
|
109
|
+
if (resolved && typeof resolved === "object") {
|
|
110
|
+
return { ...base, ...resolved };
|
|
111
|
+
}
|
|
112
|
+
return base;
|
|
113
|
+
}
|
|
114
|
+
if (configured && typeof configured === "object") {
|
|
115
|
+
return { ...base, ...configured };
|
|
116
|
+
}
|
|
117
|
+
return base;
|
|
118
|
+
}
|
|
119
|
+
function renderHoverLink(attrSource, children, theme) {
|
|
120
|
+
const attrs = parseJsxAttributes(attrSource);
|
|
121
|
+
const defaults = resolveHoverLinkOptions(theme);
|
|
122
|
+
const href = toStringValue(attrs.href);
|
|
123
|
+
const title = toStringValue(attrs.title);
|
|
124
|
+
const description = toStringValue(attrs.description);
|
|
125
|
+
if (!href || !title || !description)
|
|
126
|
+
return children;
|
|
127
|
+
const linkLabel = toStringValue(attrs.linkLabel) ??
|
|
128
|
+
toStringValue(defaults.linkLabel) ??
|
|
129
|
+
hoverLinkDefaults.linkLabel;
|
|
130
|
+
const previewLabel = toStringValue(attrs.previewLabel) ?? toStringValue(defaults.previewLabel);
|
|
131
|
+
const showIndicator = attrs.showIndicator !== undefined
|
|
132
|
+
? toBoolean(attrs.showIndicator, hoverLinkDefaults.showIndicator)
|
|
133
|
+
: toBoolean(defaults.showIndicator, hoverLinkDefaults.showIndicator);
|
|
134
|
+
const external = attrs.external !== undefined
|
|
135
|
+
? toBoolean(attrs.external, false)
|
|
136
|
+
: toBoolean(defaults.external, false);
|
|
137
|
+
const align = normalizeHoverAlign(toStringValue(attrs.align) ?? toStringValue(defaults.align));
|
|
138
|
+
const side = normalizeHoverSide(toStringValue(attrs.side) ?? toStringValue(defaults.side));
|
|
139
|
+
const sideOffset = toNumberValue(attrs.sideOffset) ??
|
|
140
|
+
toNumberValue(defaults.sideOffset) ??
|
|
141
|
+
hoverLinkDefaults.sideOffset;
|
|
142
|
+
const targetAttrs = external ? ' target="_blank" rel="noopener noreferrer"' : "";
|
|
143
|
+
const triggerHtml = escapeHtml(children.trim()) || escapeHtml(title);
|
|
144
|
+
const indicatorHtml = showIndicator
|
|
145
|
+
? '<span class="fd-hover-link-indicator" aria-hidden="true">+</span>'
|
|
146
|
+
: "";
|
|
147
|
+
const previewHtml = previewLabel
|
|
148
|
+
? `<span class="fd-hover-link-preview-label">${escapeHtml(previewLabel)}</span>`
|
|
149
|
+
: "";
|
|
150
|
+
return (`<span class="fd-hover-link" data-hover-link data-align="${align}" data-side="${side}" style="--fd-hover-link-side-offset:${sideOffset}px">` +
|
|
151
|
+
`<button type="button" class="fd-hover-link-trigger" aria-haspopup="dialog" aria-expanded="false">${triggerHtml}${indicatorHtml}</button>` +
|
|
152
|
+
`<span class="fd-hover-link-popover" role="dialog" aria-hidden="true">` +
|
|
153
|
+
`<span class="fd-hover-link-card">` +
|
|
154
|
+
`<span class="fd-hover-link-body">` +
|
|
155
|
+
previewHtml +
|
|
156
|
+
`<a href="${escapeHtml(href)}" class="fd-hover-link-title"${targetAttrs}>${escapeHtml(title)}</a>` +
|
|
157
|
+
`<span class="fd-hover-link-description">${escapeHtml(description)}</span>` +
|
|
158
|
+
`</span>` +
|
|
159
|
+
`<span class="fd-hover-link-footer">` +
|
|
160
|
+
`<a href="${escapeHtml(href)}" class="fd-hover-link-cta"${targetAttrs}>${escapeHtml(linkLabel)}<span aria-hidden="true">→</span></a>` +
|
|
161
|
+
`</span>` +
|
|
162
|
+
`</span>` +
|
|
163
|
+
`</span>` +
|
|
164
|
+
`</span>`);
|
|
165
|
+
}
|
|
46
166
|
const calloutIcons = {
|
|
47
167
|
note: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>',
|
|
48
168
|
warning: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',
|
|
@@ -118,7 +238,7 @@ function dedentCode(raw) {
|
|
|
118
238
|
*
|
|
119
239
|
* Designed for server-side use in SvelteKit `+page.server` loaders.
|
|
120
240
|
*/
|
|
121
|
-
export async function renderMarkdown(content) {
|
|
241
|
+
export async function renderMarkdown(content, options = {}) {
|
|
122
242
|
if (!content)
|
|
123
243
|
return "";
|
|
124
244
|
const hl = await getHighlighter();
|
|
@@ -167,6 +287,12 @@ export async function renderMarkdown(content) {
|
|
|
167
287
|
codeBlocks.push(wrapCodeWithCopy(html, raw, title, lang));
|
|
168
288
|
return placeholder;
|
|
169
289
|
});
|
|
290
|
+
const hoverLinkBlocks = [];
|
|
291
|
+
result = result.replace(/<HoverLink\s+([^>]*?)>([\s\S]*?)<\/HoverLink>/g, (_, attrSource, children) => {
|
|
292
|
+
const placeholder = `%%HOVERLINK_${hoverLinkBlocks.length}%%`;
|
|
293
|
+
hoverLinkBlocks.push(renderHoverLink(attrSource, children, options.theme));
|
|
294
|
+
return placeholder;
|
|
295
|
+
});
|
|
170
296
|
// Inline code
|
|
171
297
|
result = result.replace(/`([^`]+)`/g, "<code>$1</code>");
|
|
172
298
|
// Headings (h4 → h1 order to avoid prefix collisions)
|
|
@@ -272,5 +398,8 @@ export async function renderMarkdown(content) {
|
|
|
272
398
|
for (let i = 0; i < tabsBlocks.length; i++) {
|
|
273
399
|
result = result.replace(`%%TABS_${i}%%`, tabsBlocks[i]);
|
|
274
400
|
}
|
|
401
|
+
for (let i = 0; i < hoverLinkBlocks.length; i++) {
|
|
402
|
+
result = result.replace(`%%HOVERLINK_${i}%%`, hoverLinkBlocks[i]);
|
|
403
|
+
}
|
|
275
404
|
return result;
|
|
276
405
|
}
|
package/dist/server.js
CHANGED
|
@@ -431,7 +431,7 @@ export function createDocsServer(config = {}) {
|
|
|
431
431
|
});
|
|
432
432
|
}
|
|
433
433
|
const { data, content } = matter(raw);
|
|
434
|
-
const html = await renderMarkdown(content);
|
|
434
|
+
const html = await renderMarkdown(content, { theme: config.theme });
|
|
435
435
|
const currentUrl = isIndex ? `/${entry}` : `/${entry}/${slug}`;
|
|
436
436
|
const currentIndex = flatPages.findIndex((p) => p.url === currentUrl);
|
|
437
437
|
const previousPage = currentIndex > 0 ? flatPages[currentIndex - 1] : null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/svelte",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.51",
|
|
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.0.
|
|
59
|
+
"@farming-labs/docs": "0.0.51"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"@farming-labs/docs": "*"
|