foo
==>
Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))
# Can handle lone close tags {"dialect": "noMatch"}
==>
Document(CloseTag(StartCloseTag,TagName,EndTag))
# Parses ampersands in attributes
==>
Document(Element(SelfClosingTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue(InvalidEntity)), EndTag)))
# Supports self-closing dialect {"dialect": "selfClosing"}
==>
Document(Element(
OpenTag(StartTag,TagName,EndTag),
Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName,Is,UnquotedAttributeValue),SelfClosingEndTag)),
CloseTag(StartCloseTag,TagName,EndTag)))
# Allows self-closing in foreign elements
==>
Document(Element(OpenTag(StartTag,TagName,EndTag),
Element(OpenTag(StartTag,TagName,EndTag),
Element(SelfClosingTag(StartTag,TagName,SelfClosingEndTag)),
CloseTag(StartCloseTag,TagName,EndTag)),
CloseTag(StartCloseTag,TagName,EndTag)))
# Parses multiple unfinished tags in a row
Document(Element(OpenTag(StartTag,TagName,⚠),
Element(OpenTag(StartTag,TagName,⚠),
Element(OpenTag(StartTag,TagName,⚠),⚠),⚠),⚠))
# Allows self-closing on special tags {"dialect": "selfClosing"}
==>
Document(Element(
OpenTag(StartTag,TagName,EndTag),
Text,
Element(SelfClosingTag(StartTag,TagName,SelfClosingEndTag)),
Text,
Element(SelfClosingTag(StartTag,TagName,SelfClosingEndTag)),
Text,
Element(SelfClosingTag(StartTag,TagName,SelfClosingEndTag)),
Text,
Element(SelfClosingTag(StartTag,TagName,SelfClosingEndTag)),
Text,
CloseTag(StartCloseTag,TagName,EndTag)))
html-1.3.9/test/test-html.js 0000664 0000000 0000000 00000001560 14565351156 0015743 0 ustar 00root root 0000000 0000000 import {parser, configureNesting} from "../dist/index.js"
import {parser as jsParser} from "@lezer/javascript"
import {fileTests} from "@lezer/generator/dist/test"
import * as fs from "fs"
import * as path from "path"
import {fileURLToPath} from "url"
let caseDir = path.dirname(fileURLToPath(import.meta.url))
let mixed = parser.configure({
wrap: configureNesting([{
tag: "script",
attrs(attrs) {
return !attrs.type || /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i.test(attrs.type)
},
parser: jsParser
}])
})
for (let file of fs.readdirSync(caseDir)) {
if (!/\.txt$/.test(file)) continue
let name = /^[^\.]*/.exec(file)[0]
describe(name, () => {
let p = name == "mixed" ? mixed : parser
for (let {name, run} of fileTests(fs.readFileSync(path.join(caseDir, file), "utf8"), file))
it(name, () => run(p))
})
}
html-1.3.9/test/test-incremental.js 0000664 0000000 0000000 00000006221 14565351156 0017277 0 ustar 00root root 0000000 0000000 import {parser as baseParser} from "../dist/index.js"
import {TreeFragment} from "@lezer/common"
let parser = baseParser.configure({bufferLength: 2})
let r = n => Math.floor(Math.random() * n)
let tags = ["p", "ul", "li", "div", "span", "th", "tr", "body", "head", "title", "dd", "code", "em", "strong"]
function randomDoc(size) {
let doc = ""
if (!r(5)) doc += ""
let scope = []
for (let i = 0; i < size; i++) {
let sel = r(20)
if (sel < 5) {
let tag = tags[r(tags.length)]
doc += `<${tag}${r(2) ? " a=b" : ""}>`
scope.push(tag)
} else if (sel < 10 && scope.length) {
let name = scope.pop()
doc += `${r(5) ? name : "div"}>`
} else if (sel == 10) {
doc += `
![]()
`
} else if (sel == 11) {
doc += ""
} else if (sel == 12) {
doc += r(2) ? "&" : ""
} else {
for (let i = r(6) + 1; i >= 0; i--)
doc += String.fromCharCode(97 + r(26))
}
}
while (scope.length) {
let name = scope.pop()
if (r(5)) doc += `${name}>`
}
return doc
}
function check(doc, [tp, pos, txt], prevAST) {
let change = {fromA: pos, toA: pos, fromB: pos, toB: pos}, newDoc
if (tp == "insert") {
newDoc = doc.slice(0, pos) + txt + doc.slice(pos)
change.toA += txt.length
} else if (tp == "del") {
newDoc = doc.slice(0, pos) + doc.slice(pos + 1)
change.toB++
} else {
newDoc = doc.slice(0, pos) + txt + doc.slice(pos + 1)
change.toA += txt.length
change.toB++
}
let fragments = TreeFragment.applyChanges(TreeFragment.addTree(prevAST || parser.parse(doc)), [change], 2)
let ast = parser.parse(newDoc, fragments)
let orig = parser.parse(newDoc)
if (ast.toString() != orig.toString()) {
throw new Error(`Mismatch:\n ${ast}\nvs\n ${orig}\ndocument: ${
JSON.stringify(doc)}\naction: ${JSON.stringify([tp, pos, ch])}`)
}
return [newDoc, ast]
}
// Call this to just run random tests until a failing one is found.
// Not directly called in the tests because there's a bunch of
// circumstances in which uninteresting deviations in error recovery
// will create differing parses, so results have to be manually
// inspected.
function generate() {
for (let count = 0, size = 2;; size = Math.min(40, size + 1)) {
let doc = randomDoc(size), prev = null
for (let i = 0; i < 2; i++) {
console.log("Attempt", ++count)
let action = [["del", "insert", "replace"][r(3)], r(doc.length - 1), "<>/piabc "[r(9)]]
;([doc, prev] = check(doc, action, prev))
}
}
}
describe("Incremental parsing", () => {
it("doesn't get confused by reused opening tags", () => {
check("
mgnbni
", ["del", 29])
})
it("can handle a renamed opening tag after a self-closing", () => {
check("
one two three four five six seven
eight", ["replace", 37, "a"])
})
it("is okay with nameless elements", () => {
check("
![]()
<>body>", ["replace", 14, ">"])
check("abcde<>fghij<", ["replace", 12, ">"])
})
it("doesn't get confused by an invalid close tag receiving a matching open tag", () => {
check("
foo", ["insert", 0, "
"])
})
})
html-1.3.9/test/vue.txt 0000664 0000000 0000000 00000002255 14565351156 0015026 0 ustar 00root root 0000000 0000000 # Parses Vue builtin directives
==>
Document(
Element(
OpenTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue), EndTag),
CloseTag(StartCloseTag, TagName, EndTag)))
# Parses Vue :is shorthand syntax
==>
Document(
Element(
OpenTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue),EndTag),
CloseTag(StartCloseTag, TagName, EndTag)))
# Parses Vue @click shorthand syntax
==>
Document(
Element(
OpenTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue), EndTag),
Text,
CloseTag(StartCloseTag, TagName, EndTag)))
# Parses Vue @submit.prevent shorthand syntax
==>
Document(
Element(
OpenTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue), EndTag),
CloseTag(StartCloseTag, TagName, EndTag)))
# Parses Vue Dynamic Arguments
Link
==>
Document(
Element(
OpenTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue), EndTag),
Text,
CloseTag(StartCloseTag, TagName, EndTag)))