summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorIan Wrzesinski <wrzian@umich.edu>2024-07-29 00:25:03 -0500
committerIan Wrzesinski <wrzian@umich.edu>2025-01-23 16:28:29 -0500
commitc47b71b4350434a73734789ebde1374b791dc88e (patch)
tree0157e3dc277010bb9581eac8a5881109aedc269f /crates
parent0b8b7d0f233f748a5c12d1b8e31f657803122eba (diff)
Basic SymbolElem addition
Diffstat (limited to 'crates')
-rw-r--r--crates/typst-layout/src/math/mod.rs10
-rw-r--r--crates/typst-library/src/foundations/ops.rs12
-rw-r--r--crates/typst-library/src/foundations/symbol.rs33
-rw-r--r--crates/typst-library/src/foundations/value.rs6
-rw-r--r--crates/typst-library/src/math/accent.rs9
-rw-r--r--crates/typst-realize/src/lib.rs10
6 files changed, 63 insertions, 17 deletions
diff --git a/crates/typst-layout/src/math/mod.rs b/crates/typst-layout/src/math/mod.rs
index 06dc6653..905e159a 100644
--- a/crates/typst-layout/src/math/mod.rs
+++ b/crates/typst-layout/src/math/mod.rs
@@ -17,7 +17,9 @@ use rustybuzz::Feature;
use ttf_parser::Tag;
use typst_library::diag::{bail, SourceResult};
use typst_library::engine::Engine;
-use typst_library::foundations::{Content, NativeElement, Packed, Resolve, StyleChain};
+use typst_library::foundations::{
+ Content, NativeElement, Packed, Resolve, StyleChain, SymbolElem,
+};
use typst_library::introspection::{Counter, Locator, SplitLocator, TagElem};
use typst_library::layout::{
Abs, AlignElem, Axes, BlockElem, BoxElem, Em, FixedAlignment, Fragment, Frame, HElem,
@@ -535,6 +537,12 @@ fn layout_realized(
layout_h(elem, ctx, styles)?;
} else if let Some(elem) = elem.to_packed::<TextElem>() {
self::text::layout_text(elem, ctx, styles)?;
+ } else if let Some(elem) = elem.to_packed::<SymbolElem>() {
+ // This is a hack to avoid affecting layout that will be replaced in a
+ // later commit.
+ let text_elem = TextElem::new(elem.text.to_string().into());
+ let packed = Packed::new(text_elem);
+ self::text::layout_text(&packed, ctx, styles)?;
} else if let Some(elem) = elem.to_packed::<BoxElem>() {
layout_box(elem, ctx, styles)?;
} else if elem.is::<AlignPointElem>() {
diff --git a/crates/typst-library/src/foundations/ops.rs b/crates/typst-library/src/foundations/ops.rs
index 85a041b6..7dbdde8f 100644
--- a/crates/typst-library/src/foundations/ops.rs
+++ b/crates/typst-library/src/foundations/ops.rs
@@ -6,7 +6,9 @@ use ecow::eco_format;
use typst_utils::Numeric;
use crate::diag::{bail, HintedStrResult, StrResult};
-use crate::foundations::{format_str, Datetime, IntoValue, Regex, Repr, Value};
+use crate::foundations::{
+ format_str, Datetime, IntoValue, Regex, Repr, SymbolElem, Value,
+};
use crate::layout::{Alignment, Length, Rel};
use crate::text::TextElem;
use crate::visualize::Stroke;
@@ -30,10 +32,10 @@ pub fn join(lhs: Value, rhs: Value) -> StrResult<Value> {
(Symbol(a), Str(b)) => Str(format_str!("{a}{b}")),
(Bytes(a), Bytes(b)) => Bytes(a + b),
(Content(a), Content(b)) => Content(a + b),
- (Content(a), Symbol(b)) => Content(a + TextElem::packed(b.get())),
+ (Content(a), Symbol(b)) => Content(a + SymbolElem::packed(b.get())),
(Content(a), Str(b)) => Content(a + TextElem::packed(b)),
(Str(a), Content(b)) => Content(TextElem::packed(a) + b),
- (Symbol(a), Content(b)) => Content(TextElem::packed(a.get()) + b),
+ (Symbol(a), Content(b)) => Content(SymbolElem::packed(a.get()) + b),
(Array(a), Array(b)) => Array(a + b),
(Dict(a), Dict(b)) => Dict(a + b),
(Args(a), Args(b)) => Args(a + b),
@@ -130,10 +132,10 @@ pub fn add(lhs: Value, rhs: Value) -> HintedStrResult<Value> {
(Symbol(a), Str(b)) => Str(format_str!("{a}{b}")),
(Bytes(a), Bytes(b)) => Bytes(a + b),
(Content(a), Content(b)) => Content(a + b),
- (Content(a), Symbol(b)) => Content(a + TextElem::packed(b.get())),
+ (Content(a), Symbol(b)) => Content(a + SymbolElem::packed(b.get())),
(Content(a), Str(b)) => Content(a + TextElem::packed(b)),
(Str(a), Content(b)) => Content(TextElem::packed(a) + b),
- (Symbol(a), Content(b)) => Content(TextElem::packed(a.get()) + b),
+ (Symbol(a), Content(b)) => Content(SymbolElem::packed(a.get()) + b),
(Array(a), Array(b)) => Array(a + b),
(Dict(a), Dict(b)) => Dict(a + b),
diff --git a/crates/typst-library/src/foundations/symbol.rs b/crates/typst-library/src/foundations/symbol.rs
index 3045970d..8a80506f 100644
--- a/crates/typst-library/src/foundations/symbol.rs
+++ b/crates/typst-library/src/foundations/symbol.rs
@@ -9,7 +9,10 @@ use typst_syntax::{is_ident, Span, Spanned};
use typst_utils::hash128;
use crate::diag::{bail, SourceResult, StrResult};
-use crate::foundations::{cast, func, scope, ty, Array, Func, NativeFunc, Repr as _};
+use crate::foundations::{
+ cast, elem, func, scope, ty, Array, Content, Func, NativeElement, NativeFunc, Packed,
+ PlainText, Repr as _,
+};
/// A Unicode symbol.
///
@@ -425,3 +428,31 @@ fn parts(modifiers: &str) -> impl Iterator<Item = &str> {
fn contained(modifiers: &str, m: &str) -> bool {
parts(modifiers).any(|part| part == m)
}
+
+/// A single character.
+#[elem(Repr, PlainText)]
+pub struct SymbolElem {
+ /// The symbol's character.
+ #[required]
+ pub text: char, // This is called `text` for consistency with `TextElem`.
+}
+
+impl SymbolElem {
+ /// Create a new packed symbol element.
+ pub fn packed(text: impl Into<char>) -> Content {
+ Self::new(text.into()).pack()
+ }
+}
+
+impl PlainText for Packed<SymbolElem> {
+ fn plain_text(&self, text: &mut EcoString) {
+ text.push(self.text);
+ }
+}
+
+impl crate::foundations::Repr for SymbolElem {
+ /// Use a custom repr that matches normal content.
+ fn repr(&self) -> EcoString {
+ eco_format!("[{}]", self.text)
+ }
+}
diff --git a/crates/typst-library/src/foundations/value.rs b/crates/typst-library/src/foundations/value.rs
index efc480d3..8d9f5933 100644
--- a/crates/typst-library/src/foundations/value.rs
+++ b/crates/typst-library/src/foundations/value.rs
@@ -16,7 +16,7 @@ use crate::foundations::{
fields, ops, repr, Args, Array, AutoValue, Bytes, CastInfo, Content, Datetime,
Decimal, Dict, Duration, Fold, FromValue, Func, IntoValue, Label, Module,
NativeElement, NativeType, NoneValue, Plugin, Reflect, Repr, Resolve, Scope, Str,
- Styles, Symbol, Type, Version,
+ Styles, Symbol, SymbolElem, Type, Version,
};
use crate::layout::{Abs, Angle, Em, Fr, Length, Ratio, Rel};
use crate::text::{RawContent, RawElem, TextElem};
@@ -209,7 +209,7 @@ impl Value {
Self::Decimal(v) => TextElem::packed(eco_format!("{v}")),
Self::Str(v) => TextElem::packed(v),
Self::Version(v) => TextElem::packed(eco_format!("{v}")),
- Self::Symbol(v) => TextElem::packed(v.get()),
+ Self::Symbol(v) => SymbolElem::packed(v.get()),
Self::Content(v) => v,
Self::Module(module) => module.content(),
_ => RawElem::new(RawContent::Text(self.repr()))
@@ -656,7 +656,7 @@ primitive! { Duration: "duration", Duration }
primitive! { Content: "content",
Content,
None => Content::empty(),
- Symbol(v) => TextElem::packed(v.get()),
+ Symbol(v) => SymbolElem::packed(v.get()),
Str(v) => TextElem::packed(v)
}
primitive! { Styles: "styles", Styles }
diff --git a/crates/typst-library/src/math/accent.rs b/crates/typst-library/src/math/accent.rs
index b87e527f..b162c52b 100644
--- a/crates/typst-library/src/math/accent.rs
+++ b/crates/typst-library/src/math/accent.rs
@@ -1,8 +1,7 @@
use crate::diag::bail;
-use crate::foundations::{cast, elem, func, Content, NativeElement, Value};
+use crate::foundations::{cast, elem, func, Content, NativeElement, SymbolElem};
use crate::layout::{Length, Rel};
use crate::math::Mathy;
-use crate::text::TextElem;
/// Attaches an accent to a base.
///
@@ -142,8 +141,8 @@ cast! {
Accent,
self => self.0.into_value(),
v: char => Self::new(v),
- v: Content => match v.to_packed::<TextElem>() {
- Some(elem) => Value::Str(elem.text.clone().into()).cast()?,
- None => bail!("expected text"),
+ v: Content => match v.to_packed::<SymbolElem>() {
+ Some(elem) => Self::new(elem.text),
+ None => bail!("expected a symbol"),
},
}
diff --git a/crates/typst-realize/src/lib.rs b/crates/typst-realize/src/lib.rs
index 6ab6d81c..99db2ef1 100644
--- a/crates/typst-realize/src/lib.rs
+++ b/crates/typst-realize/src/lib.rs
@@ -16,7 +16,7 @@ use typst_library::engine::Engine;
use typst_library::foundations::{
Content, Context, ContextElem, Element, NativeElement, Recipe, RecipeIndex, Selector,
SequenceElem, Show, ShowSet, Style, StyleChain, StyleVec, StyledElem, Styles,
- Synthesize, Transformation,
+ SymbolElem, Synthesize, Transformation,
};
use typst_library::html::{tag, HtmlElem};
use typst_library::introspection::{Locatable, SplitLocator, Tag, TagElem};
@@ -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, '_, '_, '_>,
- content: &'a Content,
+ mut content: &'a Content,
styles: StyleChain<'a>,
) -> SourceResult<()> {
// Tags can always simply be pushed.
@@ -230,6 +230,12 @@ 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)? {