livemark 0.22.0 → 0.24.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.
- package/README.md +1 -1
- package/build/actions/changelog/build.js +4 -8
- package/build/actions/config/load.js +1 -1
- package/build/actions/config/load.unit.js +1 -1
- package/build/actions/target/build.js +2 -5
- package/build/commands/build.js +1 -1
- package/build/commands/escape.js +1 -1
- package/build/commands/preview.js +1 -1
- package/build/commands/start.js +1 -1
- package/build/components/Abbr.js +2 -2
- package/build/components/Article.js +2 -2
- package/build/components/BlogIndex.js +2 -4
- package/build/components/Callout.js +1 -1
- package/build/components/ChangelogIndex.js +1 -1
- package/build/components/CodeBlock.js +3 -5
- package/build/components/CodeTabs.js +1 -1
- package/build/components/Columns.js +2 -4
- package/build/components/Content.js +2 -2
- package/build/components/ContentTab.js +1 -1
- package/build/components/ContentTabs.js +1 -1
- package/build/components/DefinitionList.js +1 -1
- package/build/components/FileTree.js +1 -1
- package/build/components/FootnoteRef.js +2 -2
- package/build/components/InlineToc.js +1 -1
- package/build/components/Layout.js +1 -1
- package/build/components/LinkButton.js +1 -1
- package/build/components/Mermaid.js +1 -1
- package/build/components/PackageTabs.js +2 -2
- package/build/components/PageToolbar.js +9 -7
- package/build/components/PrevNext.js +3 -7
- package/build/components/SearchDialog.js +1 -1
- package/build/components/SectionHeader.js +1 -1
- package/build/components/Sidebar.js +2 -2
- package/build/components/SidebarArticles.js +2 -2
- package/build/components/SidebarLinks.js +2 -2
- package/build/components/TagIndex.js +2 -4
- package/build/components/Toc.js +1 -1
- package/build/content/article.js +1 -1
- package/build/content-collections.js +2 -4
- package/build/elements/alert-dialog.js +4 -4
- package/build/elements/alert.js +1 -1
- package/build/elements/avatar.d.ts +1 -1
- package/build/elements/avatar.js +2 -2
- package/build/elements/badge.js +1 -1
- package/build/elements/breadcrumb.js +1 -1
- package/build/elements/button-group.d.ts +1 -1
- package/build/elements/button-group.js +2 -2
- package/build/elements/calendar.js +4 -4
- package/build/elements/carousel.js +1 -1
- package/build/elements/chart.js +4 -14
- package/build/elements/collapsible.js +3 -3
- package/build/elements/command.js +1 -1
- package/build/elements/context-menu.js +4 -4
- package/build/elements/dialog.js +1 -1
- package/build/elements/direction.d.ts +1 -1
- package/build/elements/direction.js +2 -2
- package/build/elements/drawer.js +1 -1
- package/build/elements/dropdown-menu.js +2 -2
- package/build/elements/empty.d.ts +1 -1
- package/build/elements/empty.js +2 -2
- package/build/elements/field.js +1 -1
- package/build/elements/hover-card.js +2 -2
- package/build/elements/input-group.js +1 -1
- package/build/elements/item.js +1 -1
- package/build/elements/menubar.js +1 -1
- package/build/elements/native-select.js +1 -1
- package/build/elements/navigation-menu.js +1 -1
- package/build/elements/pagination.js +2 -2
- package/build/elements/popover.js +1 -1
- package/build/elements/progress.d.ts +1 -1
- package/build/elements/progress.js +2 -2
- package/build/elements/resizable.js +2 -2
- package/build/elements/scroll-area.js +1 -1
- package/build/elements/select.js +1 -1
- package/build/elements/sheet.js +1 -1
- package/build/elements/sidebar.js +2 -3
- package/build/elements/table.js +1 -1
- package/build/elements/toggle-group.js +1 -1
- package/build/elements/tooltip.js +1 -1
- package/build/helpers/changelog-source.js +1 -1
- package/build/helpers/dynamic-icon-resolver.js +1 -1
- package/build/helpers/resolve-asset-path.unit.js +1 -1
- package/build/helpers/resolve-base.unit.js +2 -2
- package/build/helpers/resolve-includes.js +2 -2
- package/build/helpers/resolve-includes.unit.js +1 -1
- package/build/helpers/rss.js +2 -4
- package/build/helpers/rss.unit.js +1 -1
- package/build/helpers/section.js +2 -3
- package/build/helpers/section.unit.js +4 -13
- package/build/helpers/toc.unit.js +2 -4
- package/build/plugins/rehype-inline-code.js +2 -2
- package/build/plugins/rehype-task-list-a11y.js +1 -1
- package/build/plugins/remark-abbr.js +2 -4
- package/build/plugins/remark-ansi.js +2 -4
- package/build/plugins/remark-ansi.unit.js +1 -1
- package/build/plugins/remark-badge.js +2 -4
- package/build/plugins/remark-button.unit.js +1 -1
- package/build/plugins/remark-callout.js +1 -1
- package/build/plugins/remark-card.js +1 -1
- package/build/plugins/remark-code-tabs.js +4 -8
- package/build/plugins/remark-columns.js +1 -1
- package/build/plugins/remark-custom-heading-id.unit.js +1 -1
- package/build/plugins/remark-deflist.js +1 -1
- package/build/plugins/remark-details.js +2 -4
- package/build/plugins/remark-filetree.js +1 -1
- package/build/plugins/remark-filetree.unit.js +1 -1
- package/build/plugins/remark-media.js +3 -7
- package/build/plugins/remark-media.unit.js +1 -1
- package/build/plugins/remark-steps.unit.js +1 -1
- package/build/plugins/remark-tab.js +4 -2
- package/build/plugins/remark-tab.unit.js +3 -7
- package/build/plugins/remark-toc.unit.js +1 -1
- package/build/plugins/shiki-icon.js +1 -1
- package/build/plugins/shiki-line-highlight.js +1 -1
- package/build/plugins/vite-livemark.js +1 -1
- package/build/plugins/vite-robots.js +1 -1
- package/build/plugins/vite-robots.unit.js +1 -1
- package/build/routes/$.js +1 -1
- package/build/vite.config.js +3 -8
- package/package.json +2 -2
- package/skills/authoring/SKILL.md +1 -1
- package/skills/configuration/SKILL.md +1 -3
- package/source/actions/changelog/build.ts +4 -20
- package/source/actions/config/load.ts +1 -3
- package/source/actions/config/load.unit.ts +2 -7
- package/source/actions/target/build.ts +1 -4
- package/source/commands/build.ts +1 -7
- package/source/commands/escape.ts +3 -8
- package/source/commands/preview.ts +1 -7
- package/source/commands/start.ts +1 -7
- package/source/components/Abbr.tsx +1 -5
- package/source/components/Article.tsx +1 -5
- package/source/components/BlogIndex.tsx +3 -9
- package/source/components/Callout.tsx +1 -6
- package/source/components/ChangelogIndex.tsx +1 -3
- package/source/components/CodeBlock.tsx +4 -14
- package/source/components/CodeTabs.tsx +1 -3
- package/source/components/Columns.tsx +1 -3
- package/source/components/Content.tsx +1 -5
- package/source/components/ContentTab.tsx +1 -4
- package/source/components/ContentTabs.tsx +3 -10
- package/source/components/DefinitionList.tsx +1 -4
- package/source/components/FileTree.tsx +1 -5
- package/source/components/FootnoteRef.tsx +1 -5
- package/source/components/InlineToc.tsx +1 -4
- package/source/components/Layout.tsx +3 -10
- package/source/components/LinkButton.tsx +1 -7
- package/source/components/Mermaid.tsx +1 -3
- package/source/components/PackageTabs.tsx +1 -5
- package/source/components/PageToolbar.tsx +10 -14
- package/source/components/PrevNext.tsx +2 -6
- package/source/components/SearchDialog.tsx +2 -6
- package/source/components/SectionHeader.tsx +1 -7
- package/source/components/Sidebar.tsx +2 -7
- package/source/components/SidebarArticles.tsx +4 -20
- package/source/components/SidebarLinks.tsx +2 -6
- package/source/components/TagIndex.tsx +3 -9
- package/source/components/Toc.tsx +2 -7
- package/source/content/article.ts +1 -2
- package/source/content-collections.ts +2 -5
- package/source/elements/alert-dialog.tsx +7 -29
- package/source/elements/alert.tsx +1 -4
- package/source/elements/avatar.tsx +4 -20
- package/source/elements/badge.tsx +2 -4
- package/source/elements/breadcrumb.tsx +3 -13
- package/source/elements/button-group.tsx +1 -6
- package/source/elements/calendar.tsx +6 -23
- package/source/elements/carousel.tsx +3 -10
- package/source/elements/chart.tsx +8 -33
- package/source/elements/collapsible.tsx +2 -6
- package/source/elements/command.tsx +3 -12
- package/source/elements/context-menu.tsx +7 -24
- package/source/elements/dialog.tsx +3 -13
- package/source/elements/direction.tsx +1 -4
- package/source/elements/drawer.tsx +3 -9
- package/source/elements/dropdown-menu.tsx +4 -18
- package/source/elements/empty.tsx +2 -12
- package/source/elements/field.tsx +2 -6
- package/source/elements/hover-card.tsx +1 -3
- package/source/elements/input-group.tsx +14 -27
- package/source/elements/item.tsx +3 -12
- package/source/elements/menubar.tsx +4 -13
- package/source/elements/native-select.tsx +3 -14
- package/source/elements/navigation-menu.tsx +1 -4
- package/source/elements/pagination.tsx +3 -13
- package/source/elements/popover.tsx +1 -4
- package/source/elements/progress.tsx +3 -15
- package/source/elements/resizable.tsx +3 -11
- package/source/elements/scroll-area.tsx +1 -5
- package/source/elements/select.tsx +3 -13
- package/source/elements/sheet.tsx +2 -9
- package/source/elements/sidebar.tsx +6 -24
- package/source/elements/table.tsx +3 -12
- package/source/elements/toggle-group.tsx +1 -3
- package/source/elements/tooltip.tsx +2 -9
- package/source/helpers/changelog-source.ts +1 -3
- package/source/helpers/dynamic-icon-resolver.tsx +1 -4
- package/source/helpers/resolve-asset-path.unit.ts +6 -12
- package/source/helpers/resolve-base.unit.ts +1 -2
- package/source/helpers/resolve-includes.ts +2 -8
- package/source/helpers/resolve-includes.unit.ts +9 -36
- package/source/helpers/rss.ts +3 -9
- package/source/helpers/rss.unit.ts +1 -3
- package/source/helpers/section.ts +1 -4
- package/source/helpers/section.unit.ts +5 -18
- package/source/helpers/toc.unit.ts +1 -3
- package/source/plugins/rehype-inline-code.ts +5 -21
- package/source/plugins/rehype-task-list-a11y.ts +1 -2
- package/source/plugins/remark-abbr.ts +1 -3
- package/source/plugins/remark-ansi.ts +2 -5
- package/source/plugins/remark-ansi.unit.ts +6 -18
- package/source/plugins/remark-badge.ts +1 -3
- package/source/plugins/remark-button.unit.ts +3 -9
- package/source/plugins/remark-callout.ts +35 -40
- package/source/plugins/remark-card.ts +25 -29
- package/source/plugins/remark-code-tabs.ts +3 -7
- package/source/plugins/remark-columns.ts +13 -17
- package/source/plugins/remark-custom-heading-id.unit.ts +2 -6
- package/source/plugins/remark-deflist.ts +1 -2
- package/source/plugins/remark-details.ts +28 -34
- package/source/plugins/remark-filetree.ts +28 -34
- package/source/plugins/remark-filetree.unit.ts +1 -4
- package/source/plugins/remark-media.ts +2 -6
- package/source/plugins/remark-media.unit.ts +2 -6
- package/source/plugins/remark-steps.unit.ts +2 -7
- package/source/plugins/remark-tab.ts +26 -30
- package/source/plugins/remark-tab.unit.ts +2 -6
- package/source/plugins/remark-toc.unit.ts +1 -3
- package/source/plugins/shiki-icon.ts +1 -4
- package/source/plugins/shiki-line-highlight.ts +4 -11
- package/source/plugins/vite-livemark.ts +3 -10
- package/source/plugins/vite-robots.ts +1 -6
- package/source/plugins/vite-robots.unit.ts +1 -3
- package/source/routes/$.tsx +1 -3
- package/source/styles/general.css +1 -5
- package/source/vite.config.ts +2 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livemark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "Livemark description",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Evgeny Karev",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"react-dom": "19.2.4",
|
|
106
106
|
"semantic-release": "24.2.9",
|
|
107
107
|
"tempy": "3.2.0",
|
|
108
|
-
"vite-plus": "0.1.
|
|
108
|
+
"vite-plus": "0.1.24",
|
|
109
109
|
"wrangler": "4.85.0"
|
|
110
110
|
},
|
|
111
111
|
"peerDependencies": {
|
|
@@ -92,6 +92,6 @@ After authoring, run:
|
|
|
92
92
|
|
|
93
93
|
## References
|
|
94
94
|
|
|
95
|
-
- Full frontmatter reference: `docs/
|
|
95
|
+
- Full frontmatter reference: `docs/authoring/frontmatter.md`.
|
|
96
96
|
- Schema source of truth: `website/models/article.ts`.
|
|
97
97
|
- Transform pipeline: `website/content-collections.ts`.
|
|
@@ -59,9 +59,7 @@ export default defineConfig({
|
|
|
59
59
|
],
|
|
60
60
|
|
|
61
61
|
// Optional: per-file frontmatter overrides
|
|
62
|
-
patches: [
|
|
63
|
-
{ file: "README.md", article: { title: "Overview", icon: "sparkles" } },
|
|
64
|
-
],
|
|
62
|
+
patches: [{ file: "README.md", article: { title: "Overview", icon: "sparkles" } }],
|
|
65
63
|
})
|
|
66
64
|
```
|
|
67
65
|
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
access,
|
|
3
|
-
mkdir,
|
|
4
|
-
readFile,
|
|
5
|
-
readdir,
|
|
6
|
-
rm,
|
|
7
|
-
writeFile,
|
|
8
|
-
} from "node:fs/promises"
|
|
1
|
+
import { access, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises"
|
|
9
2
|
import { dirname, join, resolve } from "node:path"
|
|
10
3
|
import slugify from "@sindresorhus/slugify"
|
|
11
4
|
import type { Root, RootContent } from "mdast"
|
|
@@ -61,10 +54,7 @@ export function cacheIncludeGlob(config: Config) {
|
|
|
61
54
|
* `cache/changelog/`: the rendered `.md` entries plus a `meta.json`
|
|
62
55
|
* holding the etag for conditional GETs. On refresh we wipe only the
|
|
63
56
|
* `.md` files, leaving meta intact. */
|
|
64
|
-
export async function buildChangelog(
|
|
65
|
-
section: ChangelogSection,
|
|
66
|
-
config: Config,
|
|
67
|
-
) {
|
|
57
|
+
export async function buildChangelog(section: ChangelogSection, config: Config) {
|
|
68
58
|
const targetDir = targetDirFor(config.configPath)
|
|
69
59
|
const cacheDir = join(targetDir, CACHE_SUBDIR)
|
|
70
60
|
const metaPath = join(cacheDir, "meta.json")
|
|
@@ -160,9 +150,7 @@ function escapeMdxAngles(markdown: string) {
|
|
|
160
150
|
return line
|
|
161
151
|
}
|
|
162
152
|
if (inFence) return line
|
|
163
|
-
return line.replace(/`[^`]*`|</g, match =>
|
|
164
|
-
match === "<" ? "\\<" : match,
|
|
165
|
-
)
|
|
153
|
+
return line.replace(/`[^`]*`|</g, match => (match === "<" ? "\\<" : match))
|
|
166
154
|
})
|
|
167
155
|
.join("\n")
|
|
168
156
|
}
|
|
@@ -230,11 +218,7 @@ async function buildFromGitHub(
|
|
|
230
218
|
}
|
|
231
219
|
|
|
232
220
|
function wrapFrontmatter(entry: ChangelogEntry, section: ChangelogSection) {
|
|
233
|
-
const lines = [
|
|
234
|
-
"---",
|
|
235
|
-
`title: ${entry.title}`,
|
|
236
|
-
`path: ${section.prefix}${entry.slug}/`,
|
|
237
|
-
]
|
|
221
|
+
const lines = ["---", `title: ${entry.title}`, `path: ${section.prefix}${entry.slug}/`]
|
|
238
222
|
if (entry.date) lines.push(`date: ${entry.date}`)
|
|
239
223
|
if (entry.sourceUrl) {
|
|
240
224
|
lines.push(`sourceUrl: ${entry.sourceUrl}`, "sourceAction: view")
|
|
@@ -33,9 +33,7 @@ function detectCommand() {
|
|
|
33
33
|
* hash, watcher) still has a stable per-project key.
|
|
34
34
|
*/
|
|
35
35
|
export async function loadConfig(path?: string): Promise<Config> {
|
|
36
|
-
const configIndex = process.argv.findIndex(
|
|
37
|
-
a => a === "-c" || a === "--config",
|
|
38
|
-
)
|
|
36
|
+
const configIndex = process.argv.findIndex(a => a === "-c" || a === "--config")
|
|
39
37
|
const cliPath = configIndex !== -1 ? process.argv[configIndex + 1] : undefined
|
|
40
38
|
const explicit = path ?? cliPath
|
|
41
39
|
const resolved = resolve(explicit ?? "livemark.config.ts")
|
|
@@ -6,9 +6,7 @@ import { loadConfig } from "./load.ts"
|
|
|
6
6
|
|
|
7
7
|
describe("loadConfig", () => {
|
|
8
8
|
it("should throw when an explicit path points at a missing file", async () => {
|
|
9
|
-
await expect(loadConfig("/nonexistent/config.ts")).rejects.toThrow(
|
|
10
|
-
/not found/,
|
|
11
|
-
)
|
|
9
|
+
await expect(loadConfig("/nonexistent/config.ts")).rejects.toThrow(/not found/)
|
|
12
10
|
})
|
|
13
11
|
|
|
14
12
|
it("should return defaults when no path is given and cwd has no config", () =>
|
|
@@ -29,10 +27,7 @@ describe("loadConfig", () => {
|
|
|
29
27
|
it("should load config from explicit path", () =>
|
|
30
28
|
temporaryDirectoryTask(async tmpDir => {
|
|
31
29
|
const configPath = join(tmpDir, "livemark.config.ts")
|
|
32
|
-
fs.writeFileSync(
|
|
33
|
-
configPath,
|
|
34
|
-
'export default { include: "articles/**/*.mdx" }\n',
|
|
35
|
-
)
|
|
30
|
+
fs.writeFileSync(configPath, 'export default { include: "articles/**/*.mdx" }\n')
|
|
36
31
|
const config = await loadConfig(configPath)
|
|
37
32
|
expect(config.include).toBe("articles/**/*.mdx")
|
|
38
33
|
expect(config.root).toBe(tmpDir)
|
|
@@ -81,9 +81,6 @@ export function buildTarget(configPath: string) {
|
|
|
81
81
|
* rebuilding it. Used by code that needs to write into the target
|
|
82
82
|
* (e.g. cache writers) outside of `buildTarget`'s setup phase. */
|
|
83
83
|
export function targetDirFor(configPath: string) {
|
|
84
|
-
const hash = createHash("sha256")
|
|
85
|
-
.update(configPath)
|
|
86
|
-
.digest("hex")
|
|
87
|
-
.slice(0, 16)
|
|
84
|
+
const hash = createHash("sha256").update(configPath).digest("hex").slice(0, 16)
|
|
88
85
|
return join(TARGETS_ROOT, hash)
|
|
89
86
|
}
|
package/source/commands/build.ts
CHANGED
|
@@ -2,13 +2,7 @@ import { join } from "node:path"
|
|
|
2
2
|
import { Command } from "commander"
|
|
3
3
|
import { createBuilder } from "vite"
|
|
4
4
|
|
|
5
|
-
const configFile = join(
|
|
6
|
-
import.meta.dirname,
|
|
7
|
-
"..",
|
|
8
|
-
"..",
|
|
9
|
-
"source",
|
|
10
|
-
"vite.config.ts",
|
|
11
|
-
)
|
|
5
|
+
const configFile = join(import.meta.dirname, "..", "..", "source", "vite.config.ts")
|
|
12
6
|
|
|
13
7
|
/**
|
|
14
8
|
* Build the site for production.
|
|
@@ -29,14 +29,11 @@ export const escape = new Command("escape")
|
|
|
29
29
|
.action((relPath?: string) => {
|
|
30
30
|
if (!relPath) {
|
|
31
31
|
for (const file of listEscapable()) console.log(file)
|
|
32
|
-
console.log(
|
|
33
|
-
pc.dim("\nRun 'livemark escape <path>' to copy a file into .livemark/"),
|
|
34
|
-
)
|
|
32
|
+
console.log(pc.dim("\nRun 'livemark escape <path>' to copy a file into .livemark/"))
|
|
35
33
|
return
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
const isTopLevelFile =
|
|
39
|
-
!relPath.includes("/") && ESCAPABLE_FILES.includes(relPath)
|
|
36
|
+
const isTopLevelFile = !relPath.includes("/") && ESCAPABLE_FILES.includes(relPath)
|
|
40
37
|
const [first] = relPath.split("/")
|
|
41
38
|
const isFolderPath =
|
|
42
39
|
!!first && ESCAPABLE_FOLDERS.includes(first) && !relPath.includes("..")
|
|
@@ -63,9 +60,7 @@ export const escape = new Command("escape")
|
|
|
63
60
|
|
|
64
61
|
mkdirSync(dirname(dest), { recursive: true })
|
|
65
62
|
writeFileSync(dest, readFileSync(src))
|
|
66
|
-
console.log(
|
|
67
|
-
`Copied ${pc.dim(relPath)} → ${pc.green(`.livemark/${relPath}`)}`,
|
|
68
|
-
)
|
|
63
|
+
console.log(`Copied ${pc.dim(relPath)} → ${pc.green(`.livemark/${relPath}`)}`)
|
|
69
64
|
})
|
|
70
65
|
|
|
71
66
|
function listEscapable() {
|
|
@@ -2,13 +2,7 @@ import { join } from "node:path"
|
|
|
2
2
|
import { Command } from "commander"
|
|
3
3
|
import { preview as vitePreview } from "vite"
|
|
4
4
|
|
|
5
|
-
const configFile = join(
|
|
6
|
-
import.meta.dirname,
|
|
7
|
-
"..",
|
|
8
|
-
"..",
|
|
9
|
-
"source",
|
|
10
|
-
"vite.config.ts",
|
|
11
|
-
)
|
|
5
|
+
const configFile = join(import.meta.dirname, "..", "..", "source", "vite.config.ts")
|
|
12
6
|
|
|
13
7
|
/**
|
|
14
8
|
* Preview the production build locally.
|
package/source/commands/start.ts
CHANGED
|
@@ -2,13 +2,7 @@ import { join } from "node:path"
|
|
|
2
2
|
import { Command } from "commander"
|
|
3
3
|
import { createServer } from "vite"
|
|
4
4
|
|
|
5
|
-
const configFile = join(
|
|
6
|
-
import.meta.dirname,
|
|
7
|
-
"..",
|
|
8
|
-
"..",
|
|
9
|
-
"source",
|
|
10
|
-
"vite.config.ts",
|
|
11
|
-
)
|
|
5
|
+
const configFile = join(import.meta.dirname, "..", "..", "source", "vite.config.ts")
|
|
12
6
|
|
|
13
7
|
/**
|
|
14
8
|
* Start a development server.
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Tooltip,
|
|
3
|
-
TooltipContent,
|
|
4
|
-
TooltipTrigger,
|
|
5
|
-
} from "../elements/tooltip.tsx"
|
|
1
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../elements/tooltip.tsx"
|
|
6
2
|
|
|
7
3
|
/** Renders an abbreviation with a shadcn tooltip showing its full form */
|
|
8
4
|
export function Abbr(props: { text: string; title: string }) {
|
|
@@ -13,11 +13,7 @@ import { Column } from "./Column.tsx"
|
|
|
13
13
|
import { Columns } from "./Columns.tsx"
|
|
14
14
|
import { ContentTab } from "./ContentTab.tsx"
|
|
15
15
|
import { ContentTabs } from "./ContentTabs.tsx"
|
|
16
|
-
import {
|
|
17
|
-
DefinitionDetail,
|
|
18
|
-
DefinitionList,
|
|
19
|
-
DefinitionTerm,
|
|
20
|
-
} from "./DefinitionList.tsx"
|
|
16
|
+
import { DefinitionDetail, DefinitionList, DefinitionTerm } from "./DefinitionList.tsx"
|
|
21
17
|
import { Details } from "./Details.tsx"
|
|
22
18
|
import { FileTree } from "./FileTree.tsx"
|
|
23
19
|
import { Footer } from "./Footer.tsx"
|
|
@@ -31,9 +31,7 @@ export function BlogIndex(props: { sectionPrefix: string }) {
|
|
|
31
31
|
const parts = [`## ${post.title}`]
|
|
32
32
|
if (post.date) parts.push(formatDate(post.date))
|
|
33
33
|
if (post.author) {
|
|
34
|
-
parts.push(
|
|
35
|
-
Array.isArray(post.author) ? post.author.join(", ") : post.author,
|
|
36
|
-
)
|
|
34
|
+
parts.push(Array.isArray(post.author) ? post.author.join(", ") : post.author)
|
|
37
35
|
}
|
|
38
36
|
if (post.description) parts.push("", post.description)
|
|
39
37
|
return parts.join("\n")
|
|
@@ -77,16 +75,12 @@ export function BlogIndex(props: { sectionPrefix: string }) {
|
|
|
77
75
|
{post.date && <span>{formatDate(post.date)}</span>}
|
|
78
76
|
{post.author && (
|
|
79
77
|
<span>
|
|
80
|
-
{Array.isArray(post.author)
|
|
81
|
-
? post.author.join(", ")
|
|
82
|
-
: post.author}
|
|
78
|
+
{Array.isArray(post.author) ? post.author.join(", ") : post.author}
|
|
83
79
|
</span>
|
|
84
80
|
)}
|
|
85
81
|
</p>
|
|
86
82
|
{post.description && (
|
|
87
|
-
<p className="text-muted-foreground mt-2">
|
|
88
|
-
{post.description}
|
|
89
|
-
</p>
|
|
83
|
+
<p className="text-muted-foreground mt-2">{post.description}</p>
|
|
90
84
|
)}
|
|
91
85
|
</article>
|
|
92
86
|
))}
|
|
@@ -54,12 +54,7 @@ export function Callout(props: {
|
|
|
54
54
|
const title = props.title ?? config.label
|
|
55
55
|
|
|
56
56
|
return (
|
|
57
|
-
<aside
|
|
58
|
-
className={cn(
|
|
59
|
-
"not-prose my-4 rounded-xl border px-4 py-3",
|
|
60
|
-
config.classes,
|
|
61
|
-
)}
|
|
62
|
-
>
|
|
57
|
+
<aside className={cn("not-prose my-4 rounded-xl border px-4 py-3", config.classes)}>
|
|
63
58
|
<div className="flex items-center gap-2 font-semibold text-sm mb-2">
|
|
64
59
|
<Icon className="size-4 shrink-0" />
|
|
65
60
|
<span>{title}</span>
|
|
@@ -74,9 +74,7 @@ export function ChangelogIndex(props: { sectionPrefix: string }) {
|
|
|
74
74
|
</p>
|
|
75
75
|
)}
|
|
76
76
|
{entry.description && (
|
|
77
|
-
<p className="text-muted-foreground mt-2">
|
|
78
|
-
{entry.description}
|
|
79
|
-
</p>
|
|
77
|
+
<p className="text-muted-foreground mt-2">{entry.description}</p>
|
|
80
78
|
)}
|
|
81
79
|
</article>
|
|
82
80
|
))}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { Check, ChevronDown, Clipboard, WrapText } from "lucide-react"
|
|
2
2
|
import { useRef, useState } from "react"
|
|
3
|
-
import {
|
|
4
|
-
Tooltip,
|
|
5
|
-
TooltipContent,
|
|
6
|
-
TooltipTrigger,
|
|
7
|
-
} from "../elements/tooltip.tsx"
|
|
3
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../elements/tooltip.tsx"
|
|
8
4
|
|
|
9
5
|
export function CodeBlock(props: React.ComponentProps<"pre">) {
|
|
10
6
|
const [copied, setCopied] = useState(false)
|
|
@@ -17,9 +13,7 @@ export function CodeBlock(props: React.ComponentProps<"pre">) {
|
|
|
17
13
|
const maxLines = meta?.match(/maxLines=(\d+)/)?.[1]
|
|
18
14
|
const icon = extra.icon as string | undefined
|
|
19
15
|
const style = props.style as Record<string, string> | undefined
|
|
20
|
-
const collapsedHeight = maxLines
|
|
21
|
-
? `${Number(maxLines) * 1.5 + 1.75}rem`
|
|
22
|
-
: undefined
|
|
16
|
+
const collapsedHeight = maxLines ? `${Number(maxLines) * 1.5 + 1.75}rem` : undefined
|
|
23
17
|
|
|
24
18
|
const handleCopy = () => {
|
|
25
19
|
const text = preRef.current?.textContent ?? ""
|
|
@@ -54,9 +48,7 @@ export function CodeBlock(props: React.ComponentProps<"pre">) {
|
|
|
54
48
|
>
|
|
55
49
|
<WrapText className="size-3.5" />
|
|
56
50
|
</TooltipTrigger>
|
|
57
|
-
<TooltipContent>
|
|
58
|
-
{wrap ? "Disable wrap" : "Enable wrap"}
|
|
59
|
-
</TooltipContent>
|
|
51
|
+
<TooltipContent>{wrap ? "Disable wrap" : "Enable wrap"}</TooltipContent>
|
|
60
52
|
</Tooltip>
|
|
61
53
|
<Tooltip>
|
|
62
54
|
<TooltipTrigger
|
|
@@ -83,9 +75,7 @@ export function CodeBlock(props: React.ComponentProps<"pre">) {
|
|
|
83
75
|
>
|
|
84
76
|
<WrapText className="size-3.5" />
|
|
85
77
|
</TooltipTrigger>
|
|
86
|
-
<TooltipContent>
|
|
87
|
-
{wrap ? "Disable wrap" : "Enable wrap"}
|
|
88
|
-
</TooltipContent>
|
|
78
|
+
<TooltipContent>{wrap ? "Disable wrap" : "Enable wrap"}</TooltipContent>
|
|
89
79
|
</Tooltip>
|
|
90
80
|
<Tooltip>
|
|
91
81
|
<TooltipTrigger
|
|
@@ -37,9 +37,7 @@ export function CodeTabs(props: {
|
|
|
37
37
|
useEffect(() => {
|
|
38
38
|
if (!props.sync) return
|
|
39
39
|
const handler = (e: Event) => {
|
|
40
|
-
const { sync, title } = (
|
|
41
|
-
e as CustomEvent<{ sync: string; title: string }>
|
|
42
|
-
).detail
|
|
40
|
+
const { sync, title } = (e as CustomEvent<{ sync: string; title: string }>).detail
|
|
43
41
|
if (sync !== props.sync) return
|
|
44
42
|
const idx = names.indexOf(title)
|
|
45
43
|
if (idx >= 0) setActive(idx)
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/** Grid layout for arranging content side by side */
|
|
2
2
|
export function Columns(props: { cols?: string; children: React.ReactNode }) {
|
|
3
3
|
const cols = props.cols ? parseInt(props.cols, 10) : undefined
|
|
4
|
-
const style = cols
|
|
5
|
-
? { gridTemplateColumns: `repeat(${cols}, 1fr)` }
|
|
6
|
-
: undefined
|
|
4
|
+
const style = cols ? { gridTemplateColumns: `repeat(${cols}, 1fr)` } : undefined
|
|
7
5
|
return (
|
|
8
6
|
<div className="grid gap-6 my-4 sm:grid-cols-2" style={style}>
|
|
9
7
|
{props.children}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
/** Simple wrapper that provides a title prop for ContentTabs to read */
|
|
2
|
-
export function ContentTab(props: {
|
|
3
|
-
title: string
|
|
4
|
-
children: React.ReactNode
|
|
5
|
-
}) {
|
|
2
|
+
export function ContentTab(props: { title: string; children: React.ReactNode }) {
|
|
6
3
|
return <div>{props.children}</div>
|
|
7
4
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { Children, isValidElement, useEffect, useState } from "react"
|
|
2
2
|
|
|
3
3
|
/** Tabbed container component for grouping content tabs with optional sync across groups */
|
|
4
|
-
export function ContentTabs(props: {
|
|
5
|
-
sync?: string
|
|
6
|
-
children: React.ReactNode
|
|
7
|
-
}) {
|
|
4
|
+
export function ContentTabs(props: { sync?: string; children: React.ReactNode }) {
|
|
8
5
|
const children = Children.toArray(props.children)
|
|
9
6
|
const titles = children.map(child =>
|
|
10
7
|
isValidElement<{ title: string }>(child) ? child.props.title : "",
|
|
@@ -38,9 +35,7 @@ export function ContentTabs(props: {
|
|
|
38
35
|
useEffect(() => {
|
|
39
36
|
if (!props.sync) return
|
|
40
37
|
const handler = (e: Event) => {
|
|
41
|
-
const { sync, title } = (
|
|
42
|
-
e as CustomEvent<{ sync: string; title: string }>
|
|
43
|
-
).detail
|
|
38
|
+
const { sync, title } = (e as CustomEvent<{ sync: string; title: string }>).detail
|
|
44
39
|
if (sync !== props.sync) return
|
|
45
40
|
const idx = titles.indexOf(title)
|
|
46
41
|
if (idx >= 0) setActive(idx)
|
|
@@ -70,9 +65,7 @@ export function ContentTabs(props: {
|
|
|
70
65
|
{children.map((child, i) => (
|
|
71
66
|
<div
|
|
72
67
|
key={titles[i]}
|
|
73
|
-
className={
|
|
74
|
-
i === active ? "p-4 prose dark:prose-invert max-w-none" : "hidden"
|
|
75
|
-
}
|
|
68
|
+
className={i === active ? "p-4 prose dark:prose-invert max-w-none" : "hidden"}
|
|
76
69
|
>
|
|
77
70
|
{child}
|
|
78
71
|
</div>
|
|
@@ -13,9 +13,6 @@ export function DefinitionTerm(props: ComponentProps<"dt">) {
|
|
|
13
13
|
/** Styled definition detail with a left border accent */
|
|
14
14
|
export function DefinitionDetail(props: ComponentProps<"dd">) {
|
|
15
15
|
return (
|
|
16
|
-
<dd
|
|
17
|
-
{...props}
|
|
18
|
-
className="ml-0 pl-4 border-l-2 border-border text-muted-foreground"
|
|
19
|
-
/>
|
|
16
|
+
<dd {...props} className="ml-0 pl-4 border-l-2 border-border text-muted-foreground" />
|
|
20
17
|
)
|
|
21
18
|
}
|
|
@@ -21,11 +21,7 @@ function TreeItems(props: { items: TreeItem[]; depth: number }) {
|
|
|
21
21
|
return (
|
|
22
22
|
<ul className={props.depth > 0 ? "ml-4 border-l border-border pl-2" : ""}>
|
|
23
23
|
{props.items.map((item, index) => (
|
|
24
|
-
<TreeNode
|
|
25
|
-
key={`${item.name}-${index}`}
|
|
26
|
-
item={item}
|
|
27
|
-
depth={props.depth}
|
|
28
|
-
/>
|
|
24
|
+
<TreeNode key={`${item.name}-${index}`} item={item} depth={props.depth} />
|
|
29
25
|
))}
|
|
30
26
|
</ul>
|
|
31
27
|
)
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { type ComponentProps, useEffect, useState } from "react"
|
|
2
|
-
import {
|
|
3
|
-
HoverCard,
|
|
4
|
-
HoverCardContent,
|
|
5
|
-
HoverCardTrigger,
|
|
6
|
-
} from "../elements/hover-card.tsx"
|
|
2
|
+
import { HoverCard, HoverCardContent, HoverCardTrigger } from "../elements/hover-card.tsx"
|
|
7
3
|
|
|
8
4
|
const FOOTNOTE_PREFIX = "#user-content-fn-"
|
|
9
5
|
|
|
@@ -13,10 +13,7 @@ export function InlineToc(props: { maxLevel?: string }) {
|
|
|
13
13
|
<p className="text-base font-semibold mb-4">Table of Contents</p>
|
|
14
14
|
<ul className="text-base space-y-2.5">
|
|
15
15
|
{items.map(item => (
|
|
16
|
-
<li
|
|
17
|
-
key={item.url}
|
|
18
|
-
style={{ paddingLeft: `${(item.depth - 2) * 1.25}rem` }}
|
|
19
|
-
>
|
|
16
|
+
<li key={item.url} style={{ paddingLeft: `${(item.depth - 2) * 1.25}rem` }}>
|
|
20
17
|
<a
|
|
21
18
|
href={item.url}
|
|
22
19
|
className="text-muted-foreground hover:text-primary transition-colors"
|
|
@@ -26,10 +26,7 @@ function splatFor(pathname: string) {
|
|
|
26
26
|
return { _splat: pathname.replace(/^\/|\/$/g, "") }
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export function Layout(props: {
|
|
30
|
-
withSidebar?: boolean
|
|
31
|
-
children?: React.ReactNode
|
|
32
|
-
}) {
|
|
29
|
+
export function Layout(props: { withSidebar?: boolean; children?: React.ReactNode }) {
|
|
33
30
|
const pathname = useLocation({ select: l => l.pathname })
|
|
34
31
|
const articleRoute = useMatch({ from: "/$", shouldThrow: false })
|
|
35
32
|
const activeSection = articleRoute
|
|
@@ -56,10 +53,7 @@ export function Layout(props: {
|
|
|
56
53
|
<div className="hidden lg:flex">
|
|
57
54
|
<SidebarTrigger />
|
|
58
55
|
</div>
|
|
59
|
-
<SiteLink
|
|
60
|
-
to={siteLinkTarget}
|
|
61
|
-
className="lg:hidden flex items-center gap-2"
|
|
62
|
-
>
|
|
56
|
+
<SiteLink to={siteLinkTarget} className="lg:hidden flex items-center gap-2">
|
|
63
57
|
<SiteTitle />
|
|
64
58
|
</SiteLink>
|
|
65
59
|
</>
|
|
@@ -100,8 +94,7 @@ export function Layout(props: {
|
|
|
100
94
|
const latestVersion =
|
|
101
95
|
section.type === "changelog" && section.version
|
|
102
96
|
? sortedArticles.find(
|
|
103
|
-
a =>
|
|
104
|
-
a.path === sectionFlatArticles.get(section.prefix)?.[0],
|
|
97
|
+
a => a.path === sectionFlatArticles.get(section.prefix)?.[0],
|
|
105
98
|
)?.title
|
|
106
99
|
: undefined
|
|
107
100
|
return (
|
|
@@ -5,13 +5,7 @@ import { cn } from "../utils/style.ts"
|
|
|
5
5
|
export function LinkButton(props: {
|
|
6
6
|
href: string
|
|
7
7
|
label: string
|
|
8
|
-
variant?:
|
|
9
|
-
| "default"
|
|
10
|
-
| "outline"
|
|
11
|
-
| "secondary"
|
|
12
|
-
| "ghost"
|
|
13
|
-
| "destructive"
|
|
14
|
-
| "link"
|
|
8
|
+
variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" | "link"
|
|
15
9
|
size?: "default" | "sm" | "lg"
|
|
16
10
|
}) {
|
|
17
11
|
return (
|
|
@@ -7,9 +7,7 @@ export function Mermaid(props: { children: string }) {
|
|
|
7
7
|
return (
|
|
8
8
|
<Suspense
|
|
9
9
|
fallback={
|
|
10
|
-
<div className="not-prose mermaid flex justify-center">
|
|
11
|
-
Loading diagram…
|
|
12
|
-
</div>
|
|
10
|
+
<div className="not-prose mermaid flex justify-center">Loading diagram…</div>
|
|
13
11
|
}
|
|
14
12
|
>
|
|
15
13
|
<MermaidRenderer>{props.children}</MermaidRenderer>
|
|
@@ -55,11 +55,7 @@ export function PackageTabs(props: PackageTabsProps) {
|
|
|
55
55
|
className="me-2 p-1 rounded-md text-muted-foreground hover:text-foreground transition-colors"
|
|
56
56
|
aria-label="Copy code"
|
|
57
57
|
>
|
|
58
|
-
{copied ?
|
|
59
|
-
<Check className="size-3.5" />
|
|
60
|
-
) : (
|
|
61
|
-
<Clipboard className="size-3.5" />
|
|
62
|
-
)}
|
|
58
|
+
{copied ? <Check className="size-3.5" /> : <Clipboard className="size-3.5" />}
|
|
63
59
|
</button>
|
|
64
60
|
</div>
|
|
65
61
|
<div className="text-[0.8125rem] py-3.5 overflow-auto max-h-[600px]">
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { useState, useCallback } from "react"
|
|
2
2
|
import { Eye, Pencil, Copy, Check, ExternalLink } from "lucide-react"
|
|
3
3
|
|
|
4
|
+
const LLM_PROMPT = "Read {url}, I want to ask questions about it."
|
|
5
|
+
|
|
4
6
|
/** Toolbar with action buttons displayed for the article content */
|
|
5
7
|
export function PageToolbar(props: {
|
|
6
8
|
file?: string
|
|
@@ -24,13 +26,11 @@ export function PageToolbar(props: {
|
|
|
24
26
|
setTimeout(() => setCopied(false), 2000)
|
|
25
27
|
}, [props.content])
|
|
26
28
|
|
|
27
|
-
const
|
|
28
|
-
(url
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
[props.content],
|
|
33
|
-
)
|
|
29
|
+
const openIn = (base: string, extra?: Record<string, string>) => {
|
|
30
|
+
const q = LLM_PROMPT.replace("{url}", window.location.href)
|
|
31
|
+
const params = new URLSearchParams({ ...extra, q })
|
|
32
|
+
window.open(`${base}?${params}`, "_blank", "noopener,noreferrer")
|
|
33
|
+
}
|
|
34
34
|
|
|
35
35
|
const buttonClass =
|
|
36
36
|
"flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
@@ -59,16 +59,12 @@ export function PageToolbar(props: {
|
|
|
59
59
|
</span>
|
|
60
60
|
)}
|
|
61
61
|
<button type="button" onClick={handleCopy} className={buttonClass}>
|
|
62
|
-
{copied ?
|
|
63
|
-
<Check className="size-3.5" />
|
|
64
|
-
) : (
|
|
65
|
-
<Copy className="size-3.5" />
|
|
66
|
-
)}
|
|
62
|
+
{copied ? <Check className="size-3.5" /> : <Copy className="size-3.5" />}
|
|
67
63
|
Copy Markdown
|
|
68
64
|
</button>
|
|
69
65
|
<button
|
|
70
66
|
type="button"
|
|
71
|
-
onClick={() =>
|
|
67
|
+
onClick={() => openIn("https://chatgpt.com/", { hints: "search" })}
|
|
72
68
|
className={buttonClass}
|
|
73
69
|
>
|
|
74
70
|
<ExternalLink className="size-3.5" />
|
|
@@ -76,7 +72,7 @@ export function PageToolbar(props: {
|
|
|
76
72
|
</button>
|
|
77
73
|
<button
|
|
78
74
|
type="button"
|
|
79
|
-
onClick={() =>
|
|
75
|
+
onClick={() => openIn("https://claude.ai/new")}
|
|
80
76
|
className={buttonClass}
|
|
81
77
|
>
|
|
82
78
|
<ExternalLink className="size-3.5" />
|
|
@@ -18,12 +18,8 @@ export function PrevNext(props: { path: string }) {
|
|
|
18
18
|
|
|
19
19
|
const prevPath = index > 0 ? flat[index - 1] : undefined
|
|
20
20
|
const nextPath = index < flat.length - 1 ? flat[index + 1] : undefined
|
|
21
|
-
const prev = prevPath
|
|
22
|
-
|
|
23
|
-
: undefined
|
|
24
|
-
const next = nextPath
|
|
25
|
-
? sortedArticles.find(a => a.path === nextPath)
|
|
26
|
-
: undefined
|
|
21
|
+
const prev = prevPath ? sortedArticles.find(a => a.path === prevPath) : undefined
|
|
22
|
+
const next = nextPath ? sortedArticles.find(a => a.path === nextPath) : undefined
|
|
27
23
|
|
|
28
24
|
if (!prev && !next) return null
|
|
29
25
|
|
|
@@ -80,9 +80,7 @@ export function SearchDialog(props: {
|
|
|
80
80
|
})
|
|
81
81
|
setResults(
|
|
82
82
|
hits.hits.map(hit => {
|
|
83
|
-
const article = sortedArticles.find(
|
|
84
|
-
a => a.title === hit.document.title,
|
|
85
|
-
)
|
|
83
|
+
const article = sortedArticles.find(a => a.title === hit.document.title)
|
|
86
84
|
if (!article)
|
|
87
85
|
return toResult(
|
|
88
86
|
{
|
|
@@ -161,9 +159,7 @@ export function SearchDialog(props: {
|
|
|
161
159
|
<Icon className="size-5 shrink-0 mt-0.5 self-start opacity-60" />
|
|
162
160
|
)}
|
|
163
161
|
<div className="flex flex-col gap-0.5 min-w-0">
|
|
164
|
-
<span className="text-base font-medium">
|
|
165
|
-
{result.title}
|
|
166
|
-
</span>
|
|
162
|
+
<span className="text-base font-medium">{result.title}</span>
|
|
167
163
|
{result.snippet && (
|
|
168
164
|
<span className="text-sm text-muted-foreground line-clamp-1">
|
|
169
165
|
<HighlightedText text={result.snippet} term={query} />
|