diff --git a/deno.json b/deno.json index 4766fd7..665129d 100644 --- a/deno.json +++ b/deno.json @@ -1,6 +1,6 @@ { "name": "@dbushell/hyperless", - "version": "0.11.0", + "version": "0.12.0", "exports": { ".": "./mod.ts" }, diff --git a/package.json b/package.json index 6951d23..335cb67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dbushell/hyperless", - "version": "0.11.0", + "version": "0.12.0", "repository": { "type": "git", "url": "git+https://github.com/dbushell/hyperless.git" diff --git a/src/html-parser.ts b/src/html-parser.ts index bd9cab4..cf4935d 100644 --- a/src/html-parser.ts +++ b/src/html-parser.ts @@ -5,6 +5,9 @@ import {anyTag, comment} from './regexp.ts'; /** Regular expression to match HTML comment or tag */ const commentTag = new RegExp(`^${comment.source}|^${anyTag.source}`); +/** List of valid
  • parents */ +const listTags = new Set(['ol', 'ul', 'menu']); + /** HTML parser state */ type ParseState = 'DATA' | 'RAWTEXT'; @@ -107,7 +110,15 @@ export const parseHTML = (html: string, options = parseOptions): Node => { } // Append opening tag and ascend else { - const node = new Node(parent, 'ELEMENT', tagText, tagRaw); + const node = new Node(null, 'ELEMENT', tagText, tagRaw); + // Close unclosed `
  • ` if new `
  • ` item is found + if ( + node.tag === 'li' && + parent.tag === 'li' && + listTags.has(parent.parent?.tag!) + ) { + parent = parent.parent!; + } parent.append(node); parent = node; } diff --git a/test/html_test.ts b/test/html_test.ts index 4c5eead..807f3a9 100644 --- a/test/html_test.ts +++ b/test/html_test.ts @@ -64,6 +64,35 @@ Deno.test('leftover text', () => { assertEquals(root.at(1)!.raw, 'Leftover'); }); +Deno.test('unclosed
  • ', () => { + const html = ` +`.replace(/\s+/g, ''); + const root = parseHTML(html); + assertEquals(root.at(0)!.size, 3); + assertEquals( + root.toString(), + ` +`.replace(/\s+/g, '') + ); +}); + Deno.test('comments', () => { const html = `