Name the two text-joining rules for whose rule they are, side by side in adjacent-text.ts
This commit is contained in:
@@ -11,7 +11,7 @@ import { blockNodes } from '../adf/block-nodes.ts'
|
|||||||
import { directivePrefix } from '../markdown/directive-syntax.ts'
|
import { directivePrefix } from '../markdown/directive-syntax.ts'
|
||||||
import { emptyKeys, mergeAdjacentText } from '../adf/document.ts'
|
import { emptyKeys, mergeAdjacentText } from '../adf/document.ts'
|
||||||
import { inlineNodes } from '../adf/inline-nodes.ts'
|
import { inlineNodes } from '../adf/inline-nodes.ts'
|
||||||
import { joinsNormally } from '../markdown/plain/editor-normal.ts'
|
import { joinsWhenEditorNormal } from '../markdown/adjacent-text.ts'
|
||||||
import { markAttributes } from '../adf/mark-attributes.ts'
|
import { markAttributes } from '../adf/mark-attributes.ts'
|
||||||
|
|
||||||
type Positions = { block: AdfNode; inline: AdfNode }
|
type Positions = { block: AdfNode; inline: AdfNode }
|
||||||
@@ -91,7 +91,7 @@ function withoutEmptyKeys<T extends AdfMark | AdfNode>(held: T): T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function occasionallyApart(arbitrary: Arbitrary<AdfNode[]>): Arbitrary<AdfNode[]> {
|
function occasionallyApart(arbitrary: Arbitrary<AdfNode[]>): Arbitrary<AdfNode[]> {
|
||||||
return fc.tuple(arbitrary, fc.nat({ max: 5 })).map(([nodes, roll]) => (roll === 0 ? nodes : mergeAdjacentText(nodes, joinsNormally)))
|
return fc.tuple(arbitrary, fc.nat({ max: 5 })).map(([nodes, roll]) => (roll === 0 ? nodes : mergeAdjacentText(nodes, joinsWhenEditorNormal)))
|
||||||
}
|
}
|
||||||
|
|
||||||
function pipeTable({ body, header }: { body: AdfNode[][]; header: AdfNode[] }): AdfNode {
|
function pipeTable({ body, header }: { body: AdfNode[][]; header: AdfNode[] }): AdfNode {
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import type { AdfAttributes, AdfMark, AdfNode } from '../adf/document.ts'
|
||||||
|
import type { JsonValue } from '../json-value.ts'
|
||||||
|
import { identicalMark, identicalMarks, isPlainText, nodeAttrs, nodeMarks } from '../adf/document.ts'
|
||||||
|
import { spellInlineLeafDirective } from './directive-syntax.ts'
|
||||||
|
|
||||||
|
type JsonContainer = JsonValue[] | { [key: string]: JsonValue }
|
||||||
|
|
||||||
|
export const textBreakName = 'textBreak'
|
||||||
|
|
||||||
|
export const textBreakSpelling = spellInlineLeafDirective(textBreakName, '')
|
||||||
|
|
||||||
|
// The lossless reader's rule: CommonMark reads the pair back as one text run (spec/flavour.md, Inline nodes).
|
||||||
|
export function joinsWhenRead(previous: AdfNode, node: AdfNode): boolean {
|
||||||
|
return isPlainText(previous) && isPlainText(node) && identicalMarks(nodeMarks(previous), nodeMarks(node))
|
||||||
|
}
|
||||||
|
|
||||||
|
// The editor's rule, parting from the reader's only on shapes editor-normal ADF erases: an empty attrs, content or marks, and -0 in a mark.
|
||||||
|
export function joinsWhenEditorNormal(previous: AdfNode, node: AdfNode): boolean {
|
||||||
|
if (!joinsAsEditorText(previous) || !joinsAsEditorText(node)) return false
|
||||||
|
return identicalMarks(nodeMarks(previous).map(normalMark), nodeMarks(node).map(normalMark))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sameMarkWhenEditorNormal(left: AdfMark, right: AdfMark): boolean {
|
||||||
|
return identicalMark(normalMark(left), normalMark(right))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalMark(mark: AdfMark): AdfMark {
|
||||||
|
const attrs = normalAttributes(nodeAttrs(mark))
|
||||||
|
return attrs === undefined ? { type: mark.type } : { attrs, type: mark.type }
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalAttributes(attrs: AdfAttributes): AdfAttributes | undefined {
|
||||||
|
if (Object.keys(attrs).length === 0) return undefined
|
||||||
|
const normal = { ...attrs }
|
||||||
|
const pending: JsonContainer[] = [normal]
|
||||||
|
for (let held = pending.pop(); held !== undefined; held = pending.pop()) {
|
||||||
|
if (Array.isArray(held)) for (const [index, value] of held.entries()) held[index] = normalValue(value, pending)
|
||||||
|
else for (const [key, value] of Object.entries(held)) held[key] = normalValue(value, pending)
|
||||||
|
}
|
||||||
|
return normal
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalValue(value: JsonValue, pending: JsonContainer[]): JsonValue {
|
||||||
|
if (Object.is(value, -0)) return 0
|
||||||
|
if (value === null || typeof value !== 'object') return value
|
||||||
|
const copy = Array.isArray(value) ? [...value] : { ...value }
|
||||||
|
pending.push(copy)
|
||||||
|
return copy
|
||||||
|
}
|
||||||
|
|
||||||
|
function joinsAsEditorText(node: AdfNode): boolean {
|
||||||
|
return node.type === 'text' && Object.keys(nodeAttrs(node)).length === 0
|
||||||
|
}
|
||||||
@@ -11,9 +11,9 @@ import { escapeUnbalanced, spellDestination } from '../commonmark/link-syntax.ts
|
|||||||
import { failure, faulted, success, type ConvertErrorPath, type Result } from '../../result.ts'
|
import { failure, faulted, success, type ConvertErrorPath, type Result } from '../../result.ts'
|
||||||
import { highlightDelimiter } from '../plain/conventions.ts'
|
import { highlightDelimiter } from '../plain/conventions.ts'
|
||||||
import { inlineNodeModel } from '../../adf/inline-nodes.ts'
|
import { inlineNodeModel } from '../../adf/inline-nodes.ts'
|
||||||
|
import { joinsWhenRead, textBreakSpelling } from '../adjacent-text.ts'
|
||||||
import { largestNesting } from '../../nesting.ts'
|
import { largestNesting } from '../../nesting.ts'
|
||||||
import { longestBacktickRun } from '../commonmark/backtick-runs.ts'
|
import { longestBacktickRun } from '../commonmark/backtick-runs.ts'
|
||||||
import { readsAsOne, textBreakSpelling } from '../text-break.ts'
|
|
||||||
import { slotLineEndingFault, spellInlineDirectiveOpener, spellInlineLeafDirective } from '../directive-syntax.ts'
|
import { slotLineEndingFault, spellInlineDirectiveOpener, spellInlineLeafDirective } from '../directive-syntax.ts'
|
||||||
import { spellInlineNodeAttributes } from './inline-directive-spelling.ts'
|
import { spellInlineNodeAttributes } from './inline-directive-spelling.ts'
|
||||||
import { spellTextDirective } from '../text-directive.ts'
|
import { spellTextDirective } from '../text-directive.ts'
|
||||||
@@ -186,7 +186,7 @@ function emitRun(nodes: readonly AdfNode[], depth: number, firstIndex: number, c
|
|||||||
const runs = inlineRuns(nodes, depth, firstIndex, context.carried)
|
const runs = inlineRuns(nodes, depth, firstIndex, context.carried)
|
||||||
const segments: InlineSegment[] = []
|
const segments: InlineSegment[] = []
|
||||||
for (const [offset, run] of runs.entries()) {
|
for (const [offset, run] of runs.entries()) {
|
||||||
if (partsText(runs[offset - 1], run, context.carried)) segments.push(syntax(textBreakSpelling))
|
if (takesTextBreak(runs[offset - 1], run, context.carried)) segments.push(syntax(textBreakSpelling))
|
||||||
const runContext = { ...context, atBlockEnd: context.atBlockEnd && offset === runs.length - 1 }
|
const runContext = { ...context, atBlockEnd: context.atBlockEnd && offset === runs.length - 1 }
|
||||||
const emitted = run.kind === 'plain' ? emitLeaf(run.node, runContext, run.index) : emitMarkedRun(run.nodes, run.mark, depth, run.index, runContext)
|
const emitted = run.kind === 'plain' ? emitLeaf(run.node, runContext, run.index) : emitMarkedRun(run.nodes, run.mark, depth, run.index, runContext)
|
||||||
if (!emitted.ok) return emitted
|
if (!emitted.ok) return emitted
|
||||||
@@ -213,10 +213,10 @@ function inlineRuns(nodes: readonly AdfNode[], depth: number, firstIndex: number
|
|||||||
return runs
|
return runs
|
||||||
}
|
}
|
||||||
|
|
||||||
function partsText(previous: InlineRun | undefined, run: InlineRun, carried: ReadonlySet<number>): boolean {
|
function takesTextBreak(previous: InlineRun | undefined, run: InlineRun, carried: ReadonlySet<number>): boolean {
|
||||||
if (previous?.kind !== 'plain' || run.kind !== 'plain') return false
|
if (previous?.kind !== 'plain' || run.kind !== 'plain') return false
|
||||||
if (carries(previous.node, carried, previous.index) || carries(run.node, carried, run.index)) return false
|
if (carries(previous.node, carried, previous.index) || carries(run.node, carried, run.index)) return false
|
||||||
return readsAsOne(previous.node, run.node)
|
return joinsWhenRead(previous.node, run.node)
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodePath(context: InlineContext, index: number): ConvertErrorPath {
|
function nodePath(context: InlineContext, index: number): ConvertErrorPath {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { inlineNodeModel } from '../../adf/inline-nodes.ts'
|
|||||||
import { readEmptyKeys, spellsEmpty } from '../empty-keys.ts'
|
import { readEmptyKeys, spellsEmpty } from '../empty-keys.ts'
|
||||||
import { readVocabulary } from './directive-attributes.ts'
|
import { readVocabulary } from './directive-attributes.ts'
|
||||||
import { slotLineEndingFault } from '../directive-syntax.ts'
|
import { slotLineEndingFault } from '../directive-syntax.ts'
|
||||||
import { textBreakName } from '../text-break.ts'
|
import { textBreakName } from '../adjacent-text.ts'
|
||||||
import { textDirectiveName } from '../text-directive.ts'
|
import { textDirectiveName } from '../text-directive.ts'
|
||||||
|
|
||||||
export type BlockDirectiveNode = { contentModel: BlockNodeModel['contentModel']; node: AdfNode }
|
export type BlockDirectiveNode = { contentModel: BlockNodeModel['contentModel']; node: AdfNode }
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { failure, faulted, success, type ConvertErrorPath, type Result } from '.
|
|||||||
import { highlightDelimiter, highlightFlanking } from '../plain/conventions.ts'
|
import { highlightDelimiter, highlightFlanking } from '../plain/conventions.ts'
|
||||||
import { identicalMarks, mergeAdjacentText, nodeAttrs, nodeMarks } from '../../adf/document.ts'
|
import { identicalMarks, mergeAdjacentText, nodeAttrs, nodeMarks } from '../../adf/document.ts'
|
||||||
import { inlineNodeModel } from '../../adf/inline-nodes.ts'
|
import { inlineNodeModel } from '../../adf/inline-nodes.ts'
|
||||||
|
import { joinsWhenRead, textBreakName, textBreakSpelling } from '../adjacent-text.ts'
|
||||||
import { noSpans, readInlineDirective } from '../directive-syntax.ts'
|
import { noSpans, readInlineDirective } from '../directive-syntax.ts'
|
||||||
import { normalizeLabel, readInlineTarget, readLabel } from '../commonmark/link-syntax.ts'
|
import { normalizeLabel, readInlineTarget, readLabel } from '../commonmark/link-syntax.ts'
|
||||||
import { openingLinkTakesDirective } from '../emit/inline-line.ts'
|
import { openingLinkTakesDirective } from '../emit/inline-line.ts'
|
||||||
@@ -19,7 +20,6 @@ import { readCarriedInline } from '../opaque-carry.ts'
|
|||||||
import { readDirectiveMark } from './directive-marks.ts'
|
import { readDirectiveMark } from './directive-marks.ts'
|
||||||
import { readInlineDirectiveNode } from './directive-nodes.ts'
|
import { readInlineDirectiveNode } from './directive-nodes.ts'
|
||||||
import { readTextDirective } from '../text-directive.ts'
|
import { readTextDirective } from '../text-directive.ts'
|
||||||
import { readsAsOne, textBreakName, textBreakSpelling } from '../text-break.ts'
|
|
||||||
|
|
||||||
export type InlineContent = { carry?: undefined; image: AdfNode; nodes?: undefined } | { carry: boolean; image?: undefined; nodes: AdfNode[] }
|
export type InlineContent = { carry?: undefined; image: AdfNode; nodes?: undefined } | { carry: boolean; image?: undefined; nodes: AdfNode[] }
|
||||||
|
|
||||||
@@ -312,7 +312,7 @@ function partText(items: readonly Inline[], scan: Scan): Result<AdfNode[]> {
|
|||||||
}
|
}
|
||||||
const previous = items[index - 1]
|
const previous = items[index - 1]
|
||||||
const next = items[index + 1]
|
const next = items[index + 1]
|
||||||
if (previous === undefined || next === undefined || !isNode(previous) || !isNode(next) || !readsAsOne(previous, next)) {
|
if (previous === undefined || next === undefined || !isNode(previous) || !isNode(next) || !joinsWhenRead(previous, next)) {
|
||||||
return failure('unsupported-node-shape', `delete ${textBreakSpelling} here: it stands only between two runs of text with the same formatting, which would otherwise read as one`, scan.path)
|
return failure('unsupported-node-shape', `delete ${textBreakSpelling} here: it stands only between two runs of text with the same formatting, which would otherwise read as one`, scan.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -508,11 +508,11 @@ function resolveNodes(pieces: readonly Piece[], scan: Scan, highlights: boolean)
|
|||||||
writeUnpaired(nodes, runs, pairings)
|
writeUnpaired(nodes, runs, pairings)
|
||||||
if (!markPairings(pieces, nodes, pairings)) return failure('unsupported-node-shape', carriedInMark, scan.path)
|
if (!markPairings(pieces, nodes, pairings)) return failure('unsupported-node-shape', carriedInMark, scan.path)
|
||||||
markHighlights(pieces, nodes, highlights ? pairedHighlights(pieces, nodes) : [])
|
markHighlights(pieces, nodes, highlights ? pairedHighlights(pieces, nodes) : [])
|
||||||
return success(mergeText(nodes.flat()))
|
return success(mergeReadText(nodes.flat()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// A text break and a carried node are walls: the text on either side joins only its own side.
|
// A text break and a carried node are walls: the text on either side joins only its own side.
|
||||||
function mergeText(items: readonly Inline[]): Inline[] {
|
function mergeReadText(items: readonly Inline[]): Inline[] {
|
||||||
const merged: Inline[] = []
|
const merged: Inline[] = []
|
||||||
let run: AdfNode[] = []
|
let run: AdfNode[] = []
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
@@ -520,11 +520,11 @@ function mergeText(items: readonly Inline[]): Inline[] {
|
|||||||
run.push(item)
|
run.push(item)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for (const node of mergeAdjacentText(run, readsAsOne)) merged.push(node)
|
for (const node of mergeAdjacentText(run, joinsWhenRead)) merged.push(node)
|
||||||
merged.push(item)
|
merged.push(item)
|
||||||
run = []
|
run = []
|
||||||
}
|
}
|
||||||
for (const node of mergeAdjacentText(run, readsAsOne)) merged.push(node)
|
for (const node of mergeAdjacentText(run, joinsWhenRead)) merged.push(node)
|
||||||
return merged
|
return merged
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,14 @@
|
|||||||
import type { AdfAttributes, AdfDocument, AdfMark, AdfNode } from '../../adf/document.ts'
|
import type { AdfDocument, AdfNode } from '../../adf/document.ts'
|
||||||
import type { JsonValue } from '../../json-value.ts'
|
import { joinsWhenEditorNormal, normalAttributes, normalMark } from '../adjacent-text.ts'
|
||||||
import { identicalMark, identicalMarks, mergeAdjacentText, nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
import { mergeAdjacentText, nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
||||||
|
|
||||||
type JsonContainer = JsonValue[] | { [key: string]: JsonValue }
|
|
||||||
|
|
||||||
type NodeHolder = { content?: AdfNode[] }
|
type NodeHolder = { content?: AdfNode[] }
|
||||||
|
|
||||||
export function sameMark(left: AdfMark, right: AdfMark): boolean {
|
|
||||||
return identicalMark(normalMark(left), normalMark(right))
|
|
||||||
}
|
|
||||||
|
|
||||||
export function joinsNormally(previous: AdfNode, node: AdfNode): boolean {
|
|
||||||
if (!mergesText(previous) || !mergesText(node)) return false
|
|
||||||
return identicalMarks(nodeMarks(previous).map(normalMark), nodeMarks(node).map(normalMark))
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toEditorNormal(document: AdfDocument): AdfDocument {
|
export function toEditorNormal(document: AdfDocument): AdfDocument {
|
||||||
const normal: AdfDocument = { type: document.type, version: Object.is(document.version, -0) ? 0 : document.version }
|
const normal: AdfDocument = { type: document.type, version: Object.is(document.version, -0) ? 0 : document.version }
|
||||||
const pending: { holder: NodeHolder; source: NodeHolder }[] = [{ holder: normal, source: document }]
|
const pending: { holder: NodeHolder; source: NodeHolder }[] = [{ holder: normal, source: document }]
|
||||||
for (let entry = pending.pop(); entry !== undefined; entry = pending.pop()) {
|
for (let entry = pending.pop(); entry !== undefined; entry = pending.pop()) {
|
||||||
const content = mergeAdjacentText(nodeContent(entry.source), joinsNormally)
|
const content = mergeAdjacentText(nodeContent(entry.source), joinsWhenEditorNormal)
|
||||||
if (content.length === 0) continue
|
if (content.length === 0) continue
|
||||||
entry.holder.content = content.map((source) => {
|
entry.holder.content = content.map((source) => {
|
||||||
const holder = normalNode(source)
|
const holder = normalNode(source)
|
||||||
@@ -39,31 +28,3 @@ function normalNode(node: AdfNode): AdfNode {
|
|||||||
if (node.text !== undefined) normal.text = node.text
|
if (node.text !== undefined) normal.text = node.text
|
||||||
return normal
|
return normal
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalMark(mark: AdfMark): AdfMark {
|
|
||||||
const attrs = normalAttributes(nodeAttrs(mark))
|
|
||||||
return attrs === undefined ? { type: mark.type } : { attrs, type: mark.type }
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalAttributes(attrs: AdfAttributes): AdfAttributes | undefined {
|
|
||||||
if (Object.keys(attrs).length === 0) return undefined
|
|
||||||
const normal = { ...attrs }
|
|
||||||
const pending: JsonContainer[] = [normal]
|
|
||||||
for (let held = pending.pop(); held !== undefined; held = pending.pop()) {
|
|
||||||
if (Array.isArray(held)) for (const [index, value] of held.entries()) held[index] = normalValue(value, pending)
|
|
||||||
else for (const [key, value] of Object.entries(held)) held[key] = normalValue(value, pending)
|
|
||||||
}
|
|
||||||
return normal
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalValue(value: JsonValue, pending: JsonContainer[]): JsonValue {
|
|
||||||
if (Object.is(value, -0)) return 0
|
|
||||||
if (value === null || typeof value !== 'object') return value
|
|
||||||
const copy = Array.isArray(value) ? [...value] : { ...value }
|
|
||||||
pending.push(copy)
|
|
||||||
return copy
|
|
||||||
}
|
|
||||||
|
|
||||||
function mergesText(node: AdfNode): boolean {
|
|
||||||
return node.type === 'text' && Object.keys(nodeAttrs(node)).length === 0
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { LineContainer } from '../line-container.ts'
|
|||||||
import type { MarkRun } from '../emit/line-escaping.ts'
|
import type { MarkRun } from '../emit/line-escaping.ts'
|
||||||
import { blockNodeModel } from '../../adf/block-nodes.ts'
|
import { blockNodeModel } from '../../adf/block-nodes.ts'
|
||||||
import { failure, success, type ConvertErrorPath, type Result } from '../../result.ts'
|
import { failure, success, type ConvertErrorPath, type Result } from '../../result.ts'
|
||||||
import { joinsNormally, sameMark } from './editor-normal.ts'
|
import { joinsWhenEditorNormal, sameMarkWhenEditorNormal } from '../adjacent-text.ts'
|
||||||
import { largestNesting } from '../../nesting.ts'
|
import { largestNesting } from '../../nesting.ts'
|
||||||
import { mergeAdjacentText, nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
import { mergeAdjacentText, nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
||||||
import { plainLineFallback, type PlainLineFallback } from '../emit/inline-line.ts'
|
import { plainLineFallback, type PlainLineFallback } from '../emit/inline-line.ts'
|
||||||
@@ -175,11 +175,11 @@ function highlighted(leaves: readonly AdfNode[]): AdfNode[] {
|
|||||||
const marks = nodeMarks(leaf)
|
const marks = nodeMarks(leaf)
|
||||||
if (marks[0]?.type === highlight) {
|
if (marks[0]?.type === highlight) {
|
||||||
const held = marks.slice(1)
|
const held = marks.slice(1)
|
||||||
shared = run.length === 0 ? held : shared.filter((mark) => held.some((other) => sameMark(other, mark)))
|
shared = run.length === 0 ? held : shared.filter((mark) => held.some((other) => sameMarkWhenEditorNormal(other, mark)))
|
||||||
run.push(leaf)
|
run.push(leaf)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for (const held of run) spelled.push(withMarks(held, [...shared, highlightMark, ...nodeMarks(held).slice(1).filter((mark) => !shared.some((other) => sameMark(other, mark)))]))
|
for (const held of run) spelled.push(withMarks(held, [...shared, highlightMark, ...nodeMarks(held).slice(1).filter((mark) => !shared.some((other) => sameMarkWhenEditorNormal(other, mark)))]))
|
||||||
run = []
|
run = []
|
||||||
spelled.push(leaf)
|
spelled.push(leaf)
|
||||||
}
|
}
|
||||||
@@ -193,7 +193,7 @@ function withMarks(leaf: AdfNode, marks: readonly AdfMark[]): AdfNode {
|
|||||||
|
|
||||||
function trimmedEdges(leaves: readonly AdfNode[]): AdfNode[] {
|
function trimmedEdges(leaves: readonly AdfNode[]): AdfNode[] {
|
||||||
for (let current = leaves; ; ) {
|
for (let current = leaves; ; ) {
|
||||||
const merged = withoutEdgeBreaks(mergeAdjacentText(current, joinsNormally))
|
const merged = withoutEdgeBreaks(mergeAdjacentText(current, joinsWhenEditorNormal))
|
||||||
let changed = false
|
let changed = false
|
||||||
const trimmed: AdfNode[] = []
|
const trimmed: AdfNode[] = []
|
||||||
for (const [index, leaf] of merged.entries()) {
|
for (const [index, leaf] of merged.entries()) {
|
||||||
@@ -251,7 +251,7 @@ function edgeDepth(marks: readonly AdfMark[], neighbour: AdfNode | undefined, wh
|
|||||||
function sameMarkAt(marks: readonly AdfMark[], others: readonly AdfMark[], index: number): boolean {
|
function sameMarkAt(marks: readonly AdfMark[], others: readonly AdfMark[], index: number): boolean {
|
||||||
const mark = marks[index]
|
const mark = marks[index]
|
||||||
const other = others[index]
|
const other = others[index]
|
||||||
return mark !== undefined && other !== undefined && sameMark(mark, other)
|
return mark !== undefined && other !== undefined && sameMarkWhenEditorNormal(mark, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
function spellableLine(leaves: AdfNode[], container: LineContainer, path: ConvertErrorPath): Result<AdfNode[]> {
|
function spellableLine(leaves: AdfNode[], container: LineContainer, path: ConvertErrorPath): Result<AdfNode[]> {
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
import type { AdfNode } from '../adf/document.ts'
|
|
||||||
import { identicalMarks, isPlainText, nodeMarks } from '../adf/document.ts'
|
|
||||||
import { spellInlineLeafDirective } from './directive-syntax.ts'
|
|
||||||
|
|
||||||
export const textBreakName = 'textBreak'
|
|
||||||
|
|
||||||
export const textBreakSpelling = spellInlineLeafDirective(textBreakName, '')
|
|
||||||
|
|
||||||
// Whether CommonMark reads the pair back as one text node, where neither rides the carry (spec/flavour.md, Inline nodes).
|
|
||||||
export function readsAsOne(previous: AdfNode, node: AdfNode): boolean {
|
|
||||||
return isPlainText(previous) && isPlainText(node) && identicalMarks(nodeMarks(previous), nodeMarks(node))
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user