mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Add SymbolElem to realization
This commit is contained in:
parent
fecdc39846
commit
7838da02ec
@ -221,7 +221,7 @@ impl<'a, 'x, 'y, 'z, 's> Grouped<'a, 'x, 'y, 'z, 's> {
|
||||
/// Handles an arbitrary piece of content during realization.
|
||||
fn visit<'a>(
|
||||
s: &mut State<'a, '_, '_, '_>,
|
||||
mut content: &'a Content,
|
||||
content: &'a Content,
|
||||
styles: StyleChain<'a>,
|
||||
) -> SourceResult<()> {
|
||||
// Tags can always simply be pushed.
|
||||
@ -230,12 +230,6 @@ fn visit<'a>(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(elem) = content.to_packed::<SymbolElem>() {
|
||||
// This is a hack to avoid affecting layout that will be replaced in a
|
||||
// later commit.
|
||||
content = Box::leak(Box::new(TextElem::packed(elem.text.to_string())));
|
||||
}
|
||||
|
||||
// Transformations for math content based on the realization kind. Needs
|
||||
// to happen before show rules.
|
||||
if visit_math_rules(s, content, styles)? {
|
||||
@ -247,7 +241,7 @@ fn visit<'a>(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Recurse into sequences. Styled elements and sequences can currently also
|
||||
// Recurse into sequences. Styled elements and sequences can currently also
|
||||
// have labels, so this needs to happen before they are handled.
|
||||
if let Some(sequence) = content.to_packed::<SequenceElem>() {
|
||||
for elem in &sequence.children {
|
||||
@ -301,7 +295,14 @@ fn visit_math_rules<'a>(
|
||||
// In normal realization, we apply regex show rules to consecutive
|
||||
// textual elements via `TEXTUAL` grouping. However, in math, this is
|
||||
// not desirable, so we just do it on a per-element basis.
|
||||
if let Some(elem) = content.to_packed::<TextElem>() {
|
||||
if let Some(elem) = content.to_packed::<SymbolElem>() {
|
||||
if let Some(m) =
|
||||
find_regex_match_in_str(elem.text.encode_utf8(&mut [0; 4]), styles)
|
||||
{
|
||||
visit_regex_match(s, &[(content, styles)], m)?;
|
||||
return Ok(true);
|
||||
}
|
||||
} else if let Some(elem) = content.to_packed::<TextElem>() {
|
||||
if let Some(m) = find_regex_match_in_str(&elem.text, styles) {
|
||||
visit_regex_match(s, &[(content, styles)], m)?;
|
||||
return Ok(true);
|
||||
@ -314,6 +315,14 @@ fn visit_math_rules<'a>(
|
||||
visit(s, s.store(eq), styles)?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// Symbols in non-math content transparently convert to `TextElem` so we
|
||||
// don't have to handle them in non-math layout.
|
||||
if let Some(elem) = content.to_packed::<SymbolElem>() {
|
||||
let text = TextElem::packed(elem.text).spanned(elem.span());
|
||||
visit(s, s.store(text), styles)?;
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
@ -792,7 +801,7 @@ static HTML_DOCUMENT_RULES: &[&GroupingRule] =
|
||||
/// Grouping rules used in HTML fragment realization.
|
||||
static HTML_FRAGMENT_RULES: &[&GroupingRule] = &[&TEXTUAL, &CITES, &LIST, &ENUM, &TERMS];
|
||||
|
||||
/// Grouping rules used in math realizatio.
|
||||
/// Grouping rules used in math realization.
|
||||
static MATH_RULES: &[&GroupingRule] = &[&CITES, &LIST, &ENUM, &TERMS];
|
||||
|
||||
/// Groups adjacent textual elements for text show rule application.
|
||||
@ -801,6 +810,9 @@ static TEXTUAL: GroupingRule = GroupingRule {
|
||||
tags: true,
|
||||
trigger: |content, _| {
|
||||
let elem = content.elem();
|
||||
// Note that `SymbolElem` converts into `TextElem` before textual show
|
||||
// rules run, and we apply textual rules to elements manually during
|
||||
// math realization, so we don't check for it here.
|
||||
elem == TextElem::elem()
|
||||
|| elem == LinebreakElem::elem()
|
||||
|| elem == SmartQuoteElem::elem()
|
||||
@ -1124,7 +1136,16 @@ fn visit_regex_match<'a>(
|
||||
m: RegexMatch<'a>,
|
||||
) -> SourceResult<()> {
|
||||
let match_range = m.offset..m.offset + m.text.len();
|
||||
let piece = TextElem::packed(m.text);
|
||||
|
||||
// Replace with the correct intuitive element kind: if matching against a
|
||||
// lone symbol, return a `SymbolElem`, otherwise return a newly composed
|
||||
// `TextElem`. We should only match against a `SymbolElem` during math
|
||||
// realization (`RealizationKind::Math`).
|
||||
let piece = match elems {
|
||||
&[(lone, _)] if lone.is::<SymbolElem>() => lone.clone(),
|
||||
_ => TextElem::packed(m.text),
|
||||
};
|
||||
|
||||
let context = Context::new(None, Some(m.styles));
|
||||
let output = m.recipe.apply(s.engine, context.track(), piece)?;
|
||||
|
||||
@ -1147,10 +1168,16 @@ fn visit_regex_match<'a>(
|
||||
continue;
|
||||
}
|
||||
|
||||
// At this point, we can have a `TextElem`, `SpaceElem`,
|
||||
// At this point, we can have a `TextElem`, `SymbolElem`, `SpaceElem`,
|
||||
// `LinebreakElem`, or `SmartQuoteElem`. We now determine the range of
|
||||
// the element.
|
||||
let len = content.to_packed::<TextElem>().map_or(1, |elem| elem.text.len());
|
||||
let len = if let Some(elem) = content.to_packed::<TextElem>() {
|
||||
elem.text.len()
|
||||
} else if let Some(elem) = content.to_packed::<SymbolElem>() {
|
||||
elem.text.len_utf8()
|
||||
} else {
|
||||
1 // The rest are Ascii, so just one byte.
|
||||
};
|
||||
let elem_range = cursor..cursor + len;
|
||||
|
||||
// If the element starts before the start of match, visit it fully or
|
||||
|
BIN
tests/ref/cases-content-symbol.png
Normal file
BIN
tests/ref/cases-content-symbol.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 191 B |
BIN
tests/ref/cases-content-text.png
Normal file
BIN
tests/ref/cases-content-text.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 184 B |
@ -6,6 +6,14 @@
|
||||
#test(upper(memes), "ARE MEMES GREAT?")
|
||||
#test(upper("Ελλάδα"), "ΕΛΛΆΔΑ")
|
||||
|
||||
--- cases-content-text ---
|
||||
// Check that cases are applied to text nested in content
|
||||
#lower(box("HI!"))
|
||||
|
||||
--- cases-content-symbol ---
|
||||
// Check that cases are applied to symbols nested in content
|
||||
#lower($H I !$.body)
|
||||
|
||||
--- upper-bad-type ---
|
||||
// Error: 8-9 expected string or content, found integer
|
||||
#upper(1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user