From d10edbc5f88edcc296f44a87f24ce98922477df4 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Wed, 19 Aug 2026 07:42:07 +0200 Subject: [PATCH] fix(highlight): vendor pure-Lezer Svelte parser (#3534) * fix(highlight): vendor pure-Lezer Svelte parser Replace @replit/codemirror-lang-svelte with a vendored, pure-Lezer Svelte parser so the daemon and desktop app stop pulling the interactive CodeMirror editor runtime. @replit/codemirror-lang-svelte executes EditorView.inputHandler and HTML autocompletion at module load and depends on @codemirror/view, @codemirror/state, and @codemirror/lang-* as peers. Those peers were not declared by @getpaseo/highlight, so electron-builder omitted them from app.asar and the daemon crashed on startup with ERR_MODULE_NOT_FOUND: Cannot find package '@codemirror/lang-css'. The vendored parser uses only @lezer/lr, @lezer/common, @lezer/highlight, @lezer/javascript, and @lezer/css, with @codemirror/language kept for the existing Language wrapper. Drops the now-unused @codemirror/autocomplete dependency and adds @lezer/lr as a direct dependency. * fix(nix): update npm-deps hash for vendored Svelte parser --- nix/npm-deps.hash | 2 +- package-lock.json | 159 ++---- packages/highlight/package.json | 3 +- packages/highlight/src/parsers.ts | 5 +- packages/highlight/src/svelte/highlight.ts | 54 ++ packages/highlight/src/svelte/nesting.ts | 106 ++++ packages/highlight/src/svelte/parser.ts | 218 +++++++++ packages/highlight/src/svelte/terms.ts | 23 + packages/highlight/src/svelte/tokens.ts | 545 +++++++++++++++++++++ 9 files changed, 1004 insertions(+), 111 deletions(-) create mode 100644 packages/highlight/src/svelte/highlight.ts create mode 100644 packages/highlight/src/svelte/nesting.ts create mode 100644 packages/highlight/src/svelte/parser.ts create mode 100644 packages/highlight/src/svelte/terms.ts create mode 100644 packages/highlight/src/svelte/tokens.ts diff --git a/nix/npm-deps.hash b/nix/npm-deps.hash index 2bc240e14..739af5ec6 100644 --- a/nix/npm-deps.hash +++ b/nix/npm-deps.hash @@ -1 +1 @@ -sha256-2TmrD5JqI4AQSbngbTOfOnR+Z6Gmk3bxC7Bif+FN7jM= +sha256-NyHZR53Y2lZP0eRe068qED1PhB6qPYnSOblFO9NRAKM= diff --git a/package-lock.json b/package-lock.json index 27d33df12..393bb9f0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2554,6 +2554,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.3.tgz", "integrity": "sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -2573,54 +2574,6 @@ "@lezer/common": "^1.1.0" } }, - "node_modules/@codemirror/lang-css": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", - "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@lezer/common": "^1.0.2", - "@lezer/css": "^1.1.7" - } - }, - "node_modules/@codemirror/lang-html": { - "version": "6.4.12", - "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.12.tgz", - "integrity": "sha512-pw2ReWKUqSkbvh76RAT4NYxiogRu+PWkR2ukAwO9uOgrm8uipkzjtKKtNpyeAQwHOqxEeSvAXZ6vr3AfyB9y/w==", - "license": "MIT", - "peer": true, - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/lang-css": "^6.0.0", - "@codemirror/lang-javascript": "^6.0.0", - "@codemirror/language": "^6.4.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0", - "@lezer/css": "^1.1.0", - "@lezer/html": "^1.3.12" - } - }, - "node_modules/@codemirror/lang-javascript": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.5.tgz", - "integrity": "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==", - "license": "MIT", - "peer": true, - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.6.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0", - "@lezer/javascript": "^1.0.0" - } - }, "node_modules/@codemirror/language": { "version": "6.12.4", "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.4.tgz", @@ -2644,18 +2597,6 @@ "@codemirror/language": "^6.0.0" } }, - "node_modules/@codemirror/lint": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.7.tgz", - "integrity": "sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.42.0", - "crelt": "^1.0.5" - } - }, "node_modules/@codemirror/search": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.7.1.tgz", @@ -11229,25 +11170,6 @@ "@lezer/lr": "^1.0.0" } }, - "node_modules/@replit/codemirror-lang-svelte": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-svelte/-/codemirror-lang-svelte-6.0.0.tgz", - "integrity": "sha512-U2OqqgMM6jKelL0GNWbAmqlu1S078zZNoBqlJBW+retTc5M4Mha6/Y2cf4SVg6ddgloJvmcSpt4hHrVoM4ePRA==", - "license": "MIT", - "peerDependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/lang-css": "^6.0.1", - "@codemirror/lang-html": "^6.2.0", - "@codemirror/lang-javascript": "^6.1.1", - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0", - "@lezer/javascript": "^1.2.0", - "@lezer/lr": "^1.0.0" - } - }, "node_modules/@replit/codemirror-vim": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/@replit/codemirror-vim/-/codemirror-vim-6.3.0.tgz", @@ -11302,7 +11224,8 @@ "optional": true, "os": [ "android" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-android-arm64": { "version": "4.59.0", @@ -11315,7 +11238,8 @@ "optional": true, "os": [ "android" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.59.0", @@ -11328,7 +11252,8 @@ "optional": true, "os": [ "darwin" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-darwin-x64": { "version": "4.59.0", @@ -11341,7 +11266,8 @@ "optional": true, "os": [ "darwin" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-freebsd-arm64": { "version": "4.59.0", @@ -11354,7 +11280,8 @@ "optional": true, "os": [ "freebsd" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-freebsd-x64": { "version": "4.59.0", @@ -11367,7 +11294,8 @@ "optional": true, "os": [ "freebsd" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { "version": "4.59.0", @@ -11380,7 +11308,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { "version": "4.59.0", @@ -11393,7 +11322,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm64-gnu": { "version": "4.59.0", @@ -11406,7 +11336,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm64-musl": { "version": "4.59.0", @@ -11419,7 +11350,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-loong64-gnu": { "version": "4.59.0", @@ -11432,7 +11364,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-loong64-musl": { "version": "4.59.0", @@ -11445,7 +11378,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { "version": "4.59.0", @@ -11458,7 +11392,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-ppc64-musl": { "version": "4.59.0", @@ -11471,7 +11406,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { "version": "4.59.0", @@ -11484,7 +11420,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-riscv64-musl": { "version": "4.59.0", @@ -11497,7 +11434,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-s390x-gnu": { "version": "4.59.0", @@ -11510,7 +11448,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.59.0", @@ -11523,7 +11462,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-x64-musl": { "version": "4.59.0", @@ -11536,7 +11476,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-openbsd-x64": { "version": "4.59.0", @@ -11549,7 +11490,8 @@ "optional": true, "os": [ "openbsd" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-openharmony-arm64": { "version": "4.59.0", @@ -11562,7 +11504,8 @@ "optional": true, "os": [ "openharmony" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-arm64-msvc": { "version": "4.59.0", @@ -11575,7 +11518,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-ia32-msvc": { "version": "4.59.0", @@ -11588,7 +11532,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-x64-gnu": { "version": "4.59.0", @@ -11601,7 +11546,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-x64-msvc": { "version": "4.59.0", @@ -11614,7 +11560,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rtsao/scc": { "version": "1.1.0", @@ -19208,6 +19155,7 @@ "dev": true, "license": "BSD-3-Clause", "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -38694,7 +38642,6 @@ "name": "@getpaseo/highlight", "version": "0.4.0", "dependencies": { - "@codemirror/autocomplete": "6.20.3", "@codemirror/language": "6.12.4", "@codemirror/legacy-modes": "^6.5.3", "@lezer/common": "^1.5.0", @@ -38706,6 +38653,7 @@ "@lezer/java": "^1.1.3", "@lezer/javascript": "^1.5.4", "@lezer/json": "^1.0.3", + "@lezer/lr": "^1.4.8", "@lezer/markdown": "^1.6.2", "@lezer/php": "^1.0.5", "@lezer/python": "^1.1.18", @@ -38714,7 +38662,6 @@ "@lezer/yaml": "^1.0.4", "@replit/codemirror-lang-csharp": "^6.2.0", "@replit/codemirror-lang-nix": "^6.0.1", - "@replit/codemirror-lang-svelte": "^6.0.0", "lezer-elixir": "^1.1.2" }, "devDependencies": { diff --git a/packages/highlight/package.json b/packages/highlight/package.json index 9bb454fba..a13f1675f 100644 --- a/packages/highlight/package.json +++ b/packages/highlight/package.json @@ -27,7 +27,6 @@ "typecheck": "tsgo --noEmit" }, "dependencies": { - "@codemirror/autocomplete": "6.20.3", "@codemirror/language": "6.12.4", "@codemirror/legacy-modes": "^6.5.3", "@lezer/common": "^1.5.0", @@ -39,6 +38,7 @@ "@lezer/java": "^1.1.3", "@lezer/javascript": "^1.5.4", "@lezer/json": "^1.0.3", + "@lezer/lr": "^1.4.8", "@lezer/markdown": "^1.6.2", "@lezer/php": "^1.0.5", "@lezer/python": "^1.1.18", @@ -47,7 +47,6 @@ "@lezer/yaml": "^1.0.4", "@replit/codemirror-lang-csharp": "^6.2.0", "@replit/codemirror-lang-nix": "^6.0.1", - "@replit/codemirror-lang-svelte": "^6.0.0", "lezer-elixir": "^1.1.2" }, "devDependencies": { diff --git a/packages/highlight/src/parsers.ts b/packages/highlight/src/parsers.ts index b28a0e53a..d6537ebc9 100644 --- a/packages/highlight/src/parsers.ts +++ b/packages/highlight/src/parsers.ts @@ -16,9 +16,10 @@ import { parser as xmlParser } from "@lezer/xml"; import { parser as yamlParser } from "@lezer/yaml"; import { csharpLanguage } from "@replit/codemirror-lang-csharp"; import { nixLanguage } from "@replit/codemirror-lang-nix"; -import { svelteLanguage } from "@replit/codemirror-lang-svelte"; import { parser as elixirParser } from "lezer-elixir"; import type { Parser } from "@lezer/common"; +import { parser as svelteBaseParser } from "./svelte/parser.js"; +import { configureNesting, defaultNesting } from "./svelte/nesting.js"; function language(parser: Parser): Language { return new Language(defineLanguageFacet(), parser); @@ -51,7 +52,7 @@ const languagesByExtension: Record = { html: language(htmlParser), htm: language(htmlParser), // Svelte - svelte: svelteLanguage, + svelte: language(svelteBaseParser.configure({ wrap: configureNesting(defaultNesting) })), // XML xml: language(xmlParser), // Java diff --git a/packages/highlight/src/svelte/highlight.ts b/packages/highlight/src/svelte/highlight.ts new file mode 100644 index 000000000..356f319b7 --- /dev/null +++ b/packages/highlight/src/svelte/highlight.ts @@ -0,0 +1,54 @@ +import { styleTags, tags as t } from "@lezer/highlight"; + +export const svelteHighlighting = styleTags({ + "Text RawText": t.content, + "StartTag StartCloseTag SelfClosingEndTag EndTag": t.angleBracket, + TagName: t.tagName, + "MismatchedCloseTag/TagName": [t.tagName, t.invalid], + AttributeName: t.attributeName, + UnquotedAttributeValue: t.attributeValue, + "DoubleQuote SingleQuote AttributeValueContent": t.attributeValue, + Is: t.definitionOperator, + "EntityReference CharacterReference": t.character, + Comment: t.blockComment, + ProcessingInst: t.processingInstruction, + DoctypeDecl: t.documentMeta, + "{ }": t.bracket, + "[ ]": t.squareBracket, + "( )": t.paren, + "| , :": t.punctuation, + "...": t.derefOperator, + ComponentName: t.className, + SvelteElementNamespace: t.namespace, + SvelteElementType: t.tagName, + StyleAttributeName: t.propertyName, + BlockType: t.controlKeyword, + BlockPrefix: t.typeOperator, + "UnknownBlock/BlockType": t.invalid, + UnknownBlockContent: t.invalid, + "if then catch": t.controlKeyword, + as: t.definitionOperator, + Variable: t.variableName, + Modifier: t.modifier, + DirectlyInterpolatedAttributeValue: t.attributeValue, + "DirectiveOn/DirectiveName": t.controlKeyword, + "DirectiveOn/DirectiveTarget": t.typeName, + "DirectiveUse/DirectiveName": t.controlKeyword, + "DirectiveUse/DirectiveTarget": t.function(t.variableName), + "DirectiveBind/DirectiveName": t.controlKeyword, + "DirectiveBind/DirectiveTarget": t.variableName, + "DirectiveLet/DirectiveName": t.definitionKeyword, + "DirectiveLet/DirectiveTarget": t.definition(t.variableName), + "DirectiveTransition/DirectiveName": t.operatorKeyword, + "DirectiveTransition/DirectiveTarget": t.function(t.variableName), + "DirectiveIn/DirectiveName": t.operatorKeyword, + "DirectiveIn/DirectiveTarget": t.function(t.variableName), + "DirectiveOut/DirectiveName": t.operatorKeyword, + "DirectiveOut/DirectiveTarget": t.function(t.variableName), + "DirectiveAnimate/DirectiveName": t.operatorKeyword, + "DirectiveAnimate/DirectiveTarget": t.function(t.variableName), + "DirectiveClass/DirectiveName": t.attributeName, + "DirectiveClass/DirectiveTarget": t.variableName, + "DirectiveStyle/DirectiveName": t.attributeName, + "DirectiveStyle/DirectiveTarget": t.propertyName, +}); diff --git a/packages/highlight/src/svelte/nesting.ts b/packages/highlight/src/svelte/nesting.ts new file mode 100644 index 000000000..4b941e6f7 --- /dev/null +++ b/packages/highlight/src/svelte/nesting.ts @@ -0,0 +1,106 @@ +import { + parseMixed, + type Input, + type NestedParse, + type Parser, + type SyntaxNodeRef, +} from "@lezer/common"; +import { parser as cssParser } from "@lezer/css"; +import { parser as jsParser } from "@lezer/javascript"; +import { LongExpression, ScriptText, ShortExpression, StyleText, TextareaText } from "./terms.js"; + +export interface NestedLang { + tag: "script" | "style" | "textarea"; + attrs?: (attrs: Record) => boolean; + parser: Parser; +} + +const expressionParser = jsParser.configure({ top: "SingleExpression" }); + +export const defaultNesting: NestedLang[] = [ + { + tag: "script", + attrs: (attrs) => attrs.type === "text/typescript" || attrs.lang === "ts", + parser: jsParser.configure({ dialect: "ts" }), + }, + { + tag: "script", + attrs(attrs) { + return ( + !attrs.type || + /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i.test(attrs.type) + ); + }, + parser: jsParser, + }, + { + tag: "style", + attrs(attrs) { + return ( + (!attrs.lang || attrs.lang === "css" || attrs.lang === "scss") && + (!attrs.type || /^(text\/)?(x-)?(stylesheet|css|scss)$/i.test(attrs.type)) + ); + }, + parser: cssParser, + }, +]; + +function getAttrs(element: SyntaxNodeRef, input: Input): Record { + const attrs: Record = Object.create(null); + const firstChild = element.node.firstChild; + if (!firstChild) return attrs; + for (const att of firstChild.getChildren("Attribute")) { + const name = att.getChild("AttributeName"); + const value = att.getChild("AttributeValue") || att.getChild("UnquotedAttributeValue"); + if (name) { + const attrName = input.read(name.from, name.to); + if (!value) { + attrs[attrName] = ""; + } else if (value.name === "AttributeValue") { + attrs[attrName] = input.read(value.from + 1, value.to - 1); + } else { + attrs[attrName] = input.read(value.from, value.to); + } + } + } + return attrs; +} + +function maybeNest(node: SyntaxNodeRef, input: Input, tags: NestedLang[]): NestedParse | null { + let attrs: Record | undefined; + const parent = node.node.parent; + if (!parent) return null; + for (const tag of tags) { + if (!tag.attrs || tag.attrs(attrs || (attrs = getAttrs(parent, input)))) { + return { parser: tag.parser }; + } + } + return null; +} + +export function configureNesting(tags: NestedLang[]) { + const script: NestedLang[] = []; + const style: NestedLang[] = []; + const textarea: NestedLang[] = []; + for (const tag of tags) { + let array: NestedLang[]; + if (tag.tag === "script") { + array = script; + } else if (tag.tag === "style") { + array = style; + } else if (tag.tag === "textarea") { + array = textarea; + } else { + throw new RangeError("Only script, style, and textarea tags can host nested parsers"); + } + array.push(tag); + } + return parseMixed((node, input) => { + const id = node.type.id; + if (id === LongExpression || id === ShortExpression) return { parser: expressionParser }; + if (id === ScriptText) return maybeNest(node, input, script); + if (id === StyleText) return maybeNest(node, input, style); + if (id === TextareaText) return maybeNest(node, input, textarea); + return null; + }); +} diff --git a/packages/highlight/src/svelte/parser.ts b/packages/highlight/src/svelte/parser.ts new file mode 100644 index 000000000..6446f33a7 --- /dev/null +++ b/packages/highlight/src/svelte/parser.ts @@ -0,0 +1,218 @@ +// Generated by lezer-generator from @replit/codemirror-lang-svelte@6.0.0 +// Vendored to remove @codemirror/view and @codemirror/state DOM dependencies. +// Only pure Lezer primitives are used here. +import { LRParser } from "@lezer/lr"; +import { + commentContent, + elementContext, + longExpression, + scriptTokens, + shortExpression, + styleTokens, + tagStart, + textareaTokens, +} from "./tokens.js"; +import { svelteHighlighting } from "./highlight.js"; + +const spec_BlockPrefix: Record = { "#": 41, ":": 51, "/": 59, "@": 109 }; +const spec_BlockType = new Map([ + ["if", 44], + ["else", 52], + ["each", 64], + ["await", 82], + ["then", 90], + ["catch", 94], + ["key", 102], + ["html", 110], + ["debug", 114], + ["const", 118], +]); +const spec_identifier = new Map([ + ["if", 54], + ["as", 66], + ["then", 84], + ["catch", 86], +]); +const spec_AttributeName: Record = { + on: 313, + bind: 317, + let: 319, + class: 321, + style: 323, + use: 325, + transition: 327, + in: 329, + out: 331, + animate: 333, +}; +const spec_TagName: Record = { svelte: 243 }; + +export const parser = /*@__PURE__*/ LRParser.deserialize({ + version: 14, + states: + "DxQVO#|OOO!ZO#|O'#ClO#[O#|O'#CzO$]O#|O'#DTO%^O#|O'#D_O&_Q'[O'#DjO&mQ&jO'#DrO&rQ&jO'#EpO&wQ&jO'#EsO&|Q&jO'#EvO'XQ&jO'#E|O'^OXO'#DqO'iOYO'#DqO'tO[O'#DqO)TO#|O'#DqOOOW'#Dq'#DqO)[O&zO'#FOO&|Q&jO'#FQO&|Q&jO'#FROOOW'#Fj'#FjOOOW'#FT'#FTQVO#|OOOOOW'#FU'#FUO!ZO#|O,59WOOOW,59W,59WO)uQ'[O'#DjO#[O#|O,59fOOOW,59f,59fO)|Q'[O'#DjOOOW'#FV'#FVO$]O#|O,59oOOOW,59o,59oO*fQ'[O'#DjOOOW'#FW'#FWO%^O#|O,59yOOOW,59y,59yO*mQ'[O'#DjO+OQ&jO,5:UO+TQ,UO,5:VO+YQ,UO,59XO+hQ,UO,59}O,nQ7[O,5:^O,uQ7[O,5;[O,|Q7[O,5;_O-TO,UO'#ExOOQO'#F|'#F|O-YQ7[O,5;bO-dQ7[O,5;hOOOX'#F^'#F^O-kOXO'#EnO-vOXO,5:]OOOY'#F_'#F_O.OOYO'#EqO.ZOYO,5:]OOO['#F`'#F`O.cO[O'#EtO.nO[O,5:]O.vO#|O,5:]O&|Q&jO'#E{OOOW,5:],5:]OOO`'#Fa'#FaO.}O&zO,5;jOOOW,5;j,5;jO/VQ,UO,5;lO/[Q,UO,5;mOOOW-E9R-E9ROOOW-E9S-E9SOOOW1G.r1G.rO/aQ,UO,59`O/fQ,UO,59dOOOW1G/Q1G/QO/kQ,UO,59nOOOW-E9T-E9TOOOW1G/Z1G/ZO/pQ,UO,59tO/xQ,UO,59xOOOW-E9U-E9UOOOW1G/e1G/eO/}Q,UO,59|OOOW1G/p1G/pO0SQMhO1G/qO0[Q'[O1G.sO0aQ'|O1G/RO0fQ'|O1G/[O0kQ'[O1G/fO0pQ'[O1G/iO0uQ!LQO1G/lO0zQ'[O1G/nO1PQ$ISO'#DtOOOO'#Dz'#DzO1[O,UO'#DyOOOO'#EO'#EOO1aO,UO'#D}OOOO'#EQ'#EQO1fO,UO'#EPOOOO'#ES'#ESO1kO,UO'#EROOOO'#EU'#EUO1pO,UO'#ETOOOO'#EW'#EWO1uO,UO'#EVOOOO'#EY'#EYO1zO,UO'#EXOOOO'#E['#E[O2PO,UO'#EZOOOO'#E^'#E^O2UO,UO'#E]OOOO'#E`'#E`O2ZO,UO'#E_O2`Q7[O'#DxO3gQ7[O'#EjO4kQ7[O'#ElOOQO'#Fl'#FlOOQO'#FY'#FYO5rQ7[O1G/xOOOX1G/x1G/xOOQO'#Fm'#FmO5yQ7[O1G0vOOOY1G0v1G0vO6QQ7[O1G0yOOO[1G0y1G0yO6XO(CWO,5;dO6^Q7[O1G0|OOOW1G0|1G0|OOOW1G1S1G1SO6hQ7[O1G1SOOOX-E9[-E9[O6oQ&jO'#EoOOOW1G/w1G/wOOOY-E9]-E9]O6tQ&jO'#ErOOO[-E9^-E9^O6yQ&jO'#EuO7OQ,UO,5;gOOO`-E9_-E9_OOOW1G1U1G1UOOOW1G1W1G1WOOOW1G1X1G1XP)dQ'[O'#DjO7TQ$ISO1G.zO7]Q&jO1G/OO7bQ&jO1G/YP*TQ'[O'#DjO7gQ!LQO1G/`O7oQ!LQO1G/bO7wQ&jO1G/dO7|Q&jO1G/hOOOW7+%]7+%]O8RQ&jO7+%]O8WQ&jO7+$_O8]Q$ISO7+$mO8bQ$ISO7+$vO8mQ&jO7+%QO8rQ&jO7+%TO8wQ&jO7+%WO9PQ&jO7+%YOOQO'#Du'#DuOOQO,5:`,5:`O9UQ&jO,5:`O9ZQ'[O,5:bO9`O07`O,5:eO9eO07`O,5:iO9jO07`O,5:kO9oO07`O,5:mO9tO07`O,5:oO9yO07`O,5:qO:OO07`O,5:sO:TO07`O,5:uO:YO07`O,5:wO:_O07`O,5:yO:dQ?MpO'#FZO:iQ7[O,5:dO;pQ!0LbO,5:dOSQ'[O7+$fOOOW7+$j7+$jOOOW7+$t7+$tOOOW7+$z7+$zO>XQ&jO7+$zOOOW7+$|7+$|O>^Q&jO7+$|OOOW7+%O7+%OOOOW7+%S7+%SOOOW<cQ'|O<hQ'|O<mQ!LQO'#FXO>rQ&jO<zQ&jO1G/|OOQO1G0P1G0POOQO1G0T1G0TOOQO1G0V1G0VOOQO1G0X1G0XOOQO1G0Z1G0ZOOQO1G0]1G0]OOQO1G0_1G0_OOQO1G0a1G0aOOQO1G0c1G0cOOQO1G0e1G0eOOQO,5;u,5;uOOQO-E9X-E9XO?PQ!0LbO1G0OO?_Q'[O'#DjOOQO'#Ed'#EdO?uO#@ItO'#EdO@_O&2DjO'#EdOOQO1G0O1G0OOOQO1G0p1G0pO@fQ!0LbO1G0rOOQO1G0r1G0rOOOW1G0u1G0uOOOW1G0x1G0xOOOW1G0{1G0{O@tQ&jO<^AN>^OOQO7+%h7+%hOOQO7+%j7+%jOOOO'#Fz'#FzOOOO'#F['#F[OAZO#@ItO'#EfOOQO,5;O,5;OOAbO&jO,5;OOOOO'#F]'#F]OAgO&2DjO'#EhOAnO&jO,5;OOOQO7+&^7+&^OOOWAN=lAN=lOOOWG23_G23_OAsQ'[OG23_OAxQ!LQOG23_OOOWG23hG23hOOOO-E9Y-E9YOOQO1G0j1G0jOOOO-E9Z-E9ZOBTQ&jOLD(yOOOWLD(yLD(yOBYQ'[OLD(yOB_Q&jOLD(yOBgQ&jO!$'LeOBlQ&jO!$'LeOOOW!$'Le!$'LeOBqQ'[O!$'LeOOOW!)9BP!)9BPOBvQ&jO!)9BPOB{Q&jO!)9BPOOOW!.K7k!.K7kOCQQ&jO!.K7kOOOW!4/-V!4/-V", + stateData: + "Cd~O$]OS~OSXOTUOUVOVWOWYOYbOZaO[cObTO!acO!bcO!ccO!dcO#scO#vdO$q`O~OSXOTUOUVOVWOWYOYbOZaO[cObiO!acO!bcO!ccO!dcO#scO$q`O~OSXOTUOUVOVWOWYOYbOZaO[cOblO!acO!bcO!ccO!dcO#scO$q`O~OSXOTUOUVOVWOWYOYbOZaO[cObpO!acO!bcO!ccO!dcO#scO$q`O~OSXOTUOUVOVWOWYOYbOZaO[cObtO!acO!bcO!ccO!dcO#scO$q`O~O]uOcvOdwO!WxO~O!gyO~O!gzO~O!g{O~O!g}O#k}O#m|O~O!g!PO~O$V!QOP#bP$Y#bP~O$W!TOQ#eP$Y#eP~O$X!WOR#hP$Y#hP~OSXOTUOUVOVWOWYOX![OYbOZaO[cObTO!acO!bcO!ccO!dcO#scO$q`O~O$Y!]O~P(PO$Z!^O$r!`O~O]uOcvOdwOi!fO!WxO~Om!gO~P)dOm!iO~P)dO]uOcvOdwOi!lO!WxO~Om!mO~P*TO]uOcvOdwOm!pO!WxO~Og!qO~Oe!rO~Of!sOp!tOy!uO!T!vO~O!X!wO!Z!xO!]!yO~Ob!zO!o#cO#_#bO$b!{O$d!}O$e#PO$f#RO$g#TO$h#VO$i#XO$j#ZO$k#]O$l#_O~O#a#gO~P+sO#a#jO~P+sO#a#lO~P+sO$c#mO~O#a#oO#q#pO~P+sO#a#pO~P+sO$V!QOP#bX$Y#bX~OP#sO$Y#tO~O$W!TOQ#eX$Y#eX~OQ#vO$Y#tO~O$X!WOR#hX$Y#hX~OR#xO$Y#tO~O$Y#tO~P(PO$Z!^O$r#{O~O#a#|O~O#a#}O~Oj$PO~Of$QO~Op$RO~O}$TO!P$UO~Oy$VO~O!T$WO~Og$XO!`$YO~O]$ZO~O^$[O~O^$]O~O]$^O~O]$_O~Ou$`O~O]$aO~Og$cO!k$eO$_$bO~O$c$fO~O$c$gO~O$c$hO~O$c$iO~O$c$jO~O$c$kO~O$c$lO~O$c$mO~O$c$nO~O$c$oO~O#T$pO#V$rOb!lX!o!lX#_!lX#a!lX$b!lX$d!lX$e!lX$f!lX$g!lX$h!lX$i!lX$j!lX$k!lX$l!lX#q!lX~O#V$sOb#^X!o#^X#_#^X#a#^X$b#^X$d#^X$e#^X$f#^X$g#^X$h#^X$i#^X$j#^X$k#^X$l#^X#q#^X~O#T$pO#V$uOb#`X!o#`X#_#`X#a#`X$b#`X$d#`X$e#`X$f#`X$g#`X$h#`X$i#`X$j#`X$k#`X$l#`X#q#`X~O#a$wO~P+sO#a$xO~P+sO#a$yO~P+sO#n$zO~O#a${O#q$|O~P+sO#a$|O~P+sO!g$}O~O!g%OO~O!g%PO~O#a%QO~Og%ROk%SO~Og%TO~Og%UO~Og%VOu%WO~Og%XOu%YO~Og%ZO~Og%[O~Og%]O~Og%^O~Oq%_O~Og%`Oz%aO{%aO~Og%bO~Og%cO~Og%fOt%dO~Og%gO~Og%hO~O]%iO~O!p%jO~O!p%kO~O!p%lO~O!p%mO~O!p%nO~O!p%oO~O!p%pO~O!p%qO~O!p%rO~O!p%sO~O#U%tO~O#T$pO#V%vOb!la!o!la#_!la#a!la$b!la$d!la$e!la$f!la$g!la$h!la$i!la$j!la$k!la$l!la#q!la~Ob%wO#X%yO#Z%zO#]%{O~Ob%wO#X%yO#Z%zO#]%|O~O#T$pO#V%}Ob#`a!o#`a#_#`a#a#`a$b#`a$d#`a$e#`a$f#`a$g#`a$h#`a$i#`a$j#`a$k#`a$l#`a#q#`a~Ob%wO#X%yO#Z%zO#]&OO~O#a&PO~O#a&QO~O#a&RO~O]&SO~Og&TO~Og&UO~O^&VO~O^&WO~Ou&XO~Og&ZOt%dO~Og&[O~Ob%wO#X%yO#Z%zO#]&]O~O]uO~Ob%wO!b&^O!c&^O!d&^O$m&_O~O#X&aO~P?dOb%wO!b&^O!c&^O!d&^O$o&cO~O#Z&aO~P?|Ob%wO#X%yO#Z%zO#]&fO~Og&gO~Og&hOr&iOt&jO~Og&kO~O#X#YX~P?dO#X&mO~O#Z#[X~P?|O#Z&mO~O]&oO~Og&pOr&qOu&rO~Os&sO~O]&tO~Og&uOr&vO~Og&wO~Os&xO~O]&yO~Og&zO~Os&{O~Og&|O~O!`$]#q$q#s#v!c!b#_!o!d#a~", + goto: "1T$qPPPPPPPPPPPPPPPP$r%QPPPPPP%`PPP%fP$r%lPPPPPP%z$r&QPPP&`P&`P&d$r&jP&x$rPP$rP$rP'O$rPPPPP$r'kP'y(V'yP'y(Y(fPP(Y(r(Y)O(Y)[(Y)h(Y)t(Y*Q(Y*^(Y*j(Y*vPPP+SP+cP+fP'yP'yP+i+l+o+},Q,T,c,f,iP,wPP,}-TP$rP$r$rP-c-i-s-y.T.Z.q.{/R/X/_/e/kPPPPPPPP/qP0V0cPPPPPPPPPPPP0oP0wicOPQRS^egjnr!ZiPOPQRS^egjnr!ZXfPQgjQhPR!egiQOPQRS^egjnr!ZQkQR!hjiROPQRS^egjnr!ZTmRnQoRR!kniSOPQRS^egjnr!ZQsSR!orhcOPQRS^egjnr!ZY%x$r$s$u%v%}X&^%y%z&`&diZOPQRS^egjnr!Ze#dyz{!O!P#f#i#k#n#qR$d!ze#hyz{!O!P#f#i#k#n#qe!|yz{!O!P#f#i#k#n#qe#Oyz{!O!P#f#i#k#n#qe#Qyz{!O!P#f#i#k#n#qe#Syz{!O!P#f#i#k#n#qe#Uyz{!O!P#f#i#k#n#qe#Wyz{!O!P#f#i#k#n#qe#Yyz{!O!P#f#i#k#n#qe#[yz{!O!P#f#i#k#n#qe#^yz{!O!P#f#i#k#n#qe#`yz{!O!P#f#i#k#n#qQ%{$rQ%|$sQ&O$uQ&]%vR&f%}R&b%yR&e%zR!SZR#t!Si[OPQRS^egjnr!ZR!V[R#t!Vi]OPQRS^egjnr!ZR!Y]R#t!Yi^OPQRS^egjnr!ZX}Xab![Q!]^R#t!Zi_OPQRS^egjnr!ZQeOR!ceQgPQjQT!dgjQnRR!jnQrSQ!Z^T!nr!ZQ%e$`R&Y%eQ#fyQ#izQ#k{Q#n!OQ#q!PZ$v#f#i#k#n#qQ$q#aQ$t#cT%u$q$tQ&`%yR&l&`Q&d%zR&n&dQ!RZR#r!RQ!U[R#u!UQ!X]R#w!XQ!_`R#z!_SdOeWfPQgjSmRnXqS^r!Ze#eyz{!O!P#f#i#k#n#qe#ayz{!O!P#f#i#k#n#qS&_%y&`T&c%z&dQ!OXQ!aaQ!bbR#y![", + nodeNames: + "⚠ StartCloseTag StartCloseTag StartCloseTag StartTag StartTag StartTag StartTag StartTag StartCloseTag StartCloseTag StartCloseTag IncompleteCloseTag LongExpression ShortExpression Document IfBlock IfBlockOpen { BlockPrefix BlockPrefix BlockType BlockType } ElseBlock BlockPrefix BlockType if IfBlockClose BlockPrefix EachBlock EachBlockOpen BlockType as ( ) , Variable EachBlockClose AwaitBlock AwaitBlockOpen BlockType then catch ThenBlock BlockType CatchBlock BlockType AwaitBlockClose KeyBlock KeyBlockOpen BlockType KeyBlockClose RawHTMLBlock BlockPrefix BlockType DebugBlock BlockType ConstBlock BlockType Interpolation UnknownBlock UnknownBlockContent Text EntityReference CharacterReference InvalidEntity Element OpenTag TagName DirectlyInterpolatedAttribute DirectlyInterpolatedAttributeValue SpreadInterpolatedAttribute ... Directive DirectiveOn DirectiveName AttributeName DirectiveTarget DirectiveBind DirectiveName DirectiveLet DirectiveName DirectiveClass DirectiveName DirectiveStyle DirectiveName DirectiveUse DirectiveName DirectiveTransition DirectiveName DirectiveIn DirectiveName DirectiveOut DirectiveName DirectiveAnimate DirectiveName | Modifier Is AttributeValue DoubleQuote AttributeValueContent SingleQuote AttributeValueContent UnquotedAttributeValue StyleAttribute StyleAttributeName Attribute EndTag ScriptText CloseTag OpenTag StyleText CloseTag OpenTag TextareaText CloseTag OpenTag ComponentName SvelteElementName SvelteElementNamespace SvelteElementType CloseTag SelfClosingTag SelfClosingEndTag Comment ProcessingInst MismatchedCloseTag CloseTag DoctypeDecl", + maxTerm: 172, + context: elementContext, + nodeProps: [ + [ + "closedBy", + -10, + 1, + 2, + 3, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + "EndTag", + 4, + "EndTag SelfClosingEndTag", + 17, + "IfBlockClose", + 18, + "}", + 31, + "EachBlockClose", + 34, + "(", + 40, + "AwaitBlockClose", + 48, + "AwaitBlockOpen", + 50, + "KeyBlockClose", + -4, + 68, + 112, + 115, + 118, + "CloseTag", + 101, + '"', + 103, + "'", + ], + [ + "group", + -10, + 12, + 60, + 64, + 65, + 66, + 67, + 126, + 127, + 128, + 129, + "Entity", + -4, + 16, + 30, + 39, + 49, + "Block Entity", + -4, + 17, + 31, + 40, + 50, + "BlockOpen", + -3, + 24, + 44, + 46, + "BlockInline", + -4, + 28, + 38, + 48, + 52, + "BlockClose", + -4, + 53, + 56, + 58, + 61, + "BlockInline Entity", + 63, + "Entity TextContent", + -3, + 110, + 113, + 116, + "TextContent Entity", + ], + [ + "openedBy", + 23, + "{", + 28, + "IfBlockOpen", + 35, + ")", + 38, + "EachBlockOpen", + 52, + "KeyBlockOpen", + 101, + '"', + 103, + "'", + 109, + "StartTag StartCloseTag", + -4, + 111, + 114, + 117, + 123, + "OpenTag", + 125, + "StartTag", + ], + ], + propSources: [svelteHighlighting], + skippedNodes: [0], + repeatNodeCount: 13, + tokenData: + "&8h$IRR!dOX%aXY/TYZ/TZ[%a[]1{]^/T^p%apq/Tqr2yrsEastF_tuHxuv2yvw!)[wx#,nxy#-lyz#0Vz|2y|}#2p}!O#5Z!O!P#Kk!P!Q$%S!Q![2y![!]$'{!]!^2y!^!_$)u!_!`%'{!`!a%({!a!b2y!b!cF_!c!}%){!}#R2y#R#S%AU#S#T&%m#T#o&'m#o#p&1P#p#q&1d#q#r&3[#r#s2y#s$f%a$f$g2y$g%WHx%W%o%AU%o%pHx%p&a%AU&a&bHx&b1p%AU1p4UHx4U4d%AU4d4eHx4e$IS%AU$IS$I`Hx$I`$Ib%AU$Ib$KhHx$Kh%#t%AU%#t&/xHx&/x&Et%AU&Et&FVHx&FV;'S%AU;'S;:j&5p;:j;=`&5v<%l?&rHx?&r?Ah%AU?Ah?BY&5|?BY?Mn%AU?MnO&5|$3X%ng!aP#]7[$mMh$o!LQ!``OX'VXZ(wZ['V[^(w^p'Vpq(wqr'Vrs(wsv'Vvw*}wx(wx!^'V!^!_)q!_!a(w!a#S'V#S#T(w#T#o'V#o#p*}#p#q'V#q#r-b#r;'S'V;'S;=`.}<%lO'V7m'`g!aP#]7[!``OX'VXZ(wZ['V[^(w^p'Vpq(wqr'Vrs(wsv'Vvw*}wx(wx!^'V!^!_)q!_!a(w!a#S'V#S#T(w#T#o'V#o#p*}#p#q'V#q#r-b#r;'S'V;'S;=`.}<%lO'Va)OZ!aP!``Ov(wvw)qw!^(w!^!_)q!_#o(w#o#p)q#p#q(w#q#r*Y#r;'S(w;'S;=`*w<%lO(w`)vS!``O#q)q#r;'S)q;'S;=`*S<%lO)q`*VP;=`<%l)qP*_U!aPOv*Yw!^*Y!_#o*Y#p;'S*Y;'S;=`*q<%lO*YP*tP;=`<%l*Ya*zP;=`<%l(w7l+Uc#]7[!``OX*}XZ)qZ[*}[^)q^p*}pq)qqr*}rs)qsw*}wx)qx!^*}!^!a)q!a#S*}#S#T)q#T#q*}#q#r,a#r;'S*};'S;=`-[<%lO*}7[,fY#]7[OX,aZ[,a^p,aqr,asw,ax!^,a!a#S,a#T;'S,a;'S;=`-U<%lO,a7[-XP;=`<%l,a7l-_P;=`<%l*}7]-id!aP#]7[OX-bXZ*YZ[-b[^*Y^p-bpq*Yqr-brs*Ysv-bvw,awx*Yx!^-b!_!a*Y!a#S-b#S#T*Y#T#o-b#o#p,a#p;'S-b;'S;=`.w<%lO-b7].zP;=`<%l-b7m/QP;=`<%l'V$@q/bb!aP$mMh$o!LQ!``$]EUOX(wXY0jYZ0jZ](w]^0j^p(wpq0jqv(wvw)qw!^(w!^!_)q!_#o(w#o#p)q#p#q(w#q#r*Y#r;'S(w;'S;=`*w<%lO(wEV0sb!aP!``$]EUOX(wXY0jYZ0jZ](w]^0j^p(wpq0jqv(wvw)qw!^(w!^!_)q!_#o(w#o#p)q#p#q(w#q#r*Y#r;'S(w;'S;=`*w<%lO(w#J{2WZ!aP$mMh$o!LQ!``Ov(wvw)qw!^(w!^!_)q!_#o(w#o#p)q#p#q(w#q#r*Y#r;'S(w;'S;=`*w<%lO(w$DR3^p!p&j#U,U!aP#]7[$mMh$o!LQ!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wsv5bvw7uwx(wx!P5b!P!Q'V!Q![5b![!]'V!]!^5b!^!_:Q!_!a(w!a#S5b#S#T>y#T#o5b#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f;'S5b;'S;=`EZ<%l?Ah5b?Ah?BY'V?BY?Mn5b?MnO'VHg5qp!p&j#U,U!aP#]7[!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wsv5bvw7uwx(wx!P5b!P!Q'V!Q![5b![!]'V!]!^5b!^!_:Q!_!a(w!a#S5b#S#T>y#T#o5b#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f;'S5b;'S;=`EZ<%l?Ah5b?Ah?BY'V?BY?Mn5b?MnO'VHf8Sn!p&j#U,U#]7[!``!oWOX*}XZ)qZ[*}[^)q^p*}pq)qqr7urs)qsw7uwx)qx!P7u!P!Q*}!Q![7u![!]*}!]!^7u!^!_:Q!_!a)q!a#S7u#S#T:Q#T#o7u#o#q*}#q#rs<%l?Ah7u?Ah?BY*}?BY?Mn7u?MnO*}2Y:]f!p&j#U,U!``!oWOq)qqr:Qrs)qsw:Qwx)qx!P:Q!P!Q)q!Q![:Q![!])q!]!_:Q!_!a)q!a#o:Q#o#q)q#q#r;q#r#s:Q#s$f)q$f;'S:Q;'S;=`m<%l?AhpP;=`<%lvP;=`<%l7u2Z?Wi!p&j#U,U!aP!``!oWOq(wqr>yrs(wsv>yvw:Qwx(wx!P>y!P!Q(w!Q![>y![!](w!]!^>y!^!_:Q!_!a(w!a#o>y#o#p)q#p#q(w#q#r@u#r#s>y#s$f(w$f;'S>y;'S;=`Bo<%l?Ah>y?Ah?BY(w?BY?Mn>y?MnO(w1yAQg!p&j#U,U!aP!oWOq*Yqr@urs*Ysv@uvw;qwx*Yx!P@u!P!Q*Y!Q![@u![!]*Y!]!^@u!^!_;q!_!a*Y!a#o@u#p#q*Y#q#s@u#s$f*Y$f;'S@u;'S;=`Bi<%l?Ah@u?Ah?BY*Y?BY?Mn@u?MnO*Y1yBlP;=`<%l@u2ZBrP;=`<%l>yHVCSo!p&j#U,U!aP#]7[!oWOX-bXZ*YZ[-b[^*Y^p-bpq*YqrBurs*YsvBuvwy#T#o5b#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f;'S5b;'S;=`EZ<%l?Ah5b?Ah?BY'V?BY?Mn5b?MnO'V$FZIcweS!p&j#U,U!aP#]7[up$mMh$o!LQ$_!b!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wst5btuK|uv5bvw7uwx(wx!O5b!O!PN|!P!Q'V!Q![K|![!]'V!]!^5b!^!_:Q!_!a(w!a!c5b!c!}K|!}#R5b#R#SK|#S#T>y#T#oK|#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$g5b$g;'SK|;'S;=`!&h<%l?AhK|?Ah?BY!&n?BY?MnK|?MnO!&nJoLcweS!p&j#U,U!aP#]7[up$_!b!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wst5btuK|uv5bvw7uwx(wx!O5b!O!PN|!P!Q'V!Q![K|![!]'V!]!^5b!^!_:Q!_!a(w!a!c5b!c!}K|!}#R5b#R#SK|#S#T>y#T#oK|#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$g5b$g;'SK|;'S;=`!&h<%l?AhK|?Ah?BY!&n?BY?MnK|?MnO!&nIX! _w!p&j#U,U!aP#]7[up!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wst5btuN|uv5bvw7uwx(wx!O5b!O!PN|!P!Q'V!Q![N|![!]'V!]!^5b!^!_:Q!_!a(w!a!c5b!c!}N|!}#R5b#R#SN|#S#T>y#T#oN|#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$g5b$g;'SN|;'S;=`!#x<%l?AhN|?Ah?BY!$O?BY?MnN|?MnO!$OIX!#{P;=`<%lN|8_!$Zq!aP#]7[up!``OX'VXZ(wZ['V[^(w^p'Vpq(wqr'Vrs(wst'Vtu!$Ouv'Vvw*}wx(wx!O'V!O!P!$O!P!Q'V!Q![!$O![!^'V!^!_)q!_!a(w!a!c'V!c!}!$O!}#R'V#R#S!$O#S#T(w#T#o!$O#o#p*}#p#q'V#q#r-b#r$g'V$g;'S!$O;'S;=`!&b<%lO!$O8_!&eP;=`<%l!$OJo!&kP;=`<%lK|9u!&}qeS!aP#]7[up$_!b!``OX'VXZ(wZ['V[^(w^p'Vpq(wqr'Vrs(wst'Vtu!&nuv'Vvw*}wx(wx!O'V!O!P!$O!P!Q'V!Q![!&n![!^'V!^!_)q!_!a(w!a!c'V!c!}!&n!}#R'V#R#S!&n#S#T(w#T#o!&n#o#p*}#p#q'V#q#r-b#r$g'V$g;'S!&n;'S;=`!)U<%lO!&n9u!)XP;=`<%l!&n$DR!)ko!p&j#U,U#]7[!``!oW!d#JkOX!+lXZ!-UZ[!+l[^!-U^p!+lpq)qqr!3Qrs!-Ust!B^tw!3Qwx!-Ux!P!3Q!P!Q!+l!Q![!3Q![!]!+l!]!^7u!^!_!7m!_!a!-U!a#S!3Q#S#T!7m#T#o!3Q#o#q!+l#q#r!>U#r#s!3Q#s$f!+l$f;'S!3Q;'S;=`!BW<%l?Ah!3Q?Ah?BY!+l?BY?Mn!3Q?MnO!+l$3X!+se#]7[!``OX!+lXZ!-UZ[!+l[^!-U^p!+lpq)qqr!+lrs!-Ust*}tw!+lwx!-Ux!]!+l!]!^!/[!^!a!-U!a#S!+l#S#T!-U#T#q!+l#q#r!0p#r;'S!+l;'S;=`!2z<%lO!+l#J{!-ZZ!``Op!-Upq)qqs!-Ust)qt!]!-U!]!^!-|!^#q!-U#q#r!.a#r;'S!-U;'S;=`!/U<%lO!-U#J{!.TS!``!b#JkO#q)q#r;'S)q;'S;=`*S<%lO)q#Jk!.dVOp!.aqs!.at!]!.a!]!^!.y!^;'S!.a;'S;=`!/O<%lO!.a#Jk!/OO!b#Jk#Jk!/RP;=`<%l!.a#J{!/XP;=`<%l!-U$3X!/ec#]7[!``!b#JkOX*}XZ)qZ[*}[^)q^p*}pq)qqr*}rs)qsw*}wx)qx!^*}!^!a)q!a#S*}#S#T)q#T#q*}#q#r,a#r;'S*};'S;=`-[<%lO*}$2w!0ub#]7[OX!0pXZ!.aZ[!0p[^!.a^p!0pqr!0prs!.ast,atw!0pwx!.ax!]!0p!]!^!1}!^!a!.a!a#S!0p#S#T!.a#T;'S!0p;'S;=`!2t<%lO!0p$2w!2UY#]7[!b#JkOX,aZ[,a^p,aqr,asw,ax!^,a!a#S,a#T;'S,a;'S;=`-U<%lO,a$2w!2wP;=`<%l!0p$3X!2}P;=`<%l!+l$DR!3_o!p&j#U,U#]7[!``!oWOX!+lXZ!-UZ[!+l[^!-U^p!+lpq)qqr!3Qrs!-Ust7utw!3Qwx!-Ux!P!3Q!P!Q!+l!Q![!3Q![!]!+l!]!^!5`!^!_!7m!_!a!-U!a#S!3Q#S#T!7m#T#o!3Q#o#q!+l#q#r!>U#r#s!3Q#s$f!+l$f;'S!3Q;'S;=`!BW<%l?Ah!3Q?Ah?BY!+l?BY?Mn!3Q?MnO!+l$DR!5on!p&j#U,U#]7[!``!b#Jk!oWOX*}XZ)qZ[*}[^)q^p*}pq)qqr7urs)qsw7uwx)qx!P7u!P!Q*}!Q![7u![!]*}!]!^7u!^!_:Q!_!a)q!a#S7u#S#T:Q#T#o7u#o#q*}#q#rs<%l?Ah7u?Ah?BY*}?BY?Mn7u?MnO*}$-u!7xi!p&j#U,U!``!oWOp!-Upq)qqr!7mrs!-Ust:Qtw!7mwx!-Ux!P!7m!P!Q!-U!Q![!7m![!]!-U!]!^!9g!^!_!7m!_!a!-U!a#o!7m#o#q!-U#q#r!;Y#r#s!7m#s$f!-U$f;'S!7m;'S;=`!>O<%l?Ah!7m?Ah?BY!-U?BY?Mn!7m?MnO!-U$-u!9tf!p&j#U,U!``!b#Jk!oWOq)qqr:Qrs)qsw:Qwx)qx!P:Q!P!Q)q!Q![:Q![!])q!]!_:Q!_!a)q!a#o:Q#o#q)q#q#r;q#r#s:Q#s$f)q$f;'S:Q;'S;=`RP;=`<%l!7m$Cq!>am!p&j#U,U#]7[!oWOX!0pXZ!.aZ[!0p[^!.a^p!0pqr!>Urs!.astUwx!.ax!P!>U!P!Q!0p!Q![!>U![!]!0p!]!^!@[!^!_!;Y!_!a!.a!a#S!>U#S#T!;Y#T#o!>U#o#q!0p#q#s!>U#s$f!0p$f;'S!>U;'S;=`!BQ<%l?Ah!>U?Ah?BY!0p?BY?Mn!>U?MnO!0p$Cq!@ig!p&j#U,U#]7[!b#Jk!oWOX,aZ[,a^p,aqrm<%l?AhU$DR!BZP;=`<%l!3Q$DR!Bkn!p&j#U,U#]7[!``!oWOX!DiXZ!FOZ[!Di[^!FO^p!Dipq)qqr!Knrs!FOsw!Knwx!FOx!P!Kn!P!Q!Di!Q![!Kn![!]!Di!]!^7u!^!_#!W!_!a!FO!a#S!Kn#S#T#!W#T#o!Kn#o#q!Di#q#r#(i#r#s!Kn#s$f!Di$f;'S!Kn;'S;=`#,h<%l?Ah!Kn?Ah?BY!Di?BY?Mn!Kn?MnO!Di$3X!Dpd#]7[!``OX!DiXZ!FOZ[!Di[^!FO^p!Dipq)qqr!Dirs!FOsw!Diwx!FOx!]!Di!]!^!G{!^!a!FO!a#S!Di#S#T!FO#T#q!Di#q#r!Ia#r;'S!Di;'S;=`!Kh<%lO!Di#J{!FTX!``Op!FOpq)qq!]!FO!]!^!Fp!^#q!FO#q#r!GT#r;'S!FO;'S;=`!Gu<%lO!FO#J{!FwS!``!c#JkO#q)q#r;'S)q;'S;=`*S<%lO)q#Jk!GWUOp!GTq!]!GT!]!^!Gj!^;'S!GT;'S;=`!Go<%lO!GT#Jk!GoO!c#Jk#Jk!GrP;=`<%l!GT#J{!GxP;=`<%l!FO$3X!HUc#]7[!``!c#JkOX*}XZ)qZ[*}[^)q^p*}pq)qqr*}rs)qsw*}wx)qx!^*}!^!a)q!a#S*}#S#T)q#T#q*}#q#r,a#r;'S*};'S;=`-[<%lO*}$2w!Ifa#]7[OX!IaXZ!GTZ[!Ia[^!GT^p!Iaqr!Iars!GTsw!Iawx!GTx!]!Ia!]!^!Jk!^!a!GT!a#S!Ia#S#T!GT#T;'S!Ia;'S;=`!Kb<%lO!Ia$2w!JrY#]7[!c#JkOX,aZ[,a^p,aqr,asw,ax!^,a!a#S,a#T;'S,a;'S;=`-U<%lO,a$2w!KeP;=`<%l!Ia$3X!KkP;=`<%l!Di$DR!K{n!p&j#U,U#]7[!``!oWOX!DiXZ!FOZ[!Di[^!FO^p!Dipq)qqr!Knrs!FOsw!Knwx!FOx!P!Kn!P!Q!Di!Q![!Kn![!]!Di!]!^!My!^!_#!W!_!a!FO!a#S!Kn#S#T#!W#T#o!Kn#o#q!Di#q#r#(i#r#s!Kn#s$f!Di$f;'S!Kn;'S;=`#,h<%l?Ah!Kn?Ah?BY!Di?BY?Mn!Kn?MnO!Di$DR!NYn!p&j#U,U#]7[!``!c#Jk!oWOX*}XZ)qZ[*}[^)q^p*}pq)qqr7urs)qsw7uwx)qx!P7u!P!Q*}!Q![7u![!]*}!]!^7u!^!_:Q!_!a)q!a#S7u#S#T:Q#T#o7u#o#q*}#q#rs<%l?Ah7u?Ah?BY*}?BY?Mn7u?MnO*}$-u#!ch!p&j#U,U!``!oWOp!FOpq)qqr#!Wrs!FOsw#!Wwx!FOx!P#!W!P!Q!FO!Q![#!W![!]!FO!]!^##}!^!_#!W!_!a!FO!a#o#!W#o#q!FO#q#r#%p#r#s#!W#s$f!FO$f;'S#!W;'S;=`#(c<%l?Ah#!W?Ah?BY!FO?BY?Mn#!W?MnO!FO$-u#$[f!p&j#U,U!``!c#Jk!oWOq)qqr:Qrs)qsw:Qwx)qx!P:Q!P!Q)q!Q![:Q![!])q!]!_:Q!_!a)q!a#o:Q#o#q)q#q#r;q#r#s:Q#s$f)q$f;'S:Q;'S;=`m<%l?Ahy#T#o5b#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f;'S5b;'S;=`EZ<%l?Ah5b?Ah?BY'V?BY?Mn5b?MnO'V$DT#0lpsQ!p&j#U,U!aP#]7[$mMh$o!LQ!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wsv5bvw7uwx(wx!P5b!P!Q'V!Q![5b![!]'V!]!^5b!^!_:Q!_!a(w!a#S5b#S#T>y#T#o5b#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f;'S5b;'S;=`EZ<%l?Ah5b?Ah?BY'V?BY?Mn5b?MnO'V$DT#3VptQ!p&j#U,U!aP#]7[$mMh$o!LQ!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wsv5bvw7uwx(wx!P5b!P!Q'V!Q![5b![!]'V!]!^5b!^!_:Q!_!a(w!a#S5b#S#T>y#T#o5b#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f;'S5b;'S;=`EZ<%l?Ah5b?Ah?BY'V?BY?Mn5b?MnO'V$DT#5nr!p&j#U,U!aP#]7[$mMh$o!LQ!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wsv5bvw7uwx(wx}5b}!O#7x!O!P5b!P!Q'V!Q![5b![!]'V!]!^5b!^!_:Q!_!a(w!a#S5b#S#T>y#T#o5b#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f;'S5b;'S;=`EZ<%l?Ah5b?Ah?BY'V?BY?Mn5b?MnO'VHi#8Xq!p&j#U,U!aP#]7[!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr#:`rs(wsv#:`vw#y#T#o5b#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f;'S5b;'S;=`EZ<%l?Ah5b?Ah?BY'V?BY?Mn5b?MnO'VIy#Nfq!p&j#U,U!aP#]7[!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wsv5bvw7uwx(wx!O5b!O!P$!m!P!Q'V!Q![5b![!]'V!]!^5b!^!_:Q!_!a(w!a#S5b#S#T>y#T#o5b#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f;'S5b;'S;=`EZ<%l?Ah5b?Ah?BY'V?BY?Mn5b?MnO'VIy$#Op!k!b!p&j#U,U!aP#]7[!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wsv5bvw7uwx(wx!P5b!P!Q'V!Q![5b![!]'V!]!^5b!^!_:Q!_!a(w!a#S5b#S#T>y#T#o5b#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f;'S5b;'S;=`EZ<%l?Ah5b?Ah?BY'V?BY?Mn5b?MnO'V$3g$%chcQ!aP#]7[$mMh$o!LQ!``OX'VXZ(wZ['V[^(w^p'Vpq(wqr'Vrs(wsv'Vvw*}wx(wx!^'V!^!_)q!_!`(w!`!a$&}!a#S'V#S#T(w#T#o'V#o#p*}#p#q'V#q#r-b#r;'S'V;'S;=`.}<%lO'Vm$'YZ!aP!``#qW#a[Ov(wvw)qw!^(w!^!_)q!_#o(w#o#p)q#p#q(w#q#r*Y#r;'S(w;'S;=`*w<%lO(w$3_$(^g$cScQ!aP#]7[$mMh$o!LQ!``OX'VXZ(wZ['V[^(w^p'Vpq(wqr'Vrs(wsv'Vvw*}wx(wx!^'V!^!_)q!_!a(w!a#S'V#S#T(w#T#o'V#o#p*}#p#q'V#q#r-b#r;'S'V;'S;=`.}<%lO'V$-u$*Ug!p&j#U,U$mMh$o!LQ!``!oWOq)qqr$+mrs)qsw:Qwx)qx!P:Q!P!Q)q!Q![:Q![!])q!]!_:Q!_!a)q!a!b$LZ!b#o:Q#o#q)q#q#r;q#r#s:Q#s$f)q$f;'S:Q;'S;=``!a#o$`!a#q$=t#q#r$>s#r;'S$=t;'S;=`$?b<%lO$=ta$>gS!``#vPO#q)q#r;'S)q;'S;=`*S<%lO)qP$>vTO!`$>s!`!a$?V!a;'S$>s;'S;=`$?[<%lO$>sP$?[O#vPP$?_P;=`<%l$>sa$?eP;=`<%l$=t1y$?qf!p&j#U,U!oWOq$>sqr$?hrs$>ssw$?hwx$>sx!P$?h!P!Q$>s!Q![$?h![!]$>s!]!_$?h!_!`$>s!`!a$?V!a#o$?h#o#q$>s#q#s$?h#s$f$>s$f;'S$?h;'S;=`$AV<%l?Ah$?h?Ah?BY$>s?BY?Mn$?h?MnO$>s1y$AYP;=`<%l$?h2Z$A`P;=`<%l$y#T#o%y#T#o%.o#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$}5b$}%O%.o%O%W5b%W%o%.o%o%p5b%p&a%.o&a&b5b&b1p%.o1p4U%.o4U4d%.o4d4e5b4e$IS%.o$IS$I`5b$I`$Ib%.o$Ib$Je5b$Je$Jg%.o$Jg$Kh5b$Kh%#t%.o%#t&/x5b&/x&Et%.o&Et&FV5b&FV;'S%.o;'S;:j%2|;:j;=`EZ<%l?&r5b?&r?Ah%.o?Ah?BY'V?BY?Mn%.o?MnO'VHi%3PP;=`<%l%.oIZ%3g!a#kQ!p&j#U,U!aP#]7[up!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wst5btuN|uv5bvw7uwx(wx}5b}!O%.o!O!P%3S!P!Q'V!Q![%3S![!]'V!]!^5b!^!_:Q!_!a(w!a!c5b!c!}%3S!}#R5b#R#S%3S#S#T>y#T#o%3S#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$g5b$g$}N|$}%O%3S%O%WN|%W%o%3S%o%pN|%p&a%3S&a&bN|&b1p%3S1p4U%3S4U4d%3S4d4eN|4e$IS%3S$IS$I`N|$I`$Ib%3S$Ib$JeN|$Je$Jg%3S$Jg$KhN|$Kh%#t%3S%#t&/xN|&/x&Et%3S&Et&FVN|&FV;'S%3S;'S;:j%7l;:j;=`!#x<%l?&rN|?&r?Ah%3S?Ah?BY!$O?BY?Mn%3S?MnO!$OIZ%7oP;=`<%l%3SJq%8Z!aeS#kQ!p&j#U,U!aP#]7[up$_!b!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wst5btuK|uv5bvw7uwx(wx}5b}!O%.o!O!P%3S!P!Q'V!Q![%7r![!]'V!]!^5b!^!_:Q!_!a(w!a!c5b!c!}%7r!}#R5b#R#S%7r#S#T>y#T#o%7r#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$g5b$g$}K|$}%O%7r%O%WK|%W%o%7r%o%pK|%p&a%7r&a&bK|&b1p%7r1p4U%7r4U4d%7r4d4eK|4e$IS%7r$IS$I`K|$I`$Ib%7r$Ib$JeK|$Je$Jg%7r$Jg$KhK|$Kh%#t%7r%#t&/xK|&/x&Et%7r&Et&FVK|&FV;'S%7r;'S;:j%<`;:j;=`!&h<%l?&rK|?&r?Ah%7r?Ah?BY!&n?BY?Mn%7r?MnO!&nJq%y#T#o%y#T#o%Ny#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$g5b$g$}K|$}%O%Ny%O%WK|%W%o%Ny%o%pK|%p&a%Ny&a&bK|&b1p%Ny1p4U%Ny4U4d%Ny4d4eK|4e$IS%Ny$IS$I`K|$I`$Ib%Ny$Ib$JeK|$Je$Jg%Ny$Jg$KhK|$Kh%#t%Ny%#t&/xK|&/x&Et%Ny&Et&FVK|&FV;'S%Ny;'S;:j&%g;:j;=`!&h<%l?&rK|?&r?Ah%Ny?Ah?BY!&n?BY?Mn%Ny?MnO!&nHi%FX!^!p&j#U,U!gQ!aP#]7[!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wsv5bvw7uwx(wx}5b}!O%Ev!O!P%Ev!P!Q'V!Q![%Ev![!]'V!]!^5b!^!_:Q!_!a(w!a!c5b!c!}%Ev!}#R5b#R#S%Ev#S#T>y#T#o%Ev#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$}5b$}%O%Ev%O%W5b%W%o%Ev%o%p5b%p&a%Ev&a&b5b&b1p%Ev1p4U%Ev4U4d%Ev4d4e5b4e$IS%Ev$IS$I`5b$I`$Ib%Ev$Ib$Je5b$Je$Jg%Ev$Jg$Kh5b$Kh%#t%Ev%#t&/x5b&/x&Et%Ev&Et&FV5b&FV;'S%Ev;'S;:j%JT;:j;=`EZ<%l?&r5b?&r?Ah%Ev?Ah?BY'V?BY?Mn%Ev?MnO'VHi%JWP;=`<%l%EvIZ%Jn!a!p&j#U,U!gQ!aP#]7[up!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wst5btuN|uv5bvw7uwx(wx}5b}!O%Ev!O!P%JZ!P!Q'V!Q![%JZ![!]'V!]!^5b!^!_:Q!_!a(w!a!c5b!c!}%JZ!}#R5b#R#S%JZ#S#T>y#T#o%JZ#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$g5b$g$}N|$}%O%JZ%O%WN|%W%o%JZ%o%pN|%p&a%JZ&a&bN|&b1p%JZ1p4U%JZ4U4d%JZ4d4eN|4e$IS%JZ$IS$I`N|$I`$Ib%JZ$Ib$JeN|$Je$Jg%JZ$Jg$KhN|$Kh%#t%JZ%#t&/xN|&/x&Et%JZ&Et&FVN|&FV;'S%JZ;'S;:j%Ns;:j;=`!#x<%l?&rN|?&r?Ah%JZ?Ah?BY!$O?BY?Mn%JZ?MnO!$OIZ%NvP;=`<%l%JZJq& b!aeS!p&j#U,U!gQ!aP#]7[up$_!b!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wst5btuK|uv5bvw7uwx(wx}5b}!O%Ev!O!P%JZ!P!Q'V!Q![%Ny![!]'V!]!^5b!^!_:Q!_!a(w!a!c5b!c!}%Ny!}#R5b#R#S%Ny#S#T>y#T#o%Ny#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$g5b$g$}K|$}%O%Ny%O%WK|%W%o%Ny%o%pK|%p&a%Ny&a&bK|&b1p%Ny1p4U%Ny4U4d%Ny4d4eK|4e$IS%Ny$IS$I`K|$I`$Ib%Ny$Ib$JeK|$Je$Jg%Ny$Jg$KhK|$Kh%#t%Ny%#t&/xK|&/x&Et%Ny&Et&FVK|&FV;'S%Ny;'S;:j&%g;:j;=`!&h<%l?&rK|?&r?Ah%Ny?Ah?BY!&n?BY?Mn%Ny?MnO!&nJq&%jP;=`<%l%Ny$-u&&Oi!p&j#U,U!aP$mMh$o!LQ!``!oWOq(wqr>yrs(wsv>yvw:Qwx(wx!P>y!P!Q(w!Q![>y![!](w!]!^>y!^!_:Q!_!a(w!a#o>y#o#p)q#p#q(w#q#r@u#r#s>y#s$f(w$f;'S>y;'S;=`Bo<%l?Ah>y?Ah?BY(w?BY?Mn>y?MnO(w$IR&([!aeS!p&j#U,U#n#t!gQ!aP#]7[up$mMh$o!LQ$_!b!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wst5btuK|uv5bvw7uwx(wx}5b}!O%Ev!O!P%JZ!P!Q'V!Q![%Ny![!]'V!]!^5b!^!_:Q!_!a(w!a!c5b!c!}&,a!}#R5b#R#S%Ny#S#T>y#T#o&,a#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$g5b$g$}K|$}%O%Ny%O%WK|%W%o%Ny%o%pK|%p&a%Ny&a&bK|&b1p%Ny1p4U%Ny4U4d%Ny4d4eK|4e$IS%Ny$IS$I`K|$I`$Ib%Ny$Ib$JeK|$Je$Jg%Ny$Jg$KhK|$Kh%#t%Ny%#t&/xK|&/x&Et%Ny&Et&FVK|&FV;'S%Ny;'S;:j&%g;:j;=`!&h<%l?&rK|?&r?Ah%Ny?Ah?BY!&n?BY?Mn%Ny?MnO!&nMg&,z!aeS!p&j#U,U#n#t!gQ!aP#]7[up$_!b!``!oWOX'VXZ(wZ['V[^(w^p'Vpq(wqr5brs(wst5btuK|uv5bvw7uwx(wx}5b}!O%Ev!O!P%JZ!P!Q'V!Q![%Ny![!]'V!]!^5b!^!_:Q!_!a(w!a!c5b!c!}&,a!}#R5b#R#S%Ny#S#T>y#T#o&,a#o#p*}#p#q'V#q#rBu#r#s5b#s$f'V$f$g5b$g$}K|$}%O%Ny%O%WK|%W%o%Ny%o%pK|%p&a%Ny&a&bK|&b1p%Ny1p4U%Ny4U4d%Ny4d4eK|4e$IS%Ny$IS$I`K|$I`$Ib%Ny$Ib$JeK|$Je$Jg%Ny$Jg$KhK|$Kh%#t%Ny%#t&/xK|&/x&Et%Ny&Et&FVK|&FV;'S%Ny;'S;:j&%g;:j;=`!&h<%l?&rK|?&r?Ah%Ny?Ah?BY!&n?BY?Mn%Ny?MnO!&n$3a&1WSb$3P!``O#q)q#r;'S)q;'S;=`*S<%lO)q$3a&1sg#TW!aP#]7[$mMh$o!LQ!``OX'VXZ(wZ['V[^(w^p'Vpq(wqr'Vrs(wsv'Vvw*}wx(wx!^'V!^!_)q!_!a(w!a#S'V#S#T(w#T#o'V#o#p*}#p#q'V#q#r-b#r;'S'V;'S;=`.}<%lO'V$FX&3oog#f!p&j#U,U!aP#]7[$mMh$o!LQ!oWOX-bXZ*YZ[-b[^*Y^p-bpq*YqrBurs*YsvBuvw spec_BlockPrefix[value] ?? -1 }, + { term: 21, get: (value: string) => spec_BlockType.get(value) ?? -1 }, + { term: 153, get: (value: string) => spec_identifier.get(value) ?? -1 }, + { term: 77, get: (value: string) => spec_AttributeName[value] ?? -1 }, + { term: 69, get: (value: string) => spec_TagName[value] ?? -1 }, + ], + tokenPrec: 1571, +}); diff --git a/packages/highlight/src/svelte/terms.ts b/packages/highlight/src/svelte/terms.ts new file mode 100644 index 000000000..6a0b8472d --- /dev/null +++ b/packages/highlight/src/svelte/terms.ts @@ -0,0 +1,23 @@ +export const scriptText = 145; +export const StartCloseScriptTag = 1; +export const styleText = 146; +export const StartCloseStyleTag = 2; +export const textareaText = 147; +export const StartCloseTextareaTag = 3; +export const StartTag = 4; +export const StartScriptTag = 5; +export const StartStyleTag = 6; +export const StartTextareaTag = 7; +export const StartSelfClosingTag = 8; +export const StartCloseTag = 9; +export const MismatchedStartCloseTag = 11; +export const missingCloseTag = 148; +export const IncompleteCloseTag = 12; +export const commentContent$1 = 149; +export const LongExpression = 13; +export const ShortExpression = 14; +export const Element = 67; +export const ScriptText = 110; +export const StyleText = 113; +export const TextareaText = 116; +export const OpenTag = 118; diff --git a/packages/highlight/src/svelte/tokens.ts b/packages/highlight/src/svelte/tokens.ts new file mode 100644 index 000000000..8395c1625 --- /dev/null +++ b/packages/highlight/src/svelte/tokens.ts @@ -0,0 +1,545 @@ +import { ContextTracker, ExternalTokenizer, type InputStream, type Stack } from "@lezer/lr"; +import { + commentContent$1, + Element, + IncompleteCloseTag, + LongExpression, + MismatchedStartCloseTag, + missingCloseTag, + OpenTag, + scriptText, + ShortExpression, + StartCloseScriptTag, + StartCloseStyleTag, + StartCloseTag, + StartCloseTextareaTag, + StartScriptTag, + StartSelfClosingTag, + StartStyleTag, + StartTag, + StartTextareaTag, + styleText, + textareaText, +} from "./terms.js"; + +const selfClosers: Record = { + 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: Record = { + 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: Record> = { + 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: number): boolean { + return ( + ch === 45 || + ch === 46 || + ch === 58 || + (ch >= 65 && ch <= 90) || + ch === 95 || + (ch >= 97 && ch <= 122) || + ch >= 161 + ); +} + +function isSpace(ch: number): boolean { + return ch === 9 || ch === 10 || ch === 13 || ch === 32; +} + +const lessThan = 60; +const greaterThan$1 = 62; +const slash$1 = 47; +const question = 63; +const bang = 33; + +let cachedName: string | null | undefined = null; +let cachedInput: InputStream | null = null; +let cachedPos = 0; + +function tagNameAfter(input: InputStream, offset: number): string | null | undefined { + const pos = input.pos + offset; + if (cachedPos === pos && cachedInput === input) return cachedName; + let next = input.peek(offset); + let curOffset = offset; + while (isSpace(next)) { + curOffset++; + next = input.peek(curOffset); + } + let name = ""; + for (;;) { + if (!nameChar(next)) break; + name += String.fromCharCode(next); + curOffset++; + next = input.peek(curOffset); + } + cachedInput = input; + cachedPos = pos; + let result: string | null | undefined; + if (name) { + result = name.toLowerCase(); + } else if (next === question || next === bang) { + result = undefined; + } else { + result = null; + } + cachedName = result; + return result; +} + +export class ElementContext { + name: string; + parent: ElementContext | null; + hash: number; + + constructor(name: string, parent: ElementContext | null) { + this.name = name; + this.parent = parent; + this.hash = parent ? parent.hash : 0; + for (let i = 0; i < name.length; i++) { + this.hash += (this.hash << 4) + name.charCodeAt(i) + (name.charCodeAt(i) << 8); + } + } +} + +const startTagTerms = new Set([ + StartTag, + StartSelfClosingTag, + StartScriptTag, + StartStyleTag, + StartTextareaTag, +]); + +export const elementContext = new ContextTracker({ + start: null, + shift(context, term, _stack, input) { + return startTagTerms.has(term) + ? new ElementContext(tagNameAfter(input, 1) || "", context) + : context; + }, + reduce(context, term) { + return term === Element && context ? context.parent : context; + }, + reuse(context, node, _stack, input) { + const type = node.type.id; + return type === StartTag || type === OpenTag + ? new ElementContext(tagNameAfter(input, 1) || "", context) + : context; + }, + hash(context) { + return context ? context.hash : 0; + }, + strict: false, +}); + +export const tagStart = new ExternalTokenizer( + // oxlint-disable-next-line complexity -- vendored Lezer tokenizer + (input: InputStream, stack: Stack) => { + if (input.next !== lessThan) { + if (input.next < 0 && stack.context) input.acceptToken(missingCloseTag); + return; + } + input.advance(); + const close = (input.next as number) === slash$1; + if (close) input.advance(); + const name = tagNameAfter(input, 0); + if (name === undefined) return; + if (!name) { + input.acceptToken(close ? IncompleteCloseTag : StartTag); + return; + } + + const parent = stack.context ? (stack.context as ElementContext).name : null; + if (close) { + if (name === parent) { + input.acceptToken(StartCloseTag); + return; + } + if (parent && implicitlyClosed[parent]) { + input.acceptToken(missingCloseTag, -2); + return; + } + for ( + let cx: ElementContext | null = stack.context as ElementContext | null; + cx; + cx = cx.parent + ) { + if (cx.name === name) return; + } + input.acceptToken(MismatchedStartCloseTag); + } else { + if (name === "script") { + input.acceptToken(StartScriptTag); + return; + } + if (name === "style") { + input.acceptToken(StartStyleTag); + return; + } + if (name === "textarea") { + input.acceptToken(StartTextareaTag); + return; + } + if (Object.prototype.hasOwnProperty.call(selfClosers, name)) { + input.acceptToken(StartSelfClosingTag); + return; + } + if (parent && closeOnOpen[parent]?.[name]) { + input.acceptToken(missingCloseTag, -1); + } else { + input.acceptToken(StartTag); + } + } + }, + { contextual: true }, +); + +function contentTokenizer(tag: string, textToken: number, endToken: number): ExternalTokenizer { + const lastState = 2 + tag.length; + return new ExternalTokenizer((input) => { + 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$1) || + (state >= 2 && state < lastState && input.next === tag.charCodeAt(state - 2)) + ) { + state++; + matchedLen++; + } else if ((state === 2 || state === lastState) && isSpace(input.next)) { + matchedLen++; + } else if (state === lastState && input.next === greaterThan$1) { + if (i > matchedLen) input.acceptToken(textToken, -matchedLen); + else input.acceptToken(endToken, -(matchedLen - 2)); + break; + } else if ((input.next === 10 || input.next === 13) && i) { + input.acceptToken(textToken, 1); + break; + } else { + state = 0; + 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); + +const space = new Set([ + 9, 10, 11, 12, 13, 32, 133, 160, 5760, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, + 8202, 8232, 8233, 8239, 8287, 12288, +]); +const parenOpen = 40; +const parenClose = 41; +const squareOpen = 91; +const squareClose = 93; +const curlyOpen = 123; +const curlyClose = 125; +const comma = 44; +const colon = 58; +const hash = 35; +const at = 64; +const slash = 47; +const greaterThan = 62; +const dash = 45; +const quoteDouble = 34; +const quoteSingle = 39; +const backslash = 92; +const newline = 10; +const asterisk = 42; +const tick = 96; +const prefixes = new Set([colon, hash, at, slash]); + +export const commentContent = new ExternalTokenizer((input) => { + for (let dashes = 0, i = 0; ; i++) { + if (input.next < 0) { + if (i) input.acceptToken(commentContent$1); + break; + } + if (input.next === dash) { + dashes++; + } else if (input.next === greaterThan && dashes >= 2) { + if (i > 3) input.acceptToken(commentContent$1, -2); + break; + } else { + dashes = 0; + } + input.advance(); + } +}); + +function createStringHandler(input: InputStream) { + let inString = false; + let inStringType: "double" | "single" | "template" | null = null; + let inStringIgnoreNext = false; + return () => { + if (inString) { + if (inStringIgnoreNext) { + inStringIgnoreNext = false; + return true; + } + if (input.next === backslash) { + inStringIgnoreNext = true; + return true; + } + if (inStringType === "double" && input.next === quoteDouble) { + inString = false; + inStringType = null; + return true; + } + if (inStringType === "single" && input.next === quoteSingle) { + inString = false; + inStringType = null; + return true; + } + if (inStringType === "template" && input.next === tick) { + inString = false; + inStringType = null; + return true; + } + return true; + } + if (input.next === quoteDouble) { + inString = true; + inStringType = "double"; + return true; + } + if (input.next === quoteSingle) { + inString = true; + inStringType = "single"; + return true; + } + if (input.next === tick) { + inString = true; + inStringType = "template"; + return true; + } + return false; + }; +} + +function createCommentHandler(input: InputStream) { + let inLineComment = false; + let inBlockComment = false; + return () => { + if (inLineComment) { + if (input.next === newline) { + inLineComment = false; + return true; + } + return true; + } + if (inBlockComment) { + if (input.next === asterisk && input.peek(1) === slash) { + inBlockComment = false; + return true; + } + return true; + } + if (input.next === slash && input.peek(1) === slash) { + inLineComment = true; + return true; + } + if (input.next === slash && input.peek(1) === asterisk) { + inBlockComment = true; + return true; + } + return false; + }; +} + +export const longExpression = new ExternalTokenizer((input) => { + if (prefixes.has(input.next)) { + return; + } + const commentHandler = createCommentHandler(input); + const stringHandler = createStringHandler(input); + const stack: ("(" | "{" | "[")[] = []; + const popIfMatch = (match: "(" | "{" | "[") => { + const idx = stack.lastIndexOf(match); + if (idx !== -1) { + while (stack.length > idx) { + stack.pop(); + } + } + }; + for (let pos = 0; ; pos++) { + if (input.next < 0) { + if (pos > 0) input.acceptToken(LongExpression); + break; + } + if (commentHandler() || stringHandler()) { + input.advance(); + continue; + } + if ( + stack.length === 0 && + (input.next === curlyClose || input.next === parenClose || input.next === squareClose) + ) { + input.acceptToken(LongExpression); + break; + } + switch (input.next) { + case parenOpen: + stack.push("("); + break; + case parenClose: + popIfMatch("("); + break; + case squareOpen: + stack.push("["); + break; + case squareClose: + popIfMatch("["); + break; + case curlyOpen: + stack.push("{"); + break; + case curlyClose: + popIfMatch("{"); + break; + } + input.advance(); + } +}); + +// oxlint-disable-next-line complexity -- vendored Lezer tokenizer +export const shortExpression = new ExternalTokenizer((input) => { + if (prefixes.has(input.peek(0))) { + return; + } + const commentHandler = createCommentHandler(input); + const stringHandler = createStringHandler(input); + const stack: ("(" | "{" | "[")[] = []; + const popIfMatch = (match: "(" | "{" | "[") => { + const idx = stack.lastIndexOf(match); + if (idx !== -1) { + while (stack.length > idx) { + stack.pop(); + } + } + }; + for (let pos = 0; ; pos++) { + if (input.next < 0) { + if (pos > 0) input.acceptToken(ShortExpression); + break; + } + if (commentHandler() || stringHandler()) { + input.advance(); + continue; + } + if ( + stack.length === 0 && + (input.next === curlyClose || + input.next === parenClose || + input.next === squareClose || + input.next === comma) + ) { + input.acceptToken(ShortExpression); + break; + } + switch (input.next) { + case parenOpen: + stack.push("("); + break; + case parenClose: + popIfMatch("("); + break; + case squareOpen: + stack.push("["); + break; + case squareClose: + popIfMatch("["); + break; + case curlyOpen: + stack.push("{"); + break; + case curlyClose: + popIfMatch("{"); + break; + } + if (pos !== 0 && stack.length === 0 && space.has(input.next)) { + input.acceptToken(ShortExpression); + break; + } + input.advance(); + } +});