mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
[WIP] Label and reference syntax
This commit is contained in:
parent
0cb876ebf9
commit
0d12f2ab23
@ -203,6 +203,8 @@ impl Eval for MarkupNode {
|
|||||||
Self::Heading(heading) => heading.eval(vm)?,
|
Self::Heading(heading) => heading.eval(vm)?,
|
||||||
Self::List(list) => list.eval(vm)?,
|
Self::List(list) => list.eval(vm)?,
|
||||||
Self::Enum(enum_) => enum_.eval(vm)?,
|
Self::Enum(enum_) => enum_.eval(vm)?,
|
||||||
|
Self::Label(_) => Content::Empty,
|
||||||
|
Self::Ref(label) => Content::show(library::structure::RefNode(label.clone())),
|
||||||
Self::Expr(expr) => expr.eval(vm)?.display(),
|
Self::Expr(expr) => expr.eval(vm)?.display(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ pub fn new() -> Scope {
|
|||||||
std.def_fn("smallcaps", text::smallcaps);
|
std.def_fn("smallcaps", text::smallcaps);
|
||||||
|
|
||||||
// Structure.
|
// Structure.
|
||||||
|
std.def_node::<structure::RefNode>("ref");
|
||||||
std.def_node::<structure::HeadingNode>("heading");
|
std.def_node::<structure::HeadingNode>("heading");
|
||||||
std.def_node::<structure::ListNode>("list");
|
std.def_node::<structure::ListNode>("list");
|
||||||
std.def_node::<structure::EnumNode>("enum");
|
std.def_node::<structure::EnumNode>("enum");
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
mod doc;
|
mod doc;
|
||||||
mod heading;
|
mod heading;
|
||||||
mod list;
|
mod list;
|
||||||
|
mod reference;
|
||||||
mod table;
|
mod table;
|
||||||
|
|
||||||
pub use doc::*;
|
pub use doc::*;
|
||||||
pub use heading::*;
|
pub use heading::*;
|
||||||
pub use list::*;
|
pub use list::*;
|
||||||
|
pub use reference::*;
|
||||||
pub use table::*;
|
pub use table::*;
|
||||||
|
28
src/library/structure/reference.rs
Normal file
28
src/library/structure/reference.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use crate::library::prelude::*;
|
||||||
|
|
||||||
|
/// A reference to a label.
|
||||||
|
#[derive(Debug, Hash)]
|
||||||
|
pub struct RefNode(pub EcoString);
|
||||||
|
|
||||||
|
#[node(showable)]
|
||||||
|
impl RefNode {
|
||||||
|
fn construct(_: &mut Machine, args: &mut Args) -> TypResult<Content> {
|
||||||
|
Ok(Content::show(Self(args.expect("label")?)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Show for RefNode {
|
||||||
|
fn unguard(&self, _: Selector) -> ShowNode {
|
||||||
|
Self(self.0.clone()).pack()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self, _: StyleChain) -> Dict {
|
||||||
|
dict! {
|
||||||
|
"label" => Value::Str(self.0.clone().into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn realize(&self, _: &mut Context, _: StyleChain) -> TypResult<Content> {
|
||||||
|
Ok(Content::Text(format_eco!("@{}", self.0)))
|
||||||
|
}
|
||||||
|
}
|
@ -169,6 +169,9 @@ pub static THEME: Lazy<Theme> = Lazy::new(|| Theme {
|
|||||||
item("markup.raw", Some("#818181"), None),
|
item("markup.raw", Some("#818181"), None),
|
||||||
item("markup.list", Some("#8b41b1"), None),
|
item("markup.list", Some("#8b41b1"), None),
|
||||||
item("comment", Some("#8a8a8a"), None),
|
item("comment", Some("#8a8a8a"), None),
|
||||||
|
item("punctuation.shortcut", Some("#1d6c76"), None),
|
||||||
|
item("constant.character.escape", Some("#1d6c76"), None),
|
||||||
|
item("entity.name.label, markup.other.reference", Some("#1d6c76"), None),
|
||||||
item("keyword, constant.language, variable.language", Some("#d73a49"), None),
|
item("keyword, constant.language, variable.language", Some("#d73a49"), None),
|
||||||
item("storage.type, storage.modifier", Some("#d73a49"), None),
|
item("storage.type, storage.modifier", Some("#d73a49"), None),
|
||||||
item("entity.other", Some("#8b41b1"), None),
|
item("entity.other", Some("#8b41b1"), None),
|
||||||
@ -177,8 +180,6 @@ pub static THEME: Lazy<Theme> = Lazy::new(|| Theme {
|
|||||||
item("meta.annotation", Some("#301414"), None),
|
item("meta.annotation", Some("#301414"), None),
|
||||||
item("constant", Some("#b60157"), None),
|
item("constant", Some("#b60157"), None),
|
||||||
item("string", Some("#298e0d"), None),
|
item("string", Some("#298e0d"), None),
|
||||||
item("punctuation.shortcut", Some("#1d6c76"), None),
|
|
||||||
item("constant.character.escape", Some("#1d6c76"), None),
|
|
||||||
item("invalid", Some("#ff0000"), None),
|
item("invalid", Some("#ff0000"), None),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -175,18 +175,24 @@ fn markup_indented(p: &mut Parser, min_indent: usize) {
|
|||||||
_ => false,
|
_ => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let marker = p.marker();
|
||||||
let mut at_start = false;
|
let mut at_start = false;
|
||||||
p.perform(NodeKind::Markup { min_indent }, |p| {
|
|
||||||
while !p.eof() {
|
|
||||||
if let Some(NodeKind::Space { newlines: (1 ..) }) = p.peek() {
|
|
||||||
if p.column(p.current_end()) < min_indent {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
markup_node(p, &mut at_start);
|
while !p.eof() {
|
||||||
|
match p.peek() {
|
||||||
|
Some(NodeKind::Space { newlines: (1 ..) })
|
||||||
|
if p.column(p.current_end()) < min_indent =>
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Some(NodeKind::Label(_)) => break,
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
markup_node(p, &mut at_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
marker.end(p, NodeKind::Markup { min_indent });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a markup node.
|
/// Parse a markup node.
|
||||||
@ -212,16 +218,18 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) {
|
|||||||
|
|
||||||
// Text and markup.
|
// Text and markup.
|
||||||
NodeKind::Text(_)
|
NodeKind::Text(_)
|
||||||
|
| NodeKind::Linebreak { .. }
|
||||||
| NodeKind::NonBreakingSpace
|
| NodeKind::NonBreakingSpace
|
||||||
| NodeKind::Shy
|
| NodeKind::Shy
|
||||||
| NodeKind::EnDash
|
| NodeKind::EnDash
|
||||||
| NodeKind::EmDash
|
| NodeKind::EmDash
|
||||||
| NodeKind::Ellipsis
|
| NodeKind::Ellipsis
|
||||||
| NodeKind::Quote { .. }
|
| NodeKind::Quote { .. }
|
||||||
| NodeKind::Linebreak { .. }
|
| NodeKind::Escape(_)
|
||||||
| NodeKind::Raw(_)
|
| NodeKind::Raw(_)
|
||||||
| NodeKind::Math(_)
|
| NodeKind::Math(_)
|
||||||
| NodeKind::Escape(_) => {
|
| NodeKind::Label(_)
|
||||||
|
| NodeKind::Ref(_) => {
|
||||||
p.eat();
|
p.eat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,8 +148,10 @@ impl<'s> Tokens<'s> {
|
|||||||
'*' if !self.in_word() => NodeKind::Star,
|
'*' if !self.in_word() => NodeKind::Star,
|
||||||
'_' if !self.in_word() => NodeKind::Underscore,
|
'_' if !self.in_word() => NodeKind::Underscore,
|
||||||
'`' => self.raw(),
|
'`' => self.raw(),
|
||||||
'$' => self.math(),
|
|
||||||
'=' => NodeKind::Eq,
|
'=' => NodeKind::Eq,
|
||||||
|
'$' => self.math(),
|
||||||
|
'<' => self.label(),
|
||||||
|
'@' => self.reference(),
|
||||||
c if c == '.' || c.is_ascii_digit() => self.numbering(start, c),
|
c if c == '.' || c.is_ascii_digit() => self.numbering(start, c),
|
||||||
|
|
||||||
// Plain text.
|
// Plain text.
|
||||||
@ -277,7 +279,9 @@ impl<'s> Tokens<'s> {
|
|||||||
// Parenthesis and hashtag.
|
// Parenthesis and hashtag.
|
||||||
'[' | ']' | '{' | '}' | '#' |
|
'[' | ']' | '{' | '}' | '#' |
|
||||||
// Markup.
|
// Markup.
|
||||||
'~' | '\'' | '"' | '*' | '_' | '`' | '$' | '=' | '-' | '.' => {
|
'~' | '-' | '.' | ':' |
|
||||||
|
'\'' | '"' | '*' | '_' | '`' | '$' | '=' |
|
||||||
|
'<' | '>' | '@' => {
|
||||||
self.s.expect(c);
|
self.s.expect(c);
|
||||||
NodeKind::Escape(c)
|
NodeKind::Escape(c)
|
||||||
}
|
}
|
||||||
@ -453,6 +457,29 @@ impl<'s> Tokens<'s> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn label(&mut self) -> NodeKind {
|
||||||
|
let label = self.s.eat_while(is_id_continue);
|
||||||
|
if self.s.eat_if('>') {
|
||||||
|
if !label.is_empty() {
|
||||||
|
NodeKind::Label(label.into())
|
||||||
|
} else {
|
||||||
|
NodeKind::Error(SpanPos::Full, "label cannot be empty".into())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.terminated = false;
|
||||||
|
NodeKind::Error(SpanPos::End, "expected closing angle bracket".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reference(&mut self) -> NodeKind {
|
||||||
|
let label = self.s.eat_while(is_id_continue);
|
||||||
|
if !label.is_empty() {
|
||||||
|
NodeKind::Ref(label.into())
|
||||||
|
} else {
|
||||||
|
NodeKind::Error(SpanPos::Full, "label cannot be empty".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ident(&mut self, start: usize) -> NodeKind {
|
fn ident(&mut self, start: usize) -> NodeKind {
|
||||||
self.s.eat_while(is_id_continue);
|
self.s.eat_while(is_id_continue);
|
||||||
match self.s.from(start) {
|
match self.s.from(start) {
|
||||||
|
@ -84,6 +84,8 @@ impl Markup {
|
|||||||
NodeKind::Heading => node.cast().map(MarkupNode::Heading),
|
NodeKind::Heading => node.cast().map(MarkupNode::Heading),
|
||||||
NodeKind::List => node.cast().map(MarkupNode::List),
|
NodeKind::List => node.cast().map(MarkupNode::List),
|
||||||
NodeKind::Enum => node.cast().map(MarkupNode::Enum),
|
NodeKind::Enum => node.cast().map(MarkupNode::Enum),
|
||||||
|
NodeKind::Label(v) => Some(MarkupNode::Label(v.clone())),
|
||||||
|
NodeKind::Ref(v) => Some(MarkupNode::Ref(v.clone())),
|
||||||
_ => node.cast().map(MarkupNode::Expr),
|
_ => node.cast().map(MarkupNode::Expr),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -116,6 +118,10 @@ pub enum MarkupNode {
|
|||||||
List(ListNode),
|
List(ListNode),
|
||||||
/// An item in an enumeration (ordered list): `1. ...`.
|
/// An item in an enumeration (ordered list): `1. ...`.
|
||||||
Enum(EnumNode),
|
Enum(EnumNode),
|
||||||
|
/// A label.
|
||||||
|
Label(EcoString),
|
||||||
|
/// A reference.
|
||||||
|
Ref(EcoString),
|
||||||
/// An expression.
|
/// An expression.
|
||||||
Expr(Expr),
|
Expr(Expr),
|
||||||
}
|
}
|
||||||
|
@ -153,6 +153,10 @@ pub enum Category {
|
|||||||
Punctuation,
|
Punctuation,
|
||||||
/// A line or block comment.
|
/// A line or block comment.
|
||||||
Comment,
|
Comment,
|
||||||
|
/// An easily typable shortcut to a unicode codepoint.
|
||||||
|
Shortcut,
|
||||||
|
/// An escape sequence.
|
||||||
|
Escape,
|
||||||
/// Strong text.
|
/// Strong text.
|
||||||
Strong,
|
Strong,
|
||||||
/// Emphasized text.
|
/// Emphasized text.
|
||||||
@ -165,10 +169,10 @@ pub enum Category {
|
|||||||
Heading,
|
Heading,
|
||||||
/// A list or enumeration.
|
/// A list or enumeration.
|
||||||
List,
|
List,
|
||||||
/// An easily typable shortcut to a unicode codepoint.
|
/// A label.
|
||||||
Shortcut,
|
Label,
|
||||||
/// An escape sequence.
|
/// A reference.
|
||||||
Escape,
|
Ref,
|
||||||
/// A keyword.
|
/// A keyword.
|
||||||
Keyword,
|
Keyword,
|
||||||
/// An operator symbol.
|
/// An operator symbol.
|
||||||
@ -212,6 +216,13 @@ impl Category {
|
|||||||
NodeKind::Dot => Some(Category::Punctuation),
|
NodeKind::Dot => Some(Category::Punctuation),
|
||||||
NodeKind::LineComment => Some(Category::Comment),
|
NodeKind::LineComment => Some(Category::Comment),
|
||||||
NodeKind::BlockComment => Some(Category::Comment),
|
NodeKind::BlockComment => Some(Category::Comment),
|
||||||
|
NodeKind::Linebreak { .. } => Some(Category::Shortcut),
|
||||||
|
NodeKind::NonBreakingSpace => Some(Category::Shortcut),
|
||||||
|
NodeKind::Shy => Some(Category::Shortcut),
|
||||||
|
NodeKind::EnDash => Some(Category::Shortcut),
|
||||||
|
NodeKind::EmDash => Some(Category::Shortcut),
|
||||||
|
NodeKind::Ellipsis => Some(Category::Shortcut),
|
||||||
|
NodeKind::Escape(_) => Some(Category::Escape),
|
||||||
NodeKind::Strong => Some(Category::Strong),
|
NodeKind::Strong => Some(Category::Strong),
|
||||||
NodeKind::Emph => Some(Category::Emph),
|
NodeKind::Emph => Some(Category::Emph),
|
||||||
NodeKind::Raw(_) => Some(Category::Raw),
|
NodeKind::Raw(_) => Some(Category::Raw),
|
||||||
@ -222,13 +233,8 @@ impl Category {
|
|||||||
_ => Some(Category::Operator),
|
_ => Some(Category::Operator),
|
||||||
},
|
},
|
||||||
NodeKind::EnumNumbering(_) => Some(Category::List),
|
NodeKind::EnumNumbering(_) => Some(Category::List),
|
||||||
NodeKind::Linebreak { .. } => Some(Category::Shortcut),
|
NodeKind::Label(_) => Some(Category::Label),
|
||||||
NodeKind::NonBreakingSpace => Some(Category::Shortcut),
|
NodeKind::Ref(_) => Some(Category::Ref),
|
||||||
NodeKind::Shy => Some(Category::Shortcut),
|
|
||||||
NodeKind::EnDash => Some(Category::Shortcut),
|
|
||||||
NodeKind::EmDash => Some(Category::Shortcut),
|
|
||||||
NodeKind::Ellipsis => Some(Category::Shortcut),
|
|
||||||
NodeKind::Escape(_) => Some(Category::Escape),
|
|
||||||
NodeKind::Not => Some(Category::Keyword),
|
NodeKind::Not => Some(Category::Keyword),
|
||||||
NodeKind::And => Some(Category::Keyword),
|
NodeKind::And => Some(Category::Keyword),
|
||||||
NodeKind::Or => Some(Category::Keyword),
|
NodeKind::Or => Some(Category::Keyword),
|
||||||
@ -344,14 +350,16 @@ impl Category {
|
|||||||
Self::Bracket => "punctuation.definition.typst",
|
Self::Bracket => "punctuation.definition.typst",
|
||||||
Self::Punctuation => "punctuation.typst",
|
Self::Punctuation => "punctuation.typst",
|
||||||
Self::Comment => "comment.typst",
|
Self::Comment => "comment.typst",
|
||||||
|
Self::Shortcut => "punctuation.shortcut.typst",
|
||||||
|
Self::Escape => "constant.character.escape.content.typst",
|
||||||
Self::Strong => "markup.bold.typst",
|
Self::Strong => "markup.bold.typst",
|
||||||
Self::Emph => "markup.italic.typst",
|
Self::Emph => "markup.italic.typst",
|
||||||
Self::Raw => "markup.raw.typst",
|
Self::Raw => "markup.raw.typst",
|
||||||
Self::Math => "string.other.math.typst",
|
Self::Math => "string.other.math.typst",
|
||||||
Self::Heading => "markup.heading.typst",
|
Self::Heading => "markup.heading.typst",
|
||||||
Self::List => "markup.list.typst",
|
Self::List => "markup.list.typst",
|
||||||
Self::Shortcut => "punctuation.shortcut.typst",
|
Self::Label => "entity.name.label.typst",
|
||||||
Self::Escape => "constant.character.escape.content.typst",
|
Self::Ref => "markup.other.reference.typst",
|
||||||
Self::Keyword => "keyword.typst",
|
Self::Keyword => "keyword.typst",
|
||||||
Self::Operator => "keyword.operator.typst",
|
Self::Operator => "keyword.operator.typst",
|
||||||
Self::None => "constant.language.none.typst",
|
Self::None => "constant.language.none.typst",
|
||||||
|
@ -723,6 +723,10 @@ pub enum NodeKind {
|
|||||||
///
|
///
|
||||||
/// Can also exist without the number: `.`.
|
/// Can also exist without the number: `.`.
|
||||||
EnumNumbering(Option<usize>),
|
EnumNumbering(Option<usize>),
|
||||||
|
/// A label: `<label>`.
|
||||||
|
Label(EcoString),
|
||||||
|
/// A reference: `@label`.
|
||||||
|
Ref(EcoString),
|
||||||
/// An identifier: `center`.
|
/// An identifier: `center`.
|
||||||
Ident(EcoString),
|
Ident(EcoString),
|
||||||
/// A boolean: `true`, `false`.
|
/// A boolean: `true`, `false`.
|
||||||
@ -935,6 +939,8 @@ impl NodeKind {
|
|||||||
Self::Heading => "heading",
|
Self::Heading => "heading",
|
||||||
Self::Enum => "enumeration item",
|
Self::Enum => "enumeration item",
|
||||||
Self::EnumNumbering(_) => "enumeration item numbering",
|
Self::EnumNumbering(_) => "enumeration item numbering",
|
||||||
|
Self::Label(_) => "label",
|
||||||
|
Self::Ref(_) => "reference",
|
||||||
Self::Ident(_) => "identifier",
|
Self::Ident(_) => "identifier",
|
||||||
Self::Bool(_) => "boolean",
|
Self::Bool(_) => "boolean",
|
||||||
Self::Int(_) => "integer",
|
Self::Int(_) => "integer",
|
||||||
@ -1060,6 +1066,8 @@ impl Hash for NodeKind {
|
|||||||
Self::Heading => {}
|
Self::Heading => {}
|
||||||
Self::Enum => {}
|
Self::Enum => {}
|
||||||
Self::EnumNumbering(num) => num.hash(state),
|
Self::EnumNumbering(num) => num.hash(state),
|
||||||
|
Self::Label(c) => c.hash(state),
|
||||||
|
Self::Ref(c) => c.hash(state),
|
||||||
Self::Ident(v) => v.hash(state),
|
Self::Ident(v) => v.hash(state),
|
||||||
Self::Bool(v) => v.hash(state),
|
Self::Bool(v) => v.hash(state),
|
||||||
Self::Int(v) => v.hash(state),
|
Self::Int(v) => v.hash(state),
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 14 KiB |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
@ -30,7 +30,7 @@
|
|||||||
// Who needs whitespace anyways?
|
// Who needs whitespace anyways?
|
||||||
#import*from"target.typ"
|
#import*from"target.typ"
|
||||||
|
|
||||||
// Should output `Hi`.
|
// Should output `bye`.
|
||||||
// Stop at semicolon.
|
// Stop at semicolon.
|
||||||
#import a, c from "target.typ";bye
|
#import a, c from "target.typ";bye
|
||||||
|
|
||||||
@ -93,25 +93,21 @@ This is never reached.
|
|||||||
// Error: 17-18 expected expression, found comma
|
// Error: 17-18 expected expression, found comma
|
||||||
#import a, b, c,, from "target.typ"
|
#import a, b, c,, from "target.typ"
|
||||||
|
|
||||||
// Should output `"target.typ"`.
|
|
||||||
// Error: 1-6 unexpected keyword `from`
|
// Error: 1-6 unexpected keyword `from`
|
||||||
#from "target.typ"
|
#from "target.typ"
|
||||||
|
|
||||||
// Should output `target`.
|
|
||||||
// Error: 2:2 expected semicolon or line break
|
// Error: 2:2 expected semicolon or line break
|
||||||
#import * from "target.typ
|
#import * from "target.typ
|
||||||
"target
|
"target
|
||||||
|
|
||||||
// Should output `@ 0.2.1`.
|
|
||||||
// Error: 28 expected semicolon or line break
|
// Error: 28 expected semicolon or line break
|
||||||
#import * from "target.typ" @ 0.2.1
|
#import * from "target.typ" § 0.2.1
|
||||||
|
|
||||||
// A star in the list.
|
// A star in the list.
|
||||||
// Error: 12-13 expected expression, found star
|
// Error: 12-13 expected expression, found star
|
||||||
#import a, *, b from "target.typ"
|
#import a, *, b from "target.typ"
|
||||||
|
|
||||||
// An item after a star.
|
// An item after a star.
|
||||||
// Should output `, a from "target.typ"`.
|
|
||||||
// Error: 10 expected keyword `from`
|
// Error: 10 expected keyword `from`
|
||||||
#import *, a from "target.typ"
|
#import *, a from "target.typ"
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
---
|
---
|
||||||
// Escapable symbols.
|
// Escapable symbols.
|
||||||
\\ \/ \[ \] \{ \} \# \* \_ \
|
\\ \/ \[ \] \{ \} \# \* \_ \
|
||||||
\= \~ \` \$ \" \'
|
\= \~ \` \$ \" \' \< \> \@
|
||||||
|
|
||||||
// No need to escape.
|
// No need to escape.
|
||||||
( ) ; < >
|
( ) ;
|
||||||
|
|
||||||
// Unescapable.
|
// Unescapable.
|
||||||
\a \: \; \( \)
|
\a \: \; \( \)
|
||||||
|
@ -31,11 +31,11 @@ Text
|
|||||||
The keyword ```rust let```.
|
The keyword ```rust let```.
|
||||||
|
|
||||||
// Trimming depends on number backticks.
|
// Trimming depends on number backticks.
|
||||||
<``> \
|
(``) \
|
||||||
<` untrimmed `> \
|
(` untrimmed `) \
|
||||||
<``` trimmed` ```> \
|
(``` trimmed` ```) \
|
||||||
<``` trimmed ```> \
|
(``` trimmed ```) \
|
||||||
<``` trimmed```>
|
(``` trimmed```) \
|
||||||
|
|
||||||
---
|
---
|
||||||
// First line is not dedented and leading space is still possible.
|
// First line is not dedented and leading space is still possible.
|
||||||
|
@ -81,7 +81,7 @@
|
|||||||
"name": "markup.heading.typst",
|
"name": "markup.heading.typst",
|
||||||
"contentName": "entity.name.section.typst",
|
"contentName": "entity.name.section.typst",
|
||||||
"begin": "^\\s*=+\\s+",
|
"begin": "^\\s*=+\\s+",
|
||||||
"end": "\n",
|
"end": "\n|(?=<)",
|
||||||
"beginCaptures": { "0": { "name": "punctuation.definition.heading.typst" } },
|
"beginCaptures": { "0": { "name": "punctuation.definition.heading.typst" } },
|
||||||
"patterns": [{ "include": "#markup" }]
|
"patterns": [{ "include": "#markup" }]
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user