Part the source into adf/ and markdown/ ahead of the parser #30

Merged
lilleman merged 3 commits from tick-3a into main 2026-08-27 22:51:38 +02:00
5 changed files with 14 additions and 13 deletions
Showing only changes of commit 48dcdeccea - Show all commits
+2 -2
View File
@@ -138,8 +138,8 @@ live Atlassian APIs; property-generated ADF trees; the CommonMark spec suite aga
fields it claims (`isAdfDocument`); past it everything is typed. Make invalid states
unrepresentable.
- `src/adf/` holds ADF's own knowledge and imports no format. Each format directory (`markdown/`,
`html/`) parts into `emit/` (ADF→format) and `parse/` (format→ADF), its root holding only what
both directions read.
`html/`) parts into `emit/` (ADF→format) and `parse/` (format→ADF), its root holding what both
directions read.
- The attribute vocabulary is ADF's: `adf/` walks it and narrows each value to its kind, and a
format spells the narrowed value. A spelling that re-checks the type is the check's second copy.
- Explicit over implicit; descriptive names; no catch-all files (`utils`, `helpers`, `misc`); a
+1 -1
View File
@@ -1,7 +1,7 @@
import type { AdfAttributes } from './document.ts'
import type { JsonValue } from '../json-value.ts'
export type AttributeKind = 'boolean' | 'json' | 'number' | 'string'
type AttributeKind = 'boolean' | 'json' | 'number' | 'string'
export type AttributeVocabulary = Readonly<Record<string, AttributeKind>>
+8 -6
View File
@@ -1,11 +1,13 @@
import type { BlockType } from '../adf/block-directives.ts'
const blockArguments: Readonly<Record<string, string>> = {
blockTaskItem: 'state',
panel: 'panelType',
taskItem: 'state',
} satisfies Partial<Record<BlockType, string>>
const argumentByType = new Map(
Object.entries({
blockTaskItem: 'state',
panel: 'panelType',
taskItem: 'state',
} satisfies Partial<Record<BlockType, string>>),
)
export function blockArgument(type: string): string | undefined {
return blockArguments[type]
return argumentByType.get(type)
}
+2 -3
View File
@@ -1,8 +1,5 @@
export type LinePosition = 'first' | 'later'
const asciiPunctuation = /[!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]/
const htmlConstructs = [/^<[!?]/, /^<\/?[A-Za-z][A-Za-z0-9-]*(?:[\s/>]|$)/, /^<[^\s<>@]+@[^\s<>@]+>/]
const controlCharacterRange = '\\u0000-\\u001f\\u007f'
const autolinkSource = `[A-Za-z][A-Za-z0-9+.-]{1,31}:[^\\s<>${controlCharacterRange}]*`
const nullCharacterSource = '\\u0000'
@@ -14,7 +11,9 @@ const bracketedAutolink = new RegExp(`^<(?:${autolinkSource})>`)
const controlCharacter = new RegExp(`[${controlCharacterRange}]`)
const entityReference = new RegExp(entityReferenceSource)
const nullCharacter = new RegExp(nullCharacterSource)
const asciiPunctuation = /[!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]/
const firstCharacterOpeners = [/^#{1,6}(?:[ \t]|$)/, /^>/, /^[*+-](?:[ \t]|$)/, /^`{3,}/, /^~{3,}/, /^:{2,}/, /^\|/]
const htmlConstructs = [/^<[!?]/, /^<\/?[A-Za-z][A-Za-z0-9-]*(?:[\s/>]|$)/, /^<[^\s<>@]+@[^\s<>@]+>/]
const orderedListOpener = /^(\d{1,9})[.)](?:[ \t]|$)/
const setextUnderline = /^(?:=+|-+)$/
const thematicBreak = /^(?:(?:\*[ \t]*){3,}|(?:-[ \t]*){3,}|(?:_[ \t]*){3,})$/
+1 -1
View File
@@ -189,7 +189,7 @@ detail is settled at its own milestone.
HTML will want too, not a markdown spelling.
**Settled** (the maintainer, 2026-08-27): `markdown/` parts here as well, into `emit/` and
`parse/` with the shared set at the root — the grammar module, emphasis matching,
destination spelling, the tables' markdown halves — and `parse/` arriving with 3b's first
the tables' markdown halves — and `parse/` arriving with 3b's first
file, the rule `html/` already follows. And the node tables, a second copy of
`spec/flavour.md`'s prose whose mistyped attribute name degrades into a false refusal no
test catches, get their guard: a test reads the spec's node sections, takes each