Colour markdown, which is the one language that is not tokens

The token scanner asks what a character is; markdown's meaning is where it
sits, so a `#` opens a heading at the start of a line and is an ordinary
character three words in. `MarkdownSyntax.kt` reads structure a line at a
time and then each line's prose left to right, and `spansOf` is the one
entry point that hides which of the two scanners a language got.

Conservative wherever a guess would be invisible: emphasis needs a closer on
the same line with no space beside either marker, so the `*p = *q` of a C
fragment opens nothing; an underscore may not start or end inside a word;
and an indented code block is left plain, since four spaces after a blank
line and four after a bullet are the same line.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Opus 5 committed 2026-09-04 02:37:32 -04:00
1 parent a401e6a7e3
commit 68c5180260
8 files changed
+476 -12

No files matched your search

+15
View File
@@ -239,6 +239,21 @@ and are the reason several tempting simplifications were rejected.
to the end of the code. `HighlighterTest.kt` is the JVM unit test
(`./gradlew :androidApp:testDebugUnitTest`); the cases in it are the
library's mistakes, kept as regressions.
**Markdown is the one language that is not a `Rules` row**
(`MarkdownSyntax.kt`, added 2026-09-04). It has no keywords and no
strings, and what a character means there depends on where on the line it
sits -- a `#` opens a heading at the start of a line and is an ordinary
character three words in -- which is a question the token scanner cannot
ask. So it carries a scanner of its own, structure a line at a time and
then the inline forms left to right, and `spansOf` in `Languages.kt` is
the one entry point that hides which of the two a language got. It is
deliberately conservative where a guess would be invisible: emphasis needs
a closer on the same line with no space beside either marker (so the
`*p = *q` of a C fragment in a paragraph opens nothing), an underscore may
not start or end inside a word (`snake_case_name`), and an indented code
block is left plain, because four spaces after a blank line and four
spaces after a bullet are the same line and only what came before tells
them apart.
It replaced dev.snipme:highlights 1.1.0 on 2026-09-03, which found
comments before it knew the language and paired `/*` with `*/` by
ordinal. That library used one set of delimiters for every language, so