mirror of
https://github.com/larvit/adf-codec.git
synced 2026-11-12 11:48:29 +01:00
Write the property's block carries as adf: fences, canonical and hostile
This commit is contained in:
@@ -758,3 +758,20 @@ Read most (opens and searches):
|
||||
- `CHANGELOG.md` 1
|
||||
- `README.md` 1
|
||||
- `mutation-tests/run.sh` 1
|
||||
|
||||
## Reading cost, chunk 1b0dd5a87659, finished 2026-11-08T23:23:58Z
|
||||
|
||||
196044 new input tokens before the first commit.
|
||||
|
||||
Read most (opens and searches):
|
||||
|
||||
- `todo.md` 12
|
||||
- `README.md` 5
|
||||
- `src/markdown/portable/portable-markdown-to-adf.test.ts` 5
|
||||
- `docs/decisions.md` 4
|
||||
- `spec/flavour.md` 4
|
||||
- `docker-runner.sh` 3
|
||||
- `src/markdown/portable/adf-to-portable-markdown.test.ts` 3
|
||||
- `src/markdown/portable/portable-markdown-to-adf.ts` 2
|
||||
- `AGENTS.md` 1
|
||||
- `ci.sh` 1
|
||||
|
||||
@@ -12,7 +12,7 @@ import { adfToLosslessMarkdown } from '../markdown/emit/adf-to-markdown.ts'
|
||||
import { adfToPortableMarkdown } from '../markdown/portable/adf-to-portable-markdown.ts'
|
||||
import { blockArgument, marksAttribute } from '../markdown/directive/block.ts'
|
||||
import { blockNodes } from '../adf/block-nodes.ts'
|
||||
import { carryName } from '../markdown/opaque-carry.ts'
|
||||
import { carryFencePrefix, carryName } from '../markdown/opaque-carry.ts'
|
||||
import { commonMarkToAdf, losslessMarkdownToAdf } from '../markdown/parse/markdown-to-adf.ts'
|
||||
import {
|
||||
directivePrefix,
|
||||
@@ -168,15 +168,37 @@ function container(opener: string, body: string, closer: string): string {
|
||||
return [opener, body, closer].filter((line) => line !== '').join('\n')
|
||||
}
|
||||
|
||||
const carriedNode = fc.oneof(
|
||||
fc.tuple(fc.constantFrom('mention', 'paragraph', 'status', 'widget'), fc.dictionary(jsonKey, jsonValue, { maxKeys: 2, noNullPrototype: true })).map(([type, attrs]): JsonValue => ({ attrs, type })),
|
||||
textOf(1).map((held): JsonValue => ({ text: held, type: 'text' })),
|
||||
type CarriedParts = readonly [type: string, untyped: { [key: string]: JsonValue }]
|
||||
const carriedAttributes = fc.dictionary(jsonKey, jsonValue, { maxKeys: 2, noNullPrototype: true })
|
||||
const carriedParts = fc.oneof(
|
||||
fc.tuple(fc.constantFrom('mention', 'paragraph', 'status', 'widget'), carriedAttributes).map(([type, attrs]): CarriedParts => [type, { attrs }]),
|
||||
textOf(1).map((held): CarriedParts => ['text', { text: held }]),
|
||||
)
|
||||
const unnamedParts = fc.tuple(fc.constantFrom(' x', 'a`b', 'a\\b', 'a&b'), carriedAttributes).map(([type, attrs]): CarriedParts => [type, { attrs }])
|
||||
const carriedNode = carriedParts.map(([type, untyped]): JsonValue => ({ ...untyped, type }))
|
||||
const spellCarry = (json: string) => spellInlineLeafDirective(carryName, `{json=${spellStringAttribute(json)}}`)
|
||||
const inlineCarry = carriedNode.map((node) => spellCarry(serializeCanonicalJson(node, 'compact')))
|
||||
const hostileInlineCarry = fc.oneof(carriedNode, jsonValue).map((node) => spellCarry(JSON.stringify(node, null, 1)))
|
||||
const blockCarry = carriedNode.map((node) => fencedCodeBlock(carryName, serializeCanonicalJson(node, 'two-space')))
|
||||
const hostileBlockCarry = fc.oneof(carriedNode, jsonValue).map((node) => fencedCodeBlock(carryName, JSON.stringify(node)))
|
||||
const blockCarry = fc.oneof(
|
||||
{ arbitrary: carriedParts.map(([type, untyped]) => fencedCodeBlock(`${carryFencePrefix}${type}`, serializeCanonicalJson(untyped, 'two-space'))), weight: 3 },
|
||||
{ arbitrary: unnamedParts.map(([type, untyped]) => fencedCodeBlock(carryFencePrefix, serializeCanonicalJson({ ...untyped, type }, 'two-space'))), weight: 1 },
|
||||
)
|
||||
const hostileBlockCarry = fc
|
||||
.tuple(
|
||||
fc.oneof(carriedParts, unnamedParts),
|
||||
fc.oneof(
|
||||
{ arbitrary: fc.constantFrom(undefined, ''), weight: 6 },
|
||||
{ arbitrary: fc.constantFrom('widget', 'x y', 'a`b', 'a\\b', 'a&b', ' padded'), weight: 1 },
|
||||
),
|
||||
fc.oneof({ arbitrary: fc.constantFrom('untyped', 'typed'), weight: 6 }, { arbitrary: fc.constant('other'), weight: 1 }),
|
||||
fc.oneof({ arbitrary: fc.constant('canonical'), weight: 4 }, { arbitrary: fc.constantFrom('compact', 'indented'), weight: 1 }),
|
||||
jsonValue,
|
||||
)
|
||||
.map(([[type, untyped], named, body, spelling, other]) => {
|
||||
const value = body === 'untyped' ? untyped : body === 'typed' ? { ...untyped, type } : other
|
||||
const json = spelling === 'canonical' ? serializeCanonicalJson(value, 'two-space') : spelling === 'compact' ? JSON.stringify(value) : JSON.stringify(value, null, 1)
|
||||
return fencedCodeBlock(`${carryFencePrefix}${named ?? type}`, json)
|
||||
})
|
||||
|
||||
function prefixLines(body: string, first: string, rest: (index: number) => string): string {
|
||||
return body
|
||||
@@ -402,6 +424,7 @@ const edit: Arbitrary<Edit> = fc.tuple(fc.nat(), fc.nat({ max: 3 }), fc.oneof(pi
|
||||
const markdown = fc.oneof(
|
||||
{ arbitrary: cleanMarkdown, weight: 4 },
|
||||
{ arbitrary: hostileMarkdown, weight: 2 },
|
||||
{ arbitrary: fc.oneof(blockCarry, hostileBlockCarry), weight: 2 },
|
||||
{ arbitrary: canonical, weight: 2 },
|
||||
{ arbitrary: fc.tuple(fc.oneof(cleanMarkdown, canonical), fc.array(edit, { maxLength: 3, minLength: 1 })).map(([held, edits]) => edited(held, edits)), weight: 3 },
|
||||
{ arbitrary: fc.string({ maxLength: 40, unit: piece }), weight: 1 },
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
| 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 |
|
||||
| 75 | 0.4.0 | | | **Make the generated-markdown property write block carries as `adf:` fences, canonical and hostile.** | 1 | 1 | 1 | 1 | 2 | code health by 2 | 17.4 |
|
||||
| 154 | 0.4.0 | | | **Pair highlights over the inline reader's pieces by their offsets before building nodes, so no placeholder text node stands in for a delimiter.** | 2 | 1 | 2 | 3 | 4 | code health by 4 | 17.4 |
|
||||
| 155 | 0.4.0 | | | **Have `closeBracket` return the link, image or literal bracket it builds, and apply it to the scan in one caller.** | 2 | 1 | 2 | 3 | 4 | code health by 4 | 17.4 |
|
||||
| 162 | 0.4.0 | | | **Pin each rule of the emphasis sweep with a hand-worked line, so every mutant that lets a pair fall where the one-run-per-pass reference keeps it fails a test.** | 2 | 1 | 1 | 2 | 4 | code health by 4 | 17.4 |
|
||||
@@ -75,14 +74,6 @@ 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.
|
||||
|
||||
### 75. Make the generated-markdown property write block carries as `adf:` fences, canonical and hostile.
|
||||
|
||||
`blockCarry` and `hostileBlockCarry` (`src/conformance/markdown-property.test.ts`) write a fence
|
||||
whose info string is `carry`. Under the `docs/decisions.md` entry "The carry fence names the node
|
||||
type", that is an ordinary code language, so the property reaches `readCarriedBlock`'s refusals only
|
||||
where a random edit lands in a canonical document. Write `adf:<type>` and `adf:` fences, canonical
|
||||
and hostile. Technical principle: for pure logic over many inputs, prefer a property test, so the property must reach the fenced carry's refusals itself. Found by the technical-principles audit, 2026-10-04.
|
||||
|
||||
### 154. Pair highlights over the inline reader's pieces by their offsets before building nodes, so no placeholder text node stands in for a delimiter.
|
||||
|
||||
A comprehension seat found `src/markdown/inline-content.ts` `resolveNodes` / `pairedHighlights`
|
||||
|
||||
Reference in New Issue
Block a user