Rename template to content

This commit is contained in:
Laurenz 2022-03-11 12:59:55 +01:00
parent 5ce2a006b6
commit 5ac7eb3860
66 changed files with 403 additions and 414 deletions

View File

@ -4,15 +4,15 @@
// There are variables and they can take normal values like strings, ...
#let city = "Berlin"
// ... but also "template" values. While these contain markup,
// ... but also "content" values. While these contain markup,
// they are also values and can be summed, stored in arrays etc.
// There are also more standard control flow structures, like #if and #for.
#let university = [*Technische Universität {city}*]
#let faculty = [*Fakultät II, Institut for Mathematik*]
// The `box` function just places content into a rectangular container. When
// the only argument to a function is a template, the parentheses can be omitted
// (i.e. `f[a]` is the same as `f([a])`).
// the only argument to a function is a content block, the parentheses can be
// omitted (i.e. `f[a]` is the same as `f([a])`).
#box[
// Backslash adds a forced line break.
#university \
@ -26,8 +26,8 @@
// Adds vertical spacing.
#v(6mm)
// If the last argument to a function is a template, we can also place it behind
// the parentheses.
// If the last argument to a function is a content block, we can also place it
// behind the parentheses.
#align(center)[
// Markdown-like syntax for headings.
==== 3. Übungsblatt Computerorientierte Mathematik II #v(4mm)

View File

