Skip to content

Commit e00dafe

Browse files
committed
fix: mermaid edge label — keep arrow (-->) and label (|yes|) as separate tokens, color label as string
1 parent c0c360a commit e00dafe

1 file changed

Lines changed: 23 additions & 4 deletions

File tree

src/tokenize.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,12 @@ const MERMAID_KEYWORDS: &[&str] = &[
9898
/// Flowchart directions → `@constant` (unanimous across grammars; distinct from keywords).
9999
const MERMAID_DIRECTIONS: &[&str] = &["tb", "td", "bt", "rl", "lr"];
100100

101-
/// Characters that make up flow/sequence/class/ER edge operators (`-->`, `-.->`, `==>`,
102-
/// `<|--`, `..>`, `--)`, …). Letters `x`/`o` (arrowheads) are deliberately excluded so a
103-
/// run never eats an adjacent identifier letter (e.g. the `oo` in `foo-->bar`).
101+
/// Characters that make up flow/sequence/edge operators (`-->`, `-.->`, `==>`, `..>`,
102+
/// `--)`, …). Letters `x`/`o` (arrowheads) are excluded so a run never eats an adjacent
103+
/// identifier letter (e.g. the `oo` in `foo-->bar`); `|` is excluded so an edge label
104+
/// `-->|yes|` keeps the arrow (`-->`) and the label (`|yes|`) as separate tokens.
104105
fn is_arrow_char(c: u8) -> bool {
105-
matches!(c, b'-' | b'.' | b'=' | b'<' | b'>' | b'~' | b'|' | b'*')
106+
matches!(c, b'-' | b'.' | b'=' | b'<' | b'>' | b'~' | b'*')
106107
}
107108

108109
/// Tokenize Mermaid source. Colors comments (`%%`), quoted strings, edge/arrow operators,
@@ -145,6 +146,22 @@ pub fn highlight_mermaid(src: &str) -> Vec<HighlightSpan> {
145146
spans.push(span(start..i, string));
146147
continue;
147148
}
149+
// Edge label `|text|` (e.g. `A -->|yes| B`): the label reads as a string, distinct
150+
// from the arrow before it. Requires a non-empty `|…|` on the same line — a bare `|`
151+
// (or ER `||` cardinality) falls through as plain punctuation.
152+
if c == b'|' {
153+
let mut j = i + 1;
154+
while j < b.len() && b[j] != b'|' && b[j] != b'\n' {
155+
j += 1;
156+
}
157+
if j < b.len() && b[j] == b'|' && j > i + 1 {
158+
spans.push(span(i..j + 1, string));
159+
i = j + 1;
160+
continue;
161+
}
162+
i += 1;
163+
continue;
164+
}
148165
// Edge/arrow operator: a run of arrow chars that actually forms a connector.
149166
if is_arrow_char(c) {
150167
let start = i;
@@ -302,6 +319,8 @@ mod tests {
302319
assert_eq!(cat_of(&c, "flowchart"), Some("keyword"));
303320
assert_eq!(cat_of(&c, "LR"), Some("constant"));
304321
assert_eq!(cat_of(&c, "-->"), Some("operator"));
322+
// The edge label `|yes|` is a string, kept separate from the arrow `-->`.
323+
assert_eq!(cat_of(&c, "|yes|"), Some("string"));
305324
assert_eq!(cat_of(&c, "pie"), Some("keyword"));
306325
assert_eq!(cat_of(&c, "\"a\""), Some("string"));
307326
assert_eq!(cat_of(&c, "42"), Some("number"));

0 commit comments

Comments
 (0)