From 55730e022182e86602521b521e3defd9055f2885 Mon Sep 17 00:00:00 2001
From: Danil <81031453+Kostenkov-2021@users.noreply.github.com>
Date: Wed, 3 Jun 2026 12:20:37 +0300
Subject: [PATCH 1/4] Russian Braille fixes
This commit adds fixes to Russian Braille. Now the test with parentheses is passed. Also there are devision and multiplication signs have been modified according to the Russian braille specs.
---
Rules/Braille/Russian/unicode.yaml | 8 +++++++-
tests/braille/Russian/russian.rs | 20 ++++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/Rules/Braille/Russian/unicode.yaml b/Rules/Braille/Russian/unicode.yaml
index 1f2c733c..a0b0dc3c 100644
--- a/Rules/Braille/Russian/unicode.yaml
+++ b/Rules/Braille/Russian/unicode.yaml
@@ -4,13 +4,15 @@
- ",": [t: "⠠⠂"]
- "!": [t: "⠠⠖"]
- "?": [t: "⠠⠢"]
-- ":": [t: "⠠⠒"]
+- ":": [t: "⠀⠲"]
- ";": [t: "⠠⠆"]
- "{": [t: "⠠⠪"]
- "}": [t: "⠠⠕"]
- "+": [t: "⠀⠖"]
- "-": [t: "⠀⠤"]
- "=": [t: "⠀⠶"]
+- "(": [t: "⠣"]
+- ")": [t: "⠜"]
- ">": [t: "⠀⠕⠀"]
- "<": [t: "⠀⠪⠀"]
- "%": [t: "⠼⠴"]
@@ -92,6 +94,10 @@
- "∕": [t: "⠠⠌"]
- "∖": [t: "⠀⠰⠤"]
- "∗": [t: "⠔"]
+- "·": [t: "⠄"]
+- "×": [t: "⠀⠦"]
+- "⋅": [t: "⠄"]
+- "": [t: "⠄"]
- "∘": [t: "⠴"]
- "√": [t: "⠩⠱"]
- "∛": [t: "⠩⠒⠱"]
diff --git a/tests/braille/Russian/russian.rs b/tests/braille/Russian/russian.rs
index 869bf972..7ccb33d4 100644
--- a/tests/braille/Russian/russian.rs
+++ b/tests/braille/Russian/russian.rs
@@ -29,6 +29,26 @@ fn cyrillic_text() -> Result<()> {
return Ok(());
}
+#[test]
+fn wikipedia_linear_parens() -> Result<()> {
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠼⠉⠄⠣⠼⠊⠀⠤⠼⠛⠜⠀⠶⠼⠋")?;
+ return Ok(());
+}
+
+#[test]
+fn source_arithmetic_examples() -> Result<()> {
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠼⠃⠙⠄⠼⠓⠁⠀⠶⠼⠁⠊⠙⠙")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠼⠛⠓⠉⠀⠲⠼⠊⠀⠶⠼⠓⠛")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠼⠁⠃⠀⠦⠼⠉⠑⠀⠶⠼⠙⠃⠚")?;
+ return Ok(());
+}
+
#[test]
fn nested_fraction_and_root() -> Result<()> {
let expr = r#""#;
From 5e4c6116ae07546cbda27f071fe2e817a0ced659 Mon Sep 17 00:00:00 2001
From: Danil <81031453+Kostenkov-2021@users.noreply.github.com>
Date: Wed, 3 Jun 2026 12:45:55 +0300
Subject: [PATCH 2/4] Braille - Latin and Greek letters fixes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This commit adds a layer of Latin and Greek alphabets for Russian mathematical Braille.
* In unicode.yaml Latin and Greek letters now go through the internal markers of the alphabetic mode.
• In braille.rs russian_cleanup turns these markers into real signs:
◦ Latin lowercase: ⠠
◦ Latin uppercase: ⠨
◦ Greek lowercase: ⠰
◦ Greek uppercase: ⠸
Added tests to russian.rs to x+A+y+B, the Latin letter after the number.
---
Rules/Braille/Russian/unicode.yaml | 212 ++++++++++++++---------------
src/braille.rs | 30 +++-
tests/braille/Russian/russian.rs | 30 +++-
3 files changed, 160 insertions(+), 112 deletions(-)
diff --git a/Rules/Braille/Russian/unicode.yaml b/Rules/Braille/Russian/unicode.yaml
index a0b0dc3c..8b72b2ba 100644
--- a/Rules/Braille/Russian/unicode.yaml
+++ b/Rules/Braille/Russian/unicode.yaml
@@ -20,59 +20,59 @@
- ";": [t: "⠠⠢"]
- "Ϳ": [t: "⠰⠊"]
- "·": [t: "⠰"]
-- "α": [t: "⠰⠁"]
-- "β": [t: "⠰⠃"]
-- "γ": [t: "⠰⠛"]
-- "δ": [t: "⠰⠙"]
-- "ε": [t: "⠰⠑"]
-- "ζ": [t: "⠰⠵"]
-- "η": [t: "⠰⠚"]
-- "θ": [t: "⠰⠓"]
-- "ι": [t: "⠰⠊"]
-- "κ": [t: "⠰⠅"]
-- "λ": [t: "⠰⠇"]
-- "μ": [t: "⠰⠍"]
-- "ν": [t: "⠰⠝"]
-- "ξ": [t: "⠰⠭"]
-- "ο": [t: "⠰⠕"]
-- "π": [t: "⠰⠏"]
-- "ρ": [t: "⠰⠗"]
-- "σ": [t: "⠰⠎"]
-- "τ": [t: "⠰⠞"]
-- "υ": [t: "⠰⠥"]
-- "φ": [t: "⠰⠋"]
-- "χ": [t: "⠰⠉"]
-- "ψ": [t: "⠰⠽"]
-- "ω": [t: "⠰⠺"]
-- "Α": [t: "⠸⠁"]
-- "Β": [t: "⠸⠃"]
-- "Γ": [t: "⠸⠛"]
-- "Δ": [t: "⠸⠙"]
-- "Ε": [t: "⠸⠑"]
-- "Ζ": [t: "⠸⠵"]
-- "Η": [t: "⠸⠚"]
-- "Θ": [t: "⠸⠓"]
-- "Ι": [t: "⠸⠊"]
-- "Κ": [t: "⠸⠅"]
-- "Λ": [t: "⠸⠇"]
-- "Μ": [t: "⠸⠍"]
-- "Ν": [t: "⠸⠝"]
-- "Ξ": [t: "⠸⠭"]
-- "Ο": [t: "⠸⠕"]
-- "Π": [t: "⠸⠏"]
-- "Ρ": [t: "⠸⠗"]
-- "Σ": [t: "⠸⠎"]
-- "Τ": [t: "⠸⠞"]
-- "Υ": [t: "⠸⠥"]
-- "Φ": [t: "⠸⠋"]
-- "Χ": [t: "⠸⠉"]
-- "Ψ": [t: "⠸⠽"]
-- "Ω": [t: "⠸⠺"]
-- "ϐ": [t: "⠰⠃"]
-- "ϑ": [t: "⠰⠓"]
-- "ϕ": [t: "⠰⠋"]
-- "ϖ": [t: "⠰⠏"]
-- "ϱ": [t: "⠰⠗"]
+- "α": [t: "g⠁"]
+- "β": [t: "g⠃"]
+- "γ": [t: "g⠛"]
+- "δ": [t: "g⠙"]
+- "ε": [t: "g⠑"]
+- "ζ": [t: "g⠵"]
+- "η": [t: "g⠚"]
+- "θ": [t: "g⠓"]
+- "ι": [t: "g⠊"]
+- "κ": [t: "g⠅"]
+- "λ": [t: "g⠇"]
+- "μ": [t: "g⠍"]
+- "ν": [t: "g⠝"]
+- "ξ": [t: "g⠭"]
+- "ο": [t: "g⠕"]
+- "π": [t: "g⠏"]
+- "ρ": [t: "g⠗"]
+- "σ": [t: "g⠎"]
+- "τ": [t: "g⠞"]
+- "υ": [t: "g⠥"]
+- "φ": [t: "g⠋"]
+- "χ": [t: "g⠉"]
+- "ψ": [t: "g⠽"]
+- "ω": [t: "g⠺"]
+- "Α": [t: "v⠁"]
+- "Β": [t: "v⠃"]
+- "Γ": [t: "v⠛"]
+- "Δ": [t: "v⠙"]
+- "Ε": [t: "v⠑"]
+- "Ζ": [t: "v⠵"]
+- "Η": [t: "v⠚"]
+- "Θ": [t: "v⠓"]
+- "Ι": [t: "v⠊"]
+- "Κ": [t: "v⠅"]
+- "Λ": [t: "v⠇"]
+- "Μ": [t: "v⠍"]
+- "Ν": [t: "v⠝"]
+- "Ξ": [t: "v⠭"]
+- "Ο": [t: "v⠕"]
+- "Π": [t: "v⠏"]
+- "Ρ": [t: "v⠗"]
+- "Σ": [t: "v⠎"]
+- "Τ": [t: "v⠞"]
+- "Υ": [t: "v⠥"]
+- "Φ": [t: "v⠋"]
+- "Χ": [t: "v⠉"]
+- "Ψ": [t: "v⠽"]
+- "Ω": [t: "v⠺"]
+- "ϐ": [t: "g⠃"]
+- "ϑ": [t: "g⠓"]
+- "ϕ": [t: "g⠋"]
+- "ϖ": [t: "g⠏"]
+- "ϱ": [t: "g⠗"]
- "′": [t: "⠔"]
- "″": [t: "⠔⠔"]
- "‴": [t: "⠔⠔⠔"]
@@ -97,7 +97,7 @@
- "·": [t: "⠄"]
- "×": [t: "⠀⠦"]
- "⋅": [t: "⠄"]
-- "": [t: "⠄"]
+- "": [t: ""]
- "∘": [t: "⠴"]
- "√": [t: "⠩⠱"]
- "∛": [t: "⠩⠒⠱"]
@@ -163,58 +163,58 @@
- "♮": [t: "⠻⠨⠝⠻"]
# Latin letters and digits used for mathematical identifiers.
-- "a": [t: "⠁"]
-- "A": [t: "C⠁"]
-- "b": [t: "⠃"]
-- "B": [t: "C⠃"]
-- "c": [t: "⠉"]
-- "C": [t: "C⠉"]
-- "d": [t: "⠙"]
-- "D": [t: "C⠙"]
-- "e": [t: "⠑"]
-- "E": [t: "C⠑"]
-- "f": [t: "⠋"]
-- "F": [t: "C⠋"]
-- "g": [t: "⠛"]
-- "G": [t: "C⠛"]
-- "h": [t: "⠓"]
-- "H": [t: "C⠓"]
-- "i": [t: "⠊"]
-- "I": [t: "C⠊"]
-- "j": [t: "⠚"]
-- "J": [t: "C⠚"]
-- "k": [t: "⠅"]
-- "K": [t: "C⠅"]
-- "l": [t: "⠇"]
-- "L": [t: "C⠇"]
-- "m": [t: "⠍"]
-- "M": [t: "C⠍"]
-- "n": [t: "⠝"]
-- "N": [t: "C⠝"]
-- "o": [t: "⠕"]
-- "O": [t: "C⠕"]
-- "p": [t: "⠏"]
-- "P": [t: "C⠏"]
-- "q": [t: "⠟"]
-- "Q": [t: "C⠟"]
-- "r": [t: "⠗"]
-- "R": [t: "C⠗"]
-- "s": [t: "⠎"]
-- "S": [t: "C⠎"]
-- "t": [t: "⠞"]
-- "T": [t: "C⠞"]
-- "u": [t: "⠥"]
-- "U": [t: "C⠥"]
-- "v": [t: "⠧"]
-- "V": [t: "C⠧"]
-- "w": [t: "⠺"]
-- "W": [t: "C⠺"]
-- "x": [t: "⠭"]
-- "X": [t: "C⠭"]
-- "y": [t: "⠽"]
-- "Y": [t: "C⠽"]
-- "z": [t: "⠵"]
-- "Z": [t: "C⠵"]
+- "a": [t: "l⠁"]
+- "A": [t: "u⠁"]
+- "b": [t: "l⠃"]
+- "B": [t: "u⠃"]
+- "c": [t: "l⠉"]
+- "C": [t: "u⠉"]
+- "d": [t: "l⠙"]
+- "D": [t: "u⠙"]
+- "e": [t: "l⠑"]
+- "E": [t: "u⠑"]
+- "f": [t: "l⠋"]
+- "F": [t: "u⠋"]
+- "g": [t: "l⠛"]
+- "G": [t: "u⠛"]
+- "h": [t: "l⠓"]
+- "H": [t: "u⠓"]
+- "i": [t: "l⠊"]
+- "I": [t: "u⠊"]
+- "j": [t: "l⠚"]
+- "J": [t: "u⠚"]
+- "k": [t: "l⠅"]
+- "K": [t: "u⠅"]
+- "l": [t: "l⠇"]
+- "L": [t: "u⠇"]
+- "m": [t: "l⠍"]
+- "M": [t: "u⠍"]
+- "n": [t: "l⠝"]
+- "N": [t: "u⠝"]
+- "o": [t: "l⠕"]
+- "O": [t: "u⠕"]
+- "p": [t: "l⠏"]
+- "P": [t: "u⠏"]
+- "q": [t: "l⠟"]
+- "Q": [t: "u⠟"]
+- "r": [t: "l⠗"]
+- "R": [t: "u⠗"]
+- "s": [t: "l⠎"]
+- "S": [t: "u⠎"]
+- "t": [t: "l⠞"]
+- "T": [t: "u⠞"]
+- "u": [t: "l⠥"]
+- "U": [t: "u⠥"]
+- "v": [t: "l⠧"]
+- "V": [t: "u⠧"]
+- "w": [t: "l⠺"]
+- "W": [t: "u⠺"]
+- "x": [t: "l⠭"]
+- "X": [t: "u⠭"]
+- "y": [t: "l⠽"]
+- "Y": [t: "u⠽"]
+- "z": [t: "l⠵"]
+- "Z": [t: "u⠵"]
- "0": [t: "N⠚"]
- "1": [t: "N⠁"]
- "2": [t: "N⠃"]
diff --git a/src/braille.rs b/src/braille.rs
index 6b259776..ec26cb2d 100644
--- a/src/braille.rs
+++ b/src/braille.rs
@@ -2183,7 +2183,8 @@ fn russian_cleanup(_pref_manager: Ref, raw_braille: String) -
previous_char_was_digit = matches!(ch, '⠚' | '⠁' | '⠃' | '⠉' | '⠙' | '⠑' | '⠋' | '⠛' | '⠓' | '⠊');
}
- let result = REPLACE_INDICATORS.replace_all(&raw_braille_without_repeated_number_indicators, |cap: &Captures| {
+ let result = add_russian_alphabet_indicators(&raw_braille_without_repeated_number_indicators);
+ let result = REPLACE_INDICATORS.replace_all(&result, |cap: &Captures| {
match &cap[0] {
"B" => "⠸",
"C" => "⠠",
@@ -2198,6 +2199,33 @@ fn russian_cleanup(_pref_manager: Ref, raw_braille: String) -
return COLLAPSE_SPACES.replace_all(&result, "⠀")
.trim_matches('⠀')
.to_string();
+
+ fn add_russian_alphabet_indicators(raw_braille: &str) -> String {
+ let mut result = String::with_capacity(raw_braille.len());
+ let mut alphabet_mode = None;
+ for ch in raw_braille.chars() {
+ match ch {
+ 'l' | 'u' | 'g' | 'v' => {
+ if alphabet_mode != Some(ch) {
+ result.push_str(match ch {
+ 'l' => "⠠", // Latin lowercase: dots 6
+ 'u' => "⠨", // Latin uppercase: dots 4-6
+ 'g' => "⠰", // Greek lowercase: dots 5-6
+ 'v' => "⠸", // Greek uppercase: dots 4-5-6
+ _ => unreachable!(),
+ });
+ alphabet_mode = Some(ch);
+ }
+ },
+ 'C' | 'N' | '#' => {
+ alphabet_mode = None;
+ result.push(ch);
+ },
+ _ => result.push(ch),
+ }
+ }
+ return result;
+ }
}
#[allow(non_snake_case)]
diff --git a/tests/braille/Russian/russian.rs b/tests/braille/Russian/russian.rs
index 7ccb33d4..589ab986 100644
--- a/tests/braille/Russian/russian.rs
+++ b/tests/braille/Russian/russian.rs
@@ -11,14 +11,14 @@ fn numbers_and_operators() -> Result<()> {
#[test]
fn fraction() -> Result<()> {
let expr = r#""#;
- test_braille("Russian", expr, "⠆⠭⠀⠳⠼⠃⠰")?;
+ test_braille("Russian", expr, "⠆⠠⠭⠀⠳⠼⠃⠰")?;
return Ok(());
}
#[test]
fn scripts_and_root() -> Result<()> {
let expr = r#""#;
- test_braille("Russian", expr, "⠭⠌⠼⠃⠱⠀⠖⠩⠱⠽⠹")?;
+ test_braille("Russian", expr, "⠠⠭⠌⠼⠃⠱⠀⠖⠩⠱⠠⠽⠹")?;
return Ok(());
}
@@ -30,7 +30,7 @@ fn cyrillic_text() -> Result<()> {
}
#[test]
-fn wikipedia_linear_parens() -> Result<()> {
+fn wikipedia_linear_parens_flat() -> Result<()> {
let expr = r#""#;
test_braille("Russian", expr, "⠼⠉⠄⠣⠼⠊⠀⠤⠼⠛⠜⠀⠶⠼⠋")?;
return Ok(());
@@ -52,7 +52,27 @@ fn source_arithmetic_examples() -> Result<()> {
#[test]
fn nested_fraction_and_root() -> Result<()> {
let expr = r#""#;
- test_braille("Russian", expr, "⠆⠭⠀⠖⠩⠱⠆⠼⠁⠀⠳⠽⠰⠹⠀⠳⠭⠀⠤⠽⠰")?;
+ test_braille("Russian", expr, "⠆⠠⠭⠀⠖⠩⠱⠆⠼⠁⠀⠳⠠⠽⠰⠹⠀⠳⠭⠀⠤⠽⠰")?;
+ return Ok(());
+}
+
+#[test]
+fn latin_alphabet_indicators() -> Result<()> {
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠠⠭⠀⠖⠨⠁⠀⠖⠠⠽⠀⠖⠨⠃⠀⠶⠠⠭⠀⠖⠽⠀⠖⠨⠁⠀⠖⠃")?;
+ return Ok(());
+}
+
+#[test]
+fn alphabet_indicators_after_numbers_and_greek() -> Result<()> {
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠼⠃⠄⠠⠭⠀⠖⠼⠁⠑⠀⠶⠼⠃⠉")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠨⠇⠀⠶⠼⠃⠰⠏⠠⠗")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠰⠁⠀⠖⠃⠀⠶⠸⠁⠀⠖⠃")?;
return Ok(());
}
@@ -73,6 +93,6 @@ fn wikipedia_linear_parens() -> Result<()> {
#[test]
fn wikipedia_sqrt() -> Result<()> {
let expr = r#""#;
- test_braille("Russian", expr, "⠩⠱⠼⠁⠚⠚⠚⠚⠀⠪⠀⠼⠁⠚⠁")?;
+ test_braille("Russian", expr, "⠩⠱⠼⠁⠚⠚⠚⠚⠹⠀⠪⠀⠼⠁⠚⠁")?;
return Ok(());
}
From 9c99bb51da12deda8a4dec418e11012416af9091 Mon Sep 17 00:00:00 2001
From: Danil <81031453+Kostenkov-2021@users.noreply.github.com>
Date: Wed, 3 Jun 2026 13:00:38 +0300
Subject: [PATCH 3/4] Braille - Roots, powers and scripts
This commit adds Roots, powers and scripts according to the Russian math Braille specs.
---
Rules/Braille/Russian/Russian_Rules.yaml | 63 +++++++++++++++++++++++-
Rules/Braille/Russian/unicode.yaml | 12 +++++
tests/braille/Russian/russian.rs | 22 +++++++--
3 files changed, 93 insertions(+), 4 deletions(-)
diff --git a/Rules/Braille/Russian/Russian_Rules.yaml b/Rules/Braille/Russian/Russian_Rules.yaml
index 1effd8c4..f717e6b6 100644
--- a/Rules/Braille/Russian/Russian_Rules.yaml
+++ b/Rules/Braille/Russian/Russian_Rules.yaml
@@ -67,7 +67,7 @@
-
name: default
tag: mroot
- match: "."
+ match: "not(*[2][self::m:mn and translate(., '0123456789', '')=''])"
replace:
- t: "⠩"
- x: "*[2]"
@@ -75,6 +75,43 @@
- x: "*[1]"
- t: "⠹"
+-
+ name: integer-index
+ tag: mroot
+ match: "*[2][self::m:mn and translate(., '0123456789', '')='']"
+ replace:
+ - t: "⠩"
+ - x: "BrailleChars(translate(*[2], '0123456789', '\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009'), 'Russian')"
+ - t: "⠱"
+ - x: "*[1]"
+ - t: "⠹"
+
+-
+ name: simple-numeric
+ tag: mfrac
+ match:
+ - "*[1][self::m:mn and translate(., '0123456789', '')=''] and"
+ - "*[2][self::m:mn and translate(., '0123456789', '')='']"
+ replace:
+ - x: "*[1]"
+ - x: "BrailleChars(translate(*[2], '0123456789', '\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009'), 'Russian')"
+
+-
+ name: simple-algebraic
+ tag: mfrac
+ match:
+ - "(*[1][self::m:mi] or *[1][self::m:mn and translate(., '0123456789', '')='']) and"
+ - "(*[2][self::m:mi] or *[2][self::m:mn and translate(., '0123456789', '')=''])"
+ replace:
+ - x: "*[1]"
+ - t: "⠳"
+ - test:
+ if: "*[2][self::m:mn]"
+ then:
+ - x: "BrailleChars(translate(*[2], '0123456789', '\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009'), 'Russian')"
+ else:
+ - x: "*[2]"
+
-
name: default
tag: mfrac
@@ -163,6 +200,18 @@
match: "*[2][translate(., \"'*`ª°²³´¹º′″‴‵‶‷⁗\",'')='']"
replace: [x: "*"]
+-
+ name: integer
+ tag: [msub, munder]
+ match: "*[2][self::m:mn and translate(., '0123456789', '')='']"
+ replace:
+ - x: "*[1]"
+ - test:
+ if: "self::m:munder"
+ then: [t: "⠨⠡"]
+ else: [t: "⠡"]
+ - x: "BrailleChars(translate(*[2], '0123456789', '\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009'), 'Russian')"
+
-
name: default
tag: [msub, munder]
@@ -176,6 +225,18 @@
- x: "*[2]"
- t: "⠱"
+-
+ name: integer
+ tag: [msup, mover]
+ match: "*[2][self::m:mn and translate(., '0123456789', '')='']"
+ replace:
+ - x: "*[1]"
+ - test:
+ if: "self::m:mover"
+ then: [t: "⠨⠌"]
+ else: [t: "⠌"]
+ - x: "BrailleChars(translate(*[2], '0123456789', '\ue000\ue001\ue002\ue003\ue004\ue005\ue006\ue007\ue008\ue009'), 'Russian')"
+
-
name: default
tag: [msup, mover]
diff --git a/Rules/Braille/Russian/unicode.yaml b/Rules/Braille/Russian/unicode.yaml
index 8b72b2ba..4407eb8e 100644
--- a/Rules/Braille/Russian/unicode.yaml
+++ b/Rules/Braille/Russian/unicode.yaml
@@ -226,6 +226,18 @@
- "8": [t: "N⠓"]
- "9": [t: "N⠊"]
+# Lowered digits used in denominators and integer scripts.
+- "\ue000": [t: "⠴"]
+- "\ue001": [t: "⠂"]
+- "\ue002": [t: "⠆"]
+- "\ue003": [t: "⠒"]
+- "\ue004": [t: "⠲"]
+- "\ue005": [t: "⠢"]
+- "\ue006": [t: "⠖"]
+- "\ue007": [t: "⠶"]
+- "\ue008": [t: "⠦"]
+- "\ue009": [t: "⠔"]
+
# Russian literary braille letters for mtext and Cyrillic identifiers.
- "а": [t: "⠁"]
- "А": [t: "C⠁"]
diff --git a/tests/braille/Russian/russian.rs b/tests/braille/Russian/russian.rs
index 589ab986..4cdf9796 100644
--- a/tests/braille/Russian/russian.rs
+++ b/tests/braille/Russian/russian.rs
@@ -11,14 +11,14 @@ fn numbers_and_operators() -> Result<()> {
#[test]
fn fraction() -> Result<()> {
let expr = r#""#;
- test_braille("Russian", expr, "⠆⠠⠭⠀⠳⠼⠃⠰")?;
+ test_braille("Russian", expr, "⠠⠭⠳⠆")?;
return Ok(());
}
#[test]
fn scripts_and_root() -> Result<()> {
let expr = r#""#;
- test_braille("Russian", expr, "⠠⠭⠌⠼⠃⠱⠀⠖⠩⠱⠠⠽⠹")?;
+ test_braille("Russian", expr, "⠠⠭⠌⠆⠀⠖⠩⠱⠽⠹")?;
return Ok(());
}
@@ -52,7 +52,23 @@ fn source_arithmetic_examples() -> Result<()> {
#[test]
fn nested_fraction_and_root() -> Result<()> {
let expr = r#""#;
- test_braille("Russian", expr, "⠆⠠⠭⠀⠖⠩⠱⠆⠼⠁⠀⠳⠠⠽⠰⠹⠀⠳⠭⠀⠤⠽⠰")?;
+ test_braille("Russian", expr, "⠆⠠⠭⠀⠖⠩⠱⠼⠁⠳⠠⠽⠹⠀⠳⠭⠀⠤⠽⠰")?;
+ return Ok(());
+}
+
+#[test]
+fn source_simple_fractions_scripts_roots() -> Result<()> {
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠼⠁⠆")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠠⠁⠳⠒")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠠⠃⠡⠶")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠩⠒⠱⠠⠭⠹")?;
return Ok(());
}
From ed3176789a8662e1286f36225574e43060aaac46 Mon Sep 17 00:00:00 2001
From: Danil <81031453+Kostenkov-2021@users.noreply.github.com>
Date: Wed, 3 Jun 2026 13:14:46 +0300
Subject: [PATCH 4/4] Update Russian Braille rules and mappings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fix YAML replace syntax and extend Russian braille rules: add chemical-formula-operator-bond and prefix-geometry-ops rules, broaden function-name matching (include tg/ctg variants) and add separator markers. Update unicode mappings (degree sign, invisible characters, conditional ∪ mapping, parallel/arrow glyphs) and adjust several function/operator braille outputs. Add/expand tests to cover functions, geometry, matrices and chemical formulas to validate the changes.
---
Rules/Braille/Russian/Russian_Rules.yaml | 62 ++++++++++++++++--------
Rules/Braille/Russian/unicode.yaml | 16 +++++-
tests/braille/Russian/russian.rs | 35 +++++++++++++
3 files changed, 92 insertions(+), 21 deletions(-)
diff --git a/Rules/Braille/Russian/Russian_Rules.yaml b/Rules/Braille/Russian/Russian_Rules.yaml
index f717e6b6..6ac752bc 100644
--- a/Rules/Braille/Russian/Russian_Rules.yaml
+++ b/Rules/Braille/Russian/Russian_Rules.yaml
@@ -162,9 +162,7 @@
name: default
tag: mtable
match: "."
- replace:
- - t: "⠞⠃⠇"
- - x: "*"
+ replace: [x: "*"]
-
name: default
@@ -283,6 +281,30 @@
- x: "*"
- t: "⠜"
+-
+ name: chemical-formula-operator-bond
+ tag: mo
+ match: "@data-chemical-bond"
+ replace:
+ - test:
+ - if: ".='-' or .=':'"
+ then: [t: "⠤"]
+ - else_if: ".='=' or .='∷'"
+ then: [t: "⠦"]
+ - else_if: ".='≡'"
+ then: [t: "⠿"]
+ else: [x: "text()"]
+
+-
+ name: prefix-geometry-ops
+ tag: mo
+ match:
+ - "parent::*[count(*) = 2 and name()='mrow' and not(preceding-sibling::*)] and"
+ - "( .='∠' or .='△' or .='∪' )"
+ replace:
+ - x: "text()"
+ - t: "#"
+
-
name: default
tag: mo
@@ -300,39 +322,41 @@
-
name: functions
tag: mi
- match: "IsInDefinition(., 'Speech', 'FunctionNames')"
+ match:
+ - "IsInDefinition(., 'Speech', 'FunctionNames') or"
+ - ".='tg' or .='ctg' or .='arctg' or .='arcctg'"
replace:
- test:
- if: ".='arcsin'"
- then: [t: "⠫⠁⠎"]
+ then: [t: "⠫⠁⠎#"]
- else_if: ".='arccos'"
- then: [t: "⠫⠁⠉"]
+ then: [t: "⠫⠁⠉#"]
- else_if: ".='arctg' or .='arctan'"
- then: [t: "⠫⠁⠞"]
+ then: [t: "⠫⠁⠞#"]
- else_if: ".='arcctg' or .='arccotan' or .='arccot'"
- then: [t: "⠫⠁⠉⠞"]
+ then: [t: "⠫⠁⠉⠞#"]
- else_if: ".='sin'"
- then: [t: "⠫⠎"]
+ then: [t: "⠫⠎#"]
- else_if: ".='cos'"
- then: [t: "⠫⠉"]
+ then: [t: "⠫⠉#"]
- else_if: ".='tg' or .='tan'"
- then: [t: "⠫⠞"]
+ then: [t: "⠫⠞#"]
- else_if: ".='ctg' or .='cotan' or .='cot'"
- then: [t: "⠫⠉⠞"]
+ then: [t: "⠫⠉⠞#"]
- else_if: ".='log'"
- then: [t: "⠫⠇"]
+ then: [t: "⠫⠇#"]
- else_if: ".='ln'"
- then: [t: "⠫⠇⠝"]
+ then: [t: "⠫⠇⠝#"]
- else_if: ".='lg'"
- then: [t: "⠫⠇⠛"]
+ then: [t: "⠫⠇⠛#"]
- else_if: ".='lim'"
- then: [t: "⠫⠇⠍"]
+ then: [t: "⠫⠇⠍#"]
- else_if: ".='min'"
- then: [t: "⠫⠍⠝"]
+ then: [t: "⠫⠍⠝#"]
- else_if: ".='max'"
- then: [t: "⠫⠍⠭"]
+ then: [t: "⠫⠍⠭#"]
- else_if: ".='exp'"
- then: [t: "⠫⠑"]
+ then: [t: "⠫⠑#"]
else: [x: "BrailleChars(., 'Russian')"]
-
diff --git a/Rules/Braille/Russian/unicode.yaml b/Rules/Braille/Russian/unicode.yaml
index 4407eb8e..885f51a6 100644
--- a/Rules/Braille/Russian/unicode.yaml
+++ b/Rules/Braille/Russian/unicode.yaml
@@ -76,6 +76,7 @@
- "′": [t: "⠔"]
- "″": [t: "⠔⠔"]
- "‴": [t: "⠔⠔⠔"]
+- "°": [t: "⠨⠴"]
- "∀": [t: "⠫⠄"]
- "∂": [t: "⠹"]
- "∃": [t: "⠫⠢"]
@@ -97,7 +98,10 @@
- "·": [t: "⠄"]
- "×": [t: "⠀⠦"]
- "⋅": [t: "⠄"]
+- "": [t: ""]
- "": [t: ""]
+- "": [t: ""]
+- "": [t: ""]
- "∘": [t: "⠴"]
- "√": [t: "⠩⠱"]
- "∛": [t: "⠩⠒⠱"]
@@ -106,11 +110,15 @@
- "∠": [t: "⠸⠪"]
- "∣": [t: "⠸"]
- "∤": [t: "⠀⠼⠀"]
-- "∥": [t: "⠸⠸"]
+- "∥": [t: "⠸⠸#"]
- "∧": [t: "⠀⠰⠢"]
- "∨": [t: "⠀⠰⠔"]
- "∩": [t: "⠀⠰⠲"]
-- "∪": [t: "⠀⠰⠴"]
+- "∪":
+ - test:
+ if: "following-sibling::*[1][self::m:mi]"
+ then: [t: "⠸⠜"]
+ else: [t: "⠀⠰⠴"]
- "∫": [t: "⠮"]
- "∬": [t: "⠮⠮"]
- "∭": [t: "⠮⠮⠮"]
@@ -159,6 +167,10 @@
- "⋰": [t: "⠠⠲⠲⠲"]
- "⋱": [t: "⠠⠲⠲⠲"]
- "△": [t: "⠸⠙"]
+- "→": [t: "⠀⠒⠕"]
+- "⟶": [t: "⠀⠒⠕"]
+- "←": [t: "⠀⠦⠶"]
+- "⟵": [t: "⠀⠦⠶"]
- "◻": [t: "⠶"]
- "♮": [t: "⠻⠨⠝⠻"]
diff --git a/tests/braille/Russian/russian.rs b/tests/braille/Russian/russian.rs
index 4cdf9796..313c4532 100644
--- a/tests/braille/Russian/russian.rs
+++ b/tests/braille/Russian/russian.rs
@@ -112,3 +112,38 @@ fn wikipedia_sqrt() -> Result<()> {
test_braille("Russian", expr, "⠩⠱⠼⠁⠚⠚⠚⠚⠹⠀⠪⠀⠼⠁⠚⠁")?;
return Ok(());
}
+
+#[test]
+fn source_functions_logs_derivatives() -> Result<()> {
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠫⠉⠰⠁")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠫⠞⠠⠭⠄⠫⠉⠞⠠⠭⠀⠶⠼⠁")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠫⠇⠡⠠⠭⠱⠽⠄⠫⠇⠡⠠⠽⠱⠭⠀⠶⠼⠁")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠠⠽⠔⠣⠭⠜⠀⠶⠋⠣⠭⠜")?;
+ return Ok(());
+}
+
+#[test]
+fn source_geometry_matrix_chemistry() -> Result<()> {
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠸⠪⠨⠁⠃⠉⠀⠶⠼⠁⠑⠨⠴⠼⠉⠚⠔⠼⠁⠃⠔⠔")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠨⠁⠃⠸⠸⠨⠉⠙")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠣⠠⠁⠀⠃⠨⠳⠉⠀⠙⠜")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠨⠓⠡⠆⠕")?;
+
+ let expr = r#""#;
+ test_braille("Russian", expr, "⠨⠓⠡⠆⠉⠦⠉⠓⠡⠆")?;
+ return Ok(());
+}