@ -80,7 +80,7 @@ fn bench_eval(iai: &mut Iai) {
fn bench_layout(iai: &mut Iai) {
let (mut ctx, id) = context();
let module = ctx.evaluate(id).unwrap();
iai.run(|| module.template.layout(&mut ctx));
iai.run(|| module.content.layout(&mut ctx));
}
fn bench_render(iai: &mut Iai) {

View File

@ -89,7 +89,7 @@ impl Array {
a.partial_cmp(b).unwrap_or_else(|| {
if result.is_ok() {
result = Err(format!(
"cannot compare {} with {}",
"cannot order {} and {}",
a.type_name(),
b.type_name(),
));

View File

@ -49,8 +49,8 @@ impl<'a> CapturesVisitor<'a> {
// through the expressions that contain them).
Some(Expr::Ident(ident)) => self.capture(ident),
// Blocks and templates create a scope.
Some(Expr::Code(_) | Expr::Template(_)) => {
// Code and content blocks create a scope.
Some(Expr::Code(_) | Expr::Content(_)) => {
self.internal.enter();
for child in node.children() {
self.visit(child);

View File

@ -2,24 +2,25 @@ use std::any::TypeId;
use std::fmt::{self, Debug, Formatter, Write};
use std::hash::{Hash, Hasher};
use super::{Args, Func, StyleMap, Template, Value};
use super::{Args, Content, Func, StyleMap, Value};
use crate::diag::TypResult;
use crate::Context;
/// A class of nodes.
///
/// You can [construct] an instance of a class in Typst code by invoking the
/// class as a callable. This always produces a template value, but not
/// class as a callable. This always produces a content value, but not
/// necessarily a simple inline or block node. For example, the `text`
/// constructor does not actually create a [`TextNode`]. Instead it applies
/// styling to whatever node you pass in and returns it structurally unchanged.
/// styling to whatever content you pass in and returns it structurally
/// unchanged.
///
/// The arguments you can pass to a class constructor fall into two categories:
/// Data that is inherent to the instance (e.g. the text/content of a heading)
/// and style properties (e.g. the fill color of a heading). As the latter are
/// often shared by many instances throughout a document, they can also be
/// conveniently configured through class's [`set`] rule. Then, they apply to
/// all nodes that are instantiated into the template where the `set` was
/// all nodes that are instantiated into the content block where the `set` was
/// executed.
///
/// ```typst
@ -55,8 +56,8 @@ impl Class {
construct: |ctx, args| {
let mut styles = StyleMap::new();
T::set(args, &mut styles)?;
let template = T::construct(ctx, args)?;
Ok(Value::Template(template.styled_with_map(styles.scoped())))
let content = T::construct(ctx, args)?;
Ok(Value::Content(content.styled_with_map(styles.scoped())))
},
set: T::set,
}
@ -80,8 +81,8 @@ impl Class {
/// Construct an instance of the class.
///
/// This parses both property and data arguments (in this order), styles the
/// template constructed from the data with the style properties and wraps
/// it in a value.
/// content constructed from the data with the style properties and wraps it
/// in a value.
pub fn construct(&self, ctx: &mut Context, mut args: Args) -> TypResult<Value> {
let value = (self.construct)(ctx, &mut args)?;
args.finish()?;
@ -126,7 +127,7 @@ pub trait Construct {
///
/// This is passed only the arguments that remain after execution of the
/// class's set rule.
fn construct(ctx: &mut Context, args: &mut Args) -> TypResult<Template>;
fn construct(ctx: &mut Context, args: &mut Args) -> TypResult<Content>;
}
/// Set style properties of a class.

View File

@ -20,29 +20,23 @@ use crate::util::EcoString;
///
/// This results from:
/// - anything written between square brackets in Typst
/// - any class constructor
/// - any node constructor
///
/// This enum has two notable variants:
/// Content is represented as a tree of nodes. There are two nodes of special
/// interest:
///
/// 1. A `Styled` template attaches a style map to a template. This map affects
/// the whole subtemplate. For example, a single bold word could be
/// represented as a `Styled(Text("Hello"), [TextNode::STRONG: true])`
/// template.
///
/// 2. A `Sequence` template combines multiple arbitrary templates and is the
/// representation of a "flow" of content. So, when you write `[Hi] + [you]`
/// in Typst, this type's [`Add`] implementation is invoked and the two
/// [`Text`](Self::Text) templates are combined into a single
/// [`Sequence`](Self::Sequence) template.
///
/// A sequence may contain nested sequences (meaning this variant effectively
/// allows templates to form trees). All nested sequences can equivalently be
/// represented as a single flat sequence, but allowing nesting doesn't hurt
/// since we can just recurse into the nested sequences. Also, in theory,
/// this allows better complexity when adding large sequence nodes just like
/// for something like a text rope.
/// 1. A `Styled` node attaches a style map to other content. For example, a
/// single bold word could be represented as a `Styled(Text("Hello"),
/// [TextNode::STRONG: true])` node.
/// 2. A `Sequence` node content combines other arbitrary content and is the
/// representation of a "flow" of other nodes. So, when you write `[Hi] +
/// [you]` in Typst, this type's [`Add`] implementation is invoked and the
/// two [`Text`](Self::Text) nodes are combined into a single
/// [`Sequence`](Self::Sequence) node. A sequence may contain nested
/// sequences.
#[derive(PartialEq, Clone, Hash)]
pub enum Template {
pub enum Content {
/// A word space.
Space,
/// A line break.
@ -71,19 +65,19 @@ pub enum Template {
Page(PageNode),
/// A node that can be realized with styles.
Show(ShowNode),
/// A template with attached styles.
/// Content with attached styles.
Styled(Arc<(Self, StyleMap)>),
/// A sequence of multiple subtemplates.
/// A sequence of multiple nodes.
Sequence(Arc<Vec<Self>>),
}
impl Template {
/// Create an empty template.
impl Content {
/// Create empty content.
pub fn new() -> Self {
Self::sequence(vec![])
}
/// Create a template from an inline-level node.
/// Create content from an inline-level node.
pub fn inline<T>(node: T) -> Self
where
T: Layout + Debug + Hash + Sync + Send + 'static,
@ -91,7 +85,7 @@ impl Template {
Self::Inline(node.pack())
}
/// Create a template from a block-level node.
/// Create content from a block-level node.
pub fn block<T>(node: T) -> Self
where
T: Layout + Debug + Hash + Sync + Send + 'static,
@ -99,7 +93,7 @@ impl Template {
Self::Block(node.pack())
}
/// Create a template from a showable node.
/// Create content from a showable node.
pub fn show<T>(node: T) -> Self
where
T: Show + Debug + Hash + Sync + Send + 'static,
@ -107,7 +101,7 @@ impl Template {
Self::Show(node.pack())
}
/// Style this template with a single property.
/// Style this content with a single style property.
pub fn styled<P: Property>(mut self, key: P, value: P::Value) -> Self {
if let Self::Styled(styled) = &mut self {
if let Some((_, map)) = Arc::get_mut(styled) {
@ -121,7 +115,7 @@ impl Template {
self.styled_with_map(StyleMap::with(key, value))
}
/// Style this template with a full style map.
/// Style this content with a full style map.
pub fn styled_with_map(mut self, styles: StyleMap) -> Self {
if styles.is_empty() {
return self;
@ -139,17 +133,17 @@ impl Template {
Self::Styled(Arc::new((self, styles)))
}
/// Style this template in monospace.
/// Style this content in monospace.
pub fn monospaced(self) -> Self {
self.styled(TextNode::MONOSPACED, true)
}
/// Underline this template.
/// Underline this content.
pub fn underlined(self) -> Self {
Self::show(DecoNode::<UNDERLINE>(self))
}
/// Create a new sequence template.
/// Create a new sequence nodes from multiples nodes.
pub fn sequence(seq: Vec<Self>) -> Self {
if seq.len() == 1 {
seq.into_iter().next().unwrap()
@ -158,15 +152,15 @@ impl Template {
}
}
/// Repeat this template `n` times.
/// Repeat this content `n` times.
pub fn repeat(&self, n: i64) -> StrResult<Self> {
let count = usize::try_from(n)
.map_err(|_| format!("cannot repeat this template {} times", n))?;
.map_err(|_| format!("cannot repeat this content {} times", n))?;
Ok(Self::sequence(vec![self.clone(); count]))
}
/// Layout this template into a collection of pages.
/// Layout this content into a collection of pages.
pub fn layout(&self, ctx: &mut Context) -> TypResult<Vec<Arc<Frame>>> {
let sya = Arena::new();
let tpa = Arena::new();
@ -190,13 +184,13 @@ impl Template {
}
}
impl Default for Template {
impl Default for Content {
fn default() -> Self {
Self::new()
}
}
impl Add for Template {
impl Add for Content {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
@ -222,19 +216,19 @@ impl Add for Template {
}
}
impl AddAssign for Template {
impl AddAssign for Content {
fn add_assign(&mut self, rhs: Self) {
*self = std::mem::take(self) + rhs;
}
}
impl Sum for Template {
impl Sum for Content {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
Self::sequence(iter.collect())
}
}
impl Layout for Template {
impl Layout for Content {
fn layout(
&self,
ctx: &mut Context,
@ -254,18 +248,18 @@ impl Layout for Template {
fn pack(self) -> LayoutNode {
match self {
Template::Block(node) => node,
Content::Block(node) => node,
other => LayoutNode::new(other),
}
}
}
/// Builds a flow or page nodes from a template.
/// Builds a flow or page nodes from content.
struct Builder<'a> {
/// An arena where intermediate style chains are stored.
sya: &'a Arena<StyleChain<'a>>,
/// An arena where intermediate templates are stored.
tpa: &'a Arena<Template>,
/// An arena where intermediate content resulting from show rules is stored.
tpa: &'a Arena<Content>,
/// The already built page runs.
pages: Option<StyleVecBuilder<'a, PageNode>>,
/// The currently built list.
@ -280,7 +274,7 @@ struct Builder<'a> {
impl<'a> Builder<'a> {
/// Prepare the builder.
fn new(sya: &'a Arena<StyleChain<'a>>, tpa: &'a Arena<Template>, top: bool) -> Self {
fn new(sya: &'a Arena<StyleChain<'a>>, tpa: &'a Arena<Content>, top: bool) -> Self {
Self {
sya,
tpa,
@ -292,33 +286,33 @@ impl<'a> Builder<'a> {
}
}
/// Process a template.
/// Process content.
fn process(
&mut self,
ctx: &mut Context,
template: &'a Template,
content: &'a Content,
styles: StyleChain<'a>,
) -> TypResult<()> {
if let Some(builder) = &mut self.list {
match template {
Template::Space => {
builder.staged.push((template, styles));
match content {
Content::Space => {
builder.staged.push((content, styles));
return Ok(());
}
Template::Parbreak => {
builder.staged.push((template, styles));
Content::Parbreak => {
builder.staged.push((content, styles));
return Ok(());
}
Template::List(item) if builder.kind == UNORDERED => {
Content::List(item) if builder.kind == UNORDERED => {
builder.wide |=
builder.staged.iter().any(|&(t, _)| *t == Template::Parbreak);
builder.staged.iter().any(|&(t, _)| *t == Content::Parbreak);
builder.staged.clear();
builder.items.push(item.clone());
return Ok(());
}
Template::Enum(item) if builder.kind == ORDERED => {
Content::Enum(item) if builder.kind == ORDERED => {
builder.wide |=
builder.staged.iter().any(|&(t, _)| *t == Template::Parbreak);
builder.staged.iter().any(|&(t, _)| *t == Content::Parbreak);
builder.staged.clear();
builder.items.push(item.clone());
return Ok(());
@ -327,14 +321,14 @@ impl<'a> Builder<'a> {
}
}
match template {
Template::Space => {
match content {
Content::Space => {
self.par.weak(ParChild::Text(' '.into()), 0, styles);
}
Template::Linebreak => {
Content::Linebreak => {
self.par.destructive(ParChild::Text('\n'.into()), styles);
}
Template::Horizontal(kind) => {
Content::Horizontal(kind) => {
let child = ParChild::Spacing(*kind);
if kind.is_fractional() {
self.par.destructive(child, styles);
@ -342,21 +336,21 @@ impl<'a> Builder<'a> {
self.par.ignorant(child, styles);
}
}
Template::Text(text) => {
Content::Text(text) => {
self.par.supportive(ParChild::Text(text.clone()), styles);
}
Template::Inline(node) => {
Content::Inline(node) => {
self.par.supportive(ParChild::Node(node.clone()), styles);
}
Template::Parbreak => {
Content::Parbreak => {
self.finish_par(styles);
self.flow.weak(FlowChild::Parbreak, 1, styles);
}
Template::Colbreak => {
Content::Colbreak => {
self.finish_par(styles);
self.flow.destructive(FlowChild::Colbreak, styles);
}
Template::Vertical(kind) => {
Content::Vertical(kind) => {
self.finish_par(styles);
let child = FlowChild::Spacing(*kind);
if kind.is_fractional() {
@ -365,7 +359,7 @@ impl<'a> Builder<'a> {
self.flow.ignorant(child, styles);
}
}
Template::Block(node) => {
Content::Block(node) => {
self.finish_par(styles);
let child = FlowChild::Node(node.clone());
if node.is::<PlaceNode>() {
@ -375,7 +369,7 @@ impl<'a> Builder<'a> {
}
self.finish_par(styles);
}
Template::List(item) => {
Content::List(item) => {
self.list = Some(ListBuilder {
styles,
kind: UNORDERED,
@ -384,7 +378,7 @@ impl<'a> Builder<'a> {
staged: vec![],
});
}
Template::Enum(item) => {
Content::Enum(item) => {
self.list = Some(ListBuilder {
styles,
kind: ORDERED,
@ -393,22 +387,22 @@ impl<'a> Builder<'a> {
staged: vec![],
});
}
Template::Pagebreak => {
Content::Pagebreak => {
self.finish_page(ctx, true, true, styles)?;
}
Template::Page(page) => {
Content::Page(page) => {
self.finish_page(ctx, false, false, styles)?;
if let Some(pages) = &mut self.pages {
pages.push(page.clone(), styles);
}
}
Template::Show(node) => {
Content::Show(node) => {
let id = node.id();
let template = node.show(ctx, styles)?;
let stored = self.tpa.alloc(template);
let content = node.show(ctx, styles)?;
let stored = self.tpa.alloc(content);
self.process(ctx, stored, styles.unscoped(id))?;
}
Template::Styled(styled) => {
Content::Styled(styled) => {
let (sub, map) = styled.as_ref();
let stored = self.sya.alloc(styles);
let styles = map.chain(stored);
@ -432,7 +426,7 @@ impl<'a> Builder<'a> {
None => {}
}
}
Template::Sequence(seq) => {
Content::Sequence(seq) => {
for sub in seq.iter() {
self.process(ctx, sub, styles)?;
}
@ -487,15 +481,15 @@ impl<'a> Builder<'a> {
None => return Ok(()),
};
let template = match kind {
UNORDERED => Template::show(ListNode::<UNORDERED> { start: 1, wide, items }),
ORDERED | _ => Template::show(ListNode::<ORDERED> { start: 1, wide, items }),
let content = match kind {
UNORDERED => Content::show(ListNode::<UNORDERED> { start: 1, wide, items }),
ORDERED | _ => Content::show(ListNode::<ORDERED> { start: 1, wide, items }),
};
let stored = self.tpa.alloc(template);
let stored = self.tpa.alloc(content);
self.process(ctx, stored, styles)?;
for (template, styles) in staged {
self.process(ctx, template, styles)?;
for (content, styles) in staged {
self.process(ctx, content, styles)?;
}
Ok(())
@ -535,10 +529,10 @@ struct ListBuilder<'a> {
kind: ListKind,
items: Vec<ListItem>,
wide: bool,
staged: Vec<(&'a Template, StyleChain<'a>)>,
staged: Vec<(&'a Content, StyleChain<'a>)>,
}
impl Debug for Template {
impl Debug for Content {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::Space => f.pad("Space"),

View File

@ -19,7 +19,7 @@ use crate::Context;
/// Layout return one frame per used region alongside constraints that define
/// whether the result is reusable in other regions.
pub trait Layout {
/// Layout the node into the given regions, producing constrained frames.
/// Layout this node into the given regions, producing constrained frames.
fn layout(
&self,
ctx: &mut Context,

View File

@ -11,6 +11,7 @@ mod styles;
mod capture;
mod class;
mod collapse;
mod content;
mod control;
mod func;
mod layout;
@ -18,12 +19,12 @@ mod module;
mod ops;
mod scope;
mod show;
mod template;
pub use array::*;
pub use capture::*;
pub use class::*;
pub use collapse::*;
pub use content::*;
pub use control::*;
pub use dict::*;
pub use func::*;
@ -32,7 +33,6 @@ pub use module::*;
pub use scope::*;
pub use show::*;
pub use styles::*;
pub use template::*;
pub use value::*;
use unicode_segmentation::UnicodeSegmentation;
@ -58,7 +58,7 @@ pub trait Eval {
pub type EvalResult<T> = Result<T, Control>;
impl Eval for Markup {
type Output = Template;
type Output = Content;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
eval_markup(ctx, scp, &mut self.nodes())
@ -70,7 +70,7 @@ fn eval_markup(
ctx: &mut Context,
scp: &mut Scopes,
nodes: &mut impl Iterator<Item = MarkupNode>,
) -> EvalResult<Template> {
) -> EvalResult<Content> {
let mut seq = Vec::with_capacity(nodes.size_hint().1.unwrap_or_default());
while let Some(node) = nodes.next() {
@ -92,18 +92,18 @@ fn eval_markup(
});
}
Ok(Template::sequence(seq))
Ok(Content::sequence(seq))
}
impl Eval for MarkupNode {
type Output = Template;
type Output = Content;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
Ok(match self {
Self::Space => Template::Space,
Self::Linebreak => Template::Linebreak,
Self::Parbreak => Template::Parbreak,
Self::Text(text) => Template::Text(text.clone()),
Self::Space => Content::Space,
Self::Linebreak => Content::Linebreak,
Self::Parbreak => Content::Parbreak,
Self::Text(text) => Content::Text(text.clone()),
Self::Strong(strong) => strong.eval(ctx, scp)?,
Self::Emph(emph) => emph.eval(ctx, scp)?,
Self::Raw(raw) => raw.eval(ctx, scp)?,
@ -117,45 +117,45 @@ impl Eval for MarkupNode {
}
impl Eval for StrongNode {
type Output = Template;
type Output = Content;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
Ok(Template::show(library::text::StrongNode(
Ok(Content::show(library::text::StrongNode(
self.body().eval(ctx, scp)?,
)))
}
}
impl Eval for EmphNode {
type Output = Template;
type Output = Content;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
Ok(Template::show(library::text::EmphNode(
Ok(Content::show(library::text::EmphNode(
self.body().eval(ctx, scp)?,
)))
}
}
impl Eval for RawNode {
type Output = Template;
type Output = Content;
fn eval(&self, _: &mut Context, _: &mut Scopes) -> EvalResult<Self::Output> {
let template = Template::show(library::text::RawNode {
let content = Content::show(library::text::RawNode {
text: self.text.clone(),
block: self.block,
});
Ok(match self.lang {
Some(_) => template.styled(library::text::RawNode::LANG, self.lang.clone()),
None => template,
Some(_) => content.styled(library::text::RawNode::LANG, self.lang.clone()),
None => content,
})
}
}
impl Eval for MathNode {
type Output = Template;
type Output = Content;
fn eval(&self, _: &mut Context, _: &mut Scopes) -> EvalResult<Self::Output> {
Ok(Template::show(library::math::MathNode {
Ok(Content::show(library::math::MathNode {
formula: self.formula.clone(),
display: self.display,
}))
@ -163,10 +163,10 @@ impl Eval for MathNode {
}
impl Eval for HeadingNode {
type Output = Template;
type Output = Content;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
Ok(Template::show(library::structure::HeadingNode {
Ok(Content::show(library::structure::HeadingNode {
body: self.body().eval(ctx, scp)?,
level: self.level(),
}))
@ -174,10 +174,10 @@ impl Eval for HeadingNode {
}
impl Eval for ListNode {
type Output = Template;
type Output = Content;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
Ok(Template::List(library::structure::ListItem {
Ok(Content::List(library::structure::ListItem {
number: None,
body: Box::new(self.body().eval(ctx, scp)?),
}))
@ -185,10 +185,10 @@ impl Eval for ListNode {
}
impl Eval for EnumNode {
type Output = Template;
type Output = Content;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
Ok(Template::Enum(library::structure::ListItem {
Ok(Content::Enum(library::structure::ListItem {
number: self.number(),
body: Box::new(self.body().eval(ctx, scp)?),
}))
@ -203,7 +203,7 @@ impl Eval for Expr {
Self::Lit(v) => v.eval(ctx, scp),
Self::Ident(v) => v.eval(ctx, scp),
Self::Code(v) => v.eval(ctx, scp),
Self::Template(v) => v.eval(ctx, scp).map(Value::Template),
Self::Content(v) => v.eval(ctx, scp).map(Value::Content),
Self::Array(v) => v.eval(ctx, scp).map(Value::Array),
Self::Dict(v) => v.eval(ctx, scp).map(Value::Dict),
Self::Group(v) => v.eval(ctx, scp),
@ -222,7 +222,7 @@ impl Eval for Expr {
Self::While(v) => v.eval(ctx, scp),
Self::For(v) => v.eval(ctx, scp),
Self::Import(v) => v.eval(ctx, scp),
Self::Include(v) => v.eval(ctx, scp).map(Value::Template),
Self::Include(v) => v.eval(ctx, scp).map(Value::Content),
Self::Break(v) => v.eval(ctx, scp),
Self::Continue(v) => v.eval(ctx, scp),
Self::Return(v) => v.eval(ctx, scp),
@ -276,14 +276,14 @@ impl Eval for CodeBlock {
}
}
impl Eval for TemplateBlock {
type Output = Template;
impl Eval for ContentBlock {
type Output = Content;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
scp.enter();
let template = self.body().eval(ctx, scp)?;
let content = self.body().eval(ctx, scp)?;
scp.exit();
Ok(template)
Ok(content)
}
}
@ -716,13 +716,13 @@ impl Eval for ImportExpr {
}
impl Eval for IncludeExpr {
type Output = Template;
type Output = Content;
fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult<Self::Output> {
let span = self.path().span();
let path = self.path().eval(ctx, scp)?.cast::<EcoString>().at(span)?;
let module = import(ctx, &path, span)?;
Ok(module.template.clone())
Ok(module.content.clone())
}
}

View File

@ -1,4 +1,4 @@
use super::{Scope, Template};
use super::{Content, Scope};
use crate::source::{SourceId, SourceStore};
/// An evaluated module, ready for importing or layouting.
@ -7,7 +7,7 @@ pub struct Module {
/// The top-level definitions that were bound in this module.
pub scope: Scope,
/// The module's layoutable contents.
pub template: Template,
pub content: Content,
/// The source file revisions this module depends on.
pub deps: Vec<(SourceId, usize)>,
}

View File

@ -19,11 +19,11 @@ pub fn join(lhs: Value, rhs: Value) -> StrResult<Value> {
(a, None) => a,
(None, b) => b,
(Str(a), Str(b)) => Str(a + b),
(Str(a), Content(b)) => Content(super::Content::Text(a) + b),
(Content(a), Str(b)) => Content(a + super::Content::Text(b)),
(Content(a), Content(b)) => Content(a + b),
(Array(a), Array(b)) => Array(a + b),
(Dict(a), Dict(b)) => Dict(a + b),
(Template(a), Template(b)) => Template(a + b),
(Template(a), Str(b)) => Template(a + super::Template::Text(b)),
(Str(a), Template(b)) => Template(super::Template::Text(a) + b),
(a, b) => mismatch!("cannot join {} with {}", a, b),
})
}
@ -81,15 +81,16 @@ pub fn add(lhs: Value, rhs: Value) -> StrResult<Value> {
(Fractional(a), Fractional(b)) => Fractional(a + b),
(Str(a), Str(b)) => Str(a + b),
(Content(a), None) => Content(a),
(None, Content(b)) => Content(b),
(Content(a), Content(b)) => Content(a + b),
(Content(a), Str(b)) => Content(a + super::Content::Text(b)),
(Str(a), Content(b)) => Content(super::Content::Text(a) + b),
(Array(a), Array(b)) => Array(a + b),
(Dict(a), Dict(b)) => Dict(a + b),
(Template(a), None) => Template(a),
(None, Template(b)) => Template(b),
(Template(a), Template(b)) => Template(a + b),
(Template(a), Str(b)) => Template(a + super::Template::Text(b)),
(Str(a), Template(b)) => Template(super::Template::Text(a) + b),
(a, b) => {
if let (Dyn(a), Dyn(b)) = (&a, &b) {
// 1D alignments can be summed into 2D alignments.
@ -177,8 +178,8 @@ pub fn mul(lhs: Value, rhs: Value) -> StrResult<Value> {
(Int(a), Str(b)) => Str(repeat_str(b, a)?),
(Array(a), Int(b)) => Array(a.repeat(b)?),
(Int(a), Array(b)) => Array(b.repeat(a)?),
(Template(a), Int(b)) => Template(a.repeat(b)?),
(Int(a), Template(b)) => Template(b.repeat(a)?),
(Content(a), Int(b)) => Content(a.repeat(b)?),
(Int(a), Content(b)) => Content(b.repeat(a)?),
(a, b) => mismatch!("cannot multiply {} with {}", a, b),
})
@ -293,9 +294,9 @@ pub fn equal(lhs: &Value, rhs: &Value) -> bool {
(Fractional(a), Fractional(b)) => a == b,
(Color(a), Color(b)) => a == b,
(Str(a), Str(b)) => a == b,
(Content(a), Content(b)) => a == b,
(Array(a), Array(b)) => a == b,
(Dict(a), Dict(b)) => a == b,
(Template(a), Template(b)) => a == b,
(Func(a), Func(b)) => a == b,
(Dyn(a), Dyn(b)) => a == b,

View File

@ -3,15 +3,15 @@ use std::fmt::{self, Debug, Formatter};
use std::hash::Hash;
use std::sync::Arc;
use super::{StyleChain, Template};
use super::{Content, StyleChain};
use crate::diag::TypResult;
use crate::util::Prehashed;
use crate::Context;
/// A node that can be realized given some styles.
pub trait Show {
/// Realize the template in the given styles.
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template>;
/// Realize this node in the given styles.
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content>;
/// Convert to a packed show node.
fn pack(self) -> ShowNode
@ -42,7 +42,7 @@ impl ShowNode {
}
impl Show for ShowNode {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
self.0.show(ctx, styles)
}

View File

@ -3,7 +3,7 @@ use std::fmt::{self, Debug, Formatter};
use std::hash::{Hash, Hasher};
use std::sync::Arc;
use super::{Args, Func, Span, Template, Value};
use super::{Args, Content, Func, Span, Value};
use crate::diag::{At, TypResult};
use crate::library::layout::PageNode;
use crate::library::text::ParNode;
@ -414,7 +414,7 @@ impl<'a> StyleChain<'a> {
node: &dyn Any,
ctx: &mut Context,
values: impl IntoIterator<Item = Value>,
) -> TypResult<Option<Template>> {
) -> TypResult<Option<Content>> {
Ok(if let Some(recipe) = self.recipes(node.type_id()).next() {
let args = Args::from_values(recipe.span, values);
Some(recipe.func.call(ctx, args)?.cast().at(recipe.span)?)

View File

@ -4,7 +4,7 @@ use std::fmt::{self, Debug, Formatter};
use std::hash::{Hash, Hasher};
use std::sync::Arc;
use super::{ops, Args, Array, Class, Dict, Func, Layout, Template};
use super::{ops, Args, Array, Class, Content, Dict, Func, Layout};
use crate::diag::{with_alternative, StrResult};
use crate::geom::{Angle, Color, Fractional, Length, Linear, Relative, RgbaColor};
use crate::syntax::Spanned;
@ -37,12 +37,12 @@ pub enum Value {
Color(Color),
/// A string: `"string"`.
Str(EcoString),
/// A content value: `[*Hi* there]`.
Content(Content),
/// An array of values: `(1, "hi", 12cm)`.
Array(Array),
/// A dictionary value: `(color: #f79143, pattern: dashed)`.
Dict(Dict),
/// A template value: `[*Hi* there]`.
Template(Template),
/// An executable function.
Func(Func),
/// Captured arguments to a function.
@ -54,20 +54,20 @@ pub enum Value {
}
impl Value {
/// Create a template value from an inline-level node.
/// Create a content value from an inline-level node.
pub fn inline<T>(node: T) -> Self
where
T: Layout + Debug + Hash + Sync + Send + 'static,
{
Self::Template(Template::inline(node))
Self::Content(Content::inline(node))
}
/// Create a template value from a block-level node.
/// Create a content value from a block-level node.
pub fn block<T>(node: T) -> Self
where
T: Layout + Debug + Hash + Sync + Send + 'static,
{
Self::Template(Template::block(node))
Self::Content(Content::block(node))
}
/// The name of the stored value's type.
@ -85,9 +85,9 @@ impl Value {
Self::Fractional(_) => Fractional::TYPE_NAME,
Self::Color(_) => Color::TYPE_NAME,
Self::Str(_) => EcoString::TYPE_NAME,
Self::Content(_) => Content::TYPE_NAME,
Self::Array(_) => Array::TYPE_NAME,
Self::Dict(_) => Dict::TYPE_NAME,
Self::Template(_) => Template::TYPE_NAME,
Self::Func(_) => Func::TYPE_NAME,
Self::Args(_) => Args::TYPE_NAME,
Self::Class(_) => Class::TYPE_NAME,
@ -111,16 +111,16 @@ impl Value {
}
/// Return the display representation of the value.
pub fn display(self) -> Template {
pub fn display(self) -> Content {
match self {
Value::None => Template::new(),
Value::Int(v) => Template::Text(format_eco!("{}", v)),
Value::Float(v) => Template::Text(format_eco!("{}", v)),
Value::Str(v) => Template::Text(v),
Value::Template(v) => v,
Value::None => Content::new(),
Value::Int(v) => Content::Text(format_eco!("{}", v)),
Value::Float(v) => Content::Text(format_eco!("{}", v)),
Value::Str(v) => Content::Text(v),
Value::Content(v) => v,
// For values which can't be shown "naturally", we print the
// representation in monospace.
v => Template::Text(v.repr()).monospaced(),
v => Content::Text(v.repr()).monospaced(),
}
}
}
@ -146,9 +146,9 @@ impl Debug for Value {
Self::Fractional(v) => Debug::fmt(v, f),
Self::Color(v) => Debug::fmt(v, f),
Self::Str(v) => Debug::fmt(v, f),
Self::Content(_) => f.pad("<content>"),
Self::Array(v) => Debug::fmt(v, f),
Self::Dict(v) => Debug::fmt(v, f),
Self::Template(_) => f.pad("<template>"),
Self::Func(v) => Debug::fmt(v, f),
Self::Args(v) => Debug::fmt(v, f),
Self::Class(v) => Debug::fmt(v, f),
@ -185,9 +185,9 @@ impl Hash for Value {
Self::Fractional(v) => v.hash(state),
Self::Color(v) => v.hash(state),
Self::Str(v) => v.hash(state),
Self::Content(v) => v.hash(state),
Self::Array(v) => v.hash(state),
Self::Dict(v) => v.hash(state),
Self::Template(v) => v.hash(state),
Self::Func(v) => v.hash(state),
Self::Args(v) => v.hash(state),
Self::Class(v) => v.hash(state),
@ -441,9 +441,9 @@ primitive! { Linear: "relative length", Linear, Length(v) => v.into(), Relative(
primitive! { Fractional: "fractional length", Fractional }
primitive! { Color: "color", Color }
primitive! { EcoString: "string", Str }
primitive! { Content: "content", Content, None => Content::new() }
primitive! { Array: "array", Array }
primitive! { Dict: "dictionary", Dict }
primitive! { Template: "template", Template, None => Template::new() }
primitive! { Func: "function", Func, Class(v) => v.constructor() }
primitive! { Args: "arguments", Args }
primitive! { Class: "class", Class }

View File

@ -7,7 +7,7 @@
//! provided in the [AST] module.
//! - **Evaluation:** The next step is to [evaluate] the markup. This produces a
//! [module], consisting of a scope of values that were exported by the code
//! and a [template], a hierarchical, styled representation with the contents
//! and [content], a hierarchical, styled representation with the contents
//! of the module. The nodes of this tree are well structured and
//! order-independent and thus much better suited for layouting than the raw
//! markup.
@ -23,8 +23,8 @@
//! [AST]: syntax::ast
//! [evaluate]: eval::Eval
//! [module]: eval::Module
//! [template]: eval::Template
//! [layouted]: eval::Template::layout
//! [content]: eval::Content
//! [layouted]: eval::Content::layout
//! [PDF]: export::pdf
#![allow(clippy::len_without_is_empty)]
@ -110,8 +110,8 @@ impl Context {
/// Evaluate a source file and return the resulting module.
///
/// Returns either a module containing a scope with top-level bindings and a
/// layoutable template or diagnostics in the form of a vector of error
/// Returns either a module containing a scope with top-level bindings and
/// layoutable contents or diagnostics in the form of a vector of error
/// messages with file and span information.
pub fn evaluate(&mut self, id: SourceId) -> TypResult<Module> {
// Prevent cyclic evaluation.
@ -139,16 +139,12 @@ impl Context {
// Evaluate the module.
let prev = std::mem::replace(&mut self.deps, vec![(id, source.rev())]);
self.route.push(id);
let template = ast.eval(self, &mut scp);
let content = ast.eval(self, &mut scp);
self.route.pop().unwrap();
let deps = std::mem::replace(&mut self.deps, prev);
// Assemble the module.
let module = Module {
scope: scp.top,
template: template?,
deps,
};
let module = Module { scope: scp.top, content: content?, deps };
// Save the evaluated module.
self.modules.insert(id, module.clone());
@ -162,7 +158,7 @@ impl Context {
/// diagnostics in the form of a vector of error message with file and span
/// information.
pub fn typeset(&mut self, id: SourceId) -> TypResult<Vec<Arc<Frame>>> {
self.evaluate(id)?.template.layout(self)
self.evaluate(id)?.content.layout(self)
}
/// Resolve a user-entered path (relative to the current evaluation

View File

@ -6,8 +6,8 @@ pub struct HideNode(pub LayoutNode);
#[class]
impl HideNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::inline(Self(args.expect("body")?)))
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::inline(Self(args.expect("body")?)))
}
}

View File

@ -12,7 +12,7 @@ impl ImageNode {
/// How the image should adjust itself to a given area.
pub const FIT: ImageFit = ImageFit::Cover;
fn construct(ctx: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(ctx: &mut Context, args: &mut Args) -> TypResult<Content> {
let path = args.expect::<Spanned<EcoString>>("path to image file")?;
let full = ctx.resolve(&path.v);
let id = ctx.images.load(&full).map_err(|err| {
@ -25,7 +25,7 @@ impl ImageNode {
let width = args.named("width")?;
let height = args.named("height")?;
Ok(Template::inline(
Ok(Content::inline(
ImageNode(id).pack().sized(Spec::new(width, height)),
))
}

View File

@ -30,7 +30,7 @@ impl<const S: ShapeKind> ShapeNode<S> {
/// How much to pad the shape's content.
pub const PADDING: Linear = Linear::zero();
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
let size = match S {
SQUARE => args.named::<Length>("size")?.map(Linear::from),
CIRCLE => args.named::<Length>("radius")?.map(|r| 2.0 * Linear::from(r)),
@ -47,7 +47,7 @@ impl<const S: ShapeKind> ShapeNode<S> {
size => size,
};
Ok(Template::inline(
Ok(Content::inline(
Self(args.find()?).pack().sized(Spec::new(width, height)),
))
}

View File

@ -24,7 +24,7 @@ impl<const T: TransformKind> TransformNode<T> {
/// The origin of the transformation.
pub const ORIGIN: Spec<Option<Align>> = Spec::default();
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
let transform = match T {
MOVE => {
let tx = args.named("x")?.unwrap_or_default();
@ -43,7 +43,7 @@ impl<const T: TransformKind> TransformNode<T> {
}
};
Ok(Template::inline(Self {
Ok(Content::inline(Self {
transform,
child: args.expect("body")?,
}))

View File

@ -12,10 +12,10 @@ pub struct AlignNode {
#[class]
impl AlignNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
let aligns: Spec<_> = args.find()?.unwrap_or_default();
let body: LayoutNode = args.expect("body")?;
Ok(Template::block(body.aligned(aligns)))
Ok(Content::block(body.aligned(aligns)))
}
}

View File

@ -16,8 +16,8 @@ impl ColumnsNode {
/// The size of the gutter space between each column.
pub const GUTTER: Linear = Relative::new(0.04).into();
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::block(Self {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::block(Self {
columns: args.expect("column count")?,
child: args.expect("body")?,
}))
@ -105,7 +105,7 @@ pub struct ColbreakNode;
#[class]
impl ColbreakNode {
fn construct(_: &mut Context, _: &mut Args) -> TypResult<Template> {
Ok(Template::Colbreak)
fn construct(_: &mut Context, _: &mut Args) -> TypResult<Content> {
Ok(Content::Colbreak)
}
}

View File

@ -5,11 +5,11 @@ pub struct BoxNode;
#[class]
impl BoxNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
let width = args.named("width")?;
let height = args.named("height")?;
let body: LayoutNode = args.find()?.unwrap_or_default();
Ok(Template::inline(body.sized(Spec::new(width, height))))
Ok(Content::inline(body.sized(Spec::new(width, height))))
}
}
@ -18,7 +18,7 @@ pub struct BlockNode;
#[class]
impl BlockNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::Block(args.find()?.unwrap_or_default()))
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::Block(args.find()?.unwrap_or_default()))
}
}

View File

@ -13,13 +13,13 @@ pub struct GridNode {
#[class]
impl GridNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
let columns = args.named("columns")?.unwrap_or_default();
let rows = args.named("rows")?.unwrap_or_default();
let base_gutter: Vec<TrackSizing> = args.named("gutter")?.unwrap_or_default();
let column_gutter = args.named("column-gutter")?;
let row_gutter = args.named("row-gutter")?;
Ok(Template::block(Self {
Ok(Content::block(Self {
tracks: Spec::new(columns, rows),
gutter: Spec::new(
column_gutter.unwrap_or_else(|| base_gutter.clone()),

View File

@ -11,7 +11,7 @@ pub struct PadNode {
#[class]
impl PadNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
let all = args.find()?;
let hor = args.named("horizontal")?;
let ver = args.named("vertical")?;
@ -21,7 +21,7 @@ impl PadNode {
let bottom = args.named("bottom")?.or(ver).or(all).unwrap_or_default();
let body: LayoutNode = args.expect("body")?;
let padding = Sides::new(left, top, right, bottom);
Ok(Template::block(body.padded(padding)))
Ok(Content::block(body.padded(padding)))
}
}

View File

@ -32,8 +32,8 @@ impl PageNode {
/// The page's footer.
pub const FOOTER: Marginal = Marginal::None;
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::Page(Self(args.expect("body")?)))
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::Page(Self(args.expect("body")?)))
}
fn set(args: &mut Args, styles: &mut StyleMap) -> TypResult<()> {
@ -125,12 +125,12 @@ impl PageNode {
(Length::zero(), padding.top, header),
(size.y - padding.bottom, padding.bottom, footer),
] {
if let Some(template) = marginal.resolve(ctx, page)? {
if let Some(content) = marginal.resolve(ctx, page)? {
let pos = Point::new(padding.left, y);
let w = size.x - padding.left - padding.right;
let area = Size::new(w, h);
let pod = Regions::one(area, area, area.map(Length::is_finite));
let sub = Layout::layout(&template, ctx, &pod, styles)?.remove(0);
let sub = Layout::layout(&content, ctx, &pod, styles)?.remove(0);
Arc::make_mut(frame).push_frame(pos, sub);
}
}
@ -155,8 +155,8 @@ pub struct PagebreakNode;
#[class]
impl PagebreakNode {
fn construct(_: &mut Context, _: &mut Args) -> TypResult<Template> {
Ok(Template::Pagebreak)
fn construct(_: &mut Context, _: &mut Args) -> TypResult<Content> {
Ok(Content::Pagebreak)
}
}
@ -165,18 +165,18 @@ impl PagebreakNode {
pub enum Marginal {
/// Nothing,
None,
/// A bare template.
Template(Template),
/// A closure mapping from a page number to a template.
/// Bare content.
Content(Content),
/// A closure mapping from a page number to content.
Func(Func, Span),
}
impl Marginal {
/// Resolve the marginal based on the page number.
pub fn resolve(&self, ctx: &mut Context, page: usize) -> TypResult<Option<Template>> {
pub fn resolve(&self, ctx: &mut Context, page: usize) -> TypResult<Option<Content>> {
Ok(match self {
Self::None => None,
Self::Template(template) => Some(template.clone()),
Self::Content(content) => Some(content.clone()),
Self::Func(func, span) => {
let args = Args::from_values(*span, [Value::Int(page as i64)]);
func.call(ctx, args)?.cast().at(*span)?
@ -187,15 +187,15 @@ impl Marginal {
impl Cast<Spanned<Value>> for Marginal {
fn is(value: &Spanned<Value>) -> bool {
matches!(&value.v, Value::Template(_) | Value::Func(_))
matches!(&value.v, Value::Content(_) | Value::Func(_))
}
fn cast(value: Spanned<Value>) -> StrResult<Self> {
match value.v {
Value::None => Ok(Self::None),
Value::Template(v) => Ok(Self::Template(v)),
Value::Content(v) => Ok(Self::Content(v)),
Value::Func(v) => Ok(Self::Func(v, value.span)),
_ => Err("expected none, template or function")?,
_ => Err("expected none, content or function")?,
}
}
}

View File

@ -7,12 +7,12 @@ pub struct PlaceNode(pub LayoutNode);
#[class]
impl PlaceNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
let aligns = args.find()?.unwrap_or(Spec::with_x(Some(Align::Left)));
let tx = args.named("dx")?.unwrap_or_default();
let ty = args.named("dy")?.unwrap_or_default();
let body: LayoutNode = args.expect("body")?;
Ok(Template::block(Self(
Ok(Content::block(Self(
body.moved(Point::new(tx, ty)).aligned(aligns),
)))
}

View File

@ -5,8 +5,8 @@ pub struct HNode;
#[class]
impl HNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::Horizontal(args.expect("spacing")?))
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::Horizontal(args.expect("spacing")?))
}
}
@ -15,8 +15,8 @@ pub struct VNode;
#[class]
impl VNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::Vertical(args.expect("spacing")?))
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::Vertical(args.expect("spacing")?))
}
}

View File

@ -14,8 +14,8 @@ pub struct StackNode {
#[class]
impl StackNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::block(Self {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::block(Self {
dir: args.named("dir")?.unwrap_or(Dir::TTB),
spacing: args.named("spacing")?,
children: args.all()?,
@ -76,12 +76,12 @@ impl Debug for StackChild {
castable! {
StackChild,
Expected: "linear, fractional or template",
Expected: "linear, fractional or content",
Value::Length(v) => Self::Spacing(SpacingKind::Linear(v.into())),
Value::Relative(v) => Self::Spacing(SpacingKind::Linear(v.into())),
Value::Linear(v) => Self::Spacing(SpacingKind::Linear(v)),
Value::Fractional(v) => Self::Spacing(SpacingKind::Fractional(v)),
Value::Template(v) => Self::Node(v.pack()),
Value::Content(v) => Self::Node(v.pack()),
}
/// Performs stack layout.

View File

@ -13,8 +13,8 @@ pub struct MathNode {
#[class]
impl MathNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::show(Self {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self {
formula: args.expect("formula")?,
display: args.named("display")?.unwrap_or(false),
}))
@ -22,18 +22,18 @@ impl MathNode {
}
impl Show for MathNode {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
Ok(styles
.show(self, ctx, [
Value::Str(self.formula.clone()),
Value::Bool(self.display),
])?
.unwrap_or_else(|| {
let mut template = Template::Text(self.formula.trim().into());
let mut content = Content::Text(self.formula.trim().into());
if self.display {
template = Template::Block(template.pack());
content = Content::Block(content.pack());
}
template.monospaced()
content.monospaced()
}))
}
}

View File

@ -167,6 +167,6 @@ castable! {
castable! {
LayoutNode,
Expected: "template",
Value::Template(template) => template.pack(),
Expected: "content",
Value::Content(content) => content.pack(),
}

View File

@ -9,8 +9,8 @@ pub use typst_macros::class;
pub use crate::diag::{with_alternative, At, StrResult, TypResult};
pub use crate::eval::{
Arg, Args, Array, Cast, Construct, Dict, Func, Layout, LayoutNode, Merge, Property,
Regions, Scope, Set, Show, ShowNode, Smart, StyleChain, StyleMap, StyleVec, Template,
Arg, Args, Array, Cast, Construct, Content, Dict, Func, Layout, LayoutNode, Merge,
Property, Regions, Scope, Set, Show, ShowNode, Smart, StyleChain, StyleMap, StyleVec,
Value,
};
pub use crate::frame::*;

View File

@ -8,7 +8,7 @@ pub struct HeadingNode {
/// default style, this controls the text size of the heading.
pub level: usize,
/// The heading's contents.
pub body: Template,
pub body: Content,
}
#[class]
@ -35,8 +35,8 @@ impl HeadingNode {
/// Whether the heading is block-level.
pub const BLOCK: Leveled<bool> = Leveled::Value(true);
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::show(Self {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self {
body: args.expect("body")?,
level: args.named("level")?.unwrap_or(1),
}))
@ -44,7 +44,7 @@ impl HeadingNode {
}
impl Show for HeadingNode {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
macro_rules! resolve {
($key:expr) => {
styles.get_cloned($key).resolve(ctx, self.level)?
@ -55,7 +55,7 @@ impl Show for HeadingNode {
let mut body = styles
.show(self, ctx, [
Value::Int(self.level as i64),
Value::Template(self.body.clone()),
Value::Content(self.body.clone()),
])?
.unwrap_or_else(|| self.body.clone());
@ -90,22 +90,22 @@ impl Show for HeadingNode {
let above = resolve!(Self::ABOVE);
if !above.is_zero() {
seq.push(Template::Vertical(above.into()));
seq.push(Content::Vertical(above.into()));
}
seq.push(body);
let below = resolve!(Self::BELOW);
if !below.is_zero() {
seq.push(Template::Vertical(below.into()));
seq.push(Content::Vertical(below.into()));
}
let mut template = Template::sequence(seq).styled_with_map(map);
let mut content = Content::sequence(seq).styled_with_map(map);
if resolve!(Self::BLOCK) {
template = Template::block(template);
content = Content::block(content);
}
Ok(template)
Ok(content)
}
}

View File

@ -22,7 +22,7 @@ pub struct ListItem {
/// The number of the item.
pub number: Option<usize>,
/// The node that produces the item's body.
pub body: Box<Template>,
pub body: Box<Content>,
}
/// An ordered list.
@ -43,8 +43,8 @@ impl<const L: ListKind> ListNode<L> {
/// The extra padding below the list.
pub const BELOW: Length = Length::zero();
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::show(Self {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self {
start: args.named("start")?.unwrap_or(0),
wide: args.named("wide")?.unwrap_or(false),
items: args
@ -57,13 +57,13 @@ impl<const L: ListKind> ListNode<L> {
}
impl<const L: ListKind> Show for ListNode<L> {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> {
let template = if let Some(template) = styles.show(
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
let content = if let Some(content) = styles.show(
self,
ctx,
self.items.iter().map(|item| Value::Template((*item.body).clone())),
self.items.iter().map(|item| Value::Content((*item.body).clone())),
)? {
template
content
} else {
let mut children = vec![];
let mut number = self.start;
@ -91,7 +91,7 @@ impl<const L: ListKind> Show for ListNode<L> {
let indent = styles.get(Self::INDENT).resolve(em);
let body_indent = styles.get(Self::BODY_INDENT).resolve(em);
Template::block(GridNode {
Content::block(GridNode {
tracks: Spec::with_x(vec![
TrackSizing::Linear(indent.into()),
TrackSizing::Auto,
@ -106,17 +106,17 @@ impl<const L: ListKind> Show for ListNode<L> {
let mut seq = vec![];
let above = styles.get(Self::ABOVE);
if !above.is_zero() {
seq.push(Template::Vertical(above.into()));
seq.push(Content::Vertical(above.into()));
}
seq.push(template);
seq.push(content);
let below = styles.get(Self::BELOW);
if !below.is_zero() {
seq.push(Template::Vertical(below.into()));
seq.push(Content::Vertical(below.into()));
}
Ok(Template::sequence(seq))
Ok(Content::sequence(seq))
}
}
@ -135,15 +135,15 @@ pub const UNORDERED: ListKind = 0;
/// Ordered list labelling style.
pub const ORDERED: ListKind = 1;
/// Either a template or a closure mapping to a template.
/// Either content or a closure mapping to content.
#[derive(Debug, Clone, PartialEq, Hash)]
pub enum Label {
/// The default labelling.
Default,
/// A pattern with prefix, numbering, lower / upper case and suffix.
Pattern(EcoString, Numbering, bool, EcoString),
/// A bare template.
Template(Template),
/// Bare content.
Content(Content),
/// A closure mapping from an item number to a value.
Func(Func, Span),
}
@ -155,18 +155,18 @@ impl Label {
ctx: &mut Context,
kind: ListKind,
number: usize,
) -> TypResult<Template> {
) -> TypResult<Content> {
Ok(match self {
Self::Default => match kind {
UNORDERED => Template::Text('•'.into()),
ORDERED | _ => Template::Text(format_eco!("{}.", number)),
UNORDERED => Content::Text('•'.into()),
ORDERED | _ => Content::Text(format_eco!("{}.", number)),
},
Self::Pattern(prefix, numbering, upper, suffix) => {
let fmt = numbering.apply(number);
let mid = if *upper { fmt.to_uppercase() } else { fmt.to_lowercase() };
Template::Text(format_eco!("{}{}{}", prefix, mid, suffix))
Content::Text(format_eco!("{}{}{}", prefix, mid, suffix))
}
Self::Template(template) => template.clone(),
Self::Content(content) => content.clone(),
Self::Func(func, span) => {
let args = Args::from_values(*span, [Value::Int(number as i64)]);
func.call(ctx, args)?.cast().at(*span)?
@ -177,7 +177,7 @@ impl Label {
impl Cast<Spanned<Value>> for Label {
fn is(value: &Spanned<Value>) -> bool {
matches!(&value.v, Value::Template(_) | Value::Func(_))
matches!(&value.v, Value::Content(_) | Value::Func(_))
}
fn cast(value: Spanned<Value>) -> StrResult<Self> {
@ -200,9 +200,9 @@ impl Cast<Spanned<Value>> for Label {
let suffix = s.rest().into();
Ok(Self::Pattern(prefix.into(), numbering, upper, suffix))
}
Value::Template(v) => Ok(Self::Template(v)),
Value::Content(v) => Ok(Self::Content(v)),
Value::Func(v) => Ok(Self::Func(v, value.span)),
_ => Err("expected pattern, template or function")?,
_ => Err("expected pattern, content or function")?,
}
}
}

View File

@ -9,7 +9,7 @@ pub struct TableNode {
/// Defines sizing of gutter rows and columns between content.
pub gutter: Spec<Vec<TrackSizing>>,
/// The nodes to be arranged in the table.
pub children: Vec<Template>,
pub children: Vec<Content>,
}
#[class]
@ -25,13 +25,13 @@ impl TableNode {
/// How much to pad the cells's content.
pub const PADDING: Linear = Length::pt(5.0).into();
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
let columns = args.named("columns")?.unwrap_or_default();
let rows = args.named("rows")?.unwrap_or_default();
let base_gutter: Vec<TrackSizing> = args.named("gutter")?.unwrap_or_default();
let column_gutter = args.named("column-gutter")?;
let row_gutter = args.named("row-gutter")?;
Ok(Template::show(Self {
Ok(Content::show(Self {
tracks: Spec::new(columns, rows),
gutter: Spec::new(
column_gutter.unwrap_or_else(|| base_gutter.clone()),
@ -53,13 +53,13 @@ impl TableNode {
}
impl Show for TableNode {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> {
if let Some(template) = styles.show(
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
if let Some(content) = styles.show(
self,
ctx,
self.children.iter().map(|child| Value::Template(child.clone())),
self.children.iter().map(|child| Value::Content(child.clone())),
)? {
return Ok(template);
return Ok(content);
}
let primary = styles.get(Self::PRIMARY);
@ -91,7 +91,7 @@ impl Show for TableNode {
})
.collect();
Ok(Template::block(GridNode {
Ok(Content::block(GridNode {
tracks: self.tracks.clone(),
gutter: self.gutter.clone(),
children,

View File

@ -7,7 +7,7 @@ use crate::library::prelude::*;
/// Typeset underline, stricken-through or overlined text.
#[derive(Debug, Hash)]
pub struct DecoNode<const L: DecoLine>(pub Template);
pub struct DecoNode<const L: DecoLine>(pub Content);
/// Typeset underlined text.
pub type UnderlineNode = DecoNode<UNDERLINE>;
@ -37,15 +37,15 @@ impl<const L: DecoLine> DecoNode<L> {
/// with the glyphs. Does not apply to strikethrough.
pub const EVADE: bool = true;
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::show(Self(args.expect::<Template>("body")?)))
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self(args.expect::<Content>("body")?)))
}
}
impl<const L: DecoLine> Show for DecoNode<L> {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
Ok(styles
.show(self, ctx, [Value::Template(self.0.clone())])?
.show(self, ctx, [Value::Content(self.0.clone())])?
.unwrap_or_else(|| {
self.0.clone().styled(TextNode::LINES, vec![Decoration {
line: L,

View File

@ -8,7 +8,7 @@ pub struct LinkNode {
/// The url the link points to.
pub url: EcoString,
/// How the link is represented.
pub body: Option<Template>,
pub body: Option<Content>,
}
#[class]
@ -19,8 +19,8 @@ impl LinkNode {
/// Whether to underline link.
pub const UNDERLINE: bool = true;
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::show(Self {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self {
url: args.expect::<EcoString>("url")?,
body: args.find()?,
}))
@ -28,12 +28,12 @@ impl LinkNode {
}
impl Show for LinkNode {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
let mut body = styles
.show(self, ctx, [
Value::Str(self.url.clone()),
match &self.body {
Some(body) => Value::Template(body.clone()),
Some(body) => Value::Content(body.clone()),
None => Value::None,
},
])?
@ -45,7 +45,7 @@ impl Show for LinkNode {
text = text.trim_start_matches(prefix);
}
let shorter = text.len() < url.len();
Template::Text(if shorter { text.into() } else { url.clone() })
Content::Text(if shorter { text.into() } else { url.clone() })
});
let mut map = StyleMap::new();

View File

@ -110,7 +110,7 @@ impl TextNode {
#[skip]
pub const LINK: Option<EcoString> = None;
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
// The text constructor is special: It doesn't create a text node.
// Instead, it leaves the passed argument structurally unchanged, but
// styles all text in it.
@ -120,38 +120,38 @@ impl TextNode {
/// Strong text, rendered in boldface.
#[derive(Debug, Hash)]
pub struct StrongNode(pub Template);
pub struct StrongNode(pub Content);
#[class]
impl StrongNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::show(Self(args.expect("body")?)))
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self(args.expect("body")?)))
}
}
impl Show for StrongNode {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
Ok(styles
.show(self, ctx, [Value::Template(self.0.clone())])?
.show(self, ctx, [Value::Content(self.0.clone())])?
.unwrap_or_else(|| self.0.clone().styled(TextNode::STRONG, true)))
}
}
/// Emphasized text, rendered with an italic face.
#[derive(Debug, Hash)]
pub struct EmphNode(pub Template);
pub struct EmphNode(pub Content);
#[class]
impl EmphNode {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::show(Self(args.expect("body")?)))
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self(args.expect("body")?)))
}
}
impl Show for EmphNode {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
Ok(styles
.show(self, ctx, [Value::Template(self.0.clone())])?
.show(self, ctx, [Value::Content(self.0.clone())])?
.unwrap_or_else(|| self.0.clone().styled(TextNode::EMPH, true)))
}
}

View File

@ -45,12 +45,12 @@ impl ParNode {
/// The indent the first line of a consecutive paragraph should have.
pub const INDENT: Linear = Linear::zero();
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
// The paragraph constructor is special: It doesn't create a paragraph
// since that happens automatically through markup. Instead, it just
// lifts the passed body to the block level so that it won't merge with
// adjacent stuff and it styles the contained paragraphs.
Ok(Template::Block(args.expect("body")?))
Ok(Content::Block(args.expect("body")?))
}
fn set(args: &mut Args, styles: &mut StyleMap) -> TypResult<()> {
@ -185,8 +185,8 @@ pub struct ParbreakNode;
#[class]
impl ParbreakNode {
fn construct(_: &mut Context, _: &mut Args) -> TypResult<Template> {
Ok(Template::Parbreak)
fn construct(_: &mut Context, _: &mut Args) -> TypResult<Content> {
Ok(Content::Parbreak)
}
}
@ -195,8 +195,8 @@ pub struct LinebreakNode;
#[class]
impl LinebreakNode {
fn construct(_: &mut Context, _: &mut Args) -> TypResult<Template> {
Ok(Template::Linebreak)
fn construct(_: &mut Context, _: &mut Args) -> TypResult<Content> {
Ok(Content::Linebreak)
}
}

View File

@ -29,8 +29,8 @@ impl RawNode {
/// The language to syntax-highlight in.
pub const LANG: Option<EcoString> = None;
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Template> {
Ok(Template::show(Self {
fn construct(_: &mut Context, args: &mut Args) -> TypResult<Content> {
Ok(Content::show(Self {
text: args.expect("text")?,
block: args.named("block")?.unwrap_or(false),
}))
@ -38,10 +38,10 @@ impl RawNode {
}
impl Show for RawNode {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Template> {
fn show(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
let lang = styles.get_ref(Self::LANG).as_ref();
if let Some(template) = styles.show(self, ctx, [
if let Some(content) = styles.show(self, ctx, [
Value::Str(self.text.clone()),
match lang {
Some(lang) => Value::Str(lang.clone()),
@ -49,7 +49,7 @@ impl Show for RawNode {
},
Value::Bool(self.block),
])? {
return Ok(template);
return Ok(content);
}
let foreground = THEME
@ -59,7 +59,7 @@ impl Show for RawNode {
.unwrap_or(Color::BLACK)
.into();
let mut template = if matches!(
let mut content = if matches!(
lang.map(|s| s.to_lowercase()).as_deref(),
Some("typ" | "typst")
) {
@ -72,7 +72,7 @@ impl Show for RawNode {
seq.push(styled(&self.text[range], foreground, style));
});
Template::sequence(seq)
Content::sequence(seq)
} else if let Some(syntax) =
lang.and_then(|token| SYNTAXES.find_syntax_by_token(&token))
{
@ -80,7 +80,7 @@ impl Show for RawNode {
let mut highlighter = HighlightLines::new(syntax, &THEME);
for (i, line) in self.text.lines().enumerate() {
if i != 0 {
seq.push(Template::Linebreak);
seq.push(Content::Linebreak);
}
for (style, piece) in highlighter.highlight(line, &SYNTAXES) {
@ -88,23 +88,23 @@ impl Show for RawNode {
}
}
Template::sequence(seq)
Content::sequence(seq)
} else {
Template::Text(self.text.clone())
Content::Text(self.text.clone())
};
if self.block {
template = Template::Block(template.pack());
content = Content::Block(content.pack());
}
Ok(template.monospaced())
Ok(content.monospaced())
}
}
/// Style a piece of text with a syntect style.
fn styled(piece: &str, foreground: Paint, style: Style) -> Template {
fn styled(piece: &str, foreground: Paint, style: Style) -> Content {
let mut styles = StyleMap::new();
let mut body = Template::Text(piece.into());
let mut body = Content::Text(piece.into());
let paint = style.foreground.into();
if paint != foreground {

View File

@ -39,7 +39,7 @@ fn minmax(args: &mut Args, goal: Ordering) -> TypResult<Value> {
}
None => bail!(
span,
"cannot compare {} with {}",
"cannot compare {} and {}",
extremum.type_name(),
v.type_name(),
),

View File

@ -170,13 +170,13 @@ pub fn upper(_: &mut Context, args: &mut Args) -> TypResult<Value> {
case(Case::Upper, args)
}
/// Change the case of a string or template.
/// Change the case of a string or content.
fn case(case: Case, args: &mut Args) -> TypResult<Value> {
let Spanned { v, span } = args.expect("string or template")?;
let Spanned { v, span } = args.expect("string or content")?;
Ok(match v {
Value::Str(v) => Value::Str(case.apply(&v).into()),
Value::Template(v) => Value::Template(v.styled(TextNode::CASE, Some(case))),
v => bail!(span, "expected string or template, found {}", v.type_name()),
Value::Content(v) => Value::Content(v.styled(TextNode::CASE, Some(case))),
v => bail!(span, "expected string or content, found {}", v.type_name()),
})
}

View File

@ -4,8 +4,7 @@ use std::sync::Arc;
use crate::syntax::{Green, GreenNode, NodeKind};
use super::{
is_newline, parse, reparse_block, reparse_markup_elements, reparse_template,
TokenMode,
is_newline, parse, reparse_block, reparse_content, reparse_markup_elements, TokenMode,
};
/// Allows partial refreshs of the [`Green`] node tree.
@ -43,7 +42,7 @@ impl Reparser<'_> {
mut offset: usize,
outermost: bool,
) -> Option<Range<usize>> {
let child_mode = green.kind().mode().unwrap_or(TokenMode::Code);
let child_mode = green.kind().only_in_mode().unwrap_or(TokenMode::Code);
let original_count = green.children().len();
let mut search = SearchState::default();
@ -137,7 +136,7 @@ impl Reparser<'_> {
let superseded_span = pos.offset .. pos.offset + prev_len;
let func: Option<ReparseMode> = match child.kind() {
NodeKind::CodeBlock => Some(ReparseMode::Code),
NodeKind::TemplateBlock => Some(ReparseMode::Template),
NodeKind::ContentBlock => Some(ReparseMode::Content),
_ => None,
};
@ -168,7 +167,7 @@ impl Reparser<'_> {
if start.offset == self.replace_range.start
|| ahead_kind.only_at_start()
|| ahead_kind.mode() != Some(TokenMode::Markup)
|| ahead_kind.only_in_mode() != Some(TokenMode::Markup)
{
start = ahead;
at_start = ahead_at_start;
@ -216,7 +215,7 @@ impl Reparser<'_> {
&self.src[newborn_span.start ..],
newborn_span.len(),
),
ReparseMode::Template => reparse_template(
ReparseMode::Content => reparse_content(
&prefix,
&self.src[newborn_span.start ..],
newborn_span.len(),
@ -294,23 +293,13 @@ impl SearchState {
enum ReparseMode {
/// Reparse a code block, including its braces.
Code,
/// Reparse a template block, including its square brackets.
Template,
/// Reparse a content block, including its square brackets.
Content,
/// Reparse elements of the markup. The variant carries whether the node is
/// `at_start` and the minimum indent of the containing markup node.
MarkupElements(bool, usize),
}
impl NodeKind {
/// Whether this node has to appear at the start of a line.
pub fn only_at_start(&self) -> bool {
match self {
Self::Heading | Self::Enum | Self::List => true,
_ => false,
}
}
}
#[cfg(test)]
#[rustfmt::skip]
mod tests {

View File

@ -52,10 +52,10 @@ pub fn reparse_block(
Some((vec![first], terminated, 1))
}
/// Reparse a template literal.
/// Reparse a content block.
///
/// Returns `Some` if all of the input was consumed.
pub fn reparse_template(
pub fn reparse_content(
prefix: &str,
src: &str,
end_pos: usize,
@ -65,7 +65,7 @@ pub fn reparse_template(
return None;
}
template(&mut p);
content(&mut p);
let (mut green, terminated) = p.consume()?;
let first = green.remove(0);
@ -152,7 +152,7 @@ pub fn reparse_markup_elements(
/// Parse markup.
///
/// If `at_start` is true, things like headings that may only appear at the
/// beginning of a line or template are initially allowed.
/// beginning of a line or content block are initially allowed.
fn markup(p: &mut Parser, mut at_start: bool) {
p.perform(NodeKind::Markup(0), |p| {
while !p.eof() {
@ -235,9 +235,9 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) {
| NodeKind::Import
| NodeKind::Include => markup_expr(p),
// Block and template.
// Code and content block.
NodeKind::LeftBrace => block(p),
NodeKind::LeftBracket => template(p),
NodeKind::LeftBracket => content(p),
NodeKind::Error(_, _) => p.eat(),
_ => p.unexpected(),
@ -424,7 +424,7 @@ fn primary(p: &mut Parser, atomic: bool) -> ParseResult {
// Structures.
Some(NodeKind::LeftParen) => parenthesized(p, atomic),
Some(NodeKind::LeftBrace) => Ok(block(p)),
Some(NodeKind::LeftBracket) => Ok(template(p)),
Some(NodeKind::LeftBracket) => Ok(content(p)),
// Keywords.
Some(NodeKind::Let) => let_expr(p),
@ -679,9 +679,9 @@ fn block(p: &mut Parser) {
});
}
// Parse a template block: `[...]`.
fn template(p: &mut Parser) {
p.perform(NodeKind::TemplateBlock, |p| {
// Parse a content block: `[...]`.
fn content(p: &mut Parser) {
p.perform(NodeKind::ContentBlock, |p| {
p.start_group(Group::Bracket);
markup(p, true);
p.end_group();
@ -712,7 +712,7 @@ fn args(p: &mut Parser, direct: bool, brackets: bool) -> ParseResult {
}
while brackets && p.peek_direct() == Some(&NodeKind::LeftBracket) {
template(p);
content(p);
}
});
@ -922,7 +922,7 @@ fn return_expr(p: &mut Parser) -> ParseResult {
/// Parse a control flow body.
fn body(p: &mut Parser) -> ParseResult {
match p.peek() {
Some(NodeKind::LeftBracket) => Ok(template(p)),
Some(NodeKind::LeftBracket) => Ok(content(p)),
Some(NodeKind::LeftBrace) => Ok(block(p)),
_ => {
p.expected("body");

View File

@ -221,8 +221,8 @@ pub enum Expr {
Ident(Ident),
/// A code block: `{ let x = 1; x + 2 }`.
Code(CodeBlock),
/// A template block: `[*Hi* there!]`.
Template(TemplateBlock),
/// A content block: `[*Hi* there!]`.
Content(ContentBlock),
/// A grouped expression: `(1 + 2)`.
Group(GroupExpr),
/// An array expression: `(1, "hi", 12cm)`.
@ -270,7 +270,7 @@ impl TypedNode for Expr {
match node.kind() {
NodeKind::Ident(_) => node.cast().map(Self::Ident),
NodeKind::CodeBlock => node.cast().map(Self::Code),
NodeKind::TemplateBlock => node.cast().map(Self::Template),
NodeKind::ContentBlock => node.cast().map(Self::Content),
NodeKind::GroupExpr => node.cast().map(Self::Group),
NodeKind::ArrayExpr => node.cast().map(Self::Array),
NodeKind::DictExpr => node.cast().map(Self::Dict),
@ -299,7 +299,7 @@ impl TypedNode for Expr {
match self {
Self::Lit(v) => v.as_red(),
Self::Code(v) => v.as_red(),
Self::Template(v) => v.as_red(),
Self::Content(v) => v.as_red(),
Self::Ident(v) => v.as_red(),
Self::Array(v) => v.as_red(),
Self::Dict(v) => v.as_red(),
@ -419,14 +419,14 @@ impl CodeBlock {
}
node! {
/// A template block: `[*Hi* there!]`.
TemplateBlock: TemplateBlock
/// A content block: `[*Hi* there!]`.
ContentBlock: ContentBlock
}
impl TemplateBlock {
/// The contents of the template.
impl ContentBlock {
/// The contained markup.
pub fn body(&self) -> Markup {
self.0.cast_first_child().expect("template is missing body")
self.0.cast_first_child().expect("content is missing body")
}
}

View File

@ -203,7 +203,7 @@ impl Category {
NodeKind::List => None,
NodeKind::Enum => None,
NodeKind::CodeBlock => None,
NodeKind::TemplateBlock => None,
NodeKind::ContentBlock => None,
NodeKind::GroupExpr => None,
NodeKind::ArrayExpr => None,
NodeKind::DictExpr => None,

View File

@ -579,9 +579,9 @@ pub enum NodeKind {
From,
/// The `as` keyword.
As,
/// Template markup of which all lines must start in some column.
/// Markup of which all lines must start in some column.
///
/// Notably, the usize does not determine in which column the markup
/// Notably, the number does not determine in which column the markup
/// started, but to the right of which column all markup elements must be,
/// so it is zero except for headings and lists.
Markup(usize),
@ -644,8 +644,8 @@ pub enum NodeKind {
Str(EcoString),
/// A code block: `{ let x = 1; x + 2 }`.
CodeBlock,
/// A template block: `[*Hi* there!]`.
TemplateBlock,
/// A content block: `[*Hi* there!]`.
ContentBlock,
/// A grouped expression: `(1 + 2)`.
GroupExpr,
/// An array expression: `(1, "hi", 12cm)`.
@ -763,8 +763,16 @@ impl NodeKind {
}
}
/// Whether this node has to appear at the start of a line.
pub fn only_at_start(&self) -> bool {
match self {
Self::Heading | Self::Enum | Self::List => true,
_ => false,
}
}
/// Which mode this node can appear in, in both if `None`.
pub fn mode(&self) -> Option<TokenMode> {
pub fn only_in_mode(&self) -> Option<TokenMode> {
match self {
Self::Markup(_)
| Self::Linebreak
@ -782,7 +790,7 @@ impl NodeKind {
| Self::List
| Self::Raw(_)
| Self::Math(_) => Some(TokenMode::Markup),
Self::TemplateBlock
Self::ContentBlock
| Self::Space(_)
| Self::Ident(_)
| Self::CodeBlock
@ -884,7 +892,7 @@ impl NodeKind {
Self::Fraction(_) => "`fr` value",
Self::Str(_) => "string",
Self::CodeBlock => "code block",
Self::TemplateBlock => "template block",
Self::ContentBlock => "content block",
Self::GroupExpr => "group",
Self::ArrayExpr => "array",
Self::DictExpr => "dictionary",
@ -1008,7 +1016,7 @@ impl Hash for NodeKind {
Self::Fraction(v) => v.to_bits().hash(state),
Self::Str(v) => v.hash(state),
Self::CodeBlock => {}
Self::TemplateBlock => {}
Self::ContentBlock => {}
Self::GroupExpr => {}
Self::ArrayExpr => {}
Self::DictExpr => {}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -11,7 +11,7 @@
for s in parts [{s}]
}
// Evaluates to join of the templates and strings.
// Evaluates to join of the content and strings.
{
[How]
if true {
@ -52,13 +52,13 @@
// Some things can't be joined.
{
[A]
// Error: 3-4 cannot join template with integer
// Error: 3-4 cannot join content with integer
1
[B]
}
---
// Block directly in template also creates a scope.
// Block directly in markup also creates a scope.
{ let x = 1 }
// Error: 7-8 unknown variable
@ -103,7 +103,7 @@
}
---
// Template also creates a scope.
// Content blocks also create a scope.
[#let x = 1]
// Error: 2-3 unknown variable

View File

@ -63,7 +63,7 @@
---
#let f(x) = x
// Error: 1-6 expected callable or collection, found template
// Error: 1-6 expected callable or collection, found content
#f[1](2)
---

View File

@ -2,7 +2,7 @@
// Ref: false
---
// Don't parse closure directly in template.
// Don't parse closure directly in content.
// Ref: true
#let x = "\"hi\""

View File

@ -28,7 +28,7 @@
"]"
}
// Template body.
// Content block body.
// Should output `2345`.
#for v in (1, 2, 3, 4, 5, 6, 7) [#if v >= 2 and v <= 5 { repr(v) }]
@ -76,7 +76,7 @@
// Return value.
#test(for v in "" [], none)
#test(type(for v in "1" []), "template")
#test(type(for v in "1" []), "content")
---
// Uniterable expression.

View File

@ -16,7 +16,7 @@
One.
]
// Template in condition.
// Content block in condition.
#if [] != none [
Two.
]
@ -39,10 +39,10 @@
"Four" + point
}
// Template can be argument or body depending on whitespace.
// Content block can be argument or body depending on whitespace.
{
if "template" == type[b] [Fi] else [Nope]
if "template" == type [Nope] else [ve.]
if "content" == type[b] [Fi] else [Nope]
if "content" == type [Nope] else [ve.]
}
#let i = 3

View File

@ -14,7 +14,7 @@
#test({2*}, 2)
---
// Error: 2-12 cannot apply '+' to template
// Error: 2-12 cannot apply '+' to content
{+([] + [])}
---

View File

@ -2,7 +2,7 @@
// Ref: false
---
// Test template addition.
// Test adding content.
// Ref: true
{[*Hello* ] + [world!]}
@ -130,7 +130,7 @@
#test(test == test, true)
#test((() => {}) == (() => {}), false)
// Templates compare by some kind of equality.
// Content compares by hash equality.
#let t = [a]
#test(t == t, true)
#test([] == [], true)

View File

@ -39,7 +39,7 @@
{"a\n[]\"\u{1F680}string"}
---
// Templates.
// Content.
{[*{"H" + "i"} there*]}
---

View File

@ -30,7 +30,7 @@
#test(f(2), "ad")
---
// Test return with joining and template.
// Test return with joining and content.
// Ref: true
#let f(text, caption: none) = {

View File

@ -26,11 +26,11 @@
#test(while false {}, none)
#let i = 0
#test(type(while i < 1 [{ i += 1 }]), "template")
#test(type(while i < 1 [{ i += 1 }]), "content")
---
// Condition must be boolean.
// Error: 8-14 expected boolean, found template
// Error: 8-14 expected boolean, found content
#while [nope] [nope]
---

View File

@ -17,7 +17,7 @@
. Indented
---
// Test automatic numbering in summed templates.
// Test automatic numbering in summed content.
#for i in range(5) {
[. #roman(1 + i)]
}
@ -55,6 +55,6 @@
#set enum(label: "(())")
---
// Error: 18-28 expected template, found boolean
// Error: 18-28 expected content, found boolean
#set enum(label: n => false)
. A

View File

@ -28,7 +28,7 @@ paragraphs.
---
- Level 1
- Level [
2 through template
2 through content block
]
---

View File

@ -1,5 +1,5 @@
// Test that set affects the instantiation site and not the
// definition site of a template.
// definition site of a content.
---
// Test that text is affected by instantiation-site bold.

View File

@ -39,7 +39,7 @@ A [= Heading] C
= Heading
---
// Error: 1-28 expected template, found string
// Error: 1-28 expected content, found string
#show heading(_, _) as "hi"
= Heading

View File

@ -15,7 +15,7 @@ transports meaning from parchment to reader, the wave that sparks a flame
in booklovers and the great fulfiller of human need.
---
// Test wrap in template.
// Test wrap in content block.
A [_B #wrap c in [*#c*]; C_] D
---

View File

@ -7,7 +7,7 @@ _Emphasized and *strong* words!_
// Inside of a word it's a normal underscore or star.
hello_world Nutzer*innen
// Can contain paragraph in child template.
// Can contain paragraph in nested content block.
_Still [
] emphasized._

View File

@ -36,7 +36,7 @@
#test("(" + join("a", "b", "c", sep: ", ") + ")", "(a, b, c)")
---
// Test joining templates.
// Test content joining.
// Ref: true
#join([One], [Two], [Three], sep: [, ]).
@ -72,7 +72,7 @@
#float(float)
---
// Error: 6-8 cannot convert template to string
// Error: 6-8 cannot convert content to string
#str([])
---

View File

@ -24,7 +24,7 @@
#test(upper("Ελλάδα"), "ΕΛΛΆΔΑ")
---
// Error: 8-9 expected string or template, found integer
// Error: 8-9 expected string or content, found integer
#upper(1)
---
@ -35,9 +35,9 @@
#test(sorted((2, 1, 3, 10, 5, 8, 6, -7, 2)), (-7, 1, 2, 2, 3, 5, 6, 8, 10))
---
// Error: 9-21 cannot compare string with integer
// Error: 9-21 cannot order string and integer
#sorted((1, 2, "ab"))
---
// Error: 9-24 cannot compare template with template
// Error: 9-24 cannot order content and content
#sorted(([Hi], [There]))

View File

@ -54,7 +54,7 @@
#min()
---
// Error: 9-13 cannot compare integer with string
// Error: 9-13 cannot compare integer and string
#min(1, "hi")
---

View File

@ -14,17 +14,17 @@
"patterns": [{ "include": "$self" }]
},
{
"name": "meta.block.typst",
"name": "meta.block.code.typst",
"begin": "{",
"end": "}",
"captures": { "0": { "name": "punctuation.definition.block.typst" } },
"captures": { "0": { "name": "punctuation.definition.block.code.typst" } },
"patterns": [{ "include": "#code" }]
},
{
"name": "meta.template.typst",
"name": "meta.block.content.typst",
"begin": "\\[",
"end": "\\]",
"captures": { "0": { "name": "punctuation.definition.template.typst" } },
"captures": { "0": { "name": "punctuation.definition.block.content.typst" } },
"patterns": [{ "include": "#markup" }]
}
]