3
0
mirror of https://github.com/larvit/adf-codec.git synced 2026-11-12 11:48:29 +01:00

Answer stability round 1: 1 🔴, 2 🟡 (0 misread); hold a pair whose opener may capture a held pair's delimiter, draw repeated units, pin the carry guards

This commit is contained in:
2026-10-30 01:37:16 +01:00
committed by Lillem4n
parent 47b990feea
commit f151ea5c09
4 changed files with 23 additions and 3 deletions
+5 -1
View File
@@ -217,7 +217,11 @@ const lineLeaf = fc.oneof(
{ arbitrary: fc.record({ attrs: fc.constantFrom({ id: 'a' }, { id: 'a', odd: 'b' }), marks: lineMarks }).map((held): AdfNode => ({ ...held, type: 'mention' })), weight: 1 },
)
export const lineContainer = fc.constantFrom<LineContainer>('heading', 'paragraph', 'table-cell')
export const markedLine = fc.array(lineLeaf, { maxLength: 10, minLength: 1 })
// A unit repeated is the line where one misread run re-pairs every copy after it.
const repeatedUnit = fc
.tuple(fc.array(lineLeaf, { maxLength: 2 }), fc.array(lineLeaf, { maxLength: 3, minLength: 1 }), fc.integer({ max: 5, min: 2 }), fc.array(lineLeaf, { maxLength: 2 }))
.map(([head, unit, repeats, tail]) => [...head, ...Array.from({ length: repeats }, () => unit.map((node) => ({ ...node }))).flat(), ...tail])
export const markedLine = fc.oneof(fc.array(lineLeaf, { maxLength: 10, minLength: 1 }), repeatedUnit)
export const adfDocument = fc.oneof(
{ arbitrary: fc.array(positions.block, { depthIdentifier, maxLength: 4, minLength: 1 }).map((content): AdfDocument => ({ content, type: 'doc', version: 1 })), weight: 30 },
+2
View File
@@ -19,6 +19,8 @@ test('spells a line alike taking every fallback a pass finds or the first alone'
[[{ marks: [{ type: 'em' }], text: 'a', type: 'text' }, { marks: [{ type: 'em' }, { type: 'strike' }, { type: 'strong' }], text: 'a', type: 'text' }, { text: 'a', type: 'text' }], 'paragraph'],
[[1, 2, 3].flatMap(() => [{ text: 'un', type: 'text' }, { marks: [{ type: 'em' }, { type: 'strong' }], text: '-r', type: 'text' }]), 'paragraph'],
[[{ text: 'un', type: 'text' }, { marks: [{ type: 'em' }, { type: 'strong' }], text: '-r', type: 'text' }, { marks: [{ type: 'strike' }], text: 'un', type: 'text' }, { marks: [{ type: 'strike' }, { type: 'em' }, { type: 'strong' }], text: '-r', type: 'text' }, { text: 'z', type: 'text' }], 'paragraph'],
[[{ marks: [{ type: 'strike' }], text: ' b', type: 'text' }, { marks: [{ type: 'em' }], text: '!-', type: 'text' }], 'paragraph'],
[[{ marks: [{ type: 'strike' }], text: 'r', type: 'text' }, { marks: [{ type: 'strike' }, { type: 'strong' }, { type: 'em' }], text: '[ ', type: 'text' }, ...[1, 2, 3, 4, 5].map(() => ({ marks: [{ type: 'strike' }], text: ' ', type: 'text' }))], 'heading'],
],
},
)
+13 -2
View File
@@ -333,11 +333,22 @@ function misflankedHighlights(placed: readonly PlacedSegment[], output: string):
return misflanked
}
// A pair falls with the first where one run per pass would take it back too: one of its delimiters cannot flank however the unsettled pairs fall, and taking it back moves no delimiter another verdict reads.
// A pair falls with the first where one run per pass would take it back too: one of its delimiters cannot flank however the unsettled pairs fall.
function fallsWithFirst(sweep: PairSweep, judged: number): boolean {
if (!fallsCleanly(sweep, judged)) return false
const spellings = pairSpellings(sweep, judged, judged)
return spellings !== undefined && spellings.every((character) => !mayFlank(sweep, judged, character, 'opener') || !mayFlank(sweep, judged, character, 'closer'))
return spellings !== undefined && spellings.every((character) => !mayFlank(sweep, judged, character, 'opener') || (!mayFlank(sweep, judged, character, 'closer') && !holdsAlike(sweep, judged, character)))
}
// An opener that may open can pair with a delimiter of its own character inside, so one run per pass may take back a pair standing there first.
function holdsAlike({ fallen, pairs }: PairSweep, judged: number, character: string): boolean {
const pair = pairs[judged]
for (let held = judged - 1; pair !== undefined && held >= 0; held -= 1) {
const inner = pairs[held]
if (inner === undefined || inner.closer < pair.opener) return false
if (fallen[held] === 0 && (inner.delimiter.length === 1 ? character !== '~' : inner.delimiter.startsWith(character))) return true
}
return false
}
// A carry splits every pair holding it, so a carried pair holds no pair that may fall first; a dropped pair keeps its leaves where no run merges at its ends.
@@ -21,6 +21,9 @@ test('reduces a line alike dropping every run a pass may or the first alone', ()
[[1, 2, 3].flatMap(() => [{ marks: [{ type: 'em' }, { type: 'strike' }, { type: 'strong' }], text: '(', type: 'text' }, { attrs: { id: 'a' }, type: 'mention' }]), 'paragraph'],
[[{ text: 'z', type: 'text' }, ...[1, 2, 3].flatMap(() => [{ marks: [{ type: 'strike' }], text: '(b', type: 'text' }, { marks: [{ type: 'em' }], text: '(b', type: 'text' }])], 'paragraph'],
[[...[1, 2, 3].flatMap(() => [{ marks: [{ type: 'strike' }], text: 'b(', type: 'text' }, { marks: [{ type: 'em' }], text: 'b(', type: 'text' }]), { text: 'z', type: 'text' }], 'paragraph'],
[[...[1, 2, 3].flatMap(() => [{ marks: [{ type: 'em' }, { type: 'strong' }], text: '(', type: 'text' }, { marks: [{ type: 'em' }], text: '(', type: 'text' }]), { text: 'a', type: 'text' }], 'paragraph'],
[[...[1, 2, 3, 4, 5].flatMap(() => [{ marks: [{ type: 'em' }, { type: 'strong' }], text: '~** ', type: 'text' }, { marks: [{ type: 'em' }], text: '- _', type: 'text' }]), { text: 'r', type: 'text' }], 'table-cell'],
[[...[1, 2, 3].flatMap(() => [{ marks: [{ type: 'em' }, { type: 'strong' }], text: ' ~~ ', type: 'text' }, { marks: [{ type: 'em' }, { type: 'strike' }, { type: 'strong' }], text: ')', type: 'text' }]), { text: 'a', type: 'text' }, { marks: [{ type: 'strike' }, { type: 'strong' }], text: '.unun', type: 'text' }], 'heading'],
],
},
)