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-plugin-svelte": "^2.46.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",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-svelte": "^3.2.7",
|
||||
|
@ -48,15 +51,19 @@
|
|||
"hast-util-heading": "^3.0.0",
|
||||
"hast-util-heading-rank": "^3.0.0",
|
||||
"hast-util-to-text": "^4.0.2",
|
||||
"hastscript": "^9.0.0",
|
||||
"lucide-static": "^0.462.0",
|
||||
"lucide-svelte": "^0.446.0",
|
||||
"rehype-infer-description-meta": "^2.0.0",
|
||||
"rehype-raw": "^7.0.0",
|
||||
"rehype-sanitize": "^6.0.0",
|
||||
"rehype-slug": "^6.0.0",
|
||||
"rehype-stringify": "^10.0.1",
|
||||
"remark-directive": "^3.0.0",
|
||||
"remark-frontmatter": "^5.0.0",
|
||||
"remark-gemoji": "^8.0.0",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"remark-github-admonitions-to-directives": "^2.1.0",
|
||||
"remark-parse": "^11.0.0",
|
||||
"remark-rehype": "^11.1.1",
|
||||
"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/utilities";
|
||||
|
||||
@import "admonitions.css";
|
||||
|
||||
:root {
|
||||
--color-background: 255 245 230;
|
||||
--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
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
|
|
|
@ -3,14 +3,19 @@ import type { Nodes } from "hast"
|
|||
import { heading } from "hast-util-heading"
|
||||
import { headingRank } from "hast-util-heading-rank"
|
||||
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 rehypeRaw from "rehype-raw"
|
||||
import rehypeSanitize from "rehype-sanitize"
|
||||
import rehypeSanitize, { defaultSchema } from "rehype-sanitize"
|
||||
import rehypeSlug from "rehype-slug"
|
||||
import rehypeStringify from "rehype-stringify"
|
||||
import remarkDirective from "remark-directive"
|
||||
import remarkFrontmatter from "remark-frontmatter"
|
||||
import remarkGemoji from "remark-gemoji"
|
||||
import remarkGfm from "remark-gfm"
|
||||
import remarkGithubAdmonitionsToDirectives from "remark-github-admonitions-to-directives"
|
||||
import remarkParse from "remark-parse"
|
||||
import remarkRehype from "remark-rehype"
|
||||
import { createCssVariablesTheme, createHighlighter } from "shiki"
|
||||
|
@ -23,15 +28,92 @@ const highlighter = createHighlighter({
|
|||
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 () => {
|
||||
return unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkFrontmatter)
|
||||
.use(remarkGfm)
|
||||
.use(remarkGemoji)
|
||||
.use(remarkRehype, { allowDangerousHtml: true })
|
||||
.use(remarkGithubAdmonitionsToDirectives)
|
||||
.use(remarkDirective)
|
||||
.use(remarkRehype, { allowDangerousHtml: true, handlers: remarkRehypeHandlers })
|
||||
.use(rehypeRaw)
|
||||
.use(rehypeSanitize)
|
||||
.use(rehypeSanitize, sanitizeSchema)
|
||||
.use(rehypeShikiFromHighlighter, await highlighter, {
|
||||
lazy: true,
|
||||
theme: createCssVariablesTheme({
|
||||
|
@ -58,7 +140,13 @@ export const docsMarkdown = (async () => {
|
|||
.use(remarkFrontmatter)
|
||||
.use(remarkGfm)
|
||||
.use(remarkGemoji)
|
||||
.use(remarkRehype, { allowDangerousHtml: true, clobberPrefix: "" })
|
||||
.use(remarkGithubAdmonitionsToDirectives)
|
||||
.use(remarkDirective)
|
||||
.use(remarkRehype, {
|
||||
allowDangerousHtml: true,
|
||||
clobberPrefix: "",
|
||||
handlers: remarkRehypeHandlers,
|
||||
})
|
||||
.use(rehypeSlug)
|
||||
.use(() => (node, file) => {
|
||||
const toc: TocItem[] = []
|
||||
|
@ -97,7 +185,7 @@ export const docsMarkdown = (async () => {
|
|||
}) as Node
|
||||
})
|
||||
.use(rehypeRaw)
|
||||
.use(rehypeSanitize)
|
||||
.use(rehypeSanitize, sanitizeSchema)
|
||||
.use(rehypeShikiFromHighlighter, await highlighter, {
|
||||
lazy: true,
|
||||
theme: createCssVariablesTheme({
|
||||
|
|
Loading…
Reference in a new issue