Premier commit déjà bien avancé
This commit is contained in:
297
frontend/node_modules/@lezer/html/CHANGELOG.md
generated
vendored
Normal file
297
frontend/node_modules/@lezer/html/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,297 @@
|
||||
## 1.3.12 (2025-09-26)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Emit tokens for `<` characters without tag name, so that autocompletion can work with them.
|
||||
|
||||
## 1.3.11 (2025-09-25)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Don't parse `<` followed by whitespace as the start of a tag.
|
||||
|
||||
## 1.3.10 (2024-05-29)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix an issue that broke attribute reading when defining a nested language on a tag that isn't a `style`, `textearea`, or `script` tag.
|
||||
|
||||
## 1.3.9 (2024-02-21)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
When using the "selfClosing" dialect, fix parse errors for `<br/>` (tags that implicitly self-close) and `<script/>` (special tags).
|
||||
|
||||
## 1.3.8 (2023-12-28)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Add `bidiIsolate` node props for tags, comments, and attributes.
|
||||
|
||||
Mark tags, attributes, and comments as isolating for bidirectional text.
|
||||
|
||||
## 1.3.7 (2023-11-23)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that caused the parser to not properly recognize empty HTML comments. Don't emit nested parses for empty elements in configureNesting
|
||||
|
||||
Fix an issue where `configureNesting` could emit empty overlay ranges for empty elements.
|
||||
|
||||
## 1.3.6 (2023-07-12)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Improve parsing of multiple unfinished opening tags by disallowing less-than characters in attribute names.
|
||||
|
||||
## 1.3.5 (2023-07-03)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make the package work with new TS resolution styles.
|
||||
|
||||
## 1.3.4 (2023-03-27)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that caused mixed parsing of non-style/script elements to attach the nested parse tree to the incorrect node.
|
||||
|
||||
## 1.3.3 (2023-02-21)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make sure build output is strictly ES6 again.
|
||||
|
||||
## 1.3.2 (2023-02-16)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a crash caused by nexted parsing of attributes returning invalid ranges for attributes missing their closing quote.
|
||||
|
||||
## 1.3.1 (2023-02-11)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Always allow self-closing tags in `<svg>` and `<math>` tags.
|
||||
|
||||
## 1.3.0 (2022-12-16)
|
||||
|
||||
### New features
|
||||
|
||||
`configureNesting` now supports targeting tags other than `style`, `script`, and `textarea`.
|
||||
|
||||
## 1.2.0 (2022-11-25)
|
||||
|
||||
### New features
|
||||
|
||||
`configureNesting` now takes a second argument that can be used to specify that the value of some attributes should be parsed with an external parser.
|
||||
|
||||
## 1.1.1 (2022-11-18)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Align allowed characters in unquoted attribute values with the spec. Replace another unicode escape with a character
|
||||
|
||||
## 1.1.0 (2022-11-16)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Allow more characters in attribute names, following HTML spec.
|
||||
|
||||
### New features
|
||||
|
||||
The new `"selfClosing"` dialect allows `/>` syntax to be used to create self-closing tags.
|
||||
|
||||
## 1.0.1 (2022-07-27)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Continue parsing when an invalid entity reference appears in an attribute value.
|
||||
|
||||
## 1.0.0 (2022-06-06)
|
||||
|
||||
### New features
|
||||
|
||||
First stable version.
|
||||
|
||||
## 0.16.1 (2022-05-16)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug where comment end tokens preceded by dashes were sometimes not recognized.
|
||||
|
||||
## 0.16.0 (2022-04-20)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Move to 0.16 serialized parser format.
|
||||
|
||||
### New features
|
||||
|
||||
The parser now includes syntax highlighting information in its node types.
|
||||
|
||||
## 0.15.1 (2022-02-16)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make sure the tree for unfinished self-closing tags shows them as self-closing.
|
||||
|
||||
## 0.15.0 (2021-08-11)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
The module's name changed from `lezer-html` to `@lezer/html`.
|
||||
|
||||
Upgrade to the 0.15.0 lezer interfaces.
|
||||
|
||||
## 0.13.6 (2021-06-16)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Add a rule for invalid `&` syntax to avoid error-recovery around stray ampersands.
|
||||
|
||||
## 0.13.5 (2021-05-05)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a problem where like attributes inappropriately included trailing whitespace.
|
||||
|
||||
## 0.13.4 (2021-03-10)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Strip quotes from attribute values passed to `attrs` predicates in `configureNesting`.
|
||||
|
||||
## 0.13.3 (2021-02-17)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Optimize the tokenizer by using a context tracker.
|
||||
|
||||
## 0.13.2 (2021-01-22)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make comments consist of multiple tokens, so that huge comments don't freeze the parser.
|
||||
|
||||
## 0.13.1 (2020-12-04)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix versions of lezer packages depended on.
|
||||
|
||||
## 0.13.0 (2020-12-04)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
The nested parser configuration utility is now called `configureNesting`, and returns an object to pass to `Parser.configure`'s `nested` option instead of a new parser.
|
||||
|
||||
### New features
|
||||
|
||||
The parser can now be given a "noMatch" dialect to not mark mismatched tags.
|
||||
|
||||
## 0.12.0 (2020-10-23)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Adjust to changed serialized parser format.
|
||||
|
||||
### New features
|
||||
|
||||
The parser now more effectively matches close and open tags, even in the presence of mismatched tags.
|
||||
|
||||
## 0.11.1 (2020-09-26)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix lezer depencency versions
|
||||
|
||||
## 0.11.0 (2020-09-26)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Follow change in serialized parser format.
|
||||
|
||||
## 0.10.0 (2020-08-07)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Upgrade to 0.10 parser serialization
|
||||
|
||||
## 0.9.0 (2020-06-08)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Upgrade to 0.9 parser serialization
|
||||
|
||||
### New features
|
||||
|
||||
Tag start/end tokens now have `NodeProp.openedBy`/`closedBy` props.
|
||||
|
||||
## 0.8.4 (2020-04-09)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Regenerate parser with a fix in lezer-generator so that the top node prop is properly assigned.
|
||||
|
||||
## 0.8.3 (2020-04-01)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make the package load as an ES module on node
|
||||
|
||||
## 0.8.2 (2020-02-28)
|
||||
|
||||
### New features
|
||||
|
||||
Provide an ES module file.
|
||||
|
||||
## 0.8.1 (2020-02-26)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Adds support for single-quoted attribute values.
|
||||
|
||||
Don't treat /> tag ends as self-closing, just ignore them instead.
|
||||
|
||||
## 0.8.0 (2020-02-03)
|
||||
|
||||
### New features
|
||||
|
||||
Follow 0.8.0 release of the library.
|
||||
|
||||
## 0.7.0 (2020-01-20)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Use the lezer 0.7.0 parser format.
|
||||
|
||||
## 0.5.2 (2020-01-15)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Allow whitespace between the `<` and `/` in a close tag.
|
||||
|
||||
## 0.5.1 (2019-10-22)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix top prop missing from build output.
|
||||
|
||||
## 0.5.0 (2019-10-22)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Move from `lang` to `top` prop on document node.
|
||||
|
||||
## 0.4.0 (2019-09-10)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Adjust to 0.4.0 parse table format.
|
||||
|
||||
## 0.3.0 (2019-08-22)
|
||||
|
||||
### New features
|
||||
|
||||
First numbered release.
|
||||
21
frontend/node_modules/@lezer/html/LICENSE
generated
vendored
Normal file
21
frontend/node_modules/@lezer/html/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2018 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
37
frontend/node_modules/@lezer/html/README.md
generated
vendored
Normal file
37
frontend/node_modules/@lezer/html/README.md
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
# @lezer/html
|
||||
|
||||
This is an HTML grammar for the
|
||||
[lezer](https://lezer.codemirror.net/) parser system.
|
||||
|
||||
The code is licensed under an MIT license.
|
||||
|
||||
## Interface
|
||||
|
||||
This package exports two bindings:
|
||||
|
||||
**`parser`**`: Parser`
|
||||
|
||||
The parser instance for the basic HTML grammar. Supports two dialects:
|
||||
|
||||
- `"noMatch"` turns off tag matching, creating regular syntax nodes
|
||||
even for mismatched tags.
|
||||
|
||||
- `"selfClosing"` adds support for `/>` self-closing tag syntax.
|
||||
|
||||
**`configureNesting`**`(tags?: {`\
|
||||
` tag: string,`\
|
||||
` attrs?: (attrs: {[attr: string]: string}) => boolean,`\
|
||||
` parser: Parser,`\
|
||||
`}[], attributes?: {`\
|
||||
` name: string,`\
|
||||
` tagName?: string,`\
|
||||
` parser: Parser,`\
|
||||
`}[]): ParseWrapper`
|
||||
|
||||
Create a nested parser config object which overrides the way the
|
||||
content of some tags or attributes is parsed. Each tag override is an
|
||||
object with a `tag` property holding the (lower case) tag name to
|
||||
override, and an optional `attrs` predicate that, if given, has to
|
||||
return true for the tag's attributes for this override to apply.
|
||||
|
||||
The `parser` property describes the way the tag's content is parsed.
|
||||
354
frontend/node_modules/@lezer/html/dist/index.cjs
generated
vendored
Normal file
354
frontend/node_modules/@lezer/html/dist/index.cjs
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
14
frontend/node_modules/@lezer/html/dist/index.d.cts
generated
vendored
Normal file
14
frontend/node_modules/@lezer/html/dist/index.d.cts
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import {LRParser} from "@lezer/lr"
|
||||
import {Input, PartialParse, Parser, TreeCursor, ParseWrapper} from "@lezer/common"
|
||||
|
||||
export const parser: LRParser
|
||||
|
||||
export function configureNesting(tags?: readonly {
|
||||
tag: string,
|
||||
attrs?: (attrs: {[attr: string]: string}) => boolean,
|
||||
parser: Parser
|
||||
}[], attributes?: {
|
||||
name: string,
|
||||
tagName?: string,
|
||||
parser: Parser
|
||||
}[]): ParseWrapper
|
||||
14
frontend/node_modules/@lezer/html/dist/index.d.ts
generated
vendored
Normal file
14
frontend/node_modules/@lezer/html/dist/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import {LRParser} from "@lezer/lr"
|
||||
import {Input, PartialParse, Parser, TreeCursor, ParseWrapper} from "@lezer/common"
|
||||
|
||||
export const parser: LRParser
|
||||
|
||||
export function configureNesting(tags?: readonly {
|
||||
tag: string,
|
||||
attrs?: (attrs: {[attr: string]: string}) => boolean,
|
||||
parser: Parser
|
||||
}[], attributes?: {
|
||||
name: string,
|
||||
tagName?: string,
|
||||
parser: Parser
|
||||
}[]): ParseWrapper
|
||||
349
frontend/node_modules/@lezer/html/dist/index.js
generated
vendored
Normal file
349
frontend/node_modules/@lezer/html/dist/index.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
37
frontend/node_modules/@lezer/html/package.json
generated
vendored
Normal file
37
frontend/node_modules/@lezer/html/package.json
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@lezer/html",
|
||||
"version": "1.3.12",
|
||||
"description": "lezer-based HTML grammar",
|
||||
"main": "dist/index.cjs",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"module": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"author": "Marijn Haverbeke <marijn@haverbeke.berlin>",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@lezer/javascript": "^1.0.0",
|
||||
"@lezer/generator": "^1.0.0",
|
||||
"mocha": "^10.2.0",
|
||||
"rollup": "^2.52.2",
|
||||
"@rollup/plugin-node-resolve": "^9.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lezer/lr": "^1.0.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/common": "^1.2.0"
|
||||
},
|
||||
"repository": {
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/lezer-parser/html.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "lezer-generator src/html.grammar -o src/parser && rollup -c",
|
||||
"build-debug": "lezer-generator src/html.grammar --names -o src/parser && rollup -c",
|
||||
"prepare": "npm run build",
|
||||
"test": "mocha test/test-*.js"
|
||||
}
|
||||
}
|
||||
16
frontend/node_modules/@lezer/html/rollup.config.js
generated
vendored
Normal file
16
frontend/node_modules/@lezer/html/rollup.config.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
import {nodeResolve} from "@rollup/plugin-node-resolve"
|
||||
|
||||
export default {
|
||||
input: "./src/index.js",
|
||||
output: [{
|
||||
format: "cjs",
|
||||
file: "./dist/index.cjs"
|
||||
}, {
|
||||
format: "es",
|
||||
file: "./dist/index.js"
|
||||
}],
|
||||
external(id) { return !/^[\.\/]/.test(id) },
|
||||
plugins: [
|
||||
nodeResolve()
|
||||
]
|
||||
}
|
||||
87
frontend/node_modules/@lezer/html/src/content.js
generated
vendored
Normal file
87
frontend/node_modules/@lezer/html/src/content.js
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
import {ScriptText, StyleText, TextareaText,
|
||||
Element, TagName, Attribute, AttributeName, OpenTag, CloseTag,
|
||||
AttributeValue, UnquotedAttributeValue} from "./parser.terms.js"
|
||||
import {parseMixed} from "@lezer/common"
|
||||
|
||||
function getAttrs(openTag, input) {
|
||||
let attrs = Object.create(null)
|
||||
for (let att of openTag.getChildren(Attribute)) {
|
||||
let name = att.getChild(AttributeName), value = att.getChild(AttributeValue) || att.getChild(UnquotedAttributeValue)
|
||||
if (name) attrs[input.read(name.from, name.to)] =
|
||||
!value ? "" : value.type.id == AttributeValue ? input.read(value.from + 1, value.to - 1) : input.read(value.from, value.to)
|
||||
}
|
||||
return attrs
|
||||
}
|
||||
|
||||
function findTagName(openTag, input) {
|
||||
let tagNameNode = openTag.getChild(TagName)
|
||||
return tagNameNode ? input.read(tagNameNode.from, tagNameNode.to) : " "
|
||||
}
|
||||
|
||||
function maybeNest(node, input, tags) {
|
||||
let attrs
|
||||
for (let tag of tags) {
|
||||
if (!tag.attrs || tag.attrs(attrs || (attrs = getAttrs(node.node.parent.firstChild, input))))
|
||||
return {parser: tag.parser}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// tags?: {
|
||||
// tag: string,
|
||||
// attrs?: ({[attr: string]: string}) => boolean,
|
||||
// parser: Parser
|
||||
// }[]
|
||||
// attributes?: {
|
||||
// name: string,
|
||||
// tagName?: string,
|
||||
// parser: Parser
|
||||
// }[]
|
||||
|
||||
export function configureNesting(tags = [], attributes = []) {
|
||||
let script = [], style = [], textarea = [], other = []
|
||||
for (let tag of tags) {
|
||||
let array = tag.tag == "script" ? script : tag.tag == "style" ? style : tag.tag == "textarea" ? textarea : other
|
||||
array.push(tag)
|
||||
}
|
||||
let attrs = attributes.length ? Object.create(null) : null
|
||||
for (let attr of attributes) (attrs[attr.name] || (attrs[attr.name] = [])).push(attr)
|
||||
|
||||
return parseMixed((node, input) => {
|
||||
let id = node.type.id
|
||||
if (id == ScriptText) return maybeNest(node, input, script)
|
||||
if (id == StyleText) return maybeNest(node, input, style)
|
||||
if (id == TextareaText) return maybeNest(node, input, textarea)
|
||||
|
||||
if (id == Element && other.length) {
|
||||
let n = node.node, open = n.firstChild, tagName = open && findTagName(open, input), attrs
|
||||
if (tagName) for (let tag of other) {
|
||||
if (tag.tag == tagName && (!tag.attrs || tag.attrs(attrs || (attrs = getAttrs(open, input))))) {
|
||||
let close = n.lastChild
|
||||
let to = close.type.id == CloseTag ? close.from : n.to
|
||||
if (to > open.to)
|
||||
return {parser: tag.parser, overlay: [{from: open.to, to}]}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attrs && id == Attribute) {
|
||||
let n = node.node, nameNode
|
||||
if (nameNode = n.firstChild) {
|
||||
let matches = attrs[input.read(nameNode.from, nameNode.to)]
|
||||
if (matches) for (let attr of matches) {
|
||||
if (attr.tagName && attr.tagName != findTagName(n.parent, input)) continue
|
||||
let value = n.lastChild
|
||||
if (value.type.id == AttributeValue) {
|
||||
let from = value.from + 1
|
||||
let last = value.lastChild, to = value.to - (last && last.isError ? 0 : 1)
|
||||
if (to > from) return {parser: attr.parser, overlay: [{from, to}]}
|
||||
} else if (value.type.id == UnquotedAttributeValue) {
|
||||
return {parser: attr.parser, overlay: [{from: value.from, to: value.to}]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
})
|
||||
}
|
||||
15
frontend/node_modules/@lezer/html/src/highlight.js
generated
vendored
Normal file
15
frontend/node_modules/@lezer/html/src/highlight.js
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
import {styleTags, tags as t} from "@lezer/highlight"
|
||||
|
||||
export const htmlHighlighting = styleTags({
|
||||
"Text RawText IncompleteTag IncompleteCloseTag": t.content,
|
||||
"StartTag StartCloseTag SelfClosingEndTag EndTag": t.angleBracket,
|
||||
TagName: t.tagName,
|
||||
"MismatchedCloseTag/TagName": [t.tagName, t.invalid],
|
||||
AttributeName: t.attributeName,
|
||||
"AttributeValue UnquotedAttributeValue": t.attributeValue,
|
||||
Is: t.definitionOperator,
|
||||
"EntityReference CharacterReference": t.character,
|
||||
Comment: t.blockComment,
|
||||
ProcessingInst: t.processingInstruction,
|
||||
DoctypeDecl: t.documentMeta
|
||||
})
|
||||
181
frontend/node_modules/@lezer/html/src/html.grammar
generated
vendored
Normal file
181
frontend/node_modules/@lezer/html/src/html.grammar
generated
vendored
Normal file
@ -0,0 +1,181 @@
|
||||
@top Document { (entity | DoctypeDecl)+ }
|
||||
|
||||
@dialects { noMatch, selfClosing }
|
||||
|
||||
entity[@isGroup=Entity] {
|
||||
Text |
|
||||
EntityReference |
|
||||
CharacterReference |
|
||||
InvalidEntity |
|
||||
Element |
|
||||
Comment |
|
||||
ProcessingInst |
|
||||
IncompleteTag |
|
||||
IncompleteCloseTag |
|
||||
MismatchedCloseTag |
|
||||
NoMatchCloseTag
|
||||
}
|
||||
|
||||
Element {
|
||||
OpenScriptTag ScriptText (CloseScriptTag | missingCloseTag) |
|
||||
OpenStyleTag StyleText (CloseStyleTag | missingCloseTag) |
|
||||
OpenTextareaTag TextareaText (CloseTextareaTag | missingCloseTag) |
|
||||
OpenTag entity* (CloseTag | missingCloseTag) |
|
||||
SelfClosingTag
|
||||
}
|
||||
|
||||
ScriptText[group="TextContent Entity"] { scriptText* }
|
||||
|
||||
StyleText[group="TextContent Entity"] { styleText* }
|
||||
|
||||
TextareaText[group="TextContent Entity"] { textareaText* }
|
||||
|
||||
@skip { space } {
|
||||
OpenTag[closedBy=CloseTag,isolate=ltr] {
|
||||
StartTag TagName Attribute* EndTag
|
||||
}
|
||||
|
||||
SelfClosingTag[isolate=ltr] {
|
||||
StartSelfClosingTag TagName Attribute* (EndTag | SelfClosingEndTag) |
|
||||
(StartTag | StartScriptTag | StartStyleTag | StartTextareaTag) TagName Attribute* SelfClosingEndTag
|
||||
}
|
||||
|
||||
MismatchedCloseTag[isolate=ltr] {
|
||||
MismatchedStartCloseTag TagName EndTag
|
||||
}
|
||||
|
||||
NoMatchCloseTag[@name=CloseTag,isolate=ltr] {
|
||||
NoMatchStartCloseTag TagName EndTag
|
||||
}
|
||||
|
||||
CloseTag[openedBy=OpenTag,isolate=ltr] {
|
||||
StartCloseTag TagName EndTag
|
||||
}
|
||||
|
||||
OpenScriptTag[@name=OpenTag,closedBy=CloseTag,isolate=ltr] {
|
||||
StartScriptTag TagName Attribute* EndTag
|
||||
}
|
||||
|
||||
CloseScriptTag[@name=CloseTag,openedBy=OpenTag,isolate=ltr] {
|
||||
StartCloseScriptTag TagName EndTag
|
||||
}
|
||||
|
||||
OpenStyleTag[@name=OpenTag,closedBy=CloseTag,isolate=ltr] {
|
||||
StartStyleTag TagName Attribute* EndTag
|
||||
}
|
||||
|
||||
CloseStyleTag[@name=CloseTag,openedBy=OpenTag,isolate=ltr] {
|
||||
StartCloseStyleTag TagName EndTag
|
||||
}
|
||||
|
||||
OpenTextareaTag[@name=OpenTag,closedBy=CloseTag,isolate=ltr] {
|
||||
StartTextareaTag TagName Attribute* EndTag
|
||||
}
|
||||
|
||||
CloseTextareaTag[@name=CloseTag,openedBy=OpenTag,isolate=ltr] {
|
||||
StartCloseTextareaTag TagName EndTag
|
||||
}
|
||||
|
||||
Attribute {
|
||||
AttributeName (Is (AttributeValue | UnquotedAttributeValue))?
|
||||
}
|
||||
}
|
||||
|
||||
AttributeValue[isolate] {
|
||||
"\"" (attributeContentDouble | EntityReference | CharacterReference | InvalidEntity)* "\"" |
|
||||
"\'" (attributeContentSingle | EntityReference | CharacterReference | InvalidEntity)* "\'"
|
||||
}
|
||||
|
||||
Comment[isolate] { commentStart commentContent* commentEnd }
|
||||
|
||||
@context elementContext from "./tokens.js"
|
||||
|
||||
@external tokens scriptTokens from "./tokens.js" {
|
||||
scriptText
|
||||
StartCloseScriptTag[@name=StartCloseTag,closedBy=EndTag]
|
||||
}
|
||||
|
||||
@external tokens styleTokens from "./tokens.js" {
|
||||
styleText
|
||||
StartCloseStyleTag[@name=StartCloseTag,closedBy=EndTag]
|
||||
}
|
||||
|
||||
@external tokens textareaTokens from "./tokens.js" {
|
||||
textareaText
|
||||
StartCloseTextareaTag[@name=StartCloseTag,closedBy=EndTag]
|
||||
}
|
||||
|
||||
@external tokens endTag from "./tokens.js" {
|
||||
EndTag[openedBy="StartTag StartCloseTag"]
|
||||
SelfClosingEndTag[openedBy=StartTag,@dialect=selfClosing]
|
||||
}
|
||||
|
||||
@external tokens tagStart from "./tokens.js" {
|
||||
StartTag[closedBy="EndTag SelfClosingEndTag"],
|
||||
StartScriptTag[@name=StartTag,closedBy=EndTag],
|
||||
StartStyleTag[@name=StartTag,closedBy=EndTag],
|
||||
StartTextareaTag[@name=StartTag,closedBy=EndTag],
|
||||
StartSelfClosingTag[@name=StartTag,closedBy=EndTag],
|
||||
StartCloseTag[closedBy=EndTag],
|
||||
NoMatchStartCloseTag[@name=StartCloseTag,closedBy=EndTag]
|
||||
MismatchedStartCloseTag[@name=StartCloseTag,closedBy=EndTag],
|
||||
missingCloseTag,
|
||||
IncompleteTag,
|
||||
IncompleteCloseTag
|
||||
}
|
||||
|
||||
@external tokens commentContent from "./tokens.js" {
|
||||
commentContent
|
||||
}
|
||||
|
||||
@tokens {
|
||||
nameStart {
|
||||
":" | @asciiLetter | "_" |
|
||||
$[\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D] |
|
||||
$[\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u{10000}-\u{EFFFF}]
|
||||
}
|
||||
|
||||
nameChar {
|
||||
nameStart | "-" | "." | @digit | $[\u00B7\u0300-\u036F\u203F-\u2040]
|
||||
}
|
||||
|
||||
identifier { nameStart nameChar* }
|
||||
|
||||
TagName { identifier }
|
||||
|
||||
AttributeName { ![\u0000-\u0020\u007F-\u009F"'<>/=\uFDD0-\uFDEF\uFFFE\uFFFF]+ }
|
||||
|
||||
UnquotedAttributeValue[isolate] { ![ \t\n\r\u000C=<>"'`]+ }
|
||||
|
||||
attributeContentDouble { !["&]+ }
|
||||
|
||||
attributeContentSingle { !['&]+ }
|
||||
|
||||
Is { "=" }
|
||||
|
||||
EntityReference { "&" ![#; ]+ ";" }
|
||||
|
||||
CharacterReference { "&#" ![; ]+ ";" }
|
||||
|
||||
InvalidEntity { "&" }
|
||||
|
||||
@precedence { CharacterReference, EntityReference, InvalidEntity }
|
||||
|
||||
Text[group=TextContent] { ![<&]+ }
|
||||
|
||||
commentStart { "<!--" }
|
||||
commentEnd { "-->" }
|
||||
|
||||
ProcessingInst { "<?" piContent }
|
||||
|
||||
piContent { ![?] piContent | "?" piQuestion }
|
||||
piQuestion { ![>] piContent | ">" }
|
||||
|
||||
DoctypeDecl { "<!" ("doctype" | "DOCTYPE") ![>]* ">" }
|
||||
|
||||
@precedence { commentStart, ProcessingInst, DoctypeDecl }
|
||||
|
||||
space { (" " | "\t" | "\r" | "\n")+ }
|
||||
}
|
||||
|
||||
@external propSource htmlHighlighting from "./highlight"
|
||||
2
frontend/node_modules/@lezer/html/src/index.js
generated
vendored
Normal file
2
frontend/node_modules/@lezer/html/src/index.js
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export {parser} from "./parser"
|
||||
export {configureNesting} from "./content"
|
||||
27
frontend/node_modules/@lezer/html/src/parser.js
generated
vendored
Normal file
27
frontend/node_modules/@lezer/html/src/parser.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
53
frontend/node_modules/@lezer/html/src/parser.terms.js
generated
vendored
Normal file
53
frontend/node_modules/@lezer/html/src/parser.terms.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
// This file was generated by lezer-generator. You probably shouldn't edit it.
|
||||
export const
|
||||
scriptText = 55,
|
||||
StartCloseScriptTag = 1,
|
||||
styleText = 56,
|
||||
StartCloseStyleTag = 2,
|
||||
textareaText = 57,
|
||||
StartCloseTextareaTag = 3,
|
||||
EndTag = 4,
|
||||
SelfClosingEndTag = 5,
|
||||
StartTag = 6,
|
||||
StartScriptTag = 7,
|
||||
StartStyleTag = 8,
|
||||
StartTextareaTag = 9,
|
||||
StartSelfClosingTag = 10,
|
||||
StartCloseTag = 11,
|
||||
NoMatchStartCloseTag = 12,
|
||||
MismatchedStartCloseTag = 13,
|
||||
missingCloseTag = 58,
|
||||
IncompleteTag = 14,
|
||||
IncompleteCloseTag = 15,
|
||||
commentContent = 59,
|
||||
Document = 16,
|
||||
Text = 17,
|
||||
EntityReference = 18,
|
||||
CharacterReference = 19,
|
||||
InvalidEntity = 20,
|
||||
Element = 21,
|
||||
OpenScriptTag = 22,
|
||||
TagName = 23,
|
||||
Attribute = 24,
|
||||
AttributeName = 25,
|
||||
Is = 26,
|
||||
AttributeValue = 27,
|
||||
UnquotedAttributeValue = 28,
|
||||
ScriptText = 29,
|
||||
CloseScriptTag = 30,
|
||||
OpenStyleTag = 31,
|
||||
StyleText = 32,
|
||||
CloseStyleTag = 33,
|
||||
OpenTextareaTag = 34,
|
||||
TextareaText = 35,
|
||||
CloseTextareaTag = 36,
|
||||
OpenTag = 37,
|
||||
CloseTag = 38,
|
||||
SelfClosingTag = 39,
|
||||
Comment = 40,
|
||||
ProcessingInst = 41,
|
||||
MismatchedCloseTag = 42,
|
||||
NoMatchCloseTag = 43,
|
||||
DoctypeDecl = 44,
|
||||
Dialect_noMatch = 0,
|
||||
Dialect_selfClosing = 1
|
||||
199
frontend/node_modules/@lezer/html/src/tokens.js
generated
vendored
Normal file
199
frontend/node_modules/@lezer/html/src/tokens.js
generated
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
/* Hand-written tokenizers for HTML. */
|
||||
|
||||
import {ExternalTokenizer, ContextTracker} from "@lezer/lr"
|
||||
import {StartTag, StartCloseTag, NoMatchStartCloseTag, MismatchedStartCloseTag, missingCloseTag,
|
||||
StartSelfClosingTag, IncompleteCloseTag, Element, OpenTag, IncompleteTag,
|
||||
StartScriptTag, scriptText, StartCloseScriptTag,
|
||||
StartStyleTag, styleText, StartCloseStyleTag,
|
||||
StartTextareaTag, textareaText, StartCloseTextareaTag,
|
||||
Dialect_noMatch, Dialect_selfClosing, EndTag, SelfClosingEndTag,
|
||||
commentContent as cmntContent} from "./parser.terms.js"
|
||||
|
||||
const selfClosers = {
|
||||
area: true, base: true, br: true, col: true, command: true,
|
||||
embed: true, frame: true, hr: true, img: true, input: true,
|
||||
keygen: true, link: true, meta: true, param: true, source: true,
|
||||
track: true, wbr: true, menuitem: true
|
||||
}
|
||||
|
||||
const implicitlyClosed = {
|
||||
dd: true, li: true, optgroup: true, option: true, p: true,
|
||||
rp: true, rt: true, tbody: true, td: true, tfoot: true,
|
||||
th: true, tr: true
|
||||
}
|
||||
|
||||
const closeOnOpen = {
|
||||
dd: {dd: true, dt: true},
|
||||
dt: {dd: true, dt: true},
|
||||
li: {li: true},
|
||||
option: {option: true, optgroup: true},
|
||||
optgroup: {optgroup: true},
|
||||
p: {
|
||||
address: true, article: true, aside: true, blockquote: true, dir: true,
|
||||
div: true, dl: true, fieldset: true, footer: true, form: true,
|
||||
h1: true, h2: true, h3: true, h4: true, h5: true, h6: true,
|
||||
header: true, hgroup: true, hr: true, menu: true, nav: true, ol: true,
|
||||
p: true, pre: true, section: true, table: true, ul: true
|
||||
},
|
||||
rp: {rp: true, rt: true},
|
||||
rt: {rp: true, rt: true},
|
||||
tbody: {tbody: true, tfoot: true},
|
||||
td: {td: true, th: true},
|
||||
tfoot: {tbody: true},
|
||||
th: {td: true, th: true},
|
||||
thead: {tbody: true, tfoot: true},
|
||||
tr: {tr: true}
|
||||
}
|
||||
|
||||
function nameChar(ch) {
|
||||
return ch == 45 || ch == 46 || ch == 58 || ch >= 65 && ch <= 90 || ch == 95 || ch >= 97 && ch <= 122 || ch >= 161
|
||||
}
|
||||
|
||||
function isSpace(ch) {
|
||||
return ch == 9 || ch == 10 || ch == 13 || ch == 32
|
||||
}
|
||||
|
||||
let cachedName = null, cachedInput = null, cachedPos = 0
|
||||
function tagNameAfter(input, offset) {
|
||||
let pos = input.pos + offset
|
||||
if (cachedPos == pos && cachedInput == input) return cachedName
|
||||
let next = input.peek(offset), name = ""
|
||||
for (;;) {
|
||||
if (!nameChar(next)) break
|
||||
name += String.fromCharCode(next)
|
||||
next = input.peek(++offset)
|
||||
}
|
||||
// Undefined to signal there's a <? or <!, null for just missing
|
||||
cachedInput = input; cachedPos = pos
|
||||
return cachedName = name ? name.toLowerCase() : next == question || next == bang ? undefined : null
|
||||
}
|
||||
|
||||
const lessThan = 60, greaterThan = 62, slash = 47, question = 63, bang = 33, dash = 45
|
||||
|
||||
function ElementContext(name, parent) {
|
||||
this.name = name
|
||||
this.parent = parent
|
||||
}
|
||||
|
||||
const startTagTerms = [StartTag, StartSelfClosingTag, StartScriptTag, StartStyleTag, StartTextareaTag]
|
||||
|
||||
export const elementContext = new ContextTracker({
|
||||
start: null,
|
||||
shift(context, term, stack, input) {
|
||||
return startTagTerms.indexOf(term) > -1 ? new ElementContext(tagNameAfter(input, 1) || "", context) : context
|
||||
},
|
||||
reduce(context, term) {
|
||||
return term == Element && context ? context.parent : context
|
||||
},
|
||||
reuse(context, node, stack, input) {
|
||||
let type = node.type.id
|
||||
return type == StartTag || type == OpenTag
|
||||
? new ElementContext(tagNameAfter(input, 1) || "", context) : context
|
||||
},
|
||||
strict: false
|
||||
})
|
||||
|
||||
export const tagStart = new ExternalTokenizer((input, stack) => {
|
||||
if (input.next != lessThan) {
|
||||
// End of file, close any open tags
|
||||
if (input.next < 0 && stack.context) input.acceptToken(missingCloseTag)
|
||||
return
|
||||
}
|
||||
input.advance()
|
||||
let close = input.next == slash
|
||||
if (close) input.advance()
|
||||
let name = tagNameAfter(input, 0)
|
||||
if (name === undefined) return
|
||||
if (!name) return input.acceptToken(close ? IncompleteCloseTag : IncompleteTag)
|
||||
|
||||
let parent = stack.context ? stack.context.name : null
|
||||
if (close) {
|
||||
if (name == parent) return input.acceptToken(StartCloseTag)
|
||||
if (parent && implicitlyClosed[parent]) return input.acceptToken(missingCloseTag, -2)
|
||||
if (stack.dialectEnabled(Dialect_noMatch)) return input.acceptToken(NoMatchStartCloseTag)
|
||||
for (let cx = stack.context; cx; cx = cx.parent) if (cx.name == name) return
|
||||
input.acceptToken(MismatchedStartCloseTag)
|
||||
} else {
|
||||
if (name == "script") return input.acceptToken(StartScriptTag)
|
||||
if (name == "style") return input.acceptToken(StartStyleTag)
|
||||
if (name == "textarea") return input.acceptToken(StartTextareaTag)
|
||||
if (selfClosers.hasOwnProperty(name)) return input.acceptToken(StartSelfClosingTag)
|
||||
if (parent && closeOnOpen[parent] && closeOnOpen[parent][name]) input.acceptToken(missingCloseTag, -1)
|
||||
else input.acceptToken(StartTag)
|
||||
}
|
||||
}, {contextual: true})
|
||||
|
||||
export const commentContent = new ExternalTokenizer(input => {
|
||||
for (let dashes = 0, i = 0;; i++) {
|
||||
if (input.next < 0) {
|
||||
if (i) input.acceptToken(cmntContent)
|
||||
break
|
||||
}
|
||||
if (input.next == dash) {
|
||||
dashes++
|
||||
} else if (input.next == greaterThan && dashes >= 2) {
|
||||
if (i >= 3) input.acceptToken(cmntContent, -2)
|
||||
break
|
||||
} else {
|
||||
dashes = 0
|
||||
}
|
||||
input.advance()
|
||||
}
|
||||
})
|
||||
|
||||
function inForeignElement(context) {
|
||||
for (; context; context = context.parent)
|
||||
if (context.name == "svg" || context.name == "math") return true
|
||||
return false
|
||||
}
|
||||
|
||||
export const endTag = new ExternalTokenizer((input, stack) => {
|
||||
if (input.next == slash && input.peek(1) == greaterThan) {
|
||||
let selfClosing = stack.dialectEnabled(Dialect_selfClosing) || inForeignElement(stack.context)
|
||||
input.acceptToken(selfClosing ? SelfClosingEndTag : EndTag, 2)
|
||||
} else if (input.next == greaterThan) {
|
||||
input.acceptToken(EndTag, 1)
|
||||
}
|
||||
})
|
||||
|
||||
function contentTokenizer(tag, textToken, endToken) {
|
||||
let lastState = 2 + tag.length
|
||||
return new ExternalTokenizer(input => {
|
||||
// state means:
|
||||
// - 0 nothing matched
|
||||
// - 1 '<' matched
|
||||
// - 2 '</'
|
||||
// - 3-(1+tag.length) part of the tag matched
|
||||
// - lastState whole tag + possibly whitespace matched
|
||||
for (let state = 0, matchedLen = 0, i = 0;; i++) {
|
||||
if (input.next < 0) {
|
||||
if (i) input.acceptToken(textToken)
|
||||
break
|
||||
}
|
||||
if (state == 0 && input.next == lessThan ||
|
||||
state == 1 && input.next == slash ||
|
||||
state >= 2 && state < lastState && input.next == tag.charCodeAt(state - 2)) {
|
||||
state++
|
||||
matchedLen++
|
||||
} else if (state == lastState && input.next == greaterThan) {
|
||||
if (i > matchedLen)
|
||||
input.acceptToken(textToken, -matchedLen)
|
||||
else
|
||||
input.acceptToken(endToken, -(matchedLen - 2))
|
||||
break
|
||||
} else if ((input.next == 10 /* '\n' */ || input.next == 13 /* '\r' */) && i) {
|
||||
input.acceptToken(textToken, 1)
|
||||
break
|
||||
} else {
|
||||
state = matchedLen = 0
|
||||
}
|
||||
input.advance()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const scriptTokens = contentTokenizer("script", scriptText, StartCloseScriptTag)
|
||||
|
||||
export const styleTokens = contentTokenizer("style", styleText, StartCloseStyleTag)
|
||||
|
||||
export const textareaTokens = contentTokenizer("textarea", textareaText, StartCloseTextareaTag)
|
||||
69
frontend/node_modules/@lezer/html/test/mixed.txt
generated
vendored
Normal file
69
frontend/node_modules/@lezer/html/test/mixed.txt
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
# Doesn't parse VB as JS
|
||||
|
||||
<script type="text/visualbasic">let something = 20</script>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,Attribute(AttributeName,Is,AttributeValue),EndTag),
|
||||
ScriptText,
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Does parse type-less script tags as JS
|
||||
|
||||
<script>/foo/</script>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Script(ExpressionStatement(RegExp)),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Still doesn't end script tags on closing tags
|
||||
|
||||
<script type=something></foo></script>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,Attribute(AttributeName,Is,UnquotedAttributeValue),EndTag),
|
||||
ScriptText,
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Missing end tag
|
||||
|
||||
<html><script>null
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Script(ExpressionStatement(null)))))
|
||||
|
||||
# JS with script type
|
||||
|
||||
<script type="text/javascript">console.log(2)</script>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,Attribute(AttributeName,Is,AttributeValue),EndTag),
|
||||
Script(...),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# JS with unquoted script type
|
||||
|
||||
<script type=module>console.log(2)</script>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,Attribute(AttributeName,Is,UnquotedAttributeValue),EndTag),
|
||||
Script(...),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Error in JS
|
||||
|
||||
<script>a b</script>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Script(...),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
370
frontend/node_modules/@lezer/html/test/tags.txt
generated
vendored
Normal file
370
frontend/node_modules/@lezer/html/test/tags.txt
generated
vendored
Normal file
@ -0,0 +1,370 @@
|
||||
# Regular tag
|
||||
|
||||
<foo>bar</foo>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Nested tag
|
||||
|
||||
<a><b>c</b><br></a>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)),
|
||||
Element(SelfClosingTag(StartTag,TagName,EndTag)),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Attribute
|
||||
|
||||
<br foo="bar">
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName,Is,AttributeValue),EndTag)))
|
||||
|
||||
# Multiple attributes
|
||||
|
||||
<a x="one" y="two" z="three"></a>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,
|
||||
Attribute(AttributeName,Is,AttributeValue),
|
||||
Attribute(AttributeName,Is,AttributeValue),
|
||||
Attribute(AttributeName,Is,AttributeValue),EndTag),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Value-less attributes
|
||||
|
||||
<a x y="one" z></a>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,
|
||||
Attribute(AttributeName),
|
||||
Attribute(AttributeName,Is,AttributeValue),
|
||||
Attribute(AttributeName),EndTag),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Unquoted attributes
|
||||
|
||||
<a x=one y z=two></a>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,
|
||||
Attribute(AttributeName,Is,UnquotedAttributeValue),
|
||||
Attribute(AttributeName),
|
||||
Attribute(AttributeName,Is,UnquotedAttributeValue),EndTag),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Unquoted attributes with slashes
|
||||
|
||||
<link as=font crossorigin=anonymous href=/fonts/google-sans/regular/latin.woff2 rel=preload>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(SelfClosingTag(StartTag,TagName,
|
||||
Attribute(AttributeName,Is,UnquotedAttributeValue),
|
||||
Attribute(AttributeName,Is,UnquotedAttributeValue),
|
||||
Attribute(AttributeName,Is,UnquotedAttributeValue),
|
||||
Attribute(AttributeName,Is,UnquotedAttributeValue),
|
||||
EndTag)))
|
||||
|
||||
# Single-quoted attributes
|
||||
|
||||
<link x='one' z='two&'>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(SelfClosingTag(StartTag, TagName,
|
||||
Attribute(AttributeName, Is, AttributeValue),
|
||||
Attribute(AttributeName, Is, AttributeValue(EntityReference)),
|
||||
EndTag)))
|
||||
|
||||
# Entities
|
||||
|
||||
<a attr="one&two">&C</a>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,
|
||||
Attribute(AttributeName,Is,AttributeValue(EntityReference)),EndTag),
|
||||
EntityReference,CharacterReference,
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Doctype
|
||||
|
||||
<!doctype html>
|
||||
<doc></doc>
|
||||
|
||||
==>
|
||||
|
||||
Document(DoctypeDecl,Text,Element(OpenTag(StartTag,TagName,EndTag),CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Processing instructions
|
||||
|
||||
<?foo?><bar><?baz?></bar>
|
||||
|
||||
==>
|
||||
|
||||
Document(ProcessingInst,Element(OpenTag(StartTag,TagName,EndTag),ProcessingInst,CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Comments
|
||||
|
||||
<!-- top comment -->
|
||||
<element><!-- inner comment --> text</element>
|
||||
<!---->
|
||||
<!--
|
||||
-->
|
||||
|
||||
==>
|
||||
|
||||
Document(Comment,Text,Element(OpenTag(StartTag,TagName,EndTag),Comment,Text,CloseTag(StartCloseTag,TagName,EndTag)),Text,Comment,Text,Comment)
|
||||
|
||||
# Mismatched tag
|
||||
|
||||
<a></b>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),MismatchedCloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Unclosed tag
|
||||
|
||||
<a>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag)))
|
||||
|
||||
# Ignore pseudo-xml self-closers
|
||||
|
||||
<br/>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(SelfClosingTag(StartTag,TagName,EndTag)))
|
||||
|
||||
# Unclosed implicitly closed tag
|
||||
|
||||
<p>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag)))
|
||||
|
||||
# Nested mismatched tag
|
||||
|
||||
<a><b><c></c></x></a>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Element(OpenTag(StartTag,TagName,EndTag),CloseTag(StartCloseTag,TagName,EndTag)),
|
||||
MismatchedCloseTag(StartCloseTag,TagName,EndTag),
|
||||
⚠),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Incomplete close tag
|
||||
|
||||
<html><body></</html>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Element(OpenTag(StartTag,TagName,EndTag), IncompleteCloseTag, ⚠),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Re-synchronize close tags
|
||||
|
||||
<a><b><c></x></c></a>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Element(OpenTag(StartTag,TagName,EndTag),
|
||||
MismatchedCloseTag(StartCloseTag,TagName,EndTag),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)),
|
||||
⚠),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Top-level mismatched close tag
|
||||
|
||||
<a></a></a>
|
||||
|
||||
==>
|
||||
|
||||
Document(
|
||||
Element(OpenTag(StartTag,TagName,EndTag),CloseTag(StartCloseTag,TagName,EndTag)),
|
||||
MismatchedCloseTag(StartCloseTag,TagName,EndTag))
|
||||
|
||||
# Self-closing tags
|
||||
|
||||
<a><img src=blah></a>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName,Is,UnquotedAttributeValue),EndTag)),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Implicitly closed
|
||||
|
||||
<dl><dd>Hello</dl>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Element(OpenTag(StartTag,TagName,EndTag),Text),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Closed by sibling
|
||||
|
||||
<div>
|
||||
<p>Foo
|
||||
<p>Bar
|
||||
</div>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Text,
|
||||
Element(OpenTag(StartTag,TagName,EndTag),Text),
|
||||
Element(OpenTag(StartTag,TagName,EndTag),Text),
|
||||
CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Closed by sibling at top
|
||||
|
||||
<p>Foo
|
||||
<p>Bar
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),Text),Element(OpenTag(StartTag,TagName,EndTag),Text))
|
||||
|
||||
# Textarea
|
||||
|
||||
<p>Enter something: <textarea code-lang=javascript>function foo() {
|
||||
return "</bar>"
|
||||
}</textarea>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),
|
||||
Text,
|
||||
Element(OpenTag(StartTag,TagName,Attribute(AttributeName,Is,UnquotedAttributeValue),EndTag),
|
||||
TextareaText,
|
||||
CloseTag(StartCloseTag,TagName,EndTag))))
|
||||
|
||||
# Script
|
||||
|
||||
<script>This is not an entity: <</script>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),ScriptText,CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Doesn't get confused by a stray ampersand
|
||||
|
||||
<html>a&b</html>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),Text,InvalidEntity,Text,CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Can ignore mismatches {"dialect": "noMatch"}
|
||||
|
||||
<div>foo</p>
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))
|
||||
|
||||
# Can handle lone close tags {"dialect": "noMatch"}
|
||||
|
||||
</strong>
|
||||
|
||||
==>
|
||||
|
||||
Document(CloseTag(StartCloseTag,TagName,EndTag))
|
||||
|
||||
# Parses ampersands in attributes
|
||||
|
||||
<img src="foo&bar">
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(SelfClosingTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue(InvalidEntity)), EndTag)))
|
||||
|
||||
# Supports self-closing dialect {"dialect": "selfClosing"}
|
||||
|
||||
<section><image id=i2 /></section>
|
||||
|
||||
==>
|
||||
|
||||
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
|
||||
|
||||
<div><svg><circle/></svg></div>
|
||||
|
||||
==>
|
||||
|
||||
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
|
||||
|
||||
<div
|
||||
<div
|
||||
<div
|
||||
|
||||
==>
|
||||
|
||||
Document(Element(OpenTag(StartTag,TagName,⚠),
|
||||
Element(OpenTag(StartTag,TagName,⚠),
|
||||
Element(OpenTag(StartTag,TagName,⚠),⚠),⚠),⚠))
|
||||
|
||||
# Allows self-closing on special tags {"dialect": "selfClosing"}
|
||||
|
||||
<body>
|
||||
<br/>
|
||||
<textarea/>
|
||||
<script/>
|
||||
<style/>
|
||||
</body>
|
||||
|
||||
==>
|
||||
|
||||
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)))
|
||||
|
||||
# Only treats less-than as opening a tag when followed by a name
|
||||
|
||||
< div>x
|
||||
|
||||
==>
|
||||
|
||||
Document(IncompleteTag,Text)
|
||||
29
frontend/node_modules/@lezer/html/test/test-html.js
generated
vendored
Normal file
29
frontend/node_modules/@lezer/html/test/test-html.js
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
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))
|
||||
})
|
||||
}
|
||||
|
||||
97
frontend/node_modules/@lezer/html/test/test-incremental.js
generated
vendored
Normal file
97
frontend/node_modules/@lezer/html/test/test-incremental.js
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
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 += "<!doctype html>"
|
||||
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 += `<img>`
|
||||
} else if (sel == 11) {
|
||||
doc += "<script>a()</script>"
|
||||
} 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("<code><code>mgnbni</code></code>", ["del", 29])
|
||||
})
|
||||
|
||||
it("can handle a renamed opening tag after a self-closing", () => {
|
||||
check("<p>one two three four five six seven<p>eight", ["replace", 37, "a"])
|
||||
})
|
||||
|
||||
it("is okay with nameless elements", () => {
|
||||
check("<body><code><img></code><>body>", ["replace", 14, ">"])
|
||||
check("abcde<>fghij<", ["replace", 12, ">"])
|
||||
})
|
||||
|
||||
it("doesn't get confused by an invalid close tag receiving a matching open tag", () => {
|
||||
check("<div><p>foo</body>", ["insert", 0, "<body>"])
|
||||
})
|
||||
})
|
||||
56
frontend/node_modules/@lezer/html/test/vue.txt
generated
vendored
Normal file
56
frontend/node_modules/@lezer/html/test/vue.txt
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
# Parses Vue builtin directives
|
||||
|
||||
<span v-text="msg"></span>
|
||||
|
||||
==>
|
||||
|
||||
Document(
|
||||
Element(
|
||||
OpenTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue), EndTag),
|
||||
CloseTag(StartCloseTag, TagName, EndTag)))
|
||||
|
||||
# Parses Vue :is shorthand syntax
|
||||
|
||||
<Component :is="view"></Component>
|
||||
|
||||
==>
|
||||
|
||||
Document(
|
||||
Element(
|
||||
OpenTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue),EndTag),
|
||||
CloseTag(StartCloseTag, TagName, EndTag)))
|
||||
|
||||
# Parses Vue @click shorthand syntax
|
||||
|
||||
<button @click="handler()">Click me</button>
|
||||
|
||||
==>
|
||||
|
||||
Document(
|
||||
Element(
|
||||
OpenTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue), EndTag),
|
||||
Text,
|
||||
CloseTag(StartCloseTag, TagName, EndTag)))
|
||||
|
||||
# Parses Vue @submit.prevent shorthand syntax
|
||||
|
||||
<form @submit.prevent="onSubmit"></form>
|
||||
|
||||
==>
|
||||
|
||||
Document(
|
||||
Element(
|
||||
OpenTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue), EndTag),
|
||||
CloseTag(StartCloseTag, TagName, EndTag)))
|
||||
|
||||
# Parses Vue Dynamic Arguments
|
||||
|
||||
<a v-bind:[attributeName]="url">Link</a>
|
||||
|
||||
==>
|
||||
|
||||
Document(
|
||||
Element(
|
||||
OpenTag(StartTag, TagName, Attribute(AttributeName, Is, AttributeValue), EndTag),
|
||||
Text,
|
||||
CloseTag(StartCloseTag, TagName, EndTag)))
|
||||
Reference in New Issue
Block a user