mirror of
https://github.com/larvit/adf-codec.git
synced 2026-11-12 11:48:29 +01:00
Drop the unreachable task-list guards in tryTaskList
This commit is contained in:
@@ -7,7 +7,6 @@ import { emitBlock, joinBlocks, quotedBlocks, spelledList, walkBlocks } from '..
|
||||
import { emitInlineLine } from '../emit/inline-line.ts'
|
||||
import { failure, success } from '../../result.ts'
|
||||
import { isTaskItem } from '../../adf/block-nodes.ts'
|
||||
import { largestNesting } from '../../nesting.ts'
|
||||
import { nodeAttrs, nodeContent } from '../../adf/document.ts'
|
||||
|
||||
const portableBlockWriters: FlavourBlockWriters = {
|
||||
@@ -41,18 +40,20 @@ function headed(head: string): (body: BlockText) => BlockText {
|
||||
|
||||
function tryTaskList(node: AdfNode, path: ConvertErrorPath, depth: number, writing: Writing): Result<EmittedBlock> {
|
||||
const items: PlacedBlock[][] = []
|
||||
let headroom = largestNesting - depth - 1
|
||||
// The portable reduction leaves a task list opening with a task, so `item` is set before any child nests in it.
|
||||
let item: PlacedBlock[] = []
|
||||
// A child other than a task nests in the task before it.
|
||||
for (const [index, child] of nodeContent(node).entries()) {
|
||||
const task = isTaskItem(child)
|
||||
const walk = task ? taskBlocks(child, [...path, 'content', index], depth + 1, writing) : placedBlock(child, [...path, 'content', index], depth + 1, writing)
|
||||
if (!walk.ok) return walk
|
||||
headroom = Math.min(headroom, walk.value.headroom)
|
||||
const previous = items.at(-1)
|
||||
if (task || previous === undefined) items.push([...walk.value.blocks])
|
||||
else for (const block of walk.value.blocks) previous.push(block)
|
||||
if (task) {
|
||||
item = []
|
||||
items.push(item)
|
||||
}
|
||||
for (const block of walk.value.blocks) item.push(block)
|
||||
}
|
||||
const list = spelledList(items.map((blocks) => joinBlocks(blocks, 'list-item')), undefined, headroom)
|
||||
const list = spelledList(items.map((blocks) => joinBlocks(blocks, 'list-item')), undefined, Number.POSITIVE_INFINITY)
|
||||
// The portable reduction leaves no task a list item cannot hold: a directive here would break the flavour.
|
||||
return list === undefined ? failure('unsupported-node-shape', 'a task holds blocks no list item spells', path) : success(list)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
| ID | Release | Blocked by | Exempt | Item | L | E | I | R | S | Moves | Score |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| 153 | 0.4.0 | | question | **Decide whether `src/markdown/` root may import `emit/`, `parse/` or `portable/`, and hold the answer in `.oxlintrc.json` and §The source parts by ADF and format.** | 1 | 2 | 2 | 3 | 2 | code health by 3 | 26.2 |
|
||||
| 175 | 0.4.0 | | | **Delete the guards in `tryTaskList` that `reduceToPortable` makes unreachable, once a test shows `adfToPortableMarkdown` reaches none of them.** | 1 | 1 | 1 | 1 | 2 | code health by 2 | 17.4 |
|
||||
| 175 | 0.4.0 | | | **Delete the `'a task holds blocks no list item spells'` failure and the child paths in `tryTaskList`, once `spelledList` yields a list the portable reduction can never refuse.** | 1 | 1 | 1 | 1 | 2 | code health by 2 | 17.4 |
|
||||
| 176 | 0.4.0 | | | **Delete `runEdge`'s `standing === 'moves'` give-up, and any code only it needs, once a test or an argument shows `runEdge` never reaches it, or else pin the case with a hand-worked line.** | 1 | 1 | 2 | 2 | 2 | code health by 2 | 17.4 |
|
||||
| 45 | 0.4.0 | | defect | **Replace `isAdfDocument` with a reader returning `Result<AdfDocument>`.** | 2 | 1 | 3 | 4 | 3 | 1 by 2 | 13.1 |
|
||||
| 127 | 0.4.0 | | principle | **Hold what `entity-references.test.ts`, `json-text.test.ts` and `result.test.ts` check by asserting outcomes, so none reads source text.** | 2 | 2 | 1 | 3 | 3 | code health by 2 | 13.1 |
|
||||
@@ -72,14 +72,13 @@ a paragraph opening with a spellable `!adf:link` (§Nothing recurses unbounded).
|
||||
`src/markdown/**` bans only `html/`; banning `emit/`, `parse/` and `portable/` for the root's own
|
||||
files, with its `ci.sh` probe, extends the decision.
|
||||
|
||||
### 175. Delete the guards in `tryTaskList` that `reduceToPortable` makes unreachable, once a test shows `adfToPortableMarkdown` reaches none of them.
|
||||
### 175. Delete the `'a task holds blocks no list item spells'` failure and the child paths in `tryTaskList`, once `spelledList` yields a list the portable reduction can never refuse.
|
||||
|
||||
`reduceToPortable` runs first and turns a task list opening with a non-task into a bullet list. So
|
||||
`tryTaskList` (`portable/block-spelling.ts`) never sees `previous === undefined`, and its
|
||||
`'a task holds blocks no list item spells'` failure has no test. The `path` it passes to
|
||||
`taskBlocks` and `placedBlock`, and its `Math.min` of `headroom`, change no output, since the
|
||||
nesting refusal's path comes from `reduceToPortable`. Found by mutation testing for item 128,
|
||||
2026-11-08.
|
||||
`reduceToPortable` runs first, so `adfToPortableMarkdown` never reaches `tryTaskList`'s
|
||||
(`portable/block-spelling.ts`) failure; no test reaches it either. It stays because `spelledList`
|
||||
returns `undefined` for the blocks a list item cannot hold, and the type has no cast to drop it.
|
||||
The `path` it passes to `taskBlocks` and `placedBlock` changes no output, since the nesting
|
||||
refusal's path comes from `reduceToPortable`. Found by mutation testing for item 128, 2026-11-08.
|
||||
|
||||
### 176. Delete `runEdge`'s `standing === 'moves'` give-up, and any code only it needs, once a test or an argument shows `runEdge` never reaches it, or else pin the case with a hand-worked line.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user