mirror of
https://github.com/pesde-pkg/pesde.git
synced 2024-12-12 11:00:36 +00:00
feat: add admonitions to main website (#11)
* feat: add admonitions * feat: better admonition styles * feat: more admonition styles
This commit is contained in:
parent
81ecd02df2
commit
af30701a21
6 changed files with 212 additions and 5 deletions
Binary file not shown.
|
@ -24,6 +24,9 @@
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-svelte": "^2.46.0",
|
"eslint-plugin-svelte": "^2.46.0",
|
||||||
"globals": "^15.11.0",
|
"globals": "^15.11.0",
|
||||||
|
"mdast": "^3.0.0",
|
||||||
|
"mdast-util-directive": "^3.0.0",
|
||||||
|
"mdast-util-to-hast": "^13.2.0",
|
||||||
"mdsvex": "^0.12.3",
|
"mdsvex": "^0.12.3",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"prettier-plugin-svelte": "^3.2.7",
|
"prettier-plugin-svelte": "^3.2.7",
|
||||||
|
@ -48,15 +51,19 @@
|
||||||
"hast-util-heading": "^3.0.0",
|
"hast-util-heading": "^3.0.0",
|
||||||
"hast-util-heading-rank": "^3.0.0",
|
"hast-util-heading-rank": "^3.0.0",
|
||||||
"hast-util-to-text": "^4.0.2",
|
"hast-util-to-text": "^4.0.2",
|
||||||
|
"hastscript": "^9.0.0",
|
||||||
|
"lucide-static": "^0.462.0",
|
||||||
"lucide-svelte": "^0.446.0",
|
"lucide-svelte": "^0.446.0",
|
||||||
"rehype-infer-description-meta": "^2.0.0",
|
"rehype-infer-description-meta": "^2.0.0",
|
||||||
"rehype-raw": "^7.0.0",
|
"rehype-raw": "^7.0.0",
|
||||||
"rehype-sanitize": "^6.0.0",
|
"rehype-sanitize": "^6.0.0",
|
||||||
"rehype-slug": "^6.0.0",
|
"rehype-slug": "^6.0.0",
|
||||||
"rehype-stringify": "^10.0.1",
|
"rehype-stringify": "^10.0.1",
|
||||||
|
"remark-directive": "^3.0.0",
|
||||||
"remark-frontmatter": "^5.0.0",
|
"remark-frontmatter": "^5.0.0",
|
||||||
"remark-gemoji": "^8.0.0",
|
"remark-gemoji": "^8.0.0",
|
||||||
"remark-gfm": "^4.0.0",
|
"remark-gfm": "^4.0.0",
|
||||||
|
"remark-github-admonitions-to-directives": "^2.1.0",
|
||||||
"remark-parse": "^11.0.0",
|
"remark-parse": "^11.0.0",
|
||||||
"remark-rehype": "^11.1.1",
|
"remark-rehype": "^11.1.1",
|
||||||
"shiki": "^1.22.2",
|
"shiki": "^1.22.2",
|
||||||
|
|
108
website/src/admonitions.css
Normal file
108
website/src/admonitions.css
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
.admonition {
|
||||||
|
@apply my-4 rounded-sm px-4 py-3 text-[--tw-prose-body] prose-p:my-2 prose-pre:my-4;
|
||||||
|
@apply border-l-4 border-[--admonition-border];
|
||||||
|
@apply bg-[--admonition-bg];
|
||||||
|
|
||||||
|
@apply [--shiki-background:theme(colors.white/0.2)];
|
||||||
|
@apply dark:[--shiki-background:theme(colors.black/0.2)];
|
||||||
|
|
||||||
|
--tw-prose-body: theme(colors.light);
|
||||||
|
--tw-prose-headings: theme(colors.light);
|
||||||
|
--tw-prose-lead: theme(colors.light);
|
||||||
|
--tw-prose-links: var(--admonition-text);
|
||||||
|
--tw-prose-bold: theme(colors.light);
|
||||||
|
--tw-prose-counters: theme(colors.light);
|
||||||
|
--tw-prose-bullets: var(--admonition-border);
|
||||||
|
--tw-prose-hr: var(--admonition-border);
|
||||||
|
--tw-prose-quotes: theme(colors.light);
|
||||||
|
--tw-prose-quote-borders: var(--admonition-border);
|
||||||
|
--tw-prose-code: theme(colors.light);
|
||||||
|
--tw-prose-pre-code: theme(colors.light);
|
||||||
|
--tw-prose-pre-bg: var(--shiki-background);
|
||||||
|
--tw-prose-th-borders: var(--admonition-border);
|
||||||
|
--tw-prose-td-borders: var(--admonition-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition pre {
|
||||||
|
@apply border border-[--admonition-border] bg-[--shiki-background];
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-title {
|
||||||
|
@apply flex items-center space-x-2 text-lg font-semibold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-title * {
|
||||||
|
color: var(--admonition-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-icon {
|
||||||
|
@apply inline-block size-6 bg-current;
|
||||||
|
mask-image: var(--admonition-icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-note {
|
||||||
|
--admonition-bg: theme(colors.blue.600 / 0.1);
|
||||||
|
--admonition-border: theme(colors.blue.600 / 0.4);
|
||||||
|
--admonition-text: theme(colors.blue.950);
|
||||||
|
--admonition-icon: url(lucide-static/icons/info.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-tip {
|
||||||
|
--admonition-bg: theme(colors.green.600 / 0.1);
|
||||||
|
--admonition-border: theme(colors.green.600 / 0.4);
|
||||||
|
--admonition-text: theme(colors.green.950);
|
||||||
|
--admonition-icon: url(lucide-static/icons/lightbulb.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-info {
|
||||||
|
--admonition-bg: theme(colors.purple.600 / 0.1);
|
||||||
|
--admonition-border: theme(colors.purple.600 / 0.4);
|
||||||
|
--admonition-text: theme(colors.purple.950);
|
||||||
|
--admonition-icon: url(lucide-static/icons/message-square-warning.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-warning {
|
||||||
|
--admonition-bg: theme(colors.yellow.600 / 0.1);
|
||||||
|
--admonition-border: theme(colors.yellow.600 / 0.4);
|
||||||
|
--admonition-text: theme(colors.yellow.950);
|
||||||
|
--admonition-icon: url(lucide-static/icons/triangle-alert.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-danger {
|
||||||
|
--admonition-bg: theme(colors.red.600 / 0.1);
|
||||||
|
--admonition-border: theme(colors.red.600 / 0.4);
|
||||||
|
--admonition-text: theme(colors.red.950);
|
||||||
|
--admonition-icon: url(lucide-static/icons/octagon-alert.svg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.admonition-note {
|
||||||
|
--admonition-bg: theme(colors.blue.500 / 0.1);
|
||||||
|
--admonition-border: theme(colors.blue.500 / 0.6);
|
||||||
|
--admonition-text: theme(colors.blue.100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-tip {
|
||||||
|
--admonition-bg: theme(colors.green.500 / 0.1);
|
||||||
|
--admonition-border: theme(colors.green.500 / 0.6);
|
||||||
|
--admonition-text: theme(colors.green.100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-info {
|
||||||
|
--admonition-bg: theme(colors.purple.500 / 0.1);
|
||||||
|
--admonition-border: theme(colors.purple.500 / 0.6);
|
||||||
|
--admonition-text: theme(colors.purple.100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-warning {
|
||||||
|
--admonition-bg: theme(colors.yellow.500 / 0.1);
|
||||||
|
--admonition-border: theme(colors.yellow.500 / 0.6);
|
||||||
|
--admonition-text: theme(colors.yellow.100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admonition-danger {
|
||||||
|
--admonition-bg: theme(colors.red.500 / 0.1);
|
||||||
|
--admonition-border: theme(colors.red.500 / 0.6);
|
||||||
|
--admonition-text: theme(colors.red.100);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@
|
||||||
@import "tailwindcss/components";
|
@import "tailwindcss/components";
|
||||||
@import "tailwindcss/utilities";
|
@import "tailwindcss/utilities";
|
||||||
|
|
||||||
|
@import "admonitions.css";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--color-background: 255 245 230;
|
--color-background: 255 245 230;
|
||||||
--color-card: 245 230 210;
|
--color-card: 245 230 210;
|
||||||
|
|
2
website/src/app.d.ts
vendored
2
website/src/app.d.ts
vendored
|
@ -1,3 +1,5 @@
|
||||||
|
/// <reference types="mdast-util-directive" />
|
||||||
|
|
||||||
// See https://kit.svelte.dev/docs/types#app
|
// See https://kit.svelte.dev/docs/types#app
|
||||||
// for information about these interfaces
|
// for information about these interfaces
|
||||||
declare global {
|
declare global {
|
||||||
|
|
|
@ -3,14 +3,19 @@ import type { Nodes } from "hast"
|
||||||
import { heading } from "hast-util-heading"
|
import { heading } from "hast-util-heading"
|
||||||
import { headingRank } from "hast-util-heading-rank"
|
import { headingRank } from "hast-util-heading-rank"
|
||||||
import { toText } from "hast-util-to-text"
|
import { toText } from "hast-util-to-text"
|
||||||
|
import { h, type Child } from "hastscript"
|
||||||
|
import type { ContainerDirective } from "mdast-util-directive"
|
||||||
|
import type { Handler } from "mdast-util-to-hast"
|
||||||
import rehypeInferDescriptionMeta from "rehype-infer-description-meta"
|
import rehypeInferDescriptionMeta from "rehype-infer-description-meta"
|
||||||
import rehypeRaw from "rehype-raw"
|
import rehypeRaw from "rehype-raw"
|
||||||
import rehypeSanitize from "rehype-sanitize"
|
import rehypeSanitize, { defaultSchema } from "rehype-sanitize"
|
||||||
import rehypeSlug from "rehype-slug"
|
import rehypeSlug from "rehype-slug"
|
||||||
import rehypeStringify from "rehype-stringify"
|
import rehypeStringify from "rehype-stringify"
|
||||||
|
import remarkDirective from "remark-directive"
|
||||||
import remarkFrontmatter from "remark-frontmatter"
|
import remarkFrontmatter from "remark-frontmatter"
|
||||||
import remarkGemoji from "remark-gemoji"
|
import remarkGemoji from "remark-gemoji"
|
||||||
import remarkGfm from "remark-gfm"
|
import remarkGfm from "remark-gfm"
|
||||||
|
import remarkGithubAdmonitionsToDirectives from "remark-github-admonitions-to-directives"
|
||||||
import remarkParse from "remark-parse"
|
import remarkParse from "remark-parse"
|
||||||
import remarkRehype from "remark-rehype"
|
import remarkRehype from "remark-rehype"
|
||||||
import { createCssVariablesTheme, createHighlighter } from "shiki"
|
import { createCssVariablesTheme, createHighlighter } from "shiki"
|
||||||
|
@ -23,15 +28,92 @@ const highlighter = createHighlighter({
|
||||||
langs: [],
|
langs: [],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const ADMONITION_TYPES = {
|
||||||
|
note: {
|
||||||
|
label: "Note",
|
||||||
|
},
|
||||||
|
tip: {
|
||||||
|
label: "Tip",
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
label: "Info",
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
label: "Warning",
|
||||||
|
},
|
||||||
|
danger: {
|
||||||
|
label: "Danger",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const containerDirectiveHandler: Handler = (state, node: ContainerDirective) => {
|
||||||
|
const type = node.name as keyof typeof ADMONITION_TYPES
|
||||||
|
if (!type || !(type in ADMONITION_TYPES)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeInfo = ADMONITION_TYPES[type]
|
||||||
|
|
||||||
|
let label: Child = typeInfo.label
|
||||||
|
|
||||||
|
const firstChild = node.children[0]
|
||||||
|
if (firstChild?.type === "paragraph" && firstChild.data?.directiveLabel) {
|
||||||
|
node.children.shift()
|
||||||
|
label = state.all(firstChild)
|
||||||
|
}
|
||||||
|
|
||||||
|
return h(
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
class: `admonition admonition-${type}`,
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h(
|
||||||
|
"p",
|
||||||
|
{
|
||||||
|
class: "admonition-title",
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h("span", {
|
||||||
|
class: "admonition-icon",
|
||||||
|
}),
|
||||||
|
h(
|
||||||
|
"span",
|
||||||
|
{
|
||||||
|
class: "admonition-label",
|
||||||
|
},
|
||||||
|
label,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
state.all(node),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const sanitizeSchema: typeof defaultSchema = {
|
||||||
|
...defaultSchema,
|
||||||
|
attributes: {
|
||||||
|
...defaultSchema.attributes,
|
||||||
|
"*": [...(defaultSchema.attributes?.["*"] ?? []), ["className", "admonition", /^admonition-/]],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const remarkRehypeHandlers = {
|
||||||
|
containerDirective: containerDirectiveHandler,
|
||||||
|
}
|
||||||
|
|
||||||
export const markdown = (async () => {
|
export const markdown = (async () => {
|
||||||
return unified()
|
return unified()
|
||||||
.use(remarkParse)
|
.use(remarkParse)
|
||||||
.use(remarkFrontmatter)
|
.use(remarkFrontmatter)
|
||||||
.use(remarkGfm)
|
.use(remarkGfm)
|
||||||
.use(remarkGemoji)
|
.use(remarkGemoji)
|
||||||
.use(remarkRehype, { allowDangerousHtml: true })
|
.use(remarkGithubAdmonitionsToDirectives)
|
||||||
|
.use(remarkDirective)
|
||||||
|
.use(remarkRehype, { allowDangerousHtml: true, handlers: remarkRehypeHandlers })
|
||||||
.use(rehypeRaw)
|
.use(rehypeRaw)
|
||||||
.use(rehypeSanitize)
|
.use(rehypeSanitize, sanitizeSchema)
|
||||||
.use(rehypeShikiFromHighlighter, await highlighter, {
|
.use(rehypeShikiFromHighlighter, await highlighter, {
|
||||||
lazy: true,
|
lazy: true,
|
||||||
theme: createCssVariablesTheme({
|
theme: createCssVariablesTheme({
|
||||||
|
@ -58,7 +140,13 @@ export const docsMarkdown = (async () => {
|
||||||
.use(remarkFrontmatter)
|
.use(remarkFrontmatter)
|
||||||
.use(remarkGfm)
|
.use(remarkGfm)
|
||||||
.use(remarkGemoji)
|
.use(remarkGemoji)
|
||||||
.use(remarkRehype, { allowDangerousHtml: true, clobberPrefix: "" })
|
.use(remarkGithubAdmonitionsToDirectives)
|
||||||
|
.use(remarkDirective)
|
||||||
|
.use(remarkRehype, {
|
||||||
|
allowDangerousHtml: true,
|
||||||
|
clobberPrefix: "",
|
||||||
|
handlers: remarkRehypeHandlers,
|
||||||
|
})
|
||||||
.use(rehypeSlug)
|
.use(rehypeSlug)
|
||||||
.use(() => (node, file) => {
|
.use(() => (node, file) => {
|
||||||
const toc: TocItem[] = []
|
const toc: TocItem[] = []
|
||||||
|
@ -97,7 +185,7 @@ export const docsMarkdown = (async () => {
|
||||||
}) as Node
|
}) as Node
|
||||||
})
|
})
|
||||||
.use(rehypeRaw)
|
.use(rehypeRaw)
|
||||||
.use(rehypeSanitize)
|
.use(rehypeSanitize, sanitizeSchema)
|
||||||
.use(rehypeShikiFromHighlighter, await highlighter, {
|
.use(rehypeShikiFromHighlighter, await highlighter, {
|
||||||
lazy: true,
|
lazy: true,
|
||||||
theme: createCssVariablesTheme({
|
theme: createCssVariablesTheme({
|
||||||
|
|
Loading…
Reference in a new issue