mirror of
https://github.com/larvit/adf-codec.git
synced 2026-11-12 11:48:29 +01:00
Answer architecture round 2: rename isBareText to isSpellableText, say which link holdsLink counts, the README names the type passed
This commit is contained in:
+3
-3
@@ -66,12 +66,12 @@ export function emptyKeys(held: { attrs?: AdfAttributes; content?: AdfNode[]; ma
|
||||
}
|
||||
|
||||
// No attrs, content or empty marks; a format may spell this node as text, and anything more rides a carry.
|
||||
export function isBareText(node: AdfNode): boolean {
|
||||
export function isSpellableText(node: AdfNode): boolean {
|
||||
return node.type === 'text' && node.attrs === undefined && node.content === undefined && node.marks?.length !== 0
|
||||
}
|
||||
|
||||
export function isUnmarkedBareText(node: AdfNode): boolean {
|
||||
return isBareText(node) && node.marks === undefined
|
||||
export function isUnmarkedSpellableText(node: AdfNode): boolean {
|
||||
return isSpellableText(node) && node.marks === undefined
|
||||
}
|
||||
|
||||
export function identicalMark(left: AdfMark, right: AdfMark): boolean {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { AdfNode } from '../adf/document.ts'
|
||||
import { identicalMarks, isBareText, nodeMarks } from '../adf/document.ts'
|
||||
import { identicalMarks, isSpellableText, nodeMarks } from '../adf/document.ts'
|
||||
import { spellInlineLeafDirective } from './directive-syntax.ts'
|
||||
|
||||
export const textBreakName = 'textBreak'
|
||||
@@ -8,5 +8,5 @@ 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 isBareText(previous) && isBareText(node) && identicalMarks(nodeMarks(previous), nodeMarks(node))
|
||||
return isSpellableText(previous) && isSpellableText(node) && identicalMarks(nodeMarks(previous), nodeMarks(node))
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { AdfDocument, AdfNode } from '../../adf/document.ts'
|
||||
import type { BlockNodeModel } from '../../adf/block-nodes.ts'
|
||||
import type { Flavour } from '../plain/conventions.ts'
|
||||
import { adfDocumentFault, holdsOnlyAttributes, isUnmarkedBareText, nodeAttrs, nodeContent } from '../../adf/document.ts'
|
||||
import { adfDocumentFault, holdsOnlyAttributes, isUnmarkedSpellableText, nodeAttrs, nodeContent } from '../../adf/document.ts'
|
||||
import { alertMarker, foldedAlertMarker, leadingMarker, readAlertMarker, readTaskMarker, taskMarker } from '../plain/conventions.ts'
|
||||
import { blockDirectiveForm, documentSpelling, listBreakSpelling } from '../block-directive.ts'
|
||||
import { blockNodeModel, blockNodes } from '../../adf/block-nodes.ts'
|
||||
@@ -277,7 +277,7 @@ function fencedTexts(node: AdfNode): string[] | undefined {
|
||||
if (node.content === undefined) return ['']
|
||||
const texts: string[] = []
|
||||
for (const child of node.content) {
|
||||
if (!isUnmarkedBareText(child) || typeof child.text !== 'string' || child.text === '' || /\r/.test(child.text) || holdsNullCharacter(child.text)) return undefined
|
||||
if (!isUnmarkedSpellableText(child) || typeof child.text !== 'string' || child.text === '' || /\r/.test(child.text) || holdsNullCharacter(child.text)) return undefined
|
||||
texts.push(child.text)
|
||||
}
|
||||
return texts
|
||||
|
||||
@@ -9,7 +9,7 @@ import { escapeUnbalanced, spellDestination } from '../commonmark/link-syntax.ts
|
||||
import { failure, success, type ConvertErrorPath, type Result } from '../../result.ts'
|
||||
import { highlightDelimiter } from '../plain/conventions.ts'
|
||||
import { holdsNullCharacter, trimTrailingSpace } from '../commonmark/grammar.ts'
|
||||
import { identicalMark, isBareText, nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
||||
import { identicalMark, isSpellableText, nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
||||
import { inlineNodeModel } from '../../adf/inline-nodes.ts'
|
||||
import { joinsWhenRead, textBreakSpelling } from '../adjacent-text.ts'
|
||||
import { largestNesting } from '../../nesting.ts'
|
||||
@@ -220,7 +220,7 @@ function nodePath(context: InlineContext, index: number): ConvertErrorPath {
|
||||
// Decides the text-node and slot-fault carries up front, so a line holding many of them is emitted once.
|
||||
function carries(node: AdfNode, carried: ReadonlySet<number>, index: number): boolean {
|
||||
if (carried.has(index)) return true
|
||||
if (node.type === 'text') return !isBareText(node) || typeof node.text !== 'string' || node.text === ''
|
||||
if (node.type === 'text') return !isSpellableText(node) || typeof node.text !== 'string' || node.text === ''
|
||||
const model = inlineNodeModel(node.type)
|
||||
if (model === undefined) return true
|
||||
const slot = model.textAttribute === undefined ? undefined : nodeAttrs(node)[model.textAttribute]
|
||||
@@ -265,7 +265,7 @@ function emitInlineDirective(node: AdfNode, model: InlineNodeModel, index: numbe
|
||||
|
||||
// CommonMark reads a raw carriage return as a line ending and a null character as U+FFFD, so neither is written raw.
|
||||
function emitText(node: AdfNode, context: InlineContext, index: number): Emission {
|
||||
if (!isBareText(node) || typeof node.text !== 'string' || node.text === '') return { carry: { first: index, last: index } }
|
||||
if (!isSpellableText(node) || typeof node.text !== 'string' || node.text === '') return { carry: { first: index, last: index } }
|
||||
const escaping: InlineEscaping = context.bracketed ? 'bracketed' : 'backslash'
|
||||
const parts = node.text.split(/(\n+|\0+|\r)/).filter((part) => part !== '')
|
||||
return { segments: parts.map((part) => (part === '\r' ? syntax(' ') : /^[\n\0]/.test(part) ? textDirectiveSegment(part) : { escaping, text: part })) }
|
||||
@@ -316,7 +316,7 @@ function emitCodeSpan(nodes: readonly AdfNode[], depth: number, range: NodeRange
|
||||
const spans: string[] = []
|
||||
for (const node of nodes) {
|
||||
const { text } = node
|
||||
if (!isBareText(node) || nodeMarks(node).length !== depth + 1 || typeof text !== 'string' || text === '' || /[\n\r]/.test(text) || holdsNullCharacter(text)) return { carry: range }
|
||||
if (!isSpellableText(node) || nodeMarks(node).length !== depth + 1 || typeof text !== 'string' || text === '' || /[\n\r]/.test(text) || holdsNullCharacter(text)) return { carry: range }
|
||||
const fence = '`'.repeat(longestBacktickRun(text) + 1)
|
||||
spans.push(`${fence}${needsPadding(text) ? ` ${text} ` : text}${fence}`)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { BlockNodeModel } from '../../adf/block-nodes.ts'
|
||||
import type { ConvertFault } from '../../result.ts'
|
||||
import type { DirectiveAttributes, DirectiveValue } from '../directive-syntax.ts'
|
||||
import type { Elsewhere } from './directive-attributes.ts'
|
||||
import { attributeNestingMessage, isUnmarkedBareText } from '../../adf/document.ts'
|
||||
import { attributeNestingMessage, isUnmarkedSpellableText } from '../../adf/document.ts'
|
||||
import { attributeValue, directivePrefix, spellAttributeValue, unknownDirectiveFault } from '../directive-syntax.ts'
|
||||
import { blockArgument, blockDirectiveForm, marksAttribute, readMarkValues } from '../block-directive.ts'
|
||||
import { blockNodeModel } from '../../adf/block-nodes.ts'
|
||||
@@ -92,7 +92,7 @@ function blockSpellingFault(name: string): ConvertFault | undefined {
|
||||
function slotText(content: readonly AdfNode[]): string | undefined {
|
||||
if (content.length === 0) return ''
|
||||
const only = content.length === 1 ? content[0] : undefined
|
||||
if (only === undefined || !isUnmarkedBareText(only) || typeof only.text !== 'string') return undefined
|
||||
if (only === undefined || !isUnmarkedSpellableText(only) || typeof only.text !== 'string') return undefined
|
||||
return only.text
|
||||
}
|
||||
|
||||
|
||||
@@ -327,7 +327,6 @@ function isTextBreak(item: Inline): item is TextBreak {
|
||||
return 'kind' in item && item.kind === 'textBreak'
|
||||
}
|
||||
|
||||
// The nodes the items hold, with text breaks dropped.
|
||||
function adfNodes(items: readonly Inline[]): AdfNode[] {
|
||||
const nodes: AdfNode[] = []
|
||||
for (const item of items) {
|
||||
@@ -345,7 +344,7 @@ function holdsImage(pieces: readonly Piece[]): boolean {
|
||||
return pieces.some((piece) => piece.kind === 'image')
|
||||
}
|
||||
|
||||
// A node whose marks are its own rides its own piece, its marks restoring with it rather than riding a spelling, so the guard below answers for it.
|
||||
// An `ownMarks` piece restores its link with its node, so only a link a `nodes` piece spells counts.
|
||||
function holdsLink(pieces: readonly Piece[]): boolean {
|
||||
return pieces.some((piece) => piece.kind === 'nodes' && marksLink(piece.nodes))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user