typst: fix URL comment split and heading label highlighting
Build and Deploy Verso / deploy (push) Successful in 13m56s
Build and Deploy Verso / deploy (push) Successful in 13m56s
- Add URL token (https://... / http://...) so '://' is never split into ':' + LineComment '//', preventing URLs from being styled as comments - Stop headingTitleTokenizer before '<label>' patterns so labels at the end of headings get Label node styling instead of being consumed as heading title text - Style URL nodes with t.url tag Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -77,6 +77,9 @@ export const TypstLanguage = LRLanguage.define({
|
||||
'Strong/"*" Strong/StrongBody': t.strong,
|
||||
'Emphasis/"_" Emphasis/EmphBody': t.emphasis,
|
||||
|
||||
// Bare URLs (https://... / http://...)
|
||||
URL: t.url,
|
||||
|
||||
// Labels (<name>) and references (@name)
|
||||
'Label/"<" Label/">" Label/LabelName': t.labelName,
|
||||
'Ref/"@" Ref/RefName': t.labelName,
|
||||
|
||||
@@ -35,6 +35,8 @@ const DOT = 46 // .
|
||||
const OPEN_PAREN = 40 // (
|
||||
const COMMA = 44 // ,
|
||||
const COLON = 58 // :
|
||||
const OPEN_ANGLE = 60 // <
|
||||
const CLOSE_ANGLE = 62 // >
|
||||
|
||||
const KEYWORDS = new Set([
|
||||
'let', 'set', 'show', 'import', 'include',
|
||||
@@ -87,6 +89,17 @@ export const headingTitleTokenizer = new ExternalTokenizer(
|
||||
while (input.next !== -1 && input.next !== NEWLINE) {
|
||||
if (input.next === SLASH &&
|
||||
(input.peek(1) === SLASH || input.peek(1) === STAR)) break
|
||||
// Stop before a trailing '<label>' so it is parsed as a Label node
|
||||
// rather than being merged into the heading title text.
|
||||
// Only stops when '<' is immediately followed by a valid label name and '>'.
|
||||
if (input.next === OPEN_ANGLE) {
|
||||
const ch = input.peek(1)
|
||||
if (isAlpha(ch) || isDigit(ch) || ch === UNDERSCORE) {
|
||||
let j = 2
|
||||
while (isIdentTail(input.peek(j)) || input.peek(j) === DOT || input.peek(j) === COLON) j++
|
||||
if (input.peek(j) === CLOSE_ANGLE) break
|
||||
}
|
||||
}
|
||||
input.advance()
|
||||
hasContent = true
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ item {
|
||||
Label |
|
||||
Ref |
|
||||
Escape |
|
||||
URL |
|
||||
MarkupContent
|
||||
}
|
||||
|
||||
@@ -218,6 +219,11 @@ Escape { "\\" EscapeChar }
|
||||
("pt" | "mm" | "cm" | "in" | "em" | "rem" | "fr" | "deg" | "rad" | "%")?
|
||||
}
|
||||
|
||||
// URL: bare https:// or http:// links in markup text. Matched as a single
|
||||
// token so '://' is never split into ':' + LineComment '//…'. Stops at
|
||||
// whitespace and angle brackets (labels use '<…>').
|
||||
URL { ("https" | "http") "://" (![ \t\n<>])* }
|
||||
|
||||
// Regular markup: excludes all special-character starters plus whitespace
|
||||
// (whitespace is handled by @skip). The '/' is excluded so that '//' and
|
||||
// '/*' are not accidentally consumed as plain text.
|
||||
@@ -241,7 +247,8 @@ Escape { "\\" EscapeChar }
|
||||
// "[" > MarkupContent: ContentBlock callSuffix wins in merged code/markup states.
|
||||
// CodeString > MarkupContent: '"' starts a string literal after a keyword.
|
||||
// ":" > MarkupContent: keywordBody ':' wins over markup colon in code states.
|
||||
@precedence { CodeBool EscapeChar CodeString "[" ":" "(" "." "]" "_" spaces MarkupContent }
|
||||
// URL > MarkupContent: 'https://' / 'http://' wins over plain markup text.
|
||||
@precedence { CodeBool EscapeChar CodeString URL "[" ":" "(" "." "]" "_" spaces MarkupContent }
|
||||
}
|
||||
|
||||
@skip { spaces }
|
||||
|
||||
Reference in New Issue
Block a user