diff --git a/AGENTS.md b/AGENTS.md index f88b32f..9d97f5a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 diff --git a/src/adf/attribute-vocabulary.ts b/src/adf/attribute-vocabulary.ts index 7e30d80..8c8fde5 100644 --- a/src/adf/attribute-vocabulary.ts +++ b/src/adf/attribute-vocabulary.ts @@ -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> diff --git a/src/markdown/block-directive-arguments.ts b/src/markdown/block-directive-arguments.ts index ee86d95..9087549 100644 --- a/src/markdown/block-directive-arguments.ts +++ b/src/markdown/block-directive-arguments.ts @@ -1,11 +1,13 @@ import type { BlockType } from '../adf/block-directives.ts' -const blockArguments: Readonly> = { - blockTaskItem: 'state', - panel: 'panelType', - taskItem: 'state', -} satisfies Partial> +const argumentByType = new Map( + Object.entries({ + blockTaskItem: 'state', + panel: 'panelType', + taskItem: 'state', + } satisfies Partial>), +) export function blockArgument(type: string): string | undefined { - return blockArguments[type] + return argumentByType.get(type) } diff --git a/src/markdown/commonmark-grammar.ts b/src/markdown/commonmark-grammar.ts index 022b654..0d9dec1 100644 --- a/src/markdown/commonmark-grammar.ts +++ b/src/markdown/commonmark-grammar.ts @@ -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,})$/ diff --git a/todo.md b/todo.md index 411b5e7..6135f99 100644 --- a/todo.md +++ b/todo.md @@ -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