Reorganize library and tests
@ -395,7 +395,7 @@ impl SystemWorld {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
root,
|
root,
|
||||||
library: Prehashed::new(typst_library::new()),
|
library: Prehashed::new(typst_library::build()),
|
||||||
book: Prehashed::new(searcher.book),
|
book: Prehashed::new(searcher.book),
|
||||||
fonts: searcher.fonts,
|
fonts: searcher.fonts,
|
||||||
hashes: RefCell::default(),
|
hashes: RefCell::default(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::base::NumberingPattern;
|
use crate::compute::NumberingPattern;
|
||||||
use crate::layout::{BlockNode, GridNode, HNode, Spacing, TrackSizing};
|
use crate::layout::{BlockNode, GridNode, HNode, ParNode, Spacing, TrackSizing};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::text::{ParNode, SpaceNode, TextNode};
|
use crate::text::{SpaceNode, TextNode};
|
||||||
|
|
||||||
/// An unordered (bulleted) or ordered (numbered) list.
|
/// An unordered (bulleted) or ordered (numbered) list.
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
9
library/src/basics/mod.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
//! Common document elements.
|
||||||
|
|
||||||
|
mod heading;
|
||||||
|
mod list;
|
||||||
|
mod table;
|
||||||
|
|
||||||
|
pub use self::heading::*;
|
||||||
|
pub use self::list::*;
|
||||||
|
pub use self::table::*;
|
@ -106,12 +106,6 @@ pub fn str(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a blind text string.
|
|
||||||
pub fn lorem(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
|
||||||
let words: usize = args.expect("number of words")?;
|
|
||||||
Ok(Value::Str(lipsum::lipsum(words).into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a label from a string.
|
/// Create a label from a string.
|
||||||
pub fn label(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
pub fn label(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
||||||
Ok(Value::Label(Label(args.expect("string")?)))
|
Ok(Value::Label(Label(args.expect("string")?)))
|
@ -1,20 +1,9 @@
|
|||||||
//! Foundational functions.
|
use crate::prelude::*;
|
||||||
|
|
||||||
mod calc;
|
|
||||||
mod create;
|
|
||||||
mod data;
|
|
||||||
mod numbering;
|
|
||||||
|
|
||||||
pub use self::calc::*;
|
|
||||||
pub use self::create::*;
|
|
||||||
pub use self::data::*;
|
|
||||||
pub use self::numbering::*;
|
|
||||||
|
|
||||||
use comemo::Track;
|
use comemo::Track;
|
||||||
use typst::model::{self, Route, Vm};
|
|
||||||
use typst::syntax::Source;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use typst::model;
|
||||||
|
use typst::syntax::Source;
|
||||||
|
|
||||||
/// The name of a value's type.
|
/// The name of a value's type.
|
||||||
pub fn type_(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
pub fn type_(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
||||||
@ -39,7 +28,7 @@ pub fn assert(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
|||||||
pub fn eval(vm: &Vm, args: &mut Args) -> SourceResult<Value> {
|
pub fn eval(vm: &Vm, args: &mut Args) -> SourceResult<Value> {
|
||||||
let Spanned { v: text, span } = args.expect::<Spanned<String>>("source")?;
|
let Spanned { v: text, span } = args.expect::<Spanned<String>>("source")?;
|
||||||
let source = Source::synthesized(text, span);
|
let source = Source::synthesized(text, span);
|
||||||
let route = Route::default();
|
let route = model::Route::default();
|
||||||
let module = model::eval(vm.world(), route.track(), &source)?;
|
let module = model::eval(vm.world(), route.track(), &source)?;
|
||||||
Ok(Value::Content(module.content))
|
Ok(Value::Content(module.content))
|
||||||
}
|
}
|
13
library/src/compute/mod.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//! Computational functions.
|
||||||
|
|
||||||
|
mod calc;
|
||||||
|
mod create;
|
||||||
|
mod data;
|
||||||
|
mod foundations;
|
||||||
|
mod utility;
|
||||||
|
|
||||||
|
pub use self::calc::*;
|
||||||
|
pub use self::create::*;
|
||||||
|
pub use self::data::*;
|
||||||
|
pub use self::foundations::*;
|
||||||
|
pub use self::utility::*;
|
@ -4,6 +4,12 @@ use unscanny::Scanner;
|
|||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// Create a blind text string.
|
||||||
|
pub fn lorem(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
||||||
|
let words: usize = args.expect("number of words")?;
|
||||||
|
Ok(Value::Str(lipsum::lipsum(words).into()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Apply a numbering pattern to a number.
|
/// Apply a numbering pattern to a number.
|
||||||
pub fn numbering(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
pub fn numbering(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
||||||
let number = args.expect::<usize>("number")?;
|
let number = args.expect::<usize>("number")?;
|
||||||
@ -11,7 +17,15 @@ pub fn numbering(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
|||||||
Ok(Value::Str(pattern.apply(number).into()))
|
Ok(Value::Str(pattern.apply(number).into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A numbering pattern for lists or headings.
|
/// How to turn a number into text.
|
||||||
|
///
|
||||||
|
/// A pattern consists of a prefix, followed by one of `1`, `a`, `A`, `i`, `I`
|
||||||
|
/// or `*`, and then a suffix.
|
||||||
|
///
|
||||||
|
/// Examples of valid patterns:
|
||||||
|
/// - `1)`
|
||||||
|
/// - `a.`
|
||||||
|
/// - `(I)`
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct NumberingPattern {
|
pub struct NumberingPattern {
|
||||||
prefix: EcoString,
|
prefix: EcoString,
|
||||||
@ -60,7 +74,7 @@ castable! {
|
|||||||
|
|
||||||
/// Different kinds of numberings.
|
/// Different kinds of numberings.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum NumberingKind {
|
enum NumberingKind {
|
||||||
Arabic,
|
Arabic,
|
||||||
Letter,
|
Letter,
|
||||||
Roman,
|
Roman,
|
@ -1,5 +1,5 @@
|
|||||||
|
use super::{HorizontalAlign, ParNode};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::text::{HorizontalAlign, ParNode};
|
|
||||||
|
|
||||||
/// Align content along the layouting axes.
|
/// Align content along the layouting axes.
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use typst::model::Style;
|
use typst::model::Style;
|
||||||
|
|
||||||
use super::{AlignNode, BlockNode, ColbreakNode, PlaceNode, Spacing, VNode};
|
use super::{AlignNode, BlockNode, ColbreakNode, ParNode, PlaceNode, Spacing, VNode};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::text::ParNode;
|
|
||||||
|
|
||||||
/// Arrange spacing, paragraphs and block-level nodes into a flow.
|
/// Arrange spacing, paragraphs and block-level nodes into a flow.
|
||||||
///
|
///
|
||||||
|
@ -5,9 +5,12 @@ mod columns;
|
|||||||
mod container;
|
mod container;
|
||||||
mod flow;
|
mod flow;
|
||||||
mod grid;
|
mod grid;
|
||||||
|
mod hide;
|
||||||
mod pad;
|
mod pad;
|
||||||
mod page;
|
mod page;
|
||||||
|
mod par;
|
||||||
mod place;
|
mod place;
|
||||||
|
mod repeat;
|
||||||
mod spacing;
|
mod spacing;
|
||||||
mod stack;
|
mod stack;
|
||||||
mod transform;
|
mod transform;
|
||||||
@ -17,9 +20,12 @@ pub use self::columns::*;
|
|||||||
pub use self::container::*;
|
pub use self::container::*;
|
||||||
pub use self::flow::*;
|
pub use self::flow::*;
|
||||||
pub use self::grid::*;
|
pub use self::grid::*;
|
||||||
|
pub use self::hide::*;
|
||||||
pub use self::pad::*;
|
pub use self::pad::*;
|
||||||
pub use self::page::*;
|
pub use self::page::*;
|
||||||
|
pub use self::par::*;
|
||||||
pub use self::place::*;
|
pub use self::place::*;
|
||||||
|
pub use self::repeat::*;
|
||||||
pub use self::spacing::*;
|
pub use self::spacing::*;
|
||||||
pub use self::stack::*;
|
pub use self::stack::*;
|
||||||
pub use self::transform::*;
|
pub use self::transform::*;
|
||||||
@ -36,14 +42,11 @@ use typst::model::{
|
|||||||
};
|
};
|
||||||
use typst::World;
|
use typst::World;
|
||||||
|
|
||||||
|
use crate::basics::{DescNode, EnumNode, ListItem, ListNode, DESC, ENUM, LIST};
|
||||||
|
use crate::meta::DocumentNode;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::shared::BehavedBuilder;
|
use crate::shared::BehavedBuilder;
|
||||||
use crate::structure::{
|
use crate::text::{LinebreakNode, SmartQuoteNode, SpaceNode, TextNode};
|
||||||
DescNode, DocumentNode, EnumNode, ListItem, ListNode, DESC, ENUM, LIST,
|
|
||||||
};
|
|
||||||
use crate::text::{
|
|
||||||
LinebreakNode, ParNode, ParbreakNode, SmartQuoteNode, SpaceNode, TextNode,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Root-level layout.
|
/// Root-level layout.
|
||||||
#[capability]
|
#[capability]
|
||||||
|
@ -4,12 +4,11 @@ use xi_unicode::LineBreakIterator;
|
|||||||
|
|
||||||
use typst::model::Key;
|
use typst::model::Key;
|
||||||
|
|
||||||
use super::{
|
use super::{HNode, RepeatNode, Spacing};
|
||||||
shape, Lang, LinebreakNode, Quoter, Quotes, ShapedText, SmartQuoteNode, SpaceNode,
|
|
||||||
TextNode,
|
|
||||||
};
|
|
||||||
use crate::layout::{HNode, Spacing};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::text::{
|
||||||
|
shape, LinebreakNode, Quoter, Quotes, ShapedText, SmartQuoteNode, SpaceNode, TextNode,
|
||||||
|
};
|
||||||
|
|
||||||
/// Arrange text, spacing and inline-level nodes into a paragraph.
|
/// Arrange text, spacing and inline-level nodes into a paragraph.
|
||||||
#[derive(Hash)]
|
#[derive(Hash)]
|
||||||
@ -129,30 +128,6 @@ impl ParbreakNode {
|
|||||||
|
|
||||||
impl Unlabellable for ParbreakNode {}
|
impl Unlabellable for ParbreakNode {}
|
||||||
|
|
||||||
/// Repeats content to fill a line.
|
|
||||||
#[derive(Debug, Hash)]
|
|
||||||
pub struct RepeatNode(pub Content);
|
|
||||||
|
|
||||||
#[node(Layout, Inline)]
|
|
||||||
impl RepeatNode {
|
|
||||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
|
||||||
Ok(Self(args.expect("body")?).pack())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Layout for RepeatNode {
|
|
||||||
fn layout(
|
|
||||||
&self,
|
|
||||||
world: Tracked<dyn World>,
|
|
||||||
styles: StyleChain,
|
|
||||||
regions: &Regions,
|
|
||||||
) -> SourceResult<Fragment> {
|
|
||||||
self.0.layout(world, styles, regions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Inline for RepeatNode {}
|
|
||||||
|
|
||||||
/// Range of a substring of text.
|
/// Range of a substring of text.
|
||||||
type Range = std::ops::Range<usize>;
|
type Range = std::ops::Range<usize>;
|
||||||
|
|
25
library/src/layout/repeat.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// Repeats content to fill a line.
|
||||||
|
#[derive(Debug, Hash)]
|
||||||
|
pub struct RepeatNode(pub Content);
|
||||||
|
|
||||||
|
#[node(Layout, Inline)]
|
||||||
|
impl RepeatNode {
|
||||||
|
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||||
|
Ok(Self(args.expect("body")?).pack())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Layout for RepeatNode {
|
||||||
|
fn layout(
|
||||||
|
&self,
|
||||||
|
world: Tracked<dyn World>,
|
||||||
|
styles: StyleChain,
|
||||||
|
regions: &Regions,
|
||||||
|
) -> SourceResult<Fragment> {
|
||||||
|
self.0.layout(world, styles, regions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Inline for RepeatNode {}
|
@ -1,8 +1,7 @@
|
|||||||
use typst::model::StyledNode;
|
use typst::model::StyledNode;
|
||||||
|
|
||||||
use super::{AlignNode, Spacing};
|
use super::{AlignNode, ParNode, Spacing};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::text::ParNode;
|
|
||||||
|
|
||||||
/// Arrange content and spacing along an axis.
|
/// Arrange content and spacing along an axis.
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
//! Typst's standard library.
|
//! Typst's standard library.
|
||||||
|
|
||||||
pub mod base;
|
pub mod basics;
|
||||||
pub mod graphics;
|
pub mod compute;
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
|
pub mod meta;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
pub mod shared;
|
pub mod shared;
|
||||||
pub mod structure;
|
|
||||||
pub mod text;
|
pub mod text;
|
||||||
|
pub mod visualize;
|
||||||
|
|
||||||
use typst::geom::{Align, Color, Dir, GenAlign};
|
use typst::geom::{Align, Color, Dir, GenAlign};
|
||||||
use typst::model::{LangItems, Library, Node, NodeId, Scope, StyleMap};
|
use typst::model::{LangItems, Library, Node, NodeId, Scope, StyleMap};
|
||||||
@ -15,7 +16,7 @@ use typst::model::{LangItems, Library, Node, NodeId, Scope, StyleMap};
|
|||||||
use self::layout::LayoutRoot;
|
use self::layout::LayoutRoot;
|
||||||
|
|
||||||
/// Construct the standard library.
|
/// Construct the standard library.
|
||||||
pub fn new() -> Library {
|
pub fn build() -> Library {
|
||||||
Library { scope: scope(), styles: styles(), items: items() }
|
Library { scope: scope(), styles: styles(), items: items() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,97 +24,102 @@ pub fn new() -> Library {
|
|||||||
fn scope() -> Scope {
|
fn scope() -> Scope {
|
||||||
let mut std = Scope::new();
|
let mut std = Scope::new();
|
||||||
|
|
||||||
|
// Basics.
|
||||||
|
std.def_node::<basics::HeadingNode>("heading");
|
||||||
|
std.def_node::<basics::ListNode>("list");
|
||||||
|
std.def_node::<basics::EnumNode>("enum");
|
||||||
|
std.def_node::<basics::DescNode>("desc");
|
||||||
|
std.def_node::<basics::TableNode>("table");
|
||||||
|
|
||||||
// Text.
|
// Text.
|
||||||
|
std.def_node::<text::TextNode>("text");
|
||||||
std.def_node::<text::LinebreakNode>("linebreak");
|
std.def_node::<text::LinebreakNode>("linebreak");
|
||||||
std.def_node::<text::SmartQuoteNode>("smartquote");
|
std.def_node::<text::SmartQuoteNode>("smartquote");
|
||||||
std.def_node::<text::TextNode>("text");
|
|
||||||
std.def_node::<text::ParNode>("par");
|
|
||||||
std.def_node::<text::ParbreakNode>("parbreak");
|
|
||||||
std.def_node::<text::StrongNode>("strong");
|
std.def_node::<text::StrongNode>("strong");
|
||||||
std.def_node::<text::EmphNode>("emph");
|
std.def_node::<text::EmphNode>("emph");
|
||||||
std.def_node::<text::RawNode>("raw");
|
|
||||||
std.def_node::<text::UnderlineNode>("underline");
|
|
||||||
std.def_node::<text::StrikethroughNode>("strike");
|
|
||||||
std.def_node::<text::OverlineNode>("overline");
|
|
||||||
std.def_node::<text::SuperNode>("super");
|
|
||||||
std.def_node::<text::SubNode>("sub");
|
|
||||||
std.def_node::<text::LinkNode>("link");
|
|
||||||
std.def_node::<text::RepeatNode>("repeat");
|
|
||||||
std.def_fn("lower", text::lower);
|
std.def_fn("lower", text::lower);
|
||||||
std.def_fn("upper", text::upper);
|
std.def_fn("upper", text::upper);
|
||||||
std.def_fn("smallcaps", text::smallcaps);
|
std.def_fn("smallcaps", text::smallcaps);
|
||||||
|
std.def_node::<text::SubNode>("sub");
|
||||||
// Structure.
|
std.def_node::<text::SuperNode>("super");
|
||||||
std.def_node::<structure::DocumentNode>("document");
|
std.def_node::<text::UnderlineNode>("underline");
|
||||||
std.def_node::<structure::RefNode>("ref");
|
std.def_node::<text::StrikeNode>("strike");
|
||||||
std.def_node::<structure::HeadingNode>("heading");
|
std.def_node::<text::OverlineNode>("overline");
|
||||||
std.def_node::<structure::ListNode>("list");
|
std.def_node::<text::RawNode>("raw");
|
||||||
std.def_node::<structure::EnumNode>("enum");
|
|
||||||
std.def_node::<structure::DescNode>("desc");
|
|
||||||
std.def_node::<structure::TableNode>("table");
|
|
||||||
|
|
||||||
// Layout.
|
|
||||||
std.def_node::<layout::PageNode>("page");
|
|
||||||
std.def_node::<layout::PagebreakNode>("pagebreak");
|
|
||||||
std.def_node::<layout::HNode>("h");
|
|
||||||
std.def_node::<layout::VNode>("v");
|
|
||||||
std.def_node::<layout::BoxNode>("box");
|
|
||||||
std.def_node::<layout::BlockNode>("block");
|
|
||||||
std.def_node::<layout::AlignNode>("align");
|
|
||||||
std.def_node::<layout::PadNode>("pad");
|
|
||||||
std.def_node::<layout::StackNode>("stack");
|
|
||||||
std.def_node::<layout::GridNode>("grid");
|
|
||||||
std.def_node::<layout::ColumnsNode>("columns");
|
|
||||||
std.def_node::<layout::ColbreakNode>("colbreak");
|
|
||||||
std.def_node::<layout::PlaceNode>("place");
|
|
||||||
std.def_node::<layout::MoveNode>("move");
|
|
||||||
std.def_node::<layout::ScaleNode>("scale");
|
|
||||||
std.def_node::<layout::RotateNode>("rotate");
|
|
||||||
|
|
||||||
// Graphics.
|
|
||||||
std.def_node::<graphics::ImageNode>("image");
|
|
||||||
std.def_node::<graphics::LineNode>("line");
|
|
||||||
std.def_node::<graphics::RectNode>("rect");
|
|
||||||
std.def_node::<graphics::SquareNode>("square");
|
|
||||||
std.def_node::<graphics::EllipseNode>("ellipse");
|
|
||||||
std.def_node::<graphics::CircleNode>("circle");
|
|
||||||
std.def_node::<graphics::HideNode>("hide");
|
|
||||||
|
|
||||||
// Math.
|
// Math.
|
||||||
std.def_node::<math::MathNode>("math");
|
std.def_node::<math::MathNode>("math");
|
||||||
|
std.def_node::<math::AtomNode>("atom");
|
||||||
|
std.def_node::<math::FracNode>("frac");
|
||||||
std.define("sum", "∑");
|
std.define("sum", "∑");
|
||||||
std.define("in", "∈");
|
std.define("in", "∈");
|
||||||
std.define("arrow", "→");
|
std.define("arrow", "→");
|
||||||
std.define("NN", "ℕ");
|
std.define("NN", "ℕ");
|
||||||
std.define("RR", "ℝ");
|
std.define("RR", "ℝ");
|
||||||
|
|
||||||
// Base.
|
// Layout.
|
||||||
std.def_fn("type", base::type_);
|
std.def_node::<layout::PageNode>("page");
|
||||||
std.def_fn("repr", base::repr);
|
std.def_node::<layout::PagebreakNode>("pagebreak");
|
||||||
std.def_fn("assert", base::assert);
|
std.def_node::<layout::FlowNode>("flow");
|
||||||
std.def_fn("eval", base::eval);
|
std.def_node::<layout::VNode>("v");
|
||||||
std.def_fn("int", base::int);
|
std.def_node::<layout::ParNode>("par");
|
||||||
std.def_fn("float", base::float);
|
std.def_node::<layout::ParbreakNode>("parbreak");
|
||||||
std.def_fn("luma", base::luma);
|
std.def_node::<layout::HNode>("h");
|
||||||
std.def_fn("rgb", base::rgb);
|
std.def_node::<layout::BoxNode>("box");
|
||||||
std.def_fn("cmyk", base::cmyk);
|
std.def_node::<layout::BlockNode>("block");
|
||||||
std.def_fn("str", base::str);
|
std.def_node::<layout::StackNode>("stack");
|
||||||
std.def_fn("lorem", base::lorem);
|
std.def_node::<layout::GridNode>("grid");
|
||||||
std.def_fn("label", base::label);
|
std.def_node::<layout::ColumnsNode>("columns");
|
||||||
std.def_fn("regex", base::regex);
|
std.def_node::<layout::ColbreakNode>("colbreak");
|
||||||
std.def_fn("range", base::range);
|
std.def_node::<layout::PlaceNode>("place");
|
||||||
std.def_fn("numbering", base::numbering);
|
std.def_node::<layout::AlignNode>("align");
|
||||||
std.def_fn("abs", base::abs);
|
std.def_node::<layout::PadNode>("pad");
|
||||||
std.def_fn("min", base::min);
|
std.def_node::<layout::RepeatNode>("repeat");
|
||||||
std.def_fn("max", base::max);
|
std.def_node::<layout::MoveNode>("move");
|
||||||
std.def_fn("even", base::even);
|
std.def_node::<layout::ScaleNode>("scale");
|
||||||
std.def_fn("odd", base::odd);
|
std.def_node::<layout::RotateNode>("rotate");
|
||||||
std.def_fn("mod", base::mod_);
|
std.def_node::<layout::HideNode>("hide");
|
||||||
std.def_fn("csv", base::csv);
|
|
||||||
std.def_fn("json", base::json);
|
|
||||||
std.def_fn("xml", base::xml);
|
|
||||||
|
|
||||||
// Predefined colors.
|
// Visualize.
|
||||||
|
std.def_node::<visualize::ImageNode>("image");
|
||||||
|
std.def_node::<visualize::LineNode>("line");
|
||||||
|
std.def_node::<visualize::RectNode>("rect");
|
||||||
|
std.def_node::<visualize::SquareNode>("square");
|
||||||
|
std.def_node::<visualize::EllipseNode>("ellipse");
|
||||||
|
std.def_node::<visualize::CircleNode>("circle");
|
||||||
|
|
||||||
|
// Meta.
|
||||||
|
std.def_node::<meta::DocumentNode>("document");
|
||||||
|
std.def_node::<meta::RefNode>("ref");
|
||||||
|
std.def_node::<meta::LinkNode>("link");
|
||||||
|
|
||||||
|
// Compute.
|
||||||
|
std.def_fn("type", compute::type_);
|
||||||
|
std.def_fn("repr", compute::repr);
|
||||||
|
std.def_fn("assert", compute::assert);
|
||||||
|
std.def_fn("eval", compute::eval);
|
||||||
|
std.def_fn("int", compute::int);
|
||||||
|
std.def_fn("float", compute::float);
|
||||||
|
std.def_fn("luma", compute::luma);
|
||||||
|
std.def_fn("rgb", compute::rgb);
|
||||||
|
std.def_fn("cmyk", compute::cmyk);
|
||||||
|
std.def_fn("str", compute::str);
|
||||||
|
std.def_fn("label", compute::label);
|
||||||
|
std.def_fn("regex", compute::regex);
|
||||||
|
std.def_fn("range", compute::range);
|
||||||
|
std.def_fn("abs", compute::abs);
|
||||||
|
std.def_fn("min", compute::min);
|
||||||
|
std.def_fn("max", compute::max);
|
||||||
|
std.def_fn("even", compute::even);
|
||||||
|
std.def_fn("odd", compute::odd);
|
||||||
|
std.def_fn("mod", compute::mod_);
|
||||||
|
std.def_fn("csv", compute::csv);
|
||||||
|
std.def_fn("json", compute::json);
|
||||||
|
std.def_fn("xml", compute::xml);
|
||||||
|
std.def_fn("lorem", compute::lorem);
|
||||||
|
std.def_fn("numbering", compute::numbering);
|
||||||
|
|
||||||
|
// Colors.
|
||||||
std.define("black", Color::BLACK);
|
std.define("black", Color::BLACK);
|
||||||
std.define("gray", Color::GRAY);
|
std.define("gray", Color::GRAY);
|
||||||
std.define("silver", Color::SILVER);
|
std.define("silver", Color::SILVER);
|
||||||
@ -167,7 +173,7 @@ fn items() -> LangItems {
|
|||||||
text_id: NodeId::of::<text::TextNode>(),
|
text_id: NodeId::of::<text::TextNode>(),
|
||||||
text_str: |content| Some(&content.to::<text::TextNode>()?.0),
|
text_str: |content| Some(&content.to::<text::TextNode>()?.0),
|
||||||
smart_quote: |double| text::SmartQuoteNode { double }.pack(),
|
smart_quote: |double| text::SmartQuoteNode { double }.pack(),
|
||||||
parbreak: || text::ParbreakNode.pack(),
|
parbreak: || layout::ParbreakNode.pack(),
|
||||||
strong: |body| text::StrongNode(body).pack(),
|
strong: |body| text::StrongNode(body).pack(),
|
||||||
emph: |body| text::EmphNode(body).pack(),
|
emph: |body| text::EmphNode(body).pack(),
|
||||||
raw: |text, lang, block| {
|
raw: |text, lang, block| {
|
||||||
@ -177,15 +183,13 @@ fn items() -> LangItems {
|
|||||||
None => content,
|
None => content,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
link: |url| text::LinkNode::from_url(url).pack(),
|
link: |url| meta::LinkNode::from_url(url).pack(),
|
||||||
ref_: |target| structure::RefNode(target).pack(),
|
ref_: |target| meta::RefNode(target).pack(),
|
||||||
heading: |level, body| structure::HeadingNode { level, body }.pack(),
|
heading: |level, body| basics::HeadingNode { level, body }.pack(),
|
||||||
list_item: |body| structure::ListItem::List(Box::new(body)).pack(),
|
list_item: |body| basics::ListItem::List(Box::new(body)).pack(),
|
||||||
enum_item: |number, body| {
|
enum_item: |number, body| basics::ListItem::Enum(number, Box::new(body)).pack(),
|
||||||
structure::ListItem::Enum(number, Box::new(body)).pack()
|
|
||||||
},
|
|
||||||
desc_item: |term, body| {
|
desc_item: |term, body| {
|
||||||
structure::ListItem::Desc(Box::new(structure::DescItem { term, body })).pack()
|
basics::ListItem::Desc(Box::new(basics::DescItem { term, body })).pack()
|
||||||
},
|
},
|
||||||
math: |children, display| math::MathNode { children, display }.pack(),
|
math: |children, display| math::MathNode { children, display }.pack(),
|
||||||
math_atom: |atom| math::AtomNode(atom).pack(),
|
math_atom: |atom| math::AtomNode(atom).pack(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::layout::{LayoutRoot, PageNode};
|
use crate::layout::{LayoutRoot, PageNode};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// The root node of the model.
|
/// The root node that represents a full document.
|
||||||
#[derive(Hash)]
|
#[derive(Hash)]
|
||||||
pub struct DocumentNode(pub StyleVec<PageNode>);
|
pub struct DocumentNode(pub StyleVec<PageNode>);
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
use super::TextNode;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::text::TextNode;
|
||||||
|
|
||||||
/// Link text and other elements to a destination.
|
/// Link text and other elements to a destination.
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
9
library/src/meta/mod.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
//! Interaction between document parts.
|
||||||
|
|
||||||
|
mod document;
|
||||||
|
mod link;
|
||||||
|
mod reference;
|
||||||
|
|
||||||
|
pub use self::document::*;
|
||||||
|
pub use self::link::*;
|
||||||
|
pub use self::reference::*;
|
@ -1,13 +0,0 @@
|
|||||||
//! Document structuring.
|
|
||||||
|
|
||||||
mod document;
|
|
||||||
mod heading;
|
|
||||||
mod list;
|
|
||||||
mod reference;
|
|
||||||
mod table;
|
|
||||||
|
|
||||||
pub use self::document::*;
|
|
||||||
pub use self::heading::*;
|
|
||||||
pub use self::list::*;
|
|
||||||
pub use self::reference::*;
|
|
||||||
pub use self::table::*;
|
|
@ -12,7 +12,7 @@ pub struct DecoNode<const L: DecoLine>(pub Content);
|
|||||||
pub type UnderlineNode = DecoNode<UNDERLINE>;
|
pub type UnderlineNode = DecoNode<UNDERLINE>;
|
||||||
|
|
||||||
/// Typeset stricken-through text.
|
/// Typeset stricken-through text.
|
||||||
pub type StrikethroughNode = DecoNode<STRIKETHROUGH>;
|
pub type StrikeNode = DecoNode<STRIKETHROUGH>;
|
||||||
|
|
||||||
/// Typeset overlined text.
|
/// Typeset overlined text.
|
||||||
pub type OverlineNode = DecoNode<OVERLINE>;
|
pub type OverlineNode = DecoNode<OVERLINE>;
|
||||||
@ -65,7 +65,7 @@ impl<const L: DecoLine> Show for DecoNode<L> {
|
|||||||
///
|
///
|
||||||
/// For more details, see [`DecoNode`].
|
/// For more details, see [`DecoNode`].
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
pub(super) struct Decoration {
|
pub struct Decoration {
|
||||||
pub line: DecoLine,
|
pub line: DecoLine,
|
||||||
pub stroke: PartialStroke<Abs>,
|
pub stroke: PartialStroke<Abs>,
|
||||||
pub offset: Smart<Abs>,
|
pub offset: Smart<Abs>,
|
||||||
|
146
library/src/text/misc.rs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
use super::TextNode;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// A text space.
|
||||||
|
#[derive(Debug, Hash)]
|
||||||
|
pub struct SpaceNode;
|
||||||
|
|
||||||
|
#[node(Unlabellable, Behave)]
|
||||||
|
impl SpaceNode {
|
||||||
|
fn construct(_: &Vm, _: &mut Args) -> SourceResult<Content> {
|
||||||
|
Ok(Self.pack())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Unlabellable for SpaceNode {}
|
||||||
|
|
||||||
|
impl Behave for SpaceNode {
|
||||||
|
fn behaviour(&self) -> Behaviour {
|
||||||
|
Behaviour::Weak(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A line break.
|
||||||
|
#[derive(Debug, Hash)]
|
||||||
|
pub struct LinebreakNode {
|
||||||
|
pub justify: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[node(Behave)]
|
||||||
|
impl LinebreakNode {
|
||||||
|
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||||
|
let justify = args.named("justify")?.unwrap_or(false);
|
||||||
|
Ok(Self { justify }.pack())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Behave for LinebreakNode {
|
||||||
|
fn behaviour(&self) -> Behaviour {
|
||||||
|
Behaviour::Destructive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Strong content, rendered in boldface by default.
|
||||||
|
#[derive(Debug, Hash)]
|
||||||
|
pub struct StrongNode(pub Content);
|
||||||
|
|
||||||
|
#[node(Show)]
|
||||||
|
impl StrongNode {
|
||||||
|
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||||
|
Ok(Self(args.expect("body")?).pack())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn field(&self, name: &str) -> Option<Value> {
|
||||||
|
match name {
|
||||||
|
"body" => Some(Value::Content(self.0.clone())),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Show for StrongNode {
|
||||||
|
fn show(&self, _: Tracked<dyn World>, _: StyleChain) -> Content {
|
||||||
|
self.0.clone().styled(TextNode::BOLD, Toggle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Emphasized content, rendered with an italic font by default.
|
||||||
|
#[derive(Debug, Hash)]
|
||||||
|
pub struct EmphNode(pub Content);
|
||||||
|
|
||||||
|
#[node(Show)]
|
||||||
|
impl EmphNode {
|
||||||
|
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||||
|
Ok(Self(args.expect("body")?).pack())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn field(&self, name: &str) -> Option<Value> {
|
||||||
|
match name {
|
||||||
|
"body" => Some(Value::Content(self.0.clone())),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Show for EmphNode {
|
||||||
|
fn show(&self, _: Tracked<dyn World>, _: StyleChain) -> Content {
|
||||||
|
self.0.clone().styled(TextNode::ITALIC, Toggle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A toggle that turns on and off alternatingly if folded.
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub struct Toggle;
|
||||||
|
|
||||||
|
impl Fold for Toggle {
|
||||||
|
type Output = bool;
|
||||||
|
|
||||||
|
fn fold(self, outer: Self::Output) -> Self::Output {
|
||||||
|
!outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a string or content to lowercase.
|
||||||
|
pub fn lower(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
||||||
|
case(Case::Lower, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a string or content to uppercase.
|
||||||
|
pub fn upper(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
||||||
|
case(Case::Upper, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Change the case of text.
|
||||||
|
fn case(case: Case, args: &mut Args) -> SourceResult<Value> {
|
||||||
|
let Spanned { v, span } = args.expect("string or content")?;
|
||||||
|
Ok(match v {
|
||||||
|
Value::Str(v) => Value::Str(case.apply(&v).into()),
|
||||||
|
Value::Content(v) => Value::Content(v.styled(TextNode::CASE, Some(case))),
|
||||||
|
v => bail!(span, "expected string or content, found {}", v.type_name()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A case transformation on text.
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub enum Case {
|
||||||
|
/// Everything is lowercased.
|
||||||
|
Lower,
|
||||||
|
/// Everything is uppercased.
|
||||||
|
Upper,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Case {
|
||||||
|
/// Apply the case to a string.
|
||||||
|
pub fn apply(self, text: &str) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Lower => text.to_lowercase(),
|
||||||
|
Self::Upper => text.to_uppercase(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Display text in small capitals.
|
||||||
|
pub fn smallcaps(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
||||||
|
let body: Content = args.expect("content")?;
|
||||||
|
Ok(Value::Content(body.styled(TextNode::SMALLCAPS, true)))
|
||||||
|
}
|
@ -1,16 +1,15 @@
|
|||||||
//! Text handling and paragraph layout.
|
//! Text handling.
|
||||||
|
|
||||||
mod deco;
|
mod deco;
|
||||||
mod link;
|
mod misc;
|
||||||
mod par;
|
|
||||||
mod quotes;
|
mod quotes;
|
||||||
mod raw;
|
mod raw;
|
||||||
mod shaping;
|
mod shaping;
|
||||||
mod shift;
|
mod shift;
|
||||||
|
|
||||||
pub use self::deco::*;
|
pub use self::deco::*;
|
||||||
pub use self::link::*;
|
pub use self::misc::*;
|
||||||
pub use self::par::*;
|
pub use self::quotes::*;
|
||||||
pub use self::raw::*;
|
pub use self::raw::*;
|
||||||
pub use self::shaping::*;
|
pub use self::shaping::*;
|
||||||
pub use self::shift::*;
|
pub use self::shift::*;
|
||||||
@ -21,7 +20,7 @@ use rustybuzz::Tag;
|
|||||||
use typst::font::{FontMetrics, FontStretch, FontStyle, FontWeight, VerticalFontMetric};
|
use typst::font::{FontMetrics, FontStretch, FontStyle, FontWeight, VerticalFontMetric};
|
||||||
use typst::util::EcoString;
|
use typst::util::EcoString;
|
||||||
|
|
||||||
use self::quotes::*;
|
use crate::layout::ParNode;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// A single run of text with the same style.
|
/// A single run of text with the same style.
|
||||||
@ -114,19 +113,19 @@ impl TextNode {
|
|||||||
|
|
||||||
/// Whether the font weight should be increased by 300.
|
/// Whether the font weight should be increased by 300.
|
||||||
#[property(skip, fold)]
|
#[property(skip, fold)]
|
||||||
const BOLD: Toggle = false;
|
pub const BOLD: Toggle = false;
|
||||||
/// Whether the font style should be inverted.
|
/// Whether the font style should be inverted.
|
||||||
#[property(skip, fold)]
|
#[property(skip, fold)]
|
||||||
const ITALIC: Toggle = false;
|
pub const ITALIC: Toggle = false;
|
||||||
/// A case transformation that should be applied to the text.
|
/// A case transformation that should be applied to the text.
|
||||||
#[property(skip)]
|
#[property(skip)]
|
||||||
const CASE: Option<Case> = None;
|
pub const CASE: Option<Case> = None;
|
||||||
/// Whether small capital glyphs should be used. ("smcp")
|
/// Whether small capital glyphs should be used. ("smcp")
|
||||||
#[property(skip)]
|
#[property(skip)]
|
||||||
const SMALLCAPS: bool = false;
|
pub const SMALLCAPS: bool = false;
|
||||||
/// Decorative lines.
|
/// Decorative lines.
|
||||||
#[property(skip, fold)]
|
#[property(skip, fold)]
|
||||||
const DECO: Decoration = vec![];
|
pub const DECO: Decoration = vec![];
|
||||||
|
|
||||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||||
// The text constructor is special: It doesn't create a text node.
|
// The text constructor is special: It doesn't create a text node.
|
||||||
@ -409,161 +408,3 @@ impl Fold for FontFeatures {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A text space.
|
|
||||||
#[derive(Debug, Hash)]
|
|
||||||
pub struct SpaceNode;
|
|
||||||
|
|
||||||
#[node(Unlabellable, Behave)]
|
|
||||||
impl SpaceNode {
|
|
||||||
fn construct(_: &Vm, _: &mut Args) -> SourceResult<Content> {
|
|
||||||
Ok(Self.pack())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Unlabellable for SpaceNode {}
|
|
||||||
|
|
||||||
impl Behave for SpaceNode {
|
|
||||||
fn behaviour(&self) -> Behaviour {
|
|
||||||
Behaviour::Weak(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A line break.
|
|
||||||
#[derive(Debug, Hash)]
|
|
||||||
pub struct LinebreakNode {
|
|
||||||
pub justify: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[node(Behave)]
|
|
||||||
impl LinebreakNode {
|
|
||||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
|
||||||
let justify = args.named("justify")?.unwrap_or(false);
|
|
||||||
Ok(Self { justify }.pack())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Behave for LinebreakNode {
|
|
||||||
fn behaviour(&self) -> Behaviour {
|
|
||||||
Behaviour::Destructive
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A smart quote.
|
|
||||||
#[derive(Debug, Hash)]
|
|
||||||
pub struct SmartQuoteNode {
|
|
||||||
pub double: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[node]
|
|
||||||
impl SmartQuoteNode {
|
|
||||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
|
||||||
let double = args.named("double")?.unwrap_or(true);
|
|
||||||
Ok(Self { double }.pack())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a string or content to lowercase.
|
|
||||||
pub fn lower(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
|
||||||
case(Case::Lower, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a string or content to uppercase.
|
|
||||||
pub fn upper(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
|
||||||
case(Case::Upper, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Change the case of text.
|
|
||||||
fn case(case: Case, args: &mut Args) -> SourceResult<Value> {
|
|
||||||
let Spanned { v, span } = args.expect("string or content")?;
|
|
||||||
Ok(match v {
|
|
||||||
Value::Str(v) => Value::Str(case.apply(&v).into()),
|
|
||||||
Value::Content(v) => Value::Content(v.styled(TextNode::CASE, Some(case))),
|
|
||||||
v => bail!(span, "expected string or content, found {}", v.type_name()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A case transformation on text.
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub enum Case {
|
|
||||||
/// Everything is uppercased.
|
|
||||||
Upper,
|
|
||||||
/// Everything is lowercased.
|
|
||||||
Lower,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Case {
|
|
||||||
/// Apply the case to a string.
|
|
||||||
pub fn apply(self, text: &str) -> String {
|
|
||||||
match self {
|
|
||||||
Self::Upper => text.to_uppercase(),
|
|
||||||
Self::Lower => text.to_lowercase(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Display text in small capitals.
|
|
||||||
pub fn smallcaps(_: &Vm, args: &mut Args) -> SourceResult<Value> {
|
|
||||||
let body: Content = args.expect("content")?;
|
|
||||||
Ok(Value::Content(body.styled(TextNode::SMALLCAPS, true)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Strong content, rendered in boldface by default.
|
|
||||||
#[derive(Debug, Hash)]
|
|
||||||
pub struct StrongNode(pub Content);
|
|
||||||
|
|
||||||
#[node(Show)]
|
|
||||||
impl StrongNode {
|
|
||||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
|
||||||
Ok(Self(args.expect("body")?).pack())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn field(&self, name: &str) -> Option<Value> {
|
|
||||||
match name {
|
|
||||||
"body" => Some(Value::Content(self.0.clone())),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Show for StrongNode {
|
|
||||||
fn show(&self, _: Tracked<dyn World>, _: StyleChain) -> Content {
|
|
||||||
self.0.clone().styled(TextNode::BOLD, Toggle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Emphasized content, rendered with an italic font by default.
|
|
||||||
#[derive(Debug, Hash)]
|
|
||||||
pub struct EmphNode(pub Content);
|
|
||||||
|
|
||||||
#[node(Show)]
|
|
||||||
impl EmphNode {
|
|
||||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
|
||||||
Ok(Self(args.expect("body")?).pack())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn field(&self, name: &str) -> Option<Value> {
|
|
||||||
match name {
|
|
||||||
"body" => Some(Value::Content(self.0.clone())),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Show for EmphNode {
|
|
||||||
fn show(&self, _: Tracked<dyn World>, _: StyleChain) -> Content {
|
|
||||||
self.0.clone().styled(TextNode::ITALIC, Toggle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A toggle that turns on and off alternatingly if folded.
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub struct Toggle;
|
|
||||||
|
|
||||||
impl Fold for Toggle {
|
|
||||||
type Output = bool;
|
|
||||||
|
|
||||||
fn fold(self, outer: Self::Output) -> Self::Output {
|
|
||||||
!outer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,10 +1,24 @@
|
|||||||
use typst::syntax::is_newline;
|
use typst::syntax::is_newline;
|
||||||
|
|
||||||
use super::{Lang, Region};
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// A smart quote.
|
||||||
|
#[derive(Debug, Hash)]
|
||||||
|
pub struct SmartQuoteNode {
|
||||||
|
pub double: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[node]
|
||||||
|
impl SmartQuoteNode {
|
||||||
|
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||||
|
let double = args.named("double")?.unwrap_or(true);
|
||||||
|
Ok(Self { double }.pack())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// State machine for smart quote subtitution.
|
/// State machine for smart quote subtitution.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(super) struct Quoter {
|
pub struct Quoter {
|
||||||
/// How many quotes have been opened.
|
/// How many quotes have been opened.
|
||||||
quote_depth: usize,
|
quote_depth: usize,
|
||||||
/// Whether an opening quote might follow.
|
/// Whether an opening quote might follow.
|
||||||
@ -68,7 +82,7 @@ fn is_opening_bracket(c: char) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Decides which quotes to subtitute smart quotes with.
|
/// Decides which quotes to subtitute smart quotes with.
|
||||||
pub(super) struct Quotes<'s> {
|
pub struct Quotes<'s> {
|
||||||
/// The opening single quote.
|
/// The opening single quote.
|
||||||
pub single_open: &'s str,
|
pub single_open: &'s str,
|
||||||
/// The closing single quote.
|
/// The closing single quote.
|
||||||
|
@ -6,6 +6,7 @@ use typst::font::{Font, FontVariant};
|
|||||||
use typst::util::SliceExt;
|
use typst::util::SliceExt;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::meta::LinkNode;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// The result of shaping text.
|
/// The result of shaping text.
|
||||||
@ -13,7 +14,7 @@ use crate::prelude::*;
|
|||||||
/// This type contains owned or borrowed shaped text runs, which can be
|
/// This type contains owned or borrowed shaped text runs, which can be
|
||||||
/// measured, used to reshape substrings more quickly and converted into a
|
/// measured, used to reshape substrings more quickly and converted into a
|
||||||
/// frame.
|
/// frame.
|
||||||
pub(super) struct ShapedText<'a> {
|
pub struct ShapedText<'a> {
|
||||||
/// The text that was shaped.
|
/// The text that was shaped.
|
||||||
pub text: &'a str,
|
pub text: &'a str,
|
||||||
/// The text direction.
|
/// The text direction.
|
||||||
@ -32,7 +33,7 @@ pub(super) struct ShapedText<'a> {
|
|||||||
|
|
||||||
/// A single glyph resulting from shaping.
|
/// A single glyph resulting from shaping.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(super) struct ShapedGlyph {
|
pub struct ShapedGlyph {
|
||||||
/// The font the glyph is contained in.
|
/// The font the glyph is contained in.
|
||||||
pub font: Font,
|
pub font: Font,
|
||||||
/// The glyph's index in the font.
|
/// The glyph's index in the font.
|
||||||
@ -314,7 +315,7 @@ struct ShapingContext<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Shape text into [`ShapedText`].
|
/// Shape text into [`ShapedText`].
|
||||||
pub(super) fn shape<'a>(
|
pub fn shape<'a>(
|
||||||
world: Tracked<dyn World>,
|
world: Tracked<dyn World>,
|
||||||
text: &'a str,
|
text: &'a str,
|
||||||
styles: StyleChain<'a>,
|
styles: StyleChain<'a>,
|
||||||
|
@ -2,8 +2,8 @@ use std::ffi::OsStr;
|
|||||||
|
|
||||||
use typst::image::{Image, ImageFormat, RasterFormat, VectorFormat};
|
use typst::image::{Image, ImageFormat, RasterFormat, VectorFormat};
|
||||||
|
|
||||||
|
use crate::meta::LinkNode;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::text::LinkNode;
|
|
||||||
|
|
||||||
/// Show a raster or vector graphic.
|
/// Show a raster or vector graphic.
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
@ -1,11 +1,9 @@
|
|||||||
//! Graphical elements and effects.
|
//! Drawing and visualization.
|
||||||
|
|
||||||
mod hide;
|
|
||||||
mod image;
|
mod image;
|
||||||
mod line;
|
mod line;
|
||||||
mod shape;
|
mod shape;
|
||||||
|
|
||||||
pub use self::hide::*;
|
|
||||||
pub use self::image::*;
|
pub use self::image::*;
|
||||||
pub use self::line::*;
|
pub use self::line::*;
|
||||||
pub use self::shape::*;
|
pub use self::shape::*;
|
@ -1,7 +1,7 @@
|
|||||||
use std::f64::consts::SQRT_2;
|
use std::f64::consts::SQRT_2;
|
||||||
|
|
||||||
|
use crate::meta::LinkNode;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::text::LinkNode;
|
|
||||||
|
|
||||||
/// A sizable and fillable shape with optional content.
|
/// A sizable and fillable shape with optional content.
|
||||||
#[derive(Debug, Hash)]
|
#[derive(Debug, Hash)]
|
@ -1,4 +1,4 @@
|
|||||||
//! Document and computation model.
|
//! Content and computation model.
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod library;
|
mod library;
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
## Directory structure
|
## Directory structure
|
||||||
Top level directory structure:
|
Top level directory structure:
|
||||||
- `src`: Testing code.
|
- `src`: Testing code.
|
||||||
- `typ`: Input files.
|
- `typ`: Input files. The tests in `compiler` specifically test the compiler
|
||||||
|
while the others test the standard library (but also the compiler
|
||||||
|
indirectly).
|
||||||
- `ref`: Reference images which the output is compared with to determine whether
|
- `ref`: Reference images which the output is compared with to determine whether
|
||||||
a test passed or failed.
|
a test passed or failed.
|
||||||
- `png`: PNG files produced by tests.
|
- `png`: PNG files produced by tests.
|
||||||
|
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 595 B |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 6.9 KiB |
BIN
tests/ref/basics/desc.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
tests/ref/basics/enum.png
Normal file
After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 977 B |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
BIN
tests/ref/compiler/bench.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
tests/ref/compiler/block.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 520 B After Width: | Height: | Size: 520 B |
Before Width: | Height: | Size: 797 B After Width: | Height: | Size: 797 B |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
BIN
tests/ref/compiler/if.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
tests/ref/compiler/import.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
tests/ref/compiler/include.png
Normal file
After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
BIN
tests/ref/compiler/let.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
tests/ref/compiler/methods-color.png
Normal file
After Width: | Height: | Size: 506 B |
BIN
tests/ref/compiler/ops.png
Normal file
After Width: | Height: | Size: 972 B |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
BIN
tests/ref/compiler/return.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
BIN
tests/ref/compiler/while.png
Normal file
After Width: | Height: | Size: 995 B |
BIN
tests/ref/compute/create.png
Normal file
After Width: | Height: | Size: 155 B |
BIN
tests/ref/compute/data.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
tests/ref/compute/utility.png
Normal file
After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 94 B After Width: | Height: | Size: 92 B |
Before Width: | Height: | Size: 936 B |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.3 KiB |
BIN
tests/ref/layout/flow-orphan.png
Normal file
After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 430 B After Width: | Height: | Size: 423 B |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.6 KiB |