@dominikcz/greg 0.9.27

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 (183) hide show
  1. package/README.md +397 -0
  2. package/bin/greg.js +241 -0
  3. package/bin/init.js +351 -0
  4. package/bin/templates/docs/getting-started.md +47 -0
  5. package/bin/templates/docs/index.md +11 -0
  6. package/bin/templates/greg.config.js +39 -0
  7. package/bin/templates/greg.config.ts +38 -0
  8. package/bin/templates/index.html +16 -0
  9. package/bin/templates/src/App.svelte +5 -0
  10. package/bin/templates/src/app.css +20 -0
  11. package/bin/templates/src/main.js +9 -0
  12. package/bin/templates/svelte.config.js +1 -0
  13. package/bin/templates/tsconfig.json +21 -0
  14. package/bin/templates/vite.config.js +23 -0
  15. package/docs/__partials/markdown/examples/basic.md +4 -0
  16. package/docs/__partials/markdown/examples/diff.md +10 -0
  17. package/docs/__partials/markdown/examples/focus.md +5 -0
  18. package/docs/__partials/markdown/examples/language-title.md +3 -0
  19. package/docs/__partials/markdown/examples/line-highlighting.md +5 -0
  20. package/docs/__partials/markdown/examples/line-numbers.md +5 -0
  21. package/docs/__partials/note.md +4 -0
  22. package/docs/guide/__shared-warning.md +4 -0
  23. package/docs/guide/asset-handling.md +88 -0
  24. package/docs/guide/deploying.md +162 -0
  25. package/docs/guide/getting-started.md +334 -0
  26. package/docs/guide/index.md +23 -0
  27. package/docs/guide/localization.md +290 -0
  28. package/docs/guide/markdown/code.md +95 -0
  29. package/docs/guide/markdown/components-and-mermaid.md +43 -0
  30. package/docs/guide/markdown/containers.md +110 -0
  31. package/docs/guide/markdown/header-anchors.md +34 -0
  32. package/docs/guide/markdown/includes.md +84 -0
  33. package/docs/guide/markdown/index.md +20 -0
  34. package/docs/guide/markdown/inline-attributes.md +21 -0
  35. package/docs/guide/markdown/links-and-toc.md +64 -0
  36. package/docs/guide/markdown/math.md +54 -0
  37. package/docs/guide/markdown/syntax-highlighting.md +75 -0
  38. package/docs/guide/routing.md +150 -0
  39. package/docs/guide/using-svelte.md +88 -0
  40. package/docs/guide/versioning.md +281 -0
  41. package/docs/incompatibilities.md +48 -0
  42. package/docs/index.md +43 -0
  43. package/docs/reference/badge.md +100 -0
  44. package/docs/reference/carbon-ads.md +46 -0
  45. package/docs/reference/code-group.md +126 -0
  46. package/docs/reference/home-page.md +232 -0
  47. package/docs/reference/index.md +18 -0
  48. package/docs/reference/markdowndocs.md +275 -0
  49. package/docs/reference/outline.md +79 -0
  50. package/docs/reference/search.md +263 -0
  51. package/docs/reference/steps.md +200 -0
  52. package/docs/reference/team-page.md +189 -0
  53. package/docs/reference/theme.md +150 -0
  54. package/fakeDocsGenerator/generate_docs.js +310 -0
  55. package/package.json +92 -0
  56. package/scripts/build-versions.js +609 -0
  57. package/scripts/generate-static.js +79 -0
  58. package/scripts/render-markdown.js +420 -0
  59. package/src/lib/MarkdownDocs/AiChat.svelte +936 -0
  60. package/src/lib/MarkdownDocs/BackToTop.svelte +68 -0
  61. package/src/lib/MarkdownDocs/Breadcrumb.svelte +68 -0
  62. package/src/lib/MarkdownDocs/DocsNavigation.svelte +149 -0
  63. package/src/lib/MarkdownDocs/DocsSiteHeader.svelte +758 -0
  64. package/src/lib/MarkdownDocs/DocsVersionSwitcher.svelte +103 -0
  65. package/src/lib/MarkdownDocs/MarkdownDocs.svelte +2115 -0
  66. package/src/lib/MarkdownDocs/MarkdownRenderer.svelte +487 -0
  67. package/src/lib/MarkdownDocs/Outline.svelte +238 -0
  68. package/src/lib/MarkdownDocs/PrevNext.svelte +115 -0
  69. package/src/lib/MarkdownDocs/SearchModal.svelte +1241 -0
  70. package/src/lib/MarkdownDocs/TreeView.svelte +32 -0
  71. package/src/lib/MarkdownDocs/TreeViewItem.svelte +219 -0
  72. package/src/lib/MarkdownDocs/VersionOutdatedNotice.svelte +72 -0
  73. package/src/lib/MarkdownDocs/__tests__/codeDirectives.test.js +54 -0
  74. package/src/lib/MarkdownDocs/__tests__/common.test.js +41 -0
  75. package/src/lib/MarkdownDocs/__tests__/docsExamplesLint.test.js +77 -0
  76. package/src/lib/MarkdownDocs/__tests__/fixtures/docs/markdown/__partial-basic.md +3 -0
  77. package/src/lib/MarkdownDocs/__tests__/fixtures/docs/markdown/snippet.js +9 -0
  78. package/src/lib/MarkdownDocs/__tests__/fixtures/includes/part.md +11 -0
  79. package/src/lib/MarkdownDocs/__tests__/fixtures/includes/wrapper.md +5 -0
  80. package/src/lib/MarkdownDocs/__tests__/fixtures/snippets/sample.js +8 -0
  81. package/src/lib/MarkdownDocs/__tests__/fixtures/snippets/sample.md +5 -0
  82. package/src/lib/MarkdownDocs/__tests__/helpers.js +67 -0
  83. package/src/lib/MarkdownDocs/__tests__/localeUtils.test.js +204 -0
  84. package/src/lib/MarkdownDocs/__tests__/markdown.test.js +704 -0
  85. package/src/lib/MarkdownDocs/__tests__/markdownRendererRuntime.test.js +65 -0
  86. package/src/lib/MarkdownDocs/__tests__/searchIndexBuilder.test.js +117 -0
  87. package/src/lib/MarkdownDocs/__tests__/sqliteStore.test.js +202 -0
  88. package/src/lib/MarkdownDocs/__tests__/useRouter.test.js +16 -0
  89. package/src/lib/MarkdownDocs/ai/adapters/customAdapter.js +14 -0
  90. package/src/lib/MarkdownDocs/ai/adapters/customAdapter.ts +43 -0
  91. package/src/lib/MarkdownDocs/ai/adapters/ollamaAdapter.js +81 -0
  92. package/src/lib/MarkdownDocs/ai/adapters/ollamaAdapter.ts +116 -0
  93. package/src/lib/MarkdownDocs/ai/adapters/openaiAdapter.js +92 -0
  94. package/src/lib/MarkdownDocs/ai/adapters/openaiAdapter.ts +137 -0
  95. package/src/lib/MarkdownDocs/ai/aiProvider.ts +31 -0
  96. package/src/lib/MarkdownDocs/ai/characters.js +52 -0
  97. package/src/lib/MarkdownDocs/ai/characters.ts +69 -0
  98. package/src/lib/MarkdownDocs/ai/chunkStore.ts +25 -0
  99. package/src/lib/MarkdownDocs/ai/chunker.js +85 -0
  100. package/src/lib/MarkdownDocs/ai/chunker.ts +135 -0
  101. package/src/lib/MarkdownDocs/ai/docLinker.js +26 -0
  102. package/src/lib/MarkdownDocs/ai/docLinker.ts +36 -0
  103. package/src/lib/MarkdownDocs/ai/promptBuilder.js +33 -0
  104. package/src/lib/MarkdownDocs/ai/promptBuilder.ts +53 -0
  105. package/src/lib/MarkdownDocs/ai/ragPipeline.js +54 -0
  106. package/src/lib/MarkdownDocs/ai/ragPipeline.ts +106 -0
  107. package/src/lib/MarkdownDocs/ai/stores/memoryStore.js +88 -0
  108. package/src/lib/MarkdownDocs/ai/stores/memoryStore.ts +112 -0
  109. package/src/lib/MarkdownDocs/ai/stores/sqliteStore.ts +372 -0
  110. package/src/lib/MarkdownDocs/ai/types.ts +71 -0
  111. package/src/lib/MarkdownDocs/aiServer.js +288 -0
  112. package/src/lib/MarkdownDocs/codeDirectives.js +191 -0
  113. package/src/lib/MarkdownDocs/codeFenceInfo.js +45 -0
  114. package/src/lib/MarkdownDocs/codeGroup.ts +46 -0
  115. package/src/lib/MarkdownDocs/common.ts +47 -0
  116. package/src/lib/MarkdownDocs/docsUtils.js +281 -0
  117. package/src/lib/MarkdownDocs/index.plugins.js +22 -0
  118. package/src/lib/MarkdownDocs/layouts/LayoutDoc.svelte +8 -0
  119. package/src/lib/MarkdownDocs/layouts/LayoutHome.svelte +58 -0
  120. package/src/lib/MarkdownDocs/layouts/LayoutPage.svelte +9 -0
  121. package/src/lib/MarkdownDocs/loadGregConfig.js +82 -0
  122. package/src/lib/MarkdownDocs/localeUtils.ts +682 -0
  123. package/src/lib/MarkdownDocs/markdownRendererRuntime.ts +314 -0
  124. package/src/lib/MarkdownDocs/mermaidThemes.js +319 -0
  125. package/src/lib/MarkdownDocs/navigationUtils.js +22 -0
  126. package/src/lib/MarkdownDocs/rehypeCodeGroup.js +326 -0
  127. package/src/lib/MarkdownDocs/rehypeCodeTitle.js +96 -0
  128. package/src/lib/MarkdownDocs/rehypeToc.js +170 -0
  129. package/src/lib/MarkdownDocs/remarkCodeMeta.js +22 -0
  130. package/src/lib/MarkdownDocs/remarkContainers.js +329 -0
  131. package/src/lib/MarkdownDocs/remarkCustomAnchors.js +42 -0
  132. package/src/lib/MarkdownDocs/remarkEscapeSvelte.js +33 -0
  133. package/src/lib/MarkdownDocs/remarkGlobalComponents.js +65 -0
  134. package/src/lib/MarkdownDocs/remarkImports.js +461 -0
  135. package/src/lib/MarkdownDocs/remarkImportsBrowser.js +349 -0
  136. package/src/lib/MarkdownDocs/remarkInlineAttrs.js +95 -0
  137. package/src/lib/MarkdownDocs/remarkMathToHtml.js +138 -0
  138. package/src/lib/MarkdownDocs/searchIndexBuilder.js +497 -0
  139. package/src/lib/MarkdownDocs/searchServer.js +263 -0
  140. package/src/lib/MarkdownDocs/treeViewTypes.ts +11 -0
  141. package/src/lib/MarkdownDocs/useRouter.svelte.ts +114 -0
  142. package/src/lib/MarkdownDocs/useSplitter.svelte.ts +33 -0
  143. package/src/lib/MarkdownDocs/versioningDefaults.js +20 -0
  144. package/src/lib/MarkdownDocs/vitePluginAiServer.js +204 -0
  145. package/src/lib/MarkdownDocs/vitePluginCopyDocs.js +153 -0
  146. package/src/lib/MarkdownDocs/vitePluginFrontmatter.js +109 -0
  147. package/src/lib/MarkdownDocs/vitePluginGregConfig.js +108 -0
  148. package/src/lib/MarkdownDocs/vitePluginSearchIndex.js +57 -0
  149. package/src/lib/MarkdownDocs/vitePluginSearchServer.js +190 -0
  150. package/src/lib/components/Badge.svelte +59 -0
  151. package/src/lib/components/Button.svelte +138 -0
  152. package/src/lib/components/CarbonAds.svelte +99 -0
  153. package/src/lib/components/CodeGroup.svelte +102 -0
  154. package/src/lib/components/Feature.svelte +209 -0
  155. package/src/lib/components/Features.svelte +123 -0
  156. package/src/lib/components/Hero.svelte +399 -0
  157. package/src/lib/components/Image.svelte +128 -0
  158. package/src/lib/components/Link.svelte +105 -0
  159. package/src/lib/components/SocialLink.svelte +84 -0
  160. package/src/lib/components/SocialLinks.svelte +33 -0
  161. package/src/lib/components/Steps.svelte +143 -0
  162. package/src/lib/components/TeamMember.svelte +273 -0
  163. package/src/lib/components/TeamMembers.svelte +81 -0
  164. package/src/lib/components/TeamPage.svelte +65 -0
  165. package/src/lib/components/TeamPageSection.svelte +108 -0
  166. package/src/lib/components/TeamPageTitle.svelte +89 -0
  167. package/src/lib/components/index.js +24 -0
  168. package/src/lib/portal/context.js +12 -0
  169. package/src/lib/portal/index.js +3 -0
  170. package/src/lib/portal/portal.svelte +14 -0
  171. package/src/lib/portal/slot.svelte +8 -0
  172. package/src/lib/scss/__code.scss +128 -0
  173. package/src/lib/scss/__containers.scss +99 -0
  174. package/src/lib/scss/__markdown.scss +447 -0
  175. package/src/lib/scss/__scrollbar.scss +60 -0
  176. package/src/lib/scss/__steps.scss +100 -0
  177. package/src/lib/scss/__theme.scss +238 -0
  178. package/src/lib/scss/__toc.scss +55 -0
  179. package/src/lib/scss/__utilities.scss +7 -0
  180. package/src/lib/scss/greg.scss +9 -0
  181. package/src/lib/spinner/spinner.svelte +42 -0
  182. package/svelte.config.js +146 -0
  183. package/types/index.d.ts +456 -0
