@agenetix/docs 1.0.0

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.
Files changed (189) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +282 -0
  3. package/dist/components/BlogCard.d.ts +7 -0
  4. package/dist/components/BlogCard.d.ts.map +1 -0
  5. package/dist/components/BlogCard.js +10 -0
  6. package/dist/components/BlogCard.js.map +1 -0
  7. package/dist/components/BlogCategories.d.ts +8 -0
  8. package/dist/components/BlogCategories.d.ts.map +1 -0
  9. package/dist/components/BlogCategories.js +23 -0
  10. package/dist/components/BlogCategories.js.map +1 -0
  11. package/dist/components/BlogDirectoryPage.d.ts +10 -0
  12. package/dist/components/BlogDirectoryPage.d.ts.map +1 -0
  13. package/dist/components/BlogDirectoryPage.js +9 -0
  14. package/dist/components/BlogDirectoryPage.js.map +1 -0
  15. package/dist/components/BlogPagination.d.ts +10 -0
  16. package/dist/components/BlogPagination.d.ts.map +1 -0
  17. package/dist/components/BlogPagination.js +23 -0
  18. package/dist/components/BlogPagination.js.map +1 -0
  19. package/dist/components/BlogPostPage.d.ts +11 -0
  20. package/dist/components/BlogPostPage.d.ts.map +1 -0
  21. package/dist/components/BlogPostPage.js +17 -0
  22. package/dist/components/BlogPostPage.js.map +1 -0
  23. package/dist/components/BlogSearch.d.ts +7 -0
  24. package/dist/components/BlogSearch.d.ts.map +1 -0
  25. package/dist/components/BlogSearch.js +5 -0
  26. package/dist/components/BlogSearch.js.map +1 -0
  27. package/dist/components/CopyPageButton.d.ts +4 -0
  28. package/dist/components/CopyPageButton.d.ts.map +1 -0
  29. package/dist/components/CopyPageButton.js +71 -0
  30. package/dist/components/CopyPageButton.js.map +1 -0
  31. package/dist/components/DocsHomePage.d.ts +12 -0
  32. package/dist/components/DocsHomePage.d.ts.map +1 -0
  33. package/dist/components/DocsHomePage.js +45 -0
  34. package/dist/components/DocsHomePage.js.map +1 -0
  35. package/dist/components/DocsLayout.d.ts +3 -0
  36. package/dist/components/DocsLayout.d.ts.map +1 -0
  37. package/dist/components/DocsLayout.js +6 -0
  38. package/dist/components/DocsLayout.js.map +1 -0
  39. package/dist/components/DocsPage.d.ts +14 -0
  40. package/dist/components/DocsPage.d.ts.map +1 -0
  41. package/dist/components/DocsPage.js +16 -0
  42. package/dist/components/DocsPage.js.map +1 -0
  43. package/dist/components/DocsPageMobileToc.d.ts +6 -0
  44. package/dist/components/DocsPageMobileToc.d.ts.map +1 -0
  45. package/dist/components/DocsPageMobileToc.js +15 -0
  46. package/dist/components/DocsPageMobileToc.js.map +1 -0
  47. package/dist/components/DocsSearch.d.ts +8 -0
  48. package/dist/components/DocsSearch.d.ts.map +1 -0
  49. package/dist/components/DocsSearch.js +44 -0
  50. package/dist/components/DocsSearch.js.map +1 -0
  51. package/dist/components/DocsSearchCommand.d.ts +9 -0
  52. package/dist/components/DocsSearchCommand.d.ts.map +1 -0
  53. package/dist/components/DocsSearchCommand.js +43 -0
  54. package/dist/components/DocsSearchCommand.js.map +1 -0
  55. package/dist/components/DocsSearchPalette.d.ts +11 -0
  56. package/dist/components/DocsSearchPalette.d.ts.map +1 -0
  57. package/dist/components/DocsSearchPalette.js +28 -0
  58. package/dist/components/DocsSearchPalette.js.map +1 -0
  59. package/dist/components/DocsSearchResults.d.ts +13 -0
  60. package/dist/components/DocsSearchResults.d.ts.map +1 -0
  61. package/dist/components/DocsSearchResults.js +26 -0
  62. package/dist/components/DocsSearchResults.js.map +1 -0
  63. package/dist/components/DocsSearchTrigger.d.ts +6 -0
  64. package/dist/components/DocsSearchTrigger.d.ts.map +1 -0
  65. package/dist/components/DocsSearchTrigger.js +7 -0
  66. package/dist/components/DocsSearchTrigger.js.map +1 -0
  67. package/dist/components/DocsShell.d.ts +3 -0
  68. package/dist/components/DocsShell.d.ts.map +1 -0
  69. package/dist/components/DocsShell.js +98 -0
  70. package/dist/components/DocsShell.js.map +1 -0
  71. package/dist/components/DocsSidebar.d.ts +10 -0
  72. package/dist/components/DocsSidebar.d.ts.map +1 -0
  73. package/dist/components/DocsSidebar.js +48 -0
  74. package/dist/components/DocsSidebar.js.map +1 -0
  75. package/dist/components/DocsToc.d.ts +6 -0
  76. package/dist/components/DocsToc.d.ts.map +1 -0
  77. package/dist/components/DocsToc.js +42 -0
  78. package/dist/components/DocsToc.js.map +1 -0
  79. package/dist/components/HeadingLinks.d.ts +2 -0
  80. package/dist/components/HeadingLinks.d.ts.map +1 -0
  81. package/dist/components/HeadingLinks.js +54 -0
  82. package/dist/components/HeadingLinks.js.map +1 -0
  83. package/dist/components/MobileDocsChrome.d.ts +9 -0
  84. package/dist/components/MobileDocsChrome.d.ts.map +1 -0
  85. package/dist/components/MobileDocsChrome.js +6 -0
  86. package/dist/components/MobileDocsChrome.js.map +1 -0
  87. package/dist/components/StickyAside.d.ts +7 -0
  88. package/dist/components/StickyAside.d.ts.map +1 -0
  89. package/dist/components/StickyAside.js +5 -0
  90. package/dist/components/StickyAside.js.map +1 -0
  91. package/dist/components/blog-utils.d.ts +8 -0
  92. package/dist/components/blog-utils.d.ts.map +1 -0
  93. package/dist/components/blog-utils.js +28 -0
  94. package/dist/components/blog-utils.js.map +1 -0
  95. package/dist/components/mdx/Accordion.d.ts +13 -0
  96. package/dist/components/mdx/Accordion.d.ts.map +1 -0
  97. package/dist/components/mdx/Accordion.js +8 -0
  98. package/dist/components/mdx/Accordion.js.map +1 -0
  99. package/dist/components/mdx/Banner.d.ts +12 -0
  100. package/dist/components/mdx/Banner.d.ts.map +1 -0
  101. package/dist/components/mdx/Banner.js +10 -0
  102. package/dist/components/mdx/Banner.js.map +1 -0
  103. package/dist/components/mdx/Callout.d.ts +9 -0
  104. package/dist/components/mdx/Callout.d.ts.map +1 -0
  105. package/dist/components/mdx/Callout.js +11 -0
  106. package/dist/components/mdx/Callout.js.map +1 -0
  107. package/dist/components/mdx/Card.d.ts +16 -0
  108. package/dist/components/mdx/Card.d.ts.map +1 -0
  109. package/dist/components/mdx/Card.js +13 -0
  110. package/dist/components/mdx/Card.js.map +1 -0
  111. package/dist/components/mdx/CodeBlock.d.ts +11 -0
  112. package/dist/components/mdx/CodeBlock.d.ts.map +1 -0
  113. package/dist/components/mdx/CodeBlock.js +61 -0
  114. package/dist/components/mdx/CodeBlock.js.map +1 -0
  115. package/dist/components/mdx/CopyCodeButton.d.ts +4 -0
  116. package/dist/components/mdx/CopyCodeButton.d.ts.map +1 -0
  117. package/dist/components/mdx/CopyCodeButton.js +18 -0
  118. package/dist/components/mdx/CopyCodeButton.js.map +1 -0
  119. package/dist/components/mdx/Files.d.ts +19 -0
  120. package/dist/components/mdx/Files.d.ts.map +1 -0
  121. package/dist/components/mdx/Files.js +11 -0
  122. package/dist/components/mdx/Files.js.map +1 -0
  123. package/dist/components/mdx/InlineToc.d.ts +12 -0
  124. package/dist/components/mdx/InlineToc.d.ts.map +1 -0
  125. package/dist/components/mdx/InlineToc.js +26 -0
  126. package/dist/components/mdx/InlineToc.js.map +1 -0
  127. package/dist/components/mdx/Mermaid.d.ts +9 -0
  128. package/dist/components/mdx/Mermaid.d.ts.map +1 -0
  129. package/dist/components/mdx/Mermaid.js +63 -0
  130. package/dist/components/mdx/Mermaid.js.map +1 -0
  131. package/dist/components/mdx/Steps.d.ts +12 -0
  132. package/dist/components/mdx/Steps.d.ts.map +1 -0
  133. package/dist/components/mdx/Steps.js +8 -0
  134. package/dist/components/mdx/Steps.js.map +1 -0
  135. package/dist/components/mdx/Tabs.d.ts +22 -0
  136. package/dist/components/mdx/Tabs.d.ts.map +1 -0
  137. package/dist/components/mdx/Tabs.js +27 -0
  138. package/dist/components/mdx/Tabs.js.map +1 -0
  139. package/dist/components/mdx/index.d.ts +11 -0
  140. package/dist/components/mdx/index.d.ts.map +1 -0
  141. package/dist/components/mdx/index.js +11 -0
  142. package/dist/components/mdx/index.js.map +1 -0
  143. package/dist/components/mdx/lazy.d.ts +11 -0
  144. package/dist/components/mdx/lazy.d.ts.map +1 -0
  145. package/dist/components/mdx/lazy.js +9 -0
  146. package/dist/components/mdx/lazy.js.map +1 -0
  147. package/dist/components/useDocsSearch.d.ts +27 -0
  148. package/dist/components/useDocsSearch.d.ts.map +1 -0
  149. package/dist/components/useDocsSearch.js +119 -0
  150. package/dist/components/useDocsSearch.js.map +1 -0
  151. package/dist/index.d.ts +33 -0
  152. package/dist/index.d.ts.map +1 -0
  153. package/dist/index.js +33 -0
  154. package/dist/index.js.map +1 -0
  155. package/dist/mdx.d.ts +14 -0
  156. package/dist/mdx.d.ts.map +1 -0
  157. package/dist/mdx.js +107 -0
  158. package/dist/mdx.js.map +1 -0
  159. package/dist/server/blog.d.ts +3 -0
  160. package/dist/server/blog.d.ts.map +1 -0
  161. package/dist/server/blog.js +552 -0
  162. package/dist/server/blog.js.map +1 -0
  163. package/dist/server/docs.d.ts +5 -0
  164. package/dist/server/docs.d.ts.map +1 -0
  165. package/dist/server/docs.js +389 -0
  166. package/dist/server/docs.js.map +1 -0
  167. package/dist/server/search.d.ts +3 -0
  168. package/dist/server/search.d.ts.map +1 -0
  169. package/dist/server/search.js +216 -0
  170. package/dist/server/search.js.map +1 -0
  171. package/dist/styles.css +3337 -0
  172. package/dist/theme-provider.d.ts +19 -0
  173. package/dist/theme-provider.d.ts.map +1 -0
  174. package/dist/theme-provider.js +54 -0
  175. package/dist/theme-provider.js.map +1 -0
  176. package/dist/theme.d.ts +11 -0
  177. package/dist/theme.d.ts.map +1 -0
  178. package/dist/theme.js +602 -0
  179. package/dist/theme.js.map +1 -0
  180. package/dist/types.d.ts +379 -0
  181. package/dist/types.d.ts.map +1 -0
  182. package/dist/types.js +2 -0
  183. package/dist/types.js.map +1 -0
  184. package/dist/utils.d.ts +34 -0
  185. package/dist/utils.d.ts.map +1 -0
  186. package/dist/utils.js +85 -0
  187. package/dist/utils.js.map +1 -0
  188. package/package.json +133 -0
  189. package/styles.css +1 -0
