% Copyright 2026 Open-Guji (https://github.com/open-guji) % % Licensed under the Apache License, Version 2.0 (the "License"); % you may not use this file except in compliance with the License. % You may obtain a copy of the License at % % http://www.apache.org/licenses/LICENSE-2.0 % % Unless required by applicable law or agreed to in writing, software % distributed under the License is distributed on an "AS IS" BASIS, % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % See the License for the specific language governing permissions and % limitations under the License. % luatex-cn-banxin.sty % 古籍版心与鱼尾功能支持 % 这是 luatex_cn 的子包 % \RequirePackage{expl3} \RequirePackage{xparse} \ProvidesExplPackage {banxin/luatex-cn-banxin} {2026/02/18} {0.3.0} {Ancient Book Banxin Support} \lua_now:e { package.loaded["banxin.luatex-cn-banxin-main"]~=~nil; banxin~=~require("banxin.luatex-cn-banxin-main"); } % ============================================================================= % Variable Declarations % ============================================================================= % Banxin on/off \bool_new:N \l__luatexcn_banxin_on_bool % Banxin layout ratios \tl_new:N \l__luatexcn_banxin_upper_ratio_tl \tl_new:N \l__luatexcn_banxin_middle_ratio_tl % Banxin divider \bool_new:N \l__luatexcn_banxin_divider_bool % Yuwei \bool_new:N \l__luatexcn_banxin_upper_yuwei_bool \bool_new:N \l__luatexcn_banxin_lower_yuwei_bool % Book name variables \tl_new:N \l__luatexcn_banxin_book_name_tl \tl_new:N \l__luatexcn_banxin_book_name_font_size_tl \tl_new:N \l__luatexcn_banxin_book_name_grid_height_tl \tl_new:N \l__luatexcn_banxin_book_name_align_tl \tl_new:N \l__luatexcn_banxin_book_name_top_padding_tl % Chapter title variables \tl_new:N \l__luatexcn_banxin_chapter_title_tl \tl_new:N \l__luatexcn_banxin_chapter_title_font_size_tl \tl_new:N \l__luatexcn_banxin_chapter_title_grid_height_tl \tl_new:N \l__luatexcn_banxin_chapter_title_top_margin_tl \int_new:N \l__luatexcn_banxin_chapter_title_cols_int \tl_new:N \l__luatexcn_banxin_chapter_title_align_tl % Page number variables \tl_new:N \l__luatexcn_banxin_page_number_font_size_tl \tl_new:N \l__luatexcn_banxin_page_number_grid_height_tl \tl_new:N \l__luatexcn_banxin_page_number_align_tl \tl_new:N \l__luatexcn_banxin_page_number_bottom_padding_tl % Publisher variables \tl_new:N \l__luatexcn_banxin_publisher_tl \tl_new:N \l__luatexcn_banxin_publisher_font_size_tl \tl_new:N \l__luatexcn_banxin_publisher_grid_height_tl \tl_new:N \l__luatexcn_banxin_publisher_bottom_margin_tl \tl_new:N \l__luatexcn_banxin_publisher_align_tl % ============================================================================= % Sub-Namespace Definitions % ============================================================================= % book-name sub-namespace \keys_define:nn { luatexcn / banxin / book-name } { font-size .tl_set:N = \l__luatexcn_banxin_book_name_font_size_tl, font-size .initial:n = {}, grid-height .tl_set:N = \l__luatexcn_banxin_book_name_grid_height_tl, grid-height .initial:n = {}, align .tl_set:N = \l__luatexcn_banxin_book_name_align_tl, align .initial:n = {center}, top-padding .tl_set:N = \l__luatexcn_banxin_book_name_top_padding_tl, top-padding .initial:n = {2pt}, } % chapter sub-namespace \keys_define:nn { luatexcn / banxin / chapter } { font-size .tl_set:N = \l__luatexcn_banxin_chapter_title_font_size_tl, font-size .initial:n = {}, grid-height .tl_set:N = \l__luatexcn_banxin_chapter_title_grid_height_tl, grid-height .initial:n = {}, top-margin .tl_set:N = \l__luatexcn_banxin_chapter_title_top_margin_tl, top-margin .initial:n = {20pt}, cols .int_set:N = \l__luatexcn_banxin_chapter_title_cols_int, cols .initial:n = 1, align .tl_set:N = \l__luatexcn_banxin_chapter_title_align_tl, align .initial:n = {center}, } % page-number sub-namespace \keys_define:nn { luatexcn / banxin / page-number } { font-size .tl_set:N = \l__luatexcn_banxin_page_number_font_size_tl, font-size .initial:n = {14pt}, grid-height .tl_set:N = \l__luatexcn_banxin_page_number_grid_height_tl, grid-height .initial:n = {}, align .tl_set:N = \l__luatexcn_banxin_page_number_align_tl, align .initial:n = {right-bottom}, bottom-padding .tl_set:N = \l__luatexcn_banxin_page_number_bottom_padding_tl, bottom-padding .initial:n = {10pt}, } % publisher sub-namespace \keys_define:nn { luatexcn / banxin / publisher } { font-size .tl_set:N = \l__luatexcn_banxin_publisher_font_size_tl, font-size .initial:n = {10pt}, grid-height .tl_set:N = \l__luatexcn_banxin_publisher_grid_height_tl, grid-height .initial:n = {}, align .tl_set:N = \l__luatexcn_banxin_publisher_align_tl, align .initial:n = {right}, bottom-margin .tl_set:N = \l__luatexcn_banxin_publisher_bottom_margin_tl, bottom-margin .initial:n = {5pt}, } % ============================================================================= % Main Banxin Key Definitions % ============================================================================= \keys_define:nn { luatexcn / banxin } { % Banxin on/off banxin .bool_set:N = \l__luatexcn_banxin_on_bool, banxin .initial:n = false, % Banxin layout ratios banxin-upper-ratio .tl_set:N = \l__luatexcn_banxin_upper_ratio_tl, banxin-upper-ratio .initial:n = {0.28}, banxin-middle-ratio .tl_set:N = \l__luatexcn_banxin_middle_ratio_tl, banxin-middle-ratio .initial:n = {0.56}, % Banxin divider banxin-divider .bool_set:N = \l__luatexcn_banxin_divider_bool, banxin-divider .initial:n = true, % Yuwei upper-yuwei .bool_set:N = \l__luatexcn_banxin_upper_yuwei_bool, upper-yuwei .initial:n = true, lower-yuwei .bool_set:N = \l__luatexcn_banxin_lower_yuwei_bool, lower-yuwei .initial:n = true, % Chapter title text content (used by \chapter command) chapter-title .tl_set:N = \l__luatexcn_banxin_chapter_title_tl, chapter-title .initial:n = {}, % Nested key handlers - detect text vs key-value pairs book-name .code:n = { \tl_if_in:nnTF { #1 } { = } { \keys_set:nn { luatexcn / banxin / book-name } { #1 } } { \tl_set:Nn \l__luatexcn_banxin_book_name_tl { #1 } } }, chapter .code:n = { \keys_set:nn { luatexcn / banxin / chapter } { #1 } }, page-number .code:n = { \keys_set:nn { luatexcn / banxin / page-number } { #1 } }, publisher .code:n = { \tl_if_in:nnTF { #1 } { = } { \keys_set:nn { luatexcn / banxin / publisher } { #1 } } { \tl_set:Nn \l__luatexcn_banxin_publisher_tl { #1 } } }, } % ============================================================================= % Setup Command % ============================================================================= \NewDocumentCommand{\banxinSetup}{ m } { \keys_set:nn { luatexcn / banxin } { #1 } % Update _G.banxin.enabled for early access by content.setup \lua_now:e { _G.banxin.setup({ enabled~=~\bool_if:NTF~\l__luatexcn_banxin_on_bool~{true}~{false} }) } } % ============================================================================= % Compatibility Mode Logic % ============================================================================= % 1. Book Name / Title Synchronization \cs_if_exist:NTF \title { \NewCommandCopy \__luatexcn_banxin_orig_title \title \RenewDocumentCommand \title { m } { \__luatexcn_banxin_orig_title { #1 } \tl_set:Nn \l__luatexcn_banxin_book_name_tl { #1 } } } { \NewDocumentCommand \title { m } { \gdef\@title{#1} \tl_set:Nn \l__luatexcn_banxin_book_name_tl { #1 } } } % 2. Chapter Title Synchronization \cs_if_exist:NTF \chapter { \NewCommandCopy \__luatexcn_banxin_orig_chapter \chapter \RenewDocumentCommand \chapter { s o m } { \IfBooleanTF {#1} { \__luatexcn_banxin_orig_chapter* {#3} } { \IfNoValueTF {#2} { \__luatexcn_banxin_orig_chapter {#3} } { \__luatexcn_banxin_orig_chapter [#2] {#3} } } \tl_set:Nn \l__luatexcn_banxin_chapter_title_tl { #3 } } } { \NewDocumentCommand \chapter { m } { \tl_set:Nn \l__luatexcn_banxin_chapter_title_tl { #1 } } } % ============================================================================ % CJK Key Aliases (中文键值别名) % ============================================================================ % --- book-name sub-namespace --- \keys_define:nn { luatexcn / banxin / book-name } { 字号 .tl_set:N = \l__luatexcn_banxin_book_name_font_size_tl, 格高 .tl_set:N = \l__luatexcn_banxin_book_name_grid_height_tl, 对齐 .tl_set:N = \l__luatexcn_banxin_book_name_align_tl, } % --- chapter sub-namespace --- \keys_define:nn { luatexcn / banxin / chapter } { 字号 .tl_set:N = \l__luatexcn_banxin_chapter_title_font_size_tl, 格高 .tl_set:N = \l__luatexcn_banxin_chapter_title_grid_height_tl, 上留白 .tl_set:N = \l__luatexcn_banxin_chapter_title_top_margin_tl, 列数 .int_set:N = \l__luatexcn_banxin_chapter_title_cols_int, 列數 .int_set:N = \l__luatexcn_banxin_chapter_title_cols_int, 对齐 .tl_set:N = \l__luatexcn_banxin_chapter_title_align_tl, 對齊 .tl_set:N = \l__luatexcn_banxin_chapter_title_align_tl, } % --- page-number sub-namespace --- \keys_define:nn { luatexcn / banxin / page-number } { 字号 .tl_set:N = \l__luatexcn_banxin_page_number_font_size_tl, 格高 .tl_set:N = \l__luatexcn_banxin_page_number_grid_height_tl, 对齐 .tl_set:N = \l__luatexcn_banxin_page_number_align_tl, } % --- publisher sub-namespace --- \keys_define:nn { luatexcn / banxin / publisher } { 字号 .tl_set:N = \l__luatexcn_banxin_publisher_font_size_tl, 格高 .tl_set:N = \l__luatexcn_banxin_publisher_grid_height_tl, 对齐 .tl_set:N = \l__luatexcn_banxin_publisher_align_tl, 下留白 .tl_set:N = \l__luatexcn_banxin_publisher_bottom_margin_tl, } % --- main banxin namespace --- \keys_define:nn { luatexcn / banxin } { 版心 .bool_set:N = \l__luatexcn_banxin_on_bool, 版心上比 .tl_set:N = \l__luatexcn_banxin_upper_ratio_tl, 版心中比 .tl_set:N = \l__luatexcn_banxin_middle_ratio_tl, 版心分隔线 .bool_set:N = \l__luatexcn_banxin_divider_bool, 版心分隔線 .bool_set:N = \l__luatexcn_banxin_divider_bool, 上鱼尾 .bool_set:N = \l__luatexcn_banxin_upper_yuwei_bool, 上魚尾 .bool_set:N = \l__luatexcn_banxin_upper_yuwei_bool, 下鱼尾 .bool_set:N = \l__luatexcn_banxin_lower_yuwei_bool, 下魚尾 .bool_set:N = \l__luatexcn_banxin_lower_yuwei_bool, 章节标题 .tl_set:N = \l__luatexcn_banxin_chapter_title_tl, 章節標題 .tl_set:N = \l__luatexcn_banxin_chapter_title_tl, 书名 .meta:n = { book-name = {#1} }, 書名 .meta:n = { book-name = {#1} }, 章节 .meta:n = { chapter = {#1} }, 章節 .meta:n = { chapter = {#1} }, 页码 .meta:n = { page-number = {#1} }, 頁碼 .meta:n = { page-number = {#1} }, 出版商 .meta:n = { publisher = {#1} }, } % ============================================================================ % CJK Aliases (中文别名) % ============================================================================ % Simplified Chinese / 简体 \NewCommandCopy{\版心设置}{\banxinSetup} % Traditional Chinese / 繁体 \NewCommandCopy{\版心設置}{\banxinSetup} \ExplSyntaxOff% % \endinput%