Compare commits
3 Commits
1eb7b54f19
...
2f03e20549
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f03e20549 | |||
| ae2dc6054b | |||
| 7a53b6f7a0 |
@@ -143,6 +143,7 @@ test('lifts a == pair to the editor default highlight, Yellow200 #f8e6a0 in @atl
|
|||||||
assert.deepEqual(lifted('==**a**_b_ `c`==\n'), [paragraph(text('a', highlight, strong), text('b', highlight, em), text(' ', highlight), text('c', code))])
|
assert.deepEqual(lifted('==**a**_b_ `c`==\n'), [paragraph(text('a', highlight, strong), text('b', highlight, em), text(' ', highlight), text('c', code))])
|
||||||
assert.deepEqual(lifted('==`a`==\n'), [paragraph(text('a', code))])
|
assert.deepEqual(lifted('==`a`==\n'), [paragraph(text('a', code))])
|
||||||
assert.deepEqual(lifted('x==y==z ==a == b==, (==c==) _d_==e==\n'), [paragraph(text('x==y==z '), text('a == b', highlight), text(', ('), text('c', highlight), text(') '), text('d', em), text('e', highlight))])
|
assert.deepEqual(lifted('x==y==z ==a == b==, (==c==) _d_==e==\n'), [paragraph(text('x==y==z '), text('a == b', highlight), text(', ('), text('c', highlight), text(') '), text('d', em), text('e', highlight))])
|
||||||
|
assert.deepEqual(lifted('😀==b== ==c==😀 é==d==\n'), [paragraph(text('😀'), text('b', highlight), text(' '), text('c', highlight), text('😀 é==d=='))])
|
||||||
assert.deepEqual(lifted('# ==h==\n\n| ==c== |\n| --- |\n'), [
|
assert.deepEqual(lifted('# ==h==\n\n| ==c== |\n| --- |\n'), [
|
||||||
node('heading', { level: 1 }, text('h', highlight)),
|
node('heading', { level: 1 }, text('h', highlight)),
|
||||||
bare('table', bare('tableRow', bare('tableHeader', paragraph(text('c', highlight))))),
|
bare('table', bare('tableRow', bare('tableHeader', paragraph(text('c', highlight))))),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { AdfDocument, AdfMark, AdfNode } from '../../adf/document.ts'
|
import type { AdfDocument, AdfMark, AdfNode } from '../../adf/document.ts'
|
||||||
import { blockNodeModel } from '../../adf/block-nodes.ts'
|
import { blockNodeModel } from '../../adf/block-nodes.ts'
|
||||||
|
import { isWordCharacter } from '../commonmark/emphasis-matching.ts'
|
||||||
import { highlightDelimiter, readAlertMarker, readTaskMarker } from '../plain-conventions.ts'
|
import { highlightDelimiter, readAlertMarker, readTaskMarker } from '../plain-conventions.ts'
|
||||||
import { mergeAdjacentText, sameMarks } from '../../adf/editor-normal.ts'
|
import { mergeAdjacentText, sameMarks } from '../../adf/editor-normal.ts'
|
||||||
import { nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
import { nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
||||||
@@ -114,8 +115,11 @@ function delimiters(inline: readonly AdfNode[]): Delimiter[] {
|
|||||||
const end = offset + highlightDelimiter.length
|
const end = offset + highlightDelimiter.length
|
||||||
const before = offset > 0 ? text[offset - 1] : textOf(inline[index - 1])?.at(-1)
|
const before = offset > 0 ? text[offset - 1] : textOf(inline[index - 1])?.at(-1)
|
||||||
const after = text[end] ?? textOf(inline[index + 1])?.[0]
|
const after = text[end] ?? textOf(inline[index + 1])?.[0]
|
||||||
const closes = flanks(before) && bounds(text[end])
|
// Outside a delimiter a node's edge bounds it, standing where the source spelled a mark's punctuation.
|
||||||
found.push({ closes, holder: node, line, node: index, offset, opens: flanks(after) && bounds(text[offset - 1]), position: position + offset })
|
const outsideBefore = Array.from(text.slice(Math.max(0, offset - 2), offset)).at(-1) ?? ''
|
||||||
|
const outsideAfter = Array.from(text.slice(end, end + 2))[0] ?? ''
|
||||||
|
const closes = flanks(before) && !isWordCharacter(outsideAfter)
|
||||||
|
found.push({ closes, holder: node, line, node: index, offset, opens: flanks(after) && !isWordCharacter(outsideBefore), position: position + offset })
|
||||||
}
|
}
|
||||||
position += text.length
|
position += text.length
|
||||||
}
|
}
|
||||||
@@ -126,11 +130,6 @@ function flanks(character: string | undefined): boolean {
|
|||||||
return character !== undefined && !/\s/.test(character)
|
return character !== undefined && !/\s/.test(character)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Outside a delimiter, a node's edge stands where the source spelled a mark's punctuation.
|
|
||||||
function bounds(character: string | undefined): boolean {
|
|
||||||
return character === undefined || /[\s\p{P}\p{S}]/u.test(character)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each opener takes the next closer holding at least one character after it, both in one line and under the same marks.
|
// Each opener takes the next closer holding at least one character after it, both in one line and under the same marks.
|
||||||
function pairedDelimiters(inline: readonly AdfNode[]): Delimiter[] {
|
function pairedDelimiters(inline: readonly AdfNode[]): Delimiter[] {
|
||||||
const found = delimiters(inline)
|
const found = delimiters(inline)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Start a session with: `Read AGENTS.md and todo.md, then do what todo.md's "Next
|
|||||||
## Milestones
|
## Milestones
|
||||||
|
|
||||||
Shipping order: 3h, 3i, 3j, 5a, 5b, 5c, 5d, 5 → `0.1.0` (shipped 2026-09-05); 3k, 11, 4, 12, 13, 4b,
|
Shipping order: 3h, 3i, 3j, 5a, 5b, 5c, 5d, 5 → `0.1.0` (shipped 2026-09-05); 3k, 11, 4, 12, 13, 4b,
|
||||||
4c, 14, 15, 16, 18, 4d, 28, 17, 29, 19, 20, 21, 22, 32, 23, 24, 25, 30, 26, 27, 10, 6, 7, 31, 33, 5f, 5g →
|
4c, 14, 15, 16, 18, 4d, 28, 17, 29, 19, 20, 21, 22, 32, 23, 24, 25, 30, 26, 27, 10, 6, 7, 31, 33, 34, 5f, 5g →
|
||||||
`0.2.0`;
|
`0.2.0`;
|
||||||
8, 9 → TBD; 5e last.
|
8, 9 → TBD; 5e last.
|
||||||
The numbering is the order the work was planned in, not the order it ships. Everything known and
|
The numbering is the order the work was planned in, not the order it ships. Everything known and
|
||||||
@@ -43,8 +43,7 @@ HTML doubles the importers and the file count they touch, and 25 to 27 because t
|
|||||||
panel says the next reader pays for.
|
panel says the next reader pays for.
|
||||||
29 and 30 come from 17's prose pass (2026-09-20). 29 reads first because every goal is what a later
|
29 and 30 come from 17's prose pass (2026-09-20). 29 reads first because every goal is what a later
|
||||||
ask is settled against, 19's included; 30 sits beside 25, the other chunk rereading AGENTS.md.
|
ask is settled against, 19's included; 30 sits beside 25, the other chunk rereading AGENTS.md.
|
||||||
33 comes from 10a (2026-09-25) and reads beside 31, the other chunk about what the pipeline
|
33 comes from 10a and 34 from 10b (2026-09-25); both read beside 31.
|
||||||
measures.
|
|
||||||
31 comes from 20's gate runs (2026-09-21) and reads beside 5f, the other chunk putting a measured
|
31 comes from 20's gate runs (2026-09-21) and reads beside 5f, the other chunk putting a measured
|
||||||
number under the pipeline. 32 comes from 21's review (2026-09-21) and reads beside 22, the other
|
number under the pipeline. 32 comes from 21's review (2026-09-21) and reads beside 22, the other
|
||||||
chunk clearing a §11 seam.
|
chunk clearing a §11 seam.
|
||||||
@@ -62,6 +61,10 @@ chunk clearing a §11 seam.
|
|||||||
on one paragraph of 2000 × `un` plus `**-r**`: each run its flanking cannot spell re-emits the
|
on one paragraph of 2000 × `un` plus `**-r**`: each run its flanking cannot spell re-emits the
|
||||||
whole line before riding the carry, quadratic in the runs (§11 Bounds), and the plain
|
whole line before riding the carry, quadratic in the runs (§11 Bounds), and the plain
|
||||||
reduction's `spellableLine` drops one mark per re-emit the same way. Make both linear.
|
reduction's `spellableLine` drops one mark per re-emit the same way. Make both linear.
|
||||||
|
- [ ] **34 — Emphasis flanking reads a whole character (`0.2.0`).** Check whether
|
||||||
|
`line-escaping.ts`'s `charAt` and the parser's flanking read one UTF-16 unit beside an astral
|
||||||
|
symbol — a lone surrogate is neither punctuation nor symbol, where CommonMark reads `😀` as
|
||||||
|
punctuation — and, where they do, read the code point, with a fixture per direction.
|
||||||
- [x] **24 — The conformance gates have a directory (`0.2.0`).**
|
- [x] **24 — The conformance gates have a directory (`0.2.0`).**
|
||||||
- [x] **25 — AGENTS.md §8 and §11 are findable (`0.2.0`).**
|
- [x] **25 — AGENTS.md §8 and §11 are findable (`0.2.0`).**
|
||||||
- [x] **26 — The two mutable structures say what they guarantee (`0.2.0`).**
|
- [x] **26 — The two mutable structures say what they guarantee (`0.2.0`).**
|
||||||
|
|||||||
Reference in New Issue
Block a user