A CJK, Hangul or Southeast Asian character beside a == bounds a highlight #147

Merged
lilleman merged 5 commits from cjk-highlight into main 2026-09-29 19:53:10 +02:00
3 changed files with 11 additions and 10 deletions
Showing only changes of commit e2a660ee8e - Show all commits
+1 -1
View File
@@ -133,7 +133,7 @@ read replaces mentions, attachments and macros with text.
| `panel` | a GitHub alert, `> [!WARNING]`: info `NOTE`, note `IMPORTANT`, tip and success `TIP`, warning `WARNING`, error `CAUTION`, custom `NOTE` | `NOTE` info, `IMPORTANT` note, `TIP` tip, `WARNING` warning, `CAUTION` error, and Obsidian's: hint tip; success, check, done success; attention warning; danger, failure, fail, missing, bug, error error; any other word info — in any case; the rest of the marker's line is the first paragraph | | `panel` | a GitHub alert, `> [!WARNING]`: info `NOTE`, note `IMPORTANT`, tip and success `TIP`, warning `WARNING`, error `CAUTION`, custom `NOTE` | `NOTE` info, `IMPORTANT` note, `TIP` tip, `WARNING` warning, `CAUTION` error, and Obsidian's: hint tip; success, check, done success; attention warning; danger, failure, fail, missing, bug, error error; any other word info — in any case; the rest of the marker's line is the first paragraph |
| `expand`, `nestedExpand` | Obsidian's folded callout, `> [!NOTE]- Title` | `-` or `+` after any word, the rest of the marker's line the title; an expand inside an expand is a `nestedExpand` | | `expand`, `nestedExpand` | Obsidian's folded callout, `> [!NOTE]- Title` | `-` or `+` after any word, the rest of the marker's line the title; an expand inside an expand is a `nestedExpand` |
| `taskList` | `- [x] Done`, `- [ ] Todo` | a bullet list whose every item is so marked, `[X]` too | | `taskList` | `- [x] Done`, `- [ ] Todo` | a bullet list whose every item is so marked, `[X]` too |
| `backgroundColor` | `==text==` | `==text==` on one line, the text touching both delimiters, bounded outside by whitespace, punctuation, a line edge or a letter of a script written without spaces (Han, Hiragana, Katakana, Thai, Lao, Khmer, Myanmar), in the editor's default highlight `#f8e6a0` | | `backgroundColor` | `==text==` | `==text==` on one line, the text touching both delimiters, bounded outside by whitespace, punctuation or a line edge, or touching a Han, Hangul, Hiragana, Katakana, Thai, Lao, Khmer or Myanmar character on either side, in the editor's default highlight `#f8e6a0` |
| `table` | a pipe table: the first row its header, a cell's blocks on one line, a span kept under its header by empty cells | — | | `table` | a pipe table: the first row its header, a cell's blocks on one line, a span kept under its header by empty cells | — |
| `decisionList` | a bullet list | — | | `decisionList` | a bullet list | — |
| `mention`, `status`, `emoji`, `date` | their text: `@` kept, a mention with none `@` and its id, an emoji its `shortName` without, a date `2026-09-13` in UTC | — | | `mention`, `status`, `emoji`, `date` | their text: `@` kept, a mention with none `@` and its id, an emoji its `shortName` without, a date `2026-09-13` in UTC | — |
+4 -4
View File
@@ -151,10 +151,10 @@ renderer is the one the audience's markdown is read in.
README §Plain markdown's rows come from a survey of GitHub, GitLab, Gitea, Obsidian, Pandoc, README §Plain markdown's rows come from a survey of GitHub, GitLab, Gitea, Obsidian, Pandoc,
MkDocs, Docusaurus, Typora, Joplin, Logseq, Bear, Notion, Azure DevOps and Discord, GitHub's MkDocs, Docusaurus, Typora, Joplin, Logseq, Bear, Notion, Azure DevOps and Discord, GitHub's
renderer confirming each shape. Reader panels settled `error` as an error panel, the `==` bounds renderer confirming each shape. Reader panels settled `error` as an error panel, the `==` bounds
(3 of 3) and a letter of a script written without spaces bounding them, so `は==日本語==で` (3 of 3) and a Han, Hangul, kana, Thai, Lao, Khmer or Myanmar character on either side bounding a
highlights (3 of 3), the external image's two forms (6 of 7), the omission notes and a rule delimiter, so `は==日本語==で` (3 of 3), `==한국어==에서만` and `iPhone==専用==` (6 of 7) highlight,
opening a list item dropping (3 of 3), and a list's numbering overflowing into bullets (3 of 3, the external image's two forms (6 of 7), the omission notes and a rule opening a list item
5 of 7). dropping (3 of 3), and a list's numbering overflowing into bullets (3 of 3, 5 of 7).
Reading takes other tools' spellings, since it reads their output and writes none of them. Reading takes other tools' spellings, since it reads their output and writes none of them.
Rejected: `~sub~` and `^sup^` (`~2~` is a strike on GitHub, so `subsup` drops), underline and colour Rejected: `~sub~` and `^sup^` (`~2~` is a strike on GitHub, so `subsup` drops), underline and colour
spellings, raw HTML (`<details>`, `<mark>`), MkDocs `!!!` and the `:::` admonition family, spellings, raw HTML (`<details>`, `<mark>`), MkDocs `!!!` and the `:::` admonition family,
+6 -5
View File
@@ -16,6 +16,9 @@ const alertWords: Readonly<Record<string, string>> = {
warning: 'WARNING', warning: 'WARNING',
} }
// ー, ー and the kana voicing marks are Script=Common; Script_Extensions would also take Latin combining marks.
const boundingScript = /^[\u3099-\u309c\u30fc\uff70\uff9e\uff9f\p{Script=Han}\p{Script=Hangul}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Khmer}\p{Script=Lao}\p{Script=Myanmar}\p{Script=Thai}]$/u
const panelTypesByWord: Readonly<Record<string, string>> = { const panelTypesByWord: Readonly<Record<string, string>> = {
attention: 'warning', attention: 'warning',
bug: 'error', bug: 'error',
@@ -34,8 +37,6 @@ const panelTypesByWord: Readonly<Record<string, string>> = {
warning: 'warning', warning: 'warning',
} }
const unspacedScript = /^[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Khmer}\p{Script=Lao}\p{Script=Myanmar}\p{Script=Thai}]$/u
export function alertMarker(panelType: unknown): string { export function alertMarker(panelType: unknown): string {
const word = typeof panelType === 'string' && Object.hasOwn(alertWords, panelType) ? alertWords[panelType] : undefined const word = typeof panelType === 'string' && Object.hasOwn(alertWords, panelType) ? alertWords[panelType] : undefined
return `[!${word ?? 'NOTE'}]` return `[!${word ?? 'NOTE'}]`
@@ -62,11 +63,11 @@ export function highlightFlanking(source: string, index: number): { closes: bool
const end = index + highlightDelimiter.length const end = index + highlightDelimiter.length
const before = Array.from(source.slice(Math.max(0, index - 2), index)).at(-1) ?? '' const before = Array.from(source.slice(Math.max(0, index - 2), index)).at(-1) ?? ''
const after = Array.from(source.slice(end, end + 2))[0] ?? '' const after = Array.from(source.slice(end, end + 2))[0] ?? ''
return { closes: flanks(before) && bounds(after), opens: flanks(after) && bounds(before) } return { closes: flanks(before) && bounds(after, before), opens: flanks(after) && bounds(before, after) }
} }
function bounds(character: string): boolean { function bounds(outside: string, inside: string): boolean {
return !isWordCharacter(character) || unspacedScript.test(character) return !isWordCharacter(outside) || boundingScript.test(outside) || boundingScript.test(inside)
} }
function flanks(character: string): boolean { function flanks(character: string): boolean {