livemark 0.0.0-dev
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 +3 -0
- package/build/actions/config/define.d.ts +6 -0
- package/build/actions/config/define.js +8 -0
- package/build/actions/config/define.unit.d.ts +1 -0
- package/build/actions/config/define.unit.js +34 -0
- package/build/actions/config/load.d.ts +5 -0
- package/build/actions/config/load.js +22 -0
- package/build/actions/config/load.unit.d.ts +1 -0
- package/build/actions/config/load.unit.js +23 -0
- package/build/commands/build.d.ts +5 -0
- package/build/commands/build.js +13 -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 +9 -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 -0
- package/build/index.js +2 -0
- package/build/livemark.config.d.ts +9 -0
- package/build/livemark.config.js +5 -0
- package/build/models/config.d.ts +33 -0
- package/build/models/config.js +14 -0
- package/build/program.d.ts +2 -0
- package/build/program.js +14 -0
- package/build/vite.config.d.ts +2 -0
- package/build/vite.config.js +48 -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/Banner.tsx +32 -0
- package/build/website/components/Breadcrumbs.tsx +19 -0
- package/build/website/components/Callout.tsx +72 -0
- package/build/website/components/Cards.tsx +66 -0
- package/build/website/components/CodeBlock.tsx +118 -0
- package/build/website/components/CodeTabs.tsx +83 -0
- package/build/website/components/Columns.tsx +17 -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 +9 -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 +21 -0
- package/build/website/components/InlineToc.tsx +31 -0
- package/build/website/components/Layout.tsx +220 -0
- package/build/website/components/LinkButton.tsx +31 -0
- package/build/website/components/Mermaid.tsx +37 -0
- package/build/website/components/NotFound.tsx +27 -0
- package/build/website/components/PackageTabs.tsx +74 -0
- package/build/website/components/PageToolbar.tsx +65 -0
- package/build/website/components/PrevNext.tsx +52 -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/SiteTitle.tsx +16 -0
- package/build/website/components/SortableTable.tsx +81 -0
- package/build/website/components/SoundCloud.tsx +16 -0
- package/build/website/components/Theme.tsx +40 -0
- package/build/website/components/Toc.tsx +99 -0
- package/build/website/components/YouTube.tsx +16 -0
- package/build/website/components/ZoomImage.tsx +30 -0
- package/build/website/content-collections.ts +181 -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 +10 -0
- package/build/website/globals.d.ts +8 -0
- package/build/website/helpers/article-icon.ts +59 -0
- package/build/website/helpers/articles.ts +24 -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/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 +51 -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 +40 -0
- package/build/website/plugins/rehype-inline-code.ts +107 -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 +247 -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 +25 -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/public/logo.svg +72 -0
- package/build/website/routeTree.gen.ts +86 -0
- package/build/website/router.tsx +34 -0
- package/build/website/routes/$.tsx +149 -0
- package/build/website/routes/__root.tsx +84 -0
- package/build/website/routes/index.tsx +13 -0
- package/build/website/server.ts +7 -0
- package/build/website/styles/general.css +347 -0
- package/build/website/vite.config.ts +36 -0
- package/entrypoints/main.ts +12 -0
- package/package.json +120 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Heading, Root } from "mdast"
|
|
2
|
+
import type { Plugin } from "unified"
|
|
3
|
+
import { visit } from "unist-util-visit"
|
|
4
|
+
|
|
5
|
+
const STEP_PATTERN = /\s*\[step\]\s*$/
|
|
6
|
+
|
|
7
|
+
/** Walk a mdast tree, strip `[step]` suffixes from headings, and add a `data-step` attribute */
|
|
8
|
+
export function transformStepHeadings(tree: Root) {
|
|
9
|
+
let stepNumber = 0
|
|
10
|
+
|
|
11
|
+
visit(tree, "heading", (node: Heading) => {
|
|
12
|
+
const lastChild = node.children[node.children.length - 1]
|
|
13
|
+
if (!lastChild || lastChild.type !== "text") return
|
|
14
|
+
if (!STEP_PATTERN.test(lastChild.value)) return
|
|
15
|
+
|
|
16
|
+
stepNumber += 1
|
|
17
|
+
lastChild.value = lastChild.value.replace(STEP_PATTERN, "")
|
|
18
|
+
|
|
19
|
+
if (lastChild.value === "" && node.children.length > 1) {
|
|
20
|
+
node.children.pop()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
node.data = node.data ?? {}
|
|
24
|
+
node.data.hProperties = {
|
|
25
|
+
...node.data.hProperties,
|
|
26
|
+
"data-step": stepNumber,
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Remark plugin that converts `[step]` heading suffixes into numbered step markers */
|
|
32
|
+
export const remarkSteps: Plugin<[], Root> = () => {
|
|
33
|
+
return tree => {
|
|
34
|
+
transformStepHeadings(tree)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Heading, Root, Text } from "mdast"
|
|
2
|
+
import { describe, expect, it } from "vite-plus/test"
|
|
3
|
+
import { transformStepHeadings } from "./remark-steps.ts"
|
|
4
|
+
|
|
5
|
+
function makeHeading(depth: 1 | 2 | 3 | 4 | 5 | 6, text: string): Heading {
|
|
6
|
+
return { type: "heading", depth, children: [{ type: "text", value: text }] }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function makeTree(...children: Root["children"]): Root {
|
|
10
|
+
return { type: "root", children }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function findHeading(tree: Root, index: number): Heading {
|
|
14
|
+
const node = tree.children[index]
|
|
15
|
+
if (!node || node.type !== "heading") throw new Error("No heading at index")
|
|
16
|
+
return node
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function headingText(heading: Heading): string {
|
|
20
|
+
return heading.children
|
|
21
|
+
.filter((c): c is Text => c.type === "text")
|
|
22
|
+
.map(c => c.value)
|
|
23
|
+
.join("")
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe("transformStepHeadings", () => {
|
|
27
|
+
function process(tree: Root) {
|
|
28
|
+
transformStepHeadings(tree)
|
|
29
|
+
return tree
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
it("should strip [step] and set data-step attribute", () => {
|
|
33
|
+
const tree = process(
|
|
34
|
+
makeTree(makeHeading(3, "Install Dependencies [step]")),
|
|
35
|
+
)
|
|
36
|
+
const heading = findHeading(tree, 0)
|
|
37
|
+
expect(heading.data?.hProperties).toEqual({ "data-step": 1 })
|
|
38
|
+
expect(headingText(heading)).toBe("Install Dependencies")
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it("should auto-increment step numbers", () => {
|
|
42
|
+
const tree = process(
|
|
43
|
+
makeTree(
|
|
44
|
+
makeHeading(3, "Step One [step]"),
|
|
45
|
+
makeHeading(3, "Step Two [step]"),
|
|
46
|
+
makeHeading(3, "Step Three [step]"),
|
|
47
|
+
),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
expect(findHeading(tree, 0).data?.hProperties).toEqual({ "data-step": 1 })
|
|
51
|
+
expect(findHeading(tree, 1).data?.hProperties).toEqual({ "data-step": 2 })
|
|
52
|
+
expect(findHeading(tree, 2).data?.hProperties).toEqual({ "data-step": 3 })
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it("should leave headings without [step] unchanged", () => {
|
|
56
|
+
const tree = process(makeTree(makeHeading(2, "Normal Heading")))
|
|
57
|
+
const heading = findHeading(tree, 0)
|
|
58
|
+
expect(heading.data).toBeUndefined()
|
|
59
|
+
expect(headingText(heading)).toBe("Normal Heading")
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it("should only count [step] headings for numbering", () => {
|
|
63
|
+
const tree = process(
|
|
64
|
+
makeTree(
|
|
65
|
+
makeHeading(3, "First [step]"),
|
|
66
|
+
makeHeading(3, "Not a step"),
|
|
67
|
+
makeHeading(3, "Second [step]"),
|
|
68
|
+
),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
expect(findHeading(tree, 0).data?.hProperties).toEqual({ "data-step": 1 })
|
|
72
|
+
expect(findHeading(tree, 1).data).toBeUndefined()
|
|
73
|
+
expect(findHeading(tree, 2).data?.hProperties).toEqual({ "data-step": 2 })
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it("should handle different heading depths", () => {
|
|
77
|
+
const tree = process(
|
|
78
|
+
makeTree(
|
|
79
|
+
makeHeading(2, "Big Step [step]"),
|
|
80
|
+
makeHeading(4, "Small Step [step]"),
|
|
81
|
+
),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
expect(findHeading(tree, 0).data?.hProperties).toEqual({ "data-step": 1 })
|
|
85
|
+
expect(findHeading(tree, 1).data?.hProperties).toEqual({ "data-step": 2 })
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it("should preserve existing hProperties", () => {
|
|
89
|
+
const heading = makeHeading(3, "Custom [step]")
|
|
90
|
+
heading.data = { hProperties: { id: "custom-id" } }
|
|
91
|
+
const tree = process(makeTree(heading))
|
|
92
|
+
expect(findHeading(tree, 0).data?.hProperties).toEqual({
|
|
93
|
+
id: "custom-id",
|
|
94
|
+
"data-step": 1,
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
})
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { Root } from "mdast"
|
|
2
|
+
import type { ContainerDirective } from "mdast-util-directive"
|
|
3
|
+
import type { Plugin } from "unified"
|
|
4
|
+
import { visit, SKIP } from "unist-util-visit"
|
|
5
|
+
|
|
6
|
+
/** Walk a mdast tree and convert :::tab directives into ContentTab/ContentTabs JSX elements */
|
|
7
|
+
export function transformTabDirectives(tree: Root) {
|
|
8
|
+
visit(
|
|
9
|
+
tree,
|
|
10
|
+
"containerDirective",
|
|
11
|
+
(node: ContainerDirective, index, parent) => {
|
|
12
|
+
if (node.name !== "tab" || index === undefined || !parent) return
|
|
13
|
+
|
|
14
|
+
const title = node.attributes?.title ?? ""
|
|
15
|
+
const sync = node.attributes?.sync
|
|
16
|
+
|
|
17
|
+
const attrs: { type: "mdxJsxAttribute"; name: string; value: string }[] =
|
|
18
|
+
[{ type: "mdxJsxAttribute" as const, name: "title", value: title }]
|
|
19
|
+
if (sync) {
|
|
20
|
+
attrs.push({
|
|
21
|
+
type: "mdxJsxAttribute" as const,
|
|
22
|
+
name: "sync",
|
|
23
|
+
value: sync,
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const jsxNode = {
|
|
28
|
+
type: "mdxJsxFlowElement" as const,
|
|
29
|
+
name: "ContentTab",
|
|
30
|
+
attributes: attrs,
|
|
31
|
+
children: node.children,
|
|
32
|
+
data: { _mdxExplicitJsx: true },
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// @ts-expect-error mdxJsxFlowElement is not in mdast types
|
|
36
|
+
parent.children[index] = jsxNode
|
|
37
|
+
return SKIP
|
|
38
|
+
},
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
const children = tree.children
|
|
42
|
+
let i = 0
|
|
43
|
+
while (i < children.length) {
|
|
44
|
+
const node = children[i]
|
|
45
|
+
// @ts-expect-error mdxJsxFlowElement is not in mdast types
|
|
46
|
+
if (node?.type !== "mdxJsxFlowElement" || node.name !== "ContentTab") {
|
|
47
|
+
i++
|
|
48
|
+
continue
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let j = i + 1
|
|
52
|
+
while (j < children.length) {
|
|
53
|
+
const next = children[j]
|
|
54
|
+
// @ts-expect-error mdxJsxFlowElement is not in mdast types
|
|
55
|
+
if (next?.type !== "mdxJsxFlowElement" || next.name !== "ContentTab")
|
|
56
|
+
break
|
|
57
|
+
j++
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const group = children.slice(i, j)
|
|
61
|
+
|
|
62
|
+
const firstChild = group[0]
|
|
63
|
+
// @ts-expect-error accessing mdxJsx attributes on untyped node
|
|
64
|
+
const syncAttr = firstChild?.attributes?.find(
|
|
65
|
+
(a: { name: string }) => a.name === "sync",
|
|
66
|
+
)
|
|
67
|
+
const wrapperAttrs: {
|
|
68
|
+
type: "mdxJsxAttribute"
|
|
69
|
+
name: string
|
|
70
|
+
value: string
|
|
71
|
+
}[] = syncAttr
|
|
72
|
+
? [
|
|
73
|
+
{
|
|
74
|
+
type: "mdxJsxAttribute" as const,
|
|
75
|
+
name: "sync",
|
|
76
|
+
value: syncAttr.value,
|
|
77
|
+
},
|
|
78
|
+
]
|
|
79
|
+
: []
|
|
80
|
+
|
|
81
|
+
const wrapper = {
|
|
82
|
+
type: "mdxJsxFlowElement" as const,
|
|
83
|
+
name: "ContentTabs",
|
|
84
|
+
attributes: wrapperAttrs,
|
|
85
|
+
children: group,
|
|
86
|
+
data: { _mdxExplicitJsx: true },
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// @ts-expect-error mdxJsxFlowElement is not in mdast types
|
|
90
|
+
children.splice(i, j - i, wrapper)
|
|
91
|
+
i++
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Remark plugin that converts :::tab directives into ContentTab/ContentTabs JSX elements */
|
|
96
|
+
export const remarkTab: Plugin<[], Root> = () => {
|
|
97
|
+
return tree => {
|
|
98
|
+
transformTabDirectives(tree)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import type { Root } from "mdast"
|
|
2
|
+
import type { ContainerDirective } from "mdast-util-directive"
|
|
3
|
+
import { describe, expect, it } from "vite-plus/test"
|
|
4
|
+
import { transformTabDirectives } from "./remark-tab.ts"
|
|
5
|
+
|
|
6
|
+
function makeContainerDirective(
|
|
7
|
+
name: string,
|
|
8
|
+
attributes?: Record<string, string>,
|
|
9
|
+
): ContainerDirective {
|
|
10
|
+
return {
|
|
11
|
+
type: "containerDirective",
|
|
12
|
+
name,
|
|
13
|
+
attributes: attributes ?? {},
|
|
14
|
+
children: [
|
|
15
|
+
{ type: "paragraph", children: [{ type: "text", value: "content" }] },
|
|
16
|
+
],
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function makeTree(...children: Root["children"]): Root {
|
|
21
|
+
return { type: "root", children }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe("transformTabDirectives", () => {
|
|
25
|
+
function process(tree: Root) {
|
|
26
|
+
transformTabDirectives(tree)
|
|
27
|
+
return tree
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
it("should convert :::tab directive to ContentTab JSX element", () => {
|
|
31
|
+
const directive = makeContainerDirective("tab", { title: "React" })
|
|
32
|
+
const tree = process(makeTree(directive))
|
|
33
|
+
|
|
34
|
+
const node = tree.children[0]
|
|
35
|
+
expect(node).toMatchObject({
|
|
36
|
+
type: "mdxJsxFlowElement",
|
|
37
|
+
name: "ContentTabs",
|
|
38
|
+
children: [
|
|
39
|
+
{
|
|
40
|
+
type: "mdxJsxFlowElement",
|
|
41
|
+
name: "ContentTab",
|
|
42
|
+
attributes: [
|
|
43
|
+
{ type: "mdxJsxAttribute", name: "title", value: "React" },
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it("should default title to empty string when not provided", () => {
|
|
51
|
+
const directive = makeContainerDirective("tab")
|
|
52
|
+
const tree = process(makeTree(directive))
|
|
53
|
+
|
|
54
|
+
const wrapper = tree.children[0]
|
|
55
|
+
expect(wrapper).toMatchObject({
|
|
56
|
+
type: "mdxJsxFlowElement",
|
|
57
|
+
name: "ContentTabs",
|
|
58
|
+
children: [
|
|
59
|
+
{
|
|
60
|
+
type: "mdxJsxFlowElement",
|
|
61
|
+
name: "ContentTab",
|
|
62
|
+
attributes: [{ type: "mdxJsxAttribute", name: "title", value: "" }],
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it("should ignore non-tab container directives", () => {
|
|
69
|
+
const directive = makeContainerDirective("note")
|
|
70
|
+
const tree = process(makeTree(directive))
|
|
71
|
+
|
|
72
|
+
expect(tree.children[0]).toMatchObject({
|
|
73
|
+
type: "containerDirective",
|
|
74
|
+
name: "note",
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it("should wrap a single ContentTab in ContentTabs", () => {
|
|
79
|
+
const directive = makeContainerDirective("tab", { title: "Only" })
|
|
80
|
+
const tree = process(makeTree(directive))
|
|
81
|
+
|
|
82
|
+
expect(tree.children).toHaveLength(1)
|
|
83
|
+
expect(tree.children[0]).toMatchObject({
|
|
84
|
+
type: "mdxJsxFlowElement",
|
|
85
|
+
name: "ContentTabs",
|
|
86
|
+
children: [
|
|
87
|
+
{
|
|
88
|
+
type: "mdxJsxFlowElement",
|
|
89
|
+
name: "ContentTab",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it("should group consecutive tabs into a single ContentTabs wrapper", () => {
|
|
96
|
+
const tab1 = makeContainerDirective("tab", { title: "React" })
|
|
97
|
+
const tab2 = makeContainerDirective("tab", { title: "Vue" })
|
|
98
|
+
const tab3 = makeContainerDirective("tab", { title: "Svelte" })
|
|
99
|
+
const tree = process(makeTree(tab1, tab2, tab3))
|
|
100
|
+
|
|
101
|
+
expect(tree.children).toHaveLength(1)
|
|
102
|
+
const wrapper = tree.children[0]
|
|
103
|
+
expect(wrapper).toMatchObject({
|
|
104
|
+
type: "mdxJsxFlowElement",
|
|
105
|
+
name: "ContentTabs",
|
|
106
|
+
})
|
|
107
|
+
// @ts-expect-error mdxJsxFlowElement is not in mdast types
|
|
108
|
+
expect(wrapper.children).toHaveLength(3)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it("should not group tabs separated by other elements", () => {
|
|
112
|
+
const tab1 = makeContainerDirective("tab", { title: "A" })
|
|
113
|
+
const separator = {
|
|
114
|
+
type: "paragraph" as const,
|
|
115
|
+
children: [{ type: "text" as const, value: "break" }],
|
|
116
|
+
}
|
|
117
|
+
const tab2 = makeContainerDirective("tab", { title: "B" })
|
|
118
|
+
const tree = process(makeTree(tab1, separator, tab2))
|
|
119
|
+
|
|
120
|
+
expect(tree.children).toHaveLength(3)
|
|
121
|
+
expect(tree.children[0]).toMatchObject({
|
|
122
|
+
type: "mdxJsxFlowElement",
|
|
123
|
+
name: "ContentTabs",
|
|
124
|
+
})
|
|
125
|
+
expect(tree.children[1]).toMatchObject({ type: "paragraph" })
|
|
126
|
+
expect(tree.children[2]).toMatchObject({
|
|
127
|
+
type: "mdxJsxFlowElement",
|
|
128
|
+
name: "ContentTabs",
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it("should pass sync attribute to ContentTab when present", () => {
|
|
133
|
+
const directive = makeContainerDirective("tab", {
|
|
134
|
+
title: "npm",
|
|
135
|
+
sync: "pm",
|
|
136
|
+
})
|
|
137
|
+
const tree = process(makeTree(directive))
|
|
138
|
+
|
|
139
|
+
const wrapper = tree.children[0]
|
|
140
|
+
// @ts-expect-error mdxJsxFlowElement is not in mdast types
|
|
141
|
+
const tab = wrapper.children[0]
|
|
142
|
+
expect(tab).toMatchObject({
|
|
143
|
+
type: "mdxJsxFlowElement",
|
|
144
|
+
name: "ContentTab",
|
|
145
|
+
attributes: [
|
|
146
|
+
{ type: "mdxJsxAttribute", name: "title", value: "npm" },
|
|
147
|
+
{ type: "mdxJsxAttribute", name: "sync", value: "pm" },
|
|
148
|
+
],
|
|
149
|
+
})
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it("should propagate sync attribute to ContentTabs wrapper", () => {
|
|
153
|
+
const tab1 = makeContainerDirective("tab", {
|
|
154
|
+
title: "npm",
|
|
155
|
+
sync: "pm",
|
|
156
|
+
})
|
|
157
|
+
const tab2 = makeContainerDirective("tab", {
|
|
158
|
+
title: "pnpm",
|
|
159
|
+
sync: "pm",
|
|
160
|
+
})
|
|
161
|
+
const tree = process(makeTree(tab1, tab2))
|
|
162
|
+
|
|
163
|
+
expect(tree.children[0]).toMatchObject({
|
|
164
|
+
type: "mdxJsxFlowElement",
|
|
165
|
+
name: "ContentTabs",
|
|
166
|
+
attributes: [{ type: "mdxJsxAttribute", name: "sync", value: "pm" }],
|
|
167
|
+
})
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it("should not add sync attribute when not present", () => {
|
|
171
|
+
const tab1 = makeContainerDirective("tab", { title: "A" })
|
|
172
|
+
const tab2 = makeContainerDirective("tab", { title: "B" })
|
|
173
|
+
const tree = process(makeTree(tab1, tab2))
|
|
174
|
+
|
|
175
|
+
expect(tree.children[0]).toMatchObject({
|
|
176
|
+
type: "mdxJsxFlowElement",
|
|
177
|
+
name: "ContentTabs",
|
|
178
|
+
attributes: [],
|
|
179
|
+
})
|
|
180
|
+
})
|
|
181
|
+
})
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Root } from "mdast"
|
|
2
|
+
import type { LeafDirective } from "mdast-util-directive"
|
|
3
|
+
import type { Plugin } from "unified"
|
|
4
|
+
import { visit } from "unist-util-visit"
|
|
5
|
+
|
|
6
|
+
/** Walk a mdast tree and convert toc leaf directives into InlineToc JSX elements */
|
|
7
|
+
export function transformTocDirectives(tree: Root) {
|
|
8
|
+
visit(tree, "leafDirective", (node: LeafDirective, index, parent) => {
|
|
9
|
+
if (node.name !== "toc" || index === undefined || !parent) return
|
|
10
|
+
|
|
11
|
+
const maxLevel = node.attributes?.maxLevel
|
|
12
|
+
|
|
13
|
+
const jsxNode = {
|
|
14
|
+
type: "mdxJsxFlowElement" as const,
|
|
15
|
+
name: "InlineToc",
|
|
16
|
+
attributes: maxLevel
|
|
17
|
+
? [
|
|
18
|
+
{
|
|
19
|
+
type: "mdxJsxAttribute" as const,
|
|
20
|
+
name: "maxLevel",
|
|
21
|
+
value: maxLevel,
|
|
22
|
+
},
|
|
23
|
+
]
|
|
24
|
+
: [],
|
|
25
|
+
children: [],
|
|
26
|
+
data: { _mdxExplicitJsx: true },
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// @ts-expect-error mdxJsxFlowElement is not in mdast types
|
|
30
|
+
parent.children.splice(index, 1, jsxNode)
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Remark plugin that converts ::toc leaf directives into InlineToc JSX elements */
|
|
35
|
+
export const remarkToc: Plugin<[], Root> = () => {
|
|
36
|
+
return tree => {
|
|
37
|
+
transformTocDirectives(tree)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { Root } from "mdast"
|
|
2
|
+
import type { LeafDirective } from "mdast-util-directive"
|
|
3
|
+
import { describe, expect, it } from "vite-plus/test"
|
|
4
|
+
import { transformTocDirectives } from "./remark-toc.ts"
|
|
5
|
+
|
|
6
|
+
function makeLeafDirective(
|
|
7
|
+
name: string,
|
|
8
|
+
attributes: Record<string, string> = {},
|
|
9
|
+
): LeafDirective {
|
|
10
|
+
return {
|
|
11
|
+
type: "leafDirective" as LeafDirective["type"],
|
|
12
|
+
name,
|
|
13
|
+
attributes,
|
|
14
|
+
children: [],
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function makeTree(...children: Root["children"]): Root {
|
|
19
|
+
return { type: "root", children }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function process(tree: Root) {
|
|
23
|
+
transformTocDirectives(tree)
|
|
24
|
+
return tree
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe("transformTocDirectives", () => {
|
|
28
|
+
it("should convert toc directive to InlineToc JSX element", () => {
|
|
29
|
+
const tree = process(makeTree(makeLeafDirective("toc")))
|
|
30
|
+
const node = tree.children[0]
|
|
31
|
+
expect(node).toMatchObject({
|
|
32
|
+
type: "mdxJsxFlowElement",
|
|
33
|
+
name: "InlineToc",
|
|
34
|
+
attributes: [],
|
|
35
|
+
children: [],
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it("should ignore unrelated leaf directives", () => {
|
|
40
|
+
const tree = process(
|
|
41
|
+
makeTree(makeLeafDirective("video", { type: "youtube" })),
|
|
42
|
+
)
|
|
43
|
+
const node = tree.children[0]
|
|
44
|
+
expect(node).toMatchObject({ type: "leafDirective", name: "video" })
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it("should handle multiple toc directives in the same tree", () => {
|
|
48
|
+
const tree = process(
|
|
49
|
+
makeTree(
|
|
50
|
+
makeLeafDirective("toc"),
|
|
51
|
+
{ type: "paragraph", children: [{ type: "text", value: "hello" }] },
|
|
52
|
+
makeLeafDirective("toc"),
|
|
53
|
+
),
|
|
54
|
+
)
|
|
55
|
+
expect(tree.children[0]).toMatchObject({
|
|
56
|
+
type: "mdxJsxFlowElement",
|
|
57
|
+
name: "InlineToc",
|
|
58
|
+
})
|
|
59
|
+
expect(tree.children[1]).toMatchObject({ type: "paragraph" })
|
|
60
|
+
expect(tree.children[2]).toMatchObject({
|
|
61
|
+
type: "mdxJsxFlowElement",
|
|
62
|
+
name: "InlineToc",
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it("should preserve other children when converting toc directive", () => {
|
|
67
|
+
const tree = process(
|
|
68
|
+
makeTree(
|
|
69
|
+
{ type: "paragraph", children: [{ type: "text", value: "before" }] },
|
|
70
|
+
makeLeafDirective("toc"),
|
|
71
|
+
{ type: "paragraph", children: [{ type: "text", value: "after" }] },
|
|
72
|
+
),
|
|
73
|
+
)
|
|
74
|
+
expect(tree.children).toHaveLength(3)
|
|
75
|
+
expect(tree.children[0]).toMatchObject({ type: "paragraph" })
|
|
76
|
+
expect(tree.children[1]).toMatchObject({
|
|
77
|
+
type: "mdxJsxFlowElement",
|
|
78
|
+
name: "InlineToc",
|
|
79
|
+
})
|
|
80
|
+
expect(tree.children[2]).toMatchObject({ type: "paragraph" })
|
|
81
|
+
})
|
|
82
|
+
})
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
interface HastElement {
|
|
2
|
+
properties: Record<string, unknown>
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
interface ShikiTransformer {
|
|
6
|
+
name: string
|
|
7
|
+
pre: (
|
|
8
|
+
this: { options: { lang?: string } },
|
|
9
|
+
pre: HastElement,
|
|
10
|
+
) => HastElement | void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type Icon = { viewBox: string; fill: string; d: string }
|
|
14
|
+
|
|
15
|
+
const shortcuts: Record<string, string> = {
|
|
16
|
+
js: "javascript",
|
|
17
|
+
jsx: "react",
|
|
18
|
+
ts: "typescript",
|
|
19
|
+
tsx: "react",
|
|
20
|
+
py: "python",
|
|
21
|
+
bash: "shellscript",
|
|
22
|
+
sh: "shellscript",
|
|
23
|
+
shell: "shellscript",
|
|
24
|
+
zsh: "shellscript",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const icons: Record<string, Icon> = {
|
|
28
|
+
typescript: {
|
|
29
|
+
viewBox: "0 0 24 24",
|
|
30
|
+
fill: "currentColor",
|
|
31
|
+
d: "M1.125 0C.502 0 0 .502 0 1.125v21.75C0 23.498.502 24 1.125 24h21.75c.623 0 1.125-.502 1.125-1.125V1.125C24 .502 23.498 0 22.875 0zm17.363 9.75c.612 0 1.154.037 1.627.111a6.38 6.38 0 0 1 1.306.34v2.458a3.95 3.95 0 0 0-.643-.361 5.093 5.093 0 0 0-.717-.26 5.453 5.453 0 0 0-1.426-.2c-.3 0-.573.028-.819.086a2.1 2.1 0 0 0-.623.242c-.17.104-.3.229-.393.374a.888.888 0 0 0-.14.49c0 .196.053.373.156.529.104.156.252.304.443.444s.423.276.696.41c.273.135.582.274.926.416.47.197.892.407 1.266.628.374.222.695.473.963.753.268.279.472.598.614.957.142.359.214.776.214 1.253 0 .657-.125 1.21-.373 1.656a3.033 3.033 0 0 1-1.012 1.085 4.38 4.38 0 0 1-1.487.596c-.566.12-1.163.18-1.79.18a9.916 9.916 0 0 1-1.84-.164 5.544 5.544 0 0 1-1.512-.493v-2.63a5.033 5.033 0 0 0 3.237 1.2c.333 0 .624-.03.872-.09.249-.06.456-.144.623-.25.166-.108.29-.234.373-.38a1.023 1.023 0 0 0-.074-1.089 2.12 2.12 0 0 0-.537-.5 5.597 5.597 0 0 0-.807-.444 27.72 27.72 0 0 0-1.007-.436c-.918-.383-1.602-.852-2.053-1.405-.45-.553-.676-1.222-.676-2.005 0-.614.123-1.141.369-1.582.246-.441.58-.804 1.004-1.089a4.494 4.494 0 0 1 1.47-.629 7.536 7.536 0 0 1 1.77-.201zm-15.113.188h9.563v2.166H9.506v9.646H6.789v-9.646H3.375z",
|
|
32
|
+
},
|
|
33
|
+
javascript: {
|
|
34
|
+
viewBox: "0 0 24 24",
|
|
35
|
+
fill: "currentColor",
|
|
36
|
+
d: "M0 0h24v24H0V0zm22.034 18.276c-.175-1.095-.888-2.015-3.003-2.873-.736-.345-1.554-.585-1.797-1.14-.091-.33-.105-.51-.046-.705.15-.646.915-.84 1.515-.66.39.12.75.42.976.9 1.034-.676 1.034-.676 1.755-1.125-.27-.42-.405-.6-.586-.78-.63-.705-1.469-1.065-2.834-1.034l-.705.089c-.676.165-1.32.525-1.71 1.005-1.14 1.291-.811 3.541.569 4.471 1.365 1.02 3.361 1.244 3.616 2.205.24 1.17-.87 1.545-1.966 1.41-.811-.18-1.26-.586-1.755-1.336l-1.83 1.051c.21.48.45.689.81 1.109 1.74 1.756 6.09 1.666 6.871-1.004.029-.09.24-.705.074-1.65l.046.067zm-8.983-7.245h-2.248c0 1.938-.009 3.864-.009 5.805 0 1.232.063 2.363-.138 2.711-.33.689-1.18.601-1.566.48-.396-.196-.597-.466-.83-.855-.063-.105-.11-.196-.127-.196l-1.825 1.125c.305.63.75 1.172 1.324 1.517.855.51 2.004.675 3.207.405.783-.226 1.458-.691 1.811-1.411.51-.93.402-2.07.397-3.346.012-2.054 0-4.109 0-6.179l.004-.056z",
|
|
37
|
+
},
|
|
38
|
+
react: {
|
|
39
|
+
viewBox: "0 0 24 24",
|
|
40
|
+
fill: "currentColor",
|
|
41
|
+
d: "M14.23 12.004a2.236 2.236 0 0 1-2.235 2.236 2.236 2.236 0 0 1-2.236-2.236 2.236 2.236 0 0 1 2.235-2.236 2.236 2.236 0 0 1 2.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38-.318-.184-.688-.277-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44-.96-.236-2.006-.417-3.107-.534-.66-.905-1.345-1.727-2.035-2.447 1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442-1.107.117-2.154.298-3.113.538-.112-.49-.195-.964-.254-1.42-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87-.728.063-1.466.098-2.21.098-.74 0-1.477-.035-2.202-.093-.406-.582-.802-1.204-1.183-1.86-.372-.64-.71-1.29-1.018-1.946.303-.657.646-1.313 1.013-1.954.38-.66.773-1.286 1.18-1.868.728-.064 1.466-.098 2.21-.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933-.2-.39-.41-.783-.64-1.174-.225-.392-.465-.774-.705-1.146zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493-.28-.958-.646-1.956-1.1-2.98.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98-.45 1.017-.812 2.01-1.086 2.964-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39.24-.375.48-.762.705-1.158.225-.39.435-.788.636-1.18zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143-.695-.102-1.365-.23-2.006-.386.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295-.22-.005-.406-.05-.553-.132-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z",
|
|
42
|
+
},
|
|
43
|
+
python: {
|
|
44
|
+
viewBox: "0 0 24 24",
|
|
45
|
+
fill: "currentColor",
|
|
46
|
+
d: "M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01H8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z",
|
|
47
|
+
},
|
|
48
|
+
rust: {
|
|
49
|
+
viewBox: "0 0 24 24",
|
|
50
|
+
fill: "currentColor",
|
|
51
|
+
d: "M23.8346 11.7033l-1.0073-.6236a13.7268 13.7268 0 00-.0283-.2936l.8656-.8069a.3483.3483 0 00-.1154-.578l-1.1066-.414a8.4958 8.4958 0 00-.087-.2856l.6904-.9587a.3462.3462 0 00-.2257-.5446l-1.1663-.1894a9.3574 9.3574 0 00-.1407-.2622l.4895-1.0761a.3438.3438 0 00-.3300-.4908l-1.1845.0416a6.7444 6.7444 0 00-.1873-.2268l.2723-1.153a.3472.3472 0 00-.4233-.4164l-1.1592.2683a14.1794 14.1794 0 00-.2231-.1817l.0467-1.1872a.3462.3462 0 00-.5765-.322l-1.0907.4878c-.0799-.0499-.1613-.0983-.2449-.1456l-.1787-1.1758a.3456.3456 0 00-.5766-.2329l-.9813.6919a13.596 13.596 0 00-.2571-.1049l-.3982-1.1175a.348.348 0 00-.5815-.1272l-.8352.8738a10.2102 10.2102 0 00-.2606-.0584l-.6082-1.0131a.3459.3459 0 00-.5659-.0197l-.6602 1.0257a6.3249 6.3249 0 00-.2574.0068L8.3862.8721a.3437.3437 0 00-.5368.0921l-.4676 1.1376a10.3014 10.3014 0 00-.2444.0856L6.2788 1.394a.3447.3447 0 00-.4916.2004l-.2615 1.2048a11.5632 11.5632 0 00-.2242.149l-.9215-.5549a.3445.3445 0 00-.4345.2945l-.0488 1.2261a11.0239 11.0239 0 00-.1989.2028l-1.0498-.2744a.3441.3441 0 00-.3684.3752l.1643 1.2026c-.0553.075-.1084.1515-.1598.2293l-1.1374.0132a.3427.3427 0 00-.2938.4422l.3698 1.1347a10.4633 10.4633 0 00-.1162.2474l-1.1817.2923a.3433.3433 0 00-.2134.4944l.5627 1.0262c-.0265.085-.0502.1713-.0713.258l-1.1812.5586a.343.343 0 00-.1299.5316l.7396.8793a13.0102 13.0102 0 00-.0236.264l-1.1355.8086a.3445.3445 0 00-.0429.5513l.8937.6986a9.0776 9.0776 0 00.0235.2643L.3108 14.515a.3455.3455 0 00.0432.5508l1.0185.4941a14.4526 14.4526 0 00.0694.2602l-.6564.9682a.3443.3443 0 00.1273.5483l1.1066.2713c.0437.0833.0891.1653.136.2462l-.4348 1.0848a.3445.3445 0 00.2069.5304l1.1564.0436c.0583.0749.1182.1485.1797.2205l-.2004 1.1603a.348.348 0 00.2824.4902l1.1669-.1838c.0694.064.1404.1265.2127.1874l.0387 1.1912a.3476.3476 0 00.3498.4306l1.1388-.4038a7.4207 7.4207 0 00.2381.1482l.2723 1.1772a.3459.3459 0 00.4074.3543l1.0738-.6104c.084.0393.169.077.2553.113l.4964 1.1178a.3476.3476 0 00.4529.2643l.9744-.7985c.0873.0285.1757.0553.2649.0803l.707 1.015a.3475.3475 0 00.4827.165l.8435-.9633a8.7717 8.7717 0 00.267.0418l.8978.8715a.347.347 0 00.4959.0582l.6863-1.1004c.0877-.0039.1754-.0094.2631-.0166l1.0645.6907a.3478.3478 0 00.4921-.0466l.5043-1.2024c.0829-.0168.1657-.0349.2476-.0546l1.2024.478a.3444.3444 0 00.4721-.1462l.305-1.2685a9.4986 9.4986 0 00.2264-.0963l1.3088.241a.3462.3462 0 00.4373-.2383l.0931-1.2948a12.775 12.775 0 00.1996-.1384l1.3811-.0133a.3442.3442 0 00.3879-.3209l-.1204-1.2792a12.0697 12.0697 0 00.1677-.1767l1.4174-.2612a.3462.3462 0 00.3266-.3935l-.3286-1.222a13.5765 13.5765 0 00.1307-.2093l1.4154-.4985a.3454.3454 0 00.2558-.4536l-.5275-1.1259a8.7256 8.7256 0 00.0899-.2341l1.3741-.7219a.3439.3439 0 00.1787-.4993l-.7113-.9937a9.1373 9.1373 0 00.0449-.2543l1.2944-.9275a.3446.3446 0 00.0963-.5323zM12.0522 4.5705a.703.703 0 01.5765-.098c.3473.0982.6615.2679.9263.4973a.3873.3873 0 01-.5765.098c-.3473-.0982-.6615-.2679-.9263-.4973zm-3.2 7.5508c.2.0 .4-.0 .6-.0l.2 .6h-1l.2-.6zm4.5 2.7l-.4-.3.3-.4c-.3-.2-.7-.3-1.1-.3l-.1.5-.1-.5c-.4.0-.8.1-1.1.3l.3.4-.4.3c-.3-.3-.5-.6-.6-1l.5-.1-.5-.2c0-.4.1-.8.3-1.2l.4.3-.3-.4c.3-.3.6-.5 1-.6l.1.5.1-.5c.4.0.8.2 1.1.4l-.3.4.4-.3c.2.3.3.7.4 1.1l-.5.1.5.2c-.0.4-.2.8-.4 1.1zm3.3-2.1l-.6.0-.2-.6h1l-.2.6z",
|
|
52
|
+
},
|
|
53
|
+
shellscript: {
|
|
54
|
+
viewBox: "0 0 24 24",
|
|
55
|
+
fill: "currentColor",
|
|
56
|
+
d: "M4.814 0h14.371a2.813 2.813 0 0 1 2.814 2.814v18.371A2.813 2.813 0 0 1 19.186 24H4.814A2.813 2.813 0 0 1 2 21.186V2.814A2.813 2.813 0 0 1 4.814 0zM5.8 21.2h12.39v-1.6H5.8zm6.636-4.762L7.394 12.17l1.07-1.258 5.043 4.268zm-1.111-5.889 1.07-1.258 5.043 4.268-5.043 4.268-1.07-1.258 3.972-3.01z",
|
|
57
|
+
},
|
|
58
|
+
default: {
|
|
59
|
+
viewBox: "0 0 24 24",
|
|
60
|
+
fill: "currentColor",
|
|
61
|
+
d: "M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z",
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Shiki transformer that injects a language icon SVG into the pre element.
|
|
67
|
+
*/
|
|
68
|
+
export function transformerIcon(): ShikiTransformer {
|
|
69
|
+
return {
|
|
70
|
+
name: "livemark:icon",
|
|
71
|
+
pre(pre) {
|
|
72
|
+
const lang = this.options.lang
|
|
73
|
+
if (!lang) return
|
|
74
|
+
|
|
75
|
+
const iconName = lang in shortcuts ? shortcuts[lang]! : lang
|
|
76
|
+
const icon = iconName in icons ? icons[iconName]! : icons.default!
|
|
77
|
+
|
|
78
|
+
pre.properties.icon = `<svg viewBox="${icon.viewBox}"><path d="${icon.d}" fill="${icon.fill}" /></svg>`
|
|
79
|
+
return pre
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
}
|