feat: bump typst to v0.14.0 (#2201)
Some checks are pending
tinymist::auto_tag / auto-tag (push) Waiting to run
tinymist::ci / prepare-build (push) Waiting to run
tinymist::ci / Duplicate Actions Detection (push) Waiting to run
tinymist::ci / Check Clippy, Formatting, Completion, Documentation, and Tests (Linux) (push) Waiting to run
tinymist::ci / Check Minimum Rust version and Tests (Windows) (push) Waiting to run
tinymist::ci / announce (push) Blocked by required conditions
tinymist::ci / build (push) Blocked by required conditions
tinymist::gh_pages / build-gh-pages (push) Waiting to run

Co-authored-by: paran3xus <paran3xus007@gmail.com>
This commit is contained in:
Myriad-Dreamin 2025-10-28 23:27:31 +08:00 committed by GitHub
parent a6c39d4306
commit f011022097
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
131 changed files with 1671 additions and 1501 deletions

View file

@ -106,7 +106,7 @@ impl<'a> ColorExprWorker<'a> {
fn push_color(&mut self, range: Range<usize>, color: Color) -> Option<()> {
let rng = self.ctx.to_lsp_range(range, &self.source);
let [r, g, b, a] = color.to_rgb().to_vec4();
let (r, g, b, a) = color.to_rgb().into_components();
self.colors.push(ColorInformation {
range: rng,

View file

@ -357,7 +357,7 @@ impl<'a> CompletionCursor<'a> {
LspCompletion {
label: item.label.clone(),
kind: item.kind,
kind: item.kind.clone(),
detail: item.detail.clone(),
sort_text: item.sort_text.clone(),
filter_text: item.filter_text.clone(),
@ -853,17 +853,46 @@ impl CompletionPair<'_, '_, '_> {
/// If is printable, return the symbol itself.
/// Otherwise, return the symbol's unicode detailed description.
pub fn symbol_detail(ch: char) -> EcoString {
let ld = symbol_label_detail(ch);
pub fn symbol_detail(s: &str) -> EcoString {
let ld = symbol_label_detail(s);
if ld.starts_with("\\u") {
return ld;
}
format!("{}, unicode: `\\u{{{:04x}}}`", ld, ch as u32).into()
let mut chars = s.chars();
let unicode_repr = if let (Some(ch), None) = (chars.next(), chars.next()) {
format!("\\u{{{:04x}}}", ch as u32)
} else {
let codes: Vec<String> = s
.chars()
.map(|ch| format!("\\u{{{:04x}}}", ch as u32))
.collect();
codes.join(" + ")
};
format!("{ld}, unicode: `{unicode_repr}`").into()
}
/// If is printable, return the symbol itself.
/// Otherwise, return the symbol's unicode description.
pub fn symbol_label_detail(ch: char) -> EcoString {
pub fn symbol_label_detail(s: &str) -> EcoString {
let mut chars = s.chars();
if let (Some(ch), None) = (chars.next(), chars.next()) {
return symbol_label_detail_single_char(ch);
}
if s.chars().all(|ch| !ch.is_whitespace() && !ch.is_control()) {
return s.into();
}
let codes: Vec<String> = s
.chars()
.map(|ch| format!("\\u{{{:04x}}}", ch as u32))
.collect();
codes.join(" + ").into()
}
fn symbol_label_detail_single_char(ch: char) -> EcoString {
if !ch.is_whitespace() && !ch.is_control() {
return ch.into();
}

View file

@ -8,7 +8,7 @@ impl CompletionPair<'_, '_, '_> {
// "#import "path.typ":|"
if matches!(self.cursor.leaf.kind(), SyntaxKind::Colon)
&& let Some(parent) = self.cursor.leaf.clone().parent()
&& let Some(ast::Expr::Import(import)) = parent.get().cast()
&& let Some(ast::Expr::ModuleImport(import)) = parent.get().cast()
&& !matches!(import.imports(), Some(ast::Imports::Wildcard))
&& let Some(source) = parent.children().find(|child| child.is::<ast::Expr>())
{
@ -31,7 +31,7 @@ impl CompletionPair<'_, '_, '_> {
// "#import "path.typ": a, b, |".
if let Some(prev) = self.cursor.leaf.prev_sibling()
&& let Some(ast::Expr::Import(import)) = prev.get().cast()
&& let Some(ast::Expr::ModuleImport(import)) = prev.get().cast()
&& !self.cursor.text[prev.offset()..self.cursor.cursor].contains('\n')
&& let Some(ast::Imports::Items(items)) = import.imports()
&& let Some(source) = prev.children().find(|child| child.is::<ast::Expr>())
@ -47,7 +47,7 @@ impl CompletionPair<'_, '_, '_> {
&& let Some(parent) = self.cursor.leaf.clone().parent()
&& parent.kind() == SyntaxKind::ImportItems
&& let Some(grand) = parent.parent()
&& let Some(ast::Expr::Import(import)) = grand.get().cast()
&& let Some(ast::Expr::ModuleImport(import)) = grand.get().cast()
&& let Some(ast::Imports::Items(items)) = import.imports()
&& let Some(source) = grand.children().find(|child| child.is::<ast::Expr>())
{
@ -64,7 +64,7 @@ impl CompletionPair<'_, '_, '_> {
&& let Some(parent) = path_ctx.parent()
&& parent.kind() == SyntaxKind::ImportItems
&& let Some(grand) = parent.parent()
&& let Some(ast::Expr::Import(import)) = grand.get().cast()
&& let Some(ast::Expr::ModuleImport(import)) = grand.get().cast()
&& let Some(ast::Imports::Items(items)) = import.imports()
&& let Some(source) = grand.children().find(|child| child.is::<ast::Expr>())
{

View file

@ -302,7 +302,7 @@ pub(crate) fn value_to_completion_kind(value: &Value) -> CompletionKind {
Value::Func(..) => CompletionKind::Func,
Value::Module(..) => CompletionKind::Module,
Value::Type(..) => CompletionKind::Type,
Value::Symbol(s) => CompletionKind::Symbol(s.get()),
Value::Symbol(s) => CompletionKind::Symbol(s.get().into()),
Value::None
| Value::Auto
| Value::Bool(..)

View file

@ -255,13 +255,13 @@ impl CompletionPair<'_, '_, '_> {
}
pub fn symbol_completions(&mut self, label: EcoString, symbol: &Symbol) {
let ch = symbol.get();
let kind = CompletionKind::Symbol(ch);
let sym_val = symbol.get();
let kind = CompletionKind::Symbol(sym_val.into());
self.push_completion(Completion {
kind,
label: label.clone(),
label_details: Some(symbol_label_detail(ch)),
detail: Some(symbol_detail(ch)),
label_details: Some(symbol_label_detail(sym_val)),
detail: Some(symbol_detail(sym_val)),
..Completion::default()
});
@ -273,7 +273,7 @@ impl CompletionPair<'_, '_, '_> {
pub fn symbol_var_completions(&mut self, symbol: &Symbol, prefix: Option<&str>) {
for modifier in symbol.modifiers() {
if let Ok(modified) = symbol.clone().modified(modifier) {
if let Ok(modified) = symbol.clone().modified((), modifier) {
let label = match &prefix {
Some(prefix) => eco_format!("{prefix}.{modifier}"),
None => modifier.into(),

View file

@ -200,13 +200,11 @@ fn ref_definition(
name: &str,
ref_expr: ast::Expr,
) -> Option<Definition> {
let label = Label::construct(name.into());
let sel = Selector::Label(label);
// if it is a label, we put the selection range to itself
let (decl, ty) = match ref_expr {
ast::Expr::Label(label) => (Decl::label(name, label.span()), None),
ast::Expr::Ref(..) => {
let sel = Selector::Label(Label::construct(name.into()).ok()?);
let elem = introspector.query_first(&sel)?;
let span = elem.labelled_at();
let decl = if !span.is_detached() {

View file

@ -1447,7 +1447,7 @@ fn analyze_bib(
// todo: it doesn't respect the style chain which can be get from
// `analyze_expr`
let csl_style = bib_elem.style(StyleChain::default()).derived;
let csl_style = bib_elem.style.get_cloned(StyleChain::default()).derived;
let Value::Array(paths) = bib_elem.sources.clone().into_value() else {
return None;

View file

@ -415,8 +415,8 @@ impl Tokenizer {
PositionEncoding::Utf8 => t - s,
PositionEncoding::Utf16 => {
// todo: whether it is safe to unwrap
let utf16_start = self.source.byte_to_utf16(s).unwrap();
let utf16_end = self.source.byte_to_utf16(t).unwrap();
let utf16_start = self.source.lines().byte_to_utf16(s).unwrap();
let utf16_end = self.source.lines().byte_to_utf16(t).unwrap();
utf16_end - utf16_start
}
}
@ -432,12 +432,14 @@ impl Tokenizer {
});
self.curr_pos = position;
} else {
let final_line = self
.source
.byte_to_line(utf8_end)
.unwrap_or_else(|| self.source.len_lines()) as u32;
let final_line =
self.source
.lines()
.byte_to_line(utf8_end)
.unwrap_or_else(|| self.source.lines().len_lines()) as u32;
let next_offset = self
.source
.lines()
.line_to_byte((self.curr_pos.line + 1) as usize)
.unwrap_or(source_len);
let inline_length = encode_length(utf8_start, utf8_end.min(next_offset)) as u32;
@ -462,6 +464,7 @@ impl Tokenizer {
utf8_end
} else {
self.source
.lines()
.line_to_byte((line + 1) as usize)
.unwrap_or(source_len)
};

View file

@ -1,7 +1,10 @@
use serde::{Deserialize, Serialize};
use tinymist_analysis::analyze_expr;
use tinymist_world::ShadowApi;
use typst::foundations::{Bytes, IntoValue, StyleChain};
use typst::{
foundations::{Bytes, IntoValue, StyleChain},
text::TextElem,
};
use typst_shim::syntax::LinkedNodeExt;
use crate::{
@ -157,9 +160,7 @@ impl InteractCodeContextRequest {
fn style_at(cursor_style: StyleChain, style: &str) -> Option<JsonValue> {
match style {
"text.font" => {
let font = typst::text::TextElem::font_in(cursor_style)
.clone()
.into_value();
let font = cursor_style.get_cloned(TextElem::font).into_value();
serde_json::to_value(font).ok()
}
_ => None,

View file

@ -1,4 +1,5 @@
use typst::foundations::Repr;
use typst::visualize::Color;
use crate::prelude::*;
@ -42,15 +43,15 @@ impl ColorPresentationRequest {
));
Some(vec![
simple(format!("{:?}", color.to_hex())),
simple(color.to_rgb().repr().to_string()),
simple(color.to_luma().repr().to_string()),
simple(color.to_oklab().repr().to_string()),
simple(color.to_oklch().repr().to_string()),
simple(color.to_rgb().repr().to_string()),
simple(color.to_linear_rgb().repr().to_string()),
simple(color.to_cmyk().repr().to_string()),
simple(color.to_hsl().repr().to_string()),
simple(color.to_hsv().repr().to_string()),
simple(Color::Rgb(color.to_rgb()).repr().to_string()),
simple(Color::Luma(color.to_luma()).repr().to_string()),
simple(Color::Oklab(color.to_oklab()).repr().to_string()),
simple(Color::Oklch(color.to_oklch()).repr().to_string()),
simple(Color::Rgb(color.to_rgb()).repr().to_string()),
simple(Color::LinearRgb(color.to_linear_rgb()).repr().to_string()),
simple(Color::Cmyk(color.to_cmyk()).repr().to_string()),
simple(Color::Hsl(color.to_hsl()).repr().to_string()),
simple(Color::Hsv(color.to_hsv()).repr().to_string()),
])
}
}

View file

@ -7,7 +7,7 @@ use crate::StrRef;
use super::LspRange;
/// A kind of item that can be completed.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum CompletionKind {
/// A syntactical structure.
Syntax,
@ -25,7 +25,7 @@ pub enum CompletionKind {
/// A reference.
Reference,
/// A symbol.
Symbol(char),
Symbol(EcoString),
/// A variable.
Variable,
/// A module.
@ -36,8 +36,8 @@ pub enum CompletionKind {
Folder,
}
impl From<CompletionKind> for lsp_types::CompletionItemKind {
fn from(value: CompletionKind) -> Self {
impl From<&CompletionKind> for lsp_types::CompletionItemKind {
fn from(value: &CompletionKind) -> Self {
match value {
CompletionKind::Syntax => Self::SNIPPET,
CompletionKind::Func => Self::FUNCTION,
@ -60,7 +60,7 @@ impl serde::Serialize for CompletionKind {
where
S: serde::Serializer,
{
<Self as Into<lsp_types::CompletionItemKind>>::into(*self).serialize(serializer)
<&Self as Into<lsp_types::CompletionItemKind>>::into(self).serialize(serializer)
}
}

View file

@ -209,8 +209,8 @@ impl DocumentMetricsWorker<'_> {
let range = source.range(span)?;
let byte_index = range.start + usize::from(span_offset);
let byte_index = byte_index.min(range.end - 1);
let line = source.byte_to_line(byte_index)?;
let column = source.byte_to_column(byte_index)?;
let line = source.lines().byte_to_line(byte_index)?;
let column = source.lines().byte_to_column(byte_index)?;
let filepath = self.ctx.path_for_id(file_id).ok()?;
let filepath_str = filepath.as_path().display().to_string();

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/builtin_shadow.typ
"labelDetails": {
"description": "(fill-rest: false) => none"
},
"sortText": "139",
"sortText": "138",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/builtin_shadow_existin
"labelDetails": {
"description": "(fill-rest: false) => none"
},
"sortText": "141",
"sortText": "139",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/colon_markup.typ
"labelDetails": {
"description": "(content, b: content | none, bl: content | none, br: content | none, t: content | none, tl: content | none, tr: content | none) => attach"
},
"sortText": "076",
"sortText": "080",
"textEdit": {
"newText": " attach(${1:})",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/colon_math.typ
"labelDetails": {
"description": "(content, b: content | none, bl: content | none, br: content | none, t: content | none, tl: content | none, tr: content | none) => attach"
},
"sortText": "076",
"sortText": "080",
"textEdit": {
"newText": " attach(${1:})",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/context_code_init.typ
"labelDetails": {
"description": "(to: \"even\" | \"odd\" | none, weak: bool) => pagebreak"
},
"sortText": "140",
"sortText": "139",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/context_init.typ
"labelDetails": {
"description": "(to: \"even\" | \"odd\" | none, weak: bool) => pagebreak"
},
"sortText": "140",
"sortText": "139",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/element_where.typ
"labelDetails": {
"description": "content | none"
},
"sortText": "000",
"sortText": "001",
"textEdit": {
"newText": "caption: ${1:}",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/func_module_raw.typ
"labelDetails": {
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
},
"sortText": "160",
"sortText": "159",
"textEdit": {
"newText": "raw",
"range": {
@ -43,7 +43,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/func_module_raw.typ
"labelDetails": {
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
},
"sortText": "161",
"sortText": "160",
"textEdit": {
"newText": "raw(${1:})",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/half_completion.typ
"labelDetails": {
"description": "array | text.font"
},
"sortText": "010",
"sortText": "011",
"textEdit": {
"newText": "font: ${1:}, ",
"range": {
@ -48,7 +48,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/half_completion.typ
"labelDetails": {
"description": "array | text.font"
},
"sortText": "010",
"sortText": "011",
"textEdit": {
"newText": "font: ${1:}",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/hash.typ
"labelDetails": {
"description": "(to: \"even\" | \"odd\" | none, weak: bool) => pagebreak"
},
"sortText": "139",
"sortText": "138",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/hash_ident.typ
"labelDetails": {
"description": "(to: \"even\" | \"odd\" | none, weak: bool) => pagebreak"
},
"sortText": "139",
"sortText": "138",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/hash_math.typ
"labelDetails": {
"description": "(to: \"even\" | \"odd\" | none, weak: bool) => pagebreak"
},
"sortText": "139",
"sortText": "138",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/hash_math_ident.typ
"labelDetails": {
"description": "(to: \"even\" | \"odd\" | none, weak: bool) => pagebreak"
},
"sortText": "139",
"sortText": "138",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/import_star_typing.typ
"labelDetails": {
"description": "(content) => content"
},
"sortText": "218",
"sortText": "219",
"textEdit": {
"newText": "todo(${1:})",
"range": {
@ -48,7 +48,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/import_star_typing.typ
"labelDetails": {
"description": "(content) => content"
},
"sortText": "218",
"sortText": "219",
"textEdit": {
"newText": "todo(${1:})",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/import_typing.typ
"labelDetails": {
"description": "(content) => content"
},
"sortText": "217",
"sortText": "218",
"textEdit": {
"newText": "todo(${1:})",
"range": {
@ -48,7 +48,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/import_typing.typ
"labelDetails": {
"description": "(content) => content"
},
"sortText": "217",
"sortText": "218",
"textEdit": {
"newText": "todo(${1:})",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/let_closure_init.typ
"labelDetails": {
"description": "(to: \"even\" | \"odd\" | none, weak: bool) => pagebreak"
},
"sortText": "141",
"sortText": "140",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/let_fn_init.typ
"labelDetails": {
"description": "(to: \"even\" | \"odd\" | none, weak: bool) => pagebreak"
},
"sortText": "141",
"sortText": "140",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/let_init.typ
"labelDetails": {
"description": "(to: \"even\" | \"odd\" | none, weak: bool) => pagebreak"
},
"sortText": "141",
"sortText": "140",
"textEdit": {
"newText": "pagebreak()${1:}",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/math_bold2.typ
"labelDetails": {
"description": "(content) => content"
},
"sortText": "087",
"sortText": "093",
"textEdit": {
"newText": "bold(${1:})",
"range": {

View file

@ -40,7 +40,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/math_call_in_call.typ
"labelDetails": {
"description": "(content, size: relative) => content"
},
"sortText": "057",
"sortText": "059",
"textEdit": {
"newText": "abs(${1:})",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/math_call_in_call2.typ
"labelDetails": {
"description": "(content, size: relative) => content"
},
"sortText": "056",
"sortText": "058",
"textEdit": {
"newText": "abs(${1:})",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/math_call_in_call3.typ
"labelDetails": {
"description": "(content, size: relative) => content"
},
"sortText": "055",
"sortText": "057",
"textEdit": {
"newText": "abs(${1:})",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/math_call_in_call4.typ
"labelDetails": {
"description": "(content, size: relative) => content"
},
"sortText": "055",
"sortText": "057",
"textEdit": {
"newText": "abs(${1:})",
"range": {

View file

@ -3,7 +3,6 @@ source: crates/tinymist-query/src/completion.rs
description: Completion on / (22..23)
expression: "JsonRepr::new_pure(results)"
input_file: crates/tinymist-query/src/fixtures/completion/math_ident.typ
snapshot_kind: text
---
[
{
@ -15,7 +14,7 @@ snapshot_kind: text
"labelDetails": {
"description": ""
},
"sortText": "039",
"sortText": "040",
"textEdit": {
"newText": "Re",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/math_ident_in_call.typ
"labelDetails": {
"description": "(content, size: relative) => content"
},
"sortText": "229",
"sortText": "259",
"textEdit": {
"newText": "norm(${1:})",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/math_ident_in_call2.ty
"labelDetails": {
"description": "(content, size: relative) => content"
},
"sortText": "230",
"sortText": "260",
"textEdit": {
"newText": "norm(${1:})",
"range": {

View file

@ -3,7 +3,6 @@ source: crates/tinymist-query/src/completion.rs
description: Completion on / (21..22)
expression: "JsonRepr::new_pure(results)"
input_file: crates/tinymist-query/src/fixtures/completion/math_text.typ
snapshot_kind: text
---
[
{
@ -15,7 +14,7 @@ snapshot_kind: text
"labelDetails": {
"description": ""
},
"sortText": "039",
"sortText": "040",
"textEdit": {
"newText": "Re",
"range": {

View file

@ -14,7 +14,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/mode_math.typ
"labelDetails": {
"description": "op(text: [tanh], limits: false)"
},
"sortText": "318",
"sortText": "361",
"textEdit": {
"newText": "tanh",
"range": {

View file

@ -8,6 +8,31 @@ input_file: crates/tinymist-query/src/fixtures/completion/set_param.typ
{
"isIncomplete": false,
"items": [
{
"command": {
"command": "tinymist.triggerSuggestAndParameterHints",
"title": ""
},
"kind": 5,
"label": "body",
"labelDetails": {
"description": "content"
},
"sortText": "002",
"textEdit": {
"newText": "body: ${1:}",
"range": {
"end": {
"character": 10,
"line": 1
},
"start": {
"character": 10,
"line": 1
}
}
}
},
{
"command": {
"command": "tinymist.triggerSuggestAndParameterHints",
@ -18,7 +43,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/set_param.typ
"labelDetails": {
"description": "color"
},
"sortText": "009",
"sortText": "010",
"textEdit": {
"newText": "fill: ${1:}",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
"labelDetails": {
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
},
"sortText": "227",
"sortText": "226",
"textEdit": {
"newText": "raw",
"range": {
@ -43,7 +43,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
"labelDetails": {
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
},
"sortText": "229",
"sortText": "228",
"textEdit": {
"newText": "raw.with(${1:})",
"range": {
@ -68,7 +68,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
"labelDetails": {
"description": "([any], encoding: \"utf8\" | none) => bytes | str"
},
"sortText": "230",
"sortText": "229",
"textEdit": {
"newText": "read(${1:})",
"range": {
@ -93,7 +93,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
"labelDetails": {
"description": "([any], encoding: \"utf8\" | none) => bytes | str"
},
"sortText": "231",
"sortText": "230",
"textEdit": {
"newText": "read.with(${1:})",
"range": {
@ -115,7 +115,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform.typ
},
"kind": 15,
"label": "replacement",
"sortText": "244",
"sortText": "243",
"textEdit": {
"newText": "[${1:content}]",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform2.typ
"labelDetails": {
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
},
"sortText": "227",
"sortText": "226",
"textEdit": {
"newText": "raw",
"range": {
@ -43,7 +43,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform2.typ
"labelDetails": {
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
},
"sortText": "229",
"sortText": "228",
"textEdit": {
"newText": "raw.with(${1:})",
"range": {
@ -68,7 +68,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform2.typ
"labelDetails": {
"description": "([any], encoding: \"utf8\" | none) => bytes | str"
},
"sortText": "230",
"sortText": "229",
"textEdit": {
"newText": "read(${1:})",
"range": {
@ -93,7 +93,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform2.typ
"labelDetails": {
"description": "([any], encoding: \"utf8\" | none) => bytes | str"
},
"sortText": "231",
"sortText": "230",
"textEdit": {
"newText": "read.with(${1:})",
"range": {
@ -115,7 +115,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform2.typ
},
"kind": 15,
"label": "replacement",
"sortText": "244",
"sortText": "243",
"textEdit": {
"newText": "[${1:content}]",
"range": {

View file

@ -18,7 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform3.typ
"labelDetails": {
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
},
"sortText": "227",
"sortText": "226",
"textEdit": {
"newText": " raw",
"range": {
@ -43,7 +43,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform3.typ
"labelDetails": {
"description": "(str, align: alignment, block: bool, lang: none | str, syntaxes: [syntax], tab-size: int, theme: [theme]) => raw"
},
"sortText": "229",
"sortText": "228",
"textEdit": {
"newText": " raw.with(${1:})",
"range": {
@ -68,7 +68,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform3.typ
"labelDetails": {
"description": "([any], encoding: \"utf8\" | none) => bytes | str"
},
"sortText": "230",
"sortText": "229",
"textEdit": {
"newText": " read(${1:})",
"range": {
@ -93,7 +93,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform3.typ
"labelDetails": {
"description": "([any], encoding: \"utf8\" | none) => bytes | str"
},
"sortText": "231",
"sortText": "230",
"textEdit": {
"newText": " read.with(${1:})",
"range": {
@ -115,7 +115,7 @@ input_file: crates/tinymist-query/src/fixtures/completion/show_transform3.typ
},
"kind": 15,
"label": "replacement",
"sortText": "244",
"sortText": "243",
"textEdit": {
"newText": " [${1:content}]",
"range": {

View file

@ -29,29 +29,32 @@ A table of items.
Tables are used to arrange content in cells. Cells can contain arbitrary
content, including multiple paragraphs and are specified in row-major order.
For a hands-on explanation of all the ways you can use and customize tables
in Typst, check out the [table guide](https://typst.app/docs/guides/table-guide/).
in Typst, check out the [Table Guide](https://typst.app/docs/guides/tables/).
Because tables are just grids with different defaults for some cell
properties (notably `stroke` and `inset`), refer to the [grid
documentation](https://typst.app/docs/reference/layout/grid/) for more information on how to size the table tracks
and specify the cell appearance properties.
documentation](https://typst.app/docs/reference/layout/grid/#track-size) for more information on how to size the
table tracks and specify the cell appearance properties.
If you are unsure whether you should be using a table or a grid, consider
whether the content you are arranging semantically belongs together as a set
of related data points or similar or whether you are just want to enhance
your presentation by arranging unrelated content in a grid. In the former
case, a table is the right choice, while in the latter case, a grid is more
appropriate. Furthermore, Typst will annotate its output in the future such
that screenreaders will announce content in `table` as tabular while a
grid's content will be announced no different than multiple content blocks
in the document flow.
appropriate. Furthermore, Assistive Technology (AT) like screen readers will
announce content in a `table` as tabular while a grid's content will be
announced no different than multiple content blocks in the document flow. AT
users will be able to navigate tables two-dimensionally by cell.
Note that, to override a particular cell's properties or apply show rules on
table cells, you can use the [`table.cell`](https://typst.app/docs/reference/model/table/#definitions-cell) element. See its
documentation for more information.
table cells, you can use the [`table.cell`] element. See its documentation
for more information.
Although the `table` and the `grid` share most properties, set and show
rules on one of them do not affect the other.
rules on one of them do not affect the other. Locating most of your styling
in set and show rules is recommended, as it keeps the table's actual usages
clean and easy to read. It also allows you to easily change the appearance
of all tables in one place.
To give a table a caption and make it [referenceable](https://typst.app/docs/reference/model/ref/), put it into a
[figure].
@ -80,8 +83,8 @@ The example below demonstrates some of the most common table options.
)
```
Much like with grids, you can use [`table.cell`](https://typst.app/docs/reference/model/table/#definitions-cell) to customize
the appearance and the position of each cell.
Much like with grids, you can use [`table.cell`] to customize the appearance
and the position of each cell.
```typ
>>> #set page(width: auto)
@ -125,6 +128,18 @@ the appearance and the position of each cell.
)
```
# Accessibility
Tables are challenging to consume for users of Assistive Technology (AT). To
make the life of AT users easier, we strongly recommend that you use
[`table.header`] and [`table.footer`] to mark the header and footer sections
of your table. This will allow AT to announce the column labels for each
cell.
Because navigating a table by cell is more cumbersome than reading it
visually, you should consider making the core information in your table
available as text as well. You can do this by wrapping your table in a
[figure] and using its caption to summarize the table's content.
# Rest Parameters
## children
@ -134,8 +149,7 @@ type: content
```
The contents of the table cells, plus any extra table lines specified
with the [`table.hline`](https://typst.app/docs/reference/model/table/#definitions-hline) and
[`table.vline`](https://typst.app/docs/reference/model/table/#definitions-vline) elements.
with the [`table.hline`] and [`table.vline`] elements.
# Named Parameters
@ -147,10 +161,15 @@ type: alignment | array | auto | function
How to align the cells' content.
This can either be a single alignment, an array of alignments
(corresponding to each column) or a function that returns an alignment.
The function receives the cells' column and row indices, starting from
zero. If set to `auto`, the outer alignment is used.
If set to `auto`, the outer alignment is used.
You can specify the alignment in any of the following fashions:
- use a single alignment for all cells
- use an array of alignments corresponding to each column
- use a function that maps a cell's X/Y position (both starting from
zero) to its alignment
See the [Table Guide](https://typst.app/docs/guides/tables/#alignment) for details.
```typ
#table(
@ -168,7 +187,7 @@ type: array | auto | length | type
```
The gaps between columns. Takes precedence over `gutter`. See the
[grid documentation](https://typst.app/docs/reference/layout/grid/) for more information on gutters.
[grid documentation](https://typst.app/docs/reference/layout/grid/#parameters-gutter) for more information on gutters.
## columns (named)
@ -176,8 +195,8 @@ The gaps between columns. Takes precedence over `gutter`. See the
type: array | auto | length | type
```
The column sizes. See the [grid documentation](https://typst.app/docs/reference/layout/grid/) for more
information on track sizing.
The column sizes. See the [grid documentation](https://typst.app/docs/reference/layout/grid/#track-size) for
more information on track sizing.
## fill (named)
@ -187,9 +206,14 @@ type: color
How to fill the cells.
This can be a color or a function that returns a color. The function
receives the cells' column and row indices, starting from zero. This can
be used to implement striped tables.
This can be:
- a single fill for all cells
- an array of fill corresponding to each column
- a function that maps a cell's position to its fill
Most notably, arrays and functions are useful for creating striped
tables. See the [Table Guide](https://typst.app/docs/guides/tables/#fills) for more
details.
```typ
#table(
@ -216,7 +240,7 @@ type: array | auto | length | type
The gaps between rows and columns. This is a shorthand for setting
`column-gutter` and `row-gutter` to the same value. See the [grid
documentation](https://typst.app/docs/reference/layout/grid/) for more information on gutters.
documentation](https://typst.app/docs/reference/layout/grid/#parameters-gutter) for more information on gutters.
## inset (named)
@ -226,8 +250,21 @@ type: inset
How much to pad the cells' content.
To specify the same inset for all cells, use a single length for all
sides, or a dictionary of lengths for individual sides. See the
[box's documentation](https://typst.app/docs/reference/layout/box/#parameters-inset) for more details.
To specify a varying inset for different cells, you can:
- use a single, uniform inset for all cells
- use an array of insets for each column
- use a function that maps a cell's X/Y position (both starting from
zero) to its inset
See the [grid documentation](https://typst.app/docs/reference/layout/grid/#styling) for more details.
```typ
#table(
columns: 2,
inset: 10pt,
[Hello],
[World],
@ -235,10 +272,7 @@ How much to pad the cells' content.
#table(
columns: 2,
inset: (
x: 20pt,
y: 10pt,
),
inset: (x: 20pt, y: 10pt),
[Hello],
[World],
)
@ -251,7 +285,7 @@ type: array | auto | length | type
```
The gaps between rows. Takes precedence over `gutter`. See the
[grid documentation](https://typst.app/docs/reference/layout/grid/) for more information on gutters.
[grid documentation](https://typst.app/docs/reference/layout/grid/#parameters-gutter) for more information on gutters.
## rows (named)
@ -259,8 +293,8 @@ The gaps between rows. Takes precedence over `gutter`. See the
type: array | auto | length | type
```
The row sizes. See the [grid documentation](https://typst.app/docs/reference/layout/grid/) for more information
on track sizing.
The row sizes. See the [grid documentation](https://typst.app/docs/reference/layout/grid/#track-size) for more
information on track sizing.
## stroke (named)
@ -273,13 +307,20 @@ How to [stroke] the cells.
Strokes can be disabled by setting this to `none`.
If it is necessary to place lines which can cross spacing between cells
produced by the `gutter` option, or to override the stroke between
multiple specific cells, consider specifying one or more of
[`table.hline`](https://typst.app/docs/reference/model/table/#definitions-hline) and [`table.vline`](https://typst.app/docs/reference/model/table/#definitions-vline)
alongside your table cells.
produced by the [`gutter`](https://typst.app/docs/reference/model/table/#parameters-gutter) option, or to override the
stroke between multiple specific cells, consider specifying one or more
of [`table.hline`] and [`table.vline`] alongside your table cells.
See the [grid documentation](https://typst.app/docs/reference/layout/grid/#parameters-stroke) for more information on
strokes.
To specify the same stroke for all cells, use a single [stroke] for all
sides, or a dictionary of [strokes](https://typst.app/docs/reference/visualize/stroke/) for individual sides. See
the [rectangle's documentation](https://typst.app/docs/reference/visualize/rect/#parameters-stroke) for more details.
To specify varying strokes for different cells, you can:
- use a single stroke for all cells
- use an array of strokes corresponding to each column
- use a function that maps a cell's position to its stroke
See the [Table Guide](https://typst.app/docs/guides/tables/#strokes) for more details.
======

View file

@ -30,6 +30,15 @@ more details on compound theory.
In 1984, the first ...
```
Even without manual page breaks, content will be automatically paginated
based on the configured page size. You can set [the page height](https://typst.app/docs/reference/layout/page/#parameters-height)
to `auto` to let the page grow dynamically until a manual page break
occurs.
Pagination tries to avoid single lines of text at the top or bottom of a
page (these are called _widows_ and _orphans_). You can adjust the
[`text.costs`] parameter to disable this behavior.
# Named Parameters
## to

View file

@ -15,6 +15,7 @@ Ref: `fig:test1`
```typc
figure(
body: [Test1],
alt: none,
placement: none,
scope: "column",
caption: none,

View file

@ -68,7 +68,7 @@ input_file: crates/tinymist-query/src/fixtures/pkgs/touying-core-slides.typ
"labelDetails": {
"description": "(content, gap: length, justify: bool) => repeat"
},
"sortText": "177",
"sortText": "176",
"textEdit": {
"newText": "repeat(${1:})",
"range": {

View file

@ -4,4 +4,4 @@ description: "Check on \"(\" (18)"
expression: post_ty
input_file: crates/tinymist-query/src/fixtures/post_type_check/with_element.typ
---
( ⪰ "alternates": Type(bool) | "baseline": Type(length) | "body": Type(content) | "bottom-edge": (Type(length) | "baseline" | "bounds" | "descender") | "cjk-latin-spacing": (Type(auto) | Type(none)) | "costs": {"hyphenation": Type(ratio), "orphan": Type(ratio), "runt": Type(ratio), "widow": Type(ratio)} | "dir": Dir | "discretionary-ligatures": Type(bool) | "fallback": Type(bool) | "features": (Type(array) | Type(dictionary)) | "fill": Color | "font": (TextFont | Array<TextFont>) | "fractions": Type(bool) | "historical-ligatures": Type(bool) | "hyphenate": (Type(auto) | Type(bool)) | "kerning": Type(bool) | "lang": TextLang | "ligatures": Type(bool) | "number-type": (Type(auto) | "lining" | "old-style") | "number-width": (Type(auto) | "proportional" | "tabular") | "overhang": Type(bool) | "region": TextRegion | "script": (Type(auto) | Type(str)) | "size": TextSize | "slashed-zero": Type(bool) | "spacing": Type(relative) | "stretch": Type(ratio) | "stroke": Stroke | "style": ("italic" | "normal" | "oblique") | "stylistic-set": (Type(array) | Type(int) | Type(none)) | "top-edge": (Type(length) | "ascender" | "baseline" | "bounds" | "cap-height" | "x-height") | "tracking": Type(length) | "weight": (Type(int) | "black" | "bold" | "extrabold" | "extralight" | "light" | "medium" | "regular" | "semibold" | "thin"))
( ⪰ "alternates": Type(bool) | "baseline": Type(length) | "body": Type(content) | "bottom-edge": (Type(length) | "baseline" | "bounds" | "descender") | "cjk-latin-spacing": (Type(auto) | Type(none)) | "costs": {"hyphenation": Type(ratio), "orphan": Type(ratio), "runt": Type(ratio), "widow": Type(ratio)} | "dir": Dir | "discretionary-ligatures": Type(bool) | "fallback": Type(bool) | "features": (Type(array) | Type(dictionary)) | "fill": Color | "font": (TextFont | Array<TextFont>) | "fractions": Type(bool) | "historical-ligatures": Type(bool) | "hyphenate": (Type(auto) | Type(bool)) | "kerning": Type(bool) | "lang": TextLang | "ligatures": Type(bool) | "number-type": (Type(auto) | "lining" | "old-style") | "number-width": (Type(auto) | "proportional" | "tabular") | "overhang": Type(bool) | "region": TextRegion | "script": (Type(auto) | Type(str)) | "size": TextSize | "slashed-zero": Type(bool) | "spacing": Type(relative) | "stretch": Type(ratio) | "stroke": Stroke | "style": ("italic" | "normal" | "oblique") | "stylistic-set": (Type(array) | Type(int) | Type(none)) | "text": Type(str) | "top-edge": (Type(length) | "ascender" | "baseline" | "bounds" | "cap-height" | "x-height") | "tracking": Type(length) | "weight": (Type(int) | "black" | "bold" | "extrabold" | "extralight" | "light" | "medium" | "regular" | "semibold" | "thin"))

View file

@ -15,4 +15,4 @@ input_file: crates/tinymist-query/src/fixtures/type_check/infer.typ
80..83 -> Func(xml)
80..95 -> Any
98..102 -> Func(toml)
98..115 -> Any
98..115 -> Type(dictionary)

View file

@ -280,8 +280,8 @@ fn is_one_line(src: &Source, arg_node: &LinkedNode<'_>) -> bool {
fn is_one_line_(src: &Source, arg_node: &LinkedNode<'_>) -> Option<bool> {
let lb = arg_node.children().next()?;
let rb = arg_node.children().next_back()?;
let ll = src.byte_to_line(lb.offset())?;
let rl = src.byte_to_line(rb.offset())?;
let ll = src.lines().byte_to_line(lb.offset())?;
let rl = src.lines().byte_to_line(rb.offset())?;
Some(ll == rl)
}

View file

@ -31,8 +31,7 @@ pub fn jump_from_click(
}
// If there's no link, search for a jump target.
for (pos, item) in frame.items().rev() {
let mut pos = *pos;
for &(mut pos, ref item) in frame.items().rev() {
match item {
FrameItem::Group(group) => {
// TODO: Handle transformation.
@ -169,8 +168,7 @@ fn jump_from_cursor_(
/// Finds the position of a span in a frame.
fn find_in_frame(frame: &Frame, span: Span, min_dis: &mut u64, res: &mut Point) -> Option<Point> {
for (pos, item) in frame.items() {
let mut pos = *pos;
for &(mut pos, ref item) in frame.items() {
if let FrameItem::Group(group) = item {
// TODO: Handle transformation.
if let Some(point) = find_in_frame(&group.frame, span, min_dis, res) {

View file

@ -250,11 +250,11 @@ impl RenameFileWorker<'_> {
let import_node = root.find(span).and_then(first_ancestor_expr)?;
let (import_path, has_path_var) = node_ancestors(&import_node).find_map(|import_node| {
match import_node.cast::<ast::Expr>()? {
ast::Expr::Import(import) => Some((
ast::Expr::ModuleImport(import) => Some((
import.source(),
import.new_name().is_none() && import.imports().is_none(),
)),
ast::Expr::Include(include) => Some((include.source(), false)),
ast::Expr::ModuleInclude(include) => Some((include.source(), false)),
_ => None,
}
})?;

View file

@ -54,7 +54,7 @@ pub(crate) fn expr_of(
route.insert(source.id(), None);
let cache_hit = prev.and_then(|prev| {
if prev.source.len_bytes() != source.len_bytes()
if prev.source.lines().len_bytes() != source.lines().len_bytes()
|| hash128(&prev.source) != hash128(&source)
{
return None;
@ -273,18 +273,18 @@ impl ExprWorker<'_> {
Equation(equation) => self.check_math(equation.body().to_untyped().children()),
Math(math) => self.check_math(math.to_untyped().children()),
Code(code_block) => self.check_code(code_block.body()),
Content(content_block) => self.check_markup(content_block.body()),
CodeBlock(code_block) => self.check_code(code_block.body()),
ContentBlock(content_block) => self.check_markup(content_block.body()),
Ident(ident) => self.check_ident(ident),
MathIdent(math_ident) => self.check_math_ident(math_ident),
Label(label) => self.check_label(label),
Ref(ref_node) => self.check_ref(ref_node),
Let(let_binding) => self.check_let(let_binding),
LetBinding(let_binding) => self.check_let(let_binding),
Closure(closure) => self.check_closure(closure),
Import(module_import) => self.check_module_import(module_import),
Include(module_include) => self.check_module_include(module_include),
ModuleImport(module_import) => self.check_module_import(module_import),
ModuleInclude(module_include) => self.check_module_include(module_include),
Parenthesized(paren_expr) => self.check(paren_expr.expr()),
Array(array) => self.check_array(array),
@ -293,18 +293,20 @@ impl ExprWorker<'_> {
Binary(binary) => self.check_binary(binary),
FieldAccess(field_access) => self.check_field_access(field_access),
FuncCall(func_call) => self.check_func_call(func_call),
DestructAssign(destruct_assignment) => self.check_destruct_assign(destruct_assignment),
Set(set_rule) => self.check_set(set_rule),
Show(show_rule) => self.check_show(show_rule),
DestructAssignment(destruct_assignment) => {
self.check_destruct_assign(destruct_assignment)
}
SetRule(set_rule) => self.check_set(set_rule),
ShowRule(show_rule) => self.check_show(show_rule),
Contextual(contextual) => {
Expr::Unary(UnInst::new(UnaryOp::Context, self.defer(contextual.body())))
}
Conditional(conditional) => self.check_conditional(conditional),
While(while_loop) => self.check_while_loop(while_loop),
For(for_loop) => self.check_for_loop(for_loop),
Break(..) => Expr::Type(Ty::Builtin(BuiltinTy::Break)),
Continue(..) => Expr::Type(Ty::Builtin(BuiltinTy::Continue)),
Return(func_return) => Expr::Unary(UnInst::new(
WhileLoop(while_loop) => self.check_while_loop(while_loop),
ForLoop(for_loop) => self.check_for_loop(for_loop),
LoopBreak(..) => Expr::Type(Ty::Builtin(BuiltinTy::Break)),
LoopContinue(..) => Expr::Type(Ty::Builtin(BuiltinTy::Continue)),
FuncReturn(func_return) => Expr::Unary(UnInst::new(
UnaryOp::Return,
func_return
.body()
@ -355,15 +357,15 @@ impl ExprWorker<'_> {
let body = self.check_markup(heading.body());
self.check_element::<HeadingElem>(eco_vec![body])
}
List(item) => {
ListItem(item) => {
let body = self.check_markup(item.body());
self.check_element::<ListElem>(eco_vec![body])
}
Enum(item) => {
EnumItem(item) => {
let body = self.check_markup(item.body());
self.check_element::<EnumElem>(eco_vec![body])
}
Term(item) => {
TermItem(item) => {
let term = self.check_markup(item.term());
let description = self.check_markup(item.description());
self.check_element::<TermsElem>(eco_vec![term, description])
@ -1064,7 +1066,7 @@ impl ExprWorker<'_> {
let ident = Interned::new(Decl::ref_(ref_node));
let body = ref_node
.supplement()
.map(|block| self.check(ast::Expr::Content(block)));
.map(|block| self.check(ast::Expr::ContentBlock(block)));
let ref_expr = ContentRefExpr {
ident: ident.clone(),
of: None,

View file

@ -143,7 +143,7 @@ struct UserTestConfig {
}
fn extract_test_configuration(doc: &TypstDocument) -> Result<TestConfig> {
let selector = Label::new(PicoStr::intern("test-config"));
let selector = Label::new(PicoStr::intern("test-config")).context("failed to create label")?;
let metadata = doc.introspector().query(&Selector::Label(selector));
if metadata.len() > 1 {
// todo: attach source locations.