├── .github └── workflows │ └── test.yml ├── .gitignore ├── README.md ├── build.sh ├── kanbun-en.pdf ├── kanbun-en.tex ├── kanbun-example.pdf ├── kanbun-example.tex ├── kanbun-ja.pdf ├── kanbun-ja.tex ├── kanbun-proto.sty ├── kanbun-proto.tex ├── kanbun.lua ├── replace.sh └── test.tex /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Build LaTeX document for testing kanbun 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | build_latex: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Set up Git repository 14 | uses: actions/checkout@v4 15 | - name: Compile LaTeX document 16 | uses: xu-cheng/latex-action@v2 17 | with: 18 | root_file: test.tex 19 | latexmk_use_lualatex: true 20 | - name: Upload PDF file 21 | uses: actions/upload-artifact@v4 22 | with: 23 | name: PDF 24 | path: test.pdf 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.aux 2 | *.log 3 | *.out 4 | *.synctex.gz 5 | *.toc 6 | *.ltjruby 7 | *.zip 8 | *.pdf 9 | 10 | # generated by build.sh 11 | kanbun.sty 12 | kanbun.tex 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The `kanbun` package 2 | 3 | The `kanbun` package, like other _kanbun-kundoku_ (漢文訓読) LaTeX packages (such as `gckanbun`), allows users to manually input macros for elements in a _kanbun-kundoku_ paragraph. 4 | 5 | More importantly, it accepts input with light markup in the “_kanbun_ annotation” form when used with LuaLaTeX, which allows typesetting _kanbun-kundoku_ paragraphs efficiently. 6 | 7 | ## Build 8 | 9 | Use `replace.sh` to generate `kanbun.sty` and `kanbun.tex` from `kanbun-proto.sty` and `kanbun-proto.tex`, respectively. 10 | 11 | ```bash 12 | ./replace.sh 13 | ``` 14 | 15 | Use `build.sh` to generate the documentations and packs the LaTeX package as a `zip` file. 16 | Some open source fonts are used in the documentation, so you need to install them to compile the documentations. 17 | 18 | ```bash 19 | ./build.sh 20 | ``` 21 | 22 | ## Licence 23 | 24 | Copyright 2022 Yuanhao Chen 25 | 26 | This work may be distributed and/or modified under the 27 | conditions of the LaTeX Project Public License, either version 1.3 28 | of this license or (at your option) any later version. 29 | The latest version of this license is in 30 | 31 | and version 1.3 or later is part of all distributions of LaTeX 32 | version 2005/12/01 or later. 33 | 34 | This work has the LPPL maintenance status `maintained'. 35 | 36 | The Current Maintainer of this work is Yuanhao Chen. 37 | 38 | This work consists of the files `kanbun.sty` 39 | (from `kanbun-proto.sty`),`kanbun.lua`, `kanbun-example.tex` 40 | and `kanbun.tex` (from `kanbun-proto.tex`). 41 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # write date and version number 4 | ./replace.sh 5 | 6 | # compile documents 7 | lualatex kanbun-example.tex 8 | lualatex kanbun-en.tex 9 | lualatex kanbun-ja.tex 10 | 11 | # build zip 12 | mkdir kanbun 13 | 14 | cp kanbun.sty kanbun/kanbun.sty 15 | cp kanbun.lua kanbun/kanbun.lua 16 | 17 | cp README.md kanbun/README.md 18 | 19 | cp kanbun.tex kanbun/kanbun.tex 20 | cp kanbun-example.tex kanbun/kanbun-example.tex 21 | cp kanbun-example.pdf kanbun/kanbun-example.pdf 22 | cp kanbun-ja.tex kanbun/kanbun-ja.tex 23 | cp kanbun-ja.pdf kanbun/kanbun-ja.pdf 24 | cp kanbun-en.tex kanbun/kanbun-en.tex 25 | cp kanbun-en.pdf kanbun/kanbun-en.pdf 26 | 27 | zip -r -9 -X kanbun.zip kanbun 28 | 29 | rm -r kanbun 30 | -------------------------------------------------------------------------------- /kanbun-en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuanhao-chen-nyoeghau/kanbun/83c9f69360a11ca60029c01c7b29d34d4a9b9354/kanbun-en.pdf -------------------------------------------------------------------------------- /kanbun-en.tex: -------------------------------------------------------------------------------- 1 | \newcommand\en[1]{#1} 2 | \newcommand\ja[1]{} 3 | \input{kanbun.tex} -------------------------------------------------------------------------------- /kanbun-example.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuanhao-chen-nyoeghau/kanbun/83c9f69360a11ca60029c01c7b29d34d4a9b9354/kanbun-example.pdf -------------------------------------------------------------------------------- /kanbun-example.tex: -------------------------------------------------------------------------------- 1 | %% Copyright 2022 Yuanhao Chen 2 | % 3 | % This work may be distributed and/or modified under the 4 | % conditions of the LaTeX Project Public License, either version 1.3 5 | % of this license or (at your option) any later version. 6 | % The latest version of this license is in 7 | % http://www.latex-project.org/lppl.txt 8 | % and version 1.3 or later is part of all distributions of LaTeX 9 | % version 2005/12/01 or later. 10 | % 11 | % This work has the LPPL maintenance status `maintained'. 12 | % 13 | % The Current Maintainer of this work is Yuanhao Chen. 14 | % 15 | % This work consists of the files kanbun.sty, kanbun.lua, 16 | % kanbun-example.tex and kanbun.tex. 17 | % 18 | % example text from https://phesoca.com/kanbun-html/ 19 | \documentclass{ltjtarticle} 20 | 21 | \usepackage[match]{luatexja-fontspec} 22 | \usepackage[haranoaji]{luatexja-preset} 23 | 24 | \newlength\myzw 25 | \setlength\myzw{2.25\zw} 26 | \usepackage[kumi=beta, unit=\myzw, yokoaki=3.5]{kanbun} 27 | 28 | \usepackage[margin=0pt]{geometry} 29 | 30 | \usepackage{xcolor} 31 | 32 | \Kanbun 33 | 初メテ,帝ノ母劉貴人ハ賜(たま)ハリ[レ]死ヲ,太祖ハ告ゲ[レ]帝ニ曰ハク「昔漢武帝ハ將‹し›«テ»ニ[レ]立タセント[二]其ノ子ヲ[一]而殺シ[二]其ノ母ヲ[一],不[下]令(し)メ[三]婦人ヲ後ロニ與(あづか)ラ[二]國政ニ[一],使(し)メ[中]外家ヲ為(な)サ[上レ]亂ヲ。汝當ニ‹べ›«ク»[二]繼統ス[一],故ニ吾レ遠クシテ同ズルコト[二]漢武ト[一],為(た)リ[二]長久之計[一]。」帝素ヨリ純孝ナリ,哀シク泣キ不[レ]能ハ[二]自ラ勝ツコト[一],太祖怒ル[レ]之レヲ。帝ハ還リ[レ]宮ニ,哀シク不[二]自ラ止マ[一],日夜ニシテ號泣ス。太祖知リテ而又タ召ス[レ]之レヲ。帝欲シ[レ]入ラント,左右曰ハク「孝子事ヘバ[レ]父ニ,小杖則チ受ケ,大杖避ク[レ]之レヲ。今陛下ノ怒ルコト盛ンナリ,入レバ或イハ不測ナリ,陷ラス[二]帝ヲ於不義ニ[一]。不[レ]如カ[二]且(しばら)ク出ヅルニ[一],待チテ[二]怒リノ解クルヲ[一]而進ムコト,不ル[レ]晚カラ也。」帝ハ懼レ,從ヒ[レ]之レニ,乃チ游行シ逃グ[二]於外ニ[一]。 34 | \EndKanbun 35 | 36 | \begin{document} 37 | \color[HTML]{e0e0e0} 38 | \pagestyle{empty} 39 | \vspace*{\fill} 40 | \begin{minipage}{0.5\pageheight} 41 | \printkanbun 42 | \end{minipage} 43 | \vspace*{\fill} 44 | \end{document} -------------------------------------------------------------------------------- /kanbun-ja.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuanhao-chen-nyoeghau/kanbun/83c9f69360a11ca60029c01c7b29d34d4a9b9354/kanbun-ja.pdf -------------------------------------------------------------------------------- /kanbun-ja.tex: -------------------------------------------------------------------------------- 1 | \newcommand\en[1]{} 2 | \newcommand\ja[1]{#1} 3 | \input{kanbun.tex} -------------------------------------------------------------------------------- /kanbun-proto.sty: -------------------------------------------------------------------------------- 1 | %% Copyright 2022--\YEAR Yuanhao Chen 2 | % 3 | % This work may be distributed and/or modified under the 4 | % conditions of the LaTeX Project Public License, either version 1.3 5 | % of this license or (at your option) any later version. 6 | % The latest version of this license is in 7 | % http://www.latex-project.org/lppl.txt 8 | % and version 1.3 or later is part of all distributions of LaTeX 9 | % version 2005/12/01 or later. 10 | % 11 | % This work has the LPPL maintenance status `maintained'. 12 | % 13 | % The Current Maintainer of this work is Yuanhao Chen. 14 | % 15 | % This work consists of the files kanbun.sty, kanbun.lua, 16 | % kanbun-example.tex and kanbun.tex. 17 | % 18 | \NeedsTeXFormat{LaTeX2e}[2021/06/01] 19 | \RequirePackage{expl3,xparse,l3keys2e,ifluatex} 20 | \ProvidesExplClass{kanbun} 21 | {\YEAR/\MONTH/\DAY} {\VERSION} {漢文の訓点文の組版} 22 | 23 | \ExplSyntaxOn 24 | \cs_generate_variant:Nn \str_if_eq:nnTF { V } 25 | \cs_generate_variant:Nn \str_case:nnTF { V } 26 | \cs_generate_variant:Nn \str_case:nnTF { f } 27 | 28 | % vars used in options 29 | \@ifpackageloaded{luatexja-fontspec}{ 30 | \tl_set:Nn \kanbun_rubyfontcmd_default { \addjfontfeatures{RawFeature={+ruby}} } 31 | \tl_set:Nn \kanbun_fontcmd_default { \addjfontfeatures{RawFeature={+trad}} } 32 | }{ 33 | \tl_set:Nn \kanbun_rubyfontcmd_default {} 34 | \tl_set:Nn \kanbun_fontcmd_default {} 35 | } 36 | 37 | % options 38 | \keys_define:nn { kanbun } 39 | { 40 | , scale .fp_set:N = \kanbun_scale 41 | , scale .initial:n = { 2 } 42 | , fontcmd .tl_set:N = \kanbun_fontcmd 43 | , fontcmd .initial:n = \kanbun_fontcmd_default 44 | , rubyfontcmd .tl_set:N = \kanbun_rubyfontcmd 45 | , rubyfontcmd .initial:n = \kanbun_rubyfontcmd_default 46 | , unit .dim_set:N = \kanbun_zw 47 | , unit .initial:n = { 1em } 48 | , yokoaki .fp_set:N = \kanbun_yokoaki 49 | , yokoaki .initial:n = { 2 } 50 | , tateaki .fp_set:N = \kanbun_tateaki 51 | , tateaki .initial:n = { 2 } 52 | , okuriintrusion .fp_set:N = \kanbun_okuriintrusion 53 | , okuriintrusion .initial:n = { 1 } 54 | , kumi .str_set:N = \kanbun_kumi 55 | , kumi .initial:n = { aki } 56 | , aki .code:n = \keys_set:nn { kanbun } { kumi = aki } 57 | , beta .code:n = \keys_set:nn { kanbun } { kumi = beta } 58 | } 59 | \ProcessKeysOptions { kanbun } 60 | \DeclareDocumentCommand \setkanbun { m } { 61 | \keys_set:nn { kanbun } { #1 } 62 | } 63 | 64 | % other vars 65 | \tl_set:Nn \kanbun_rubyfontsize_rubyfontcmd { \kanbun_rubyfontcmd\fontsize{\fp_eval:n {1/\kanbun_scale}\kanbun_zw}{0pt}\selectfont } 66 | \newlength{\kanbun_furilen} 67 | \newlength{\kanbun_okurilen} 68 | \newlength{\kanbun_furiokuri_firstline_len} 69 | \int_new:N \kanbun_furiokuri_firstline_start_index 70 | \tl_set:Nn \kanbun_tateten_width { 1/30 } 71 | \tl_set:Nn \kanbunzwtosp { \fp_eval:n { \dim_ratio:nn { 1 \kanbun_zw } { 1 sp } } } 72 | \tl_set:Nn \kanbun_unit_glue { 73 | \str_if_eq:VnTF \kanbun_kumi { aki } { 74 | \penalty0 75 | } 76 | { 77 | \hskip 0\kanbun_zw plus 0.25\kanbun_zw minus 0\kanbun_zw 78 | } 79 | } 80 | \tl_set:Nn \kanbun_punct_glue { 81 | \hskip 0\kanbun_zw plus 0.5\kanbun_zw minus 0\kanbun_zw 82 | } 83 | 84 | % \kanjiunit and other macros to be used in a \kanjiunit 85 | \NewDocumentCommand { \kanbun_ensure_height } { m m } 86 | { 87 | \vbox to #1{\vss{#2}\vss} 88 | } 89 | \newbox\kanbun_current_kanjiunit 90 | \NewDocumentCommand { \kanjiunit } { m m m m m m } 91 | { 92 | \tl_set:Nn \ninojiten_punct {} 93 | \tl_set:Nn \right_punct {} 94 | \tl_set:Nn \central_punct {} 95 | \process_punct{ #4 } 96 | \tl_set:Nn \kanbun_central_punct_box { 97 | \kanbun_ensure_height{\kanbun_zw} { 98 | \str_if_eq:VnTF \kanbun_kumi { aki } 99 | { 100 | \hbox{\kern \kanbun_zw{\hbox to \fp_eval:n { \kanbun_tateaki/\kanbun_scale }\kanbun_zw{\hss{\central_punct}\hss}}} 101 | } 102 | { 103 | \hbox{\kern \kanbun_zw{\central_punct}} 104 | } 105 | } 106 | } 107 | \tl_set:Nn \kanbun_left_punct_phantom { 108 | \kanbun_ensure_height{\kanbun_zw} { 109 | \str_if_eq:VnTF \kanbun_kumi { aki } { } 110 | { 111 | \str_if_eq:nnTF { #2 } { } { } { 112 | \hbox{\phantom{\hbox to 0.5\kanbun_zw{\hss#2\hfil}}} 113 | } 114 | } 115 | } 116 | } 117 | \tl_set:Nn \kanbun_right_punct_box { 118 | \kanbun_ensure_height{\kanbun_zw} { 119 | \vfill % make sure punct stay on baseline in yoko direction (xeCJK) 120 | \str_if_eq:VnTF \right_punct { } { } { 121 | \hbox{ 122 | \kern \kanbun_zw 123 | \bool_if:NTF \kanbun_first_right_punct_is_kagi { 124 | \phantom{ \kanbun_rubyfontsize_rubyfontcmd\kaeriten{#5} } 125 | } { } 126 | \right_punct 127 | } 128 | } 129 | } 130 | } 131 | % 132 | \tl_set:Nn \unit_content { 133 | \kanbun_left_punct_phantom % compensate for width of left punct 134 | \vbox{ 135 | \bool_set_true:N \kanbun_is_right_kana 136 | \kanbun_ensure_height{ 0pt }{\hbox{\kanbun_rubyfontsize_rubyfontcmd{#1}}} % right kana 137 | \nointerlineskip % 138 | \vspace*{\fp_eval:n { 0.5/\kanbun_scale }\kanbun_zw} 139 | \kanbun_ensure_height{\kanbun_zw}{\llap{#2}} % left punct 140 | \nointerlineskip % 141 | \vspace*{-1 \kanbun_zw} 142 | \kanbun_ensure_height{\kanbun_zw}{ 143 | \hbox to \kanbun_zw{\hss{#3}\hss} 144 | } % kanji 145 | \nointerlineskip % 146 | \vspace*{-1 \kanbun_zw} 147 | \kanbun_ensure_height{\fp_eval:n { 1/\kanbun_scale }\kanbun_zw}{\hbox{\kern \kanbun_zw{\ninojiten_punct}}} % ninojiten 148 | \nointerlineskip % 149 | \vspace*{\fp_eval:n { -1/\kanbun_scale }\kanbun_zw} 150 | \kanbun_right_punct_box % right punct 151 | \nointerlineskip % 152 | \vspace*{-\kanbun_zw} 153 | \kanbun_central_punct_box % central punct 154 | \nointerlineskip % 155 | \vspace*{ \fp_eval:n { -1/\kanbun_scale }\kanbun_zw } 156 | \kanbun_ensure_height{\fp_eval:n { 1/\kanbun_scale }\kanbun_zw}{\hbox{\kanbun_rubyfontsize_rubyfontcmd\kern \kanbun_zw{\kaeriten{#5}}}} % kaeriten 157 | \nointerlineskip % 158 | \vspace*{\fp_eval:n { 0.5/\kanbun_scale }\kanbun_zw} 159 | \bool_set_false:N \kanbun_is_right_kana 160 | \kanbun_ensure_height{ 0pt }{\hbox{\kanbun_rubyfontsize_rubyfontcmd{#6}}} % left kana 161 | } 162 | } 163 | \str_if_eq:VnTF \kanbun_kumi { aki } { 164 | \setbox\kanbun_current_kanjiunit \hbox to \kanbun_zw{ \unit_content \hss} 165 | }{ 166 | \setbox\kanbun_current_kanjiunit \hbox{ \unit_content } 167 | } 168 | % 169 | % output 170 | \str_if_eq:VnTF \kanbun_kumi { aki } { } 171 | { 172 | \str_if_eq:nnTF { #2 } { } { } { 173 | \kanbun_punct_glue 174 | } 175 | } 176 | \nobreak 177 | \str_if_eq:VnTF \kanbun_kumi { aki } 178 | { 179 | \usebox\kanbun_current_kanjiunit 180 | \hskip\fp_eval:n { \kanbun_tateaki/\kanbun_scale }\kanbun_zw 181 | } 182 | { 183 | \discretionary{ 184 | \usebox\kanbun_current_kanjiunit 185 | \kern\dim_eval:n { \kanbun_zw - \box_wd:N \kanbun_current_kanjiunit } 186 | }{ 187 | % 188 | }{ 189 | \usebox\kanbun_current_kanjiunit 190 | } 191 | } 192 | \nobreak 193 | \str_if_eq:VnTF \kanbun_kumi { aki } { } 194 | { 195 | \str_if_eq:VnTF \right_punct { } { } { 196 | \kanbun_punct_glue 197 | } 198 | } 199 | \nobreak 200 | \kanbun_unit_glue 201 | } 202 | \cs_new:Nn \kanbun_dim_to_fp_and_round:n { 203 | \fp_eval:n { round( \dim_to_fp:n { #1 }, 0 ) } 204 | } 205 | \cs_new:Nn \kanbun_typeset_normal_kana:nn { 206 | \dim_compare:nNnTF { \kanbun_furilen } < { \fp_eval:n { 1-\kanbun_okuriintrusion/\kanbun_scale }\kanbun_zw } 207 | { \makebox[\fp_eval:n { 1-\kanbun_okuriintrusion/\kanbun_scale }\kanbun_zw][l]{ #1 } } 208 | { #1 } 209 | #2 210 | } 211 | \cs_new:Nn \kanbun_typeset_long_kana_by_raising_okurigana:nn { 212 | \makebox[ \dim_eval:n { \fp_eval:n { 1 + \kanbun_tateaki / \kanbun_scale }\kanbun_zw - \kanbun_okurilen } ][l]{ #1 } 213 | #2 214 | } 215 | \cs_new:Nn \kanbun_typeset_long_kana:n { 216 | \str_set:Nn \kanbun_furiokuri_all { #1 } 217 | \int_set:Nn \kanbun_furiokuri_firstline_start_index { -1 } 218 | \settowidth{ \kanbun_furiokuri_firstline_len }{ } 219 | % 220 | \fp_while_do:nn { 221 | \kanbun_dim_to_fp_and_round:n { \kanbun_furiokuri_firstline_len } < \kanbun_dim_to_fp_and_round:n { \fp_eval:n { (\kanbun_okuriintrusion + \kanbun_tateaki) / \kanbun_scale }\kanbun_zw } 222 | % \kanbun_dim_to_fp_and_round:n { \kanbun_furiokuri_firstline_len } < \kanbun_dim_to_fp_and_round:n { ( \kanbun_furilen + \kanbun_okurilen ) / 2 } 223 | } { 224 | \int_decr:N \kanbun_furiokuri_firstline_start_index 225 | \settowidth{ \kanbun_furiokuri_firstline_len }{ \str_range:Nnn \kanbun_furiokuri_all { \kanbun_furiokuri_firstline_start_index } { -1 } } 226 | } 227 | % output 228 | \rlap{\raisebox{ \bool_if:NTF \kanbun_is_right_kana { } { - } \fp_eval:n { 1 / \kanbun_scale }\kanbun_zw }[0pt][0pt]{ 229 | \kern \fp_eval:n { .5/\kanbun_scale }\kanbun_zw 230 | \kern \fp_to_dim:n { min( 0, \kanbun_dim_to_fp_and_round:n { \fp_eval:n { 2 * (\kanbun_okuriintrusion + \kanbun_tateaki) / \kanbun_scale }\kanbun_zw - \kanbun_furilen - \kanbun_okurilen } ) } 231 | \str_range:Nnn \kanbun_furiokuri_all { 1 } { \kanbun_furiokuri_firstline_start_index - 1 } 232 | }} 233 | \kern \fp_eval:n { 1-\kanbun_okuriintrusion/\kanbun_scale }\kanbun_zw \str_range:Nnn \kanbun_furiokuri_all { \kanbun_furiokuri_firstline_start_index } { -1 } 234 | } 235 | \NewDocumentCommand { \furiokuri } { m m } 236 | { 237 | \settowidth{ \kanbun_furilen }{ #1 } 238 | \settowidth{ \kanbun_okurilen }{ #2 } 239 | 240 | \str_if_eq:VnTF \kanbun_kumi { aki } 241 | { 242 | \fp_compare:nTF { \kanbun_dim_to_fp_and_round:n { \kanbun_furilen + \kanbun_okurilen } > \kanbun_dim_to_fp_and_round:n {\fp_eval:n { 1 + \kanbun_tateaki / \kanbun_scale }\kanbun_zw} } { 243 | \kanbun_typeset_long_kana:n { #1 #2 } 244 | } { 245 | \fp_compare:nTF { \kanbun_dim_to_fp_and_round:n { \kanbun_okurilen } >= \kanbun_dim_to_fp_and_round:n { \fp_eval:n { (\kanbun_okuriintrusion + \kanbun_tateaki) / \kanbun_scale }\kanbun_zw } } { 246 | \fp_compare:nTF { \kanbun_dim_to_fp_and_round:n { \kanbun_okurilen } <= \kanbun_dim_to_fp_and_round:n { \fp_eval:n { 1 + (\kanbun_tateaki - 1) / \kanbun_scale }\kanbun_zw } } { 247 | \kanbun_typeset_long_kana_by_raising_okurigana:nn { #1 } { #2 } 248 | } { 249 | \kanbun_typeset_long_kana:n { #1 #2 } 250 | } 251 | } { 252 | \kanbun_typeset_normal_kana:nn { #1 } { #2 } 253 | } 254 | } 255 | } 256 | { 257 | \kanbun_typeset_normal_kana:nn { #1 } { #2 } 258 | } 259 | } 260 | \NewDocumentCommand { \kaeriten } { m } 261 | { 262 | \tl_set:Nn \kaeriten_output { #1 } 263 | \sys_if_engine_xetex:TF {} { 264 | \platex_if_direction_tate:TF { 265 | \str_case:VnTF \kaeriten_output { 266 | % When using U+30EC: KATAKANA LETTER RE 267 | { 一レ } { \tl_set:Nn \kaeriten_output { \kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw 一\kern \fp_eval:n {-0.75/\kanbun_scale}\kanbun_zw レ } } 268 | { 甲レ } { \tl_set:Nn \kaeriten_output { 甲\kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw レ } } 269 | { 上レ } { \tl_set:Nn \kaeriten_output { 上\kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw レ } } 270 | { 天レ } { \tl_set:Nn \kaeriten_output { 天\kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw レ } } 271 | % When using U+3191: IDEOGRAPHIC ANNOTATION REVERSE MARK 272 | { 一㆑ } { \tl_set:Nn \kaeriten_output { \kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw 一\kern \fp_eval:n {-0.75/\kanbun_scale}\kanbun_zw ㆑ } } 273 | { 甲㆑ } { \tl_set:Nn \kaeriten_output { 甲\kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw ㆑ } } 274 | { 上㆑ } { \tl_set:Nn \kaeriten_output { 上\kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw ㆑ } } 275 | { 天㆑ } { \tl_set:Nn \kaeriten_output { 天\kern \fp_eval:n {-0.25/\kanbun_scale}\kanbun_zw ㆑ } } 276 | } {} {} 277 | } {} 278 | } 279 | \tl_use:N \kaeriten_output 280 | } 281 | \NewDocumentCommand { \process_punct_map } { m } { 282 | \str_case:nnTF { #1 } { 283 | { — } { \tl_put_right:Nn \central_punct { \tateten } } 284 | { ― } { \tl_put_right:Nn \central_punct { \tateten } } 285 | { ㆐ } { \tl_put_right:Nn \central_punct { \tateten } } 286 | % { : } { \tl_put_right:Nn \central_punct { \hbox to \kanbun_zw{\hss{:}\hss} } } 287 | % { ・ } { \tl_put_right:Nn \central_punct { \hbox to \kanbun_zw{\hss{・}\hss} } } 288 | { : } { \tl_put_right:Nn \right_punct { \hbox to 0.5\kanbun_zw{\hss{:}\hss} } } 289 | { ・ } { \tl_put_right:Nn \right_punct { \hbox to 0.5\kanbun_zw{\hss{・}\hss} } } 290 | { … } { \tl_put_right:Nn \central_punct { \hbox to \kanbun_zw{\hss{…}\hss} } } 291 | { ! } { \tl_put_right:Nn \central_punct { \hbox to \kanbun_zw{\hss{!}\hss} } } 292 | { ? } { \tl_put_right:Nn \central_punct { \hbox to \kanbun_zw{\hss{?}\hss} } } 293 | { 〻 } { 294 | \tl_put_right:Nn \ninojiten_punct { \ninojiten } 295 | \tl_put_right:Nn \right_punct { \phantom{\ninojiten} } 296 | } 297 | } {} { 298 | \tl_put_right:Nn \right_punct { \hbox to 0.5\kanbun_zw{\hfil#1\hss} } 299 | } 300 | } 301 | % \bool_new:N 302 | \NewDocumentCommand { \process_punct } { m } 303 | { 304 | \bool_set_false:N \kanbun_first_right_punct_is_kagi 305 | \str_case:fnTF { \str_range:nnn { #1 } { 1 } { 1 } } { 306 | { 」 } { \bool_set_true:N \kanbun_first_right_punct_is_kagi } 307 | { 』 } { \bool_set_true:N \kanbun_first_right_punct_is_kagi } 308 | } { } { } 309 | \str_map_function:nN { #1 } \process_punct_map 310 | } 311 | \NewDocumentCommand { \multifuriokuri } { O{2\kanbun_zw} m m } 312 | { 313 | \kanbun_rubyfontcmd 314 | \kern \fp_eval:n { -(#1) }\kanbun_zw 315 | \makebox[\fp_eval:n { (#1) + 1 - \kanbun_okuriintrusion/\kanbun_scale }\kanbun_zw][s]{#2} 316 | #3 317 | } 318 | 319 | % these commands are used as punct 320 | \NewDocumentCommand { \tateten } {} 321 | { 322 | \str_if_eq:VnTF \kanbun_kumi { aki } { 323 | \makebox[\fp_eval:n {\kanbun_tateaki/\kanbun_scale}\kanbun_zw][c]{ 324 | \rule[\fp_eval:n {-\kanbun_tateten_width/2}\kanbun_zw]{\fp_eval:n {\kanbun_tateaki/\kanbun_scale}\kanbun_zw}{\fp_eval:n {\kanbun_tateten_width}\kanbun_zw} 325 | } 326 | }{ 327 | \makebox[\fp_eval:n {1/\kanbun_scale}\kanbun_zw][c]{ 328 | \rule[\fp_eval:n {-\kanbun_tateten_width/2}\kanbun_zw]{\fp_eval:n {1/\kanbun_scale}\kanbun_zw}{\fp_eval:n {\kanbun_tateten_width}\kanbun_zw} 329 | } 330 | } 331 | } 332 | \NewDocumentCommand { \ninojiten } {} 333 | { \kanbun_rubyfontsize_rubyfontcmd 〻 } 334 | 335 | % corrects fontsize of ruby base 336 | % \NewDocumentCommand { \kanbunfont } {} { \parindent=0pt\kanbun_fontcmd\fontsize{\kanbun_zw}{\fp_eval:n {1+\kanbun_yokoaki/\kanbun_scale}\kanbun_zw}\selectfont} 337 | \NewDocumentCommand { \kanbunfont } {} { \kanbun_fontcmd\fontsize{\kanbun_zw}{\fp_eval:n {1+\kanbun_yokoaki/\kanbun_scale}\kanbun_zw}\selectfont} 338 | \NewDocumentEnvironment { kanjipar } { +b } 339 | { 340 | { 341 | \kanbunfont 342 | #1 343 | \par 344 | } 345 | } {} 346 | 347 | % for LuaLaTeX to parse Kanbun annotation 348 | \NewDocumentCommand{\matchkana}{ m }{ 349 | \regex_set:Nn \c_kana_regex {[\x{3040}-\x{30FA}\x{30FC}-\x{30FF}\x{31F0}-\x{31FF}\x{FF66}-\x{FF9F}\x{1B100}-\x{1B122}\x{1AFF0}-\x{1AFFF}\x{1B000}-\x{1B0FF}\x{1B130}-\x{1B16F}]} 350 | \regex_match:NnTF \c_kana_regex { #1 } { \bool_set_true:N \g_kana_bool } { \bool_set_false:N \g_kana_bool } 351 | } 352 | % 353 | \ExplSyntaxOff 354 | % 355 | \ifluatex 356 | % verbatim reader adapted from https://tex.stackexchange.com/a/361759 357 | \directlua{ 358 | verb_table = {} 359 | function store_lines (str) 360 | if string.find (str , "\noexpand\\EndKanbun" ) then 361 | luatexbase.remove_from_callback ( 362 | "process_input_buffer" , "store_lines") 363 | return "\\newif\\ifcontinue\\continuetrue\\directlua { co = coroutine.create(main_loop) }\\loop\\directlua{ ok,b=coroutine.resume(co) tex.sprint(b) }\\ifcontinue\\repeat" 364 | else 365 | table.insert(verb_table, str) 366 | end 367 | return "" 368 | end 369 | function register_verbatim () 370 | verb_table = {} 371 | luatexbase.add_to_callback( 372 | "process_input_buffer" , store_lines , "store_lines") 373 | end 374 | % require main loop 375 | require("kanbun.lua") 376 | } 377 | \def\Kanbun{\directlua{ 378 | kanbunzwtosp = \luaescapestring{\kanbunzwtosp} 379 | register_verbatim() 380 | }} 381 | \def\createcatcodes{% 382 | \bgroup% 383 | \catcode`\\=12 \catcode`\{=12 \catcode`\}=12% 384 | \catcode`\$=12 \catcode`\&=12 \catcode`\^^M=13% 385 | \catcode`\#=12 \catcode`\^=12 \catcode`\_=12% 386 | \catcode`\ =13 \catcode`\~=12 \catcode`\%=12% 387 | \savecatcodetable 1% 388 | \egroup% 389 | } 390 | \createcatcodes 391 | \bgroup% 392 | \catcode`\^^M=13\gdef^^M{\quitvmode\par}% 393 | \catcode`\ = 13\gdef {\quitvmode\Space}% 394 | \egroup% 395 | \def\Space{ } 396 | % 397 | \fi 398 | -------------------------------------------------------------------------------- /kanbun-proto.tex: -------------------------------------------------------------------------------- 1 | %% Copyright 2022--\YEAR Yuanhao Chen 2 | % 3 | % This work may be distributed and/or modified under the 4 | % conditions of the LaTeX Project Public License, either version 1.3 5 | % of this license or (at your option) any later version. 6 | % The latest version of this license is in 7 | % http://www.latex-project.org/lppl.txt 8 | % and version 1.3 or later is part of all distributions of LaTeX 9 | % version 2005/12/01 or later. 10 | % 11 | % This work has the LPPL maintenance status `maintained'. 12 | % 13 | % The Current Maintainer of this work is Yuanhao Chen. 14 | % 15 | % This work consists of the files kanbun.sty, kanbun.lua, 16 | % kanbun-example.tex and kanbun.tex. 17 | % 18 | \documentclass[12pt]{ltxdockit} 19 | 20 | \AfterTOCHead[toc]{\sffamily} 21 | \makeatletter 22 | \def\@seccntformat#1{\protect\makebox[0pt][r]{\csname the#1\endcsname\hspace{\marglistsep}}} 23 | \makeatother 24 | 25 | \usepackage{fancyvrb} 26 | \DefineShortVerb{\|} 27 | 28 | \lstnewenvironment{example}[1][] 29 | {\lstset{ 30 | basicstyle=\ja{\linespread{1}}\ttfamily, 31 | frame=single, 32 | columns=fullflexible, 33 | language=[LaTeX]TeX, 34 | moretexcs={ 35 | Kanbun, 36 | EndKanbun, 37 | printkanbun, 38 | printkanbuncode, 39 | kanbunfont, 40 | furiokuri, 41 | multifuriokuri, 42 | ExplSyntaxOn, 43 | ExplSyntaxOff, 44 | kanjiunit, 45 | setkanbun, 46 | } 47 | }} 48 | {} 49 | 50 | \usepackage{luatexja} 51 | \ltjdefcharrange{10}{"2E3A} 52 | \ltjdefcharrange{11}{"2039-"203A} 53 | \ltjsetparameter{jacharrange={-1, +2, +3, -4, -5, +6, +7, -8, +9, +10, -11}} 54 | \usepackage[match]{luatexja-fontspec} 55 | \en{\defaultfontfeatures{Numbers=OldStyle, Scale=MatchLowercase}} 56 | \ja{\defaultfontfeatures{Scale=MatchLowercase}} 57 | \defaultjfontfeatures{Scale=MatchLowercase, YokoFeatures={JFM=ja_JP/{kaiming,prop}, RawFeature={+pkna,+kern}}} 58 | \usepackage[haranoaji]{luatexja-preset} 59 | \setsansjfont{Sarasa Mono J} 60 | \setmonojfont[Scale=MatchLowercase, YokoFeatures={JFM=prop, RawFeature={+kern}}]{Sarasa Mono J} 61 | \setmainfont{Noto Serif} 62 | \setsansfont{Noto Sans} 63 | \setmonofont{Sarasa Mono J} 64 | 65 | \ja{ 66 | \parindent=1\zw 67 | \renewcommand{\baselinestretch}{1.2} 68 | } 69 | 70 | \usepackage{luatexja-ruby} 71 | \ltjsetruby{ 72 | fontcmd=\addjfontfeature{ 73 | YokoFeatures={RawFeature={-pkna,+ruby}}, 74 | TateFeatures={RawFeature={-pkna,+ruby}}, 75 | }, 76 | mode=7, 77 | } 78 | 79 | \usepackage[ 80 | rubyfontcmd=\addjfontfeature{ 81 | YokoFeatures={RawFeature={-pkna,+ruby}}, 82 | TateFeatures={RawFeature={-pkna,+ruby}}, 83 | }, 84 | ]{kanbun} 85 | \newcommand{\printkanbunblock}[2]{ 86 | { 87 | \parindent=0pt 88 | \ja{\linespread{1}} 89 | \vspace*{1\zw} 90 | \hfill 91 | \vbox{ 92 | \hsize=#1\zw 93 | { 94 | \tate 95 | \addjfontfeature{Scale=1} 96 | #2 97 | } 98 | } 99 | \hfill 100 | \vspace*{1\zw} 101 | } 102 | } 103 | 104 | \usepackage{bxtexlogo} 105 | \usepackage{realscripts} 106 | \usepackage{microtype} 107 | 108 | \usepackage{wallpaper} 109 | 110 | \Kanbun 111 | 以テ[二]羅(ら)蝶(てふ)ヲ[一]作ルガ[二]漢文訓読ヲ[一]用(ため)ノ包(ぱつけーぢ) 112 | \EndKanbun 113 | \title{\en{The \sty{kanbun} package}\ja{\sty{kanbun}パッケージ}} 114 | \subtitle{\normalsize\normalfont\addjfontfeature{Scale=1}\printkanbun} 115 | \author{ 116 | \en{Yuanhao Chen (\ruby[rubysmash=true]{陳|元|鎬}{ちん|げん|こう})} 117 | \ja{ 118 | \ruby[rubysmash=true]{陳|元|鎬}{ちん|げん|こう} (Yuanhao Chen) 119 | \footnote{日本人ではないので、日本語ネイティヴの方がいらっしゃればマニュアルを書き直して下さると嬉しい。} 120 | } 121 | } 122 | \date{ 123 | \en{\scshape \DAY \MONTH_ALPHA \YEAR, v\VERSION} 124 | \ja{\YEAR年\MONTH月\DAY日, v\VERSION} 125 | } 126 | 127 | 128 | \begin{document} 129 | 130 | \ThisCenterWallPaper{1}{kanbun-example.pdf} 131 | \ExplSyntaxOn 132 | \tl_set:Nn \kanbun_kumi { beta } 133 | \ExplSyntaxOff 134 | \maketitle 135 | \ja{\renewcommand{\contentsname}{目次}} 136 | \tableofcontents 137 | 138 | 139 | \section{\en{Introduction}\ja{はじめに}} 140 | \en{The \sty{kanbun} package, like other \emph{kanbun-kundoku} (漢文訓読) \LaTeX{} packages (such as \sty{gckanbun}), allows users to manually input macros for elements in a \emph{kanbun-kundoku} paragraph.} 141 | \ja{\sty{kanbun}パッケージでは他の漢文訓読の\LaTeX{}パッケージ(例えば \sty{gckanbun})と同じく、手動で漢文訓読の各要素に対応するマクロを入力できる。} 142 | 143 | \en{More importantly, it accepts input with light markup in the ``\emph{kanbun} annotation'' form when used with \LuaLaTeX, which allows typesetting \emph{kanbun-kundoku} paragraphs efficiently\footnote{The idea comes from \href{https://phesoca.com/kanbun-html/}{漢文\textsc{html}} by UntPhesoca, which is a JavaScript and \textsc{css} implementation.}.} 144 | \ja{更に重要なことには、 \LuaLaTeX{}で実行すれば、軽量マークアップの「漢文アノテーション」で容易く効率的に漢文訓読を組版することが可能となっている\footnote{JavaScriptやCSSによって実行するUntPhesocaの \href{https://phesoca.com/kanbun-html/}{漢文HTML} が参考となっていた。}。} 145 | 146 | 147 | \section{\en{Basic example with \LuaLaTeX}\ja{\LuaLaTeX{}での簡単な実例}} 148 | \en{As seen in the following example, typesetting a \emph{kanbun-kundoku} paragraph with the \sty{kanbun} package requires only light annotations --- it automatically transforms the annotated plain text into \LaTeX{} macros through Lua, rather than having users type in macros themselves.} 149 | \ja{次の実例のとおり、 \sty{kanbun}パッケージを使えばただの軽量なアノテーションで漢文訓読を組版できる。手動でマクロを入力するではなく、プログラムが自動的にアノテーションのあるプレーンテキストをLuaで処理して\LaTeX{}マクロに変更する。} 150 | 151 | \begin{example} 152 | \documentclass{ltjtarticle} 153 | \usepackage[kumi=aki, tateaki=1]{kanbun} 154 | \begin{document} 155 | \Kanbun 156 | 月落チ烏啼キテ霜満ツ[レ]天ニ, 157 | 江楓漁火対ス[二]愁眠ニ[一]。 158 | 姑(こ)蘇(そ)城外ノ寒山寺, 159 | 夜半ノ鐘声到ル[二]客船ニ[一]。 160 | \EndKanbun 161 | \printkanbun 162 | \end{document} 163 | \end{example} 164 | 165 | \ExplSyntaxOn 166 | \tl_set:Nn \kanbun_tateaki { 1 } 167 | \tl_set:Nn \kanbun_kumi { aki } 168 | \ExplSyntaxOff 169 | \Kanbun 170 | 月落チ烏啼キテ霜満ツ[レ]天ニ, 171 | 江楓漁火対ス[二]愁眠ニ[一]。 172 | 姑(こ)蘇(そ)城外ノ寒山寺, 173 | 夜半ノ鐘声到ル[二]客船ニ[一]。 174 | \EndKanbun 175 | 176 | \allowbreak 177 | \printkanbunblock{13}{\printkanbun} 178 | \vspace{-1.5\zw} 179 | 180 | \en{Note that if you want to use this functionality, you have to run this document with \LuaLaTeX.} 181 | \ja{この機能を使う場合、必ず\LuaLaTeX{}で実行してください。} 182 | 183 | 184 | \section{\en{Usage}\ja{使用方法}} 185 | 186 | \subsection{\en{Package options}\ja{パッケージのオプション}} 187 | \en{Load the package with} 188 | \ja{パッケージの読み込みは次のようにしてよい:} 189 | \nobreak 190 | \begin{ltxsyntax} 191 | \cmditem{usepackage}\oprm{\en{\sty{kanbun} options}\ja{ \sty{kanbun}のオプション}}|{kanbun}| 192 | \end{ltxsyntax} 193 | 194 | \en{This package provides a variety of customisable features in \emph{kanbun-kundoku}.} 195 | \ja{以下のオプションでさまざまな漢文訓読においてのパラメーターを設定できる。} 196 | 197 | \begin{optionlist} 198 | \optitem[]{scale}{\prm{\en{ratio}\ja{比}}} 199 | \en{Sets the ratio of the size of \emph{kanji} to that of ruby texts. Default: \verb|2|.} 200 | \ja{ルビ文字のサイズに対する漢字のサイズの割合を設定する。初期値: \verb|2|。} 201 | 202 | \SaveVerb{fontcmd}|\addjfontfeatures{RawFeature={+trad}}| 203 | \optitem[]{fontcmd}{\prm{\en{font command}\ja{書体のコマンド}}} 204 | \en{Sets the font command to use for \emph{kanji}. If \sty{luatexja-fontspec} is loaded, it is set default to \UseVerb{fontcmd} to obtain traditional \emph{kanji} if applicable.} 205 | \ja{漢字の書体のコマンドを設定する。\sty{luatexja-fontspec}パッケージが読み込まれてある場合、 \UseVerb{fontcmd} に初期化されて、旧字体のグリフに変更する。} 206 | 207 | \SaveVerb{rubyfontcmd}|\addjfontfeatures{RawFeature={+ruby}}| 208 | \optitem[]{rubyfontcmd}{\prm{\en{font command}\ja{書体のコマンド}}} 209 | \en{Sets the font command to use for ruby texts. If \sty{luatexja-fontspec} is loaded, it is set default to \UseVerb{rubyfontcmd} to obtain ruby glyphs when applicable.} 210 | \ja{ルビ文字の書体のコマンドを設定する。\sty{luatexja-fontspec}パッケージが読み込まれてある場合、 \UseVerb{rubyfontcmd} に初期化されて、ルビグリフに変更する。} 211 | 212 | \SaveVerb{unit}|\kanbun_init_zw| 213 | \optitem[]{unit}{\prm{\en{length}\ja{長さ}}} 214 | \en{Sets the dimensions of \emph{kanji} (assuming it is a square). Default: \UseVerb{unit}, which is a length equal to \verb|1em|.} 215 | \ja{(正方形だと仮定して)漢字の寸法を設定する。初期値: \UseVerb{unit} (\verb|1em| に等しい長さ)。} 216 | 217 | \optitem[]{yokoaki}{\prm{\en{ratio}\ja{比}}} 218 | \en{Sets the horizontal space between \emph{kanji} with respect to the size of ruby texts. Default: \verb|2|.} 219 | \ja{ルビ文字のサイズに対するインテルの幅の割合を設定する。初期値: \verb|2|。} 220 | 221 | \optitem[]{tateaki}{\prm{\en{ratio}\ja{比}}} 222 | \en{Sets the vertical space between \emph{kanji} with respect to the size of ruby texts. Default: \verb|2|.} 223 | \ja{ルビ文字のサイズに対する漢字間のアキ量の割合を設定する。初期値: \verb|2|。} 224 | 225 | \optitem[]{okuriintrusion}{\prm{\en{ratio}\ja{比}}} 226 | \en{Sets the intrusion of \emph{okurigana} (how much \emph{okurigana} should be vertically tucked into the space of \emph{kanji}) with respect to the size of ruby texts, if that does not cause an overlap with \emph{furigana}. Default: \verb|1|.} 227 | \ja{ルビ文字のサイズに対する送仮名\ruby[pre=0.5,post=1]{進入量}{イントルージョン}(送仮名を上に突かせて漢字に掛ける長さ)の割合を設定する。初期値: \verb|1|。} 228 | 229 | \optitem[]{kumi}{\opt{aki}, \opt{beta}} 230 | \en{Sets whether to use \emph{aki-gumi} (typeset with uniform inter-character spacing) or \emph{beta-gumi} (typeset with no inter-character space between adjacent character frames). Or simply call \opt{aki} or \opt{beta} without \opt{kumi=}. Default: \opt{aki}. } 231 | \ja{アキ組を使うかベタ組を使うかを設定する。\opt{kumi=} を書かず、単に \opt{aki} か \opt{beta} かと書いてもよい。} 232 | \end{optionlist} 233 | 234 | \SaveVerb{kanbunprefix}|\kanbun_| 235 | \en{After initialising the options, you can still change the option values through the command \cmd{setkanbun}. For example, to switch to \emph{beta-gumi}, you could use} 236 | \ja{オプションを初期化する後でも、 \cmd{setkanbun} を使ってオプションを変更できる。例えば、ベタ組に再設定するには下記のコードを使う。} 237 | \begin{example} 238 | \setkanbun{beta} 239 | \end{example} 240 | 241 | \subsection[\en{Basic usage without \LuaLaTeX}\ja{\LuaLaTeX{}を使わない場合の基本使用}]{\en{Basic usage without \LuaLaTeX{} (not recommended)}\ja{\LuaLaTeX{}を使わない場合の基本使用(お薦めではない)}} 242 | \en{When not using the advanced \emph{kanbun}-annotation functionality, it is possible to typeset \emph{kanbun} with any engine with \textsc{cjk} support, such as using \XeLaTeX{} with the \sty{xeCJK} package, or using \upLaTeX{} with \sty{utarticle} or other appropriate class. } 243 | \ja{漢文アノテーションの機能を使わない場合、任意の CJK 支援のあるエンジンで漢文を組版できる。例えば\XeLaTeX{} を \sty{xeCJK} パッケージと一緒に使うか、 \upLaTeX{} を \sty{utarticle} クラス或いは他の適宜なクラスと一緒に使うか、どちらもよい。} 244 | 245 | \begin{ltxsyntax} 246 | \cmditem{kanjiunit}\verb|{ |\cmd{furiokuri}\mprm{\en{right furigana}\ja{右の振仮名}}\mprm{\en{right okurigana}\ja{右の送仮名}}\verb| }|\vspace{-5pt}\\ 247 | \mprm{\en{left (top) punctuation (e.g.~`「')}\ja{左(上)の句読点(“「”など)}}\\ 248 | \mprm{\en{kanji}\ja{漢字}}\\ 249 | \mprm{\en{other punctuation}\ja{他の句読点}}\\ 250 | \mprm{\en{kaeriten}\ja{返点}}\\ 251 | \verb|{ |\cmd{furiokuri}\mprm{\en{left furigana}\ja{左の振仮名}}\mprm{\en{left okurigana}\ja{左の送仮名}}\verb| }| 252 | 253 | \cmditem{kanbunfont} 254 | 255 | \en{Sets the font size of \emph{kanji}. Use when the \opt{unit} option is set different to the document's default font size.} 256 | \ja{漢字のサイズを設定する。\opt{unit} オプションと文書のデフォルト文字サイズが違う時に使う。} 257 | 258 | \en{Use \cmd{multifuriokuri} instead of \cmd{furiokuri} if you are putting \emph{furigana} to multiple kanji.} 259 | \ja{複数個の漢字に仮名を振れば、 \cmd{furiokuri} の代わりに \cmd{multifuriokuri} を使う。} 260 | 261 | \cmditem{multifuriokuri}\oprm{\en{length by which ruby is raised}\ja{ルビ文字を上げる長さ}}\mprm{\en{furigana}\ja{振仮名}}\mprm{\en{okurigana}\ja{送仮名}} 262 | \end{ltxsyntax} 263 | 264 | \en{For example, the code} 265 | \ja{例えば、 \opt{tateaki} が \verb|1| に設定されている場合、下記のコードを使えば} 266 | \begin{example} 267 | % example text from https://phesoca.com/kanbun-html/ 268 | \kanbunfont 269 | \kanjiunit{}{}{子}{}{}{} 270 | \kanjiunit{\furiokuri{}{ク}}{}{曰}{,}{}{} 271 | \kanjiunit{\furiokuri{}{ゾ}}{}{盍}{}{三}{\furiokuri{}{ル}} 272 | \kanjiunit{}{}{各}{〻}{}{} 273 | \kanjiunit{\furiokuri{}{ハ}}{}{言}{}{二}{} 274 | \kanjiunit{\furiokuri{}{ノ}}{}{爾}{}{}{} 275 | \kanjiunit{\furiokuri{}{ヲ}}{}{志}{。}{一}{} 276 | \par 277 | \end{example} 278 | \en{outputs} 279 | \ja{こう出力する:} 280 | 281 | \printkanbunblock{6}{ 282 | \kanbunfont 283 | \kanjiunit{}{}{子}{}{}{} 284 | \kanjiunit{\furiokuri{}{ク}}{}{曰}{,}{}{} 285 | \kanjiunit{\furiokuri{}{ゾ}}{}{盍}{}{三}{\furiokuri{}{ル}} 286 | \kanjiunit{}{}{各}{〻}{}{} 287 | \kanjiunit{\furiokuri{}{ハ}}{}{言}{}{二}{} 288 | \kanjiunit{\furiokuri{}{ノ}}{}{爾}{}{}{} 289 | \kanjiunit{\furiokuri{}{ヲ}}{}{志}{。}{一}{} 290 | \par 291 | } 292 | 293 | \noindent 294 | \en{with \opt{tateaki} set to \verb|1|.} 295 | 296 | \subsection{\en{Usage with \LuaLaTeX}\ja{\LuaLaTeX{}での使用}} 297 | \en{\emph{Kanbun} annotation uses the following brackets to mark different elements in \emph{kanbun-kundoku} (as described in \href{https://phesoca.com/kanbun-html/}{漢文\textsc{html}} by UntPhesoca). } 298 | \ja{漢文アノテーションでは下記の括弧を以って漢文訓読においての各要素を示す(UntPhesocaの \href{https://phesoca.com/kanbun-html/}{漢文HTML} を参照されたい)。} 299 | \begin{itemize} 300 | \item \verb|( )|: \en{\emph{furigana} (}振仮名\en{)} 301 | \item \verb|{ }|: \en{\emph{okurigana} (}送仮名\en{) (these brackets can be omitted)}\ja{(この括弧を省略してもよい)} 302 | \item \verb|‹ ›|: \en{\emph{furigana} (振仮名) of \emph{saidoku-moji} (再読文字)}\ja{再読文字の振仮名} 303 | \item \verb|« »|: \en{\emph{okurigana} (送仮名) of \emph{saidoku-moji} (再読文字)}\ja{再読文字の送仮名} 304 | \item \verb|[ ]|: \en{\emph{kaeriten} (}返点\en{)} 305 | \item \verb|‘ ’|: \en{multiple \emph{kanji}, potentially with \emph{tateten} inserted, as a ruby base; group ruby (グループルビ)}\ja{グループルビのベース。中に\ruby{竪|点}{たて|てん}を入れてもよい} 306 | \item \en{no annotation: \emph{kanji} (漢字) and punctuation}\ja{アノテーション無し:漢字と句読点} 307 | \end{itemize} 308 | \en{\emph{Tateten} (竪点) can be input with either \verb|―| (\verb|U+2015|), \verb|—| (\verb|U+2014|) or \verb|㆐| (\verb|U+3190|).} 309 | \ja{\verb|―| (\verb|U+2015|) か \verb|—| (\verb|U+2014|) か \verb|㆐| (\verb|U+3190|) かで竪点を入力できる。} 310 | 311 | \begin{ltxsyntax} 312 | \cmditem{Kanbun}\cmditem{EndKanbun} 313 | 314 | \en{Write the annotated \emph{kanbun} between the commands \cmd{Kanbun} and \cmd{EndKanbun}, and it will be processed and saved, ready to be used later.} 315 | \ja{アノテーションのある漢文を \cmd{Kanbun} と \cmd{EndKanbun} の間に書き込む。処理されて、保存されておいて、後で使用可能となる。} 316 | 317 | \cmditem{printkanbun} 318 | 319 | \en{Where you would like to use the most recently saved \emph{kanbun-kundoku} paragraph, use \cmd{printkanbun}. It automatically calls \cmd{kanbunfont} and \cmd{par} to set the font size and line spacing and make paragraphs.} 320 | \ja{最近保存された漢文訓読を使用するには、 \cmd{printkanbun} を使う。自動的に \cmd{kanbunfont} と \cmd{par} を挿入して寸法やインテルを設定し、段落を作成する。} 321 | 322 | \cmditem{printkanbuncode} 323 | 324 | \en{If you wish to make modifications on the result or to use the result with a non-\LuaTeX{} engine, it is possible to obtain the macros using \cmd{printkanbuncode} (prints in the terminal), and continue to work from there.} 325 | \ja{処理の結果を一部変更する、もしくは結果を\LuaTeX{}でないエンジンで使用するには、結果のマクロを \cmd{printkanbuncode} で入手して(端末に出力)、そこから作業を続けることが可能。} 326 | 327 | \cmditem{printkanbunnopar} 328 | 329 | \en{The no-paragraph counterpart of \cmd{printkanbun}, which does not invoke \cmd{kanbunfont}, and uses \verb|\\| instead of \cmd{par}.} 330 | \ja{\cmd{printkanbun} に対応する段落無しのバージョン。\cmd{kanbunfont}を使用せず、 \cmd{par} の代わりに \verb|\\| を使用する。} 331 | 332 | \cmditem{printkanbunnoparcode} 333 | 334 | \en{The no-paragraph counterpart of \cmd{printkanbuncode}.} 335 | \ja{\cmd{printkanbuncode} に対応する段落無しのバージョン。} 336 | \end{ltxsyntax} 337 | 338 | \en{You can always save \cmd{printkanbun} to a macro for use later and start a new annotated \emph{kanbun} block, as in the following example.} 339 | \ja{次の実例のとおり、後で使えるように \cmd{printkanbun} をあるマクロに保存し、新しい漢文段落を書き込み始められる。} 340 | \begin{example} 341 | % example text from https://phesoca.com/kanbun-html/ 342 | \documentclass{ltjtarticle} 343 | \usepackage[kumi=beta]{kanbun} 344 | 345 | \Kanbun 346 | 此レ乃チ信(しん)之‘所―[三]以’(ゆゑん)為ル[二]陛下ノ禽(とりこ)ト[一]也。 347 | \EndKanbun 348 | \let\信\printkanbun 349 | 350 | \Kanbun 351 | 孤之有ルハ[二]孔明[一],猶ホ‹ごと›«キ»[二]魚之有ルガ[一レ]水也。 352 | \EndKanbun 353 | \let\孔明\printkanbun 354 | 355 | \begin{document} 356 | \孔明\par\bfseries\信 357 | \end{document} 358 | \end{example} 359 | 360 | \Kanbun 361 | 此レ乃チ信(しん)之‘所―[三]以’(ゆゑん)為ル[二]陛下ノ禽(とりこ)ト[一]也。 362 | \EndKanbun 363 | \let\信\printkanbun 364 | 365 | \Kanbun 366 | 孤之有ルハ[二]孔明[一],猶ホ‹ごと›«キ»[二]魚之有ルガ[一レ]水也。 367 | \EndKanbun 368 | \let\孔明\printkanbun 369 | 370 | \ExplSyntaxOn 371 | \tl_set:Nn \kanbun_kumi { beta } 372 | \ExplSyntaxOff 373 | \printkanbunblock{16}{\孔明\par\bfseries\信} 374 | 375 | 376 | \end{document} 377 | -------------------------------------------------------------------------------- /kanbun.lua: -------------------------------------------------------------------------------- 1 | -- Copyright 2022 Yuanhao Chen 2 | 3 | -- This work may be distributed and/or modified under the 4 | -- conditions of the LaTeX Project Public License, either version 1.3 5 | -- of this license or (at your option) any later version. 6 | -- The latest version of this license is in 7 | -- http://www.latex-project.org/lppl.txt 8 | -- and version 1.3 or later is part of all distributions of LaTeX 9 | -- version 2005/12/01 or later. 10 | -- 11 | -- This work has the LPPL maintenance status `maintained'. 12 | -- 13 | -- The Current Maintainer of this work is Yuanhao Chen. 14 | -- 15 | -- This work consists of the files kanbun.sty, kanbun.lua, 16 | -- kanbun-example.tex and kanbun.tex. 17 | 18 | function directtex(str) 19 | coroutine.yield(str) 20 | end 21 | 22 | function to_TeX_box(str) 23 | directtex("\\ExplSyntaxOn\\newbox\\kanbun_lua_box\\sbox\\kanbun_lua_box{"..str.."}\\ExplSyntaxOff") 24 | return tex.getbox('kanbun_lua_box') 25 | end 26 | 27 | function has_value (tab, val) 28 | for index, value in ipairs(tab) do 29 | if value == val then 30 | return true 31 | end 32 | end 33 | return false 34 | end 35 | 36 | function main_loop() 37 | brackets = {} 38 | -- 39 | brackets["furigana"] = {"(", ")"} 40 | brackets["okurigana"] = {"{","}"} -- allow user to omit 41 | brackets["kaeriten"] = {"[","]"} 42 | brackets["furigana4saidokumoji"] = {"‹","›"} 43 | brackets["okurigana4saidokumoji"] = {"«","»"} 44 | -- 45 | brackets["punctuation"] = {"⦉","⦊"} 46 | -- brackets["kanji"] = {"⌊","⌋"} 47 | -- brackets["multikanji"] = {"‘","’"} 48 | -- brackets["unit"] = {"“","”"} 49 | -- 50 | left_brackets = {} 51 | right_brackets = {} 52 | for k,v in pairs(brackets) do 53 | table.insert(left_brackets, v[1]) 54 | table.insert(right_brackets, v[2]) 55 | end 56 | 57 | -- punctuation_str = "〻―・、,。…「」『』" 58 | punctuation_str = "㆐〻―—・、,。…「」『』!?:" 59 | left_punctuation_str = "「『" 60 | 61 | lines_chars_table = {} 62 | tex_kana_bool = token.create("g_kana_bool") 63 | tex_true_bool = token.create("c_true_bool") 64 | for i,l in ipairs(verb_table) do 65 | split_line = {} 66 | for c in l:gmatch(utf8.charpattern) do 67 | table.insert(split_line, c) 68 | end 69 | 70 | -- some unknown bug (in \matchkana ?) solved by changing the last entry to an empty string if not ascii 71 | for i,c in ipairs(split_line) do 72 | last_index = i 73 | end 74 | if utf8.codepoint(split_line[last_index] or " ") < 128 then 75 | split_line[last_index+1]="" 76 | else 77 | split_line[last_index]="" 78 | end 79 | 80 | last_bracket_index = 0 81 | for j,c in ipairs(split_line) do 82 | if has_value(left_brackets, c) then 83 | last_bracket_index = j 84 | end 85 | if last_bracket_index == 0 then 86 | directtex("\\matchkana{"..c.."}") 87 | if tex_kana_bool.mode == tex_true_bool.mode then 88 | split_line[j] = brackets["okurigana"][1]..c..brackets["okurigana"][2] 89 | else 90 | split_line[j] = "“⌊"..c.."⌋”" 91 | end 92 | end 93 | if has_value(right_brackets, c) then 94 | last_bracket_index = 0 95 | end 96 | end 97 | table.insert(lines_chars_table, split_line) 98 | end 99 | 100 | annotated_lines_table = {} 101 | for i,l in ipairs(lines_chars_table) do 102 | line = table.concat(l, "") 103 | 104 | line = string.gsub(line, brackets["okurigana"][2]..brackets["okurigana"][1], "") 105 | for k,v in pairs(brackets) do 106 | line = string.gsub(line, "”(%"..v[1]..")", "%1") 107 | line = string.gsub(line, "(%"..v[2]..")(“)", "%1”%2") 108 | end 109 | for c in line:gmatch(utf8.charpattern) do 110 | last = c 111 | end 112 | if has_value(right_brackets, last) then 113 | str = str .. '”' 114 | end 115 | line = string.gsub(line, "⌊‘⌋”", "‘") 116 | line = string.gsub(line, "“⌊’⌋", "’") 117 | for p in punctuation_str:gmatch(utf8.charpattern) do 118 | line = string.gsub(line, "”“⌊("..p..")⌋", "⦉%1⦊") 119 | end 120 | line = string.gsub(line, "⦊⦉", "") 121 | 122 | -- reverse the makeshift bug fix to \matchkana 123 | line = string.gsub(line, "“⌊⌋”", "") 124 | 125 | -- process annotated text 126 | tmp_number_of_multikanji_braces = {utf8.char(61442), utf8.char(61443)} 127 | -- process line into units 128 | split_line = {} 129 | for c in line:gmatch(utf8.charpattern) do 130 | table.insert(split_line, c) 131 | end 132 | units = {} 133 | unit_content = {} 134 | last_bracket_index = 0 135 | for j,c in ipairs(split_line) do 136 | if c == "”" then 137 | last_bracket_index = last_bracket_index - 1 138 | end 139 | if last_bracket_index < 1 then 140 | table.insert(units, table.concat(unit_content, "")) 141 | unit_content = {} 142 | else 143 | table.insert(unit_content, c) 144 | end 145 | if c == "“" then 146 | last_bracket_index = last_bracket_index + 1 147 | end 148 | end 149 | -- account for multikanji 150 | for j,u in ipairs(units) do 151 | split_unit = {} 152 | for c in u:gmatch(utf8.charpattern) do 153 | table.insert(split_unit, c) 154 | end 155 | number_of_multikanji = 0 156 | local last_k 157 | for k,c in ipairs(split_unit) do 158 | if c == "“" then 159 | number_of_multikanji = number_of_multikanji + 1 160 | last_k = k 161 | end 162 | end 163 | for m,c in ipairs(split_unit) do 164 | if m == last_k then 165 | split_unit[m] = "“"..tmp_number_of_multikanji_braces[1]..number_of_multikanji..tmp_number_of_multikanji_braces[2] 166 | end 167 | end 168 | units[j] = table.concat(split_unit, "") 169 | if number_of_multikanji > 0 then 170 | units[j] = string.gsub(units[j], "“(.-)”’(.*)", "“%1%2”") 171 | units[j] = string.gsub(units[j], "‘", "") 172 | tmp_unit = units[j] 173 | table.remove(units, j) 174 | for new_unit in tmp_unit:gmatch"“(.-)”" do 175 | table.insert(units, j, new_unit) 176 | j = j + 1 177 | end 178 | end 179 | end 180 | for j,u in ipairs(units) do 181 | if u == "" then 182 | table.remove(units, j) 183 | end 184 | end 185 | next_left_punct_ = "" 186 | for j,u in ipairs(units) do 187 | right_okuri_ = u:match("%{(.-)%}") or "" 188 | kanji_ = u:match("⌊(.-)⌋") or "" 189 | right_furi_ = u:match("%((.-)%)") or "" 190 | left_furi_ = u:match("‹(.-)›") or "" 191 | left_okuri_ = u:match("«(.-)»") or "" 192 | punct_ = u:match("⦉(.-)⦊") or "" 193 | -- 194 | -- punct_ = punct_:gsub("―", "\\tateten") 195 | -- punct_ = punct_:gsub("—", "\\tateten") 196 | -- punct_ = punct_:gsub("〻", "\\ninojiten") 197 | -- 198 | kaeriten_ = u:match("%[(.-)%]") or "" 199 | multikanji_ = u:match(tmp_number_of_multikanji_braces[1].."(.-)"..tmp_number_of_multikanji_braces[2]) or 0 200 | if punctuation_str:match(kanji_) then 201 | punct_ = kanji_ 202 | kanji_ = "" 203 | end 204 | left_punct_ = next_left_punct_ 205 | next_left_punct_ = "" 206 | for p_ in punct_:gmatch(utf8.charpattern) do 207 | if left_punctuation_str:match(p_) then 208 | next_left_punct_ = next_left_punct_ .. p_ 209 | end 210 | end 211 | for p_ in left_punctuation_str:gmatch(utf8.charpattern) do 212 | punct_ = string.gsub(punct_, p_, "") 213 | end 214 | if u:match(tmp_number_of_multikanji_braces[1]) then 215 | multiruby_raise_by_ = 0 216 | for trace_back_index = 1, multikanji_-1 do 217 | multiruby_raise_by_ = multiruby_raise_by_ + to_TeX_box(units[j - trace_back_index]).width/(kanbunzwtosp) 218 | end 219 | units[j - multikanji_ + 1] = units[j - multikanji_ + 1]:gsub("\\kanjiunit", "\\hbox{\\kanjiunit") 220 | units[j] = "\\kanjiunit{\\multifuriokuri["..multiruby_raise_by_.."]{"..right_furi_.."}{"..right_okuri_.."}}{"..left_punct_.."}{"..kanji_.."}{"..punct_.."}{"..kaeriten_.."}{\\multifuriokuri["..multiruby_raise_by_.."]{"..left_furi_.."}{"..left_okuri_.."}}}" 221 | else 222 | if kanji_ == "" then 223 | units[j] = "" 224 | else 225 | units[j] = "\\kanjiunit{\\furiokuri{"..right_furi_.."}{"..right_okuri_.."}}{"..left_punct_.."}{"..kanji_.."}{"..punct_.."}{"..kaeriten_.."}{\\furiokuri{"..left_furi_.."}{"..left_okuri_.."}}" 226 | end 227 | end 228 | end 229 | line = table.concat(units, "") 230 | 231 | table.insert(annotated_lines_table, line) 232 | end 233 | 234 | -- ouput 235 | output = "{\\kanbunfont"..table.concat(annotated_lines_table, "\\par").."\\par}" 236 | directtex("\\def\\printkanbun{"..output.."}") 237 | directtex("\\def\\printkanbuncode{\\directlua{print('')print(output)}}") 238 | -- nopar output 239 | nopar_output = table.concat(annotated_lines_table, "\\\\") 240 | directtex("\\def\\printkanbunnopar{"..nopar_output.."}") 241 | directtex("\\def\\printkanbunnoparcode{\\directlua{print('')print(nopar_output)}}") 242 | 243 | -- end loop in TeX 244 | directtex("\\continuefalse") 245 | end 246 | -------------------------------------------------------------------------------- /replace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # define variables 4 | YEAR=2025 5 | MONTH_ALPHA=march 6 | MONTH=3 7 | DAY=17 8 | VERSION=1.3 9 | 10 | REGEX="s|\\\\YEAR|${YEAR}|g;s|\\\\MONTH_ALPHA|${MONTH_ALPHA}|g;s|\\\\MONTH|${MONTH}|g;s|\\\\DAY|${DAY}|g;s|\\\\VERSION|${VERSION}|g" 11 | 12 | # write variables into files 13 | sed $REGEX kanbun-proto.tex > kanbun.tex 14 | sed $REGEX kanbun-proto.sty > kanbun.sty 15 | -------------------------------------------------------------------------------- /test.tex: -------------------------------------------------------------------------------- 1 | \documentclass[tate]{jlreq} 2 | 3 | \newcommand{\setparindent}[1]{ 4 | \renewcommand{\jlreqparindent}{#1} 5 | \parindent=#1 6 | } 7 | 8 | \usepackage{scrextend} 9 | \changefontsizes{1.5em} 10 | 11 | \usepackage{kanbun} 12 | 13 | \paperheight=35em 14 | \paperwidth=102em 15 | \def\vmargin{\dimexpr(\paperheight-31.001em)/2\relax} 16 | \def\vheadsep{\dimexpr\vmargin/3\relax} 17 | \usepackage[headsep=\vheadsep, top=\vmargin, bottom=\vmargin, left=4em, right=4em]{geometry} 18 | 19 | \AtBeginDocument{\pagenumbering{gobble}} 20 | 21 | \begin{document} 22 | 23 | \setparindent{0em} 24 | \setkanbun{tateaki=0.666, unit=1.5em, yokoaki=0, aki} 25 | 26 | \Kanbun 27 |  大東亞戰爭終結ノ詔書 28 | \EndKanbun 29 | 30 | \printkanbun 31 | 32 | % 33 | 34 | \vspace{2em} 35 | 36 | % 37 | 38 | \setparindent{2em} 39 | \setkanbun{tateaki=2, unit=1em, yokoaki=2.5, aki} 40 | 41 | \Kanbun 42 | 朕深ク鑑ミ[三]世界ノ大勢ト與[二]ニ帝國ノ現狀[一],欲シ[下]以テ[二]非常ノ措置ヲ[一]收[中]㆐拾セムト時局ヲ[上],茲ニ告ク[下]爾[二]忠良ナル[一]臣民ニ[上]。 43 | 44 | 朕ハ使[下]メタリ帝國政府ヲシテ,對シ[二]米英支蘇四國ニ[一],通[中]㆐告セ受[二]㆐諾スル其ノ共同宣言ヲ[一]旨[上]。 45 | 46 | 抑〻圖リ[二]帝國臣民ノ康寧ヲ[一],偕ニスル[二]萬邦共榮之樂ヲ[一]者,皇祖皇宗之遺範ニシテ,而朕之所[二]拳拳不ル[一レ]措カ也。曩ニ所[三]㆐以宣[二]㆐戰セル米英二國ニ[一],亦實ニ出テ[四]於庶[三]㆐幾スルニ帝國ノ自存ト與ヲ[二]東亞ノ安定[一]。如キ[三]排シ[二]他國ノ主權ヲ[一]、侵スカ[二]領土ヲ[一]者,固ヨリ非ス[三]朕カ志ニ[一]。然ルニ交戰已ニ閱シ[二]四歲ヲ[一],雖(拘)ラス[三]朕カ陸海將兵之勇戰、朕カ百僚有司之勵精、朕一億衆庶之奉公,各〻盡セルニ[二]最善ヲ[一],戰局未[二]必スシモ好轉セ[一],世界ノ大勢亦不[レ]利アラ[二]於我ニ[一]。加之敵ハ新ニ使[二]㆐用シテ殘虐ナル爆彈ヲ[一],頻ニ殺[二]㆐傷シ無辜ヲ[一],慘害ノ所[レ]及フ,真ニ至ル[レ]不ルニ[レ]可カラ[レ]測ル。而モ尚繼續セムカ[二]交戰ヲ[一],終ニ不[下]招[二]㆐來スル我カ民族之滅亡ヲ[一]而已ナラ[上],延テ可シ[三]破[二]㆐卻ス人類ノ文明ヲモ[一]。如クムハ[レ]斯ノ,朕何ヲ以テカ保シ[二]億兆ノ赤子ヲ[一],謝セムヤ[二]皇祖皇宗之神靈ニ[一]。是レ朕カ所[四]㆐以至レル[レ]使ムルニ[三]帝國政府ヲシテ應セ[二]共同宣言ニ[一]也。 47 | 48 | 朕ハ對シ[下]與[二]帝國[一]共ニ終始協[二]㆐力セル於東亞ノ解放ニ[一]之諸盟邦ニ[上],不[レ]得[レ]不ル[レ]表セ[二]遺憾之意ヲ[一]。致セハ[レ]想ヲ[中]帝國臣民ニシテ,死シ[二]於戰陣ニ[一]、殉シ[二]於職域ニ[一]、斃レタル[二]於非命ニ[一]者,及其ノ遺族ニ[上],五內為ニ裂ク。且至リテハ[下]於負ヒ[二]戰傷ヲ[一]、蒙リ[二]災禍ヲ[一]、失ヒタル[二]家業ヲ[一]者之厚生ニ[上],朕之所[二]深ク軫念スル[一]也。惟フニ今後帝國ノ可[二]㆐能キ受ク[一]之苦難ハ,固ヨリ非ズ[二]尋常ニ[一]。爾臣民之衷情モ,朕善ク知ル[レ]之ヲ。然レトモ朕ハ時運ノ所[レ]趨ク,堪ヘ[レ]難キヲ[レ]堪ヘ、忍ヒ[レ]難キヲ[レ]忍ヒ,欲ス[下]以テ為ニ[二]萬世ノ[一]開カムト[中]太平ヲ[上]。 49 | 50 | 朕ハ茲ニ得テ[三]護[二]㆐持シ國體ヲ[一],信[下]㆐倚シ爾[二]忠良ナル[一]臣民之赤誠ニ[上],常ニ與[二]爾臣民[一]共ニ在リ。若シ夫レ情之所[レ]激スル、濫ニ滋クシ[二]事端ヲ[一],或ハ如キハ[下]為ニ[三]同胞排擠、互ニ亂リ[二]時局ヲ[一],誤リ[二]大道ヲ[一],失フカ[中]信義ヲ於世界ニ[上],朕最モ戒ム[レ]之ヲ。宜シク舉國一家,子孫相傳ヘ,確ク信[二]神州ノ不滅ヲ[一],念[二]任重クシテ而道遠キヲ[一],傾ケ[二]總力ヲ於將來之建設ニ[一],篤クシ[二]道義ヲ[一],鞏クシ[二]志操ヲ[一],誓テ發[二]㆐揚シ國體ノ精華ヲ[一],可シ[レ]期ス[レ]不ラムルコトヲ[レ]後レ[二]於世界之進運ニ[一]。爾臣民,其レ克ク體セヨ[二]朕カ意[一]。 51 | \EndKanbun 52 | 53 | \printkanbun 54 | 55 | % 56 | 57 | \vspace{2em} 58 | 59 | % 60 | 61 | \setparindent{0em} 62 | 63 | \Kanbun 64 | 裕仁 65 | \EndKanbun 66 | 67 | \edef\gyomei{\printkanbun} 68 | 69 | \Kanbun 70 | 天皇 71 | 御璽 72 | \EndKanbun 73 | 74 | \edef\gyoji{\printkanbun} 75 | 76 | \begin{minipage}[c]{2em} 77 | ~ 78 | \end{minipage} 79 | \begin{minipage}[c]{6em} 80 | \setkanbun{tateaki=1, unit=2em, yokoaki=1, aki} 81 | \vspace*{\fill} 82 | \gyomei 83 | \vspace*{\fill} 84 | \end{minipage} 85 | % \fbox{ 86 | \begin{minipage}[c]{12em} 87 | \setkanbun{tateaki=1, unit=4em, yokoaki=1, aki} 88 | \gyoji 89 | \end{minipage} 90 | % } 91 | 92 | \end{document} 93 | --------------------------------------------------------------------------------