From b9991fff59454a130b82faf1fc415388a2e43f40 Mon Sep 17 00:00:00 2001
From: Lilleman auf Larv ab
a > b
\n', 'text escapes & as &, < as < and > as >, and holds no character HTML cannot hold: found "> b\\n"'], - ['\n', ' holds its attributes as name="value", each value escaped as text is, then >: found "b\\">a\\n"'], + ['\n', ' holds its attributes as name="value", each value escaping & as & and " as ", then >: found "b\\">a\\n"'], + ['&b
\n', 'text escapes & as &, < as < and > as >, and holds no character HTML cannot hold: found "&b\\n"'], + ['a&b\n', 'text escapes & as &, < as < and > as >, and holds no character HTML cannot hold: found "&b\\n"'],
['a 
\n', 'text escapes & as &, < as < and > as >, and holds no character HTML cannot hold: found " \\n"'], ['a: found "x\n', ' as written here is no code element of the dialect, which writes or : found "\na\n', 'an item\'s line ends at , or at a line feed before the item\'s next block, and its text spells < as <: found "\\n"'],
['\n- ab
\n
\n', ' as written here is no inline element of the dialect: found "b\\n\\n"'],
['\n- if a < b
\n
\n', 'an item\'s line ends at , or at a line feed before the item\'s next block, and its text spells < as <: found "< b\\n\\n"'],
- ['\n- see x
\n
\n', ' holds its attributes as name="value", each value escaped as text is, then >: found "&b=2\\">x\\n\\n"'],
+ ['\n- see x
\n
\n', ' holds its attributes as name="value", each value escaping & as & and " as ", then >: found "&b=2\\">x\\n\\n"'],
['\na
x \n
\n', 'an item\'s line ends at , or at a line feed before the item\'s next block: found "x\\n"…'],
['\n- Bolt
\n- a
\n
\n
\n', 'an item\'s line ends at , or at a line feed before the item\'s next block: found "\\n- a
\\n
\na b \n\n', 'an item\'s line ends at , or at a line feed before the item\'s next block: found "b \\n\\n"'],
@@ -342,8 +344,8 @@ const messages: readonly (readonly [string, string])[] = [
['x
\n', ' as written here is no mark element of the dialect, and a mark element holds text, or one other mark element around text: found "x\\n"'],
['
x
\n', '
as written here is no mark element of the dialect, and a mark element holds text, or one other mark element around text: found "
x\\n"'],
['
\n', 'a mark element holds text, or one other mark element around text: found "\\n"'],
- ['\n', ' holds its attributes as name="value", each value escaped as text is, then >: found "&b=2\\">x"…'],
- [`a
\n${carry('div', panel, 'Check the collation.
')}\n`, 'a carry element shows exactly what adfToHtml writes for its node, then ; to change the node, edit its ADF and write the HTML again: found "collation.x\n', ' holds its attributes as name="value", each value escaping & as & and " as ", then >: found "&b=2\\">x"…'],
+ [`a
\n${carry('div', panel, 'Check the collation.
')}\n`, 'a carry element shows what adfToHtml writes for its node, as it or a browser spells it, then ; to change the node, edit its ADF and write the HTML again: found "collation.a\n', 'a of the dialect is a carry element, holding class="adf-carry" and then data-adf alone: found "a\\n"'],
['\n', 'a carry element spells its node\'s JSON canonically: compact, keys sorted, each character HTML cannot hold spelled as a JSON escape: found "{ "type":""…'],
[`${documentCarry}\n
\n`, 'a carry element holding the document stands alone, as the whole document: found "\\n
\\n"'],
diff --git a/src/html/parse/html-to-adf.ts b/src/html/parse/html-to-adf.ts
index ad59120..102894a 100644
--- a/src/html/parse/html-to-adf.ts
+++ b/src/html/parse/html-to-adf.ts
@@ -51,7 +51,7 @@ const formRefusals: Readonly> = {
element: "an item's first paragraph holding an attribute stands as its on the item's line, straight after
",
}
-// Reads back exactly what `adfToHtml` writes.
+// Reads back what `adfToHtml` writes, as it or a browser spells it.
export function htmlToAdf(html: string): Result {
return positioned(
withinEngineLimits(() => readHtml(html)),
@@ -59,15 +59,14 @@ export function htmlToAdf(html: string): Result {
)
}
-// A form post ends each line in `\r\n`, which reads as the line feed `adfToHtml` writes; a refusal's position still counts the HTML as handed in.
+// A form post ends each line in `\r\n`, which reads as the line feed `adfToHtml` writes.
function readHtml(html: string): Result {
if (typeof html !== 'string') return notAString(html, 'HTML')
const read = readLineFeeds(html.replaceAll('\r\n', '\n'))
- if (read.ok || read.error.position === undefined) return read
- return { error: { ...read.error, position: positionIn(html, read.error.position) }, ok: false }
+ return read.ok ? read : { error: { ...read.error, position: positionIn(html, read.error.position) }, ok: false }
}
-function readLineFeeds(html: string): Result {
+function readLineFeeds(html: string): Result {
if (html === '') return success({ content: [], type: 'doc', version: 1 })
return readDocumentCarry(html) ?? readBlocks(html)
}
diff --git a/src/html/parse/source.ts b/src/html/parse/source.ts
index 20d7607..da72ec2 100644
--- a/src/html/parse/source.ts
+++ b/src/html/parse/source.ts
@@ -7,7 +7,7 @@ export type Place = { index: number; parent: Place | undefined }
export type ReadNode = Result<{ end: number; node: AdfNode }, ParseError>
-// A start tag as `adfToHtml` writes it, its attributes' values unescaped.
+// A start tag as `adfToHtml` or a browser writes it, its attributes' values unescaped.
export type StartTag = { attributes: (readonly [string, string])[]; end: number; name: string; start: number }
// A tag whose name reads, its attributes or its `>` not: `stopped` is where reading them stopped.
@@ -34,7 +34,7 @@ export function misread(html: string, index: number, expected: string, unexpecte
const tag = scanStartTag(html, index)
if (tag === undefined) return { at: index, message: `${expected}: ${foundAt(html, index)}` }
if ('end' in tag) return { at: index, message: `<${tag.name}> as written here is ${unexpected}: ${foundAt(html, index)}` }
- return { at: tag.stopped, message: `<${tag.name}> holds its attributes as name="value", each value escaped as text is, then >: ${foundAt(html, tag.stopped)}` }
+ return { at: tag.stopped, message: `<${tag.name}> holds its attributes as name="value", each value escaping & as & and " as ", then >: ${foundAt(html, tag.stopped)}` }
}
// What stands at `index`, for a refusal's message, a character no one sees spelled as its escape.
@@ -45,7 +45,7 @@ export function foundAt(html: string, index: number): string {
return `found ${spelled}${index + found.length < html.length ? '…' : ''}`
}
-// The start of the same line in `html`, where the position was counted after its `\r\n` became line feeds.
+// The position of the start of `line` in `html` as handed in, for a line counted after each `\r\n` became a line feed.
export function positionIn(html: string, { line }: SourcePosition): SourcePosition {
let offset = 0
for (let passed = 1; passed < line; passed += 1) offset = html.indexOf('\n', offset) + 1