livemark 0.7.2 → 0.9.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 +115 -4
- package/package.json +15 -14
- package/source/actions/changelog/build.ts +245 -0
- package/source/actions/changelog/build.unit.ts +69 -0
- package/source/actions/config/define.ts +11 -0
- package/source/actions/config/define.unit.ts +33 -0
- package/source/actions/config/load.ts +22 -0
- package/source/actions/config/load.unit.ts +30 -0
- package/source/commands/build.ts +21 -0
- package/source/commands/escape.ts +77 -0
- package/source/commands/preview.ts +25 -0
- package/source/commands/start.ts +26 -0
- package/{build/website → source}/components/Article.tsx +44 -44
- package/{build/website → source}/components/Callout.tsx +1 -1
- package/{build/website → source}/components/Layout.tsx +3 -14
- package/{build/website → source}/components/LinkButton.tsx +1 -1
- package/{build/website → source}/components/PageToolbar.tsx +21 -8
- package/{build/website → source}/components/Section.tsx +1 -1
- package/{build/website → source}/components/SectionHeader.tsx +1 -1
- package/{build/website/components/MiniSidebar.tsx → source/components/Sidebar.tsx} +21 -5
- package/{build/website/components/Sidebar.tsx → source/components/SidebarArticles.tsx} +22 -55
- package/source/components/SidebarPosts.tsx +129 -0
- package/source/components/SidebarReleases.tsx +85 -0
- package/{build/website → source}/content-collections.ts +12 -3
- package/{build/website → source}/elements/accordion.tsx +1 -1
- package/{build/website → source}/elements/alert-dialog.tsx +1 -1
- package/{build/website → source}/elements/alert.tsx +1 -1
- package/{build/website → source}/elements/aspect-ratio.tsx +1 -1
- package/{build/website → source}/elements/avatar.tsx +1 -1
- package/{build/website → source}/elements/badge.tsx +1 -1
- package/{build/website → source}/elements/breadcrumb.tsx +1 -1
- package/{build/website → source}/elements/button-group.tsx +1 -1
- package/{build/website → source}/elements/button.tsx +1 -1
- package/{build/website → source}/elements/calendar.tsx +1 -1
- package/{build/website → source}/elements/card.tsx +1 -1
- package/{build/website → source}/elements/carousel.tsx +1 -1
- package/{build/website → source}/elements/chart.tsx +1 -1
- package/{build/website → source}/elements/checkbox.tsx +1 -1
- package/{build/website → source}/elements/command.tsx +1 -1
- package/{build/website → source}/elements/context-menu.tsx +1 -1
- package/{build/website → source}/elements/dialog.tsx +1 -1
- package/{build/website → source}/elements/drawer.tsx +1 -1
- package/{build/website → source}/elements/dropdown-menu.tsx +1 -1
- package/{build/website → source}/elements/empty.tsx +1 -1
- package/{build/website → source}/elements/field.tsx +1 -1
- package/{build/website → source}/elements/hover-card.tsx +1 -1
- package/{build/website → source}/elements/input-group.tsx +1 -1
- package/{build/website → source}/elements/input-otp.tsx +1 -1
- package/{build/website → source}/elements/input.tsx +1 -1
- package/{build/website → source}/elements/item.tsx +1 -1
- package/{build/website → source}/elements/kbd.tsx +1 -1
- package/{build/website → source}/elements/label.tsx +1 -1
- package/{build/website → source}/elements/menubar.tsx +1 -1
- package/{build/website → source}/elements/native-select.tsx +1 -1
- package/{build/website → source}/elements/navigation-menu.tsx +1 -1
- package/{build/website → source}/elements/pagination.tsx +1 -1
- package/{build/website → source}/elements/popover.tsx +1 -1
- package/{build/website → source}/elements/progress.tsx +1 -1
- package/{build/website → source}/elements/radio-group.tsx +1 -1
- package/{build/website → source}/elements/resizable.tsx +1 -1
- package/{build/website → source}/elements/scroll-area.tsx +1 -1
- package/{build/website → source}/elements/select.tsx +1 -1
- package/{build/website → source}/elements/separator.tsx +1 -1
- package/{build/website → source}/elements/sheet.tsx +1 -1
- package/{build/website → source}/elements/sidebar.tsx +7 -4
- package/{build/website → source}/elements/skeleton.tsx +1 -1
- package/{build/website → source}/elements/slider.tsx +1 -1
- package/{build/website → source}/elements/spinner.tsx +1 -1
- package/{build/website → source}/elements/switch.tsx +1 -1
- package/{build/website → source}/elements/table.tsx +1 -1
- package/{build/website → source}/elements/tabs.tsx +1 -1
- package/{build/website → source}/elements/textarea.tsx +1 -1
- package/{build/website → source}/elements/toggle-group.tsx +1 -1
- package/{build/website → source}/elements/toggle.tsx +1 -1
- package/{build/website → source}/elements/tooltip.tsx +1 -1
- package/source/entrypoints/main.ts +12 -0
- package/{build/website → source}/env.d.ts +1 -1
- package/source/helpers/program.ts +6 -0
- package/{build/website → source}/helpers/section.ts +1 -1
- package/source/hooks/media.ts +29 -0
- package/source/index.ts +1 -0
- package/{build/website → source}/models/article.ts +5 -0
- package/source/models/config.ts +51 -0
- package/source/models/link.ts +11 -0
- package/source/models/patch.ts +9 -0
- package/source/models/section.ts +45 -0
- package/source/models/theme.ts +74 -0
- package/source/program.ts +18 -0
- package/source/settings.ts +6 -0
- package/{build/website → source}/vite.config.ts +14 -9
- package/{build → target}/actions/changelog/build.d.ts +1 -0
- package/target/actions/changelog/build.js +187 -0
- package/target/actions/changelog/build.unit.js +66 -0
- package/target/actions/config/define.js +8 -0
- package/target/actions/config/define.unit.js +29 -0
- package/target/actions/config/load.js +25 -0
- package/target/actions/config/load.unit.js +23 -0
- package/target/client.d.ts +1 -0
- package/target/client.js +6 -0
- package/target/commands/build.js +14 -0
- package/target/commands/escape.js +56 -0
- package/target/commands/preview.js +18 -0
- package/target/commands/start.js +19 -0
- package/target/components/Abbr.d.ts +5 -0
- package/target/components/Abbr.js +9 -0
- package/target/components/AnsiCode.d.ts +4 -0
- package/target/components/AnsiCode.js +6 -0
- package/target/components/Article.d.ts +5 -0
- package/target/components/Article.js +104 -0
- package/target/components/BackToTop.d.ts +3 -0
- package/target/components/BackToTop.js +19 -0
- package/target/components/Banner.d.ts +2 -0
- package/target/components/Banner.js +12 -0
- package/target/components/BlogIndex.d.ts +4 -0
- package/target/components/BlogIndex.js +62 -0
- package/target/components/Breadcrumbs.d.ts +1 -0
- package/target/components/Breadcrumbs.js +13 -0
- package/target/components/Callout.d.ts +8 -0
- package/target/components/Callout.js +43 -0
- package/target/components/Card.d.ts +7 -0
- package/target/components/Card.js +17 -0
- package/target/components/Cards.d.ts +4 -0
- package/target/components/Cards.js +6 -0
- package/target/components/ChangelogIndex.d.ts +4 -0
- package/target/components/ChangelogIndex.js +57 -0
- package/target/components/CodeBlock.d.ts +1 -0
- package/target/components/CodeBlock.js +47 -0
- package/target/components/CodeTabs.d.ts +6 -0
- package/target/components/CodeTabs.js +49 -0
- package/target/components/Column.d.ts +4 -0
- package/target/components/Column.js +6 -0
- package/target/components/Columns.d.ts +5 -0
- package/target/components/Columns.js +10 -0
- package/target/components/Content.d.ts +3 -0
- package/target/components/Content.js +5 -0
- package/target/components/ContentTab.d.ts +5 -0
- package/target/components/ContentTab.js +6 -0
- package/target/components/ContentTabs.d.ts +5 -0
- package/target/components/ContentTabs.js +47 -0
- package/target/components/DefaultCatchBoundary.d.ts +2 -0
- package/target/components/DefaultCatchBoundary.js +20 -0
- package/target/components/DefinitionList.d.ts +7 -0
- package/target/components/DefinitionList.js +14 -0
- package/target/components/Details.d.ts +5 -0
- package/target/components/Details.js +13 -0
- package/target/components/FileTree.d.ts +4 -0
- package/target/components/FileTree.js +17 -0
- package/target/components/Footer.d.ts +2 -0
- package/target/components/Footer.js +9 -0
- package/target/components/FootnoteRef.d.ts +3 -0
- package/target/components/FootnoteRef.js +31 -0
- package/target/components/Heading.d.ts +8 -0
- package/target/components/Heading.js +18 -0
- package/target/components/InlineBadge.d.ts +5 -0
- package/target/components/InlineBadge.js +7 -0
- package/target/components/InlineIcon.d.ts +5 -0
- package/target/components/InlineIcon.js +10 -0
- package/target/components/InlineToc.d.ts +4 -0
- package/target/components/InlineToc.js +14 -0
- package/target/components/Layout.d.ts +4 -0
- package/target/components/Layout.js +65 -0
- package/target/components/LinkButton.d.ts +7 -0
- package/target/components/LinkButton.js +11 -0
- package/target/components/Mermaid.d.ts +4 -0
- package/target/components/Mermaid.js +8 -0
- package/target/components/MermaidRenderer.d.ts +4 -0
- package/target/components/MermaidRenderer.js +32 -0
- package/target/components/NotFound.d.ts +3 -0
- package/target/components/NotFound.js +10 -0
- package/target/components/PackageTabs.d.ts +9 -0
- package/target/components/PackageTabs.js +28 -0
- package/target/components/PageToolbar.d.ts +7 -0
- package/target/components/PageToolbar.js +34 -0
- package/target/components/PrevNext.d.ts +4 -0
- package/target/components/PrevNext.js +34 -0
- package/target/components/Search.d.ts +2 -0
- package/target/components/Search.js +16 -0
- package/target/components/SearchDialog.d.ts +5 -0
- package/target/components/SearchDialog.js +139 -0
- package/target/components/Section.d.ts +5 -0
- package/target/components/Section.js +8 -0
- package/target/components/SectionHeader.d.ts +7 -0
- package/target/components/SectionHeader.js +7 -0
- package/target/components/Sidebar.d.ts +4 -0
- package/target/components/Sidebar.js +33 -0
- package/target/components/SidebarArticles.d.ts +2 -0
- package/target/components/SidebarArticles.js +45 -0
- package/target/components/SidebarLinks.d.ts +4 -0
- package/target/components/SidebarLinks.js +26 -0
- package/target/components/SidebarPosts.d.ts +2 -0
- package/target/components/SidebarPosts.js +53 -0
- package/target/components/SidebarReleases.d.ts +2 -0
- package/target/components/SidebarReleases.js +35 -0
- package/target/components/SidebarSections.d.ts +4 -0
- package/target/components/SidebarSections.js +36 -0
- package/target/components/SiteTitle.d.ts +2 -0
- package/target/components/SiteTitle.js +12 -0
- package/target/components/SortableTable.d.ts +5 -0
- package/target/components/SortableTable.js +63 -0
- package/target/components/SoundCloud.d.ts +4 -0
- package/target/components/SoundCloud.js +7 -0
- package/target/components/TagIndex.d.ts +5 -0
- package/target/components/TagIndex.js +64 -0
- package/target/components/Theme.d.ts +1 -0
- package/target/components/Theme.js +21 -0
- package/target/components/Toc.d.ts +12 -0
- package/target/components/Toc.js +128 -0
- package/target/components/YouTube.d.ts +4 -0
- package/target/components/YouTube.js +6 -0
- package/target/components/ZoomImage.d.ts +4 -0
- package/target/components/ZoomImage.js +26 -0
- package/target/content/article.d.ts +43 -0
- package/target/content/article.js +54 -0
- package/target/content/tag.d.ts +2 -0
- package/target/content/tag.js +30 -0
- package/target/content-collections.d.ts +2 -0
- package/target/content-collections.js +200 -0
- package/target/elements/accordion.d.ts +6 -0
- package/target/elements/accordion.js +19 -0
- package/target/elements/alert-dialog.d.ts +18 -0
- package/target/elements/alert-dialog.js +44 -0
- package/target/elements/alert.d.ts +9 -0
- package/target/elements/alert.js +28 -0
- package/target/elements/aspect-ratio.d.ts +4 -0
- package/target/elements/aspect-ratio.js +9 -0
- package/target/elements/avatar.d.ts +11 -0
- package/target/elements/avatar.js +23 -0
- package/target/elements/badge.d.ts +7 -0
- package/target/elements/badge.js +34 -0
- package/target/elements/breadcrumb.d.ts +9 -0
- package/target/elements/breadcrumb.js +39 -0
- package/target/elements/button-group.d.ts +10 -0
- package/target/elements/button-group.js +37 -0
- package/target/elements/button.d.ts +8 -0
- package/target/elements/button.js +35 -0
- package/target/elements/calendar.d.ts +10 -0
- package/target/elements/calendar.js +76 -0
- package/target/elements/card.d.ts +11 -0
- package/target/elements/card.js +25 -0
- package/target/elements/carousel.d.ts +28 -0
- package/target/elements/carousel.js +95 -0
- package/target/elements/chart.d.ts +44 -0
- package/target/elements/chart.js +140 -0
- package/target/elements/checkbox.d.ts +3 -0
- package/target/elements/checkbox.js +9 -0
- package/target/elements/collapsible.d.ts +5 -0
- package/target/elements/collapsible.js +13 -0
- package/target/elements/command.d.ts +23 -0
- package/target/elements/command.js +42 -0
- package/target/elements/context-menu.d.ts +29 -0
- package/target/elements/context-menu.js +54 -0
- package/target/elements/dialog.d.ts +16 -0
- package/target/elements/dialog.js +41 -0
- package/target/elements/direction.d.ts +1 -0
- package/target/elements/direction.js +2 -0
- package/target/elements/drawer.d.ts +12 -0
- package/target/elements/drawer.js +38 -0
- package/target/elements/dropdown-menu.d.ts +24 -0
- package/target/elements/dropdown-menu.js +54 -0
- package/target/elements/empty.d.ts +11 -0
- package/target/elements/empty.js +34 -0
- package/target/elements/field.d.ts +24 -0
- package/target/elements/field.js +69 -0
- package/target/elements/hover-card.d.ts +5 -0
- package/target/elements/hover-card.js +14 -0
- package/target/elements/input-group.d.ts +18 -0
- package/target/elements/input-group.js +60 -0
- package/target/elements/input-otp.d.ts +11 -0
- package/target/elements/input-otp.js +21 -0
- package/target/elements/input.d.ts +2 -0
- package/target/elements/input.js +8 -0
- package/target/elements/item.d.ts +21 -0
- package/target/elements/item.js +79 -0
- package/target/elements/kbd.d.ts +3 -0
- package/target/elements/kbd.js +10 -0
- package/target/elements/label.d.ts +2 -0
- package/target/elements/label.js +8 -0
- package/target/elements/menubar.d.ts +29 -0
- package/target/elements/menubar.js +58 -0
- package/target/elements/native-select.d.ts +8 -0
- package/target/elements/native-select.js +16 -0
- package/target/elements/navigation-menu.d.ts +11 -0
- package/target/elements/navigation-menu.js +34 -0
- package/target/elements/pagination.d.ts +17 -0
- package/target/elements/pagination.js +33 -0
- package/target/elements/popover.d.ts +9 -0
- package/target/elements/popover.js +23 -0
- package/target/elements/progress.d.ts +7 -0
- package/target/elements/progress.js +21 -0
- package/target/elements/radio-group.d.ts +5 -0
- package/target/elements/radio-group.js +12 -0
- package/target/elements/resizable.d.ts +7 -0
- package/target/elements/resizable.js +14 -0
- package/target/elements/scroll-area.d.ts +4 -0
- package/target/elements/scroll-area.js +13 -0
- package/target/elements/select.d.ts +15 -0
- package/target/elements/select.js +39 -0
- package/target/elements/separator.d.ts +3 -0
- package/target/elements/separator.js +8 -0
- package/target/elements/sheet.d.ts +13 -0
- package/target/elements/sheet.js +41 -0
- package/target/elements/sidebar.d.ts +63 -0
- package/target/elements/sidebar.js +272 -0
- package/target/elements/skeleton.d.ts +2 -0
- package/target/elements/skeleton.js +7 -0
- package/target/elements/slider.d.ts +3 -0
- package/target/elements/slider.js +15 -0
- package/target/elements/sonner.d.ts +3 -0
- package/target/elements/sonner.js +23 -0
- package/target/elements/spinner.d.ts +2 -0
- package/target/elements/spinner.js +8 -0
- package/target/elements/switch.d.ts +5 -0
- package/target/elements/switch.js +8 -0
- package/target/elements/table.d.ts +9 -0
- package/target/elements/table.js +28 -0
- package/target/elements/tabs.d.ts +10 -0
- package/target/elements/tabs.js +29 -0
- package/target/elements/textarea.d.ts +2 -0
- package/target/elements/textarea.js +7 -0
- package/target/elements/toggle-group.d.ts +10 -0
- package/target/elements/toggle-group.js +24 -0
- package/target/elements/toggle.d.ts +8 -0
- package/target/elements/toggle.js +26 -0
- package/target/elements/tooltip.d.ts +6 -0
- package/target/elements/tooltip.js +18 -0
- package/target/entrypoints/main.js +12 -0
- package/target/helpers/article-icon.d.ts +3 -0
- package/target/helpers/article-icon.js +34 -0
- package/target/helpers/article.d.ts +24 -0
- package/target/helpers/article.js +73 -0
- package/target/helpers/changelog-source.d.ts +7 -0
- package/target/helpers/changelog-source.js +16 -0
- package/target/helpers/changelog-source.unit.d.ts +1 -0
- package/target/helpers/changelog-source.unit.js +33 -0
- package/target/helpers/dynamic-icon-resolver.d.ts +5 -0
- package/target/helpers/dynamic-icon-resolver.js +17 -0
- package/target/helpers/dynamic-icon.d.ts +5 -0
- package/target/helpers/dynamic-icon.js +8 -0
- package/target/helpers/favicon.d.ts +2 -0
- package/target/helpers/favicon.js +11 -0
- package/target/helpers/model.d.ts +3 -0
- package/target/helpers/model.js +4 -0
- package/target/helpers/program.js +5 -0
- package/target/helpers/resolve-asset-path.d.ts +2 -0
- package/target/helpers/resolve-asset-path.js +9 -0
- package/target/helpers/resolve-includes.d.ts +2 -0
- package/target/helpers/resolve-includes.js +113 -0
- package/target/helpers/resolve-includes.unit.d.ts +1 -0
- package/target/helpers/resolve-includes.unit.js +76 -0
- package/target/helpers/search-text.d.ts +2 -0
- package/target/helpers/search-text.js +16 -0
- package/target/helpers/section.d.ts +13 -0
- package/target/helpers/section.js +39 -0
- package/target/helpers/section.unit.d.ts +1 -0
- package/target/helpers/section.unit.js +62 -0
- package/target/helpers/theme.d.ts +5 -0
- package/target/helpers/theme.js +23 -0
- package/target/helpers/toc-context.d.ts +5 -0
- package/target/helpers/toc-context.js +8 -0
- package/target/helpers/toc.d.ts +3 -0
- package/target/helpers/toc.js +41 -0
- package/target/helpers/toc.unit.d.ts +1 -0
- package/target/helpers/toc.unit.js +65 -0
- package/target/hooks/in-view.d.ts +4 -0
- package/target/hooks/in-view.js +23 -0
- package/target/hooks/media.d.ts +6 -0
- package/target/hooks/media.js +25 -0
- package/target/index.js +2 -0
- package/target/models/article.d.ts +58 -0
- package/target/models/article.js +21 -0
- package/{build → target}/models/config.d.ts +10 -0
- package/target/models/config.js +34 -0
- package/target/models/link.js +9 -0
- package/{build → target}/models/patch.d.ts +5 -0
- package/target/models/patch.js +7 -0
- package/target/models/section.js +26 -0
- package/target/models/theme.js +73 -0
- package/target/models/toc.d.ts +5 -0
- package/target/models/toc.js +2 -0
- package/target/plugins/rehype-inline-code.d.ts +19 -0
- package/target/plugins/rehype-inline-code.js +55 -0
- package/target/plugins/rehype-task-list-a11y.d.ts +10 -0
- package/target/plugins/rehype-task-list-a11y.js +29 -0
- package/target/plugins/remark-abbr.d.ts +6 -0
- package/target/plugins/remark-abbr.js +39 -0
- package/target/plugins/remark-abbr.unit.d.ts +1 -0
- package/target/plugins/remark-abbr.unit.js +79 -0
- package/target/plugins/remark-ansi.d.ts +8 -0
- package/target/plugins/remark-ansi.js +239 -0
- package/target/plugins/remark-ansi.unit.d.ts +1 -0
- package/target/plugins/remark-ansi.unit.js +134 -0
- package/target/plugins/remark-badge.d.ts +6 -0
- package/target/plugins/remark-badge.js +43 -0
- package/target/plugins/remark-badge.unit.d.ts +1 -0
- package/target/plugins/remark-badge.unit.js +76 -0
- package/target/plugins/remark-button.d.ts +6 -0
- package/target/plugins/remark-button.js +52 -0
- package/target/plugins/remark-button.unit.d.ts +1 -0
- package/target/plugins/remark-button.unit.js +105 -0
- package/target/plugins/remark-callout.d.ts +4 -0
- package/target/plugins/remark-callout.js +39 -0
- package/target/plugins/remark-card.d.ts +4 -0
- package/target/plugins/remark-card.js +66 -0
- package/target/plugins/remark-code-tabs.d.ts +4 -0
- package/target/plugins/remark-code-tabs.js +72 -0
- package/target/plugins/remark-columns.d.ts +4 -0
- package/target/plugins/remark-columns.js +54 -0
- package/target/plugins/remark-custom-heading-id.d.ts +14 -0
- package/target/plugins/remark-custom-heading-id.js +54 -0
- package/target/plugins/remark-custom-heading-id.unit.d.ts +1 -0
- package/target/plugins/remark-custom-heading-id.unit.js +91 -0
- package/target/plugins/remark-deflist.d.ts +4 -0
- package/target/plugins/remark-deflist.js +31 -0
- package/target/plugins/remark-details.d.ts +4 -0
- package/target/plugins/remark-details.js +33 -0
- package/target/plugins/remark-filetree.d.ts +12 -0
- package/target/plugins/remark-filetree.js +61 -0
- package/target/plugins/remark-filetree.unit.d.ts +1 -0
- package/target/plugins/remark-filetree.unit.js +87 -0
- package/target/plugins/remark-github-callout.d.ts +4 -0
- package/target/plugins/remark-github-callout.js +62 -0
- package/target/plugins/remark-icon.d.ts +4 -0
- package/target/plugins/remark-icon.js +36 -0
- package/target/plugins/remark-image.d.ts +9 -0
- package/target/plugins/remark-image.js +26 -0
- package/target/plugins/remark-media.d.ts +6 -0
- package/target/plugins/remark-media.js +52 -0
- package/target/plugins/remark-media.unit.d.ts +1 -0
- package/target/plugins/remark-media.unit.js +54 -0
- package/target/plugins/remark-mermaid.d.ts +4 -0
- package/target/plugins/remark-mermaid.js +20 -0
- package/target/plugins/remark-npm.d.ts +4 -0
- package/target/plugins/remark-npm.js +32 -0
- package/target/plugins/remark-steps.d.ts +6 -0
- package/target/plugins/remark-steps.js +30 -0
- package/target/plugins/remark-steps.unit.d.ts +1 -0
- package/target/plugins/remark-steps.unit.js +65 -0
- package/target/plugins/remark-tab.d.ts +6 -0
- package/target/plugins/remark-tab.js +76 -0
- package/target/plugins/remark-tab.unit.d.ts +1 -0
- package/target/plugins/remark-tab.unit.js +156 -0
- package/target/plugins/remark-toc.d.ts +6 -0
- package/target/plugins/remark-toc.js +33 -0
- package/target/plugins/remark-toc.unit.d.ts +1 -0
- package/target/plugins/remark-toc.unit.js +57 -0
- package/target/plugins/shiki-icon.d.ts +16 -0
- package/target/plugins/shiki-icon.js +66 -0
- package/target/plugins/shiki-line-highlight.d.ts +27 -0
- package/target/plugins/shiki-line-highlight.js +140 -0
- package/target/plugins/vite-livemark.d.ts +13 -0
- package/target/plugins/vite-livemark.js +76 -0
- package/target/program.js +18 -0
- package/target/routeTree.gen.d.ts +57 -0
- package/target/routeTree.gen.js +27 -0
- package/target/router.d.ts +6 -0
- package/target/router.js +26 -0
- package/target/routes/$.d.ts +1 -0
- package/target/routes/$.js +85 -0
- package/target/routes/__root.d.ts +1 -0
- package/target/routes/__root.js +69 -0
- package/target/server.d.ts +2 -0
- package/target/server.js +7 -0
- package/target/settings.js +7 -0
- package/target/utils/style.d.ts +2 -0
- package/target/utils/style.js +6 -0
- package/target/vite.config.d.ts +2 -0
- package/target/vite.config.js +67 -0
- package/build/actions/changelog/build.js +0 -158
- package/build/actions/changelog/build.unit.js +0 -66
- package/build/actions/config/define.js +0 -8
- package/build/actions/config/define.unit.js +0 -29
- package/build/actions/config/load.js +0 -25
- package/build/actions/config/load.unit.js +0 -23
- package/build/commands/build.js +0 -14
- package/build/commands/escape.js +0 -56
- package/build/commands/preview.js +0 -18
- package/build/commands/start.js +0 -19
- package/build/docs/markdown/includes/example.d.ts +0 -58
- package/build/docs/markdown/includes/example.js +0 -5
- package/build/entrypoints/main.js +0 -12
- package/build/helpers/program.js +0 -5
- package/build/index.js +0 -2
- package/build/livemark.config.d.ts +0 -58
- package/build/livemark.config.js +0 -25
- package/build/models/config.js +0 -34
- package/build/models/link.js +0 -9
- package/build/models/patch.js +0 -7
- package/build/models/section.js +0 -26
- package/build/models/theme.js +0 -73
- package/build/package.json +0 -138
- package/build/program.js +0 -18
- package/build/settings.js +0 -7
- package/build/vite.config.d.ts +0 -2
- package/build/vite.config.js +0 -48
- package/build/website/components/BlogSidebar.tsx +0 -162
- package/build/website/components/ChangelogSidebar.tsx +0 -120
- package/build/website/hooks/media.ts +0 -19
- package/build/website/routeTree.gen.ts +0 -86
- /package/{build/website → source}/assets/logo.svg +0 -0
- /package/{build/website → source}/client.tsx +0 -0
- /package/{build/website → source}/components/Abbr.tsx +0 -0
- /package/{build/website → source}/components/AnsiCode.tsx +0 -0
- /package/{build/website → source}/components/BackToTop.tsx +0 -0
- /package/{build/website → source}/components/Banner.tsx +0 -0
- /package/{build/website → source}/components/BlogIndex.tsx +0 -0
- /package/{build/website → source}/components/Breadcrumbs.tsx +0 -0
- /package/{build/website → source}/components/Card.tsx +0 -0
- /package/{build/website → source}/components/Cards.tsx +0 -0
- /package/{build/website → source}/components/ChangelogIndex.tsx +0 -0
- /package/{build/website → source}/components/CodeBlock.tsx +0 -0
- /package/{build/website → source}/components/CodeTabs.tsx +0 -0
- /package/{build/website → source}/components/Column.tsx +0 -0
- /package/{build/website → source}/components/Columns.tsx +0 -0
- /package/{build/website → source}/components/Content.tsx +0 -0
- /package/{build/website → source}/components/ContentTab.tsx +0 -0
- /package/{build/website → source}/components/ContentTabs.tsx +0 -0
- /package/{build/website → source}/components/DefaultCatchBoundary.tsx +0 -0
- /package/{build/website → source}/components/DefinitionList.tsx +0 -0
- /package/{build/website → source}/components/Details.tsx +0 -0
- /package/{build/website → source}/components/FileTree.tsx +0 -0
- /package/{build/website → source}/components/Footer.tsx +0 -0
- /package/{build/website → source}/components/FootnoteRef.tsx +0 -0
- /package/{build/website → source}/components/Heading.tsx +0 -0
- /package/{build/website → source}/components/InlineBadge.tsx +0 -0
- /package/{build/website → source}/components/InlineIcon.tsx +0 -0
- /package/{build/website → source}/components/InlineToc.tsx +0 -0
- /package/{build/website → source}/components/Mermaid.tsx +0 -0
- /package/{build/website → source}/components/MermaidRenderer.tsx +0 -0
- /package/{build/website → source}/components/NotFound.tsx +0 -0
- /package/{build/website → source}/components/PackageTabs.tsx +0 -0
- /package/{build/website → source}/components/PrevNext.tsx +0 -0
- /package/{build/website → source}/components/Search.tsx +0 -0
- /package/{build/website → source}/components/SearchDialog.tsx +0 -0
- /package/{build/website → source}/components/SidebarLinks.tsx +0 -0
- /package/{build/website → source}/components/SidebarSections.tsx +0 -0
- /package/{build/website → source}/components/SiteTitle.tsx +0 -0
- /package/{build/website → source}/components/SortableTable.tsx +0 -0
- /package/{build/website → source}/components/SoundCloud.tsx +0 -0
- /package/{build/website → source}/components/TagIndex.tsx +0 -0
- /package/{build/website → source}/components/Theme.tsx +0 -0
- /package/{build/website → source}/components/Toc.tsx +0 -0
- /package/{build/website → source}/components/YouTube.tsx +0 -0
- /package/{build/website → source}/components/ZoomImage.tsx +0 -0
- /package/{build/website → source}/content/article.ts +0 -0
- /package/{build/website → source}/content/tag.ts +0 -0
- /package/{build/website → source}/elements/collapsible.tsx +0 -0
- /package/{build/website → source}/elements/direction.tsx +0 -0
- /package/{build/website → source}/elements/sonner.tsx +0 -0
- /package/{build/website → source}/helpers/article-icon.ts +0 -0
- /package/{build/website → source}/helpers/article.ts +0 -0
- /package/{build/website → source}/helpers/changelog-source.ts +0 -0
- /package/{build/website → source}/helpers/changelog-source.unit.ts +0 -0
- /package/{build/website → source}/helpers/dynamic-icon-resolver.tsx +0 -0
- /package/{build/website → source}/helpers/dynamic-icon.tsx +0 -0
- /package/{build/website → source}/helpers/favicon.ts +0 -0
- /package/{build/website → source}/helpers/model.ts +0 -0
- /package/{build/website → source}/helpers/resolve-asset-path.ts +0 -0
- /package/{build/website → source}/helpers/resolve-includes.ts +0 -0
- /package/{build/website → source}/helpers/resolve-includes.unit.ts +0 -0
- /package/{build/website → source}/helpers/search-text.ts +0 -0
- /package/{build/website → source}/helpers/section.unit.ts +0 -0
- /package/{build/website → source}/helpers/theme.ts +0 -0
- /package/{build/website → source}/helpers/toc-context.ts +0 -0
- /package/{build/website → source}/helpers/toc.ts +0 -0
- /package/{build/website → source}/helpers/toc.unit.ts +0 -0
- /package/{build/website → source}/hooks/in-view.ts +0 -0
- /package/{build/website → source}/models/toc.ts +0 -0
- /package/{build/website → source}/plugins/rehype-inline-code.ts +0 -0
- /package/{build/website → source}/plugins/rehype-task-list-a11y.ts +0 -0
- /package/{build/website → source}/plugins/remark-abbr.ts +0 -0
- /package/{build/website → source}/plugins/remark-abbr.unit.ts +0 -0
- /package/{build/website → source}/plugins/remark-ansi.ts +0 -0
- /package/{build/website → source}/plugins/remark-ansi.unit.ts +0 -0
- /package/{build/website → source}/plugins/remark-badge.ts +0 -0
- /package/{build/website → source}/plugins/remark-badge.unit.ts +0 -0
- /package/{build/website → source}/plugins/remark-button.ts +0 -0
- /package/{build/website → source}/plugins/remark-button.unit.ts +0 -0
- /package/{build/website → source}/plugins/remark-callout.ts +0 -0
- /package/{build/website → source}/plugins/remark-card.ts +0 -0
- /package/{build/website → source}/plugins/remark-code-tabs.ts +0 -0
- /package/{build/website → source}/plugins/remark-columns.ts +0 -0
- /package/{build/website → source}/plugins/remark-custom-heading-id.ts +0 -0
- /package/{build/website → source}/plugins/remark-custom-heading-id.unit.ts +0 -0
- /package/{build/website → source}/plugins/remark-deflist.ts +0 -0
- /package/{build/website → source}/plugins/remark-details.ts +0 -0
- /package/{build/website → source}/plugins/remark-filetree.ts +0 -0
- /package/{build/website → source}/plugins/remark-filetree.unit.ts +0 -0
- /package/{build/website → source}/plugins/remark-github-callout.ts +0 -0
- /package/{build/website → source}/plugins/remark-icon.ts +0 -0
- /package/{build/website → source}/plugins/remark-image.ts +0 -0
- /package/{build/website → source}/plugins/remark-media.ts +0 -0
- /package/{build/website → source}/plugins/remark-media.unit.ts +0 -0
- /package/{build/website → source}/plugins/remark-mermaid.ts +0 -0
- /package/{build/website → source}/plugins/remark-npm.ts +0 -0
- /package/{build/website → source}/plugins/remark-steps.ts +0 -0
- /package/{build/website → source}/plugins/remark-steps.unit.ts +0 -0
- /package/{build/website → source}/plugins/remark-tab.ts +0 -0
- /package/{build/website → source}/plugins/remark-tab.unit.ts +0 -0
- /package/{build/website → source}/plugins/remark-toc.ts +0 -0
- /package/{build/website → source}/plugins/remark-toc.unit.ts +0 -0
- /package/{build/website → source}/plugins/shiki-icon.ts +0 -0
- /package/{build/website → source}/plugins/shiki-line-highlight.ts +0 -0
- /package/{build/website → source}/plugins/vite-livemark.ts +0 -0
- /package/{build/website → source}/router.tsx +0 -0
- /package/{build/website → source}/routes/$.tsx +0 -0
- /package/{build/website → source}/routes/__root.tsx +0 -0
- /package/{build/website → source}/server.ts +0 -0
- /package/{build/website → source}/styles/general.css +0 -0
- /package/{build/website → source}/styles/markdown.css +0 -0
- /package/{build/website/helpers → source/utils}/style.ts +0 -0
- /package/{build → target}/actions/changelog/build.unit.d.ts +0 -0
- /package/{build → target}/actions/config/define.d.ts +0 -0
- /package/{build → target}/actions/config/define.unit.d.ts +0 -0
- /package/{build → target}/actions/config/load.d.ts +0 -0
- /package/{build → target}/actions/config/load.unit.d.ts +0 -0
- /package/{build → target}/commands/build.d.ts +0 -0
- /package/{build → target}/commands/escape.d.ts +0 -0
- /package/{build → target}/commands/preview.d.ts +0 -0
- /package/{build → target}/commands/start.d.ts +0 -0
- /package/{build → target}/entrypoints/main.d.ts +0 -0
- /package/{build → target}/helpers/program.d.ts +0 -0
- /package/{build → target}/index.d.ts +0 -0
- /package/{build → target}/models/link.d.ts +0 -0
- /package/{build → target}/models/section.d.ts +0 -0
- /package/{build → target}/models/theme.d.ts +0 -0
- /package/{build → target}/program.d.ts +0 -0
- /package/{build → target}/settings.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,118 @@
|
|
|
1
1
|
# Livemark
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](https://codecov.io/gh/datisthq/livemark)
|
|
5
|
-
[](https://www.npmjs.com/package/livemark)
|
|
3
|
+
Livemark turns plain Markdown into a fast, modern documentation site. Point it at a folder of `.md` files and it gives you a deployable React + Vite site with search, syntax highlighting, blog and changelog sections, dark mode, and a customizable component library — all built in.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
## What you get
|
|
6
|
+
|
|
7
|
+
- 📝 **Just write Markdown.** GitHub-flavored Markdown works out of the box, with frontmatter, custom heading IDs, footnotes, definition lists, and gemoji.
|
|
8
|
+
- 🎨 **Beautiful code blocks.** Syntax highlighting via [Shiki](https://shiki.style/) with 100+ languages, dual light/dark themes, line highlights, diffs, and TwoSlash type hints.
|
|
9
|
+
- 📊 **Diagrams and math.** [Mermaid](https://mermaid.js.org/) flowcharts and KaTeX equations, theme-aware, zero config.
|
|
10
|
+
- 🧩 **Rich elements.** Callouts, tabs, file trees, cards, columns, badges, package tabs (npm/pnpm/yarn/bun), embeds (YouTube, SoundCloud), and more — all as Markdown directives or MDX components.
|
|
11
|
+
- 📚 **Sections.** First-class support for docs, blog (with tags + RSS), and changelog (local `CHANGELOG.md` or GitHub releases).
|
|
12
|
+
- 🔍 **Search.** Full-text search powered by [Orama](https://oramasearch.com/), keyboard shortcuts, smart table-of-contents.
|
|
13
|
+
- 🌗 **Themable.** Tailwind v4, shadcn-style primitives, dark mode, and per-file overrides via a `.livemark/` folder.
|
|
14
|
+
- ⚡ **Built on TanStack Start.** SSR, prerendering, sitemap, and routing for free.
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
You need [Node.js](https://nodejs.org/) 24+ and a package manager (pnpm, npm, yarn, or bun).
|
|
19
|
+
|
|
20
|
+
### Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install livemark
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Configure
|
|
27
|
+
|
|
28
|
+
Create `livemark.config.ts` at the root of your project:
|
|
29
|
+
|
|
30
|
+
```ts title="livemark.config.ts"
|
|
31
|
+
import { defineConfig } from "livemark"
|
|
32
|
+
|
|
33
|
+
export default defineConfig({
|
|
34
|
+
title: "My docs",
|
|
35
|
+
description: "Documentation for my project",
|
|
36
|
+
include: ["docs/**/*.md"],
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Add content
|
|
41
|
+
|
|
42
|
+
```text title="docs/"
|
|
43
|
+
docs/
|
|
44
|
+
├── getting-started.md
|
|
45
|
+
└── usage.md
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Each `.md` file supports frontmatter:
|
|
49
|
+
|
|
50
|
+
```md title="docs/getting-started.md"
|
|
51
|
+
---
|
|
52
|
+
title: Getting Started
|
|
53
|
+
description: Set up the project in five minutes.
|
|
54
|
+
icon: rocket
|
|
55
|
+
order: 1
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
# Getting Started
|
|
59
|
+
|
|
60
|
+
Welcome!
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Run
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx livemark start # dev server with HMR at http://localhost:8000
|
|
67
|
+
npx livemark build # production build to .livemark/build/
|
|
68
|
+
npx livemark preview # serve the production build locally
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
That's the whole loop.
|
|
72
|
+
|
|
73
|
+
## Project structure
|
|
74
|
+
|
|
75
|
+
A typical Livemark site:
|
|
76
|
+
|
|
77
|
+
```text title="my-project/"
|
|
78
|
+
my-project/
|
|
79
|
+
├── livemark.config.ts # configuration
|
|
80
|
+
├── docs/ # markdown content
|
|
81
|
+
├── blog/ # blog posts (optional)
|
|
82
|
+
├── CHANGELOG.md # changelog source (optional)
|
|
83
|
+
└── .livemark/ # overrides + build cache (generated)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Anything under `.livemark/components/`, `.livemark/elements/`, or `.livemark/styles/` shadows the Livemark default with the same path — so you can customize components, primitives, and base CSS without forking the package. Run `npx livemark escape <path>` to copy a default into `.livemark/` ready to edit.
|
|
87
|
+
|
|
88
|
+
## Customization
|
|
89
|
+
|
|
90
|
+
Livemark is meant to look great with zero configuration and stay out of your way when you need more. Common customizations:
|
|
91
|
+
|
|
92
|
+
- **Site metadata** — title, description, favicon, logo. See the [Site Metadata guide](https://livemark.dev/customization/site-metadata/).
|
|
93
|
+
- **Sections** — split content into Docs / Blog / Changelog with their own URL prefixes. See [Sections](https://livemark.dev/customization/sections/).
|
|
94
|
+
- **Navigation links** — header and sidebar links to anywhere. See [Navigation Links](https://livemark.dev/customization/navigation-links/).
|
|
95
|
+
- **Syntax themes** — Shiki theme per light/dark. See [Syntax Themes](https://livemark.dev/customization/syntax-themes/).
|
|
96
|
+
- **Content patches** — override a markdown file's frontmatter from `livemark.config.ts` without touching the file. See [Content Patches](https://livemark.dev/customization/content-patches/).
|
|
97
|
+
- **File overrides** — replace any built-in component or stylesheet from your project. See [File Overrides](https://livemark.dev/customization/file-overrides/).
|
|
98
|
+
- **Custom routes** — drop a `.tsx` file into `.livemark/routes/` to add a fully custom page. See [Custom Routes](https://livemark.dev/customization/custom-routes/).
|
|
99
|
+
|
|
100
|
+
## Documentation
|
|
101
|
+
|
|
102
|
+
Full documentation lives at **[livemark.dev](https://livemark.dev)**:
|
|
103
|
+
|
|
104
|
+
- [Markdown reference](https://livemark.dev/markdown/) — every Markdown / MDX feature with examples
|
|
105
|
+
- [Customization](https://livemark.dev/customization/) — every knob, with copy-pasteable snippets
|
|
106
|
+
- [Changelog](https://livemark.dev/changelog/) — release notes
|
|
107
|
+
- [Contributing](https://livemark.dev/contributing/) — local setup and PR flow
|
|
108
|
+
|
|
109
|
+
## Resources
|
|
110
|
+
|
|
111
|
+
- **npm**: [npmjs.com/package/livemark](https://www.npmjs.com/package/livemark)
|
|
112
|
+
- **GitHub**: [github.com/datisthq/livemark](https://github.com/datisthq/livemark)
|
|
113
|
+
- **Issues**: [github.com/datisthq/livemark/issues](https://github.com/datisthq/livemark/issues)
|
|
114
|
+
- **Discussions**: [github.com/datisthq/livemark/discussions](https://github.com/datisthq/livemark/discussions)
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
MIT — see [LICENSE.md](LICENSE.md).
|
package/package.json
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livemark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Livemark description",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Evgeny Karev",
|
|
7
7
|
"repository": "https://github.com/datisthq/livemark",
|
|
8
8
|
"bin": {
|
|
9
|
-
"livemark": "./
|
|
9
|
+
"livemark": "./target/entrypoints/main.js"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
|
-
"
|
|
12
|
+
"target",
|
|
13
|
+
"source",
|
|
14
|
+
"!source/routeTree.gen.ts",
|
|
13
15
|
"skills"
|
|
14
16
|
],
|
|
15
17
|
"type": "module",
|
|
16
18
|
"sideEffects": false,
|
|
17
|
-
"imports": {
|
|
18
|
-
"#*": "./*"
|
|
19
|
-
},
|
|
20
19
|
"exports": {
|
|
21
|
-
".": "./
|
|
22
|
-
"./components/*": "./
|
|
23
|
-
"./elements/*": "./
|
|
24
|
-
"./
|
|
20
|
+
".": "./target/index.js",
|
|
21
|
+
"./components/*": "./source/components/*.tsx",
|
|
22
|
+
"./elements/*": "./source/elements/*.tsx",
|
|
23
|
+
"./hooks/*": "./source/hooks/*.ts",
|
|
24
|
+
"./styles/*": "./source/styles/*.css",
|
|
25
|
+
"./utils/*": "./source/utils/*.ts"
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
27
28
|
"@base-ui/react": "1.3.0",
|
|
@@ -113,11 +114,11 @@
|
|
|
113
114
|
"pnpm": "^10.0.0"
|
|
114
115
|
},
|
|
115
116
|
"scripts": {
|
|
116
|
-
"build": "tsgo
|
|
117
|
+
"build": "tsgo",
|
|
117
118
|
"bump": "ncu -u",
|
|
118
|
-
"clean": "rm -rf pnpm-lock.yaml node_modules
|
|
119
|
-
"docs:build": "node entrypoints/main.ts build",
|
|
120
|
-
"docs:start": "node entrypoints/main.ts start",
|
|
119
|
+
"clean": "rm -rf pnpm-lock.yaml node_modules target",
|
|
120
|
+
"docs:build": "node source/entrypoints/main.ts build",
|
|
121
|
+
"docs:start": "node source/entrypoints/main.ts start",
|
|
121
122
|
"format": "vp fmt",
|
|
122
123
|
"lint": "vp fmt --check && vp lint",
|
|
123
124
|
"release": "pnpm publish --access public --ignore-scripts --no-git-checks",
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises"
|
|
2
|
+
import { dirname, join, resolve } from "node:path"
|
|
3
|
+
import slugify from "@sindresorhus/slugify"
|
|
4
|
+
import type { Root, RootContent } from "mdast"
|
|
5
|
+
import { toString as mdastToString } from "mdast-util-to-string"
|
|
6
|
+
import remarkParse from "remark-parse"
|
|
7
|
+
import remarkStringify from "remark-stringify"
|
|
8
|
+
import { unified } from "unified"
|
|
9
|
+
import { visit } from "unist-util-visit"
|
|
10
|
+
import type { Config } from "../../models/config.ts"
|
|
11
|
+
import type { ChangelogSection } from "../../models/section.ts"
|
|
12
|
+
import { isGitHubUrl, parseGitHubRepo } from "../../helpers/changelog-source.ts"
|
|
13
|
+
|
|
14
|
+
interface Release {
|
|
15
|
+
tag_name: string
|
|
16
|
+
name?: string | null
|
|
17
|
+
published_at?: string | null
|
|
18
|
+
body?: string | null
|
|
19
|
+
html_url?: string | null
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface CacheMeta {
|
|
23
|
+
etag: string
|
|
24
|
+
fetchedAt: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface ChangelogEntry {
|
|
28
|
+
slug: string
|
|
29
|
+
title: string
|
|
30
|
+
date?: string
|
|
31
|
+
body: string
|
|
32
|
+
sourceUrl?: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const CACHE_DIR = ".livemark/cache/changelog"
|
|
36
|
+
const META_FILE = ".livemark/cache/changelog.meta.json"
|
|
37
|
+
|
|
38
|
+
const parser = unified().use(remarkParse)
|
|
39
|
+
const stringifier = unified().use(remarkStringify, {
|
|
40
|
+
bullet: "-",
|
|
41
|
+
fences: true,
|
|
42
|
+
emphasis: "_",
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
export function cacheIncludeGlob() {
|
|
46
|
+
return `${CACHE_DIR}/**/*.md`
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Build the per-version changelog cache files for a changelog section */
|
|
50
|
+
export async function buildChangelog(
|
|
51
|
+
section: ChangelogSection,
|
|
52
|
+
config: Config,
|
|
53
|
+
) {
|
|
54
|
+
const cacheDir = join(config.root, CACHE_DIR)
|
|
55
|
+
const metaPath = join(config.root, META_FILE)
|
|
56
|
+
|
|
57
|
+
const entries = isGitHubUrl(section.source)
|
|
58
|
+
? await buildFromGitHub(section.source, metaPath, cacheDir)
|
|
59
|
+
: await buildFromLocal(section.source, config.root)
|
|
60
|
+
|
|
61
|
+
if (entries === undefined) return
|
|
62
|
+
|
|
63
|
+
await rm(cacheDir, { recursive: true, force: true })
|
|
64
|
+
await mkdir(cacheDir, { recursive: true })
|
|
65
|
+
|
|
66
|
+
for (const entry of entries) {
|
|
67
|
+
const markdown = wrapFrontmatter(entry, section)
|
|
68
|
+
await writeFile(join(cacheDir, `${entry.slug}.md`), markdown, "utf-8")
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function buildFromLocal(source: string, root: string) {
|
|
73
|
+
const filePath = resolve(root, source)
|
|
74
|
+
const body = await readFile(filePath, "utf-8")
|
|
75
|
+
return splitLocalChangelog(body)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Parse CHANGELOG.md into per-version entries using mdast */
|
|
79
|
+
export function splitLocalChangelog(body: string): ChangelogEntry[] {
|
|
80
|
+
const tree = parser.parse(body) as Root
|
|
81
|
+
const entries: ChangelogEntry[] = []
|
|
82
|
+
let current: { heading: string; children: RootContent[] } | undefined
|
|
83
|
+
|
|
84
|
+
for (const child of tree.children) {
|
|
85
|
+
if (child.type === "heading" && child.depth === 2) {
|
|
86
|
+
if (current) entries.push(finalizeEntry(current))
|
|
87
|
+
current = { heading: mdastToString(child), children: [] }
|
|
88
|
+
} else if (current) {
|
|
89
|
+
current.children.push(child)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (current) entries.push(finalizeEntry(current))
|
|
93
|
+
return entries
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function finalizeEntry(input: {
|
|
97
|
+
heading: string
|
|
98
|
+
children: RootContent[]
|
|
99
|
+
}): ChangelogEntry {
|
|
100
|
+
const versionMatch = input.heading.match(/^\[?([^\]\s]+)\]?/)
|
|
101
|
+
const version = versionMatch?.[1] ?? input.heading
|
|
102
|
+
const dateMatch = input.heading.match(/\d{4}-\d{2}-\d{2}/)
|
|
103
|
+
const body = renderEntryBody(input.children)
|
|
104
|
+
return {
|
|
105
|
+
slug: slugify(version),
|
|
106
|
+
title: version,
|
|
107
|
+
date: dateMatch?.[0],
|
|
108
|
+
body,
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Serialize an entry's mdast children back to markdown */
|
|
113
|
+
function renderEntryBody(children: RootContent[]) {
|
|
114
|
+
const root: Root = { type: "root", children }
|
|
115
|
+
return stringifier.stringify(root).trimEnd()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Drop the body's leading h1 (typically the conventional-changelog
|
|
119
|
+
* `# 0.7.2 (2026-04-25)` boilerplate that duplicates the article's title),
|
|
120
|
+
* shift h2–h6 up by one so subsection headings become h1 / h2 / …, and
|
|
121
|
+
* escape stray `<` outside code so MDX doesn't mistake them for JSX. */
|
|
122
|
+
function processBody(body: string) {
|
|
123
|
+
const tree = parser.parse(body) as Root
|
|
124
|
+
visit(tree, "heading", node => {
|
|
125
|
+
if (node.depth > 1) node.depth = (node.depth - 1) as 1 | 2 | 3 | 4 | 5
|
|
126
|
+
})
|
|
127
|
+
if (tree.children[0]?.type === "heading" && tree.children[0].depth === 1) {
|
|
128
|
+
tree.children.shift()
|
|
129
|
+
}
|
|
130
|
+
return escapeMdxAngles(stringifier.stringify(tree).trimEnd())
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Escape `<` to `\<` outside fenced code blocks and inline backtick spans
|
|
134
|
+
* so commit messages with placeholders like `<subdir>` don't get parsed as
|
|
135
|
+
* JSX by MDX. */
|
|
136
|
+
function escapeMdxAngles(markdown: string) {
|
|
137
|
+
let inFence = false
|
|
138
|
+
return markdown
|
|
139
|
+
.split("\n")
|
|
140
|
+
.map(line => {
|
|
141
|
+
if (line.startsWith("```")) {
|
|
142
|
+
inFence = !inFence
|
|
143
|
+
return line
|
|
144
|
+
}
|
|
145
|
+
if (inFence) return line
|
|
146
|
+
return line.replace(/`[^`]*`|</g, match =>
|
|
147
|
+
match === "<" ? "\\<" : match,
|
|
148
|
+
)
|
|
149
|
+
})
|
|
150
|
+
.join("\n")
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function buildFromGitHub(
|
|
154
|
+
source: string,
|
|
155
|
+
metaPath: string,
|
|
156
|
+
cacheDir: string,
|
|
157
|
+
): Promise<ChangelogEntry[] | undefined> {
|
|
158
|
+
const parsed = parseGitHubRepo(source)
|
|
159
|
+
if (!parsed) {
|
|
160
|
+
throw new Error(`Could not parse GitHub repo from source: ${source}`)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const url = `https://api.github.com/repos/${parsed.owner}/${parsed.repo}/releases?per_page=100`
|
|
164
|
+
const headers: Record<string, string> = {
|
|
165
|
+
Accept: "application/vnd.github+json",
|
|
166
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const token = process.env.GITHUB_TOKEN
|
|
170
|
+
if (token) headers.Authorization = `Bearer ${token}`
|
|
171
|
+
|
|
172
|
+
const meta = await readMeta(metaPath)
|
|
173
|
+
const hasCache = await exists(cacheDir)
|
|
174
|
+
if (meta && hasCache) headers["If-None-Match"] = meta.etag
|
|
175
|
+
|
|
176
|
+
const res = await fetch(url, { headers })
|
|
177
|
+
|
|
178
|
+
if (res.status === 304) return undefined
|
|
179
|
+
|
|
180
|
+
if (!res.ok) {
|
|
181
|
+
const remaining = res.headers.get("x-ratelimit-remaining")
|
|
182
|
+
const reset = res.headers.get("x-ratelimit-reset")
|
|
183
|
+
const msg = `GitHub API ${res.status} ${res.statusText} (rate-limit remaining: ${remaining ?? "?"}, reset: ${reset ?? "?"})`
|
|
184
|
+
if (hasCache) {
|
|
185
|
+
console.warn(`${msg} — falling back to cached changelog`)
|
|
186
|
+
return undefined
|
|
187
|
+
}
|
|
188
|
+
throw new Error(msg)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const releases = (await res.json()) as Release[]
|
|
192
|
+
const etag = res.headers.get("etag")
|
|
193
|
+
if (etag) {
|
|
194
|
+
await mkdir(dirname(metaPath), { recursive: true })
|
|
195
|
+
await writeFile(
|
|
196
|
+
metaPath,
|
|
197
|
+
JSON.stringify(
|
|
198
|
+
{ etag, fetchedAt: new Date().toISOString() } satisfies CacheMeta,
|
|
199
|
+
null,
|
|
200
|
+
2,
|
|
201
|
+
),
|
|
202
|
+
"utf-8",
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return releases.map(release => ({
|
|
207
|
+
slug: slugify(release.tag_name),
|
|
208
|
+
title: release.tag_name,
|
|
209
|
+
date: release.published_at ?? undefined,
|
|
210
|
+
body: (release.body ?? "").trim(),
|
|
211
|
+
sourceUrl: release.html_url ?? undefined,
|
|
212
|
+
}))
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function wrapFrontmatter(entry: ChangelogEntry, section: ChangelogSection) {
|
|
216
|
+
const lines = [
|
|
217
|
+
"---",
|
|
218
|
+
`title: ${entry.title}`,
|
|
219
|
+
`path: ${section.prefix}${entry.slug}/`,
|
|
220
|
+
]
|
|
221
|
+
if (entry.date) lines.push(`date: ${entry.date}`)
|
|
222
|
+
if (entry.sourceUrl) {
|
|
223
|
+
lines.push(`sourceUrl: ${entry.sourceUrl}`, "sourceAction: view")
|
|
224
|
+
}
|
|
225
|
+
lines.push("---", "", `# ${entry.title}`, "", processBody(entry.body))
|
|
226
|
+
return lines.join("\n")
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function readMeta(metaPath: string): Promise<CacheMeta | undefined> {
|
|
230
|
+
try {
|
|
231
|
+
const raw = await readFile(metaPath, "utf-8")
|
|
232
|
+
return JSON.parse(raw) as CacheMeta
|
|
233
|
+
} catch {
|
|
234
|
+
return undefined
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async function exists(path: string) {
|
|
239
|
+
try {
|
|
240
|
+
await access(path)
|
|
241
|
+
return true
|
|
242
|
+
} catch {
|
|
243
|
+
return false
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, expect, it } from "vite-plus/test"
|
|
2
|
+
import { splitLocalChangelog } from "./build.ts"
|
|
3
|
+
|
|
4
|
+
describe("splitLocalChangelog", () => {
|
|
5
|
+
it("splits by h2 headings", () => {
|
|
6
|
+
const input = `# Changelog
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2026-04-15
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Foo
|
|
13
|
+
|
|
14
|
+
## [0.1.0] - 2026-04-10
|
|
15
|
+
|
|
16
|
+
Initial release.
|
|
17
|
+
`
|
|
18
|
+
const entries = splitLocalChangelog(input)
|
|
19
|
+
expect(entries).toHaveLength(2)
|
|
20
|
+
expect(entries[0]?.title).toBe("0.2.0")
|
|
21
|
+
expect(entries[0]?.date).toBe("2026-04-15")
|
|
22
|
+
expect(entries[0]?.slug).toBe("0-2-0")
|
|
23
|
+
expect(entries[1]?.title).toBe("0.1.0")
|
|
24
|
+
expect(entries[1]?.date).toBe("2026-04-10")
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it("preserves h3 heading structure in body", () => {
|
|
28
|
+
const input = `## 1.0.0
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- Thing one
|
|
33
|
+
`
|
|
34
|
+
const entries = splitLocalChangelog(input)
|
|
35
|
+
expect(entries[0]?.body).toContain("### Added")
|
|
36
|
+
expect(entries[0]?.body).toContain("- Thing one")
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it("ignores ## inside fenced code blocks", () => {
|
|
40
|
+
const input = `## 1.0.0
|
|
41
|
+
|
|
42
|
+
Some prose.
|
|
43
|
+
|
|
44
|
+
\`\`\`md
|
|
45
|
+
## Not a real version heading
|
|
46
|
+
\`\`\`
|
|
47
|
+
|
|
48
|
+
## 0.9.0
|
|
49
|
+
|
|
50
|
+
Older.
|
|
51
|
+
`
|
|
52
|
+
const entries = splitLocalChangelog(input)
|
|
53
|
+
expect(entries).toHaveLength(2)
|
|
54
|
+
expect(entries[0]?.title).toBe("1.0.0")
|
|
55
|
+
expect(entries[0]?.body).toContain("Not a real version heading")
|
|
56
|
+
expect(entries[1]?.title).toBe("0.9.0")
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it("handles bare version headings without brackets or date", () => {
|
|
60
|
+
const input = `## v1.2.3
|
|
61
|
+
|
|
62
|
+
Release notes.
|
|
63
|
+
`
|
|
64
|
+
const entries = splitLocalChangelog(input)
|
|
65
|
+
expect(entries[0]?.title).toBe("v1.2.3")
|
|
66
|
+
expect(entries[0]?.slug).toBe("v1-2-3")
|
|
67
|
+
expect(entries[0]?.date).toBeUndefined()
|
|
68
|
+
})
|
|
69
|
+
})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { z } from "zod"
|
|
2
|
+
import { UserConfig } from "../../models/config.ts"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Validate and fill defaults for a partial config object.
|
|
6
|
+
*/
|
|
7
|
+
export function defineConfig(
|
|
8
|
+
input: z.input<typeof UserConfig>,
|
|
9
|
+
): z.output<typeof UserConfig> {
|
|
10
|
+
return UserConfig.parse(input)
|
|
11
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, it } from "vite-plus/test"
|
|
2
|
+
import { defineConfig } from "./define.ts"
|
|
3
|
+
|
|
4
|
+
describe("defineConfig", () => {
|
|
5
|
+
it("should accept include as a string", () => {
|
|
6
|
+
const config = defineConfig({ include: "articles/**/*.mdx" })
|
|
7
|
+
expect(config.include).toBe("articles/**/*.mdx")
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
it("should accept include as an array", () => {
|
|
11
|
+
const config = defineConfig({
|
|
12
|
+
include: ["articles/**/*.mdx", "guides/**/*.mdx"],
|
|
13
|
+
})
|
|
14
|
+
expect(config.include).toEqual(["articles/**/*.mdx", "guides/**/*.mdx"])
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it("should accept optional exclude", () => {
|
|
18
|
+
const config = defineConfig({
|
|
19
|
+
include: "**/*.mdx",
|
|
20
|
+
exclude: "drafts/**",
|
|
21
|
+
})
|
|
22
|
+
expect(config.exclude).toBe("drafts/**")
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it("should allow omitting exclude", () => {
|
|
26
|
+
const config = defineConfig({ include: "**/*.mdx" })
|
|
27
|
+
expect(config.exclude).toBeUndefined()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it("should reject missing include", () => {
|
|
31
|
+
expect(() => defineConfig({} as any)).toThrow()
|
|
32
|
+
})
|
|
33
|
+
})
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { dirname, resolve } from "node:path"
|
|
2
|
+
import { pathToFileURL } from "node:url"
|
|
3
|
+
import type { z } from "zod"
|
|
4
|
+
import type { Config } from "../../models/config.ts"
|
|
5
|
+
import { UserConfig } from "../../models/config.ts"
|
|
6
|
+
import { defineConfig } from "./define.ts"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Load and validate a config file, checking --config/-c CLI arg, then cwd.
|
|
10
|
+
*/
|
|
11
|
+
export async function loadConfig(path?: string): Promise<Config> {
|
|
12
|
+
const configIndex = process.argv.findIndex(
|
|
13
|
+
a => a === "-c" || a === "--config",
|
|
14
|
+
)
|
|
15
|
+
const cliPath = configIndex !== -1 ? process.argv[configIndex + 1] : undefined
|
|
16
|
+
const resolved = resolve(path ?? cliPath ?? "livemark.config.ts")
|
|
17
|
+
// Cache-bust the ESM import so dev-server restart reloads edits on disk.
|
|
18
|
+
const url = `${pathToFileURL(resolved).href}?t=${Date.now()}`
|
|
19
|
+
const module: Record<string, unknown> = await import(url)
|
|
20
|
+
const input = defineConfig(module.default as z.input<typeof UserConfig>)
|
|
21
|
+
return { ...input, root: dirname(resolved), configPath: resolved }
|
|
22
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import fs from "node:fs"
|
|
2
|
+
import { join } from "node:path"
|
|
3
|
+
import { temporaryDirectoryTask } from "tempy"
|
|
4
|
+
import { describe, expect, it } from "vite-plus/test"
|
|
5
|
+
import { loadConfig } from "./load.ts"
|
|
6
|
+
|
|
7
|
+
describe("loadConfig", () => {
|
|
8
|
+
it("should throw when no config file exists", async () => {
|
|
9
|
+
await expect(loadConfig("/nonexistent/config.ts")).rejects.toThrow()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it("should load config from explicit path", () =>
|
|
13
|
+
temporaryDirectoryTask(async tmpDir => {
|
|
14
|
+
const configPath = join(tmpDir, "livemark.config.ts")
|
|
15
|
+
fs.writeFileSync(
|
|
16
|
+
configPath,
|
|
17
|
+
'export default { include: "articles/**/*.mdx" }\n',
|
|
18
|
+
)
|
|
19
|
+
const config = await loadConfig(configPath)
|
|
20
|
+
expect(config.include).toBe("articles/**/*.mdx")
|
|
21
|
+
expect(config.root).toBe(tmpDir)
|
|
22
|
+
}))
|
|
23
|
+
|
|
24
|
+
it("should validate loaded config", () =>
|
|
25
|
+
temporaryDirectoryTask(async tmpDir => {
|
|
26
|
+
const configPath = join(tmpDir, "livemark.config.ts")
|
|
27
|
+
fs.writeFileSync(configPath, "export default {}\n")
|
|
28
|
+
await expect(loadConfig(configPath)).rejects.toThrow()
|
|
29
|
+
}))
|
|
30
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { join } from "node:path"
|
|
2
|
+
import { Command } from "commander"
|
|
3
|
+
import { createBuilder } from "vite"
|
|
4
|
+
|
|
5
|
+
const configFile = join(
|
|
6
|
+
import.meta.dirname,
|
|
7
|
+
"..",
|
|
8
|
+
"..",
|
|
9
|
+
"source",
|
|
10
|
+
"vite.config.ts",
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Build the site for production.
|
|
15
|
+
*/
|
|
16
|
+
export const build = new Command("build")
|
|
17
|
+
.description("Build the site for production")
|
|
18
|
+
.action(async () => {
|
|
19
|
+
const builder = await createBuilder({ configFile })
|
|
20
|
+
await builder.buildApp()
|
|
21
|
+
})
|