3
0
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:
2026-11-09 05:08:08 +01:00
committed by Lillem4n
parent 26c16850a8
commit 796f520990
2 changed files with 15 additions and 15 deletions
+8 -7
View File
@@ -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)
}
+7 -8
View File
@@ -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.