feat: built-in callout (#1016)
* feat: built-in callout * update callout padding * lock dep version
This commit is contained in:
parent
e011c8924a
commit
9ade4e847c
|
|
@ -57,6 +57,7 @@
|
|||
"@lezer/highlight": "1.1.6",
|
||||
"@mantine/core": "7.0.2",
|
||||
"@mantine/dates": "7.0.2",
|
||||
"@microflash/remark-callout-directives": "1.6.0",
|
||||
"@monaco-editor/react": "4.5.2",
|
||||
"@popperjs/core": "2.11.8",
|
||||
"@prisma/client": "5.3.1",
|
||||
|
|
|
|||
|
|
@ -86,6 +86,9 @@ dependencies:
|
|||
'@mantine/dates':
|
||||
specifier: 7.0.2
|
||||
version: 7.0.2(@mantine/core@7.0.2)(@mantine/hooks@7.0.2)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@microflash/remark-callout-directives':
|
||||
specifier: 1.6.0
|
||||
version: 1.6.0
|
||||
'@monaco-editor/react':
|
||||
specifier: 4.5.2
|
||||
version: 4.5.2(monaco-editor@0.43.0)(react-dom@18.2.0)(react@18.2.0)
|
||||
|
|
@ -2368,6 +2371,17 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@microflash/remark-callout-directives@1.6.0:
|
||||
resolution: {integrity: sha512-W2ovtw9JdSpO/gjQb3wlf3o5AW4h+w6mewXybsrtSvifb/30P7ahBELDmFSCQBuXiofMbN8xO0/0GqVYoZrXmQ==}
|
||||
dependencies:
|
||||
defu: 6.1.2
|
||||
hastscript: 7.2.0
|
||||
mdast-util-from-markdown: 1.3.1
|
||||
unist-util-visit: 4.1.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@monaco-editor/loader@1.3.3(monaco-editor@0.43.0):
|
||||
resolution: {integrity: sha512-6KKF4CTzcJiS8BJwtxtfyYt9shBiEv32ateQ9T4UVogwn4HM/uPo9iJd2Dmbkpz8CM6Y0PDUpjnZzCwC+eYo2Q==}
|
||||
peerDependencies:
|
||||
|
|
@ -5492,6 +5506,10 @@ packages:
|
|||
object-keys: 1.1.1
|
||||
dev: true
|
||||
|
||||
/defu@6.1.2:
|
||||
resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==}
|
||||
dev: false
|
||||
|
||||
/delaunator@5.0.0:
|
||||
resolution: {integrity: sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==}
|
||||
dependencies:
|
||||
|
|
|
|||
|
|
@ -136,20 +136,94 @@
|
|||
}
|
||||
|
||||
.prose .callout {
|
||||
@apply border border-zinc-100 bg-zinc-50 text-accent rounded-xl p-5 md:p-8 font-normal;
|
||||
@apply -mx-5 md:-mx-8 my-10;
|
||||
--callout-color: hsl(207, 14%, 62%);
|
||||
--callout-background: ;
|
||||
--callout-border: hsl(205, 15%, 33%);
|
||||
--callout-radius: 8px;
|
||||
--callout-padding: 2ch;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: var(--callout-border);
|
||||
border-radius: var(--callout-radius);
|
||||
background: var(--callout-background);
|
||||
margin-top: 0.8em;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
|
||||
.prose .callout code,
|
||||
.prose .callout pre {
|
||||
background-color: hsl(0, 0%, 100%, 0.1);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.prose .callout-content {
|
||||
padding-left: var(--callout-padding);
|
||||
padding-right: var(--callout-padding);
|
||||
}
|
||||
|
||||
.prose .callout-content:first-child,
|
||||
.prose .callout-content:only-child {
|
||||
margin-block-start: 0;
|
||||
}
|
||||
|
||||
.prose .callout-content:last-child,
|
||||
.prose .callout-content:only-child {
|
||||
margin-block-end: 0;
|
||||
}
|
||||
|
||||
.prose .callout-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--callout-padding) var(--callout-padding) 0;
|
||||
}
|
||||
|
||||
.prose .callout-hint {
|
||||
margin-inline-end: calc(var(--callout-padding) / 4);
|
||||
color: var(--callout-color);
|
||||
}
|
||||
|
||||
.prose .callout-title {
|
||||
margin-inline-start: calc(var(--callout-padding) / 4);
|
||||
color: var(--callout-color);
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.prose .callout-note {
|
||||
--callout-background: hsla(0, 0%, 0%, 0.05);
|
||||
--callout-color: hsl(0, 0%, 43%);
|
||||
--callout-border: hsl(0, 0%, 0%, 0.25);
|
||||
}
|
||||
|
||||
:root.dark .prose .callout-note {
|
||||
--callout-background: hsl(0, 0%, 100%, 0.05);
|
||||
--callout-color: hsl(0, 0%, 43%);
|
||||
--callout-border: hsl(0, 0%, 100%, 0.25);
|
||||
}
|
||||
|
||||
.prose .callout-commend {
|
||||
--callout-background: hsl(153, 47%, 49%, 0.05);
|
||||
--callout-color: hsl(153, 62%, 54%);
|
||||
--callout-border: hsl(153, 47%, 49%, 0.25);
|
||||
}
|
||||
|
||||
.prose .callout-warn {
|
||||
@apply border-orange-200 bg-orange-100 text-orange-700;
|
||||
--callout-background: hsl(45, 100%, 55%, 0.05);
|
||||
--callout-color: hsl(45, 97%, 66%);
|
||||
--callout-border: hsl(45, 100%, 55%, 0.25);
|
||||
}
|
||||
|
||||
.prose .callout-success {
|
||||
@apply border-green-200 bg-green-100 text-green-700;
|
||||
.prose .callout-deter {
|
||||
--callout-background: hsl(353, 83%, 58%, 0.05);
|
||||
--callout-color: hsl(341, 89%, 63%);
|
||||
--callout-border: hsl(353, 83%, 58%, 0.25);
|
||||
}
|
||||
|
||||
.prose .callout-danger {
|
||||
@apply border-red-200 bg-red-100 text-red-700;
|
||||
.prose .callout-assert {
|
||||
--callout-background: rgba(47, 131, 157, 0.05);
|
||||
--callout-color: hsl(201, 89%, 63%);
|
||||
--callout-border: hsl(195, 61%, 56%, 0.25);
|
||||
}
|
||||
|
||||
.prose .code-wrapper {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ import remarkParse from "remark-parse"
|
|||
import remarkRehype from "remark-rehype"
|
||||
import { unified } from "unified"
|
||||
|
||||
// @ts-expect-error
|
||||
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
|
||||
|
||||
import AdvancedImage from "~/components/ui/AdvancedImage"
|
||||
|
||||
import { transformers } from "./embed-transformers"
|
||||
|
|
@ -44,7 +47,6 @@ import { rehypeTable } from "./rehype-table"
|
|||
import { rehypeVideo } from "./rehype-video"
|
||||
import { rehypeWrapCode } from "./rehype-wrap-code"
|
||||
import { rehypeExternalLink } from "./rehyper-external-link"
|
||||
import { remarkCallout } from "./remark-callout"
|
||||
import { remarkMermaid } from "./remark-mermaid"
|
||||
import { remarkPangu } from "./remark-pangu"
|
||||
import { remarkYoutube } from "./remark-youtube"
|
||||
|
|
@ -121,9 +123,9 @@ export const renderPageContent = (
|
|||
.use(remarkGfm, {
|
||||
singleTilde: false,
|
||||
})
|
||||
.use(remarkCallout)
|
||||
.use(remarkDirective)
|
||||
.use(remarkDirectiveRehype)
|
||||
.use(remarkCalloutDirectives)
|
||||
.use(remarkYoutube)
|
||||
.use(remarkMermaid)
|
||||
.use(remarkMath, {
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
import type { Root } from "mdast"
|
||||
import type { Plugin } from "unified"
|
||||
import { visit } from "unist-util-visit"
|
||||
|
||||
const CALLOUT_RE = /^(TIP|WARN|SUCCESS|DANGER):(\n|$)/
|
||||
|
||||
export const remarkCallout: Plugin<[], Root> = () => (tree: Root) => {
|
||||
visit(tree, { type: "blockquote" }, (node, index, parent) => {
|
||||
if (node.type !== "blockquote") return
|
||||
|
||||
const firstChild = node.children[0]
|
||||
if (firstChild?.type === "paragraph") {
|
||||
const paragraphFirstChild = firstChild.children[0]
|
||||
if (
|
||||
paragraphFirstChild.type === "text" &&
|
||||
CALLOUT_RE.test(paragraphFirstChild.value)
|
||||
) {
|
||||
const type = paragraphFirstChild.value.match(CALLOUT_RE)![1]
|
||||
const newValue = paragraphFirstChild.value.replace(CALLOUT_RE, "")
|
||||
// In the following case `newValue` will be empty empty
|
||||
// We should remove the paragraph
|
||||
// > TIP:
|
||||
// >
|
||||
// > some tip
|
||||
if (!newValue) {
|
||||
node.children.splice(0, 1)
|
||||
}
|
||||
paragraphFirstChild.value = newValue
|
||||
const className = `callout callout-${type.toLowerCase()}`
|
||||
node.data = {
|
||||
...node.data,
|
||||
hProperties: {
|
||||
class: className,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const allowedBlockquoteAttrs: Array<[string, ...string[]]> = [
|
||||
[
|
||||
"className",
|
||||
"callout",
|
||||
"callout-tip",
|
||||
"callout-warn",
|
||||
"callout-success",
|
||||
"callout-danger",
|
||||
],
|
||||
]
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
import { defaultSchema } from "rehype-sanitize"
|
||||
|
||||
import { allowedBlockquoteAttrs } from "./remark-callout"
|
||||
|
||||
const scheme = {
|
||||
...defaultSchema,
|
||||
tagNames: [
|
||||
|
|
@ -16,11 +14,12 @@ const scheme = {
|
|||
"audio",
|
||||
"source",
|
||||
"mermaid",
|
||||
"aside",
|
||||
...["svg", "path", "circle"],
|
||||
],
|
||||
attributes: {
|
||||
...defaultSchema.attributes,
|
||||
"*": [...(defaultSchema.attributes?.["*"] || []), "className", "style"],
|
||||
blockquote: allowedBlockquoteAttrs,
|
||||
video: ["src", "controls", "loop", "muted", "autoPlay", "playsInline"],
|
||||
audio: [
|
||||
"src",
|
||||
|
|
@ -35,6 +34,19 @@ const scheme = {
|
|||
],
|
||||
source: ["src", "type"],
|
||||
iframe: ["src", "allowFullScreen", "frameborder", "allow"],
|
||||
svg: [
|
||||
"xmlns",
|
||||
"width",
|
||||
"height",
|
||||
"viewBox",
|
||||
"fill",
|
||||
"stroke",
|
||||
"strokeLineCap",
|
||||
"strokeLineJoin",
|
||||
"strokeWidth",
|
||||
],
|
||||
path: ["d", "fill"],
|
||||
circle: ["cx", "cy", "r", "fill"],
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue