mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Introduce NodeKind::Quote
This commit is contained in:
parent
c3a387b8f7
commit
072543fc59
@ -45,6 +45,8 @@ pub enum Content {
|
||||
Horizontal(Spacing),
|
||||
/// Plain text.
|
||||
Text(EcoString),
|
||||
/// A smart quote, may be single (`false`) or double (`true`).
|
||||
Quote(bool),
|
||||
/// An inline-level node.
|
||||
Inline(LayoutNode),
|
||||
/// A paragraph break.
|
||||
@ -214,6 +216,7 @@ impl Debug for Content {
|
||||
Self::Linebreak => f.pad("Linebreak"),
|
||||
Self::Horizontal(kind) => write!(f, "Horizontal({kind:?})"),
|
||||
Self::Text(text) => write!(f, "Text({text:?})"),
|
||||
Self::Quote(double) => write!(f, "Quote({double:?})"),
|
||||
Self::Inline(node) => {
|
||||
f.write_str("Inline(")?;
|
||||
node.fmt(f)?;
|
||||
@ -384,6 +387,9 @@ impl<'a> Builder<'a> {
|
||||
self.par.ignorant(child, styles);
|
||||
}
|
||||
}
|
||||
Content::Quote(double) => {
|
||||
self.par.supportive(ParChild::Quote(*double), styles);
|
||||
}
|
||||
Content::Text(text) => {
|
||||
self.par.supportive(ParChild::Text(text.clone()), styles);
|
||||
}
|
||||
@ -496,7 +502,7 @@ impl<'a> Builder<'a> {
|
||||
.items()
|
||||
.find_map(|child| match child {
|
||||
ParChild::Spacing(_) => None,
|
||||
ParChild::Text(_) => Some(true),
|
||||
ParChild::Text(_) | ParChild::Quote(_) => Some(true),
|
||||
ParChild::Node(_) => Some(false),
|
||||
})
|
||||
.unwrap_or_default()
|
||||
|
@ -111,6 +111,7 @@ impl Eval for MarkupNode {
|
||||
Self::Linebreak => Content::Linebreak,
|
||||
Self::Parbreak => Content::Parbreak,
|
||||
Self::Text(text) => Content::Text(text.clone()),
|
||||
Self::Quote(double) => Content::Quote(*double),
|
||||
Self::Strong(strong) => strong.eval(ctx, scp)?,
|
||||
Self::Emph(emph) => emph.eval(ctx, scp)?,
|
||||
Self::Raw(raw) => raw.eval(ctx, scp)?,
|
||||
|
@ -19,6 +19,8 @@ pub struct ParNode(pub StyleVec<ParChild>);
|
||||
pub enum ParChild {
|
||||
/// A chunk of text.
|
||||
Text(EcoString),
|
||||
/// A smart quote, may be single (`false`) or double (`true`).
|
||||
Quote(bool),
|
||||
/// Horizontal spacing between other children.
|
||||
Spacing(Spacing),
|
||||
/// An arbitrary inline-level node.
|
||||
@ -89,6 +91,7 @@ impl Debug for ParChild {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::Text(text) => write!(f, "Text({:?})", text),
|
||||
Self::Quote(double) => write!(f, "Quote({})", double),
|
||||
Self::Spacing(kind) => write!(f, "{:?}", kind),
|
||||
Self::Node(node) => node.fmt(f),
|
||||
}
|
||||
@ -397,6 +400,11 @@ fn collect<'a>(
|
||||
}
|
||||
Segment::Text(full.len() - prev)
|
||||
}
|
||||
ParChild::Quote(double) => {
|
||||
let prev = full.len();
|
||||
full.push(if *double { '"' } else { '\'' });
|
||||
Segment::Text(full.len() - prev)
|
||||
}
|
||||
ParChild::Spacing(spacing) => {
|
||||
full.push(SPACING_REPLACE);
|
||||
Segment::Spacing(*spacing)
|
||||
|
@ -215,6 +215,7 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) {
|
||||
| NodeKind::NonBreakingSpace
|
||||
| NodeKind::EnDash
|
||||
| NodeKind::EmDash
|
||||
| NodeKind::Quote(_)
|
||||
| NodeKind::Linebreak
|
||||
| NodeKind::Raw(_)
|
||||
| NodeKind::Math(_)
|
||||
|
@ -143,11 +143,13 @@ impl<'s> Tokens<'s> {
|
||||
|
||||
// Markup.
|
||||
'~' => NodeKind::NonBreakingSpace,
|
||||
'-' => self.hyph(),
|
||||
'\'' => NodeKind::Quote(false),
|
||||
'"' => NodeKind::Quote(true),
|
||||
'*' if !self.in_word() => NodeKind::Star,
|
||||
'_' if !self.in_word() => NodeKind::Underscore,
|
||||
'`' => self.raw(),
|
||||
'$' => self.math(),
|
||||
'-' => self.hyph(),
|
||||
'=' => NodeKind::Eq,
|
||||
c if c == '.' || c.is_ascii_digit() => self.numbering(start, c),
|
||||
|
||||
@ -220,7 +222,7 @@ impl<'s> Tokens<'s> {
|
||||
// Comments, parentheses, code.
|
||||
'/' | '[' | ']' | '{' | '}' | '#' |
|
||||
// Markup
|
||||
'~' | '*' | '_' | '`' | '$' | '-' | '\\'
|
||||
'~' | '\'' | '"' | '*' | '_' | '`' | '$' | '-' | '\\'
|
||||
};
|
||||
|
||||
loop {
|
||||
@ -269,8 +271,8 @@ impl<'s> Tokens<'s> {
|
||||
// Parenthesis and hashtag.
|
||||
'[' | ']' | '{' | '}' | '#' |
|
||||
// Markup.
|
||||
'~' | '*' | '_' | '`' | '$' | '=' | '-' | '.' => {
|
||||
self.s.eat_assert(c);
|
||||
'~' | '\'' | '"' | '*' | '_' | '`' | '$' | '=' | '-' | '.' => {
|
||||
self.s.eat_assert(c) ;
|
||||
NodeKind::Escape(c)
|
||||
}
|
||||
'u' if self.s.rest().starts_with("u{") => {
|
||||
@ -789,7 +791,7 @@ mod tests {
|
||||
t!(Markup[" /"]: "hello-world" => Text("hello"), Minus, Text("world"));
|
||||
|
||||
// Test code symbols in text.
|
||||
t!(Markup[" /"]: "a():\"b" => Text("a():\"b"));
|
||||
t!(Markup[" /"]: "a():\"b" => Text("a():"), Quote(true), Text("b"));
|
||||
t!(Markup[" /"]: ";:,|/+" => Text(";:,|"), Text("/+"));
|
||||
t!(Markup[" /"]: "=-a" => Eq, Minus, Text("a"));
|
||||
t!(Markup[" "]: "#123" => Text("#"), Text("123"));
|
||||
@ -812,6 +814,8 @@ mod tests {
|
||||
t!(Markup: r"\_" => Escape('_'));
|
||||
t!(Markup: r"\=" => Escape('='));
|
||||
t!(Markup: r"\~" => Escape('~'));
|
||||
t!(Markup: r"\'" => Escape('\''));
|
||||
t!(Markup: r#"\""# => Escape('"'));
|
||||
t!(Markup: r"\`" => Escape('`'));
|
||||
t!(Markup: r"\$" => Escape('$'));
|
||||
t!(Markup: r"\#" => Escape('#'));
|
||||
@ -820,7 +824,6 @@ mod tests {
|
||||
t!(Markup[" /"]: r"\a" => Text(r"\"), Text("a"));
|
||||
t!(Markup[" /"]: r"\u" => Text(r"\"), Text("u"));
|
||||
t!(Markup[" /"]: r"\1" => Text(r"\"), Text("1"));
|
||||
t!(Markup[" /"]: r#"\""# => Text(r"\"), Text("\""));
|
||||
|
||||
// Test basic unicode escapes.
|
||||
t!(Markup: r"\u{}" => Error(Full, "invalid unicode escape sequence"));
|
||||
|
@ -68,6 +68,7 @@ impl Markup {
|
||||
NodeKind::NonBreakingSpace => Some(MarkupNode::Text('\u{00A0}'.into())),
|
||||
NodeKind::EnDash => Some(MarkupNode::Text('\u{2013}'.into())),
|
||||
NodeKind::EmDash => Some(MarkupNode::Text('\u{2014}'.into())),
|
||||
NodeKind::Quote(d) => Some(MarkupNode::Quote(*d)),
|
||||
NodeKind::Strong => node.cast().map(MarkupNode::Strong),
|
||||
NodeKind::Emph => node.cast().map(MarkupNode::Emph),
|
||||
NodeKind::Raw(raw) => Some(MarkupNode::Raw(raw.as_ref().clone())),
|
||||
@ -91,6 +92,8 @@ pub enum MarkupNode {
|
||||
Parbreak,
|
||||
/// Plain text.
|
||||
Text(EcoString),
|
||||
/// A smart quote: `'` (`false`) or `"` (true).
|
||||
Quote(bool),
|
||||
/// Strong content: `*Strong*`.
|
||||
Strong(StrongNode),
|
||||
/// Emphasized content: `_Emphasized_`.
|
||||
|
@ -130,6 +130,7 @@ impl Category {
|
||||
NodeKind::NonBreakingSpace => Some(Category::Shortcut),
|
||||
NodeKind::EnDash => Some(Category::Shortcut),
|
||||
NodeKind::EmDash => Some(Category::Shortcut),
|
||||
NodeKind::Quote(_) => Some(Category::Shortcut),
|
||||
NodeKind::Escape(_) => Some(Category::Escape),
|
||||
NodeKind::Not => Some(Category::Keyword),
|
||||
NodeKind::And => Some(Category::Keyword),
|
||||
|
@ -596,6 +596,8 @@ pub enum NodeKind {
|
||||
EnDash,
|
||||
/// An em-dash: `---`.
|
||||
EmDash,
|
||||
/// A smart quote: `'` (`false`) or `"` (true).
|
||||
Quote(bool),
|
||||
/// A slash and the letter "u" followed by a hexadecimal unicode entity
|
||||
/// enclosed in curly braces: `\u{1F5FA}`.
|
||||
Escape(char),
|
||||
@ -769,6 +771,7 @@ impl NodeKind {
|
||||
| Self::NonBreakingSpace
|
||||
| Self::EnDash
|
||||
| Self::EmDash
|
||||
| Self::Quote(_)
|
||||
| Self::Escape(_)
|
||||
| Self::Strong
|
||||
| Self::Emph
|
||||
@ -861,6 +864,8 @@ impl NodeKind {
|
||||
Self::NonBreakingSpace => "non-breaking space",
|
||||
Self::EnDash => "en dash",
|
||||
Self::EmDash => "em dash",
|
||||
Self::Quote(false) => "single quote",
|
||||
Self::Quote(true) => "double quote",
|
||||
Self::Escape(_) => "escape sequence",
|
||||
Self::Strong => "strong content",
|
||||
Self::Emph => "emphasized content",
|
||||
@ -981,6 +986,7 @@ impl Hash for NodeKind {
|
||||
Self::NonBreakingSpace => {}
|
||||
Self::EnDash => {}
|
||||
Self::EmDash => {}
|
||||
Self::Quote(d) => d.hash(state),
|
||||
Self::Escape(c) => c.hash(state),
|
||||
Self::Strong => {}
|
||||
Self::Emph => {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user