From c46de1eebfee78b034bf46ae2c8a495d77104314 Mon Sep 17 00:00:00 2001 From: Maciej Jur Date: Tue, 11 Apr 2023 02:36:13 +0200 Subject: [PATCH] Remark basic ruby plugin --- astro.config.ts | 4 +- package.json | 3 +- pnpm-lock.yaml | 3 + src/assets/ruby.ts | 35 +++++++++ src/content/posts/ruby-in-markdown.md | 104 ++++++++++++++++++++++++++ src/content/posts/ruby-shortcodes.md | 63 ---------------- 6 files changed, 147 insertions(+), 65 deletions(-) create mode 100644 src/assets/ruby.ts create mode 100644 src/content/posts/ruby-in-markdown.md delete mode 100644 src/content/posts/ruby-shortcodes.md 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($2)"; + +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] -%} + ({{- 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 -}} + ({{- $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($2)"; + +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] -%} - ({{- 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 -}} - ({{- $ruby -}}) - {{- else -}} - - {{- end -}} - {{- end -}} - -{{- end -}} -```