package/dist/mdx.js ADDED
@@ -0,0 +1,107 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { isValidElement } from "react";
3
+ import { MDXRemote } from "next-mdx-remote/rsc";
4
+ import rehypePrettyCode from "rehype-pretty-code";
5
+ import remarkGfm from "remark-gfm";
6
+ import { slugifyHeading } from "./utils";
7
+ import { Banner, Callout, Card, CardGrid, CodeBlock, File, Files, Folder, InlineToc, Pre, Step, Steps, } from "./components/mdx";
8
+ import { LazyAccordion, LazyAccordionItem, LazyMermaid, LazyTabs, LazyTabsContent, LazyTabsList, LazyTabsTrigger, } from "./components/mdx/lazy";
9
+ const prettyCodeOptions = {
10
+ theme: {
11
+ light: "github-light",
12
+ dark: "github-dark-default",
13
+ },
14
+ keepBackground: false,
15
+ defaultLang: {
16
+ block: "plaintext",
17
+ },
18
+ };
19
+ export async function DocsMdx({ entry, content, components }) {
20
+ const source = content ?? entry?.content ?? "";
21
+ return (_jsx("div", { className: "emcydocs-prose", children: _jsx(MDXRemote, { source: source, options: {
22
+ mdxOptions: {
23
+ remarkPlugins: [remarkGfm],
24
+ rehypePlugins: [[rehypePrettyCode, prettyCodeOptions]],
25
+ },
26
+ blockJS: false,
27
+ blockDangerousJS: true,
28
+ }, components: {
29
+ ...getDefaultMdxComponents(),
30
+ ...components,
31
+ } }) }));
32
+ }
33
+ export function getDefaultMdxComponents() {
34
+ return {
35
+ ...getCoreMdxComponents(),
36
+ ...getInteractiveMdxComponents(),
37
+ };
38
+ }
39
+ export function getCoreMdxComponents() {
40
+ return {
41
+ h1: createHeadingComponent("h1"),
42
+ h2: createHeadingComponent("h2"),
43
+ h3: createHeadingComponent("h3"),
44
+ h4: createHeadingComponent("h4"),
45
+ Banner,
46
+ Callout,
47
+ Card,
48
+ CardGrid,
49
+ CodeBlock,
50
+ File,
51
+ Files,
52
+ Folder,
53
+ InlineToc,
54
+ pre: Pre,
55
+ figure: PrettyCodeFigure,
56
+ Step,
57
+ Steps,
58
+ };
59
+ }
60
+ /** Code-split client widgets (Mermaid, tabs, accordion). */
61
+ export function getInteractiveMdxComponents() {
62
+ return {
63
+ Accordion: LazyAccordion,
64
+ AccordionItem: LazyAccordionItem,
65
+ Mermaid: LazyMermaid,
66
+ Tabs: LazyTabs,
67
+ TabsContent: LazyTabsContent,
68
+ TabsList: LazyTabsList,
69
+ TabsTrigger: LazyTabsTrigger,
70
+ };
71
+ }
72
+ function PrettyCodeFigure({ children, ...props }) {
73
+ if ("data-rehype-pretty-code-figure" in props && isValidElement(children)) {
74
+ return children;
75
+ }
76
+ return _jsx("figure", { ...props, children: children });
77
+ }
78
+ function createHeadingComponent(tag) {
79
+ return function DocsHeading({ children, id, className, ...props }) {
80
+ const text = collectText(children);
81
+ const headingId = id || slugifyHeading(text);
82
+ const Tag = tag;
83
+ return (_jsxs(Tag, { id: headingId, className: [
84
+ "emcydocs-heading",
85
+ `emcydocs-heading-${tag}`,
86
+ className ?? "",
87
+ ]
88
+ .filter(Boolean)
89
+ .join(" "), ...props, children: [_jsx("span", { children: children }), _jsx("a", { href: `#${headingId}`, className: "emcydocs-heading-anchor", "data-docs-anchor": true, "aria-label": `Copy link to ${text}`, children: "#" })] }));
90
+ };
91
+ }
92
+ function collectText(node) {
93
+ if (node === null || node === undefined || typeof node === "boolean") {
94
+ return "";
95
+ }
96
+ if (typeof node === "string" || typeof node === "number") {
97
+ return `${node}`;
98
+ }
99
+ if (Array.isArray(node)) {
100
+ return node.map(collectText).join("");
101
+ }
102
+ if (typeof node === "object" && "props" in node) {
103
+ return collectText(node.props.children);
104
+ }
105
+ return "";
106
+ }
107
+ //# sourceMappingURL=mdx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mdx.js","sourceRoot":"","sources":["../src/mdx.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { BlogSource, BlogSourceConfig } from "../types";
2
+ export declare function createBlogSource(input: BlogSourceConfig): BlogSource;
3
+ //# sourceMappingURL=blog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blog.d.ts","sourceRoot":"","sources":["../../src/server/blog.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAQV,UAAU,EACV,gBAAgB,EAGjB,MAAM,UAAU,CAAC;AA+ClB,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,GAAG,UAAU,CAsMpE"}
@@ -0,0 +1,552 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import matter from "gray-matter";
4
+ import { buildBlogHref, calculateReadingTimeMinutes, humanizeSlug, normalizeBasePath, slugifyHeading, stripMarkdown, } from "../utils";
5
+ import { extractHeadings } from "./docs";
6
+ export function createBlogSource(input) {
7
+ const config = {
8
+ contentDir: path.resolve(input.contentDir),
9
+ basePath: normalizeBasePath(input.basePath),
10
+ defaultLocale: input.defaultLocale ?? "en",
11
+ locales: Array.from(new Set(input.locales?.length ? input.locales : ["en"])),
12
+ hideDefaultLocaleInUrl: input.hideDefaultLocaleInUrl ?? true,
13
+ siteTitle: input.siteTitle,
14
+ titleSuffix: input.titleSuffix ?? input.siteTitle,
15
+ searchLimit: input.searchLimit ?? 8,
16
+ };
17
+ if (!config.locales.includes(config.defaultLocale)) {
18
+ config.locales.unshift(config.defaultLocale);
19
+ }
20
+ let contentRecords = null;
21
+ const readRecords = () => {
22
+ if (!contentRecords) {
23
+ contentRecords = discoverContentRecords(config.contentDir, config.locales);
24
+ }
25
+ return contentRecords;
26
+ };
27
+ const materializeEntries = (locale) => readRecords()
28
+ .map((record) => materializeRecord(record, locale, config))
29
+ .filter((entry) => entry !== null)
30
+ .sort(compareBlogEntries);
31
+ const getAllEntries = (locale = config.defaultLocale) => materializeEntries(locale);
32
+ const getEntry = (slug, locale = config.defaultLocale) => getAllEntries(locale).find((entry) => entry.slug === slug) ?? null;
33
+ const getCategories = (locale = config.defaultLocale) => Array.from(new Set(getAllEntries(locale).map((entry) => entry.category)))
34
+ .filter(Boolean)
35
+ .sort((left, right) => left.localeCompare(right));
36
+ const getHref = (slug, locale = config.defaultLocale) => buildBlogHref({
37
+ basePath: config.basePath,
38
+ slug,
39
+ locale,
40
+ defaultLocale: config.defaultLocale,
41
+ hideDefaultLocaleInUrl: config.hideDefaultLocaleInUrl,
42
+ });
43
+ const search = (query, locale = config.defaultLocale) => {
44
+ const results = rankBlogEntries(getAllEntries(locale), query);
45
+ return {
46
+ query: query.trim(),
47
+ total: results.length,
48
+ results: results.slice(0, config.searchLimit).map(({ score: _score, ...result }) => result),
49
+ };
50
+ };
51
+ const getDirectory = (query = {}) => {
52
+ const locale = query.locale ?? config.defaultLocale;
53
+ const trimmedQuery = query.query?.trim() ?? "";
54
+ const selectedCategory = query.category?.trim() || "all";
55
+ const pageSize = Math.max(1, query.pageSize ?? 9);
56
+ const page = Math.max(1, query.page ?? 1);
57
+ const categories = getCategories(locale);
58
+ const categoryFiltered = selectedCategory === "all"
59
+ ? getAllEntries(locale)
60
+ : getAllEntries(locale).filter((entry) => entry.category === selectedCategory);
61
+ const filteredItems = trimmedQuery
62
+ ? rankBlogEntries(categoryFiltered, trimmedQuery).map((result) => {
63
+ const entry = categoryFiltered.find((candidate) => candidate.slug === result.slug);
64
+ return entry ? stripBlogEntry(entry) : null;
65
+ }).filter((entry) => entry !== null)
66
+ : categoryFiltered.map(stripBlogEntry);
67
+ const totalItems = filteredItems.length;
68
+ const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
69
+ const safePage = Math.min(page, totalPages);
70
+ const startIndex = (safePage - 1) * pageSize;
71
+ return {
72
+ query: trimmedQuery,
73
+ selectedCategory,
74
+ categories,
75
+ page: safePage,
76
+ pageSize,
77
+ totalItems,
78
+ totalPages,
79
+ items: filteredItems.slice(startIndex, startIndex + pageSize),
80
+ };
81
+ };
82
+ const getSuggestedEntries = (slug, options = {}, locale = config.defaultLocale) => {
83
+ const entry = getEntry(slug, locale);
84
+ if (!entry) {
85
+ return [];
86
+ }
87
+ const limit = Math.max(1, options.limit ?? 3);
88
+ const strategy = options.strategy ?? "related";
89
+ const allEntries = getAllEntries(locale).filter((candidate) => candidate.slug !== slug);
90
+ if (strategy === "recent") {
91
+ return allEntries.slice(0, limit).map(stripBlogEntry);
92
+ }
93
+ const relatedPool = rankRelatedEntries(entry, allEntries);
94
+ if (strategy === "manual") {
95
+ const selected = new Map();
96
+ for (const relatedSlug of entry.relatedSlugs) {
97
+ if (selected.size >= limit) {
98
+ break;
99
+ }
100
+ const match = allEntries.find((candidate) => candidate.slug === relatedSlug);
101
+ if (match) {
102
+ selected.set(match.slug, stripBlogEntry(match));
103
+ }
104
+ }
105
+ for (const candidate of relatedPool) {
106
+ if (selected.size >= limit) {
107
+ break;
108
+ }
109
+ if (!selected.has(candidate.slug)) {
110
+ selected.set(candidate.slug, stripBlogEntry(candidate));
111
+ }
112
+ }
113
+ return Array.from(selected.values()).slice(0, limit);
114
+ }
115
+ return relatedPool.slice(0, limit).map(stripBlogEntry);
116
+ };
117
+ const getMetadata = (slug, locale = config.defaultLocale) => {
118
+ if (!slug) {
119
+ return {
120
+ title: config.titleSuffix ? `Blog | ${config.titleSuffix}` : "Blog",
121
+ description: config.siteTitle
122
+ ? `Articles and updates from ${config.siteTitle}.`
123
+ : "Articles and updates.",
124
+ };
125
+ }
126
+ const entry = getEntry(slug, locale);
127
+ if (!entry) {
128
+ return {
129
+ title: config.siteTitle ? `${config.siteTitle} | Post Not Found` : "Post Not Found",
130
+ description: "The requested blog post could not be found.",
131
+ };
132
+ }
133
+ return {
134
+ title: config.titleSuffix ? `${entry.title} | ${config.titleSuffix}` : entry.title,
135
+ description: entry.description,
136
+ };
137
+ };
138
+ const getStaticParams = (locale = config.defaultLocale) => getAllEntries(locale).map((entry) => ({ slug: entry.slug }));
139
+ const getLocaleStaticParams = () => config.locales
140
+ .filter((locale) => locale !== config.defaultLocale)
141
+ .flatMap((locale) => getAllEntries(locale).map((entry) => ({
142
+ locale,
143
+ slug: entry.slug,
144
+ })));
145
+ return {
146
+ config,
147
+ getSupportedLocales: () => [...config.locales],
148
+ getDefaultLocale: () => config.defaultLocale,
149
+ getAllEntries,
150
+ getEntry,
151
+ getCategories,
152
+ getDirectory,
153
+ search,
154
+ getSuggestedEntries,
155
+ getHref,
156
+ getMetadata,
157
+ getStaticParams,
158
+ getLocaleStaticParams,
159
+ };
160
+ }
161
+ function discoverContentRecords(contentDir, locales) {
162
+ if (!fs.existsSync(contentDir)) {
163
+ return [];
164
+ }
165
+ return fs
166
+ .readdirSync(contentDir, { withFileTypes: true })
167
+ .flatMap((entry) => {
168
+ const fullPath = path.join(contentDir, entry.name);
169
+ if (entry.isFile() && /\.(md|mdx)$/.test(entry.name)) {
170
+ return [
171
+ {
172
+ slug: entry.name.replace(/\.(md|mdx)$/, ""),
173
+ localizedFiles: new Map(),
174
+ legacyFile: fullPath,
175
+ },
176
+ ];
177
+ }
178
+ if (!entry.isDirectory()) {
179
+ return [];
180
+ }
181
+ const localizedFiles = new Map();
182
+ for (const file of fs.readdirSync(fullPath, { withFileTypes: true })) {
183
+ if (!file.isFile()) {
184
+ continue;
185
+ }
186
+ const match = file.name.match(/^([^.]+)\.(md|mdx)$/);
187
+ if (!match) {
188
+ continue;
189
+ }
190
+ const candidateLocale = match[1];
191
+ if (locales.includes(candidateLocale)) {
192
+ localizedFiles.set(candidateLocale, path.join(fullPath, file.name));
193
+ }
194
+ }
195
+ if (localizedFiles.size === 0) {
196
+ return [];
197
+ }
198
+ return [{ slug: entry.name, localizedFiles }];
199
+ })
200
+ .sort((left, right) => left.slug.localeCompare(right.slug));
201
+ }
202
+ function materializeRecord(record, requestedLocale, config) {
203
+ let filePath;
204
+ let contentLocale = requestedLocale;
205
+ const availableLocales = Array.from(record.localizedFiles.keys()).sort();
206
+ if (record.localizedFiles.size > 0) {
207
+ filePath =
208
+ record.localizedFiles.get(requestedLocale) ??
209
+ record.localizedFiles.get(config.defaultLocale) ??
210
+ availableLocales.map((locale) => record.localizedFiles.get(locale)).find(Boolean);
211
+ if (!filePath) {
212
+ return null;
213
+ }
214
+ contentLocale =
215
+ record.localizedFiles.get(requestedLocale) !== undefined
216
+ ? requestedLocale
217
+ : record.localizedFiles.get(config.defaultLocale) !== undefined
218
+ ? config.defaultLocale
219
+ : availableLocales[0];
220
+ }
221
+ else {
222
+ filePath = record.legacyFile;
223
+ contentLocale = config.defaultLocale;
224
+ }
225
+ if (!filePath) {
226
+ return null;
227
+ }
228
+ const fileContents = fs.readFileSync(filePath, "utf8");
229
+ const { data, content } = matter(fileContents);
230
+ const frontmatter = data;
231
+ const publishedAt = frontmatter.publishedAt || frontmatter.date || "";
232
+ const updatedAt = frontmatter.updatedAt || publishedAt;
233
+ const image = frontmatter.image || frontmatter.previewImage || frontmatter.imagePreview;
234
+ const authorImage = frontmatter.authorImage || frontmatter.authorPhoto;
235
+ const headings = extractHeadings(content);
236
+ return {
237
+ slug: record.slug,
238
+ href: buildBlogHref({
239
+ basePath: config.basePath,
240
+ slug: record.slug,
241
+ locale: requestedLocale,
242
+ defaultLocale: config.defaultLocale,
243
+ hideDefaultLocaleInUrl: config.hideDefaultLocaleInUrl,
244
+ }),
245
+ title: frontmatter.title || humanizeSlug(record.slug),
246
+ description: frontmatter.description || frontmatter.excerpt || "",
247
+ publishedAt,
248
+ updatedAt,
249
+ author: frontmatter.author || "Unknown author",
250
+ authorRole: frontmatter.authorRole,
251
+ authorImage,
252
+ image,
253
+ imageAlt: frontmatter.imageAlt,
254
+ category: frontmatter.category || "General",
255
+ tags: normalizeStringArray(frontmatter.tags),
256
+ readingTimeMinutes: calculateReadingTimeMinutes(content),
257
+ locale: requestedLocale,
258
+ contentLocale,
259
+ availableLocales: availableLocales.length > 0 ? availableLocales : [config.defaultLocale],
260
+ content,
261
+ headings,
262
+ filePath,
263
+ relatedSlugs: normalizeStringArray(frontmatter.relatedSlugs),
264
+ };
265
+ }
266
+ function stripBlogEntry(entry) {
267
+ const { content: _content, headings: _headings, filePath: _filePath, relatedSlugs: _relatedSlugs, ...meta } = entry;
268
+ return meta;
269
+ }
270
+ function normalizeStringArray(value) {
271
+ if (Array.isArray(value)) {
272
+ return value.map((item) => item.trim()).filter(Boolean);
273
+ }
274
+ if (typeof value === "string") {
275
+ return value
276
+ .split(",")
277
+ .map((item) => item.trim())
278
+ .filter(Boolean);
279
+ }
280
+ return [];
281
+ }
282
+ function compareBlogEntries(left, right) {
283
+ const dateDelta = toDateValue(right.publishedAt) - toDateValue(left.publishedAt);
284
+ if (dateDelta !== 0) {
285
+ return dateDelta;
286
+ }
287
+ return left.title.localeCompare(right.title);
288
+ }
289
+ function rankRelatedEntries(current, candidates) {
290
+ const currentTags = new Set(current.tags.map((tag) => tag.toLowerCase()));
291
+ return [...candidates].sort((left, right) => {
292
+ const leftCategory = Number(left.category === current.category);
293
+ const rightCategory = Number(right.category === current.category);
294
+ if (rightCategory !== leftCategory) {
295
+ return rightCategory - leftCategory;
296
+ }
297
+ const leftSharedTags = left.tags.filter((tag) => currentTags.has(tag.toLowerCase())).length;
298
+ const rightSharedTags = right.tags.filter((tag) => currentTags.has(tag.toLowerCase())).length;
299
+ if (rightSharedTags !== leftSharedTags) {
300
+ return rightSharedTags - leftSharedTags;
301
+ }
302
+ const dateDelta = toDateValue(right.publishedAt) - toDateValue(left.publishedAt);
303
+ if (dateDelta !== 0) {
304
+ return dateDelta;
305
+ }
306
+ return left.title.localeCompare(right.title);
307
+ });
308
+ }
309
+ function rankBlogEntries(entries, query) {
310
+ const trimmedQuery = query.trim();
311
+ if (trimmedQuery.length < 2) {
312
+ return [];
313
+ }
314
+ const normalizedQuery = trimmedQuery.toLowerCase();
315
+ const queryTerms = getQueryTerms(trimmedQuery);
316
+ return entries
317
+ .map((entry) => scoreBlogEntry(entry, normalizedQuery, queryTerms))
318
+ .filter((result) => result !== null)
319
+ .sort((left, right) => {
320
+ if (right.score !== left.score) {
321
+ return right.score - left.score;
322
+ }
323
+ const dateDelta = toDateValue(right.publishedAt) - toDateValue(left.publishedAt);
324
+ if (dateDelta !== 0) {
325
+ return dateDelta;
326
+ }
327
+ return left.title.localeCompare(right.title);
328
+ });
329
+ }
330
+ function scoreBlogEntry(entry, normalizedQuery, queryTerms) {
331
+ const title = entry.title.trim();
332
+ const description = entry.description.trim();
333
+ const category = entry.category.trim();
334
+ const tags = entry.tags.join(" ");
335
+ const contentText = stripMarkdown(entry.content);
336
+ const normalizedTitle = title.toLowerCase();
337
+ const normalizedDescription = description.toLowerCase();
338
+ const normalizedCategory = category.toLowerCase();
339
+ const normalizedTags = tags.toLowerCase();
340
+ const normalizedContent = contentText.toLowerCase();
341
+ let score = 0;
342
+ const matchedFields = new Set();
343
+ if (normalizedTitle.includes(normalizedQuery)) {
344
+ score += 160;
345
+ matchedFields.add("title");
346
+ }
347
+ if (normalizedDescription.includes(normalizedQuery)) {
348
+ score += 96;
349
+ matchedFields.add("description");
350
+ }
351
+ if (normalizedCategory.includes(normalizedQuery)) {
352
+ score += 88;
353
+ matchedFields.add("category");
354
+ }
355
+ if (normalizedTags.includes(normalizedQuery)) {
356
+ score += 80;
357
+ matchedFields.add("tags");
358
+ }
359
+ if (normalizedContent.includes(normalizedQuery)) {
360
+ score += 40;
361
+ matchedFields.add("content");
362
+ }
363
+ let matchedTermCount = 0;
364
+ for (const term of queryTerms) {
365
+ const titleMatches = countMatches(normalizedTitle, term);
366
+ const descriptionMatches = countMatches(normalizedDescription, term);
367
+ const categoryMatches = countMatches(normalizedCategory, term);
368
+ const tagMatches = countMatches(normalizedTags, term);
369
+ const contentMatches = Math.min(6, countMatches(normalizedContent, term));
370
+ if (titleMatches || descriptionMatches || categoryMatches || tagMatches || contentMatches) {
371
+ matchedTermCount += 1;
372
+ }
373
+ if (titleMatches > 0) {
374
+ score += 32 + (titleMatches - 1) * 10;
375
+ matchedFields.add("title");
376
+ }
377
+ if (descriptionMatches > 0) {
378
+ score += 18 + (descriptionMatches - 1) * 5;
379
+ matchedFields.add("description");
380
+ }
381
+ if (categoryMatches > 0) {
382
+ score += 20 + (categoryMatches - 1) * 5;
383
+ matchedFields.add("category");
384
+ }
385
+ if (tagMatches > 0) {
386
+ score += 18 + (tagMatches - 1) * 4;
387
+ matchedFields.add("tags");
388
+ }
389
+ if (contentMatches > 0) {
390
+ score += 8 + (contentMatches - 1) * 2;
391
+ matchedFields.add("content");
392
+ }
393
+ }
394
+ if (matchedFields.size === 0) {
395
+ return null;
396
+ }
397
+ if (matchedTermCount === queryTerms.length) {
398
+ score += 24;
399
+ }
400
+ const section = findMatchingSection(entry.content, entry.headings, normalizedQuery);
401
+ const snippet = createSnippet({
402
+ contentText: section ? stripMarkdown(section.content) : contentText,
403
+ description,
404
+ normalizedQuery,
405
+ queryTerms,
406
+ });
407
+ return {
408
+ slug: entry.slug,
409
+ href: section ? `${entry.href}#${section.anchor}` : entry.href,
410
+ title,
411
+ description,
412
+ category,
413
+ tags: entry.tags,
414
+ snippet,
415
+ matchedFields: Array.from(matchedFields),
416
+ locale: entry.locale,
417
+ contentLocale: entry.contentLocale,
418
+ publishedAt: entry.publishedAt,
419
+ updatedAt: entry.updatedAt,
420
+ sectionTitle: section?.heading,
421
+ sectionAnchor: section?.anchor,
422
+ score,
423
+ };
424
+ }
425
+ function findMatchingSection(content, headings, normalizedQuery) {
426
+ const sections = extractSections(content, headings);
427
+ if (sections.length === 0) {
428
+ return undefined;
429
+ }
430
+ const matched = sections
431
+ .map((section) => ({
432
+ section,
433
+ score: (section.heading.toLowerCase().includes(normalizedQuery) ? 40 : 0) +
434
+ (stripMarkdown(section.content).toLowerCase().includes(normalizedQuery) ? 16 : 0),
435
+ }))
436
+ .filter((candidate) => candidate.score > 0)
437
+ .sort((left, right) => right.score - left.score)[0];
438
+ return matched?.section;
439
+ }
440
+ function extractSections(content, headings) {
441
+ const sectionHeadings = headings.filter((heading) => heading.level >= 2 && heading.level <= 4);
442
+ if (sectionHeadings.length === 0) {
443
+ return [];
444
+ }
445
+ const lines = content.split("\n");
446
+ const located = sectionHeadings
447
+ .map((heading) => ({
448
+ heading,
449
+ index: lines.findIndex((line) => {
450
+ const normalizedLine = line.trim();
451
+ if (!normalizedLine) {
452
+ return false;
453
+ }
454
+ if (/^#{1,6}\s+/.test(normalizedLine)) {
455
+ return normalizedLine.replace(/^#{1,6}\s+/, "") === heading.text;
456
+ }
457
+ const htmlHeadingMatch = normalizedLine.match(/^<h[1-6][^>]*>(.*?)<\/h[1-6]>$/i);
458
+ if (htmlHeadingMatch) {
459
+ return stripMarkdown(htmlHeadingMatch[1]).trim() === heading.text;
460
+ }
461
+ return false;
462
+ }),
463
+ }))
464
+ .filter((item) => item.index >= 0);
465
+ return located.map((item, index) => {
466
+ const next = located[index + 1];
467
+ return {
468
+ heading: item.heading.text,
469
+ anchor: item.heading.id || slugifyHeading(item.heading.text),
470
+ content: lines.slice(item.index, next ? next.index : undefined).join("\n").trim(),
471
+ };
472
+ });
473
+ }
474
+ function createSnippet({ contentText, description, normalizedQuery, queryTerms, }) {
475
+ const fallbackText = description || contentText;
476
+ if (!contentText) {
477
+ return trimSnippet(fallbackText, 180);
478
+ }
479
+ const normalizedContent = contentText.toLowerCase();
480
+ const phraseIndex = normalizedContent.indexOf(normalizedQuery);
481
+ const termIndexes = queryTerms
482
+ .map((term) => normalizedContent.indexOf(term))
483
+ .filter((index) => index >= 0);
484
+ const matchIndex = phraseIndex >= 0
485
+ ? phraseIndex
486
+ : termIndexes.length > 0
487
+ ? Math.min(...termIndexes)
488
+ : -1;
489
+ if (matchIndex < 0) {
490
+ return trimSnippet(fallbackText, 180);
491
+ }
492
+ const preferredStart = Math.max(0, matchIndex - 92);
493
+ const preferredEnd = Math.min(contentText.length, matchIndex + 156);
494
+ const sentenceStart = findSnippetStart(contentText, preferredStart);
495
+ const sentenceEnd = findSnippetEnd(contentText, preferredEnd);
496
+ let snippet = contentText.slice(sentenceStart, sentenceEnd).trim();
497
+ if (sentenceStart > 0) {
498
+ snippet = `...${snippet}`;
499
+ }
500
+ if (sentenceEnd < contentText.length) {
501
+ snippet = `${snippet}...`;
502
+ }
503
+ return trimSnippet(snippet, 220);
504
+ }
505
+ function findSnippetStart(text, preferredStart) {
506
+ const punctuationIndex = Math.max(text.lastIndexOf(". ", preferredStart), text.lastIndexOf(": ", preferredStart), text.lastIndexOf("? ", preferredStart), text.lastIndexOf("! ", preferredStart));
507
+ return punctuationIndex >= 0 ? punctuationIndex + 2 : preferredStart;
508
+ }
509
+ function findSnippetEnd(text, preferredEnd) {
510
+ const punctuationMatches = [
511
+ text.indexOf(". ", preferredEnd),
512
+ text.indexOf("? ", preferredEnd),
513
+ text.indexOf("! ", preferredEnd),
514
+ ].filter((index) => index >= 0);
515
+ if (punctuationMatches.length === 0) {
516
+ return Math.min(text.length, preferredEnd);
517
+ }
518
+ return Math.min(...punctuationMatches) + 1;
519
+ }
520
+ function trimSnippet(value, maxLength) {
521
+ if (value.length <= maxLength) {
522
+ return value;
523
+ }
524
+ return `${value.slice(0, maxLength - 1).trimEnd()}...`;
525
+ }
526
+ function countMatches(value, term) {
527
+ if (!term) {
528
+ return 0;
529
+ }
530
+ let count = 0;
531
+ let index = 0;
532
+ while (index >= 0) {
533
+ index = value.indexOf(term, index);
534
+ if (index >= 0) {
535
+ count += 1;
536
+ index += term.length;
537
+ }
538
+ }
539
+ return count;
540
+ }
541
+ function getQueryTerms(query) {
542
+ return query
543
+ .toLowerCase()
544
+ .split(/\s+/)
545
+ .map((term) => term.trim())
546
+ .filter(Boolean);
547
+ }
548
+ function toDateValue(value) {
549
+ const timestamp = new Date(value).getTime();
550
+ return Number.isNaN(timestamp) ? 0 : timestamp;
551
+ }
552
+ //# sourceMappingURL=blog.js.map