Skip to content

Commit

Permalink
feat: remark and rehype plugins for attention block
Browse files Browse the repository at this point in the history
  • Loading branch information
taga3s committed Dec 8, 2024
1 parent a0f40bc commit a8f6fef
Show file tree
Hide file tree
Showing 7 changed files with 345 additions and 3 deletions.
183 changes: 183 additions & 0 deletions app/packages/rehype-attention-block/icon-svg-hasts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import type { Element } from "hast";

const NOTE_ICON_HAST: Element = {
type: "element",
tagName: "svg",
properties: {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 512 512",
},
children: [
{
type: "comment",
value:
"!Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.",
position: {
start: {
line: 1,
column: 63,
offset: 62,
},
end: {
line: 1,
column: 214,
offset: 213,
},
},
},
{
type: "element",
tagName: "path",
properties: {
d: "M362.7 19.3L314.3 67.7 444.3 197.7l48.4-48.4c25-25 25-65.5 0-90.5L453.3 19.3c-25-25-65.5-25-90.5 0zm-71 71L58.6 323.5c-10.4 10.4-18 23.3-22.2 37.4L1 481.2C-1.5 489.7 .8 498.8 7 505s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2L421.7 220.3 291.7 90.3z",
},
children: [],
position: {
start: {
line: 1,
column: 214,
offset: 213,
},
end: {
line: 1,
column: 486,
offset: 485,
},
},
},
],
position: {
start: {
line: 1,
column: 1,
offset: 0,
},
end: {
line: 1,
column: 492,
offset: 491,
},
},
};

const WARNING_ICON_HAST: Element = {
type: "element",
tagName: "svg",
properties: {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 512 512",
},
children: [
{
type: "comment",
value:
"!Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.",
position: {
start: {
line: 1,
column: 63,
offset: 62,
},
end: {
line: 1,
column: 214,
offset: 213,
},
},
},
{
type: "element",
tagName: "path",
properties: {
d: "M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7 .2 40.1S486.3 480 472 480L40 480c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8 .2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24l0 112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z",
},
children: [],
position: {
start: {
line: 1,
column: 214,
offset: 213,
},
end: {
line: 1,
column: 537,
offset: 536,
},
},
},
],
position: {
start: {
line: 1,
column: 1,
offset: 0,
},
end: {
line: 1,
column: 543,
offset: 542,
},
},
};

const TIP_ICON_HAST: Element = {
type: "element",
tagName: "svg",
properties: {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 448 512",
},
children: [
{
type: "comment",
value:
"!Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.",
position: {
start: {
line: 1,
column: 63,
offset: 62,
},
end: {
line: 1,
column: 214,
offset: 213,
},
},
},
{
type: "element",
tagName: "path",
properties: {
d: "M96 0C43 0 0 43 0 96L0 416c0 53 43 96 96 96l288 0 32 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l0-64c17.7 0 32-14.3 32-32l0-320c0-17.7-14.3-32-32-32L384 0 96 0zm0 384l256 0 0 64L96 448c-17.7 0-32-14.3-32-32s14.3-32 32-32zm32-240c0-8.8 7.2-16 16-16l192 0c8.8 0 16 7.2 16 16s-7.2 16-16 16l-192 0c-8.8 0-16-7.2-16-16zm16 48l192 0c8.8 0 16 7.2 16 16s-7.2 16-16 16l-192 0c-8.8 0-16-7.2-16-16s7.2-16 16-16z",
},
children: [],
position: {
start: {
line: 1,
column: 214,
offset: 213,
},
end: {
line: 1,
column: 621,
offset: 620,
},
},
},
],
position: {
start: {
line: 1,
column: 1,
offset: 0,
},
end: {
line: 1,
column: 627,
offset: 626,
},
},
};

export { NOTE_ICON_HAST, WARNING_ICON_HAST, TIP_ICON_HAST };
59 changes: 59 additions & 0 deletions app/packages/rehype-attention-block/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type { Element, Root, Text } from "hast";
import type { Plugin } from "unified";
import { visit } from "unist-util-visit";
import { TIP_ICON_HAST, WARNING_ICON_HAST, NOTE_ICON_HAST } from "./icon-svg-hasts";

type BlockType = "note" | "warning" | "tip";

const getSVGFromType = (type: BlockType): Element => {
switch (type) {
case "note":
return NOTE_ICON_HAST;
case "warning":
return WARNING_ICON_HAST;
case "tip":
return TIP_ICON_HAST;
}
};

const rehypeAttentionBlock: Plugin<[], Root> = () => {
return (tree) => {
visit(tree, "element", (node) => {
if (
node.tagName === "div" &&
Array.isArray(node.properties.className) &&
node.properties.className.includes("remark-atb-base")
) {
const blockType = node.properties["data-block-type"];
if (!blockType || typeof blockType !== "string") {
return;
}

const svgHast = getSVGFromType(blockType as BlockType);
const labelTextHast: Text = {
type: "text",
value: blockType.toUpperCase(),
};
const spanHast: Element = {
type: "element",
tagName: "span",
properties: {
className: ["remark-atb-label"],
},
children: [labelTextHast],
};

node.children.unshift({
type: "element",
tagName: "div",
properties: {
className: [`remark-atb-icon ${blockType}`],
},
children: [svgHast, spanHast],
});
}
});
};
};

