summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorT0mstone <39707032+T0mstone@users.noreply.github.com>2023-07-06 13:52:24 +0200
committerGitHub <noreply@github.com>2023-07-06 13:52:24 +0200
commit46a6f92bf341268a1369a6034f1bc32408aedd9e (patch)
treec6227588a8b6f9faa1fab7cb44fccf38b6fb897a /crates
parent07553cbe71cab60d1a29b72dc2ffbf25f0f3619c (diff)
Add alternative smartquotes (#1631)
Diffstat (limited to 'crates')
-rw-r--r--crates/typst-library/src/layout/par.rs6
-rw-r--r--crates/typst-library/src/text/quotes.rs31
2 files changed, 31 insertions, 6 deletions
diff --git a/crates/typst-library/src/layout/par.rs b/crates/typst-library/src/layout/par.rs
index 6b862a23..fe86f62a 100644
--- a/crates/typst-library/src/layout/par.rs
+++ b/crates/typst-library/src/layout/par.rs
@@ -598,7 +598,11 @@ fn collect<'a>(
if SmartQuoteElem::enabled_in(styles) {
let lang = TextElem::lang_in(styles);
let region = TextElem::region_in(styles);
- let quotes = Quotes::from_lang(lang, region);
+ let quotes = Quotes::from_lang(
+ lang,
+ region,
+ SmartQuoteElem::alternative_in(styles),
+ );
let peeked = iter.peek().and_then(|child| {
let child = if let Some((child, _)) = child.to_styled() {
child
diff --git a/crates/typst-library/src/text/quotes.rs b/crates/typst-library/src/text/quotes.rs
index d0798064..bc3d00a0 100644
--- a/crates/typst-library/src/text/quotes.rs
+++ b/crates/typst-library/src/text/quotes.rs
@@ -42,6 +42,19 @@ pub struct SmartQuoteElem {
/// ```
#[default(true)]
pub enabled: bool,
+
+ /// Whether to use alternative quotes.
+ ///
+ /// Does nothing for languages that don't have alternative quotes.
+ ///
+ /// ```example
+ /// #set text(lang: "de")
+ /// #set smartquote(alternative: true)
+ ///
+ /// "Das ist in anderen Anführungszeichen."
+ /// ```
+ #[default(false)]
+ pub alternative: bool,
}
/// State machine for smart quote substitution.
@@ -135,17 +148,25 @@ impl<'s> Quotes<'s> {
/// Norwegian.
///
/// For unknown languages, the English quotes are used.
- pub fn from_lang(lang: Lang, region: Option<Region>) -> Self {
+ pub fn from_lang(lang: Lang, region: Option<Region>, alternative: bool) -> Self {
let region = region.as_ref().map(Region::as_str);
+
+ let low_high = ("‚", "‘", "„", "“");
+
let (single_open, single_close, double_open, double_close) = match lang.as_str() {
- "de" if matches!(region, Some("CH" | "LI")) => ("‹", "›", "«", "»"),
- "cs" | "da" | "de" | "et" | "is" | "lt" | "lv" | "sk" | "sl" => {
- ("‚", "‘", "„", "“")
- }
+ "de" if matches!(region, Some("CH" | "LI")) => match alternative {
+ false => ("‹", "›", "«", "»"),
+ true => low_high,
+ },
+ "cs" | "da" | "de" | "sk" | "sl" if alternative => ("›", "‹", "»", "«"),
+ "cs" | "da" | "de" | "et" | "is" | "lt" | "lv" | "sk" | "sl" => low_high,
+ "fr" | "ru" if alternative => return Self::default(),
"fr" => ("‹\u{00A0}", "\u{00A0}›", "«\u{00A0}", "\u{00A0}»"),
+ "fi" | "sv" if alternative => ("’", "’", "»", "»"),
"bs" | "fi" | "sv" => ("’", "’", "”", "”"),
"es" if matches!(region, Some("ES") | None) => ("“", "”", "«", "»"),
"hu" | "pl" | "ro" => ("’", "’", "„", "”"),
+ "no" | "nb" | "nn" if alternative => low_high,
"ru" | "no" | "nb" | "nn" | "ua" => ("’", "’", "«", "»"),
_ if lang.dir() == Dir::RTL => ("’", "‘", "”", "“"),
_ => return Self::default(),