livemark 0.2.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +9 -0
- package/README.md +5 -1
- package/build/actions/changelog/build.d.ts +14 -0
- package/build/actions/changelog/build.js +158 -0
- package/build/actions/changelog/build.unit.js +66 -0
- package/build/actions/config/define.d.ts +6 -0
- package/build/actions/config/define.js +8 -0
- package/build/actions/config/define.unit.js +29 -0
- package/build/actions/config/load.d.ts +5 -0
- package/build/actions/config/load.js +25 -0
- package/build/actions/config/load.unit.js +23 -0
- package/build/commands/build.d.ts +5 -0
- package/build/commands/build.js +14 -0
- package/build/commands/escape.d.ts +9 -0
- package/build/commands/escape.js +56 -0
- package/build/commands/preview.d.ts +5 -0
- package/build/commands/preview.js +18 -0
- package/build/commands/start.d.ts +5 -0
- package/build/commands/start.js +19 -0
- package/build/docs/markdown/includes/example.d.ts +58 -0
- package/build/docs/markdown/includes/example.js +5 -0
- package/build/entrypoints/main.d.ts +2 -0
- package/build/entrypoints/main.js +12 -0
- package/build/helpers/program.d.ts +2 -0
- package/build/helpers/program.js +5 -0
- package/build/index.d.ts +1 -4
- package/build/index.js +2 -5
- package/build/livemark.config.d.ts +58 -0
- package/build/livemark.config.js +25 -0
- package/build/models/config.d.ts +340 -0
- package/build/models/config.js +34 -0
- package/build/models/link.d.ts +13 -0
- package/build/models/link.js +9 -0
- package/build/models/patch.d.ts +21 -0
- package/build/models/patch.js +7 -0
- package/build/models/section.d.ts +75 -0
- package/build/models/section.js +26 -0
- package/build/models/theme.d.ts +72 -0
- package/build/models/theme.js +73 -0
- package/build/program.d.ts +2 -0
- package/build/program.js +16 -0
- package/build/vite.config.d.ts +2 -0
- package/build/vite.config.js +48 -0
- package/build/website/assets/logo.svg +117 -0
- package/build/website/client.tsx +10 -0
- package/build/website/components/Abbr.tsx +17 -0
- package/build/website/components/AnsiCode.tsx +15 -0
- package/build/website/components/Article.tsx +172 -0
- package/build/website/components/BackToTop.tsx +32 -0
- package/build/website/components/Banner.tsx +32 -0
- package/build/website/components/BlogIndex.tsx +121 -0
- package/build/website/components/BlogSidebar.tsx +162 -0
- package/build/website/components/Breadcrumbs.tsx +22 -0
- package/build/website/components/Callout.tsx +72 -0
- package/build/website/components/Card.tsx +48 -0
- package/build/website/components/Cards.tsx +8 -0
- package/build/website/components/ChangelogIndex.tsx +111 -0
- package/build/website/components/ChangelogSidebar.tsx +120 -0
- package/build/website/components/CodeBlock.tsx +135 -0
- package/build/website/components/CodeTabs.tsx +83 -0
- package/build/website/components/Column.tsx +4 -0
- package/build/website/components/Columns.tsx +12 -0
- package/build/website/components/Content.tsx +7 -0
- package/build/website/components/ContentTab.tsx +7 -0
- package/build/website/components/ContentTabs.tsx +82 -0
- package/build/website/components/DefaultCatchBoundary.tsx +54 -0
- package/build/website/components/DefinitionList.tsx +21 -0
- package/build/website/components/Details.tsx +30 -0
- package/build/website/components/FileTree.tsx +52 -0
- package/build/website/components/Footer.tsx +16 -0
- package/build/website/components/FootnoteRef.tsx +52 -0
- package/build/website/components/Heading.tsx +20 -0
- package/build/website/components/InlineBadge.tsx +9 -0
- package/build/website/components/InlineIcon.tsx +10 -0
- package/build/website/components/InlineToc.tsx +31 -0
- package/build/website/components/Layout.tsx +190 -0
- package/build/website/components/LinkButton.tsx +31 -0
- package/build/website/components/Mermaid.tsx +18 -0
- package/build/website/components/MermaidRenderer.tsx +37 -0
- package/build/website/components/MiniSidebar.tsx +49 -0
- package/build/website/components/NotFound.tsx +27 -0
- package/build/website/components/PackageTabs.tsx +74 -0
- package/build/website/components/PageToolbar.tsx +75 -0
- package/build/website/components/PrevNext.tsx +60 -0
- package/build/website/components/Search.tsx +28 -0
- package/build/website/components/SearchDialog.tsx +245 -0
- package/build/website/components/Section.tsx +24 -0
- package/build/website/components/SectionHeader.tsx +35 -0
- package/build/website/components/Sidebar.tsx +160 -0
- package/build/website/components/SidebarLinks.tsx +70 -0
- package/build/website/components/SidebarSections.tsx +71 -0
- package/build/website/components/SiteTitle.tsx +21 -0
- package/build/website/components/SortableTable.tsx +81 -0
- package/build/website/components/SoundCloud.tsx +16 -0
- package/build/website/components/TagIndex.tsx +120 -0
- package/build/website/components/Theme.tsx +39 -0
- package/build/website/components/Toc.tsx +226 -0
- package/build/website/components/YouTube.tsx +16 -0
- package/build/website/components/ZoomImage.tsx +25 -0
- package/build/website/content/article.ts +78 -0
- package/build/website/content/tag.ts +29 -0
- package/build/website/content-collections.ts +208 -0
- package/build/website/elements/accordion.tsx +78 -0
- package/build/website/elements/alert-dialog.tsx +185 -0
- package/build/website/elements/alert.tsx +74 -0
- package/build/website/elements/aspect-ratio.tsx +22 -0
- package/build/website/elements/avatar.tsx +107 -0
- package/build/website/elements/badge.tsx +51 -0
- package/build/website/elements/breadcrumb.tsx +120 -0
- package/build/website/elements/button-group.tsx +87 -0
- package/build/website/elements/button.tsx +57 -0
- package/build/website/elements/calendar.tsx +229 -0
- package/build/website/elements/card.tsx +102 -0
- package/build/website/elements/carousel.tsx +240 -0
- package/build/website/elements/chart.tsx +372 -0
- package/build/website/elements/checkbox.tsx +26 -0
- package/build/website/elements/collapsible.tsx +19 -0
- package/build/website/elements/command.tsx +210 -0
- package/build/website/elements/context-menu.tsx +270 -0
- package/build/website/elements/dialog.tsx +152 -0
- package/build/website/elements/direction.tsx +4 -0
- package/build/website/elements/drawer.tsx +127 -0
- package/build/website/elements/dropdown-menu.tsx +260 -0
- package/build/website/elements/empty.tsx +104 -0
- package/build/website/elements/field.tsx +235 -0
- package/build/website/elements/hover-card.tsx +49 -0
- package/build/website/elements/input-group.tsx +171 -0
- package/build/website/elements/input-otp.tsx +84 -0
- package/build/website/elements/input.tsx +18 -0
- package/build/website/elements/item.tsx +199 -0
- package/build/website/elements/kbd.tsx +26 -0
- package/build/website/elements/label.tsx +17 -0
- package/build/website/elements/menubar.tsx +282 -0
- package/build/website/elements/native-select.tsx +56 -0
- package/build/website/elements/navigation-menu.tsx +171 -0
- package/build/website/elements/pagination.tsx +133 -0
- package/build/website/elements/popover.tsx +88 -0
- package/build/website/elements/progress.tsx +81 -0
- package/build/website/elements/radio-group.tsx +36 -0
- package/build/website/elements/resizable.tsx +48 -0
- package/build/website/elements/scroll-area.tsx +51 -0
- package/build/website/elements/select.tsx +200 -0
- package/build/website/elements/separator.tsx +22 -0
- package/build/website/elements/sheet.tsx +130 -0
- package/build/website/elements/sidebar.tsx +717 -0
- package/build/website/elements/skeleton.tsx +13 -0
- package/build/website/elements/slider.tsx +57 -0
- package/build/website/elements/sonner.tsx +40 -0
- package/build/website/elements/spinner.tsx +16 -0
- package/build/website/elements/switch.tsx +30 -0
- package/build/website/elements/table.tsx +112 -0
- package/build/website/elements/tabs.tsx +79 -0
- package/build/website/elements/textarea.tsx +16 -0
- package/build/website/elements/toggle-group.tsx +87 -0
- package/build/website/elements/toggle.tsx +43 -0
- package/build/website/elements/tooltip.tsx +67 -0
- package/build/website/env.d.ts +14 -0
- package/build/website/helpers/article-icon.ts +61 -0
- package/build/website/helpers/article.ts +90 -0
- package/build/website/helpers/changelog-source.ts +16 -0
- package/build/website/helpers/changelog-source.unit.ts +38 -0
- package/build/website/helpers/dynamic-icon-resolver.tsx +19 -0
- package/build/website/helpers/dynamic-icon.tsx +12 -0
- package/build/website/helpers/favicon.ts +7 -0
- package/build/website/helpers/model.ts +4 -0
- package/build/website/helpers/resolve-asset-path.ts +9 -0
- package/build/website/helpers/resolve-includes.ts +131 -0
- package/build/website/helpers/resolve-includes.unit.ts +126 -0
- package/build/website/helpers/search-text.ts +15 -0
- package/build/website/helpers/section.ts +50 -0
- package/build/website/helpers/section.unit.ts +71 -0
- package/build/website/helpers/style.ts +6 -0
- package/build/website/helpers/theme.ts +27 -0
- package/build/website/helpers/toc-context.ts +10 -0
- package/build/website/helpers/toc.ts +46 -0
- package/build/website/helpers/toc.unit.ts +74 -0
- package/build/website/hooks/in-view.ts +30 -0
- package/build/website/hooks/media.ts +19 -0
- package/build/website/models/article.ts +55 -0
- package/build/website/models/toc.ts +5 -0
- package/build/website/plugins/rehype-inline-code.ts +107 -0
- package/build/website/plugins/rehype-task-list-a11y.ts +33 -0
- package/build/website/plugins/remark-abbr.ts +46 -0
- package/build/website/plugins/remark-abbr.unit.ts +99 -0
- package/build/website/plugins/remark-ansi.ts +248 -0
- package/build/website/plugins/remark-ansi.unit.ts +197 -0
- package/build/website/plugins/remark-badge.ts +50 -0
- package/build/website/plugins/remark-badge.unit.ts +96 -0
- package/build/website/plugins/remark-button.ts +60 -0
- package/build/website/plugins/remark-button.unit.ts +147 -0
- package/build/website/plugins/remark-callout.ts +57 -0
- package/build/website/plugins/remark-card.ts +80 -0
- package/build/website/plugins/remark-code-tabs.ts +87 -0
- package/build/website/plugins/remark-columns.ts +66 -0
- package/build/website/plugins/remark-custom-heading-id.ts +70 -0
- package/build/website/plugins/remark-custom-heading-id.unit.ts +131 -0
- package/build/website/plugins/remark-deflist.ts +36 -0
- package/build/website/plugins/remark-details.ts +49 -0
- package/build/website/plugins/remark-filetree.ts +89 -0
- package/build/website/plugins/remark-filetree.unit.ts +137 -0
- package/build/website/plugins/remark-github-callout.ts +71 -0
- package/build/website/plugins/remark-icon.ts +42 -0
- package/build/website/plugins/remark-image.ts +34 -0
- package/build/website/plugins/remark-media.ts +62 -0
- package/build/website/plugins/remark-media.unit.ts +74 -0
- package/build/website/plugins/remark-mermaid.ts +23 -0
- package/build/website/plugins/remark-npm.ts +52 -0
- package/build/website/plugins/remark-steps.ts +36 -0
- package/build/website/plugins/remark-steps.unit.ts +97 -0
- package/build/website/plugins/remark-tab.ts +100 -0
- package/build/website/plugins/remark-tab.unit.ts +181 -0
- package/build/website/plugins/remark-toc.ts +39 -0
- package/build/website/plugins/remark-toc.unit.ts +82 -0
- package/build/website/plugins/shiki-icon.ts +82 -0
- package/build/website/plugins/shiki-line-highlight.ts +174 -0
- package/build/website/plugins/vite-livemark.ts +91 -0
- package/build/website/routeTree.gen.ts +86 -0
- package/build/website/router.tsx +34 -0
- package/build/website/routes/$.tsx +92 -0
- package/build/website/routes/__root.tsx +97 -0
- package/build/website/server.ts +7 -0
- package/build/website/styles/general.css +163 -0
- package/build/website/styles/markdown.css +214 -0
- package/build/website/vite.config.ts +71 -0
- package/package.json +120 -12
- package/skills/authoring/SKILL.md +97 -0
- package/skills/configuration/SKILL.md +120 -0
- package/skills/customization/SKILL.md +118 -0
- package/build/descriptor/index.d.ts +0 -3
- package/build/descriptor/index.js +0 -4
- package/build/descriptor/load.d.ts +0 -8
- package/build/descriptor/load.js +0 -40
- package/build/descriptor/node.d.ts +0 -125
- package/build/descriptor/node.js +0 -9
- package/build/descriptor/save.d.ts +0 -8
- package/build/descriptor/save.js +0 -17
- package/build/descriptor/save.spec.js +0 -80
- package/build/descriptor/validate.d.ts +0 -9
- package/build/descriptor/validate.js +0 -14
- package/build/descriptor/validate.spec.js +0 -124
- package/build/dialect/Dialect.d.ts +0 -88
- package/build/dialect/Dialect.js +0 -2
- package/build/dialect/index.d.ts +0 -3
- package/build/dialect/index.js +0 -3
- package/build/dialect/load.d.ts +0 -4
- package/build/dialect/load.js +0 -7
- package/build/dialect/save.d.ts +0 -9
- package/build/dialect/save.js +0 -13
- package/build/dialect/validate.d.ts +0 -1
- package/build/dialect/validate.js +0 -4
- package/build/metadata/index.d.ts +0 -3
- package/build/metadata/index.js +0 -4
- package/build/metadata/load.d.ts +0 -10
- package/build/metadata/load.js +0 -55
- package/build/metadata/node.d.ts +0 -125
- package/build/metadata/node.js +0 -9
- package/build/metadata/save.d.ts +0 -8
- package/build/metadata/save.js +0 -17
- package/build/metadata/save.spec.js +0 -80
- package/build/metadata/validate.d.ts +0 -9
- package/build/metadata/validate.js +0 -14
- package/build/metadata/validate.spec.d.ts +0 -1
- package/build/metadata/validate.spec.js +0 -124
- package/build/package/Contributor.d.ts +0 -21
- package/build/package/Contributor.js +0 -2
- package/build/package/Package.d.ts +0 -65
- package/build/package/Package.js +0 -2
- package/build/package/index.d.ts +0 -4
- package/build/package/index.js +0 -3
- package/build/package/load.d.ts +0 -4
- package/build/package/load.js +0 -7
- package/build/package/save.d.ts +0 -9
- package/build/package/save.js +0 -13
- package/build/package/validate.d.ts +0 -1
- package/build/package/validate.js +0 -4
- package/build/resource/License.d.ts +0 -18
- package/build/resource/License.js +0 -2
- package/build/resource/Resource.d.ts +0 -67
- package/build/resource/Resource.js +0 -2
- package/build/resource/Source.d.ts +0 -17
- package/build/resource/Source.js +0 -2
- package/build/resource/index.d.ts +0 -5
- package/build/resource/index.js +0 -2
- package/build/resource/load.d.ts +0 -1
- package/build/resource/load.js +0 -2
- package/build/resource/save.d.ts +0 -9
- package/build/resource/save.js +0 -13
- package/build/resource/types/index.d.ts +0 -1
- package/build/resource/types/index.js +0 -2
- package/build/resource/types/table.d.ts +0 -29
- package/build/resource/types/table.js +0 -2
- package/build/resource/validate.d.ts +0 -1
- package/build/resource/validate.js +0 -4
- package/build/schema/Field.d.ts +0 -5
- package/build/schema/Field.js +0 -2
- package/build/schema/Schema.d.ts +0 -55
- package/build/schema/Schema.js +0 -2
- package/build/schema/fields/any.d.ts +0 -20
- package/build/schema/fields/any.js +0 -2
- package/build/schema/fields/array.d.ts +0 -32
- package/build/schema/fields/array.js +0 -2
- package/build/schema/fields/base.d.ts +0 -42
- package/build/schema/fields/base.js +0 -2
- package/build/schema/fields/boolean.d.ts +0 -28
- package/build/schema/fields/boolean.js +0 -2
- package/build/schema/fields/date.d.ts +0 -35
- package/build/schema/fields/date.js +0 -2
- package/build/schema/fields/datetime.d.ts +0 -35
- package/build/schema/fields/datetime.js +0 -2
- package/build/schema/fields/duration.d.ts +0 -28
- package/build/schema/fields/duration.js +0 -2
- package/build/schema/fields/geojson.d.ts +0 -26
- package/build/schema/fields/geojson.js +0 -2
- package/build/schema/fields/geopoint.d.ts +0 -27
- package/build/schema/fields/geopoint.js +0 -2
- package/build/schema/fields/index.d.ts +0 -16
- package/build/schema/fields/index.js +0 -17
- package/build/schema/fields/integer.d.ts +0 -37
- package/build/schema/fields/integer.js +0 -2
- package/build/schema/fields/list.d.ts +0 -36
- package/build/schema/fields/list.js +0 -2
- package/build/schema/fields/number.d.ts +0 -40
- package/build/schema/fields/number.js +0 -2
- package/build/schema/fields/object.d.ts +0 -32
- package/build/schema/fields/object.js +0 -2
- package/build/schema/fields/string.d.ts +0 -40
- package/build/schema/fields/string.js +0 -2
- package/build/schema/fields/time.d.ts +0 -35
- package/build/schema/fields/time.js +0 -2
- package/build/schema/fields/year.d.ts +0 -28
- package/build/schema/fields/year.js +0 -2
- package/build/schema/fields/yearmonth.d.ts +0 -28
- package/build/schema/fields/yearmonth.js +0 -2
- package/build/schema/index.d.ts +0 -4
- package/build/schema/index.js +0 -2
- package/build/schema/load.d.ts +0 -1
- package/build/schema/load.js +0 -2
- package/build/schema/save.d.ts +0 -9
- package/build/schema/save.js +0 -13
- package/build/schema/validate.d.ts +0 -1
- package/build/schema/validate.js +0 -4
- package/build/tsconfig.tsbuildinfo +0 -1
- package/index.ts +0 -0
- package/tsconfig.json +0 -10
- package/typedoc.json +0 -4
- /package/build/{descriptor/save.spec.d.ts → actions/changelog/build.unit.d.ts} +0 -0
- /package/build/{descriptor/validate.spec.d.ts → actions/config/define.unit.d.ts} +0 -0
- /package/build/{metadata/save.spec.d.ts → actions/config/load.unit.d.ts} +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { allArticles } from "content-collections"
|
|
2
|
+
import type { ArticleGroup } from "../models/article.ts"
|
|
3
|
+
import {
|
|
4
|
+
buildArticleTree,
|
|
5
|
+
flattenArticleTree,
|
|
6
|
+
groupArticleTree,
|
|
7
|
+
} from "../helpers/article.ts"
|
|
8
|
+
import { matchSection, partitionBySection } from "../helpers/section.ts"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Articles sorted by frontmatter `order`:
|
|
12
|
+
* positive values first (ascending), then unordered, then negative values
|
|
13
|
+
* (so `order: -1` lands at the very end, `-2` just before it, and so on).
|
|
14
|
+
*/
|
|
15
|
+
export const sortedArticles = [...allArticles].sort(
|
|
16
|
+
(a, b) => orderKey(a.order) - orderKey(b.order),
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
/** The article whose path is `/`, if any (rendered in place at the root) */
|
|
20
|
+
export const homeArticle = sortedArticles.find(a => a.path === "/")
|
|
21
|
+
|
|
22
|
+
/** Sidebar sections derived from the path tree, partitioned by `group` */
|
|
23
|
+
export const articleGroups = groupArticleTree(
|
|
24
|
+
buildArticleTree(sortedArticles),
|
|
25
|
+
sortedArticles,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
/** Articles in depth-first order across all sections (matches sidebar walk) */
|
|
29
|
+
export const flatArticles = articleGroups.flatMap(group =>
|
|
30
|
+
flattenArticleTree(group.nodes),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
/** The first article in sidebar order, used as the default landing page */
|
|
34
|
+
export const firstArticle = sortedArticles.find(a => a.path === flatArticles[0])
|
|
35
|
+
|
|
36
|
+
function orderKey(order?: number) {
|
|
37
|
+
if (order === undefined) return Number.MAX_SAFE_INTEGER / 2
|
|
38
|
+
if (order < 0) return Number.MAX_SAFE_INTEGER + order
|
|
39
|
+
return order
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const configSections = import.meta.env.CONFIG.sections
|
|
43
|
+
|
|
44
|
+
/** Per-section article groups, keyed by section prefix */
|
|
45
|
+
export const sectionArticleGroups = new Map<string, ArticleGroup[]>()
|
|
46
|
+
|
|
47
|
+
/** Per-section flat article lists, keyed by section prefix */
|
|
48
|
+
export const sectionFlatArticles = new Map<string, string[]>()
|
|
49
|
+
|
|
50
|
+
/** Per-section first article path, keyed by section prefix */
|
|
51
|
+
export const sectionFirstArticle = new Map<string, string | undefined>()
|
|
52
|
+
|
|
53
|
+
if (configSections?.length) {
|
|
54
|
+
const sectionByPrefix = new Map(configSections.map(s => [s.prefix, s]))
|
|
55
|
+
const buckets = partitionBySection(sortedArticles, configSections)
|
|
56
|
+
for (const [key, bucket] of buckets) {
|
|
57
|
+
const section = sectionByPrefix.get(key)
|
|
58
|
+
const sorted =
|
|
59
|
+
section?.type === "blog" || section?.type === "changelog"
|
|
60
|
+
? [...bucket].sort(
|
|
61
|
+
(a, b) =>
|
|
62
|
+
new Date(b.date ?? 0).getTime() - new Date(a.date ?? 0).getTime(),
|
|
63
|
+
)
|
|
64
|
+
: bucket
|
|
65
|
+
const tree = buildArticleTree(sorted)
|
|
66
|
+
const groups = groupArticleTree(tree, sorted)
|
|
67
|
+
const flat = groups.flatMap(g => flattenArticleTree(g.nodes))
|
|
68
|
+
sectionArticleGroups.set(key, groups)
|
|
69
|
+
sectionFlatArticles.set(key, flat)
|
|
70
|
+
sectionFirstArticle.set(key, flat[0])
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Find which config section an article path belongs to */
|
|
75
|
+
export function currentSection(path: string) {
|
|
76
|
+
if (!configSections?.length) return undefined
|
|
77
|
+
return matchSection(path, configSections)
|
|
78
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { sectionFlatArticles, sortedArticles } from "./article.ts"
|
|
2
|
+
|
|
3
|
+
const configSections = import.meta.env.CONFIG.sections
|
|
4
|
+
|
|
5
|
+
/** Per-section tag → article paths mapping. Articles sorted by date descending. */
|
|
6
|
+
export const sectionTags = new Map<string, Map<string, string[]>>()
|
|
7
|
+
|
|
8
|
+
if (configSections?.length) {
|
|
9
|
+
for (const section of configSections) {
|
|
10
|
+
if (section.type !== "blog") continue
|
|
11
|
+
const flat = sectionFlatArticles.get(section.prefix) ?? []
|
|
12
|
+
const tagMap = new Map<string, string[]>()
|
|
13
|
+
for (const path of flat) {
|
|
14
|
+
const article = sortedArticles.find(a => a.path === path)
|
|
15
|
+
if (!article?.tags) continue
|
|
16
|
+
for (const tag of article.tags) {
|
|
17
|
+
const list = tagMap.get(tag)
|
|
18
|
+
if (list) {
|
|
19
|
+
list.push(path)
|
|
20
|
+
} else {
|
|
21
|
+
tagMap.set(tag, [path])
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (tagMap.size > 0) {
|
|
26
|
+
sectionTags.set(section.prefix, tagMap)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { execSync } from "node:child_process"
|
|
2
|
+
import { basename, relative, resolve } from "node:path"
|
|
3
|
+
import { defineCollection, defineConfig } from "@content-collections/core"
|
|
4
|
+
import { compileMDX } from "@content-collections/mdx"
|
|
5
|
+
import rehypeShiki from "@shikijs/rehype"
|
|
6
|
+
import { transformerTwoslash } from "@shikijs/twoslash"
|
|
7
|
+
import rehypeKatex from "rehype-katex"
|
|
8
|
+
import rehypeSlug from "rehype-slug"
|
|
9
|
+
import remarkDefinitionList from "remark-definition-list"
|
|
10
|
+
import remarkDirective from "remark-directive"
|
|
11
|
+
import remarkGemoji from "remark-gemoji"
|
|
12
|
+
import remarkGfm from "remark-gfm"
|
|
13
|
+
import remarkMath from "remark-math"
|
|
14
|
+
import { loadConfig } from "../actions/config/load.ts"
|
|
15
|
+
import { buildChangelog, cacheIncludeGlob } from "../actions/changelog/build.ts"
|
|
16
|
+
import { Article } from "./models/article.ts"
|
|
17
|
+
import { pickDefaultIcon } from "./helpers/article-icon.ts"
|
|
18
|
+
import slugify from "@sindresorhus/slugify"
|
|
19
|
+
import remarkCustomHeadingId from "./plugins/remark-custom-heading-id.ts"
|
|
20
|
+
import { remarkCallout } from "./plugins/remark-callout.ts"
|
|
21
|
+
import { remarkCard } from "./plugins/remark-card.ts"
|
|
22
|
+
import { remarkColumns } from "./plugins/remark-columns.ts"
|
|
23
|
+
import { remarkTab } from "./plugins/remark-tab.ts"
|
|
24
|
+
import { remarkBadge } from "./plugins/remark-badge.ts"
|
|
25
|
+
import { remarkButton } from "./plugins/remark-button.ts"
|
|
26
|
+
import { remarkAbbr } from "./plugins/remark-abbr.ts"
|
|
27
|
+
import { remarkDeflist } from "./plugins/remark-deflist.ts"
|
|
28
|
+
import { remarkDetails } from "./plugins/remark-details.ts"
|
|
29
|
+
import { remarkFiletree } from "./plugins/remark-filetree.ts"
|
|
30
|
+
import { remarkIcon } from "./plugins/remark-icon.ts"
|
|
31
|
+
import { remarkCodeTabs } from "./plugins/remark-code-tabs.ts"
|
|
32
|
+
import { remarkGithubCallout } from "./plugins/remark-github-callout.ts"
|
|
33
|
+
import { remarkImage } from "./plugins/remark-image.ts"
|
|
34
|
+
import { remarkMedia } from "./plugins/remark-media.ts"
|
|
35
|
+
import { remarkAnsi } from "./plugins/remark-ansi.ts"
|
|
36
|
+
import { remarkMermaid } from "./plugins/remark-mermaid.ts"
|
|
37
|
+
import { remarkToc } from "./plugins/remark-toc.ts"
|
|
38
|
+
import { remarkNpm } from "./plugins/remark-npm.ts"
|
|
39
|
+
import { remarkSteps } from "./plugins/remark-steps.ts"
|
|
40
|
+
import {
|
|
41
|
+
transformerLineHighlight,
|
|
42
|
+
transformerNotations,
|
|
43
|
+
} from "./plugins/shiki-line-highlight.ts"
|
|
44
|
+
import { rehypeInlineCode } from "./plugins/rehype-inline-code.ts"
|
|
45
|
+
import { rehypeTaskListA11y } from "./plugins/rehype-task-list-a11y.ts"
|
|
46
|
+
import { transformerIcon } from "./plugins/shiki-icon.ts"
|
|
47
|
+
import { resolveAssetPath } from "./helpers/resolve-asset-path.ts"
|
|
48
|
+
import { resolveIncludes } from "./helpers/resolve-includes.ts"
|
|
49
|
+
import { extractSearchText } from "./helpers/search-text.ts"
|
|
50
|
+
import { extractToc } from "./helpers/toc.ts"
|
|
51
|
+
|
|
52
|
+
const config = await loadConfig()
|
|
53
|
+
|
|
54
|
+
const changelogSections =
|
|
55
|
+
config.sections?.filter(s => s.type === "changelog") ?? []
|
|
56
|
+
for (const section of changelogSections) {
|
|
57
|
+
await buildChangelog(section, config)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const configInclude = Array.isArray(config.include)
|
|
61
|
+
? config.include
|
|
62
|
+
: [config.include]
|
|
63
|
+
const include = changelogSections.length
|
|
64
|
+
? [...configInclude, cacheIncludeGlob()]
|
|
65
|
+
: configInclude
|
|
66
|
+
|
|
67
|
+
// content-collections compiles this file to .content-collections/cache/;
|
|
68
|
+
// going up 2 levels reconstructs the baseDirectory it uses for path resolution
|
|
69
|
+
const baseDir = resolve(import.meta.dirname, "../..")
|
|
70
|
+
const directory = relative(baseDir, config.root) || "."
|
|
71
|
+
|
|
72
|
+
function toPath(filePath: string) {
|
|
73
|
+
const name = basename(filePath).replace(/\.\w+$/, "")
|
|
74
|
+
return slugify(name)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getLastUpdated(filePath: string) {
|
|
78
|
+
try {
|
|
79
|
+
const timestamp = execSync(`git log -1 --format=%cI -- "${filePath}"`, {
|
|
80
|
+
cwd: config.root,
|
|
81
|
+
encoding: "utf-8",
|
|
82
|
+
}).trim()
|
|
83
|
+
return timestamp || undefined
|
|
84
|
+
} catch {
|
|
85
|
+
return undefined
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function extractTitle(content: string, path: string) {
|
|
90
|
+
const match = /^#\s+(.+)$/m.exec(content)
|
|
91
|
+
if (match) return match[1]!
|
|
92
|
+
return (
|
|
93
|
+
path
|
|
94
|
+
.split("/")
|
|
95
|
+
.pop()
|
|
96
|
+
?.replace(/\.\w+$/, "") ?? path
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const articles = defineCollection({
|
|
101
|
+
name: "articles",
|
|
102
|
+
directory,
|
|
103
|
+
include,
|
|
104
|
+
exclude: config.exclude,
|
|
105
|
+
schema: Article,
|
|
106
|
+
transform: async (document, context) => {
|
|
107
|
+
const patch = config.patches?.find(p => p.file === document._meta.filePath)
|
|
108
|
+
const doc = patch ? { ...document, ...patch.article } : document
|
|
109
|
+
const filePath = resolve(config.root, doc._meta.filePath)
|
|
110
|
+
const content = resolveIncludes(doc.content, filePath)
|
|
111
|
+
const title = doc.title ?? extractTitle(content, doc._meta.path)
|
|
112
|
+
const icon = doc.icon ?? pickDefaultIcon(doc._meta.path)
|
|
113
|
+
const path = doc.path ?? toPath(doc._meta.filePath)
|
|
114
|
+
const mdx = await compileMDX(
|
|
115
|
+
context,
|
|
116
|
+
{ ...doc, content },
|
|
117
|
+
{
|
|
118
|
+
remarkPlugins: [
|
|
119
|
+
remarkGfm,
|
|
120
|
+
remarkGemoji,
|
|
121
|
+
remarkDefinitionList,
|
|
122
|
+
remarkDeflist,
|
|
123
|
+
remarkMath,
|
|
124
|
+
remarkDirective,
|
|
125
|
+
remarkCallout,
|
|
126
|
+
remarkCard,
|
|
127
|
+
remarkColumns,
|
|
128
|
+
remarkTab,
|
|
129
|
+
remarkDetails,
|
|
130
|
+
remarkFiletree,
|
|
131
|
+
remarkIcon,
|
|
132
|
+
remarkBadge,
|
|
133
|
+
remarkButton,
|
|
134
|
+
remarkAbbr,
|
|
135
|
+
remarkGithubCallout,
|
|
136
|
+
[
|
|
137
|
+
remarkImage,
|
|
138
|
+
{
|
|
139
|
+
filePath: resolve(config.root, doc._meta.filePath),
|
|
140
|
+
root: config.root,
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
remarkAnsi,
|
|
144
|
+
remarkMermaid,
|
|
145
|
+
remarkMedia,
|
|
146
|
+
remarkToc,
|
|
147
|
+
remarkNpm,
|
|
148
|
+
remarkCodeTabs,
|
|
149
|
+
remarkSteps,
|
|
150
|
+
remarkCustomHeadingId,
|
|
151
|
+
],
|
|
152
|
+
rehypePlugins: [
|
|
153
|
+
[
|
|
154
|
+
rehypeShiki,
|
|
155
|
+
{
|
|
156
|
+
themes: {
|
|
157
|
+
light: config.codeThemeLight,
|
|
158
|
+
dark: config.codeThemeDark,
|
|
159
|
+
},
|
|
160
|
+
// Darken catppuccin-latte's green (the colour used for strings and
|
|
161
|
+
// some comments) — the theme default #40A02B lands at 3.2:1 on the
|
|
162
|
+
// code-block background, below the WCAG AA 4.5:1 threshold.
|
|
163
|
+
colorReplacements: {
|
|
164
|
+
"catppuccin-latte": {
|
|
165
|
+
"#40a02b": "#2a7e16",
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
transformers: [
|
|
169
|
+
transformerTwoslash({ explicitTrigger: true }),
|
|
170
|
+
transformerIcon(),
|
|
171
|
+
transformerNotations(),
|
|
172
|
+
transformerLineHighlight(),
|
|
173
|
+
],
|
|
174
|
+
parseMetaString: (meta: string) => ({ "data-meta": meta }),
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
rehypeInlineCode,
|
|
178
|
+
rehypeSlug,
|
|
179
|
+
rehypeKatex,
|
|
180
|
+
rehypeTaskListA11y,
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
)
|
|
184
|
+
const tocItems = extractToc(content)
|
|
185
|
+
const searchText = extractSearchText(content)
|
|
186
|
+
const lastUpdated = getLastUpdated(doc._meta.filePath)
|
|
187
|
+
const image = doc.image
|
|
188
|
+
? resolveAssetPath(doc.image, filePath, config.root)
|
|
189
|
+
: undefined
|
|
190
|
+
return {
|
|
191
|
+
...doc,
|
|
192
|
+
file: doc._meta.filePath,
|
|
193
|
+
lastUpdated,
|
|
194
|
+
image,
|
|
195
|
+
title,
|
|
196
|
+
icon,
|
|
197
|
+
path,
|
|
198
|
+
tocItems,
|
|
199
|
+
searchText,
|
|
200
|
+
mdx,
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
export default defineConfig({
|
|
206
|
+
// @ts-expect-error tsgo picks wrong overload when rehype-slug augments unified types
|
|
207
|
+
content: [articles],
|
|
208
|
+
})
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion"
|
|
2
|
+
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
|
3
|
+
|
|
4
|
+
import { cn } from "../helpers/style.ts"
|
|
5
|
+
|
|
6
|
+
function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {
|
|
7
|
+
return (
|
|
8
|
+
<AccordionPrimitive.Root
|
|
9
|
+
data-slot="accordion"
|
|
10
|
+
className={cn("flex w-full flex-col", className)}
|
|
11
|
+
{...props}
|
|
12
|
+
/>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {
|
|
17
|
+
return (
|
|
18
|
+
<AccordionPrimitive.Item
|
|
19
|
+
data-slot="accordion-item"
|
|
20
|
+
className={cn("not-last:border-b", className)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function AccordionTrigger({
|
|
27
|
+
className,
|
|
28
|
+
children,
|
|
29
|
+
...props
|
|
30
|
+
}: AccordionPrimitive.Trigger.Props) {
|
|
31
|
+
return (
|
|
32
|
+
<AccordionPrimitive.Header className="flex">
|
|
33
|
+
<AccordionPrimitive.Trigger
|
|
34
|
+
data-slot="accordion-trigger"
|
|
35
|
+
className={cn(
|
|
36
|
+
"group/accordion-trigger relative flex flex-1 items-start justify-between rounded-md border border-transparent py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:after:border-ring aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
|
|
37
|
+
className,
|
|
38
|
+
)}
|
|
39
|
+
{...props}
|
|
40
|
+
>
|
|
41
|
+
{children}
|
|
42
|
+
<ChevronDownIcon
|
|
43
|
+
data-slot="accordion-trigger-icon"
|
|
44
|
+
className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden"
|
|
45
|
+
/>
|
|
46
|
+
<ChevronUpIcon
|
|
47
|
+
data-slot="accordion-trigger-icon"
|
|
48
|
+
className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline"
|
|
49
|
+
/>
|
|
50
|
+
</AccordionPrimitive.Trigger>
|
|
51
|
+
</AccordionPrimitive.Header>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function AccordionContent({
|
|
56
|
+
className,
|
|
57
|
+
children,
|
|
58
|
+
...props
|
|
59
|
+
}: AccordionPrimitive.Panel.Props) {
|
|
60
|
+
return (
|
|
61
|
+
<AccordionPrimitive.Panel
|
|
62
|
+
data-slot="accordion-content"
|
|
63
|
+
className="overflow-hidden text-sm data-open:animate-accordion-down data-closed:animate-accordion-up"
|
|
64
|
+
{...props}
|
|
65
|
+
>
|
|
66
|
+
<div
|
|
67
|
+
className={cn(
|
|
68
|
+
"h-(--accordion-panel-height) pt-0 pb-4 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
|
69
|
+
className,
|
|
70
|
+
)}
|
|
71
|
+
>
|
|
72
|
+
{children}
|
|
73
|
+
</div>
|
|
74
|
+
</AccordionPrimitive.Panel>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"
|
|
3
|
+
|
|
4
|
+
import { cn } from "../helpers/style.ts"
|
|
5
|
+
import { Button } from "./button.tsx"
|
|
6
|
+
|
|
7
|
+
function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
|
|
8
|
+
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
|
|
12
|
+
return (
|
|
13
|
+
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
|
|
18
|
+
return (
|
|
19
|
+
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function AlertDialogOverlay({
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: AlertDialogPrimitive.Backdrop.Props) {
|
|
27
|
+
return (
|
|
28
|
+
<AlertDialogPrimitive.Backdrop
|
|
29
|
+
data-slot="alert-dialog-overlay"
|
|
30
|
+
className={cn(
|
|
31
|
+
"fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
|
32
|
+
className,
|
|
33
|
+
)}
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function AlertDialogContent({
|
|
40
|
+
className,
|
|
41
|
+
size = "default",
|
|
42
|
+
...props
|
|
43
|
+
}: AlertDialogPrimitive.Popup.Props & {
|
|
44
|
+
size?: "default" | "sm"
|
|
45
|
+
}) {
|
|
46
|
+
return (
|
|
47
|
+
<AlertDialogPortal>
|
|
48
|
+
<AlertDialogOverlay />
|
|
49
|
+
<AlertDialogPrimitive.Popup
|
|
50
|
+
data-slot="alert-dialog-content"
|
|
51
|
+
data-size={size}
|
|
52
|
+
className={cn(
|
|
53
|
+
"group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-6 rounded-xl bg-popover p-6 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
54
|
+
className,
|
|
55
|
+
)}
|
|
56
|
+
{...props}
|
|
57
|
+
/>
|
|
58
|
+
</AlertDialogPortal>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function AlertDialogHeader({
|
|
63
|
+
className,
|
|
64
|
+
...props
|
|
65
|
+
}: React.ComponentProps<"div">) {
|
|
66
|
+
return (
|
|
67
|
+
<div
|
|
68
|
+
data-slot="alert-dialog-header"
|
|
69
|
+
className={cn(
|
|
70
|
+
"grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
|
|
71
|
+
className,
|
|
72
|
+
)}
|
|
73
|
+
{...props}
|
|
74
|
+
/>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function AlertDialogFooter({
|
|
79
|
+
className,
|
|
80
|
+
...props
|
|
81
|
+
}: React.ComponentProps<"div">) {
|
|
82
|
+
return (
|
|
83
|
+
<div
|
|
84
|
+
data-slot="alert-dialog-footer"
|
|
85
|
+
className={cn(
|
|
86
|
+
"flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
|
|
87
|
+
className,
|
|
88
|
+
)}
|
|
89
|
+
{...props}
|
|
90
|
+
/>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function AlertDialogMedia({
|
|
95
|
+
className,
|
|
96
|
+
...props
|
|
97
|
+
}: React.ComponentProps<"div">) {
|
|
98
|
+
return (
|
|
99
|
+
<div
|
|
100
|
+
data-slot="alert-dialog-media"
|
|
101
|
+
className={cn(
|
|
102
|
+
"mb-2 inline-flex size-16 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-8",
|
|
103
|
+
className,
|
|
104
|
+
)}
|
|
105
|
+
{...props}
|
|
106
|
+
/>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function AlertDialogTitle({
|
|
111
|
+
className,
|
|
112
|
+
...props
|
|
113
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
|
|
114
|
+
return (
|
|
115
|
+
<AlertDialogPrimitive.Title
|
|
116
|
+
data-slot="alert-dialog-title"
|
|
117
|
+
className={cn(
|
|
118
|
+
"cn-font-heading text-lg font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
|
|
119
|
+
className,
|
|
120
|
+
)}
|
|
121
|
+
{...props}
|
|
122
|
+
/>
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function AlertDialogDescription({
|
|
127
|
+
className,
|
|
128
|
+
...props
|
|
129
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
|
|
130
|
+
return (
|
|
131
|
+
<AlertDialogPrimitive.Description
|
|
132
|
+
data-slot="alert-dialog-description"
|
|
133
|
+
className={cn(
|
|
134
|
+
"text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
135
|
+
className,
|
|
136
|
+
)}
|
|
137
|
+
{...props}
|
|
138
|
+
/>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function AlertDialogAction({
|
|
143
|
+
className,
|
|
144
|
+
...props
|
|
145
|
+
}: React.ComponentProps<typeof Button>) {
|
|
146
|
+
return (
|
|
147
|
+
<Button
|
|
148
|
+
data-slot="alert-dialog-action"
|
|
149
|
+
className={cn(className)}
|
|
150
|
+
{...props}
|
|
151
|
+
/>
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function AlertDialogCancel({
|
|
156
|
+
className,
|
|
157
|
+
variant = "outline",
|
|
158
|
+
size = "default",
|
|
159
|
+
...props
|
|
160
|
+
}: AlertDialogPrimitive.Close.Props &
|
|
161
|
+
Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
|
|
162
|
+
return (
|
|
163
|
+
<AlertDialogPrimitive.Close
|
|
164
|
+
data-slot="alert-dialog-cancel"
|
|
165
|
+
className={cn(className)}
|
|
166
|
+
render={<Button variant={variant} size={size} />}
|
|
167
|
+
{...props}
|
|
168
|
+
/>
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export {
|
|
173
|
+
AlertDialog,
|
|
174
|
+
AlertDialogAction,
|
|
175
|
+
AlertDialogCancel,
|
|
176
|
+
AlertDialogContent,
|
|
177
|
+
AlertDialogDescription,
|
|
178
|
+
AlertDialogFooter,
|
|
179
|
+
AlertDialogHeader,
|
|
180
|
+
AlertDialogMedia,
|
|
181
|
+
AlertDialogOverlay,
|
|
182
|
+
AlertDialogPortal,
|
|
183
|
+
AlertDialogTitle,
|
|
184
|
+
AlertDialogTrigger,
|
|
185
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
+
import { cn } from "../helpers/style.ts"
|
|
3
|
+
|
|
4
|
+
const alertVariants = cva(
|
|
5
|
+
"grid gap-0.5 rounded-lg border px-4 py-3 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert",
|
|
6
|
+
{
|
|
7
|
+
variants: {
|
|
8
|
+
variant: {
|
|
9
|
+
default: "bg-card text-card-foreground",
|
|
10
|
+
destructive:
|
|
11
|
+
"text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
defaultVariants: {
|
|
15
|
+
variant: "default",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
function Alert({
|
|
21
|
+
className,
|
|
22
|
+
variant,
|
|
23
|
+
...props
|
|
24
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
|
|
25
|
+
return (
|
|
26
|
+
<div
|
|
27
|
+
data-slot="alert"
|
|
28
|
+
role="alert"
|
|
29
|
+
className={cn(alertVariants({ variant }), className)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
36
|
+
return (
|
|
37
|
+
<div
|
|
38
|
+
data-slot="alert-title"
|
|
39
|
+
className={cn(
|
|
40
|
+
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3",
|
|
41
|
+
className,
|
|
42
|
+
)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function AlertDescription({
|
|
49
|
+
className,
|
|
50
|
+
...props
|
|
51
|
+
}: React.ComponentProps<"div">) {
|
|
52
|
+
return (
|
|
53
|
+
<div
|
|
54
|
+
data-slot="alert-description"
|
|
55
|
+
className={cn(
|
|
56
|
+
"text-muted-foreground text-sm text-balance md:text-pretty [&_p:not(:last-child)]:mb-4 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3",
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
65
|
+
return (
|
|
66
|
+
<div
|
|
67
|
+
data-slot="alert-action"
|
|
68
|
+
className={cn("absolute top-2.5 right-3", className)}
|
|
69
|
+
{...props}
|
|
70
|
+
/>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { Alert, AlertTitle, AlertDescription, AlertAction }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { cn } from "../helpers/style.ts"
|
|
2
|
+
|
|
3
|
+
function AspectRatio({
|
|
4
|
+
ratio,
|
|
5
|
+
className,
|
|
6
|
+
...props
|
|
7
|
+
}: React.ComponentProps<"div"> & { ratio: number }) {
|
|
8
|
+
return (
|
|
9
|
+
<div
|
|
10
|
+
data-slot="aspect-ratio"
|
|
11
|
+
style={
|
|
12
|
+
{
|
|
13
|
+
"--ratio": ratio,
|
|
14
|
+
} as React.CSSProperties
|
|
15
|
+
}
|
|
16
|
+
className={cn("relative aspect-(--ratio)", className)}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { AspectRatio }
|