From ebb995fecaa90baf000db043f4b25ec302c09000 Mon Sep 17 00:00:00 2001 From: SteamedFish <69167+SteamedFish@users.noreply.github.com> Date: Thu, 6 Apr 2023 21:50:15 +0800 Subject: [PATCH] Add Chinese numbering (#565) --- Cargo.lock | 66 +++++++++++++++++++++++++++ library/Cargo.toml | 1 + library/src/meta/numbering.rs | 22 ++++++++- tests/typ/meta/numbering.typ | 84 +++++++++++++++++------------------ 4 files changed, 130 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6cc43ac7d..9b8917273 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,6 +170,31 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chinese-number" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "365a2e504d6cb41e85fba5d01a6baf7f13cad4424102859193c4674e7fdff933" +dependencies = [ + "chinese-numerals", + "chinese-variant", + "enum-ordinalize", + "num-bigint", + "num-traits", +] + +[[package]] +name = "chinese-numerals" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a5a40575256b55eebe3e39fa41e53bdaea5d67ac5a7092fa8756020c798d1e" + +[[package]] +name = "chinese-variant" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeea139b89efab957972956e5d3e4efb66a6c261f726abf6911040cc8ef700f7" + [[package]] name = "chrono" version = "0.4.24" @@ -430,6 +455,20 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "enum-ordinalize" +version = "3.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bb1df8b45ecb7ffa78dca1c17a438fb193eb083db0b1b494d2a61bcb5096a" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + [[package]] name = "errno" version = "0.3.0" @@ -910,6 +949,17 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1174,6 +1224,15 @@ dependencies = [ "xmlparser", ] +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.37.5" @@ -1240,6 +1299,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + [[package]] name = "serde" version = "1.0.158" @@ -1584,6 +1649,7 @@ dependencies = [ name = "typst-library" version = "0.1.0" dependencies = [ + "chinese-number", "comemo", "csv", "ecow", diff --git a/library/Cargo.toml b/library/Cargo.toml index 0b754dd2f..154602699 100644 --- a/library/Cargo.toml +++ b/library/Cargo.toml @@ -33,3 +33,4 @@ unicode-math-class = "0.1" unicode-script = "0.5" unicode-segmentation = "1" xi-unicode = "0.3" +chinese-number = { version = "0.7", default-features = false, features = ["number-to-chinese"] } diff --git a/library/src/meta/numbering.rs b/library/src/meta/numbering.rs index aed2a9e32..f0a1c34e8 100644 --- a/library/src/meta/numbering.rs +++ b/library/src/meta/numbering.rs @@ -1,5 +1,6 @@ use std::str::FromStr; +use chinese_number::{ChineseCase, ChineseCountMethod, ChineseVariant, NumberToChinese}; use ecow::EcoVec; use crate::prelude::*; @@ -214,7 +215,8 @@ impl FromStr for NumberingPattern { }; let prefix = pattern[handled..i].into(); - let case = if c.is_uppercase() { Case::Upper } else { Case::Lower }; + let case = + if c.is_uppercase() || c == '壹' { Case::Upper } else { Case::Lower }; pieces.push((prefix, kind, case)); handled = c.len_utf8() + i; } @@ -257,6 +259,7 @@ enum NumberingKind { Roman, Symbol, Hebrew, + Chinese, HiraganaIroha, KatakanaIroha, } @@ -270,6 +273,7 @@ impl NumberingKind { 'i' => NumberingKind::Roman, '*' => NumberingKind::Symbol, 'א' => NumberingKind::Hebrew, + '一' | '壹' => NumberingKind::Chinese, 'い' => NumberingKind::HiraganaIroha, 'イ' => NumberingKind::KatakanaIroha, _ => return None, @@ -284,6 +288,7 @@ impl NumberingKind { Self::Roman => 'i', Self::Symbol => '*', Self::Hebrew => 'א', + Self::Chinese => '一', Self::HiraganaIroha => 'い', Self::KatakanaIroha => 'イ', } @@ -432,6 +437,21 @@ impl NumberingKind { } fmt } + Self::Chinese => { + let chinesecase = match case { + Case::Lower => ChineseCase::Lower, + Case::Upper => ChineseCase::Upper, + }; + + match (n as u8).to_chinese( + ChineseVariant::Simple, + chinesecase, + ChineseCountMethod::TenThousand, + ) { + Ok(chinesestring) => EcoString::from(chinesestring), + Err(_) => '-'.into(), + } + } } } } diff --git a/tests/typ/meta/numbering.typ b/tests/typ/meta/numbering.typ index 100fa4803..2c39c4437 100644 --- a/tests/typ/meta/numbering.typ +++ b/tests/typ/meta/numbering.typ @@ -5,61 +5,61 @@ numbering("*", i) [ and ] numbering("I.a", i, i) - [ for #i] - parbreak() + [ for #i \ ] } --- #for i in range(0, 4) { numbering("A", i) - [ for #i] - linebreak() + [ for #i \ ] } -#par[...] +... \ #for i in range(26, 30) { numbering("A", i) - [ for #i] - linebreak() + [ for #i \ ] } -#par[...] +... \ #for i in range(702, 706) { numbering("A", i) - [ for #i] - linebreak() + [ for #i \ ] +} + +--- +#set text(lang: "zh") +#for i in range(9,21, step: 2){ + numbering("一", i) + [ and ] + numbering("壹", i) + [ for #i \ ] +} + +--- +#for i in range(0, 4) { + numbering("イ", i) + [ (or ] + numbering("い", i) + [) for #i \ ] +} +... \ +#for i in range(47, 51) { + numbering("イ", i) + [ (or ] + numbering("い", i) + [) for #i \ ] +} +... \ +#for i in range(2256, 2260) { + numbering("イ", i) + [ for #i \ ] +} + +--- +#set text(lang: "he") +#for i in range(9, 21, step: 2) { + numbering("א.", i) + [ עבור #i \ ] } --- // Error: 17-19 number must be at least zero #numbering("1", -1) - ---- -#set text(lang: "he") - -#for i in range(9, 21, step: 2) { - numbering("א.", i) - [ עבור #i] - parbreak() -} - ---- -#for i in range(0, 4) { - numbering("イ", i) - [ (or ] - numbering("い", i) - [) for #i] - linebreak() -} -#par[...] -#for i in range(47, 51) { - numbering("イ", i) - [ (or ] - numbering("い", i) - [) for #i] - linebreak() -} -#par[...] -#for i in range(2256, 2260) { - numbering("イ", i) - [ for #i] - linebreak() -}