summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbluebear94 <uruwi@protonmail.com>2023-08-23 08:55:43 -0400
committerGitHub <noreply@github.com>2023-08-23 14:55:43 +0200
commit3fcb5ea73cbae20500f4695685df4caf0071d45a (patch)
treef61e85c8a6f8da8810e17de24af07e95dd0694b6
parentb59b8bfb352f57d50acd67a048baa8390d37e374 (diff)
Render opening smart quote after another opening quote of a different type (#1559)
-rw-r--r--crates/typst-library/src/layout/par.rs2
-rw-r--r--crates/typst-library/src/text/quotes.rs18
-rw-r--r--tests/ref/text/quotes.pngbin77389 -> 80933 bytes
-rw-r--r--tests/typ/text/quotes.typ6
4 files changed, 23 insertions, 3 deletions
diff --git a/crates/typst-library/src/layout/par.rs b/crates/typst-library/src/layout/par.rs
index 23579105..d3cd6cbf 100644
--- a/crates/typst-library/src/layout/par.rs
+++ b/crates/typst-library/src/layout/par.rs
@@ -642,7 +642,7 @@ fn collect<'a>(
};
if let Some(last) = full.chars().last() {
- quoter.last(last);
+ quoter.last(last, child.is::<SmartQuoteElem>());
}
spans.push(segment.len(), child.span());
diff --git a/crates/typst-library/src/text/quotes.rs b/crates/typst-library/src/text/quotes.rs
index bc3d00a0..cf4a03d5 100644
--- a/crates/typst-library/src/text/quotes.rs
+++ b/crates/typst-library/src/text/quotes.rs
@@ -66,6 +66,8 @@ pub struct Quoter {
expect_opening: bool,
/// Whether the last character was numeric.
last_num: bool,
+ /// The previous type of quote character, if it was an opening quote.
+ prev_quote_type: Option<bool>,
}
impl Quoter {
@@ -75,13 +77,17 @@ impl Quoter {
quote_depth: 0,
expect_opening: true,
last_num: false,
+ prev_quote_type: None,
}
}
/// Process the last seen character.
- pub fn last(&mut self, c: char) {
+ pub fn last(&mut self, c: char, is_quote: bool) {
self.expect_opening = is_ignorable(c) || is_opening_bracket(c);
self.last_num = c.is_numeric();
+ if !is_quote {
+ self.prev_quote_type = None;
+ }
}
/// Process and substitute a quote.
@@ -92,8 +98,16 @@ impl Quoter {
peeked: Option<char>,
) -> &'a str {
let peeked = peeked.unwrap_or(' ');
- if self.expect_opening {
+ let mut expect_opening = self.expect_opening;
+ if let Some(prev_double) = self.prev_quote_type.take() {
+ if double != prev_double {
+ expect_opening = true;
+ }
+ }
+
+ if expect_opening {
self.quote_depth += 1;
+ self.prev_quote_type = Some(double);
quotes.open(double)
} else if self.quote_depth > 0
&& (peeked.is_ascii_punctuation() || is_ignorable(peeked))
diff --git a/tests/ref/text/quotes.png b/tests/ref/text/quotes.png
index 8d3702b2..757e7478 100644
--- a/tests/ref/text/quotes.png
+++ b/tests/ref/text/quotes.png
Binary files differ
diff --git a/tests/typ/text/quotes.typ b/tests/typ/text/quotes.typ
index ec8c5e6a..e8a56b4d 100644
--- a/tests/typ/text/quotes.typ
+++ b/tests/typ/text/quotes.typ
@@ -60,3 +60,9 @@ He's told some books contain questionable "example text".
"She suddenly started speaking french: #text(lang: "fr")['Je suis une banane.']" Roman told me.
Some people's thought on this would be #[#set smartquote(enabled: false); "strange."]
+
+---
+// Test nested double and single quotes.
+"'test statement'" \
+"'test' statement" \
+"statement 'test'"