mirror of
https://github.com/typst/typst
synced 2025-08-13 22:57:56 +08:00
Compare commits
8 Commits
36d83c8c09
...
d6b0d68ffa
Author | SHA1 | Date | |
---|---|---|---|
|
d6b0d68ffa | ||
|
8f039dd614 | ||
|
2eef9e84e1 | ||
|
d11ad80dee | ||
|
bad343748b | ||
|
f31c971624 | ||
|
acd3a5b7a5 | ||
|
225e845021 |
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2995,6 +2995,7 @@ dependencies = [
|
|||||||
"typst-timing",
|
"typst-timing",
|
||||||
"typst-utils",
|
"typst-utils",
|
||||||
"unicode-math-class",
|
"unicode-math-class",
|
||||||
|
"unicode-normalization",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"unscanny",
|
"unscanny",
|
||||||
"usvg",
|
"usvg",
|
||||||
|
@ -129,6 +129,7 @@ unicode-bidi = "0.3.18"
|
|||||||
unicode-ident = "1.0"
|
unicode-ident = "1.0"
|
||||||
unicode-math-class = "0.1"
|
unicode-math-class = "0.1"
|
||||||
unicode-script = "0.5"
|
unicode-script = "0.5"
|
||||||
|
unicode-normalization = "0.1.24"
|
||||||
unicode-segmentation = "1"
|
unicode-segmentation = "1"
|
||||||
unscanny = "0.1"
|
unscanny = "0.1"
|
||||||
ureq = { version = "2", default-features = false, features = ["native-tls", "gzip", "json"] }
|
ureq = { version = "2", default-features = false, features = ["native-tls", "gzip", "json"] }
|
||||||
|
@ -55,11 +55,11 @@ pub fn watch(timer: &mut Timer, command: &WatchCommand) -> StrResult<()> {
|
|||||||
// Perform initial compilation.
|
// Perform initial compilation.
|
||||||
timer.record(&mut world, |world| compile_once(world, &mut config))??;
|
timer.record(&mut world, |world| compile_once(world, &mut config))??;
|
||||||
|
|
||||||
// Watch all dependencies of the initial compilation.
|
|
||||||
watcher.update(world.dependencies())?;
|
|
||||||
|
|
||||||
// Recompile whenever something relevant happens.
|
// Recompile whenever something relevant happens.
|
||||||
loop {
|
loop {
|
||||||
|
// Watch all dependencies of the most recent compilation.
|
||||||
|
watcher.update(world.dependencies())?;
|
||||||
|
|
||||||
// Wait until anything relevant happens.
|
// Wait until anything relevant happens.
|
||||||
watcher.wait()?;
|
watcher.wait()?;
|
||||||
|
|
||||||
@ -71,9 +71,6 @@ pub fn watch(timer: &mut Timer, command: &WatchCommand) -> StrResult<()> {
|
|||||||
|
|
||||||
// Evict the cache.
|
// Evict the cache.
|
||||||
comemo::evict(10);
|
comemo::evict(10);
|
||||||
|
|
||||||
// Adjust the file watching.
|
|
||||||
watcher.update(world.dependencies())?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,6 +201,10 @@ impl Watcher {
|
|||||||
let event = event
|
let event = event
|
||||||
.map_err(|err| eco_format!("failed to watch dependencies ({err})"))?;
|
.map_err(|err| eco_format!("failed to watch dependencies ({err})"))?;
|
||||||
|
|
||||||
|
if !is_relevant_event_kind(&event.kind) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Workaround for notify-rs' implicit unwatch on remove/rename
|
// Workaround for notify-rs' implicit unwatch on remove/rename
|
||||||
// (triggered by some editors when saving files) with the
|
// (triggered by some editors when saving files) with the
|
||||||
// inotify backend. By keeping track of the potentially
|
// inotify backend. By keeping track of the potentially
|
||||||
@ -224,7 +225,17 @@ impl Watcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relevant |= self.is_event_relevant(&event);
|
// Don't recompile because the output file changed.
|
||||||
|
// FIXME: This doesn't work properly for multifile image export.
|
||||||
|
if event
|
||||||
|
.paths
|
||||||
|
.iter()
|
||||||
|
.all(|path| is_same_file(path, &self.output).unwrap_or(false))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
relevant = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we found a relevant event or if any of the missing files now
|
// If we found a relevant event or if any of the missing files now
|
||||||
@ -234,32 +245,23 @@ impl Watcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether a watch event is relevant for compilation.
|
/// Whether a kind of watch event is relevant for compilation.
|
||||||
fn is_event_relevant(&self, event: ¬ify::Event) -> bool {
|
fn is_relevant_event_kind(kind: ¬ify::EventKind) -> bool {
|
||||||
// Never recompile because the output file changed.
|
match kind {
|
||||||
if event
|
notify::EventKind::Any => true,
|
||||||
.paths
|
notify::EventKind::Access(_) => false,
|
||||||
.iter()
|
notify::EventKind::Create(_) => true,
|
||||||
.all(|path| is_same_file(path, &self.output).unwrap_or(false))
|
notify::EventKind::Modify(kind) => match kind {
|
||||||
{
|
notify::event::ModifyKind::Any => true,
|
||||||
return false;
|
notify::event::ModifyKind::Data(_) => true,
|
||||||
}
|
notify::event::ModifyKind::Metadata(_) => false,
|
||||||
|
notify::event::ModifyKind::Name(_) => true,
|
||||||
match &event.kind {
|
notify::event::ModifyKind::Other => false,
|
||||||
notify::EventKind::Any => true,
|
},
|
||||||
notify::EventKind::Access(_) => false,
|
notify::EventKind::Remove(_) => true,
|
||||||
notify::EventKind::Create(_) => true,
|
notify::EventKind::Other => false,
|
||||||
notify::EventKind::Modify(kind) => match kind {
|
|
||||||
notify::event::ModifyKind::Any => true,
|
|
||||||
notify::event::ModifyKind::Data(_) => true,
|
|
||||||
notify::event::ModifyKind::Metadata(_) => false,
|
|
||||||
notify::event::ModifyKind::Name(_) => true,
|
|
||||||
notify::event::ModifyKind::Other => false,
|
|
||||||
},
|
|
||||||
notify::EventKind::Remove(_) => true,
|
|
||||||
notify::EventKind::Other => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,8 +83,8 @@ fn html_document_impl(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let output = handle_list(&mut engine, &mut locator, children.iter().copied())?;
|
let output = handle_list(&mut engine, &mut locator, children.iter().copied())?;
|
||||||
|
let introspector = Introspector::html(&output);
|
||||||
let root = root_element(output, &info)?;
|
let root = root_element(output, &info)?;
|
||||||
let introspector = Introspector::html(&root);
|
|
||||||
|
|
||||||
Ok(HtmlDocument { info, root, introspector })
|
Ok(HtmlDocument { info, root, introspector })
|
||||||
}
|
}
|
||||||
|
@ -410,9 +410,17 @@ fn field_access_completions(
|
|||||||
elem.into_iter().chain(Some(ty))
|
elem.into_iter().chain(Some(ty))
|
||||||
};
|
};
|
||||||
|
|
||||||
// Autocomplete methods from the element's or type's scope.
|
// Autocomplete methods from the element's or type's scope. We only complete
|
||||||
|
// those which have a `self` parameter.
|
||||||
for (name, binding) in scopes.flat_map(|scope| scope.iter()) {
|
for (name, binding) in scopes.flat_map(|scope| scope.iter()) {
|
||||||
ctx.call_completion(name.clone(), binding.read());
|
let Ok(func) = binding.read().clone().cast::<Func>() else { continue };
|
||||||
|
if func
|
||||||
|
.params()
|
||||||
|
.and_then(|params| params.first())
|
||||||
|
.is_some_and(|param| param.name == "self")
|
||||||
|
{
|
||||||
|
ctx.call_completion(name.clone(), binding.read());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(scope) = value.scope() {
|
if let Some(scope) = value.scope() {
|
||||||
@ -1764,6 +1772,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_autocomplete_type_methods() {
|
fn test_autocomplete_type_methods() {
|
||||||
test("#\"hello\".", -1).must_include(["len", "contains"]);
|
test("#\"hello\".", -1).must_include(["len", "contains"]);
|
||||||
|
test("#table().", -1).must_exclude(["cell"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -61,6 +61,7 @@ ttf-parser = { workspace = true }
|
|||||||
two-face = { workspace = true }
|
two-face = { workspace = true }
|
||||||
typed-arena = { workspace = true }
|
typed-arena = { workspace = true }
|
||||||
unicode-math-class = { workspace = true }
|
unicode-math-class = { workspace = true }
|
||||||
|
unicode-normalization = { workspace = true }
|
||||||
unicode-segmentation = { workspace = true }
|
unicode-segmentation = { workspace = true }
|
||||||
unscanny = { workspace = true }
|
unscanny = { workspace = true }
|
||||||
usvg = { workspace = true }
|
usvg = { workspace = true }
|
||||||
|
@ -312,7 +312,8 @@ impl Route<'_> {
|
|||||||
if !self.within(Route::MAX_SHOW_RULE_DEPTH) {
|
if !self.within(Route::MAX_SHOW_RULE_DEPTH) {
|
||||||
bail!(
|
bail!(
|
||||||
"maximum show rule depth exceeded";
|
"maximum show rule depth exceeded";
|
||||||
hint: "check whether the show rule matches its own output"
|
hint: "maybe a show rule matches its own output";
|
||||||
|
hint: "maybe there are too deeply nested elements"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -7,12 +7,13 @@ use comemo::Tracked;
|
|||||||
use ecow::EcoString;
|
use ecow::EcoString;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use typst_syntax::{Span, Spanned};
|
use typst_syntax::{Span, Spanned};
|
||||||
|
use unicode_normalization::UnicodeNormalization;
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use crate::diag::{bail, At, SourceResult, StrResult};
|
use crate::diag::{bail, At, SourceResult, StrResult};
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
use crate::foundations::{
|
use crate::foundations::{
|
||||||
cast, dict, func, repr, scope, ty, Array, Bytes, Context, Decimal, Dict, Func,
|
cast, dict, func, repr, scope, ty, Array, Bytes, Cast, Context, Decimal, Dict, Func,
|
||||||
IntoValue, Label, Repr, Type, Value, Version,
|
IntoValue, Label, Repr, Type, Value, Version,
|
||||||
};
|
};
|
||||||
use crate::layout::Alignment;
|
use crate::layout::Alignment;
|
||||||
@ -286,6 +287,30 @@ impl Str {
|
|||||||
Ok(c.into())
|
Ok(c.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Normalizes the string to the given Unicode normal form.
|
||||||
|
///
|
||||||
|
/// This is useful when manipulating strings containing Unicode combining
|
||||||
|
/// characters.
|
||||||
|
///
|
||||||
|
/// ```typ
|
||||||
|
/// #assert.eq("é".normalize(form: "nfd"), "e\u{0301}")
|
||||||
|
/// #assert.eq("ſ́".normalize(form: "nfkc"), "ś")
|
||||||
|
/// ```
|
||||||
|
#[func]
|
||||||
|
pub fn normalize(
|
||||||
|
&self,
|
||||||
|
#[named]
|
||||||
|
#[default(UnicodeNormalForm::Nfc)]
|
||||||
|
form: UnicodeNormalForm,
|
||||||
|
) -> Str {
|
||||||
|
match form {
|
||||||
|
UnicodeNormalForm::Nfc => self.nfc().collect(),
|
||||||
|
UnicodeNormalForm::Nfd => self.nfd().collect(),
|
||||||
|
UnicodeNormalForm::Nfkc => self.nfkc().collect(),
|
||||||
|
UnicodeNormalForm::Nfkd => self.nfkd().collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether the string contains the specified pattern.
|
/// Whether the string contains the specified pattern.
|
||||||
///
|
///
|
||||||
/// This method also has dedicated syntax: You can write `{"bc" in "abcd"}`
|
/// This method also has dedicated syntax: You can write `{"bc" in "abcd"}`
|
||||||
@ -788,6 +813,25 @@ cast! {
|
|||||||
v: Str => Self::Str(v),
|
v: Str => Self::Str(v),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A Unicode normalization form.
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
|
||||||
|
pub enum UnicodeNormalForm {
|
||||||
|
/// Canonical composition where e.g. accented letters are turned into a
|
||||||
|
/// single Unicode codepoint.
|
||||||
|
#[string("nfc")]
|
||||||
|
Nfc,
|
||||||
|
/// Canonical decomposition where e.g. accented letters are split into a
|
||||||
|
/// separate base and diacritic.
|
||||||
|
#[string("nfd")]
|
||||||
|
Nfd,
|
||||||
|
/// Like NFC, but using the Unicode compatibility decompositions.
|
||||||
|
#[string("nfkc")]
|
||||||
|
Nfkc,
|
||||||
|
/// Like NFD, but using the Unicode compatibility decompositions.
|
||||||
|
#[string("nfkd")]
|
||||||
|
Nfkd,
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert an item of std's `match_indices` to a dictionary.
|
/// Convert an item of std's `match_indices` to a dictionary.
|
||||||
fn match_to_dict((start, text): (usize, &str)) -> Dict {
|
fn match_to_dict((start, text): (usize, &str)) -> Dict {
|
||||||
dict! {
|
dict! {
|
||||||
|
@ -10,7 +10,7 @@ use typst_utils::NonZeroExt;
|
|||||||
|
|
||||||
use crate::diag::{bail, StrResult};
|
use crate::diag::{bail, StrResult};
|
||||||
use crate::foundations::{Content, Label, Repr, Selector};
|
use crate::foundations::{Content, Label, Repr, Selector};
|
||||||
use crate::html::{HtmlElement, HtmlNode};
|
use crate::html::HtmlNode;
|
||||||
use crate::introspection::{Location, Tag};
|
use crate::introspection::{Location, Tag};
|
||||||
use crate::layout::{Frame, FrameItem, Page, Point, Position, Transform};
|
use crate::layout::{Frame, FrameItem, Page, Point, Position, Transform};
|
||||||
use crate::model::Numbering;
|
use crate::model::Numbering;
|
||||||
@ -55,8 +55,8 @@ impl Introspector {
|
|||||||
|
|
||||||
/// Creates an introspector for HTML.
|
/// Creates an introspector for HTML.
|
||||||
#[typst_macros::time(name = "introspect html")]
|
#[typst_macros::time(name = "introspect html")]
|
||||||
pub fn html(root: &HtmlElement) -> Self {
|
pub fn html(output: &[HtmlNode]) -> Self {
|
||||||
IntrospectorBuilder::new().build_html(root)
|
IntrospectorBuilder::new().build_html(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over all locatable elements.
|
/// Iterates over all locatable elements.
|
||||||
@ -392,9 +392,9 @@ impl IntrospectorBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Build an introspector for an HTML document.
|
/// Build an introspector for an HTML document.
|
||||||
fn build_html(mut self, root: &HtmlElement) -> Introspector {
|
fn build_html(mut self, output: &[HtmlNode]) -> Introspector {
|
||||||
let mut elems = Vec::new();
|
let mut elems = Vec::new();
|
||||||
self.discover_in_html(&mut elems, root);
|
self.discover_in_html(&mut elems, output);
|
||||||
self.finalize(elems)
|
self.finalize(elems)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,16 +434,16 @@ impl IntrospectorBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Processes the tags in the HTML element.
|
/// Processes the tags in the HTML element.
|
||||||
fn discover_in_html(&mut self, sink: &mut Vec<Pair>, elem: &HtmlElement) {
|
fn discover_in_html(&mut self, sink: &mut Vec<Pair>, nodes: &[HtmlNode]) {
|
||||||
for child in &elem.children {
|
for node in nodes {
|
||||||
match child {
|
match node {
|
||||||
HtmlNode::Tag(tag) => self.discover_in_tag(
|
HtmlNode::Tag(tag) => self.discover_in_tag(
|
||||||
sink,
|
sink,
|
||||||
tag,
|
tag,
|
||||||
Position { page: NonZeroUsize::ONE, point: Point::zero() },
|
Position { page: NonZeroUsize::ONE, point: Point::zero() },
|
||||||
),
|
),
|
||||||
HtmlNode::Text(_, _) => {}
|
HtmlNode::Text(_, _) => {}
|
||||||
HtmlNode::Element(elem) => self.discover_in_html(sink, elem),
|
HtmlNode::Element(elem) => self.discover_in_html(sink, &elem.children),
|
||||||
HtmlNode::Frame(frame) => self.discover_in_frame(
|
HtmlNode::Frame(frame) => self.discover_in_frame(
|
||||||
sink,
|
sink,
|
||||||
frame,
|
frame,
|
||||||
|
@ -50,6 +50,42 @@ impl Dir {
|
|||||||
pub const TTB: Self = Self::TTB;
|
pub const TTB: Self = Self::TTB;
|
||||||
pub const BTT: Self = Self::BTT;
|
pub const BTT: Self = Self::BTT;
|
||||||
|
|
||||||
|
/// Returns a direction from a starting point.
|
||||||
|
///
|
||||||
|
/// ```example
|
||||||
|
/// direction.from(left) \
|
||||||
|
/// direction.from(right) \
|
||||||
|
/// direction.from(top) \
|
||||||
|
/// direction.from(bottom)
|
||||||
|
/// ```
|
||||||
|
#[func]
|
||||||
|
pub const fn from(side: Side) -> Dir {
|
||||||
|
match side {
|
||||||
|
Side::Left => Self::LTR,
|
||||||
|
Side::Right => Self::RTL,
|
||||||
|
Side::Top => Self::TTB,
|
||||||
|
Side::Bottom => Self::BTT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a direction from an end point.
|
||||||
|
///
|
||||||
|
/// ```example
|
||||||
|
/// direction.to(left) \
|
||||||
|
/// direction.to(right) \
|
||||||
|
/// direction.to(top) \
|
||||||
|
/// direction.to(bottom)
|
||||||
|
/// ```
|
||||||
|
#[func]
|
||||||
|
pub const fn to(side: Side) -> Dir {
|
||||||
|
match side {
|
||||||
|
Side::Right => Self::LTR,
|
||||||
|
Side::Left => Self::RTL,
|
||||||
|
Side::Bottom => Self::TTB,
|
||||||
|
Side::Top => Self::BTT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The axis this direction belongs to, either `{"horizontal"}` or
|
/// The axis this direction belongs to, either `{"horizontal"}` or
|
||||||
/// `{"vertical"}`.
|
/// `{"vertical"}`.
|
||||||
///
|
///
|
||||||
@ -65,6 +101,22 @@ impl Dir {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The corresponding sign, for use in calculations.
|
||||||
|
///
|
||||||
|
/// ```example
|
||||||
|
/// #ltr.sign() \
|
||||||
|
/// #rtl.sign() \
|
||||||
|
/// #ttb.sign() \
|
||||||
|
/// #btt.sign()
|
||||||
|
/// ```
|
||||||
|
#[func]
|
||||||
|
pub const fn sign(self) -> i64 {
|
||||||
|
match self {
|
||||||
|
Self::LTR | Self::TTB => 1,
|
||||||
|
Self::RTL | Self::BTT => -1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The start point of this direction, as an alignment.
|
/// The start point of this direction, as an alignment.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
|
@ -56,7 +56,7 @@ requirements with examples.
|
|||||||
Typst's default page size is A4 paper. Depending on your region and your use
|
Typst's default page size is A4 paper. Depending on your region and your use
|
||||||
case, you will want to change this. You can do this by using the
|
case, you will want to change this. You can do this by using the
|
||||||
[`{page}`]($page) set rule and passing it a string argument to use a common page
|
[`{page}`]($page) set rule and passing it a string argument to use a common page
|
||||||
size. Options include the complete ISO 216 series (e.g. `"iso-a4"`, `"iso-c2"`),
|
size. Options include the complete ISO 216 series (e.g. `"a4"` and `"iso-c2"`),
|
||||||
customary US formats like `"us-legal"` or `"us-letter"`, and more. Check out the
|
customary US formats like `"us-legal"` or `"us-letter"`, and more. Check out the
|
||||||
reference for the [page's paper argument]($page.paper) to learn about all
|
reference for the [page's paper argument]($page.paper) to learn about all
|
||||||
available options.
|
available options.
|
||||||
|
2
tests/ref/html/html-elem-metadata.html
Normal file
2
tests/ref/html/html-elem-metadata.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>Hi</html>
|
@ -86,6 +86,13 @@
|
|||||||
// Error: 2-28 0x110000 is not a valid codepoint
|
// Error: 2-28 0x110000 is not a valid codepoint
|
||||||
#str.from-unicode(0x110000) // 0x10ffff is the highest valid code point
|
#str.from-unicode(0x110000) // 0x10ffff is the highest valid code point
|
||||||
|
|
||||||
|
--- str-normalize ---
|
||||||
|
// Test the `normalize` method.
|
||||||
|
#test("e\u{0301}".normalize(form: "nfc"), "é")
|
||||||
|
#test("é".normalize(form: "nfd"), "e\u{0301}")
|
||||||
|
#test("ſ\u{0301}".normalize(form: "nfkc"), "ś")
|
||||||
|
#test("ſ\u{0301}".normalize(form: "nfkd"), "s\u{0301}")
|
||||||
|
|
||||||
--- string-len ---
|
--- string-len ---
|
||||||
// Test the `len` method.
|
// Test the `len` method.
|
||||||
#test("Hello World!".len(), 12)
|
#test("Hello World!".len(), 12)
|
||||||
|
@ -5,3 +5,11 @@
|
|||||||
// Error: 2-19 `<html>` element must be the only element in the document
|
// Error: 2-19 `<html>` element must be the only element in the document
|
||||||
#html.elem("html")
|
#html.elem("html")
|
||||||
Text
|
Text
|
||||||
|
|
||||||
|
--- html-elem-metadata html ---
|
||||||
|
#html.elem("html", context {
|
||||||
|
let val = query(<l>).first().value
|
||||||
|
test(val, "Hi")
|
||||||
|
val
|
||||||
|
})
|
||||||
|
#metadata("Hi") <l>
|
||||||
|
@ -1,10 +1,35 @@
|
|||||||
|
--- dir-from ---
|
||||||
|
#test(direction.from(left), ltr)
|
||||||
|
#test(direction.from(right), rtl)
|
||||||
|
#test(direction.from(top), ttb)
|
||||||
|
#test(direction.from(bottom), btt)
|
||||||
|
|
||||||
|
--- dir-from-invalid ---
|
||||||
|
// Error: 17-23 cannot convert this alignment to a side
|
||||||
|
#direction.from(center)
|
||||||
|
|
||||||
|
--- dir-to ---
|
||||||
|
#test(direction.to(left), rtl)
|
||||||
|
#test(direction.to(right), ltr)
|
||||||
|
#test(direction.to(top), btt)
|
||||||
|
#test(direction.to(bottom), ttb)
|
||||||
|
|
||||||
|
-- dir-to-invalid ---
|
||||||
|
// Error: 15-21 cannot convert this alignment to a side
|
||||||
|
#direction.to(center)
|
||||||
|
|
||||||
--- dir-axis ---
|
--- dir-axis ---
|
||||||
// Test direction methods.
|
|
||||||
#test(ltr.axis(), "horizontal")
|
#test(ltr.axis(), "horizontal")
|
||||||
#test(rtl.axis(), "horizontal")
|
#test(rtl.axis(), "horizontal")
|
||||||
#test(ttb.axis(), "vertical")
|
#test(ttb.axis(), "vertical")
|
||||||
#test(btt.axis(), "vertical")
|
#test(btt.axis(), "vertical")
|
||||||
|
|
||||||
|
--- dir-sign ---
|
||||||
|
#test(ltr.sign(), 1)
|
||||||
|
#test(rtl.sign(), -1)
|
||||||
|
#test(ttb.sign(), 1)
|
||||||
|
#test(btt.sign(), -1)
|
||||||
|
|
||||||
--- dir-start ---
|
--- dir-start ---
|
||||||
#test(ltr.start(), left)
|
#test(ltr.start(), left)
|
||||||
#test(rtl.start(), right)
|
#test(rtl.start(), right)
|
||||||
|
@ -44,18 +44,21 @@
|
|||||||
--- recursion-via-include-in-layout ---
|
--- recursion-via-include-in-layout ---
|
||||||
// Test cyclic imports during layout.
|
// Test cyclic imports during layout.
|
||||||
// Error: 2-38 maximum show rule depth exceeded
|
// Error: 2-38 maximum show rule depth exceeded
|
||||||
// Hint: 2-38 check whether the show rule matches its own output
|
// Hint: 2-38 maybe a show rule matches its own output
|
||||||
|
// Hint: 2-38 maybe there are too deeply nested elements
|
||||||
#layout(_ => include "recursion.typ")
|
#layout(_ => include "recursion.typ")
|
||||||
|
|
||||||
--- recursion-show-math ---
|
--- recursion-show-math ---
|
||||||
// Test recursive show rules.
|
// Test recursive show rules.
|
||||||
// Error: 22-25 maximum show rule depth exceeded
|
// Error: 22-25 maximum show rule depth exceeded
|
||||||
// Hint: 22-25 check whether the show rule matches its own output
|
// Hint: 22-25 maybe a show rule matches its own output
|
||||||
|
// Hint: 22-25 maybe there are too deeply nested elements
|
||||||
#show math.equation: $x$
|
#show math.equation: $x$
|
||||||
$ x $
|
$ x $
|
||||||
|
|
||||||
--- recursion-show-math-realize ---
|
--- recursion-show-math-realize ---
|
||||||
// Error: 22-33 maximum show rule depth exceeded
|
// Error: 22-33 maximum show rule depth exceeded
|
||||||
// Hint: 22-33 check whether the show rule matches its own output
|
// Hint: 22-33 maybe a show rule matches its own output
|
||||||
|
// Hint: 22-33 maybe there are too deeply nested elements
|
||||||
#show heading: it => heading[it]
|
#show heading: it => heading[it]
|
||||||
$ #heading[hi] $
|
$ #heading[hi] $
|
||||||
|
Loading…
x
Reference in New Issue
Block a user