svedocs 0.1.0-beta.10
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/LICENSE +5 -0
- package/README.md +85 -0
- package/dist/ai/openai-compatible.d.ts +13 -0
- package/dist/ai/openai-compatible.d.ts.map +1 -0
- package/dist/ai/openai-compatible.js +92 -0
- package/dist/ai/providers.d.ts +20 -0
- package/dist/ai/providers.d.ts.map +1 -0
- package/dist/ai/providers.js +185 -0
- package/dist/ai/rate-limit.d.ts +18 -0
- package/dist/ai/rate-limit.d.ts.map +1 -0
- package/dist/ai/rate-limit.js +52 -0
- package/dist/ai/response.d.ts +4 -0
- package/dist/ai/response.d.ts.map +1 -0
- package/dist/ai/response.js +151 -0
- package/dist/ai/runtime.d.ts +32 -0
- package/dist/ai/runtime.d.ts.map +1 -0
- package/dist/ai/runtime.js +111 -0
- package/dist/ai/types.d.ts +93 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +1 -0
- package/dist/ai.d.ts +7 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +6 -0
- package/dist/ambient.d.ts +5 -0
- package/dist/cloudflare.d.ts +29 -0
- package/dist/cloudflare.d.ts.map +1 -0
- package/dist/cloudflare.js +149 -0
- package/dist/config.d.ts +373 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +299 -0
- package/dist/core/checks.d.ts +4 -0
- package/dist/core/checks.d.ts.map +1 -0
- package/dist/core/checks.js +267 -0
- package/dist/core/config.d.ts +6 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +178 -0
- package/dist/core/content.d.ts +7 -0
- package/dist/core/content.d.ts.map +1 -0
- package/dist/core/content.js +340 -0
- package/dist/core/i18n.d.ts +5 -0
- package/dist/core/i18n.d.ts.map +1 -0
- package/dist/core/i18n.js +117 -0
- package/dist/core/links.d.ts +5 -0
- package/dist/core/links.d.ts.map +1 -0
- package/dist/core/links.js +60 -0
- package/dist/core/messages.d.ts +149 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +163 -0
- package/dist/core/navigation.d.ts +5 -0
- package/dist/core/navigation.d.ts.map +1 -0
- package/dist/core/navigation.js +144 -0
- package/dist/core/routes.d.ts +36 -0
- package/dist/core/routes.d.ts.map +1 -0
- package/dist/core/routes.js +152 -0
- package/dist/core/search.d.ts +5 -0
- package/dist/core/search.d.ts.map +1 -0
- package/dist/core/search.js +41 -0
- package/dist/core/types.d.ts +468 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +4 -0
- package/dist/core/utils.d.ts +13 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +60 -0
- package/dist/core.d.ts +9 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +8 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/mdx/ast.d.ts +32 -0
- package/dist/mdx/ast.d.ts.map +1 -0
- package/dist/mdx/ast.js +148 -0
- package/dist/mdx/code.d.ts +17 -0
- package/dist/mdx/code.d.ts.map +1 -0
- package/dist/mdx/code.js +327 -0
- package/dist/mdx/compile.d.ts +29 -0
- package/dist/mdx/compile.d.ts.map +1 -0
- package/dist/mdx/compile.js +59 -0
- package/dist/mdx/diff.d.ts +9 -0
- package/dist/mdx/diff.d.ts.map +1 -0
- package/dist/mdx/diff.js +171 -0
- package/dist/mdx/headings.d.ts +4 -0
- package/dist/mdx/headings.d.ts.map +1 -0
- package/dist/mdx/headings.js +42 -0
- package/dist/mdx/links.d.ts +4 -0
- package/dist/mdx/links.d.ts.map +1 -0
- package/dist/mdx/links.js +144 -0
- package/dist/mdx/utils.d.ts +10 -0
- package/dist/mdx/utils.d.ts.map +1 -0
- package/dist/mdx/utils.js +64 -0
- package/dist/og/image.d.ts +25 -0
- package/dist/og/image.d.ts.map +1 -0
- package/dist/og/image.js +224 -0
- package/dist/og/metadata.d.ts +7 -0
- package/dist/og/metadata.d.ts.map +1 -0
- package/dist/og/metadata.js +198 -0
- package/dist/og/response.d.ts +4 -0
- package/dist/og/response.d.ts.map +1 -0
- package/dist/og/response.js +49 -0
- package/dist/og/rss.d.ts +4 -0
- package/dist/og/rss.d.ts.map +1 -0
- package/dist/og/rss.js +96 -0
- package/dist/og/sitemap.d.ts +7 -0
- package/dist/og/sitemap.d.ts.map +1 -0
- package/dist/og/sitemap.js +90 -0
- package/dist/og/types.d.ts +65 -0
- package/dist/og/types.d.ts.map +1 -0
- package/dist/og/types.js +1 -0
- package/dist/og.d.ts +6 -0
- package/dist/og.d.ts.map +1 -0
- package/dist/og.js +5 -0
- package/dist/routes.d.ts +2 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +1 -0
- package/dist/search/algolia.d.ts +10 -0
- package/dist/search/algolia.d.ts.map +1 -0
- package/dist/search/algolia.js +82 -0
- package/dist/search/cloudflare-sync.d.ts +5 -0
- package/dist/search/cloudflare-sync.d.ts.map +1 -0
- package/dist/search/cloudflare-sync.js +169 -0
- package/dist/search/cloudflare.d.ts +11 -0
- package/dist/search/cloudflare.d.ts.map +1 -0
- package/dist/search/cloudflare.js +126 -0
- package/dist/search/local.d.ts +9 -0
- package/dist/search/local.d.ts.map +1 -0
- package/dist/search/local.js +165 -0
- package/dist/search/runtime.d.ts +41 -0
- package/dist/search/runtime.d.ts.map +1 -0
- package/dist/search/runtime.js +152 -0
- package/dist/search/types.d.ts +172 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/search/types.js +1 -0
- package/dist/search/typesense.d.ts +11 -0
- package/dist/search/typesense.d.ts.map +1 -0
- package/dist/search/typesense.js +91 -0
- package/dist/search/utils.d.ts +11 -0
- package/dist/search/utils.d.ts.map +1 -0
- package/dist/search/utils.js +93 -0
- package/dist/search.d.ts +8 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +7 -0
- package/dist/svelte.d.ts +27 -0
- package/dist/svelte.d.ts.map +1 -0
- package/dist/svelte.js +45 -0
- package/dist/testing.d.ts +3 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +23 -0
- package/dist/theme/Article.svelte +145 -0
- package/dist/theme/Article.svelte.d.ts +36 -0
- package/dist/theme/Article.svelte.d.ts.map +1 -0
- package/dist/theme/AskAiPanel.svelte +241 -0
- package/dist/theme/AskAiPanel.svelte.d.ts +31 -0
- package/dist/theme/AskAiPanel.svelte.d.ts.map +1 -0
- package/dist/theme/Brand.svelte +19 -0
- package/dist/theme/Brand.svelte.d.ts +22 -0
- package/dist/theme/Brand.svelte.d.ts.map +1 -0
- package/dist/theme/Button.svelte +34 -0
- package/dist/theme/Button.svelte.d.ts +41 -0
- package/dist/theme/Button.svelte.d.ts.map +1 -0
- package/dist/theme/Checkbox.svelte +63 -0
- package/dist/theme/Checkbox.svelte.d.ts +45 -0
- package/dist/theme/Checkbox.svelte.d.ts.map +1 -0
- package/dist/theme/CodeBlock.svelte +6 -0
- package/dist/theme/CodeBlock.svelte.d.ts +22 -0
- package/dist/theme/CodeBlock.svelte.d.ts.map +1 -0
- package/dist/theme/DocPage.svelte +15 -0
- package/dist/theme/DocPage.svelte.d.ts +33 -0
- package/dist/theme/DocPage.svelte.d.ts.map +1 -0
- package/dist/theme/DocsApp.svelte +194 -0
- package/dist/theme/DocsApp.svelte.d.ts +60 -0
- package/dist/theme/DocsApp.svelte.d.ts.map +1 -0
- package/dist/theme/DocsLayout.svelte +99 -0
- package/dist/theme/DocsLayout.svelte.d.ts +39 -0
- package/dist/theme/DocsLayout.svelte.d.ts.map +1 -0
- package/dist/theme/DocsShell.svelte +91 -0
- package/dist/theme/DocsShell.svelte.d.ts +34 -0
- package/dist/theme/DocsShell.svelte.d.ts.map +1 -0
- package/dist/theme/ErrorPage.svelte +113 -0
- package/dist/theme/ErrorPage.svelte.d.ts +34 -0
- package/dist/theme/ErrorPage.svelte.d.ts.map +1 -0
- package/dist/theme/FloatingToolbar.svelte +8 -0
- package/dist/theme/FloatingToolbar.svelte.d.ts +22 -0
- package/dist/theme/FloatingToolbar.svelte.d.ts.map +1 -0
- package/dist/theme/Footer.svelte +18 -0
- package/dist/theme/Footer.svelte.d.ts +24 -0
- package/dist/theme/Footer.svelte.d.ts.map +1 -0
- package/dist/theme/FooterLinks.svelte +37 -0
- package/dist/theme/FooterLinks.svelte.d.ts +22 -0
- package/dist/theme/FooterLinks.svelte.d.ts.map +1 -0
- package/dist/theme/FormField.svelte +41 -0
- package/dist/theme/FormField.svelte.d.ts +35 -0
- package/dist/theme/FormField.svelte.d.ts.map +1 -0
- package/dist/theme/HomePage.svelte +284 -0
- package/dist/theme/HomePage.svelte.d.ts +65 -0
- package/dist/theme/HomePage.svelte.d.ts.map +1 -0
- package/dist/theme/Input.svelte +36 -0
- package/dist/theme/Input.svelte.d.ts +34 -0
- package/dist/theme/Input.svelte.d.ts.map +1 -0
- package/dist/theme/LayoutShell.svelte +120 -0
- package/dist/theme/LayoutShell.svelte.d.ts +43 -0
- package/dist/theme/LayoutShell.svelte.d.ts.map +1 -0
- package/dist/theme/LocalizedLink.svelte +21 -0
- package/dist/theme/LocalizedLink.svelte.d.ts +38 -0
- package/dist/theme/LocalizedLink.svelte.d.ts.map +1 -0
- package/dist/theme/MobileNav.svelte +20 -0
- package/dist/theme/MobileNav.svelte.d.ts +26 -0
- package/dist/theme/MobileNav.svelte.d.ts.map +1 -0
- package/dist/theme/Navbar.svelte +69 -0
- package/dist/theme/Navbar.svelte.d.ts +29 -0
- package/dist/theme/Navbar.svelte.d.ts.map +1 -0
- package/dist/theme/PageLayout.svelte +49 -0
- package/dist/theme/PageLayout.svelte.d.ts +34 -0
- package/dist/theme/PageLayout.svelte.d.ts.map +1 -0
- package/dist/theme/PageShell.svelte +98 -0
- package/dist/theme/PageShell.svelte.d.ts +35 -0
- package/dist/theme/PageShell.svelte.d.ts.map +1 -0
- package/dist/theme/PageTools.svelte +87 -0
- package/dist/theme/PageTools.svelte.d.ts +25 -0
- package/dist/theme/PageTools.svelte.d.ts.map +1 -0
- package/dist/theme/RenderError.svelte +62 -0
- package/dist/theme/RenderError.svelte.d.ts +31 -0
- package/dist/theme/RenderError.svelte.d.ts.map +1 -0
- package/dist/theme/RootLayout.svelte +274 -0
- package/dist/theme/RootLayout.svelte.d.ts +47 -0
- package/dist/theme/RootLayout.svelte.d.ts.map +1 -0
- package/dist/theme/RouteRenderError.svelte +53 -0
- package/dist/theme/RouteRenderError.svelte.d.ts +34 -0
- package/dist/theme/RouteRenderError.svelte.d.ts.map +1 -0
- package/dist/theme/SafeRenderError.svelte +49 -0
- package/dist/theme/SafeRenderError.svelte.d.ts +33 -0
- package/dist/theme/SafeRenderError.svelte.d.ts.map +1 -0
- package/dist/theme/ScopeSwitcher.svelte +107 -0
- package/dist/theme/ScopeSwitcher.svelte.d.ts +26 -0
- package/dist/theme/ScopeSwitcher.svelte.d.ts.map +1 -0
- package/dist/theme/SearchDialog.svelte +200 -0
- package/dist/theme/SearchDialog.svelte.d.ts +31 -0
- package/dist/theme/SearchDialog.svelte.d.ts.map +1 -0
- package/dist/theme/Select.svelte +37 -0
- package/dist/theme/Select.svelte.d.ts +42 -0
- package/dist/theme/Select.svelte.d.ts.map +1 -0
- package/dist/theme/SidebarTree.svelte +148 -0
- package/dist/theme/SidebarTree.svelte.d.ts +24 -0
- package/dist/theme/SidebarTree.svelte.d.ts.map +1 -0
- package/dist/theme/SocialNav.svelte +17 -0
- package/dist/theme/SocialNav.svelte.d.ts +22 -0
- package/dist/theme/SocialNav.svelte.d.ts.map +1 -0
- package/dist/theme/TableOfContents.svelte +73 -0
- package/dist/theme/TableOfContents.svelte.d.ts +25 -0
- package/dist/theme/TableOfContents.svelte.d.ts.map +1 -0
- package/dist/theme/Textarea.svelte +33 -0
- package/dist/theme/Textarea.svelte.d.ts +33 -0
- package/dist/theme/Textarea.svelte.d.ts.map +1 -0
- package/dist/theme/ThemeInit.svelte +16 -0
- package/dist/theme/ThemeInit.svelte.d.ts +23 -0
- package/dist/theme/ThemeInit.svelte.d.ts.map +1 -0
- package/dist/theme/ThemeToggle.svelte +37 -0
- package/dist/theme/ThemeToggle.svelte.d.ts +23 -0
- package/dist/theme/ThemeToggle.svelte.d.ts.map +1 -0
- package/dist/theme/TopNav.svelte +23 -0
- package/dist/theme/TopNav.svelte.d.ts +22 -0
- package/dist/theme/TopNav.svelte.d.ts.map +1 -0
- package/dist/theme/base.css +240 -0
- package/dist/theme/defaults.d.ts +4 -0
- package/dist/theme/defaults.d.ts.map +1 -0
- package/dist/theme/defaults.js +55 -0
- package/dist/theme/forms.d.ts +4 -0
- package/dist/theme/forms.d.ts.map +1 -0
- package/dist/theme/forms.js +3 -0
- package/dist/theme/headless.d.ts +62 -0
- package/dist/theme/headless.d.ts.map +1 -0
- package/dist/theme/headless.js +1064 -0
- package/dist/theme/index.d.ts +41 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +38 -0
- package/dist/theme/portal.d.ts +6 -0
- package/dist/theme/portal.d.ts.map +1 -0
- package/dist/theme/portal.js +59 -0
- package/dist/theme/styles.css +4232 -0
- package/dist/theme/types.d.ts +363 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +1 -0
- package/dist/virtual.d.ts +65 -0
- package/dist/vite.d.ts +16 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +386 -0
- package/package.json +132 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { access, readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { checkLink, createLinkCheckContext } from './links.js';
|
|
4
|
+
import { findDuplicates, normalizePath } from './utils.js';
|
|
5
|
+
export async function checkSvedocsContent(manifest, projectRoot = process.cwd()) {
|
|
6
|
+
const issues = [];
|
|
7
|
+
const routeDuplicates = findDuplicates(manifest.pages.map((page) => page.routePath));
|
|
8
|
+
const canonicalDuplicates = findDuplicates(manifest.pages
|
|
9
|
+
.map((page) => page.seo.canonical)
|
|
10
|
+
.filter((canonical) => Boolean(canonical)));
|
|
11
|
+
if (manifest.config.build.mode === 'spa') {
|
|
12
|
+
issues.push({
|
|
13
|
+
code: 'spa-risk',
|
|
14
|
+
severity: 'warning',
|
|
15
|
+
message: 'SPA mode prerenders known pages, but server-only routes and provider bindings are unavailable on static hosts.'
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
if (manifest.config.seo.rss && !manifest.config.site.url) {
|
|
19
|
+
issues.push({
|
|
20
|
+
code: 'missing-site-url',
|
|
21
|
+
severity: 'warning',
|
|
22
|
+
message: 'site.url is required to generate absolute sitemap and RSS URLs for production.'
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
const sitemapPageCount = manifest.pages.filter((page) => (!page.hidden && !/(?:^|[\s,])(?:noindex|none)(?:$|[\s,])/i.test(page.seo.robots ?? ''))).length;
|
|
26
|
+
if (manifest.config.seo.sitemap && sitemapPageCount > 50_000) {
|
|
27
|
+
issues.push({
|
|
28
|
+
code: 'sitemap-url-limit',
|
|
29
|
+
severity: 'error',
|
|
30
|
+
message: `Sitemap contains ${sitemapPageCount} URLs; split it into sitemap index files before exceeding 50,000 URLs.`
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
for (const route of routeDuplicates) {
|
|
34
|
+
issues.push({
|
|
35
|
+
code: 'duplicate-route',
|
|
36
|
+
severity: 'error',
|
|
37
|
+
message: `Duplicate route path detected: ${route}`
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
for (const canonical of canonicalDuplicates) {
|
|
41
|
+
issues.push({
|
|
42
|
+
code: 'duplicate-canonical',
|
|
43
|
+
severity: 'error',
|
|
44
|
+
message: `Duplicate canonical URL detected: ${canonical}`
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (manifest.config.checks.translations) {
|
|
48
|
+
issues.push(...createMissingTranslationIssues(manifest));
|
|
49
|
+
}
|
|
50
|
+
const linkContext = createLinkCheckContext(manifest);
|
|
51
|
+
for (const page of manifest.pages) {
|
|
52
|
+
if (!page.description) {
|
|
53
|
+
issues.push({
|
|
54
|
+
code: 'missing-description',
|
|
55
|
+
severity: 'warning',
|
|
56
|
+
message: `${page.routePath} is missing a description for SEO and search excerpts.`,
|
|
57
|
+
pageId: page.id,
|
|
58
|
+
sourcePath: page.sourcePath
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (page.plainText && page.search.length === 0) {
|
|
62
|
+
issues.push({
|
|
63
|
+
code: 'empty-search',
|
|
64
|
+
severity: 'warning',
|
|
65
|
+
message: `${page.routePath} has content but produced no search records.`,
|
|
66
|
+
pageId: page.id,
|
|
67
|
+
sourcePath: page.sourcePath
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
for (const link of page.links) {
|
|
71
|
+
const issue = checkLink(page, link, linkContext)
|
|
72
|
+
?? await checkAssetLink(projectRoot, page.sourcePath, link, manifest.config.checks.assets)
|
|
73
|
+
?? await checkExternalLink(link, manifest.config.checks.externalLinks, page.id, page.sourcePath);
|
|
74
|
+
if (issue)
|
|
75
|
+
issues.push(issue);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return issues;
|
|
79
|
+
}
|
|
80
|
+
function createMissingTranslationIssues(manifest) {
|
|
81
|
+
const locales = manifest.config.i18n.locales.map((locale) => locale.code);
|
|
82
|
+
if (locales.length <= 1)
|
|
83
|
+
return [];
|
|
84
|
+
const groups = new Map();
|
|
85
|
+
for (const page of manifest.pages) {
|
|
86
|
+
if (page.hidden)
|
|
87
|
+
continue;
|
|
88
|
+
const key = `${page.kind}:${page.scopePath}`;
|
|
89
|
+
const group = groups.get(key) ?? [];
|
|
90
|
+
group.push(page);
|
|
91
|
+
groups.set(key, group);
|
|
92
|
+
}
|
|
93
|
+
const issues = [];
|
|
94
|
+
for (const pages of groups.values()) {
|
|
95
|
+
const present = new Set(pages.map((page) => page.locale).filter((locale) => Boolean(locale)));
|
|
96
|
+
const reference = pages[0];
|
|
97
|
+
if (!reference)
|
|
98
|
+
continue;
|
|
99
|
+
for (const locale of locales) {
|
|
100
|
+
if (present.has(locale))
|
|
101
|
+
continue;
|
|
102
|
+
issues.push({
|
|
103
|
+
code: 'missing-translation',
|
|
104
|
+
severity: 'warning',
|
|
105
|
+
message: `${reference.scopePath} is missing locale ${locale}.`,
|
|
106
|
+
pageId: reference.id,
|
|
107
|
+
sourcePath: reference.sourcePath
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return issues;
|
|
112
|
+
}
|
|
113
|
+
export async function checkPackagePublication(packageRoot) {
|
|
114
|
+
const issues = [];
|
|
115
|
+
const packageJsonPath = path.join(packageRoot, 'package.json');
|
|
116
|
+
const pkg = JSON.parse(await readFile(packageJsonPath, 'utf8'));
|
|
117
|
+
if (!pkg.private && pkg.license !== 'MIT') {
|
|
118
|
+
issues.push({
|
|
119
|
+
code: 'package-license-missing',
|
|
120
|
+
severity: 'error',
|
|
121
|
+
message: 'package.json license must be MIT for public svedocs packages.'
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (!pkg.private && pkg.publishConfig?.access !== 'public') {
|
|
125
|
+
issues.push({
|
|
126
|
+
code: 'package-publish-access-missing',
|
|
127
|
+
severity: 'warning',
|
|
128
|
+
message: 'package.json publishConfig.access should be public before publishing.'
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
if (!pkg.private && pkg.publishConfig?.provenance !== true) {
|
|
132
|
+
issues.push({
|
|
133
|
+
code: 'package-provenance-missing',
|
|
134
|
+
severity: 'warning',
|
|
135
|
+
message: 'package.json publishConfig.provenance should be true for npm provenance.'
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
for (const target of extractBinTargets(pkg.bin)) {
|
|
139
|
+
if (!await fileExists(path.join(packageRoot, target))) {
|
|
140
|
+
issues.push({
|
|
141
|
+
code: 'package-bin-missing',
|
|
142
|
+
severity: 'error',
|
|
143
|
+
message: `package.json bin target is missing: ${target}.`
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
for (const [exportName, value] of Object.entries(pkg.exports ?? {})) {
|
|
148
|
+
const targets = extractExportTargets(value);
|
|
149
|
+
for (const target of targets) {
|
|
150
|
+
if (!await fileExists(path.join(packageRoot, target))) {
|
|
151
|
+
issues.push({
|
|
152
|
+
code: 'package-export-missing',
|
|
153
|
+
severity: 'error',
|
|
154
|
+
message: `${exportName} points to missing package export target ${target}.`
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
for (const file of pkg.files ?? []) {
|
|
160
|
+
if (!await fileExists(path.join(packageRoot, file))) {
|
|
161
|
+
issues.push({
|
|
162
|
+
code: 'package-file-missing',
|
|
163
|
+
severity: 'error',
|
|
164
|
+
message: `package.json files entry is missing: ${file}.`
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return issues;
|
|
169
|
+
}
|
|
170
|
+
function extractBinTargets(bin) {
|
|
171
|
+
if (!bin)
|
|
172
|
+
return [];
|
|
173
|
+
if (typeof bin === 'string')
|
|
174
|
+
return [normalizePackageTarget(bin)];
|
|
175
|
+
return Object.values(bin).map(normalizePackageTarget);
|
|
176
|
+
}
|
|
177
|
+
async function checkAssetLink(projectRoot, sourcePath, link, enabled) {
|
|
178
|
+
if (!enabled || link.kind !== 'asset')
|
|
179
|
+
return undefined;
|
|
180
|
+
const pathname = splitHrefPath(link.href);
|
|
181
|
+
const candidates = pathname.startsWith('/')
|
|
182
|
+
? [
|
|
183
|
+
path.join(projectRoot, 'static', pathname),
|
|
184
|
+
path.join(projectRoot, pathname)
|
|
185
|
+
]
|
|
186
|
+
: [
|
|
187
|
+
path.join(projectRoot, path.posix.dirname(normalizePath(sourcePath)), pathname),
|
|
188
|
+
path.join(projectRoot, 'static', pathname)
|
|
189
|
+
];
|
|
190
|
+
if (await anyFileExists(candidates))
|
|
191
|
+
return undefined;
|
|
192
|
+
return {
|
|
193
|
+
code: 'broken-asset',
|
|
194
|
+
severity: 'error',
|
|
195
|
+
message: `${sourcePath}:${link.line} references missing asset ${link.href}.`,
|
|
196
|
+
pageId: sourcePath,
|
|
197
|
+
sourcePath,
|
|
198
|
+
href: link.href
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async function checkExternalLink(link, enabled, pageId, sourcePath) {
|
|
202
|
+
if (!enabled || link.kind !== 'external' || !/^https?:\/\//.test(link.href))
|
|
203
|
+
return undefined;
|
|
204
|
+
const controller = new AbortController();
|
|
205
|
+
const timeout = setTimeout(() => controller.abort(), 4_000);
|
|
206
|
+
try {
|
|
207
|
+
const response = await fetch(link.href, {
|
|
208
|
+
method: 'HEAD',
|
|
209
|
+
redirect: 'follow',
|
|
210
|
+
signal: controller.signal
|
|
211
|
+
});
|
|
212
|
+
if (response.ok || response.status === 405)
|
|
213
|
+
return undefined;
|
|
214
|
+
return {
|
|
215
|
+
code: 'external-link-unchecked',
|
|
216
|
+
severity: 'warning',
|
|
217
|
+
message: `${sourcePath}:${link.line} external link returned ${response.status}: ${link.href}.`,
|
|
218
|
+
pageId,
|
|
219
|
+
sourcePath,
|
|
220
|
+
href: link.href
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
return {
|
|
225
|
+
code: 'external-link-unchecked',
|
|
226
|
+
severity: 'warning',
|
|
227
|
+
message: `${sourcePath}:${link.line} external link could not be verified: ${link.href}.`,
|
|
228
|
+
pageId,
|
|
229
|
+
sourcePath,
|
|
230
|
+
href: link.href
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
finally {
|
|
234
|
+
clearTimeout(timeout);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function extractExportTargets(value) {
|
|
238
|
+
if (typeof value === 'string')
|
|
239
|
+
return [normalizePackageTarget(value)];
|
|
240
|
+
if (!value || typeof value !== 'object')
|
|
241
|
+
return [];
|
|
242
|
+
return Object.values(value).flatMap(extractExportTargets);
|
|
243
|
+
}
|
|
244
|
+
function normalizePackageTarget(target) {
|
|
245
|
+
return target.replace(/^\.\//, '');
|
|
246
|
+
}
|
|
247
|
+
function splitHrefPath(href) {
|
|
248
|
+
const [withoutHash = ''] = href.trim().split('#');
|
|
249
|
+
const [pathname = ''] = withoutHash.split('?');
|
|
250
|
+
return pathname;
|
|
251
|
+
}
|
|
252
|
+
async function anyFileExists(paths) {
|
|
253
|
+
for (const candidate of paths) {
|
|
254
|
+
if (await fileExists(candidate))
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
async function fileExists(filePath) {
|
|
260
|
+
try {
|
|
261
|
+
await access(filePath);
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SvedocsConfig } from '../config.js';
|
|
2
|
+
import type { SvedocsResolvedConfig } from './types.js';
|
|
3
|
+
export { defaultSvedocsMessages } from './i18n.js';
|
|
4
|
+
export declare function resolveSvedocsConfig(config?: SvedocsConfig): SvedocsResolvedConfig;
|
|
5
|
+
export declare function isResolvedConfig(config: SvedocsConfig | SvedocsResolvedConfig | undefined): config is SvedocsResolvedConfig;
|
|
6
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAEnD,wBAAgB,oBAAoB,CAAC,MAAM,GAAE,aAAkB,GAAG,qBAAqB,CA8ItF;AA2BD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,qBAAqB,GAAG,SAAS,GAAG,MAAM,IAAI,qBAAqB,CAY3H"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { resolveSvedocsI18nConfig } from './i18n.js';
|
|
2
|
+
export { defaultSvedocsMessages } from './i18n.js';
|
|
3
|
+
export function resolveSvedocsConfig(config = {}) {
|
|
4
|
+
const contentRoot = config.content?.root ?? 'content';
|
|
5
|
+
const docsRoot = config.content?.docs ?? `${contentRoot}/docs`;
|
|
6
|
+
const pagesRoot = config.content?.pages ?? `${contentRoot}/pages`;
|
|
7
|
+
const search = config.search === false ? { enabled: false, provider: 'local', scope: 'current' } : {
|
|
8
|
+
enabled: config.search?.enabled ?? true,
|
|
9
|
+
provider: config.search?.provider ?? 'local',
|
|
10
|
+
scope: config.search?.scope ?? 'current'
|
|
11
|
+
};
|
|
12
|
+
const ai = config.ai === false ? {
|
|
13
|
+
enabled: false,
|
|
14
|
+
provider: 'mock',
|
|
15
|
+
scope: 'current',
|
|
16
|
+
label: 'Ask AI',
|
|
17
|
+
placeholder: 'Ask about the docs',
|
|
18
|
+
suggestions: [],
|
|
19
|
+
maxResults: 5
|
|
20
|
+
} : {
|
|
21
|
+
enabled: config.ai?.enabled ?? Boolean(config.ai?.provider),
|
|
22
|
+
provider: config.ai?.provider ?? 'mock',
|
|
23
|
+
scope: config.ai?.scope ?? 'current',
|
|
24
|
+
label: config.ai?.label ?? 'Ask AI',
|
|
25
|
+
placeholder: config.ai?.placeholder ?? 'Ask about the docs',
|
|
26
|
+
suggestions: config.ai?.suggestions ?? [],
|
|
27
|
+
maxResults: config.ai?.maxResults ?? 5,
|
|
28
|
+
...(config.ai?.systemPrompt ? { systemPrompt: config.ai.systemPrompt } : {}),
|
|
29
|
+
...(config.ai?.welcomeMessage ? { welcomeMessage: config.ai.welcomeMessage } : {})
|
|
30
|
+
};
|
|
31
|
+
const rss = resolveRssConfig(config);
|
|
32
|
+
return {
|
|
33
|
+
site: {
|
|
34
|
+
name: config.site?.name ?? 'svedocs',
|
|
35
|
+
title: config.site?.title ?? config.site?.name ?? 'svedocs',
|
|
36
|
+
description: config.site?.description ?? 'SvelteKit-native documentation framework.',
|
|
37
|
+
...(config.site?.url ? { url: config.site.url } : {})
|
|
38
|
+
},
|
|
39
|
+
content: {
|
|
40
|
+
root: contentRoot,
|
|
41
|
+
docs: docsRoot,
|
|
42
|
+
pages: pagesRoot,
|
|
43
|
+
include: config.content?.include ?? [`${contentRoot}/**/*.{md,mdx,svx}`],
|
|
44
|
+
exclude: config.content?.exclude ?? [
|
|
45
|
+
'**/_*.{md,mdx,svx}',
|
|
46
|
+
'**/node_modules/**',
|
|
47
|
+
'**/dist/**',
|
|
48
|
+
'**/build/**',
|
|
49
|
+
'**/.svelte-kit/**'
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
build: {
|
|
53
|
+
mode: config.build?.mode ?? 'edge'
|
|
54
|
+
},
|
|
55
|
+
theme: {
|
|
56
|
+
defaultMode: config.theme?.defaultMode ?? 'system',
|
|
57
|
+
palette: {
|
|
58
|
+
accent: config.theme?.palette?.accent ?? 'emerald',
|
|
59
|
+
neutral: config.theme?.palette?.neutral ?? 'zinc'
|
|
60
|
+
},
|
|
61
|
+
fonts: {
|
|
62
|
+
sans: config.theme?.fonts?.sans ?? '"IBM Plex Sans", "Avenir Next", sans-serif',
|
|
63
|
+
mono: config.theme?.fonts?.mono ?? '"JetBrains Mono", "SFMono-Regular", monospace',
|
|
64
|
+
display: config.theme?.fonts?.display ?? '"IBM Plex Sans", "Avenir Next", sans-serif'
|
|
65
|
+
},
|
|
66
|
+
radius: config.theme?.radius ?? '0px',
|
|
67
|
+
codeTheme: resolveCodeTheme(config.theme?.codeTheme),
|
|
68
|
+
code: {
|
|
69
|
+
lineNumbers: config.theme?.code?.lineNumbers ?? true,
|
|
70
|
+
wrap: config.theme?.code?.wrap ?? false,
|
|
71
|
+
copyButton: config.theme?.code?.copyButton ?? true
|
|
72
|
+
},
|
|
73
|
+
brand: {
|
|
74
|
+
label: config.theme?.brand?.label ?? config.site?.name ?? 'svedocs',
|
|
75
|
+
...(config.theme?.brand?.labelKey ? { labelKey: config.theme.brand.labelKey } : {}),
|
|
76
|
+
href: config.theme?.brand?.href ?? '/',
|
|
77
|
+
...(config.theme?.brand?.logo ? { logo: config.theme.brand.logo } : {}),
|
|
78
|
+
mark: config.theme?.brand?.mark ?? 'pixel'
|
|
79
|
+
},
|
|
80
|
+
nav: config.theme?.nav ?? [
|
|
81
|
+
{ label: 'Docs', labelKey: 'nav.docs', href: '/docs' }
|
|
82
|
+
],
|
|
83
|
+
social: config.theme?.social ?? [],
|
|
84
|
+
footer: config.theme?.footer === false
|
|
85
|
+
? false
|
|
86
|
+
: {
|
|
87
|
+
text: config.theme?.footer?.text ?? `MIT licensed. Built with ${config.site?.name ?? 'svedocs'}.`,
|
|
88
|
+
links: config.theme?.footer?.links ?? []
|
|
89
|
+
},
|
|
90
|
+
home: {
|
|
91
|
+
kicker: config.theme?.home?.kicker ?? 'SvelteKit-native docs',
|
|
92
|
+
...(config.theme?.home?.kickerKey ? { kickerKey: config.theme.home.kickerKey } : {}),
|
|
93
|
+
...(config.theme?.home?.primaryAction ? { primaryAction: config.theme.home.primaryAction } : {}),
|
|
94
|
+
...(config.theme?.home?.secondaryAction ? { secondaryAction: config.theme.home.secondaryAction } : {}),
|
|
95
|
+
visual: {
|
|
96
|
+
type: config.theme?.home?.visual?.type ?? 'pixel',
|
|
97
|
+
...(config.theme?.home?.visual?.src ? { src: config.theme.home.visual.src } : {}),
|
|
98
|
+
alt: config.theme?.home?.visual?.alt ?? '',
|
|
99
|
+
...(config.theme?.home?.visual?.altKey ? { altKey: config.theme.home.visual.altKey } : {})
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
search,
|
|
104
|
+
ai,
|
|
105
|
+
seo: {
|
|
106
|
+
sitemap: config.seo?.sitemap ?? true,
|
|
107
|
+
rss,
|
|
108
|
+
robots: config.seo?.robots ?? true,
|
|
109
|
+
...(config.seo?.defaultAuthor ? { defaultAuthor: config.seo.defaultAuthor } : {}),
|
|
110
|
+
head: {
|
|
111
|
+
meta: config.seo?.head?.meta ?? [],
|
|
112
|
+
links: config.seo?.head?.links ?? [],
|
|
113
|
+
jsonLd: config.seo?.head?.jsonLd ?? config.seo?.head?.jsonld ?? config.seo?.head?.['json-ld'] ?? []
|
|
114
|
+
},
|
|
115
|
+
ogImage: config.seo?.ogImage === false
|
|
116
|
+
? false
|
|
117
|
+
: {
|
|
118
|
+
template: config.seo?.ogImage?.template ?? 'default',
|
|
119
|
+
format: config.seo?.ogImage?.format ?? 'svg',
|
|
120
|
+
outDir: config.seo?.ogImage?.outDir ?? 'static/og',
|
|
121
|
+
renderer: config.seo?.ogImage?.renderer ?? 'svg'
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
source: {
|
|
125
|
+
...(config.source?.editBaseUrl ? { editBaseUrl: config.source.editBaseUrl } : {})
|
|
126
|
+
},
|
|
127
|
+
cloudflare: {
|
|
128
|
+
compatibilityDate: config.cloudflare?.compatibilityDate ?? '2026-05-18',
|
|
129
|
+
aiSearch: {
|
|
130
|
+
binding: config.cloudflare?.aiSearch?.binding ?? 'SVEDOCS_AI_SEARCH',
|
|
131
|
+
instanceName: config.cloudflare?.aiSearch?.instanceName ?? 'svedocs',
|
|
132
|
+
...(config.cloudflare?.aiSearch?.namespace ? { namespace: config.cloudflare.aiSearch.namespace } : {}),
|
|
133
|
+
remote: config.cloudflare?.aiSearch?.remote ?? false
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
checks: {
|
|
137
|
+
assets: config.checks?.assets ?? true,
|
|
138
|
+
externalLinks: config.checks?.externalLinks ?? false,
|
|
139
|
+
translations: config.checks?.translations ?? false,
|
|
140
|
+
},
|
|
141
|
+
i18n: resolveSvedocsI18nConfig(config)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function resolveRssConfig(config) {
|
|
145
|
+
const input = config.seo?.rss;
|
|
146
|
+
if (!input)
|
|
147
|
+
return false;
|
|
148
|
+
const options = typeof input === 'object' ? input : {};
|
|
149
|
+
return {
|
|
150
|
+
title: options.title ?? `${config.site?.name ?? 'svedocs'} RSS`,
|
|
151
|
+
description: options.description ?? config.site?.description ?? 'SvelteKit-native documentation updates.',
|
|
152
|
+
limit: options.limit ?? 50,
|
|
153
|
+
...(options.locale ? { locale: options.locale } : {})
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function resolveCodeTheme(input) {
|
|
157
|
+
if (typeof input === 'string') {
|
|
158
|
+
return {
|
|
159
|
+
light: input,
|
|
160
|
+
dark: input
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
light: input?.light ?? 'github-light',
|
|
165
|
+
dark: input?.dark ?? 'github-dark'
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
export function isResolvedConfig(config) {
|
|
169
|
+
const candidate = config;
|
|
170
|
+
return Boolean(candidate
|
|
171
|
+
&& Array.isArray(candidate.content?.include)
|
|
172
|
+
&& Array.isArray(candidate.content?.exclude)
|
|
173
|
+
&& typeof candidate.search?.enabled === 'boolean'
|
|
174
|
+
&& typeof candidate.ai?.enabled === 'boolean'
|
|
175
|
+
&& typeof candidate.theme?.fonts?.sans === 'string'
|
|
176
|
+
&& typeof candidate.theme?.brand?.label === 'string'
|
|
177
|
+
&& typeof candidate.cloudflare?.compatibilityDate === 'string');
|
|
178
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SvedocsConfig } from '../config.js';
|
|
2
|
+
import type { SvedocsContentManifest, SvedocsResolvedConfig } from './types.js';
|
|
3
|
+
export declare function loadSvedocsContent(options?: {
|
|
4
|
+
projectRoot?: string;
|
|
5
|
+
config?: SvedocsConfig | SvedocsResolvedConfig;
|
|
6
|
+
}): Promise<SvedocsContentManifest>;
|
|
7
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/core/content.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAQlD,OAAO,KAAK,EAAE,sBAAsB,EAAe,qBAAqB,EAA0E,MAAM,YAAY,CAAC;AAYrK,wBAAsB,kBAAkB,CAAC,OAAO,GAAE;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,aAAa,GAAG,qBAAqB,CAAC;CAC3C,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA0CvC"}
|