diff --git a/astro.config.ts b/astro.config.ts
index 4b98a95..8f04608 100644
--- a/astro.config.ts
+++ b/astro.config.ts
@@ -5,6 +5,7 @@ import remarkEmoji from 'remark-emoji';
import svelte from "@astrojs/svelte";
import mdx from '@astrojs/mdx';
import yaml from '@rollup/plugin-yaml';
+import ruby from './src/assets/ruby';
// https://astro.build/config
@@ -14,7 +15,8 @@ export default defineConfig({
markdown: {
remarkPlugins: [
[(remarkEmoji as any), {accessible: true}],
- remarkMath
+ remarkMath,
+ ruby,
],
rehypePlugins: [
[rehypeKatex, {output: 'mathml'}]
diff --git a/package.json b/package.json
index f1267f9..2d617f8 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,8 @@
"remark-math": "^5.1.1",
"reveal.js": "^4.4.0",
"sass": "^1.61.0",
- "svelte": "^3.58.0"
+ "svelte": "^3.58.0",
+ "unist-util-visit": "^4.1.2"
},
"devDependencies": {
"@rollup/plugin-yaml": "^4.0.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5222bfc..c7dc217 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -40,6 +40,9 @@ dependencies:
svelte:
specifier: ^3.58.0
version: 3.58.0
+ unist-util-visit:
+ specifier: ^4.1.2
+ version: 4.1.2
devDependencies:
'@rollup/plugin-yaml':
diff --git a/src/assets/ruby.ts b/src/assets/ruby.ts
new file mode 100644
index 0000000..cffce52
--- /dev/null
+++ b/src/assets/ruby.ts
@@ -0,0 +1,35 @@
+import { visit } from "unist-util-visit";
+import type { Node } from "unist-util-visit/lib";
+
+
+const regex = /\{.+?\}\(.+?\)/g;
+const group = /^\{(.+?)\}\((.+?)\)$/;
+const template = "$1";
+
+function toRuby(ruby: string) {
+ return ({
+ type: "html",
+ value: ruby.replace(group, template),
+ })
+}
+
+function transformRuby(node: { value: string }, index: number, parent: any) {
+ if (!regex.test(node.value)) return;
+
+ const text = node.value.split(regex).map(value => ({ type: "text", value}));
+ const ruby = node.value.match(regex)!.map(toRuby);
+
+ const merged = [];
+ for (let i = 0; i < text.length; i++) {
+ text[i] && merged.push(text[i]);
+ ruby[i] && merged.push(ruby[i]);
+ }
+
+ parent.children.splice(index, 1, ...merged);
+}
+
+export default function ruby() {
+ return (tree: Node, _: any) => {
+ visit(tree, "text", transformRuby);
+ }
+}
diff --git a/src/content/posts/ruby-in-markdown.md b/src/content/posts/ruby-in-markdown.md
new file mode 100644
index 0000000..7ce71ec
--- /dev/null
+++ b/src/content/posts/ruby-in-markdown.md
@@ -0,0 +1,104 @@
+---
+title: Ruby extensions for Markdown
+date: 2023-01-15T16:19:00+01:00
+tags: [Japanese, zola, hugo, astro]
+draft: true
+---
+In Markdown there is currently no notation for adding ruby to East Asian scripts, however it is possible to add support for it by using shortcodes in SSGs.
+
+## Examples
+### Japanese
+{日本語}(にほんご)の{文法}(ぶんぽう)は{難}(むずか)しい
+Remark: `{日本語}(にほんご)の{文法}(ぶんぽう)は{難}(むずか)しい`
+Tera: `{{/* ruby(expr="日本語,にほんご;の;文法,ぶんぽう;は;難,むずか;しい") */}}`
+
+### Chinese
+{北}(Běi){京}(jīng)
+{北}(ㄅㄟˇ){京}(ㄐㄧㄥ)
+`{{/* ruby(expr="北,Běi;京,jīng") */}}`
+`{{/* ruby(expr="北,ㄅㄟˇ;京,ㄐㄧㄥ") */}}`
+
+### Korean
+{韓}(한){國}(국)
+`{{/* ruby(expr="韓,한;國,국") */}}`
+
+### Vietnamese
+{河}(Hà){內}(Nội)
+`{河}(Hà){內}(Nội) `
+`{{/* ruby(expr="河,Hà;內,Nội") */}}`
+
+## Zola
+The following is a snippet for the Tera templating engine which is inspired by Jinja2.
+```jinja-html
+
+ {%- for item in expr | split(pat=";") -%}
+ {%- set sub_item = item | split(pat=",") -%}
+ {{- sub_item[0] -}}
+ {%- if sub_item[1] -%}
+
+ {%- else -%}
+
+ {%- endif -%}
+ {%- endfor -%}
+
+```
+
+## Hugo
+The following is a snippet for the Golang templating engine used by Hugo.
+```html
+{{- with .Get 0 -}}
+
+ {{- /* Generate the ruby markup */ -}}
+ {{- range split . ";" -}}
+ {{- $item := split . "," -}}
+ {{- $ruby := index $item 1 -}}
+ {{- index $item 0 -}}
+ {{- if $ruby -}}
+
+ {{- else -}}
+
+ {{- end -}}
+ {{- end -}}
+
+{{- end -}}
+```
+
+
+## Astro
+```ts
+import { visit } from "unist-util-visit";
+import type { Node } from "unist-util-visit/lib";
+
+
+const regex = /\{.+?\}\(.+?\)/g;
+const group = /^\{(.+?)\}\((.+?)\)$/;
+const template = "$1";
+
+function toRuby(ruby: string) {
+ return ({
+ type: "html",
+ value: ruby.replace(group, template),
+ })
+}
+
+function transformRuby(node: { value: string }, index: number, parent: any) {
+ if (!regex.test(node.value)) return;
+
+ const text = node.value.split(regex).map(value => ({ type: "text", value}));
+ const ruby = node.value.match(regex)!.map(toRuby);
+
+ const merged = [];
+ for (let i = 0; i < text.length; i++) {
+ text[i] && merged.push(text[i]);
+ ruby[i] && merged.push(ruby[i]);
+ }
+
+ parent.children.splice(index, 1, ...merged);
+}
+
+export default function ruby() {
+ return (tree: Node, _: any) => {
+ visit(tree, "text", transformRuby);
+ }
+}
+```
diff --git a/src/content/posts/ruby-shortcodes.md b/src/content/posts/ruby-shortcodes.md
deleted file mode 100644
index 3225cec..0000000
--- a/src/content/posts/ruby-shortcodes.md
+++ /dev/null
@@ -1,63 +0,0 @@
----
-title: Japanese Ruby shortcodes for Zola & Hugo
-date: 2023-01-15T16:19:00+01:00
-tags: [Japanese, zola, hugo]
-draft: true
----
-
-In Markdown there is currently no notation for adding ruby to East Asian scripts, however it is possible to add support for it by using shortcodes in SSGs.
-
-## Examples
-### Japanese
-{{ ruby(expr="日本語,にほんご;の;文法,ぶんぽう;は;難,むずか;しい") }}
-`{{/* ruby(expr="日本語,にほんご;の;文法,ぶんぽう;は;難,むずか;しい") */}}`
-
-### Chinese
-{{ ruby(expr="北,Běi;京,jīng") }}
-{{ ruby(expr="北,ㄅㄟˇ;京,ㄐㄧㄥ") }}
-`{{/* ruby(expr="北,Běi;京,jīng") */}}`
-`{{/* ruby(expr="北,ㄅㄟˇ;京,ㄐㄧㄥ") */}}`
-
-### Korean
-{{ ruby(expr="韓,한;國,국") }}
-`{{/* ruby(expr="韓,한;國,국") */}}`
-
-### Vietnamese
-{{ ruby(expr="河,Hà;內,Nội") }}
-`{{/* ruby(expr="河,Hà;內,Nội") */}}`
-
-## Zola
-The following is a snippet for the Tera templating engine which is inspired by Jinja2.
-```jinja-html
-
- {%- for item in expr | split(pat=";") -%}
- {%- set sub_item = item | split(pat=",") -%}
- {{- sub_item[0] -}}
- {%- if sub_item[1] -%}
-
- {%- else -%}
-
- {%- endif -%}
- {%- endfor -%}
-
-```
-
-## Hugo
-The following is a snippet for the Golang templating engine used by Hugo.
-```html
-{{- with .Get 0 -}}
-
- {{- /* Generate the ruby markup */ -}}
- {{- range split . ";" -}}
- {{- $item := split . "," -}}
- {{- $ruby := index $item 1 -}}
- {{- index $item 0 -}}
- {{- if $ruby -}}
-
- {{- else -}}
-
- {{- end -}}
- {{- end -}}
-
-{{- end -}}
-```