@@ -0,0 +1,275 @@
1
+ ---
2
+ title: MarkdownDocs Component
3
+ ---
4
+
5
+ `MarkdownDocs` is the top-level component that wires together the entire
6
+ documentation engine: routing, sidebar navigation, the outline panel, search,
7
+ dark/light mode and Carbon Ads.
8
+
9
+ Mount it in `src/App.svelte`:
10
+
11
+ ```svelte
12
+ <script>
13
+ import MarkdownDocs from '@dominikcz/greg'
14
+ </script>
15
+
16
+ <MarkdownDocs srcDir="/" version="1.0.0" />
17
+ ```
18
+
19
+
20
+ ## Props
21
+
22
+ ### `locales` (via `greg.config.js`)
23
+
24
+ - **Type:** `Record<string, LocaleConfig>`
25
+ - **Location:** `greg.config.js` (not a direct `<MarkdownDocs>` prop)
26
+
27
+ Localization is supported through `greg.config.js`:
28
+
29
+ - locale keys like `'/'`, `'/pl/'`
30
+ - locale-specific `lang`, `title`
31
+ - optional locale `label` used in header language switcher
32
+ - locale-specific `themeConfig` keys:
33
+ `nav`, `sidebar`, `outline`, `lastUpdatedText`, `langMenuLabel`,
34
+ `sidebarMenuLabel`, `skipToContentLabel`, `returnToTopLabel`,
35
+ `darkModeSwitchLabel`, `lightModeSwitchTitle`, `darkModeSwitchTitle`,
36
+ `docFooter`, `siteTitle`, `logo`, `socialLinks`, `editLink`, `footer`, `aside`, `lastUpdated`
37
+
38
+ Language switcher behavior:
39
+
40
+ - appears in the header when two or more locales are defined
41
+ - with `i18nRouting: true` (default), preserves current relative page across locales
42
+ - with `i18nRouting: false`, switches directly to locale root
43
+ - falls back to target locale root when the mapped page does not exist
44
+
45
+ Locale paths are resolved under `srcDir`:
46
+
47
+ - if `srcDir = '/docs'`
48
+ - locale `'/'` maps to `'/docs'`
49
+ - locale `'/pl/'` maps to `'/docs/pl'`
50
+
51
+ ```js
52
+ export default {
53
+ <MarkdownDocs srcDir="/" version="1.0.0" />
54
+ i18nRouting: true,
55
+ locales: {
56
+ '/': {
57
+ lang: 'en-US',
58
+ title: 'Docs',
59
+ themeConfig: {
60
+ nav: [{ text: 'Guide', link: '/docs/guide' }],
61
+ sidebar: [{ text: 'Guide', auto: '/guide' }],
62
+ outline: [2, 3],
63
+ lastUpdatedText: 'Last updated:',
64
+ langMenuLabel: 'Change language',
65
+ sidebarMenuLabel: 'Menu',
66
+ skipToContentLabel: 'Skip to content',
67
+ returnToTopLabel: 'Return to top',
68
+ darkModeSwitchLabel: 'Appearance',
69
+ lightModeSwitchTitle: 'Switch to light theme',
70
+ darkModeSwitchTitle: 'Switch to dark theme',
71
+ docFooter: { prev: 'Previous', next: 'Next' },
72
+ srcDir: 'docs',
73
+ docsBase: '',
74
+ },
75
+ '/pl/': {
76
+ lang: 'pl-PL',
77
+ label: 'Polski',
78
+ title: 'Dokumentacja',
79
+ themeConfig: {
80
+ nav: [{ text: 'Guide', link: '/guide' }],
81
+ sidebar: [{ text: 'Przewodnik', auto: '/pl/guide' }],
82
+ outline: { level: [2, 3], label: 'Na tej stronie' },
83
+ lastUpdatedText: 'Zaktualizowano:',
84
+ langMenuLabel: 'Zmien jezyk',
85
+ sidebarMenuLabel: 'Menu',
86
+ skipToContentLabel: 'Przejdz do tresci',
87
+ returnToTopLabel: 'Wroc na gore',
88
+ darkModeSwitchLabel: 'Wyglad',
89
+ lightModeSwitchTitle: 'Przelacz na jasny motyw',
90
+ darkModeSwitchTitle: 'Przelacz na ciemny motyw',
91
+ docFooter: { prev: 'Poprzednia', next: 'Nastepna' },
92
+ },
93
+ },
94
+ },
95
+ }
96
+ ```
97
+
98
+ ### `srcDir`
99
+ nav: [{ text: 'Przewodnik', link: '/pl/guide' }],
100
+ - **Type:** `string`
101
+ - **Default:** `"/docs"`
102
+
103
+ URL prefix that maps to the `docs/` folder. Must match the `srcDir` value
104
+ passed to `vitePluginSearchIndex` in `vite.config.js`.
105
+
106
+ ```svelte
107
+ <MarkdownDocs srcDir="/documentation" version="1.0.0" />
108
+ ```
109
+
110
+ ### `version`
111
+
112
+ - **Type:** `string`
113
+ - **Default:** `""`
114
+
115
+ Version string displayed as a badge next to the site title in the header.
116
+ Pass the package version via Vite's `define`:
117
+
118
+ ```svelte
119
+ <!-- Assuming __VERSION__ is defined in vite.config.js -->
120
+ <MarkdownDocs srcDir="/" version={__VERSION__} />
121
+ ```
122
+ URL prefix used by `<MarkdownDocs>` routing.
123
+ In `greg.config.*` use top-level `docsBase` for this value.
124
+ Top-level `srcDir` is the physical docs folder (e.g. `docs`).
125
+ ### `mainTitle`
126
+
127
+ - **Type:** `string`
128
+ - **Default:** `"Greg"`
129
+
130
+ Name of the project shown in the top-left header.
131
+
132
+ ```svelte
133
+ <MarkdownDocs srcDir="/" version="1.0.0" mainTitle="My Project" />
134
+ ```
135
+
136
+ ### `outline`
137
+
138
+ - **Type:** `false | number | [number, number] | 'deep' | { level?: …, label?: string }`
139
+ - **Default:** `[2, 3]`
140
+ <MarkdownDocs srcDir="/" version={__VERSION__} />
141
+ Controls the right-side **Outline** (on-this-page) panel.
142
+
143
+ | Value | Effect |
144
+ | ------------------------------------- | ---------------------------------- |
145
+ | `false` | Outline panel is hidden |
146
+ | `2` | Only `h2` headings |
147
+ | `[2, 3]` | `h2` and `h3` headings *(default)* |
148
+ | `'deep'` | `h2` through `h6` |
149
+ | `{ level: [2,4], label: 'Contents' }` | Custom range and panel label |
150
+
151
+ <MarkdownDocs srcDir="/" version="1.0.0" mainTitle="My Project" />
152
+ <MarkdownDocs srcDir="/" version="1.0.0" outline="deep" />
153
+ ```
154
+
155
+ ### `carbonAds`
156
+
157
+ - **Type:** `{ code: string; placement: string } | undefined`
158
+ - **Default:** `undefined`
159
+
160
+ Displays a [Carbon Ads](https://www.carbonads.net/) block in the outline sidebar.
161
+ See the [Carbon Ads reference](/reference/carbon-ads) for details.
162
+
163
+ ```svelte
164
+ <MarkdownDocs
165
+ srcDir="/"
166
+ version="1.0.0"
167
+ carbonAds={{ code: 'CWYD42JW', placement: 'myprojectdev' }}
168
+ />
169
+ ```
170
+
171
+ ### `children`
172
+
173
+ - **Type:** `Snippet | undefined`
174
+
175
+ Rendered when the active path does not match any Markdown file (i.e., when a
176
+ folder URL has no `index.md`). Useful for a custom landing splash or a
177
+ "choose a topic" prompt.
178
+
179
+ ```svelte
180
+ <MarkdownDocs srcDir="/" version="1.0.0">
181
+ {#snippet children()}
182
+ <p>👉 Select a page from the sidebar to get started.</p>
183
+ srcDir="/"
184
+ </MarkdownDocs>
185
+ ```
186
+
187
+
188
+ ## Vite configuration
189
+
190
+ `vitePluginSearchIndex` must be added to `vite.config.js` to build the
191
+ full-text search index:
192
+
193
+ ```js
194
+ // vite.config.js
195
+ import { vitePluginSearchIndex } from '@dominikcz/greg/plugins';
196
+
197
+ export default defineConfig({
198
+ plugins: [
199
+ svelte(),
200
+ vitePluginSearchIndex({ docsDir: 'docs', srcDir: '/' }),
201
+ ],
202
+ resolve: {
203
+ alias: {
204
+ '$components': resolve('./src/lib/components'),
205
+ },
206
+ },
207
+ });
208
+ ```
209
+
210
+ | Option | Description |
211
+ | ---------- | ------------------------------------------------------------------ |
212
+ | `docsDir` | Folder name relative to the project root that contains `.md` files |
213
+ | `srcDir` | URL prefix — must match the `srcDir` prop |
214
+
215
+
216
+ ## svelte.config.js
217
+ vitePluginSearchIndex({ docsDir: 'docs', srcDir: '/' }),
218
+ The markdown pipeline is configured in `svelte.config.js`. The `gregConfig`
219
+ object at the top of the file exposes user-facing options:
220
+
221
+ ```js
222
+ const gregConfig = {
223
+ markdown: {
224
+ math: false, // set to true to enable $…$ / $$…$$ rendering via MathJax
225
+ },
226
+ };
227
+ ```
228
+
229
+ ## Runtime extension model
230
+
231
+ `MarkdownRenderer.svelte` now delegates registry-style extension points to
232
+ `src/lib/MarkdownDocs/markdownRendererRuntime.ts` instead of keeping hardcoded
233
+ branches inline. This keeps runtime rendering predictable and makes new
234
+ features easier to add.
235
+
236
+ ### 1) Component hydration registry
237
+
238
+ `COMPONENT_REGISTRY` maps a tag name to:
239
+
240
+ - a Svelte `component`
241
+ - a `buildProps(el)` function
242
+
243
+ This is used for custom component tags like `badge`, `button`, `image`,
244
+ `link`, and `codegroup`.
245
+
246
+ ### 2) Markdown plugin registries
247
+
248
+ The markdown pipeline is assembled from two ordered registries:
249
+
250
+ - `getRemarkPluginEntries(baseUrl, docsPrefix)`
251
+ - `getRehypePluginEntries()`
252
+
253
+ These cover, among others:
254
+
255
+ - custom containers (`remarkContainers` + `rehypeContainers`)
256
+ - code blocks (`rehypeShiki`, `rehypeCodeTitle`, `rehypeCodeGroup`)
257
+ - Mermaid preprocessing (`rehypeMermaid`)
258
+ - Steps normalization (`rehypeStepsWrapper`)
259
+ - headings/TOC (`rehypeSlug`, `rehypeAutolinkHeadings`, `rehypeTocPlaceholder`)
260
+
261
+ ### 3) Render handlers (post-HTML stage)
262
+
263
+ After HTML is rendered, handlers are executed from ordered lists:
264
+
265
+ - `RUNTIME_RENDER_HANDLERS` (full render pass)
266
+ - `THEME_CHANGE_RENDER_HANDLERS` (theme-only pass)
267
+
268
+ Current handlers include component hydration and Mermaid initialization/re-render.
269
+
270
+ ## What to extend where
271
+
272
+ - Use **component registry** for interactive widgets rendered from custom tags.
273
+ - Use **rehype/remark registries** for static HTML transforms.
274
+ - Use **render handlers** for browser-only work that needs live DOM access
275
+ (for example diagram engines).
@@ -0,0 +1,79 @@
1
+ ---
2
+ title: Outline
3
+ ---
4
+
5
+ # Outline (On This Page)
6
+
7
+ The **Outline** panel is shown in the right column of every doc page. It displays
8
+ a scrollspy-aware list of headings for the current page and lets the reader jump
9
+ to any section.
10
+
11
+
12
+ ## Configuring the outline
13
+
14
+ Pass the `outline` prop to `<MarkdownDocs>`:
15
+
16
+ ```svelte
17
+ <!-- Show h2 and h3 (default) -->
18
+ <MarkdownDocs srcDir="/" version="1.0.0" outline={[2, 3]} />
19
+
20
+ <!-- Show all headings -->
21
+ <MarkdownDocs srcDir="/" version="1.0.0" outline="deep" />
22
+
23
+ <!-- Show only h2 -->
24
+ <MarkdownDocs srcDir="/" version="1.0.0" outline={2} />
25
+
26
+ <!-- Disable -->
27
+ <MarkdownDocs srcDir="/" version="1.0.0" outline={false} />
28
+
29
+ <!-- Custom label + range -->
30
+ <MarkdownDocs
31
+ srcDir="/"
32
+ version="1.0.0"
33
+ outline={{ level: [2, 4], label: 'Contents' }}
34
+ />
35
+ ```
36
+
37
+ ### Accepted values
38
+
39
+ | Value | Effect |
40
+ | ------------------ | ------------------------------------------------------------------------------- |
41
+ | `false` | Outline panel is hidden |
42
+ | `number` | Only that heading level (e.g. `2` → h2 only) |
43
+ | `[min, max]` | Range of heading levels, e.g. `[2, 3]` |
44
+ | `'deep'` | Same as `[2, 6]` |
45
+ | `{ level, label }` | Object form — `level` follows the rules above; `label` overrides "On this page" |
46
+
47
+
48
+ ## Scrollspy behaviour
49
+
50
+ The active link in the outline is updated as the user scrolls. A heading is
51
+ considered "active" when it reaches within 72 px of the top of the content pane.
52
+
53
+ The outline is built by scanning the live DOM with a `MutationObserver`, so it
54
+ correctly reflects the final rendered content including async-loaded pages.
55
+
56
+
57
+ ## Inline `[[toc]]`
58
+
59
+ You can also insert a static **inline** table of contents at any point inside a
60
+ page with the `[[toc]]` placeholder:
61
+
62
+ ```md
63
+ ## Contents
64
+
65
+ [[toc]]
66
+ ```
67
+
68
+ By default it includes h2 and h3. This is independent of the right-side Outline
69
+ panel — both can be used together.
70
+
71
+
72
+ ## CSS variables
73
+
74
+ | Variable | Default (light) | Description |
75
+ | ----------------------- | --------------- | -------------------------- |
76
+ | `--greg-toc-background` | `transparent` | Panel background |
77
+ | `--greg-toc-color` | `#3d3d3d` | Section label colour |
78
+ | `--greg-toc-link-color` | `#4a4a6a` | Link colour |
79
+ | `--greg-toc-link-hover` | `#646cff` | Link hover / active colour |
@@ -0,0 +1,263 @@
1
+ ---
2
+ title: Search
3
+ ---
4
+
5
+ Greg includes a built-in full-text search powered by [Fuse.js](https://fusejs.io/).
6
+ No external service or API key is required.
7
+
8
+
9
+ ## Search modes
10
+
11
+ Search mode is configured in `greg.config.js`:
12
+
13
+ ```js
14
+ search: {
15
+ provider: 'server', // 'server' | 'local' | 'none'
16
+ // serverUrl: '/api/search'
17
+ }
18
+ ```
19
+
20
+ - `server`: Browser calls `GET /api/search?q=...` and receives ready-ranked results. Recommended for large doc sets (best default).
21
+ - `local`: Browser downloads `/search-index.json` and runs Fuse.js locally. Recommended for small doc sets.
22
+ - `none`: Built-in search UI (button + modal + shortcuts) is disabled. Recommended for sites without built-in search.
23
+
24
+
25
+ ## How indexing works
26
+
27
+ At **build time**, `vitePluginSearchIndex` walks every `.md` file in the docs
28
+ folder, strips Markdown syntax, splits each page into sections (by heading) and
29
+ emits a `/search-index.json` file into the Vite output.
30
+
31
+ At **run time**:
32
+
33
+ - in `local` mode, the modal fetches `/search-index.json` and searches in-browser,
34
+ - in `server` mode, the modal queries your configured `serverUrl` endpoint.
35
+
36
+
37
+ ## Required Vite plugins
38
+
39
+ Use both plugins in `vite.config.js`:
40
+
41
+ ```js
42
+ import { vitePluginSearchIndex, vitePluginSearchServer } from '@dominikcz/greg/plugins';
43
+
44
+ export default defineConfig({
45
+ plugins: [
46
+ svelte(),
47
+ vitePluginSearchIndex({ docsDir: 'docs', srcDir: '/' }),
48
+ vitePluginSearchServer({ docsDir: 'docs', srcDir: '/' }),
49
+ ],
50
+ });
51
+ ```
52
+
53
+ `vitePluginSearchServer` exposes `/api/search` automatically in both `dev` and
54
+ `preview`.
55
+
56
+
57
+ ## Production server-side search
58
+
59
+ Build your site first:
60
+
61
+ ```bash
62
+ npm run build
63
+ ```
64
+
65
+ Then start the standalone search server:
66
+
67
+ ```bash
68
+ greg search-server --index dist/search-index.json --port 3100
69
+ ```
70
+
71
+ Set `serverUrl` to that endpoint, for example:
72
+
73
+ ```js
74
+ search: {
75
+ provider: 'server',
76
+ serverUrl: 'http://localhost:3100/api/search'
77
+ }
78
+ ```
79
+
80
+ In production, you will usually place the search server behind a reverse proxy
81
+ so your frontend can keep using `/api/search`.
82
+
83
+
84
+ ## Custom search engine
85
+
86
+ If you want Algolia, Meilisearch, Typesense, or your own backend:
87
+
88
+ - set `provider: 'none'` in `greg.config.js`,
89
+ - pass `searchProvider` prop to `<MarkdownDocs>`.
90
+
91
+ With `searchProvider` provided, Greg enables the Search button/modal again and
92
+ routes queries through your function.
93
+
94
+ `searchProvider` signature:
95
+
96
+ ```ts
97
+ (query: string, limit?: number) => Promise<SearchResult[]>
98
+ ```
99
+
100
+ Expected `SearchResult` shape:
101
+
102
+ ```ts
103
+ type SearchResult = {
104
+ id: string;
105
+ title: string;
106
+ titleHtml: string;
107
+ sectionTitle: string;
108
+ sectionTitleHtml?: string; // optional but recommended for consistent heading highlights
109
+ sectionAnchor: string;
110
+ excerptHtml: string;
111
+ score: number;
112
+ }
113
+ ```
114
+
115
+ `sectionTitleHtml` is now used by the built-in modal to render heading highlights.
116
+ If missing, Greg falls back to escaped `sectionTitle` (without match-aware markup).
117
+
118
+
119
+ ## Opening search
120
+
121
+ | Method | Action |
122
+ | ------------------------------------------ | ----------- |
123
+ | Click the **Search…** button in the header | Opens modal |
124
+ | `Ctrl + K` | Opens modal |
125
+ | `Cmd + K` (macOS) | Opens modal |
126
+
127
+
128
+ ## Keyboard navigation inside the modal
129
+
130
+ | Key | Action |
131
+ | --------- | ----------------------------- |
132
+ | `↑` / `↓` | Select previous / next result |
133
+ | `Enter` | Navigate to selected result |
134
+ | `Esc` | Close modal |
135
+
136
+
137
+ ## Search ranking
138
+
139
+ Results are scored by Fuse.js using weighted fields:
140
+
141
+ | Field | Weight |
142
+ | ----------------- | ------ |
143
+ | Page title | 3× |
144
+ | Section heading | 2× |
145
+ | Section body text | 1× |
146
+
147
+ A fuzzy threshold of `0.4` is used — tighter than the default, so only genuine
148
+ matches surface. `ignoreLocation: true` means the match can appear anywhere in
149
+ the text, not just at the start.
150
+
151
+
152
+ ## Excluding pages from the index
153
+
154
+ Files whose names start with `__` (double underscore) are automatically excluded
155
+ from both routing and the search index.
156
+
157
+
158
+ ## Limitations
159
+
160
+ - In `local` mode, large indices can significantly increase initial payload size
161
+ and memory usage in the browser.
162
+ - In `server` mode, your search endpoint must be reachable from the client
163
+ (`serverUrl` must be correct for your environment).
164
+ - Code block content is stripped from the index (not searchable).
165
+
166
+
167
+ ## AI knowledge base
168
+
169
+ The AI feature adds an **Ask AI** tab to the search modal. It uses a retrieval-augmented
170
+ generation (RAG) pipeline: your docs are chunked and embedded at build time, then the
171
+ top matching chunks are injected as context into each LLM call.
172
+
173
+ Enable it in `greg.config.js`:
174
+
175
+ ```js
176
+ search: {
177
+ ai: {
178
+ enabled: true,
179
+ provider: 'ollama', // or 'openai'
180
+ ollama: { model: 'phi4' },
181
+ }
182
+ }
183
+ ```
184
+
185
+ See the [Getting started guide](/docs/guide/getting-started) for the required Vite plugin
186
+ (`vitePluginAiServer`) and the production AI server setup.
187
+
188
+
189
+ ### AI characters (personas)
190
+
191
+ Greg ships five built-in personas that users can pick in the chat UI:
192
+
193
+ | ID | Name | Icon | Description |
194
+ | -------------- | ------------ | ---- | ---------------------------------- |
195
+ | `professional` | Professional | 👔 | Precise, formal, technical answers |
196
+ | `friendly` | Friendly | 😊 | Warm, approachable explanations |
197
+ | `pirate` | Pirate | 🏴‍☠️ | Arr! Knowledge on the high seas! |
198
+ | `sensei` | Sensei | 🥋 | Patient teacher, step-by-step |
199
+ | `concise` | Concise | ✂️ | Maximum density, minimum words |
200
+
201
+ #### Limiting which characters are available
202
+
203
+ Pass an array of IDs to show only a subset:
204
+
205
+ ```js
206
+ ai: {
207
+ characters: ['professional', 'friendly', 'concise'],
208
+ }
209
+ ```
210
+
211
+ An empty array (or omitting the key) makes all five characters available.
212
+
213
+ #### Setting the default character
214
+
215
+ ```js
216
+ ai: {
217
+ defaultCharacter: 'friendly',
218
+ }
219
+ ```
220
+
221
+ If omitted, `'professional'` is selected by default.
222
+
223
+ #### Defining custom characters
224
+
225
+ Add your own personas via `customCharacters`.
226
+ A custom entry with the same `id` as a built-in will **override** the built-in.
227
+
228
+ ```js
229
+ import { aiCharacters } from '@dominikcz/greg/plugins';
230
+
231
+ ai: {
232
+ // You can reference built-in character IDs via the exported aiCharacters array.
233
+ // console.log(aiCharacters.map(c => c.id));
234
+
235
+ customCharacters: [
236
+ {
237
+ id: 'mybot',
238
+ name: 'My Bot',
239
+ icon: '🤖',
240
+ description: 'Tailored assistant for this project',
241
+ systemPrompt: 'You are a helpful assistant specialized in this project. Always respond in the same language as the user\'s question.',
242
+ },
243
+ ],
244
+ // Optionally restrict to only your custom character plus one built-in:
245
+ characters: ['professional', 'mybot'],
246
+ }
247
+ ```
248
+
249
+ `customCharacters` is merged with the built-in list before the `characters` filter is applied.
250
+ The `aiCharacters` export is provided for reference — you can inspect built-in IDs or
251
+ re-use/extend built-in system prompts programmatically.
252
+
253
+ `AiCharacterConfig` type (from `@dominikcz/greg/types`):
254
+
255
+ ```ts
256
+ type AiCharacterConfig = {
257
+ id: string;
258
+ name: string;
259
+ icon: string;
260
+ description?: string;
261
+ systemPrompt: string;
262
+ };
263
+ ```