4.1: editor-normal and the node accessors
This commit is contained in:
@@ -6,6 +6,7 @@ import type { JsonValue } from '../../json-value.ts'
|
||||
import type { Result } from '../../result.ts'
|
||||
import { adfToMarkdown, markdownToAdf } from '../../index.ts'
|
||||
import { largestNesting } from '../../nesting.ts'
|
||||
import { toEditorNormal } from '../../adf/editor-normal.ts'
|
||||
|
||||
function document(...content: AdfNode[]): AdfDocument {
|
||||
return { content, type: 'doc', version: 1 }
|
||||
@@ -353,7 +354,9 @@ test('refuses marks and attributes nested deeper than the emitter carries', () =
|
||||
const roundTrips = (node: AdfNode): void => {
|
||||
const spelled = adfToMarkdown(document(node))
|
||||
assert.ok(spelled.ok, spelled.ok ? '' : spelled.error.message)
|
||||
assert.deepEqual(markdownToAdf(spelled.value), { ok: true, value: document(node) })
|
||||
const read = markdownToAdf(spelled.value)
|
||||
assert.ok(read.ok, read.ok ? '' : read.error.message)
|
||||
assert.deepEqual(toEditorNormal(read.value), toEditorNormal(document(node)))
|
||||
}
|
||||
|
||||
assert.equal(markdown(adfToMarkdown(document(paragraph({ marks: [{ attrs, type: 'em' }], text: 'x', type: 'text' })))), deeper('depth', 'em', largestNesting - 3))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AdfDocument, AdfNode } from '../../adf/document.ts'
|
||||
import type { BlockDirective } from '../../adf/block-directives.ts'
|
||||
import { adfDocumentFault, carriesOnly } from '../../adf/document.ts'
|
||||
import { adfDocumentFault, carriesOnly, nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
||||
import { blockDirective } from '../../adf/block-directives.ts'
|
||||
import { carriedBlock } from '../opaque-carry.ts'
|
||||
import { emitInlineLine } from './inline-line.ts'
|
||||
@@ -26,7 +26,7 @@ export function adfToMarkdown(document: AdfDocument): Result<string> {
|
||||
const fault = adfDocumentFault(document)
|
||||
if (fault !== undefined) return faulted(fault, [])
|
||||
if (document.version !== 1) return failure('unsupported-document-version', `no markdown spelling carries ADF version ${document.version}`, [])
|
||||
const blocks = emitBlocks(document.content ?? [], 'document', [], 0)
|
||||
const blocks = emitBlocks(nodeContent(document), 'document', [], 0)
|
||||
if (!blocks.ok) return blocks
|
||||
return success(blocks.value.text === '' ? '' : `${blocks.value.text}\n`)
|
||||
}
|
||||
@@ -63,8 +63,8 @@ function separationBetween(previous: PlacedBlock, next: PlacedBlock, container:
|
||||
}
|
||||
|
||||
function interruptsParagraph(node: AdfNode): boolean {
|
||||
const items = node.content ?? []
|
||||
const empty = (items[0]?.content ?? []).length === 0
|
||||
const items = nodeContent(node)
|
||||
const empty = items[0] === undefined || nodeContent(items[0]).length === 0
|
||||
if (node.type !== 'orderedList') return markerInterruptsParagraph(undefined, empty)
|
||||
return markerInterruptsParagraph(listStart(node, items.length) ?? 0, empty)
|
||||
}
|
||||
@@ -110,7 +110,7 @@ function commonMarkText(text: string): EmittedBlock {
|
||||
|
||||
function emitDirectiveBlock(node: AdfNode, directive: BlockDirective, path: ConvertErrorPath, depth: number): Result<EmittedBlock> {
|
||||
if (node.text !== undefined) return failure('unsupported-node-shape', `a ${node.type} carries no text: this one holds text`, path)
|
||||
const content = node.content ?? []
|
||||
const content = nodeContent(node)
|
||||
if (directive.contentModel === 'none' && content.length > 0) return failure('unsupported-node-shape', `a ${node.type} holds no content: this one holds some`, path)
|
||||
if (directive.contentModel === 'code') return emitCodeDirective(node, directive, path, depth)
|
||||
const header = spellDirectiveHeader(node, directive)
|
||||
@@ -134,7 +134,7 @@ function emitInlineBody(content: readonly AdfNode[], path: ConvertErrorPath): Re
|
||||
|
||||
function emitBlockquote(node: AdfNode, path: ConvertErrorPath, depth: number): Result<EmittedBlock> | undefined {
|
||||
if (!carriesOnly(node, [])) return undefined
|
||||
const inner = emitBlocks(node.content ?? [], 'document', path, depth + 1)
|
||||
const inner = emitBlocks(nodeContent(node), 'document', path, depth + 1)
|
||||
if (!inner.ok) return inner
|
||||
const text = inner.value.text
|
||||
.split('\n')
|
||||
@@ -145,7 +145,7 @@ function emitBlockquote(node: AdfNode, path: ConvertErrorPath, depth: number): R
|
||||
|
||||
function emitCodeBlock(node: AdfNode, path: ConvertErrorPath): Result<EmittedBlock> | undefined {
|
||||
if (!carriesOnly(node, ['language'])) return undefined
|
||||
const slot = languageSlot(node.attrs?.['language'])
|
||||
const slot = languageSlot(nodeAttrs(node)['language'])
|
||||
if (slot.kind === 'attribute') return undefined
|
||||
const text = codeBlockText(node, path)
|
||||
if (!text.ok) return text
|
||||
@@ -153,7 +153,7 @@ function emitCodeBlock(node: AdfNode, path: ConvertErrorPath): Result<EmittedBlo
|
||||
}
|
||||
|
||||
function emitCodeDirective(node: AdfNode, directive: BlockDirective, path: ConvertErrorPath, depth: number): Result<EmittedBlock> {
|
||||
const slot = languageSlot(node.attrs?.['language'])
|
||||
const slot = languageSlot(nodeAttrs(node)['language'])
|
||||
const header = spellDirectiveHeader(node, directive, slot.kind === 'attribute' ? [] : ['language'])
|
||||
if (header === undefined) return commonMarkLine(carriedBlock(node, path, depth))
|
||||
const text = codeBlockText(node, path)
|
||||
@@ -164,15 +164,15 @@ function emitCodeDirective(node: AdfNode, directive: BlockDirective, path: Conve
|
||||
|
||||
function codeBlockText(node: AdfNode, path: ConvertErrorPath): Result<string> {
|
||||
let text = ''
|
||||
for (const [index, child] of (node.content ?? []).entries()) {
|
||||
for (const [index, child] of nodeContent(node).entries()) {
|
||||
const childPath = [...path, 'content', index]
|
||||
if (
|
||||
child.type !== 'text' ||
|
||||
typeof child.text !== 'string' ||
|
||||
child.text === '' ||
|
||||
(child.content ?? []).length > 0 ||
|
||||
(child.marks ?? []).length > 0 ||
|
||||
Object.keys(child.attrs ?? {}).length > 0
|
||||
nodeContent(child).length > 0 ||
|
||||
nodeMarks(child).length > 0 ||
|
||||
Object.keys(nodeAttrs(child)).length > 0
|
||||
) {
|
||||
return failure('unsupported-node-shape', `a codeBlock holds plain text nodes only: this ${child.type} node is not one`, childPath)
|
||||
}
|
||||
@@ -185,10 +185,10 @@ function codeBlockText(node: AdfNode, path: ConvertErrorPath): Result<string> {
|
||||
|
||||
function emitHeading(node: AdfNode, path: ConvertErrorPath): Result<EmittedBlock> | undefined {
|
||||
if (!carriesOnly(node, ['level'])) return undefined
|
||||
const level = node.attrs?.['level']
|
||||
const level = nodeAttrs(node)['level']
|
||||
if (typeof level !== 'number' || !Number.isInteger(level) || level < 1 || level > 6) return undefined
|
||||
const hashes = '#'.repeat(level)
|
||||
const content = node.content ?? []
|
||||
const content = nodeContent(node)
|
||||
if (content.length === 0) return success(commonMarkText(hashes))
|
||||
const line = emitInlineLine(content, 'heading', path)
|
||||
if (!line.ok) return line
|
||||
@@ -198,7 +198,7 @@ function emitHeading(node: AdfNode, path: ConvertErrorPath): Result<EmittedBlock
|
||||
function emitList(node: AdfNode, path: ConvertErrorPath, depth: number): Result<EmittedBlock> | undefined {
|
||||
const ordered = node.type === 'orderedList'
|
||||
if (!carriesOnly(node, ordered ? ['order'] : [])) return undefined
|
||||
const items = node.content ?? []
|
||||
const items = nodeContent(node)
|
||||
const start = listStart(node, items.length)
|
||||
if (start === undefined || items.length === 0) return undefined
|
||||
if (items.some((item) => item.type !== 'listItem' || !carriesOnly(item, []))) return undefined
|
||||
@@ -216,13 +216,13 @@ function emitList(node: AdfNode, path: ConvertErrorPath, depth: number): Result<
|
||||
|
||||
function listStart(node: AdfNode, items: number): number | undefined {
|
||||
if (node.type !== 'orderedList') return 0
|
||||
const start = node.attrs?.['order']
|
||||
const start = nodeAttrs(node)['order']
|
||||
if (typeof start !== 'number' || !Number.isInteger(start) || start < 0 || start > largestListMarker) return undefined
|
||||
return start + items - 1 > largestListMarker ? undefined : start
|
||||
}
|
||||
|
||||
function emitListItem(item: AdfNode, marker: string, path: ConvertErrorPath, depth: number): Result<EmittedBody> | undefined {
|
||||
const inner = emitBlocks(item.content ?? [], 'list-item', path, depth + 1)
|
||||
const inner = emitBlocks(nodeContent(item), 'list-item', path, depth + 1)
|
||||
if (!inner.ok) return inner
|
||||
if (inner.value.text === '') return success({ fenceColons: 0, text: marker.trimEnd() })
|
||||
const indent = ' '.repeat(marker.length)
|
||||
@@ -232,7 +232,7 @@ function emitListItem(item: AdfNode, marker: string, path: ConvertErrorPath, dep
|
||||
}
|
||||
|
||||
function emitParagraph(node: AdfNode, path: ConvertErrorPath): Result<EmittedBlock> | undefined {
|
||||
const content = node.content ?? []
|
||||
const content = nodeContent(node)
|
||||
if (content.length === 0 || !carriesOnly(node, [])) return undefined
|
||||
const line = emitInlineLine(content, 'paragraph', path)
|
||||
if (!line.ok) return line
|
||||
@@ -240,6 +240,6 @@ function emitParagraph(node: AdfNode, path: ConvertErrorPath): Result<EmittedBlo
|
||||
}
|
||||
|
||||
function emitRule(node: AdfNode): Result<EmittedBlock> | undefined {
|
||||
if (!carriesOnly(node, []) || (node.content ?? []).length > 0) return undefined
|
||||
if (!carriesOnly(node, []) || nodeContent(node).length > 0) return undefined
|
||||
return success(commonMarkText('---'))
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { BlockDirective } from '../../adf/block-directives.ts'
|
||||
import { blockArgument } from '../block-directive-arguments.ts'
|
||||
import { isBareToken, spellAttributes, spellJsonAttribute, spellVocabulary } from '../directive-syntax.ts'
|
||||
import { markValues, marksAttribute } from '../block-directive-marks.ts'
|
||||
import { nodeAttrs, nodeMarks } from '../../adf/document.ts'
|
||||
import { vocabularyPairs } from '../../adf/attribute-vocabulary.ts'
|
||||
|
||||
export function spellDirectiveHeader(node: AdfNode, directive: BlockDirective, spelledByBody: readonly string[] = []): string | undefined {
|
||||
@@ -10,17 +11,17 @@ export function spellDirectiveHeader(node: AdfNode, directive: BlockDirective, s
|
||||
const argument = spellArgument(node, argumentAttribute)
|
||||
if (argument === undefined) return undefined
|
||||
const spelled = argumentAttribute === undefined ? spelledByBody : [argumentAttribute, ...spelledByBody]
|
||||
const pairs = vocabularyPairs(node.attrs ?? {}, directive.attributes, spelled)
|
||||
const pairs = vocabularyPairs(nodeAttrs(node), directive.attributes, spelled)
|
||||
if (pairs === undefined) return undefined
|
||||
const spelledPairs = spellVocabulary(pairs)
|
||||
const marks = node.marks ?? []
|
||||
const marks = nodeMarks(node)
|
||||
if (marks.length > 0) spelledPairs.push([marksAttribute, spellJsonAttribute(markValues(marks))])
|
||||
const attributes = spellAttributes(spelledPairs)
|
||||
return `${node.type}${argument}${attributes === '' ? '' : ` ${attributes}`}`
|
||||
}
|
||||
|
||||
function spellArgument(node: AdfNode, argumentAttribute: string | undefined): string | undefined {
|
||||
const value = argumentAttribute === undefined ? undefined : node.attrs?.[argumentAttribute]
|
||||
const value = argumentAttribute === undefined ? undefined : nodeAttrs(node)[argumentAttribute]
|
||||
if (value === undefined) return ''
|
||||
if (typeof value !== 'string' || !isBareToken(value)) return undefined
|
||||
return ` ${value}`
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { AdfNode } from '../../adf/document.ts'
|
||||
import { carriesOnly } from '../../adf/document.ts'
|
||||
import { carriesOnly, nodeAttrs, nodeContent } from '../../adf/document.ts'
|
||||
import type { ConvertErrorPath } from '../../result.ts'
|
||||
import { serializeCanonicalJson } from '../../canonical-json.ts'
|
||||
import { tryImageLine } from './inline-line.ts'
|
||||
@@ -14,11 +14,11 @@ export function tryImage(node: AdfNode, path: ConvertErrorPath): string | undefi
|
||||
}
|
||||
|
||||
function imageShape(node: AdfNode): { alt: string | undefined; url: string } | undefined {
|
||||
const content = node.content ?? []
|
||||
const content = nodeContent(node)
|
||||
const media = content[0]
|
||||
if (!carriesOnly(node, ['layout']) || serializeCanonicalJson(node.attrs ?? {}, 'compact') !== centeredMediaSingle) return undefined
|
||||
if (media === undefined || content.length !== 1 || media.type !== 'media' || !carriesOnly(media, imageAttributes) || (media.content ?? []).length > 0) return undefined
|
||||
const attrs = media.attrs ?? {}
|
||||
if (!carriesOnly(node, ['layout']) || serializeCanonicalJson(nodeAttrs(node), 'compact') !== centeredMediaSingle) return undefined
|
||||
if (media === undefined || content.length !== 1 || media.type !== 'media' || !carriesOnly(media, imageAttributes) || nodeContent(media).length > 0) return undefined
|
||||
const attrs = nodeAttrs(media)
|
||||
const alt = attrs['alt']
|
||||
const url = attrs['url']
|
||||
if (attrs['type'] !== 'external' || typeof url !== 'string') return undefined
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import type { AdfNode } from '../../adf/document.ts'
|
||||
import type { InlineDirective } from '../../adf/inline-directives.ts'
|
||||
import { nodeAttrs } from '../../adf/document.ts'
|
||||
import { spellAttributes, spellVocabulary } from '../directive-syntax.ts'
|
||||
import { vocabularyPairs } from '../../adf/attribute-vocabulary.ts'
|
||||
|
||||
export function spellInlineNodeAttributes(node: AdfNode, directive: InlineDirective): string | undefined {
|
||||
const pairs = vocabularyPairs(node.attrs ?? {}, directive.attributes, directive.textAttribute === undefined ? [] : [directive.textAttribute])
|
||||
const pairs = vocabularyPairs(nodeAttrs(node), directive.attributes, directive.textAttribute === undefined ? [] : [directive.textAttribute])
|
||||
return pairs === undefined ? undefined : spellAttributes(spellVocabulary(pairs))
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { inlineDirective } from '../../adf/inline-directives.ts'
|
||||
import { largestNesting } from '../../nesting.ts'
|
||||
import { longestBacktickRun } from '../backtick-runs.ts'
|
||||
import { markSpelling, spellMarkAttributes } from '../mark-spellings.ts'
|
||||
import { nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
||||
import { sameMark } from '../../adf/editor-normal.ts'
|
||||
import { slotLineEndingFault, spellLeafDirective } from '../directive-syntax.ts'
|
||||
import { spellDestination, spellTitle } from '../link-syntax.ts'
|
||||
@@ -127,7 +128,7 @@ function syntax(text: string): InlineSegment {
|
||||
}
|
||||
|
||||
function refuseContentAndText(node: AdfNode, path: ConvertErrorPath): Result<null> {
|
||||
const holdsContent = (node.content ?? []).length > 0
|
||||
const holdsContent = nodeContent(node).length > 0
|
||||
if (holdsContent || node.text !== undefined) {
|
||||
const held = holdsContent ? 'content' : 'text'
|
||||
return failure('unsupported-node-shape', `a ${node.type} node holds neither content nor text: this one holds ${held}`, path)
|
||||
@@ -156,7 +157,7 @@ function inlineRuns(nodes: readonly AdfNode[], depth: number, firstIndex: number
|
||||
for (const [offset, node] of nodes.entries()) {
|
||||
const index = firstIndex + offset
|
||||
// spec/flavour.md, Marks.
|
||||
const mark = carries(node, carried, index) ? undefined : (node.marks ?? [])[depth]
|
||||
const mark = carries(node, carried, index) ? undefined : nodeMarks(node)[depth]
|
||||
if (mark === undefined) {
|
||||
runs.push({ index, kind: 'plain', node })
|
||||
continue
|
||||
@@ -184,7 +185,7 @@ function emitLeaf(node: AdfNode, context: InlineContext, index: number): Result<
|
||||
if (!carried.ok) return carried
|
||||
return success({ segments: [syntax(carried.value)] })
|
||||
}
|
||||
const types = (node.marks ?? []).map((mark) => mark.type)
|
||||
const types = nodeMarks(node).map((mark) => mark.type)
|
||||
if (new Set(types).size !== types.length) return failure('unsupported-node-shape', `a ${node.type} node carries one mark type twice`, path)
|
||||
const directive = inlineDirective(node.type)
|
||||
if (directive === undefined) return emitText(node, context, index, path)
|
||||
@@ -206,7 +207,7 @@ function emitInlineDirective(node: AdfNode, directive: InlineDirective, index: n
|
||||
if (!empty.ok) return empty
|
||||
const attributes = spellInlineNodeAttributes(node, directive)
|
||||
if (attributes === undefined) return success({ carry: { first: index, last: index } })
|
||||
const slot = directive.textAttribute === undefined ? undefined : node.attrs?.[directive.textAttribute]
|
||||
const slot = directive.textAttribute === undefined ? undefined : nodeAttrs(node)[directive.textAttribute]
|
||||
if (slot === undefined) return success({ segments: [syntax(spellLeafDirective(node.type, attributes))] })
|
||||
if (typeof slot !== 'string') return success({ carry: { first: index, last: index } })
|
||||
const spans = slotLineEndingFault(node.type, slot)
|
||||
@@ -217,9 +218,9 @@ function emitInlineDirective(node: AdfNode, directive: InlineDirective, index: n
|
||||
}
|
||||
|
||||
function emitText(node: AdfNode, context: InlineContext, index: number, path: ConvertErrorPath): Result<Emission> {
|
||||
if (Object.keys(node.attrs ?? {}).length > 0) return success({ carry: { first: index, last: index } })
|
||||
if (Object.keys(nodeAttrs(node)).length > 0) return success({ carry: { first: index, last: index } })
|
||||
if (typeof node.text !== 'string' || node.text === '') return failure('unsupported-node-shape', 'a text node holds text: this one has none', path)
|
||||
if ((node.content ?? []).length > 0) return failure('unsupported-node-shape', 'a text node holds no content: this one holds some', path)
|
||||
if (nodeContent(node).length > 0) return failure('unsupported-node-shape', 'a text node holds no content: this one holds some', path)
|
||||
if (/\r/.test(node.text)) return failure('unspellable-character', 'a text node holds a carriage return CommonMark rewrites', path)
|
||||
if (holdsNullCharacter(node.text)) return failure('unspellable-character', 'a text node holds a null character CommonMark replaces', path)
|
||||
const escaping: InlineEscaping = context.bracketed ? 'bracketed' : 'backslash'
|
||||
@@ -260,9 +261,9 @@ function emitEmphasis(nodes: readonly AdfNode[], spelling: string, depth: number
|
||||
function emitCodeSpan(nodes: readonly AdfNode[], depth: number, range: NodeRange, path: ConvertErrorPath): Result<Emission> {
|
||||
let text = ''
|
||||
for (const node of nodes) {
|
||||
if (node.type !== 'text' || (node.marks ?? []).length !== depth + 1) return success({ carry: range })
|
||||
if (node.type !== 'text' || nodeMarks(node).length !== depth + 1) return success({ carry: range })
|
||||
if (typeof node.text !== 'string' || node.text === '') return failure('unsupported-node-shape', 'a text node holds text: this one has none', path)
|
||||
if ((node.content ?? []).length > 0) return failure('unsupported-node-shape', 'a text node holds no content: this one holds some', path)
|
||||
if (nodeContent(node).length > 0) return failure('unsupported-node-shape', 'a text node holds no content: this one holds some', path)
|
||||
text += node.text
|
||||
}
|
||||
if (/[\n\r]/.test(text)) return success({ carry: range })
|
||||
@@ -278,11 +279,11 @@ function needsPadding(text: string): boolean {
|
||||
}
|
||||
|
||||
function emitLink(nodes: readonly AdfNode[], mark: AdfMark, depth: number, range: NodeRange, context: InlineContext, path: ConvertErrorPath): Result<Emission> {
|
||||
const href = mark.attrs?.['href']
|
||||
const title = mark.attrs?.['title']
|
||||
const href = nodeAttrs(mark)['href']
|
||||
const title = nodeAttrs(mark)['title']
|
||||
if (typeof href !== 'string') return success({ carry: range })
|
||||
const node = nodes[0]
|
||||
const bare = nodes.length === 1 && node !== undefined && node.type === 'text' && node.text === href && (node.marks ?? []).length === depth + 1
|
||||
const bare = nodes.length === 1 && node !== undefined && node.type === 'text' && node.text === href && nodeMarks(node).length === depth + 1
|
||||
if (bare && title === undefined && isAutolink(href) && !holdsEntityReference(href)) return success({ segments: [syntax(`<${href}>`)] })
|
||||
const destination = spellDestination(href, path)
|
||||
if (!destination.ok) return destination
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { AdfNode } from '../../adf/document.ts'
|
||||
import { carriesOnly } from '../../adf/document.ts'
|
||||
import { carriesOnly, nodeContent } from '../../adf/document.ts'
|
||||
import { spellPipeDelimiter, spellPipeRow } from '../pipe-table-syntax.ts'
|
||||
import { tryPipeCell } from './inline-line.ts'
|
||||
import type { ConvertErrorPath } from '../../result.ts'
|
||||
@@ -11,7 +11,7 @@ export function tryPipeTable(node: AdfNode, path: ConvertErrorPath): string | un
|
||||
for (const [rowIndex, row] of rows.entries()) {
|
||||
const cells: string[] = []
|
||||
for (const [cellIndex, paragraph] of row.entries()) {
|
||||
const content = paragraph.content ?? []
|
||||
const content = nodeContent(paragraph)
|
||||
const line = content.length === 0 ? '' : tryPipeCell(content, [...path, 'content', rowIndex, 'content', cellIndex, 'content', 0])
|
||||
if (line === undefined) return undefined
|
||||
cells.push(line)
|
||||
@@ -23,12 +23,12 @@ export function tryPipeTable(node: AdfNode, path: ConvertErrorPath): string | un
|
||||
}
|
||||
|
||||
function pipeRows(node: AdfNode): AdfNode[][] | undefined {
|
||||
const rows = node.content ?? []
|
||||
const columns = (rows[0]?.content ?? []).length
|
||||
const rows = nodeContent(node)
|
||||
const columns = rows[0] === undefined ? 0 : nodeContent(rows[0]).length
|
||||
if (!carriesOnly(node, []) || columns === 0) return undefined
|
||||
const grid: AdfNode[][] = []
|
||||
for (const [index, row] of rows.entries()) {
|
||||
const cells = row.content ?? []
|
||||
const cells = nodeContent(row)
|
||||
if (row.type !== 'tableRow' || !carriesOnly(row, []) || cells.length !== columns) return undefined
|
||||
const wanted = index === 0 ? 'tableHeader' : 'tableCell'
|
||||
const paragraphs: AdfNode[] = []
|
||||
@@ -43,7 +43,7 @@ function pipeRows(node: AdfNode): AdfNode[][] | undefined {
|
||||
}
|
||||
|
||||
function plainParagraph(cell: AdfNode): AdfNode | undefined {
|
||||
const content = cell.content ?? []
|
||||
const content = nodeContent(cell)
|
||||
const paragraph = content[0]
|
||||
if (paragraph === undefined || content.length !== 1 || paragraph.type !== 'paragraph' || !carriesOnly(paragraph, [])) return undefined
|
||||
return paragraph
|
||||
|
||||
Reference in New Issue
Block a user