export { rehypeAttentionBlock };
29 changes: 29 additions & 0 deletions app/packages/remark-attention-block/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { Root } from "mdast";
import type { Plugin } from "unified";
import { visit } from "unist-util-visit";

const remarkAttentionBlock: Plugin<[], Root> = () => {
const regex = /\[!(?:WARNING|NOTE|TIP)\]/g;
return (tree) => {
visit(tree, "blockquote", (node) => {
if (node.children.length === 1 && node.children[0].type === "paragraph") {
const [paragraph] = node.children;
if (paragraph.children.length > 0 && paragraph.children[0].type === "text") {
const matches = paragraph.children[0].value.match(regex);
if (matches) {
const type = matches[0].toLowerCase().slice(2, -1);
node.data = {
hName: "div",
hProperties: {
className: ["remark-atb-base", `remark-atb-${type}`],
"data-block-type": type,
},
};
paragraph.children = paragraph.children.slice(2);
}
}
}
});
};
};
export { remarkAttentionBlock };
1 change: 1 addition & 0 deletions app/routes/_renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default jsxRenderer(({ children, title, description }) => {

{/* global css */}
<link rel="stylesheet" href="/static/markdown-styles.css" />
<link rel="stylesheet" href="/static/rehype-attention-block.css" />
<Style />

<Script src="/app/client.ts" async />
Expand Down
13 changes: 12 additions & 1 deletion app/routes/posts/md-test.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ publishedAt: 2024/09/14
console.log("Hello, TypeScript!");
```

- こちらは、Mermaid のサンプルです:ok_hand:
### (自作) rehype-mermaid のサンプル

```mermaid
classDiagram
Expand All @@ -58,3 +58,14 @@ Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
```

### (自作) remark-attention-block / rehype-attention-block のサンプル

> [!NOTE]
> ソードアート・オンライン, 通称SAOは、Reki Kawaharaによる日本のライトノベルシリーズ。
> [!WARNING]
> このライブラリは、まだ開発中です。予期せぬエラーが発生する可能性があります。
> [!TIP]
> 実は、このサイトの製作者は、タピオカを人生で一度も食べたことがありません。(本当:thumbsup:
57 changes: 57 additions & 0 deletions public/static/rehype-attention-block.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.remark-atb-base {
display: flex;
align-items: center;
gap: 24px;
padding: 12px 24px;
margin-top: 24px;
border-radius: 6px;
font-size: 16px;

> p {
margin: 0;
}
}

.remark-atb-note {
background-color: #d4edda;
border-color: #c3e6cb;
}

.note {
fill: #155724;
color: #155724;
}

.remark-atb-warning {
background-color: #fff3cd;
border-color: #ffeeba;
}

.warning {
fill: #856404;
color: #856404;
}

.remark-atb-tip {
background-color: #d1ecf1;
border-color: #bee5eb;
}

.tip {
fill: #0c5460;
color: #0c5460;
}

.remark-atb-icon {
max-width: 36px;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}

.remark-atb-label {
font-weight: bold;
font-size: 12px;
}
6 changes: 4 additions & 2 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import rehypeMomiji from './app/packages/rehype-momiji'
import remarkMomijiCodeFilename from './app/packages/remark-momiji-filename'
import rehypeMermaid from './app/packages/rehype-mermaid/rehypeMermaid'
import remarkEmojiName from './app/packages/remark-emoji-name'
import { remarkAttentionBlock } from './app/packages/remark-attention-block'
import { rehypeAttentionBlock } from './app/packages/rehype-attention-block'

export default defineConfig(() => {
return {
Expand All @@ -24,8 +26,8 @@ export default defineConfig(() => {
ssg({ entry: "./app/server.ts" }),
mdx({
jsxImportSource: 'hono/jsx',
remarkPlugins: [remarkGfm, remarkBreaks, remarkFrontmatter, remarkMdxFrontmatter, remarkMomijiCodeFilename, remarkEmojiName],
rehypePlugins: [[rehypeMomiji, { excludeLangs: ['mermaid'] }], rehypeMermaid],
remarkPlugins: [remarkGfm, remarkBreaks, remarkFrontmatter, remarkMdxFrontmatter, remarkMomijiCodeFilename, remarkEmojiName, remarkAttentionBlock],
rehypePlugins: [[rehypeMomiji, { excludeLangs: ['mermaid'] }], rehypeMermaid, rehypeAttentionBlock],
})
],
}
Expand Down

0 comments on commit a8f6fef

Please sign in to comment.