tutuca 0.9.36 → 0.9.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1644,6 +1644,2054 @@ class ParseCtxClassSetCollector extends ParseContext {
1644
1644
  }
1645
1645
  }
1646
1646
 
1647
+ // tools/core/html-tokenizer.js
1648
+ var CharCodes = {
1649
+ Tab: 9,
1650
+ NewLine: 10,
1651
+ FormFeed: 12,
1652
+ CarriageReturn: 13,
1653
+ Space: 32,
1654
+ ExclamationMark: 33,
1655
+ Number: 35,
1656
+ SingleQuote: 39,
1657
+ DoubleQuote: 34,
1658
+ Dash: 45,
1659
+ Slash: 47,
1660
+ Zero: 48,
1661
+ Nine: 57,
1662
+ Semi: 59,
1663
+ Lt: 60,
1664
+ Eq: 61,
1665
+ Gt: 62,
1666
+ Questionmark: 63,
1667
+ UpperA: 65,
1668
+ LowerA: 97,
1669
+ UpperF: 70,
1670
+ LowerF: 102,
1671
+ UpperZ: 90,
1672
+ LowerZ: 122,
1673
+ LowerX: 120,
1674
+ OpeningSquareBracket: 91
1675
+ };
1676
+ var State = {
1677
+ Text: 1,
1678
+ BeforeTagName: 2,
1679
+ InTagName: 3,
1680
+ InSelfClosingTag: 4,
1681
+ BeforeClosingTagName: 5,
1682
+ InClosingTagName: 6,
1683
+ AfterClosingTagName: 7,
1684
+ BeforeAttributeName: 8,
1685
+ InAttributeName: 9,
1686
+ AfterAttributeName: 10,
1687
+ BeforeAttributeValue: 11,
1688
+ InAttributeValueDq: 12,
1689
+ InAttributeValueSq: 13,
1690
+ InAttributeValueNq: 14,
1691
+ BeforeDeclaration: 15,
1692
+ InDeclaration: 16,
1693
+ InProcessingInstruction: 17,
1694
+ BeforeComment: 18,
1695
+ CDATASequence: 19,
1696
+ DeclarationSequence: 20,
1697
+ InSpecialComment: 21,
1698
+ InCommentLike: 22,
1699
+ SpecialStartSequence: 23,
1700
+ InSpecialTag: 24,
1701
+ InPlainText: 25
1702
+ };
1703
+ function isWhitespace(c) {
1704
+ return c === CharCodes.Space || c === CharCodes.NewLine || c === CharCodes.Tab || c === CharCodes.FormFeed || c === CharCodes.CarriageReturn;
1705
+ }
1706
+ function isEndOfTagSection(c) {
1707
+ return c === CharCodes.Slash || c === CharCodes.Gt || isWhitespace(c);
1708
+ }
1709
+ function isASCIIAlpha(c) {
1710
+ return c >= CharCodes.LowerA && c <= CharCodes.LowerZ || c >= CharCodes.UpperA && c <= CharCodes.UpperZ;
1711
+ }
1712
+ var QuoteType = {
1713
+ NoValue: 0,
1714
+ Unquoted: 1,
1715
+ Single: 2,
1716
+ Double: 3
1717
+ };
1718
+ var Sequences = {
1719
+ Empty: new Uint8Array(0),
1720
+ Cdata: new Uint8Array([67, 68, 65, 84, 65, 91]),
1721
+ CdataEnd: new Uint8Array([93, 93, 62]),
1722
+ CommentEnd: new Uint8Array([45, 45, 33, 62]),
1723
+ Doctype: new Uint8Array([100, 111, 99, 116, 121, 112, 101]),
1724
+ IframeEnd: new Uint8Array([60, 47, 105, 102, 114, 97, 109, 101]),
1725
+ NoembedEnd: new Uint8Array([60, 47, 110, 111, 101, 109, 98, 101, 100]),
1726
+ NoframesEnd: new Uint8Array([60, 47, 110, 111, 102, 114, 97, 109, 101, 115]),
1727
+ Plaintext: new Uint8Array([60, 47, 112, 108, 97, 105, 110, 116, 101, 120, 116]),
1728
+ ScriptEnd: new Uint8Array([60, 47, 115, 99, 114, 105, 112, 116]),
1729
+ StyleEnd: new Uint8Array([60, 47, 115, 116, 121, 108, 101]),
1730
+ TitleEnd: new Uint8Array([60, 47, 116, 105, 116, 108, 101]),
1731
+ TextareaEnd: new Uint8Array([60, 47, 116, 101, 120, 116, 97, 114, 101, 97]),
1732
+ XmpEnd: new Uint8Array([60, 47, 120, 109, 112])
1733
+ };
1734
+ var specialStartSequences = new Map([
1735
+ [Sequences.IframeEnd[2], Sequences.IframeEnd],
1736
+ [Sequences.NoembedEnd[2], Sequences.NoembedEnd],
1737
+ [Sequences.Plaintext[2], Sequences.Plaintext],
1738
+ [Sequences.ScriptEnd[2], Sequences.ScriptEnd],
1739
+ [Sequences.TitleEnd[2], Sequences.TitleEnd],
1740
+ [Sequences.XmpEnd[2], Sequences.XmpEnd]
1741
+ ]);
1742
+
1743
+ class HtmlTokenizer {
1744
+ constructor({ xmlMode = false, recognizeSelfClosing = xmlMode } = {}, cbs) {
1745
+ this.cbs = cbs;
1746
+ this.xmlMode = xmlMode;
1747
+ this.recognizeSelfClosing = recognizeSelfClosing;
1748
+ this.state = State.Text;
1749
+ this.buffer = "";
1750
+ this.sectionStart = 0;
1751
+ this.index = 0;
1752
+ this.isSpecial = false;
1753
+ this.running = true;
1754
+ this.offset = 0;
1755
+ this.currentSequence = Sequences.Empty;
1756
+ this.sequenceIndex = 0;
1757
+ }
1758
+ reset() {
1759
+ this.state = State.Text;
1760
+ this.buffer = "";
1761
+ this.sectionStart = 0;
1762
+ this.index = 0;
1763
+ this.isSpecial = false;
1764
+ this.currentSequence = Sequences.Empty;
1765
+ this.sequenceIndex = 0;
1766
+ this.running = true;
1767
+ this.offset = 0;
1768
+ }
1769
+ write(chunk) {
1770
+ this.offset += this.buffer.length;
1771
+ this.buffer = chunk;
1772
+ this.parse();
1773
+ }
1774
+ end() {
1775
+ if (this.running)
1776
+ this.finish();
1777
+ }
1778
+ pause() {
1779
+ this.running = false;
1780
+ }
1781
+ resume() {
1782
+ this.running = true;
1783
+ if (this.index < this.buffer.length + this.offset) {
1784
+ this.parse();
1785
+ }
1786
+ }
1787
+ stateText(c) {
1788
+ if (c === CharCodes.Lt || this.fastForwardTo(CharCodes.Lt)) {
1789
+ if (this.index > this.sectionStart) {
1790
+ this.cbs.ontext(this.sectionStart, this.index);
1791
+ }
1792
+ this.state = State.BeforeTagName;
1793
+ this.sectionStart = this.index;
1794
+ }
1795
+ }
1796
+ enterTagBody() {
1797
+ if (this.currentSequence === Sequences.Plaintext) {
1798
+ this.currentSequence = Sequences.Empty;
1799
+ this.state = State.InPlainText;
1800
+ } else if (this.isSpecial) {
1801
+ this.state = State.InSpecialTag;
1802
+ this.sequenceIndex = 0;
1803
+ } else {
1804
+ this.state = State.Text;
1805
+ }
1806
+ }
1807
+ stateSpecialStartSequence(c) {
1808
+ const lower = c | 32;
1809
+ if (this.sequenceIndex < this.currentSequence.length) {
1810
+ if (lower === this.currentSequence[this.sequenceIndex]) {
1811
+ this.sequenceIndex++;
1812
+ return;
1813
+ }
1814
+ if (this.sequenceIndex === 3) {
1815
+ if (this.currentSequence === Sequences.ScriptEnd && lower === Sequences.StyleEnd[3]) {
1816
+ this.currentSequence = Sequences.StyleEnd;
1817
+ this.sequenceIndex = 4;
1818
+ return;
1819
+ }
1820
+ if (this.currentSequence === Sequences.TitleEnd && lower === Sequences.TextareaEnd[3]) {
1821
+ this.currentSequence = Sequences.TextareaEnd;
1822
+ this.sequenceIndex = 4;
1823
+ return;
1824
+ }
1825
+ } else if (this.sequenceIndex === 4 && this.currentSequence === Sequences.NoembedEnd && lower === Sequences.NoframesEnd[4]) {
1826
+ this.currentSequence = Sequences.NoframesEnd;
1827
+ this.sequenceIndex = 5;
1828
+ return;
1829
+ }
1830
+ } else if (isEndOfTagSection(c)) {
1831
+ this.sequenceIndex = 0;
1832
+ this.state = State.InTagName;
1833
+ this.stateInTagName(c);
1834
+ return;
1835
+ }
1836
+ this.isSpecial = false;
1837
+ this.currentSequence = Sequences.Empty;
1838
+ this.sequenceIndex = 0;
1839
+ this.state = State.InTagName;
1840
+ this.stateInTagName(c);
1841
+ }
1842
+ stateCDATASequence(c) {
1843
+ if (c === Sequences.Cdata[this.sequenceIndex]) {
1844
+ if (++this.sequenceIndex === Sequences.Cdata.length) {
1845
+ this.state = State.InCommentLike;
1846
+ this.currentSequence = Sequences.CdataEnd;
1847
+ this.sequenceIndex = 0;
1848
+ this.sectionStart = this.index + 1;
1849
+ }
1850
+ } else {
1851
+ this.sequenceIndex = 0;
1852
+ if (this.xmlMode) {
1853
+ this.state = State.InDeclaration;
1854
+ this.stateInDeclaration(c);
1855
+ } else {
1856
+ this.state = State.InSpecialComment;
1857
+ this.stateInSpecialComment(c);
1858
+ }
1859
+ }
1860
+ }
1861
+ fastForwardTo(c) {
1862
+ while (++this.index < this.buffer.length + this.offset) {
1863
+ if (this.buffer.charCodeAt(this.index - this.offset) === c) {
1864
+ return true;
1865
+ }
1866
+ }
1867
+ this.index = this.buffer.length + this.offset - 1;
1868
+ return false;
1869
+ }
1870
+ emitComment(offset) {
1871
+ this.cbs.oncomment(this.sectionStart, this.index, offset);
1872
+ this.sequenceIndex = 0;
1873
+ this.sectionStart = this.index + 1;
1874
+ this.state = State.Text;
1875
+ }
1876
+ stateInCommentLike(c) {
1877
+ if (!this.xmlMode && this.currentSequence === Sequences.CommentEnd && this.sequenceIndex <= 1 && this.index === this.sectionStart + this.sequenceIndex && c === CharCodes.Gt) {
1878
+ this.emitComment(this.sequenceIndex);
1879
+ } else if (this.currentSequence === Sequences.CommentEnd && this.sequenceIndex === 2 && c === CharCodes.Gt) {
1880
+ this.emitComment(2);
1881
+ } else if (this.currentSequence === Sequences.CommentEnd && this.sequenceIndex === this.currentSequence.length - 1 && c !== CharCodes.Gt) {
1882
+ this.sequenceIndex = Number(c === CharCodes.Dash);
1883
+ } else if (c === this.currentSequence[this.sequenceIndex]) {
1884
+ if (++this.sequenceIndex === this.currentSequence.length) {
1885
+ if (this.currentSequence === Sequences.CdataEnd) {
1886
+ this.cbs.oncdata(this.sectionStart, this.index, 2);
1887
+ } else {
1888
+ this.cbs.oncomment(this.sectionStart, this.index, 3);
1889
+ }
1890
+ this.sequenceIndex = 0;
1891
+ this.sectionStart = this.index + 1;
1892
+ this.state = State.Text;
1893
+ }
1894
+ } else if (this.sequenceIndex === 0) {
1895
+ if (this.fastForwardTo(this.currentSequence[0])) {
1896
+ this.sequenceIndex = 1;
1897
+ }
1898
+ } else if (c !== this.currentSequence[this.sequenceIndex - 1]) {
1899
+ this.sequenceIndex = 0;
1900
+ }
1901
+ }
1902
+ isTagStartChar(c) {
1903
+ return this.xmlMode ? !isEndOfTagSection(c) : isASCIIAlpha(c);
1904
+ }
1905
+ stateInSpecialTag(c) {
1906
+ if (this.sequenceIndex === this.currentSequence.length) {
1907
+ if (isEndOfTagSection(c)) {
1908
+ const endOfText = this.index - this.currentSequence.length;
1909
+ if (this.sectionStart < endOfText) {
1910
+ const actualIndex = this.index;
1911
+ this.index = endOfText;
1912
+ this.cbs.ontext(this.sectionStart, endOfText);
1913
+ this.index = actualIndex;
1914
+ }
1915
+ this.isSpecial = false;
1916
+ this.sectionStart = endOfText + 2;
1917
+ this.stateInClosingTagName(c);
1918
+ return;
1919
+ }
1920
+ this.sequenceIndex = 0;
1921
+ }
1922
+ if ((c | 32) === this.currentSequence[this.sequenceIndex]) {
1923
+ this.sequenceIndex += 1;
1924
+ } else if (this.sequenceIndex === 0) {
1925
+ if (this.fastForwardTo(CharCodes.Lt)) {
1926
+ this.sequenceIndex = 1;
1927
+ }
1928
+ } else {
1929
+ this.sequenceIndex = Number(c === CharCodes.Lt);
1930
+ }
1931
+ }
1932
+ stateBeforeTagName(c) {
1933
+ if (c === CharCodes.ExclamationMark) {
1934
+ this.state = State.BeforeDeclaration;
1935
+ this.sectionStart = this.index + 1;
1936
+ } else if (c === CharCodes.Questionmark) {
1937
+ if (this.xmlMode) {
1938
+ this.state = State.InProcessingInstruction;
1939
+ this.sequenceIndex = 0;
1940
+ this.sectionStart = this.index + 1;
1941
+ } else {
1942
+ this.state = State.InSpecialComment;
1943
+ this.sectionStart = this.index;
1944
+ }
1945
+ } else if (this.isTagStartChar(c)) {
1946
+ this.sectionStart = this.index;
1947
+ const special = this.xmlMode || this.cbs.isInForeignContext?.() ? undefined : specialStartSequences.get(c | 32);
1948
+ if (special === undefined) {
1949
+ this.state = State.InTagName;
1950
+ } else {
1951
+ this.isSpecial = true;
1952
+ this.currentSequence = special;
1953
+ this.sequenceIndex = 3;
1954
+ this.state = State.SpecialStartSequence;
1955
+ }
1956
+ } else if (c === CharCodes.Slash) {
1957
+ this.state = State.BeforeClosingTagName;
1958
+ } else {
1959
+ this.state = State.Text;
1960
+ this.stateText(c);
1961
+ }
1962
+ }
1963
+ stateInTagName(c) {
1964
+ if (isEndOfTagSection(c)) {
1965
+ this.cbs.onopentagname(this.sectionStart, this.index);
1966
+ this.sectionStart = -1;
1967
+ this.state = State.BeforeAttributeName;
1968
+ this.stateBeforeAttributeName(c);
1969
+ }
1970
+ }
1971
+ stateBeforeClosingTagName(c) {
1972
+ if (isWhitespace(c)) {
1973
+ if (!this.xmlMode) {
1974
+ this.state = State.InSpecialComment;
1975
+ this.sectionStart = this.index;
1976
+ }
1977
+ } else if (c === CharCodes.Gt) {
1978
+ this.state = State.Text;
1979
+ if (!this.xmlMode) {
1980
+ this.sectionStart = this.index + 1;
1981
+ }
1982
+ } else {
1983
+ this.state = this.isTagStartChar(c) ? State.InClosingTagName : State.InSpecialComment;
1984
+ this.sectionStart = this.index;
1985
+ }
1986
+ }
1987
+ stateInClosingTagName(c) {
1988
+ if (isEndOfTagSection(c)) {
1989
+ this.cbs.onclosetag(this.sectionStart, this.index);
1990
+ this.sectionStart = -1;
1991
+ this.state = State.AfterClosingTagName;
1992
+ this.stateAfterClosingTagName(c);
1993
+ }
1994
+ }
1995
+ stateAfterClosingTagName(c) {
1996
+ if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) {
1997
+ this.state = State.Text;
1998
+ this.sectionStart = this.index + 1;
1999
+ }
2000
+ }
2001
+ stateBeforeAttributeName(c) {
2002
+ if (c === CharCodes.Gt) {
2003
+ this.cbs.onopentagend(this.index);
2004
+ this.enterTagBody();
2005
+ this.sectionStart = this.index + 1;
2006
+ } else if (c === CharCodes.Slash) {
2007
+ this.state = State.InSelfClosingTag;
2008
+ } else if (!isWhitespace(c)) {
2009
+ this.state = State.InAttributeName;
2010
+ this.sectionStart = this.index;
2011
+ }
2012
+ }
2013
+ stateInSelfClosingTag(c) {
2014
+ if (c === CharCodes.Gt) {
2015
+ this.cbs.onselfclosingtag(this.index);
2016
+ this.sectionStart = this.index + 1;
2017
+ if (!this.recognizeSelfClosing) {
2018
+ this.enterTagBody();
2019
+ return;
2020
+ }
2021
+ this.state = State.Text;
2022
+ this.isSpecial = false;
2023
+ this.currentSequence = Sequences.Empty;
2024
+ } else if (!isWhitespace(c)) {
2025
+ this.state = State.BeforeAttributeName;
2026
+ this.stateBeforeAttributeName(c);
2027
+ }
2028
+ }
2029
+ stateInAttributeName(c) {
2030
+ if (c === CharCodes.Eq || isEndOfTagSection(c)) {
2031
+ this.cbs.onattribname(this.sectionStart, this.index);
2032
+ this.sectionStart = this.index;
2033
+ this.state = State.AfterAttributeName;
2034
+ this.stateAfterAttributeName(c);
2035
+ }
2036
+ }
2037
+ stateAfterAttributeName(c) {
2038
+ if (c === CharCodes.Eq) {
2039
+ this.state = State.BeforeAttributeValue;
2040
+ } else if (c === CharCodes.Slash || c === CharCodes.Gt) {
2041
+ this.cbs.onattribend(QuoteType.NoValue, this.sectionStart);
2042
+ this.sectionStart = -1;
2043
+ this.state = State.BeforeAttributeName;
2044
+ this.stateBeforeAttributeName(c);
2045
+ } else if (!isWhitespace(c)) {
2046
+ this.cbs.onattribend(QuoteType.NoValue, this.sectionStart);
2047
+ this.state = State.InAttributeName;
2048
+ this.sectionStart = this.index;
2049
+ }
2050
+ }
2051
+ stateBeforeAttributeValue(c) {
2052
+ if (c === CharCodes.DoubleQuote) {
2053
+ this.state = State.InAttributeValueDq;
2054
+ this.sectionStart = this.index + 1;
2055
+ } else if (c === CharCodes.SingleQuote) {
2056
+ this.state = State.InAttributeValueSq;
2057
+ this.sectionStart = this.index + 1;
2058
+ } else if (!isWhitespace(c)) {
2059
+ this.sectionStart = this.index;
2060
+ this.state = State.InAttributeValueNq;
2061
+ this.stateInAttributeValueNoQuotes(c);
2062
+ }
2063
+ }
2064
+ handleInAttributeValue(c, quote) {
2065
+ if (c === quote || this.fastForwardTo(quote)) {
2066
+ this.cbs.onattribdata(this.sectionStart, this.index);
2067
+ this.sectionStart = -1;
2068
+ this.cbs.onattribend(quote === CharCodes.DoubleQuote ? QuoteType.Double : QuoteType.Single, this.index + 1);
2069
+ this.state = State.BeforeAttributeName;
2070
+ }
2071
+ }
2072
+ stateInAttributeValueDoubleQuotes(c) {
2073
+ this.handleInAttributeValue(c, CharCodes.DoubleQuote);
2074
+ }
2075
+ stateInAttributeValueSingleQuotes(c) {
2076
+ this.handleInAttributeValue(c, CharCodes.SingleQuote);
2077
+ }
2078
+ stateInAttributeValueNoQuotes(c) {
2079
+ if (isWhitespace(c) || c === CharCodes.Gt) {
2080
+ this.cbs.onattribdata(this.sectionStart, this.index);
2081
+ this.sectionStart = -1;
2082
+ this.cbs.onattribend(QuoteType.Unquoted, this.index);
2083
+ this.state = State.BeforeAttributeName;
2084
+ this.stateBeforeAttributeName(c);
2085
+ }
2086
+ }
2087
+ stateBeforeDeclaration(c) {
2088
+ if (c === CharCodes.OpeningSquareBracket) {
2089
+ this.state = State.CDATASequence;
2090
+ this.sequenceIndex = 0;
2091
+ } else if (this.xmlMode) {
2092
+ this.state = c === CharCodes.Dash ? State.BeforeComment : State.InDeclaration;
2093
+ } else if ((c | 32) === Sequences.Doctype[0]) {
2094
+ this.state = State.DeclarationSequence;
2095
+ this.currentSequence = Sequences.Doctype;
2096
+ this.sequenceIndex = 1;
2097
+ } else if (c === CharCodes.Gt) {
2098
+ this.cbs.oncomment(this.sectionStart, this.index, 0);
2099
+ this.state = State.Text;
2100
+ this.sectionStart = this.index + 1;
2101
+ } else if (c === CharCodes.Dash) {
2102
+ this.state = State.BeforeComment;
2103
+ } else {
2104
+ this.state = State.InSpecialComment;
2105
+ }
2106
+ }
2107
+ stateDeclarationSequence(c) {
2108
+ if (this.sequenceIndex === this.currentSequence.length) {
2109
+ this.state = State.InDeclaration;
2110
+ this.stateInDeclaration(c);
2111
+ } else if ((c | 32) === this.currentSequence[this.sequenceIndex]) {
2112
+ this.sequenceIndex += 1;
2113
+ } else if (c === CharCodes.Gt) {
2114
+ this.cbs.oncomment(this.sectionStart, this.index, 0);
2115
+ this.state = State.Text;
2116
+ this.sectionStart = this.index + 1;
2117
+ } else {
2118
+ this.state = State.InSpecialComment;
2119
+ }
2120
+ }
2121
+ stateInDeclaration(c) {
2122
+ if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) {
2123
+ this.cbs.ondeclaration(this.sectionStart, this.index);
2124
+ this.state = State.Text;
2125
+ this.sectionStart = this.index + 1;
2126
+ }
2127
+ }
2128
+ stateInProcessingInstruction(c) {
2129
+ if (c === CharCodes.Questionmark) {
2130
+ this.sequenceIndex = 1;
2131
+ } else if (c === CharCodes.Gt && this.sequenceIndex === 1) {
2132
+ this.cbs.onprocessinginstruction(this.sectionStart, this.index - 1);
2133
+ this.sequenceIndex = 0;
2134
+ this.state = State.Text;
2135
+ this.sectionStart = this.index + 1;
2136
+ } else {
2137
+ this.sequenceIndex = Number(this.fastForwardTo(CharCodes.Questionmark));
2138
+ }
2139
+ }
2140
+ stateBeforeComment(c) {
2141
+ if (c === CharCodes.Dash) {
2142
+ this.state = State.InCommentLike;
2143
+ this.currentSequence = Sequences.CommentEnd;
2144
+ this.sequenceIndex = 0;
2145
+ this.sectionStart = this.index + 1;
2146
+ } else if (this.xmlMode) {
2147
+ this.state = State.InDeclaration;
2148
+ } else if (c === CharCodes.Gt) {
2149
+ this.cbs.oncomment(this.sectionStart, this.index, 0);
2150
+ this.state = State.Text;
2151
+ this.sectionStart = this.index + 1;
2152
+ } else {
2153
+ this.state = State.InSpecialComment;
2154
+ }
2155
+ }
2156
+ stateInSpecialComment(c) {
2157
+ if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) {
2158
+ this.cbs.oncomment(this.sectionStart, this.index, 0);
2159
+ this.state = State.Text;
2160
+ this.sectionStart = this.index + 1;
2161
+ }
2162
+ }
2163
+ cleanup() {
2164
+ if (this.running && this.sectionStart !== this.index) {
2165
+ if (this.state === State.Text || this.state === State.InPlainText || this.state === State.InSpecialTag && this.sequenceIndex === 0) {
2166
+ this.cbs.ontext(this.sectionStart, this.index);
2167
+ this.sectionStart = this.index;
2168
+ } else if (this.state === State.InAttributeValueDq || this.state === State.InAttributeValueSq || this.state === State.InAttributeValueNq) {
2169
+ this.cbs.onattribdata(this.sectionStart, this.index);
2170
+ this.sectionStart = this.index;
2171
+ }
2172
+ }
2173
+ }
2174
+ shouldContinue() {
2175
+ return this.index < this.buffer.length + this.offset && this.running;
2176
+ }
2177
+ parse() {
2178
+ while (this.shouldContinue()) {
2179
+ const c = this.buffer.charCodeAt(this.index - this.offset);
2180
+ switch (this.state) {
2181
+ case State.Text:
2182
+ this.stateText(c);
2183
+ break;
2184
+ case State.InPlainText:
2185
+ this.index = this.buffer.length + this.offset - 1;
2186
+ break;
2187
+ case State.SpecialStartSequence:
2188
+ this.stateSpecialStartSequence(c);
2189
+ break;
2190
+ case State.InSpecialTag:
2191
+ this.stateInSpecialTag(c);
2192
+ break;
2193
+ case State.CDATASequence:
2194
+ this.stateCDATASequence(c);
2195
+ break;
2196
+ case State.DeclarationSequence:
2197
+ this.stateDeclarationSequence(c);
2198
+ break;
2199
+ case State.InAttributeValueDq:
2200
+ this.stateInAttributeValueDoubleQuotes(c);
2201
+ break;
2202
+ case State.InAttributeName:
2203
+ this.stateInAttributeName(c);
2204
+ break;
2205
+ case State.InCommentLike:
2206
+ this.stateInCommentLike(c);
2207
+ break;
2208
+ case State.InSpecialComment:
2209
+ this.stateInSpecialComment(c);
2210
+ break;
2211
+ case State.BeforeAttributeName:
2212
+ this.stateBeforeAttributeName(c);
2213
+ break;
2214
+ case State.InTagName:
2215
+ this.stateInTagName(c);
2216
+ break;
2217
+ case State.InClosingTagName:
2218
+ this.stateInClosingTagName(c);
2219
+ break;
2220
+ case State.BeforeTagName:
2221
+ this.stateBeforeTagName(c);
2222
+ break;
2223
+ case State.AfterAttributeName:
2224
+ this.stateAfterAttributeName(c);
2225
+ break;
2226
+ case State.InAttributeValueSq:
2227
+ this.stateInAttributeValueSingleQuotes(c);
2228
+ break;
2229
+ case State.BeforeAttributeValue:
2230
+ this.stateBeforeAttributeValue(c);
2231
+ break;
2232
+ case State.BeforeClosingTagName:
2233
+ this.stateBeforeClosingTagName(c);
2234
+ break;
2235
+ case State.AfterClosingTagName:
2236
+ this.stateAfterClosingTagName(c);
2237
+ break;
2238
+ case State.InAttributeValueNq:
2239
+ this.stateInAttributeValueNoQuotes(c);
2240
+ break;
2241
+ case State.InSelfClosingTag:
2242
+ this.stateInSelfClosingTag(c);
2243
+ break;
2244
+ case State.InDeclaration:
2245
+ this.stateInDeclaration(c);
2246
+ break;
2247
+ case State.BeforeDeclaration:
2248
+ this.stateBeforeDeclaration(c);
2249
+ break;
2250
+ case State.BeforeComment:
2251
+ this.stateBeforeComment(c);
2252
+ break;
2253
+ case State.InProcessingInstruction:
2254
+ this.stateInProcessingInstruction(c);
2255
+ break;
2256
+ }
2257
+ this.index++;
2258
+ }
2259
+ this.cleanup();
2260
+ }
2261
+ finish() {
2262
+ this.handleTrailingData();
2263
+ this.cbs.onend();
2264
+ }
2265
+ handleTrailingCommentLikeData(endIndex) {
2266
+ if (this.state !== State.InCommentLike)
2267
+ return false;
2268
+ if (this.currentSequence === Sequences.CdataEnd) {
2269
+ if (this.xmlMode) {
2270
+ if (this.sectionStart < endIndex) {
2271
+ this.cbs.oncdata(this.sectionStart, endIndex, 0);
2272
+ }
2273
+ } else {
2274
+ const cdataStart = this.sectionStart - Sequences.Cdata.length - 1;
2275
+ this.cbs.oncomment(cdataStart, endIndex, 0);
2276
+ }
2277
+ } else {
2278
+ const offset = this.xmlMode ? 0 : Math.min(this.sequenceIndex, Sequences.CommentEnd.length - 1);
2279
+ this.cbs.oncomment(this.sectionStart, endIndex, offset);
2280
+ }
2281
+ return true;
2282
+ }
2283
+ handleTrailingMarkupDeclaration(endIndex) {
2284
+ if (this.xmlMode) {
2285
+ switch (this.state) {
2286
+ case State.InSpecialComment:
2287
+ case State.BeforeComment:
2288
+ case State.CDATASequence:
2289
+ case State.DeclarationSequence:
2290
+ case State.InDeclaration:
2291
+ this.cbs.ontext(this.sectionStart, endIndex);
2292
+ return true;
2293
+ default:
2294
+ return false;
2295
+ }
2296
+ }
2297
+ switch (this.state) {
2298
+ case State.BeforeDeclaration:
2299
+ case State.InSpecialComment:
2300
+ case State.BeforeComment:
2301
+ case State.CDATASequence:
2302
+ this.cbs.oncomment(this.sectionStart, endIndex, 0);
2303
+ return true;
2304
+ case State.DeclarationSequence:
2305
+ if (this.sequenceIndex !== Sequences.Doctype.length) {
2306
+ this.cbs.oncomment(this.sectionStart, endIndex, 0);
2307
+ }
2308
+ return true;
2309
+ case State.InDeclaration:
2310
+ return true;
2311
+ default:
2312
+ return false;
2313
+ }
2314
+ }
2315
+ handleTrailingData() {
2316
+ const endIndex = this.buffer.length + this.offset;
2317
+ if (this.handleTrailingCommentLikeData(endIndex) || this.handleTrailingMarkupDeclaration(endIndex)) {
2318
+ return;
2319
+ }
2320
+ if (this.sectionStart >= endIndex)
2321
+ return;
2322
+ switch (this.state) {
2323
+ case State.InTagName:
2324
+ case State.BeforeAttributeName:
2325
+ case State.BeforeAttributeValue:
2326
+ case State.AfterAttributeName:
2327
+ case State.InAttributeName:
2328
+ case State.InAttributeValueSq:
2329
+ case State.InAttributeValueDq:
2330
+ case State.InAttributeValueNq:
2331
+ case State.InClosingTagName:
2332
+ break;
2333
+ default:
2334
+ this.cbs.ontext(this.sectionStart, endIndex);
2335
+ }
2336
+ }
2337
+ }
2338
+
2339
+ // tools/core/htmllinter-tables.js
2340
+ var VOID_ELEMENTS = new Set([
2341
+ "area",
2342
+ "base",
2343
+ "br",
2344
+ "col",
2345
+ "embed",
2346
+ "hr",
2347
+ "img",
2348
+ "input",
2349
+ "link",
2350
+ "meta",
2351
+ "source",
2352
+ "track",
2353
+ "wbr"
2354
+ ]);
2355
+ var RAW_TEXT_ELEMENTS = new Set([
2356
+ "script",
2357
+ "style",
2358
+ "iframe",
2359
+ "noembed",
2360
+ "noframes",
2361
+ "noscript",
2362
+ "xmp",
2363
+ "plaintext"
2364
+ ]);
2365
+ var RCDATA_ELEMENTS = new Set(["textarea", "title"]);
2366
+ var SPECIAL_ELEMENTS = new Set([
2367
+ "address",
2368
+ "applet",
2369
+ "area",
2370
+ "article",
2371
+ "aside",
2372
+ "base",
2373
+ "basefont",
2374
+ "bgsound",
2375
+ "blockquote",
2376
+ "br",
2377
+ "button",
2378
+ "caption",
2379
+ "center",
2380
+ "col",
2381
+ "colgroup",
2382
+ "dd",
2383
+ "details",
2384
+ "dir",
2385
+ "div",
2386
+ "dl",
2387
+ "dt",
2388
+ "embed",
2389
+ "fieldset",
2390
+ "figcaption",
2391
+ "figure",
2392
+ "footer",
2393
+ "form",
2394
+ "h1",
2395
+ "h2",
2396
+ "h3",
2397
+ "h4",
2398
+ "h5",
2399
+ "h6",
2400
+ "header",
2401
+ "hgroup",
2402
+ "hr",
2403
+ "iframe",
2404
+ "img",
2405
+ "input",
2406
+ "keygen",
2407
+ "li",
2408
+ "link",
2409
+ "listing",
2410
+ "main",
2411
+ "marquee",
2412
+ "menu",
2413
+ "meta",
2414
+ "nav",
2415
+ "noembed",
2416
+ "noframes",
2417
+ "noscript",
2418
+ "object",
2419
+ "ol",
2420
+ "p",
2421
+ "param",
2422
+ "plaintext",
2423
+ "pre",
2424
+ "script",
2425
+ "search",
2426
+ "section",
2427
+ "select",
2428
+ "source",
2429
+ "style",
2430
+ "summary",
2431
+ "table",
2432
+ "tbody",
2433
+ "td",
2434
+ "template",
2435
+ "textarea",
2436
+ "tfoot",
2437
+ "th",
2438
+ "thead",
2439
+ "title",
2440
+ "tr",
2441
+ "track",
2442
+ "ul",
2443
+ "wbr",
2444
+ "xmp"
2445
+ ]);
2446
+ var FORMATTING_ELEMENTS = new Set([
2447
+ "a",
2448
+ "b",
2449
+ "big",
2450
+ "code",
2451
+ "em",
2452
+ "font",
2453
+ "i",
2454
+ "nobr",
2455
+ "s",
2456
+ "small",
2457
+ "strike",
2458
+ "strong",
2459
+ "tt",
2460
+ "u"
2461
+ ]);
2462
+ var DEFAULT_SCOPE_BOUNDARIES = new Set([
2463
+ "applet",
2464
+ "caption",
2465
+ "html",
2466
+ "table",
2467
+ "td",
2468
+ "th",
2469
+ "marquee",
2470
+ "object",
2471
+ "template"
2472
+ ]);
2473
+ var SCOPE_LIST_ITEM = new Set([...DEFAULT_SCOPE_BOUNDARIES, "ol", "ul"]);
2474
+ var SCOPE_BUTTON = new Set([...DEFAULT_SCOPE_BOUNDARIES, "button"]);
2475
+ var SCOPE_DEFAULT = DEFAULT_SCOPE_BOUNDARIES;
2476
+ var SCOPE_TABLE = new Set(["html", "table", "template"]);
2477
+ var SCOPE_SELECT = new Set;
2478
+ var STANDARD_SVG_CAMEL_ELEMENTS = new Set([
2479
+ "altGlyph",
2480
+ "altGlyphDef",
2481
+ "altGlyphItem",
2482
+ "animateColor",
2483
+ "animateMotion",
2484
+ "animateTransform",
2485
+ "clipPath",
2486
+ "feBlend",
2487
+ "feColorMatrix",
2488
+ "feComponentTransfer",
2489
+ "feComposite",
2490
+ "feConvolveMatrix",
2491
+ "feDiffuseLighting",
2492
+ "feDisplacementMap",
2493
+ "feDistantLight",
2494
+ "feDropShadow",
2495
+ "feFlood",
2496
+ "feFuncA",
2497
+ "feFuncB",
2498
+ "feFuncG",
2499
+ "feFuncR",
2500
+ "feGaussianBlur",
2501
+ "feImage",
2502
+ "feMerge",
2503
+ "feMergeNode",
2504
+ "feMorphology",
2505
+ "feOffset",
2506
+ "fePointLight",
2507
+ "feSpecularLighting",
2508
+ "feSpotLight",
2509
+ "feTile",
2510
+ "feTurbulence",
2511
+ "foreignObject",
2512
+ "glyphRef",
2513
+ "linearGradient",
2514
+ "radialGradient",
2515
+ "textPath"
2516
+ ]);
2517
+ var STANDARD_SVG_CAMEL_ATTRS = new Set([
2518
+ "attributeName",
2519
+ "attributeType",
2520
+ "baseFrequency",
2521
+ "baseProfile",
2522
+ "calcMode",
2523
+ "clipPathUnits",
2524
+ "diffuseConstant",
2525
+ "edgeMode",
2526
+ "filterUnits",
2527
+ "glyphRef",
2528
+ "gradientTransform",
2529
+ "gradientUnits",
2530
+ "kernelMatrix",
2531
+ "kernelUnitLength",
2532
+ "keyPoints",
2533
+ "keySplines",
2534
+ "keyTimes",
2535
+ "lengthAdjust",
2536
+ "limitingConeAngle",
2537
+ "markerHeight",
2538
+ "markerUnits",
2539
+ "markerWidth",
2540
+ "maskContentUnits",
2541
+ "maskUnits",
2542
+ "numOctaves",
2543
+ "pathLength",
2544
+ "patternContentUnits",
2545
+ "patternTransform",
2546
+ "patternUnits",
2547
+ "pointsAtX",
2548
+ "pointsAtY",
2549
+ "pointsAtZ",
2550
+ "preserveAlpha",
2551
+ "preserveAspectRatio",
2552
+ "primitiveUnits",
2553
+ "refX",
2554
+ "refY",
2555
+ "repeatCount",
2556
+ "repeatDur",
2557
+ "requiredExtensions",
2558
+ "requiredFeatures",
2559
+ "specularConstant",
2560
+ "specularExponent",
2561
+ "spreadMethod",
2562
+ "startOffset",
2563
+ "stdDeviation",
2564
+ "stitchTiles",
2565
+ "surfaceScale",
2566
+ "systemLanguage",
2567
+ "tableValues",
2568
+ "targetX",
2569
+ "targetY",
2570
+ "textLength",
2571
+ "viewBox",
2572
+ "xChannelSelector",
2573
+ "yChannelSelector",
2574
+ "zoomAndPan"
2575
+ ]);
2576
+ var MATHML_CAMEL_ATTRS = new Set(["definitionURL"]);
2577
+ var FOREIGN_BREAKOUT_TAGS = new Set([
2578
+ "b",
2579
+ "big",
2580
+ "blockquote",
2581
+ "body",
2582
+ "br",
2583
+ "center",
2584
+ "code",
2585
+ "dd",
2586
+ "div",
2587
+ "dl",
2588
+ "dt",
2589
+ "em",
2590
+ "embed",
2591
+ "h1",
2592
+ "h2",
2593
+ "h3",
2594
+ "h4",
2595
+ "h5",
2596
+ "h6",
2597
+ "head",
2598
+ "hr",
2599
+ "i",
2600
+ "img",
2601
+ "li",
2602
+ "listing",
2603
+ "menu",
2604
+ "meta",
2605
+ "nobr",
2606
+ "ol",
2607
+ "p",
2608
+ "pre",
2609
+ "ruby",
2610
+ "s",
2611
+ "small",
2612
+ "span",
2613
+ "strong",
2614
+ "strike",
2615
+ "sub",
2616
+ "sup",
2617
+ "table",
2618
+ "tt",
2619
+ "u",
2620
+ "ul",
2621
+ "var"
2622
+ ]);
2623
+ var MATHML_TEXT_INTEGRATION_POINTS = new Set(["mi", "mo", "mn", "ms", "mtext"]);
2624
+ var BLOCK_LEVEL_AUTO_CLOSE_P = new Set([
2625
+ "address",
2626
+ "article",
2627
+ "aside",
2628
+ "blockquote",
2629
+ "center",
2630
+ "details",
2631
+ "dialog",
2632
+ "dir",
2633
+ "div",
2634
+ "dl",
2635
+ "fieldset",
2636
+ "figcaption",
2637
+ "figure",
2638
+ "footer",
2639
+ "form",
2640
+ "h1",
2641
+ "h2",
2642
+ "h3",
2643
+ "h4",
2644
+ "h5",
2645
+ "h6",
2646
+ "header",
2647
+ "hgroup",
2648
+ "hr",
2649
+ "main",
2650
+ "menu",
2651
+ "nav",
2652
+ "ol",
2653
+ "p",
2654
+ "plaintext",
2655
+ "pre",
2656
+ "search",
2657
+ "section",
2658
+ "summary",
2659
+ "table",
2660
+ "ul",
2661
+ "xmp",
2662
+ "li",
2663
+ "dd",
2664
+ "dt"
2665
+ ]);
2666
+ var SELECT_VALID_CHILDREN = new Set(["option", "optgroup", "hr", "script", "template"]);
2667
+ var SELECT_BREAKOUT_TAGS = new Set(["input", "keygen", "textarea", "select"]);
2668
+ var MODES = Object.freeze({
2669
+ inBody: "inBody",
2670
+ inTable: "inTable",
2671
+ inTableText: "inTableText",
2672
+ inCaption: "inCaption",
2673
+ inColumnGroup: "inColumnGroup",
2674
+ inTableBody: "inTableBody",
2675
+ inRow: "inRow",
2676
+ inCell: "inCell",
2677
+ inSelect: "inSelect",
2678
+ inSelectInTable: "inSelectInTable",
2679
+ inTemplate: "inTemplate",
2680
+ text: "text"
2681
+ });
2682
+ var NS = Object.freeze({
2683
+ html: "html",
2684
+ svg: "svg",
2685
+ math: "math"
2686
+ });
2687
+ var FRAGMENT_CONTEXT_MODES = Object.freeze({
2688
+ template: { mode: MODES.inTemplate, ns: NS.html },
2689
+ body: { mode: MODES.inBody, ns: NS.html },
2690
+ div: { mode: MODES.inBody, ns: NS.html },
2691
+ table: { mode: MODES.inTable, ns: NS.html },
2692
+ tbody: { mode: MODES.inTableBody, ns: NS.html },
2693
+ thead: { mode: MODES.inTableBody, ns: NS.html },
2694
+ tfoot: { mode: MODES.inTableBody, ns: NS.html },
2695
+ caption: { mode: MODES.inCaption, ns: NS.html },
2696
+ colgroup: { mode: MODES.inColumnGroup, ns: NS.html },
2697
+ tr: { mode: MODES.inRow, ns: NS.html },
2698
+ td: { mode: MODES.inCell, ns: NS.html },
2699
+ th: { mode: MODES.inCell, ns: NS.html },
2700
+ select: { mode: MODES.inSelect, ns: NS.html },
2701
+ svg: { mode: MODES.inBody, ns: NS.svg },
2702
+ math: { mode: MODES.inBody, ns: NS.math }
2703
+ });
2704
+
2705
+ // tools/core/htmllinter.js
2706
+ var HTML_TAG_NAME_HAS_UPPERCASE = "HTML_TAG_NAME_HAS_UPPERCASE";
2707
+ var HTML_SVG_TAG_WILL_LOWERCASE = "HTML_SVG_TAG_WILL_LOWERCASE";
2708
+ var HTML_TAG_NOT_ALLOWED_IN_PARENT = "HTML_TAG_NOT_ALLOWED_IN_PARENT";
2709
+ var HTML_TEXT_NOT_ALLOWED_IN_PARENT = "HTML_TEXT_NOT_ALLOWED_IN_PARENT";
2710
+ var HTML_VOID_ELEMENT_HAS_CLOSE_TAG = "HTML_VOID_ELEMENT_HAS_CLOSE_TAG";
2711
+ var HTML_DUPLICATE_FORM = "HTML_DUPLICATE_FORM";
2712
+ var HTML_NESTED_INTERACTIVE = "HTML_NESTED_INTERACTIVE";
2713
+ var HTML_MISNESTED_FORMATTING = "HTML_MISNESTED_FORMATTING";
2714
+ var HTML_UNEXPECTED_END_TAG = "HTML_UNEXPECTED_END_TAG";
2715
+ var LEVEL_ERROR = "error";
2716
+ var LEVEL_WARN = "warn";
2717
+ var TABLE_SCOPE_TAGS = new Set([
2718
+ "caption",
2719
+ "colgroup",
2720
+ "thead",
2721
+ "tbody",
2722
+ "tfoot",
2723
+ "tr",
2724
+ "td",
2725
+ "th",
2726
+ "table"
2727
+ ]);
2728
+ var TABLE_BODY_CELL_TAGS = new Set(["td", "th"]);
2729
+ function lintHtml(html, onFinding, opts = {}) {
2730
+ const TokenizerClass = opts.TokenizerClass ?? HtmlTokenizer;
2731
+ const ctx = new LinterCtx(html, onFinding, opts);
2732
+ const tokenizer = new TokenizerClass({ xmlMode: false, decodeEntities: false, recognizeSelfClosing: true }, ctx);
2733
+ ctx.tokenizer = tokenizer;
2734
+ tokenizer.write(html);
2735
+ tokenizer.end();
2736
+ return ctx.findingCount;
2737
+ }
2738
+
2739
+ class LinterCtx {
2740
+ constructor(html, onFinding, opts) {
2741
+ this.html = html;
2742
+ this.onFinding = onFinding;
2743
+ this.findingCount = 0;
2744
+ this.lineStarts = computeLineStarts(html);
2745
+ const ctxName = opts.fragmentContext ?? "template";
2746
+ const ctxInfo = FRAGMENT_CONTEXT_MODES[ctxName] ?? FRAGMENT_CONTEXT_MODES.template;
2747
+ this.openElements = [];
2748
+ if (ctxName === "tr") {
2749
+ this.openElements.push({ name: "table", ns: NS.html, start: -1 });
2750
+ this.openElements.push({ name: "tbody", ns: NS.html, start: -1 });
2751
+ } else if (ctxName === "tbody" || ctxName === "thead" || ctxName === "tfoot") {
2752
+ this.openElements.push({ name: "table", ns: NS.html, start: -1 });
2753
+ } else if (ctxName === "td" || ctxName === "th") {
2754
+ this.openElements.push({ name: "table", ns: NS.html, start: -1 });
2755
+ this.openElements.push({ name: "tbody", ns: NS.html, start: -1 });
2756
+ this.openElements.push({ name: "tr", ns: NS.html, start: -1 });
2757
+ } else if (ctxName === "caption") {
2758
+ this.openElements.push({ name: "table", ns: NS.html, start: -1 });
2759
+ } else if (ctxName === "colgroup") {
2760
+ this.openElements.push({ name: "table", ns: NS.html, start: -1 });
2761
+ } else if (ctxName === "svg") {
2762
+ this.openElements.push({ name: "svg", ns: NS.svg, start: -1 });
2763
+ } else if (ctxName === "math") {
2764
+ this.openElements.push({ name: "math", ns: NS.math, start: -1 });
2765
+ } else if (ctxName === "select") {
2766
+ this.openElements.push({ name: "select", ns: NS.html, start: -1 });
2767
+ }
2768
+ this.insertionMode = ctxInfo.mode;
2769
+ this.originalInsertionMode = MODES.inBody;
2770
+ this.templateInsertionModes = ctxName === "template" ? [MODES.inTemplate] : [];
2771
+ this.activeFormatting = [];
2772
+ this.formPointer = null;
2773
+ this.framesetOk = true;
2774
+ this.svgCamelElements = opts.svgCamelElements ?? STANDARD_SVG_CAMEL_ELEMENTS;
2775
+ this.transparentTagPrefixes = opts.transparentTagPrefixes ?? [];
2776
+ this.currentTagName = "";
2777
+ this.currentTagRawName = "";
2778
+ this.currentTagStart = 0;
2779
+ this.tokenizer = null;
2780
+ this.textRestoreMode = null;
2781
+ }
2782
+ onopentagname(start, end) {
2783
+ const raw = this.html.slice(start, end);
2784
+ this.currentTagRawName = raw;
2785
+ this.currentTagName = raw.toLowerCase();
2786
+ this.currentTagStart = start;
2787
+ }
2788
+ onattribname(_start, _end) {}
2789
+ onattribdata(_start, _end) {}
2790
+ onattribentity(_cp) {}
2791
+ onattribend(_quote, _end) {}
2792
+ ontextentity(_cp, _end) {}
2793
+ onopentagend(endIndex) {
2794
+ this.handleStartTag(false, endIndex);
2795
+ }
2796
+ onselfclosingtag(endIndex) {
2797
+ this.handleStartTag(true, endIndex);
2798
+ }
2799
+ onclosetag(start, end) {
2800
+ const raw = this.html.slice(start, end);
2801
+ const name = raw.toLowerCase();
2802
+ this.handleEndTag(name, start);
2803
+ }
2804
+ ontext(start, end) {
2805
+ if (start >= end)
2806
+ return;
2807
+ this.handleText(start, end);
2808
+ }
2809
+ oncomment(_start, _end, _endOffset) {}
2810
+ oncdata(start, _end, _endOffset) {
2811
+ if (this.currentNamespace() === NS.html) {
2812
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_WARN, start, {
2813
+ tag: "[CDATA[",
2814
+ mode: this.insertionMode,
2815
+ action: "ignored"
2816
+ });
2817
+ }
2818
+ }
2819
+ ondeclaration(_start, _end) {}
2820
+ onprocessinginstruction(_start, _end) {}
2821
+ isInForeignContext() {
2822
+ return this.currentNamespace() !== NS.html;
2823
+ }
2824
+ onend() {}
2825
+ report(id, level, offset, info) {
2826
+ this.findingCount++;
2827
+ const { line, column } = offsetToLineCol(this.lineStarts, offset);
2828
+ this.onFinding({
2829
+ id,
2830
+ level,
2831
+ info,
2832
+ location: { start: offset, end: offset + (info.tag?.length ?? 0), line, column }
2833
+ });
2834
+ }
2835
+ currentNode() {
2836
+ return this.openElements[this.openElements.length - 1] ?? null;
2837
+ }
2838
+ currentNamespace() {
2839
+ const top = this.currentNode();
2840
+ return top ? top.ns : NS.html;
2841
+ }
2842
+ push(name, ns, start) {
2843
+ this.openElements.push({ name, ns, start });
2844
+ }
2845
+ pop() {
2846
+ return this.openElements.pop();
2847
+ }
2848
+ hasInScope(target, scopeSet) {
2849
+ for (let i = this.openElements.length - 1;i >= 0; i--) {
2850
+ const f = this.openElements[i];
2851
+ if (f.name === target && f.ns === NS.html)
2852
+ return true;
2853
+ if (f.ns === NS.html && scopeSet.has(f.name))
2854
+ return false;
2855
+ if (f.ns !== NS.html) {
2856
+ return false;
2857
+ }
2858
+ }
2859
+ return false;
2860
+ }
2861
+ hasInDefaultScope(target) {
2862
+ return this.hasInScope(target, SCOPE_DEFAULT);
2863
+ }
2864
+ hasInButtonScope(target) {
2865
+ return this.hasInScope(target, SCOPE_BUTTON);
2866
+ }
2867
+ hasInListItemScope(target) {
2868
+ return this.hasInScope(target, SCOPE_LIST_ITEM);
2869
+ }
2870
+ hasInTableScope(target) {
2871
+ return this.hasInScope(target, SCOPE_TABLE);
2872
+ }
2873
+ hasInSelectScope(target) {
2874
+ for (let i = this.openElements.length - 1;i >= 0; i--) {
2875
+ const f = this.openElements[i];
2876
+ if (f.ns !== NS.html)
2877
+ return false;
2878
+ if (f.name === target)
2879
+ return true;
2880
+ if (f.name !== "optgroup" && f.name !== "option")
2881
+ return false;
2882
+ }
2883
+ return false;
2884
+ }
2885
+ popUntilName(name) {
2886
+ while (this.openElements.length) {
2887
+ const f = this.openElements.pop();
2888
+ if (f.name === name)
2889
+ return f;
2890
+ }
2891
+ return null;
2892
+ }
2893
+ generateImpliedEndTags(except = null) {
2894
+ const implied = new Set(["dd", "dt", "li", "optgroup", "option", "p", "rb", "rp", "rt", "rtc"]);
2895
+ while (this.openElements.length) {
2896
+ const top = this.currentNode();
2897
+ if (top.ns !== NS.html)
2898
+ break;
2899
+ if (!implied.has(top.name) || top.name === except)
2900
+ break;
2901
+ this.openElements.pop();
2902
+ }
2903
+ }
2904
+ isTransparentTag(name) {
2905
+ for (const prefix of this.transparentTagPrefixes) {
2906
+ if (name === prefix || name.startsWith(`${prefix}:`))
2907
+ return true;
2908
+ }
2909
+ return false;
2910
+ }
2911
+ handleStartTag(selfClosing, endIndex) {
2912
+ const name = this.currentTagName;
2913
+ const raw = this.currentTagRawName;
2914
+ const start = this.currentTagStart;
2915
+ const ns = this.currentNamespace();
2916
+ if (ns === NS.html) {
2917
+ if (raw !== name) {
2918
+ this.report(HTML_TAG_NAME_HAS_UPPERCASE, LEVEL_ERROR, start, {
2919
+ raw,
2920
+ lowercased: name
2921
+ });
2922
+ }
2923
+ } else if (ns === NS.svg) {
2924
+ if (raw !== raw.toLowerCase() && !this.svgCamelElements.has(raw)) {
2925
+ this.report(HTML_SVG_TAG_WILL_LOWERCASE, LEVEL_ERROR, start, {
2926
+ raw,
2927
+ lowercased: name
2928
+ });
2929
+ }
2930
+ }
2931
+ if (this.isTransparentTag(name))
2932
+ return;
2933
+ if (ns !== NS.html && !this.shouldBreakoutFromForeign(name)) {
2934
+ this.startTagInForeign(name, raw, selfClosing, start);
2935
+ return;
2936
+ }
2937
+ if (ns !== NS.html && this.shouldBreakoutFromForeign(name)) {
2938
+ while (this.openElements.length && this.currentNode()?.ns !== NS.html) {
2939
+ this.openElements.pop();
2940
+ }
2941
+ }
2942
+ this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
2943
+ }
2944
+ shouldBreakoutFromForeign(name) {
2945
+ if (FOREIGN_BREAKOUT_TAGS.has(name))
2946
+ return true;
2947
+ if (name === "font")
2948
+ return true;
2949
+ return false;
2950
+ }
2951
+ startTagInForeign(name, raw, selfClosing, start) {
2952
+ const ns = name === "svg" ? NS.svg : name === "math" ? NS.math : this.currentNamespace();
2953
+ const top = this.currentNode();
2954
+ if (top && top.ns === NS.math && MATHML_TEXT_INTEGRATION_POINTS.has(top.name) && name !== "mglyph" && name !== "malignmark") {
2955
+ this.dispatchStartTag(name, raw, selfClosing, start, start + raw.length);
2956
+ return;
2957
+ }
2958
+ if (selfClosing)
2959
+ return;
2960
+ this.push(raw, ns, start);
2961
+ }
2962
+ dispatchStartTag(name, raw, selfClosing, start, endIndex) {
2963
+ switch (this.insertionMode) {
2964
+ case MODES.inTemplate:
2965
+ return this.startInTemplate(name, raw, selfClosing, start, endIndex);
2966
+ case MODES.inBody:
2967
+ return this.startInBody(name, raw, selfClosing, start, endIndex);
2968
+ case MODES.inTable:
2969
+ return this.startInTable(name, raw, selfClosing, start, endIndex);
2970
+ case MODES.inTableText:
2971
+ this.flushTableText();
2972
+ this.insertionMode = this.originalInsertionMode;
2973
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
2974
+ case MODES.inCaption:
2975
+ return this.startInCaption(name, raw, selfClosing, start, endIndex);
2976
+ case MODES.inColumnGroup:
2977
+ return this.startInColumnGroup(name, raw, selfClosing, start, endIndex);
2978
+ case MODES.inTableBody:
2979
+ return this.startInTableBody(name, raw, selfClosing, start, endIndex);
2980
+ case MODES.inRow:
2981
+ return this.startInRow(name, raw, selfClosing, start, endIndex);
2982
+ case MODES.inCell:
2983
+ return this.startInCell(name, raw, selfClosing, start, endIndex);
2984
+ case MODES.inSelect:
2985
+ return this.startInSelect(name, raw, selfClosing, start, endIndex);
2986
+ case MODES.inSelectInTable:
2987
+ return this.startInSelectInTable(name, raw, selfClosing, start, endIndex);
2988
+ case MODES.text:
2989
+ return;
2990
+ }
2991
+ }
2992
+ startInBody(name, raw, selfClosing, start, _endIndex) {
2993
+ if (name === "html" || name === "head" || name === "body" || name === "frame" || name === "frameset") {
2994
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_WARN, start, {
2995
+ tag: raw,
2996
+ mode: this.insertionMode,
2997
+ action: "ignored"
2998
+ });
2999
+ return;
3000
+ }
3001
+ if (name === "address" || name === "article" || name === "aside" || name === "blockquote" || name === "center" || name === "details" || name === "dialog" || name === "dir" || name === "div" || name === "dl" || name === "fieldset" || name === "figcaption" || name === "figure" || name === "footer" || name === "header" || name === "hgroup" || name === "main" || name === "menu" || name === "nav" || name === "ol" || name === "p" || name === "search" || name === "section" || name === "summary" || name === "ul") {
3002
+ if (this.hasInButtonScope("p"))
3003
+ this.implicitlyClose("p", start, raw);
3004
+ this.push(raw, NS.html, start);
3005
+ return;
3006
+ }
3007
+ if (name === "h1" || name === "h2" || name === "h3" || name === "h4" || name === "h5" || name === "h6") {
3008
+ if (this.hasInButtonScope("p"))
3009
+ this.implicitlyClose("p", start, raw);
3010
+ const top = this.currentNode();
3011
+ if (top && /^h[1-6]$/.test(top.name)) {
3012
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3013
+ tag: raw,
3014
+ parent: top.name,
3015
+ mode: this.insertionMode,
3016
+ action: "auto-close-implicit"
3017
+ });
3018
+ this.openElements.pop();
3019
+ }
3020
+ this.push(raw, NS.html, start);
3021
+ return;
3022
+ }
3023
+ if (name === "pre" || name === "listing") {
3024
+ if (this.hasInButtonScope("p"))
3025
+ this.implicitlyClose("p", start, raw);
3026
+ this.push(raw, NS.html, start);
3027
+ this.framesetOk = false;
3028
+ return;
3029
+ }
3030
+ if (name === "form") {
3031
+ if (this.formPointer !== null && !this.openElementsHas("template")) {
3032
+ this.report(HTML_DUPLICATE_FORM, LEVEL_ERROR, start, {
3033
+ tag: raw,
3034
+ mode: this.insertionMode
3035
+ });
3036
+ return;
3037
+ }
3038
+ if (this.hasInButtonScope("p"))
3039
+ this.implicitlyClose("p", start, raw);
3040
+ this.push(raw, NS.html, start);
3041
+ this.formPointer = this.currentNode();
3042
+ return;
3043
+ }
3044
+ if (name === "li") {
3045
+ this.framesetOk = false;
3046
+ for (let i = this.openElements.length - 1;i >= 0; i--) {
3047
+ const f = this.openElements[i];
3048
+ if (f.ns !== NS.html)
3049
+ break;
3050
+ if (f.name === "li") {
3051
+ this.generateImpliedEndTags("li");
3052
+ while (this.openElements.length) {
3053
+ const popped = this.openElements.pop();
3054
+ if (popped.name === "li")
3055
+ break;
3056
+ }
3057
+ break;
3058
+ }
3059
+ if (SPECIAL_ELEMENTS.has(f.name) && f.name !== "address" && f.name !== "div" && f.name !== "p") {
3060
+ break;
3061
+ }
3062
+ }
3063
+ if (this.hasInButtonScope("p"))
3064
+ this.implicitlyClose("p", start, raw);
3065
+ this.push(raw, NS.html, start);
3066
+ return;
3067
+ }
3068
+ if (name === "dd" || name === "dt") {
3069
+ this.framesetOk = false;
3070
+ for (let i = this.openElements.length - 1;i >= 0; i--) {
3071
+ const f = this.openElements[i];
3072
+ if (f.ns !== NS.html)
3073
+ break;
3074
+ if (f.name === "dd" || f.name === "dt") {
3075
+ this.generateImpliedEndTags(f.name);
3076
+ while (this.openElements.length) {
3077
+ const popped = this.openElements.pop();
3078
+ if (popped.name === f.name)
3079
+ break;
3080
+ }
3081
+ break;
3082
+ }
3083
+ if (SPECIAL_ELEMENTS.has(f.name) && f.name !== "address" && f.name !== "div" && f.name !== "p") {
3084
+ break;
3085
+ }
3086
+ }
3087
+ if (this.hasInButtonScope("p"))
3088
+ this.implicitlyClose("p", start, raw);
3089
+ this.push(raw, NS.html, start);
3090
+ return;
3091
+ }
3092
+ if (name === "plaintext") {
3093
+ if (this.hasInButtonScope("p"))
3094
+ this.implicitlyClose("p", start, raw);
3095
+ this.push(raw, NS.html, start);
3096
+ return;
3097
+ }
3098
+ if (name === "button") {
3099
+ if (this.hasInDefaultScope("button")) {
3100
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3101
+ tag: raw,
3102
+ parent: "button",
3103
+ mode: this.insertionMode,
3104
+ action: "auto-close-implicit"
3105
+ });
3106
+ this.generateImpliedEndTags();
3107
+ this.popUntilName("button");
3108
+ }
3109
+ this.push(raw, NS.html, start);
3110
+ this.framesetOk = false;
3111
+ return;
3112
+ }
3113
+ if (name === "a") {
3114
+ if (this.openElementsHas("a") || this.activeFormattingHas("a")) {
3115
+ this.report(HTML_NESTED_INTERACTIVE, LEVEL_WARN, start, {
3116
+ tag: raw,
3117
+ mode: this.insertionMode
3118
+ });
3119
+ this.runAdoptionAgency("a");
3120
+ }
3121
+ this.push(raw, NS.html, start);
3122
+ this.activeFormatting.push(this.currentNode());
3123
+ return;
3124
+ }
3125
+ if (FORMATTING_ELEMENTS.has(name)) {
3126
+ this.push(raw, NS.html, start);
3127
+ this.activeFormatting.push(this.currentNode());
3128
+ return;
3129
+ }
3130
+ if (name === "nobr") {
3131
+ if (this.hasInDefaultScope("nobr")) {
3132
+ this.report(HTML_NESTED_INTERACTIVE, LEVEL_WARN, start, {
3133
+ tag: raw,
3134
+ mode: this.insertionMode
3135
+ });
3136
+ this.runAdoptionAgency("nobr");
3137
+ }
3138
+ this.push(raw, NS.html, start);
3139
+ this.activeFormatting.push(this.currentNode());
3140
+ return;
3141
+ }
3142
+ if (name === "table") {
3143
+ if (this.hasInButtonScope("p"))
3144
+ this.implicitlyClose("p", start, raw);
3145
+ this.push(raw, NS.html, start);
3146
+ this.framesetOk = false;
3147
+ this.insertionMode = MODES.inTable;
3148
+ return;
3149
+ }
3150
+ if (name === "area" || name === "br" || name === "embed" || name === "img" || name === "keygen" || name === "wbr" || name === "input" || name === "param" || name === "source" || name === "track" || name === "hr" || name === "meta" || name === "link" || name === "col" || name === "base") {
3151
+ this.framesetOk = false;
3152
+ return;
3153
+ }
3154
+ if (name === "select") {
3155
+ if (this.hasInButtonScope("p"))
3156
+ this.implicitlyClose("p", start, raw);
3157
+ this.push(raw, NS.html, start);
3158
+ this.framesetOk = false;
3159
+ this.insertionMode = MODES.inSelect;
3160
+ return;
3161
+ }
3162
+ if (name === "option" || name === "optgroup") {
3163
+ if (this.currentNode()?.name === "option") {
3164
+ this.openElements.pop();
3165
+ }
3166
+ this.push(raw, NS.html, start);
3167
+ return;
3168
+ }
3169
+ if (name === "textarea" || name === "title" || RAW_TEXT_ELEMENTS.has(name)) {
3170
+ this.push(raw, NS.html, start);
3171
+ return;
3172
+ }
3173
+ if (name === "math" || name === "svg") {
3174
+ this.push(raw, name === "svg" ? NS.svg : NS.math, start);
3175
+ this.framesetOk = false;
3176
+ return;
3177
+ }
3178
+ if (name === "caption" || name === "col" || name === "colgroup" || name === "frame" || name === "tbody" || name === "td" || name === "tfoot" || name === "th" || name === "thead" || name === "tr") {
3179
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3180
+ tag: raw,
3181
+ parent: this.currentNode()?.name ?? "(root)",
3182
+ mode: this.insertionMode,
3183
+ action: "ignored"
3184
+ });
3185
+ return;
3186
+ }
3187
+ if (selfClosing)
3188
+ return;
3189
+ this.push(raw, NS.html, start);
3190
+ }
3191
+ openElementsHas(name) {
3192
+ for (let i = this.openElements.length - 1;i >= 0; i--) {
3193
+ const f = this.openElements[i];
3194
+ if (f.ns === NS.html && f.name === name)
3195
+ return true;
3196
+ }
3197
+ return false;
3198
+ }
3199
+ activeFormattingHas(name) {
3200
+ for (let i = this.activeFormatting.length - 1;i >= 0; i--) {
3201
+ const e = this.activeFormatting[i];
3202
+ if (e === null)
3203
+ return false;
3204
+ if (e.name === name)
3205
+ return true;
3206
+ }
3207
+ return false;
3208
+ }
3209
+ runAdoptionAgency(name) {
3210
+ for (let i = this.activeFormatting.length - 1;i >= 0; i--) {
3211
+ const e = this.activeFormatting[i];
3212
+ if (e === null)
3213
+ break;
3214
+ if (e.name === name) {
3215
+ this.activeFormatting.splice(i, 1);
3216
+ const idx = this.openElements.indexOf(e);
3217
+ if (idx >= 0)
3218
+ this.openElements.splice(idx, 1);
3219
+ return;
3220
+ }
3221
+ }
3222
+ }
3223
+ implicitlyClose(name, _start, _newTagRaw) {
3224
+ while (this.openElements.length) {
3225
+ const popped = this.openElements.pop();
3226
+ if (popped.name === name)
3227
+ break;
3228
+ }
3229
+ }
3230
+ startInTemplate(name, raw, selfClosing, start, endIndex) {
3231
+ let next;
3232
+ if (name === "caption" || name === "colgroup" || name === "tbody" || name === "tfoot" || name === "thead") {
3233
+ next = MODES.inTable;
3234
+ } else if (name === "col") {
3235
+ next = MODES.inColumnGroup;
3236
+ } else if (name === "tr") {
3237
+ next = MODES.inTableBody;
3238
+ } else if (name === "td" || name === "th") {
3239
+ next = MODES.inRow;
3240
+ } else {
3241
+ this.popTemplateMode();
3242
+ this.pushTemplateMode(MODES.inBody);
3243
+ this.insertionMode = MODES.inBody;
3244
+ return this.startInBody(name, raw, selfClosing, start, endIndex);
3245
+ }
3246
+ this.popTemplateMode();
3247
+ this.pushTemplateMode(next);
3248
+ this.insertionMode = next;
3249
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3250
+ }
3251
+ popTemplateMode() {
3252
+ if (this.templateInsertionModes.length)
3253
+ this.templateInsertionModes.pop();
3254
+ }
3255
+ pushTemplateMode(mode) {
3256
+ this.templateInsertionModes.push(mode);
3257
+ }
3258
+ startInTable(name, raw, selfClosing, start, endIndex) {
3259
+ if (name === "caption") {
3260
+ this.clearStackBackToTable();
3261
+ this.activeFormatting.push(null);
3262
+ this.push(raw, NS.html, start);
3263
+ this.insertionMode = MODES.inCaption;
3264
+ return;
3265
+ }
3266
+ if (name === "colgroup") {
3267
+ this.clearStackBackToTable();
3268
+ this.push(raw, NS.html, start);
3269
+ this.insertionMode = MODES.inColumnGroup;
3270
+ return;
3271
+ }
3272
+ if (name === "col") {
3273
+ this.clearStackBackToTable();
3274
+ this.push("colgroup", NS.html, start);
3275
+ this.insertionMode = MODES.inColumnGroup;
3276
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3277
+ }
3278
+ if (name === "tbody" || name === "thead" || name === "tfoot") {
3279
+ this.clearStackBackToTable();
3280
+ this.push(raw, NS.html, start);
3281
+ this.insertionMode = MODES.inTableBody;
3282
+ return;
3283
+ }
3284
+ if (name === "td" || name === "th" || name === "tr") {
3285
+ this.clearStackBackToTable();
3286
+ this.push("tbody", NS.html, start);
3287
+ this.insertionMode = MODES.inTableBody;
3288
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3289
+ }
3290
+ if (name === "table") {
3291
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3292
+ tag: raw,
3293
+ parent: "table",
3294
+ mode: this.insertionMode,
3295
+ action: "auto-close-implicit"
3296
+ });
3297
+ if (this.hasInTableScope("table")) {
3298
+ this.popUntilName("table");
3299
+ this.resetInsertionModeAppropriately();
3300
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3301
+ }
3302
+ return;
3303
+ }
3304
+ if (name === "style" || name === "script" || name === "template") {
3305
+ return this.startInBody(name, raw, selfClosing, start, endIndex);
3306
+ }
3307
+ if (name === "input") {
3308
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_WARN, start, {
3309
+ tag: raw,
3310
+ parent: "table",
3311
+ mode: this.insertionMode,
3312
+ action: "foster-parent"
3313
+ });
3314
+ return;
3315
+ }
3316
+ if (name === "form") {
3317
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3318
+ tag: raw,
3319
+ parent: "table",
3320
+ mode: this.insertionMode,
3321
+ action: "ignored"
3322
+ });
3323
+ return;
3324
+ }
3325
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3326
+ tag: raw,
3327
+ parent: this.currentNode()?.name ?? "table",
3328
+ mode: this.insertionMode,
3329
+ action: "foster-parent"
3330
+ });
3331
+ return this.startInBody(name, raw, selfClosing, start, endIndex);
3332
+ }
3333
+ clearStackBackToTable() {
3334
+ while (this.openElements.length) {
3335
+ const top = this.currentNode();
3336
+ if (!top)
3337
+ break;
3338
+ if (top.name === "table" || top.name === "template")
3339
+ break;
3340
+ this.openElements.pop();
3341
+ }
3342
+ }
3343
+ flushTableText() {
3344
+ if (!this.pendingTableText)
3345
+ return;
3346
+ const { hasNonWhitespace, start, snippet } = this.pendingTableText;
3347
+ if (hasNonWhitespace) {
3348
+ this.report(HTML_TEXT_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3349
+ mode: this.originalInsertionMode,
3350
+ snippet
3351
+ });
3352
+ }
3353
+ this.pendingTableText = null;
3354
+ }
3355
+ startInCaption(name, raw, selfClosing, start, endIndex) {
3356
+ if (name === "caption" || name === "col" || name === "colgroup" || name === "tbody" || name === "td" || name === "tfoot" || name === "th" || name === "thead" || name === "tr") {
3357
+ if (this.hasInTableScope("caption")) {
3358
+ this.generateImpliedEndTags();
3359
+ this.popUntilName("caption");
3360
+ this.clearActiveFormattingToMarker();
3361
+ this.insertionMode = MODES.inTable;
3362
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3363
+ }
3364
+ return;
3365
+ }
3366
+ return this.startInBody(name, raw, selfClosing, start, endIndex);
3367
+ }
3368
+ clearActiveFormattingToMarker() {
3369
+ while (this.activeFormatting.length) {
3370
+ const e = this.activeFormatting.pop();
3371
+ if (e === null)
3372
+ return;
3373
+ }
3374
+ }
3375
+ startInColumnGroup(name, raw, selfClosing, start, endIndex) {
3376
+ if (name === "col") {
3377
+ return;
3378
+ }
3379
+ if (name === "template") {
3380
+ return this.startInBody(name, raw, selfClosing, start, endIndex);
3381
+ }
3382
+ if (this.currentNode()?.name === "colgroup") {
3383
+ this.openElements.pop();
3384
+ this.insertionMode = MODES.inTable;
3385
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3386
+ }
3387
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3388
+ tag: raw,
3389
+ parent: "colgroup",
3390
+ mode: this.insertionMode,
3391
+ action: "ignored"
3392
+ });
3393
+ }
3394
+ startInTableBody(name, raw, selfClosing, start, endIndex) {
3395
+ if (name === "tr") {
3396
+ this.clearStackBackToTableBody();
3397
+ this.push(raw, NS.html, start);
3398
+ this.insertionMode = MODES.inRow;
3399
+ return;
3400
+ }
3401
+ if (TABLE_BODY_CELL_TAGS.has(name)) {
3402
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_WARN, start, {
3403
+ tag: raw,
3404
+ parent: this.currentNode()?.name ?? "tbody",
3405
+ mode: this.insertionMode,
3406
+ action: "auto-close-implicit"
3407
+ });
3408
+ this.clearStackBackToTableBody();
3409
+ this.push("tr", NS.html, start);
3410
+ this.insertionMode = MODES.inRow;
3411
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3412
+ }
3413
+ if (name === "caption" || name === "col" || name === "colgroup" || name === "tbody" || name === "tfoot" || name === "thead") {
3414
+ if (this.hasInTableScope("tbody") || this.hasInTableScope("thead") || this.hasInTableScope("tfoot")) {
3415
+ this.clearStackBackToTableBody();
3416
+ this.openElements.pop();
3417
+ this.insertionMode = MODES.inTable;
3418
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3419
+ }
3420
+ return;
3421
+ }
3422
+ return this.startInTable(name, raw, selfClosing, start, endIndex);
3423
+ }
3424
+ clearStackBackToTableBody() {
3425
+ while (this.openElements.length) {
3426
+ const top = this.currentNode();
3427
+ if (!top)
3428
+ break;
3429
+ if (top.name === "tbody" || top.name === "thead" || top.name === "tfoot" || top.name === "template" || top.name === "table")
3430
+ break;
3431
+ this.openElements.pop();
3432
+ }
3433
+ }
3434
+ startInRow(name, raw, selfClosing, start, endIndex) {
3435
+ if (TABLE_BODY_CELL_TAGS.has(name)) {
3436
+ this.clearStackBackToTableRow();
3437
+ this.push(raw, NS.html, start);
3438
+ this.insertionMode = MODES.inCell;
3439
+ this.activeFormatting.push(null);
3440
+ return;
3441
+ }
3442
+ if (name === "caption" || name === "col" || name === "colgroup" || name === "tbody" || name === "tfoot" || name === "thead" || name === "tr") {
3443
+ if (this.hasInTableScope("tr")) {
3444
+ this.clearStackBackToTableRow();
3445
+ this.openElements.pop();
3446
+ this.insertionMode = MODES.inTableBody;
3447
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3448
+ }
3449
+ return;
3450
+ }
3451
+ return this.startInTable(name, raw, selfClosing, start, endIndex);
3452
+ }
3453
+ clearStackBackToTableRow() {
3454
+ while (this.openElements.length) {
3455
+ const top = this.currentNode();
3456
+ if (!top)
3457
+ break;
3458
+ if (top.name === "tr" || top.name === "template" || top.name === "table")
3459
+ break;
3460
+ this.openElements.pop();
3461
+ }
3462
+ }
3463
+ startInCell(name, raw, selfClosing, start, endIndex) {
3464
+ if (name === "caption" || name === "col" || name === "colgroup" || name === "tbody" || name === "td" || name === "tfoot" || name === "th" || name === "thead" || name === "tr") {
3465
+ if (this.hasInTableScope("td") || this.hasInTableScope("th")) {
3466
+ this.closeCell();
3467
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3468
+ }
3469
+ return;
3470
+ }
3471
+ return this.startInBody(name, raw, selfClosing, start, endIndex);
3472
+ }
3473
+ closeCell() {
3474
+ this.generateImpliedEndTags();
3475
+ while (this.openElements.length) {
3476
+ const popped = this.openElements.pop();
3477
+ if (popped.name === "td" || popped.name === "th")
3478
+ break;
3479
+ }
3480
+ this.clearActiveFormattingToMarker();
3481
+ this.insertionMode = MODES.inRow;
3482
+ }
3483
+ startInSelect(name, raw, _selfClosing, start, _endIndex) {
3484
+ if (name === "option") {
3485
+ if (this.currentNode()?.name === "option")
3486
+ this.openElements.pop();
3487
+ this.push(raw, NS.html, start);
3488
+ return;
3489
+ }
3490
+ if (name === "optgroup") {
3491
+ if (this.currentNode()?.name === "option")
3492
+ this.openElements.pop();
3493
+ if (this.currentNode()?.name === "optgroup")
3494
+ this.openElements.pop();
3495
+ this.push(raw, NS.html, start);
3496
+ return;
3497
+ }
3498
+ if (name === "hr")
3499
+ return;
3500
+ if (SELECT_BREAKOUT_TAGS.has(name)) {
3501
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3502
+ tag: raw,
3503
+ parent: "select",
3504
+ mode: this.insertionMode,
3505
+ action: "auto-close-implicit"
3506
+ });
3507
+ if (this.hasInSelectScope("select")) {
3508
+ this.popUntilName("select");
3509
+ this.resetInsertionModeAppropriately();
3510
+ }
3511
+ if (name === "select")
3512
+ return;
3513
+ return this.dispatchStartTag(name, raw, false, start, _endIndex);
3514
+ }
3515
+ if (name === "script" || name === "template") {
3516
+ return this.startInBody(name, raw, false, start, _endIndex);
3517
+ }
3518
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3519
+ tag: raw,
3520
+ parent: "select",
3521
+ mode: this.insertionMode,
3522
+ action: "ignored"
3523
+ });
3524
+ }
3525
+ startInSelectInTable(name, raw, selfClosing, start, endIndex) {
3526
+ if (name === "caption" || name === "table" || name === "tbody" || name === "tfoot" || name === "thead" || name === "tr" || name === "td" || name === "th") {
3527
+ this.report(HTML_TAG_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3528
+ tag: raw,
3529
+ parent: "select",
3530
+ mode: this.insertionMode,
3531
+ action: "auto-close-implicit"
3532
+ });
3533
+ this.popUntilName("select");
3534
+ this.resetInsertionModeAppropriately();
3535
+ return this.dispatchStartTag(name, raw, selfClosing, start, endIndex);
3536
+ }
3537
+ return this.startInSelect(name, raw, selfClosing, start, endIndex);
3538
+ }
3539
+ resetInsertionModeAppropriately() {
3540
+ for (let i = this.openElements.length - 1;i >= 0; i--) {
3541
+ const f = this.openElements[i];
3542
+ if (f.ns !== NS.html)
3543
+ continue;
3544
+ const last = i === 0;
3545
+ switch (f.name) {
3546
+ case "select":
3547
+ this.insertionMode = MODES.inSelect;
3548
+ return;
3549
+ case "td":
3550
+ case "th":
3551
+ if (!last) {
3552
+ this.insertionMode = MODES.inCell;
3553
+ return;
3554
+ }
3555
+ break;
3556
+ case "tr":
3557
+ this.insertionMode = MODES.inRow;
3558
+ return;
3559
+ case "tbody":
3560
+ case "thead":
3561
+ case "tfoot":
3562
+ this.insertionMode = MODES.inTableBody;
3563
+ return;
3564
+ case "caption":
3565
+ this.insertionMode = MODES.inCaption;
3566
+ return;
3567
+ case "colgroup":
3568
+ this.insertionMode = MODES.inColumnGroup;
3569
+ return;
3570
+ case "table":
3571
+ this.insertionMode = MODES.inTable;
3572
+ return;
3573
+ case "template":
3574
+ this.insertionMode = this.templateInsertionModes[this.templateInsertionModes.length - 1] ?? MODES.inBody;
3575
+ return;
3576
+ default:
3577
+ break;
3578
+ }
3579
+ }
3580
+ this.insertionMode = MODES.inBody;
3581
+ }
3582
+ handleEndTag(name, start) {
3583
+ if (this.isTransparentTag(name))
3584
+ return;
3585
+ const ns = this.currentNamespace();
3586
+ if (ns !== NS.html) {
3587
+ for (let i = this.openElements.length - 1;i >= 0; i--) {
3588
+ const f = this.openElements[i];
3589
+ if (f.ns === NS.html)
3590
+ break;
3591
+ if (f.name.toLowerCase() === name) {
3592
+ this.openElements.length = i;
3593
+ return;
3594
+ }
3595
+ }
3596
+ }
3597
+ if (VOID_ELEMENTS.has(name)) {
3598
+ this.report(HTML_VOID_ELEMENT_HAS_CLOSE_TAG, LEVEL_WARN, start, {
3599
+ tag: name,
3600
+ mode: this.insertionMode
3601
+ });
3602
+ return;
3603
+ }
3604
+ if (FORMATTING_ELEMENTS.has(name)) {
3605
+ const top = this.currentNode();
3606
+ if (top && top.ns === NS.html && top.name === name) {
3607
+ this.openElements.pop();
3608
+ this.removeFromActiveFormattingByRef(top);
3609
+ return;
3610
+ }
3611
+ if (this.activeFormattingHas(name) || this.openElementsHas(name)) {
3612
+ this.report(HTML_MISNESTED_FORMATTING, LEVEL_WARN, start, {
3613
+ tag: name,
3614
+ mode: this.insertionMode
3615
+ });
3616
+ this.runAdoptionAgency(name);
3617
+ return;
3618
+ }
3619
+ this.report(HTML_UNEXPECTED_END_TAG, LEVEL_WARN, start, {
3620
+ tag: name,
3621
+ mode: this.insertionMode
3622
+ });
3623
+ return;
3624
+ }
3625
+ for (let i = this.openElements.length - 1;i >= 0; i--) {
3626
+ const f = this.openElements[i];
3627
+ if (f.ns === NS.html && f.name === name) {
3628
+ this.openElements.length = i;
3629
+ if (name === "form")
3630
+ this.formPointer = null;
3631
+ if (TABLE_SCOPE_TAGS.has(name) || name === "select" || name === "template") {
3632
+ this.resetInsertionModeAppropriately();
3633
+ }
3634
+ return;
3635
+ }
3636
+ if (f.ns === NS.html && SPECIAL_ELEMENTS.has(f.name)) {
3637
+ break;
3638
+ }
3639
+ }
3640
+ }
3641
+ removeFromActiveFormattingByRef(ref) {
3642
+ const idx = this.activeFormatting.indexOf(ref);
3643
+ if (idx >= 0)
3644
+ this.activeFormatting.splice(idx, 1);
3645
+ }
3646
+ handleText(start, end) {
3647
+ if (this.insertionMode === MODES.inTable || this.insertionMode === MODES.inTableBody || this.insertionMode === MODES.inRow) {
3648
+ const slice = this.html.slice(start, end);
3649
+ const hasNonWhitespace = /\S/.test(slice);
3650
+ if (hasNonWhitespace) {
3651
+ this.report(HTML_TEXT_NOT_ALLOWED_IN_PARENT, LEVEL_ERROR, start, {
3652
+ mode: this.insertionMode,
3653
+ snippet: slice.length > 40 ? `${slice.slice(0, 40)}…` : slice
3654
+ });
3655
+ }
3656
+ return;
3657
+ }
3658
+ if (this.insertionMode === MODES.inColumnGroup) {
3659
+ const slice = this.html.slice(start, end);
3660
+ if (/\S/.test(slice)) {
3661
+ if (this.currentNode()?.name === "colgroup") {
3662
+ this.openElements.pop();
3663
+ this.insertionMode = MODES.inTable;
3664
+ return this.handleText(start, end);
3665
+ }
3666
+ }
3667
+ return;
3668
+ }
3669
+ if (this.insertionMode === MODES.inSelect || this.insertionMode === MODES.inSelectInTable) {
3670
+ return;
3671
+ }
3672
+ }
3673
+ }
3674
+ function computeLineStarts(html) {
3675
+ const arr = [0];
3676
+ for (let i = 0;i < html.length; i++) {
3677
+ if (html.charCodeAt(i) === 10)
3678
+ arr.push(i + 1);
3679
+ }
3680
+ return arr;
3681
+ }
3682
+ function offsetToLineCol(lineStarts, offset) {
3683
+ let lo = 0;
3684
+ let hi = lineStarts.length - 1;
3685
+ while (lo < hi) {
3686
+ const mid = lo + hi + 1 >>> 1;
3687
+ if (lineStarts[mid] <= offset)
3688
+ lo = mid;
3689
+ else
3690
+ hi = mid - 1;
3691
+ }
3692
+ return { line: lo + 1, column: offset - lineStarts[lo] + 1 };
3693
+ }
3694
+
1647
3695
  // tools/core/lint-check.js
1648
3696
  var ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED";
1649
3697
  var ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED";
@@ -1686,8 +3734,8 @@ var AT_PREFIX_HINT_KNOWN_BY_KIND = {
1686
3734
  "unknown-x-op": X_KNOWN_OP_NAMES,
1687
3735
  "unknown-x-attr": X_KNOWN_ATTR_NAMES
1688
3736
  };
1689
- var LEVEL_WARN = "warn";
1690
- var LEVEL_ERROR = "error";
3737
+ var LEVEL_WARN2 = "warn";
3738
+ var LEVEL_ERROR2 = "error";
1691
3739
  var LEVEL_HINT = "hint";
1692
3740
  function checkComponent(Comp, lx = new LintContext) {
1693
3741
  return lx.push({ componentName: Comp.name }, () => {
@@ -1709,6 +3757,16 @@ function checkView(lx, view, Comp, referencedAlters) {
1709
3757
  checkEventModifiers(lx, view);
1710
3758
  checkKnownHandlerNames(lx, view, Comp, referencedAlters);
1711
3759
  checkMacroCallArgs(lx, view, Comp);
3760
+ checkHtmlStructure(lx, view);
3761
+ }
3762
+ var HTML_LINT_OPTS = {
3763
+ fragmentContext: "template",
3764
+ transparentTagPrefixes: ["x"]
3765
+ };
3766
+ function checkHtmlStructure(lx, view) {
3767
+ if (typeof view.rawView !== "string" || !view.rawView)
3768
+ return;
3769
+ lintHtml(view.rawView, (f) => lx.report(f.id, { ...f.info, location: f.location }, f.level), HTML_LINT_OPTS);
1712
3770
  }
1713
3771
  function checkParseIssues(lx, view) {
1714
3772
  const issues = view.ctx.parseIssues;
@@ -2086,15 +4144,15 @@ class LintContext {
2086
4144
  }
2087
4145
  }
2088
4146
  error(id, info) {
2089
- this.report(id, info, LEVEL_ERROR);
4147
+ this.report(id, info, LEVEL_ERROR2);
2090
4148
  }
2091
4149
  warn(id, info) {
2092
- this.report(id, info, LEVEL_WARN);
4150
+ this.report(id, info, LEVEL_WARN2);
2093
4151
  }
2094
4152
  hint(id, info) {
2095
4153
  this.report(id, info, LEVEL_HINT);
2096
4154
  }
2097
- report(id, info = {}, level = LEVEL_ERROR) {
4155
+ report(id, info = {}, level = LEVEL_ERROR2) {
2098
4156
  this.reports.push({ id, info, level, context: { ...this.frame } });
2099
4157
  }
2100
4158
  }
@@ -2218,12 +4276,36 @@ function lintIdToMessage(id, info) {
2218
4276
  }
2219
4277
  case "BAD_VALUE":
2220
4278
  return `${badValueMessage(info)}${fmtTagSuffix(info)}`;
4279
+ case "HTML_TAG_NAME_HAS_UPPERCASE":
4280
+ return `Tag <${info.raw}> will be lowercased to <${info.lowercased}>${fmtLocationSuffix(info)}`;
4281
+ case "HTML_SVG_TAG_WILL_LOWERCASE":
4282
+ return `SVG tag <${info.raw}> is not in the WHATWG case-correction list — will be lowercased to <${info.lowercased}>${fmtLocationSuffix(info)}`;
4283
+ case "HTML_TAG_NOT_ALLOWED_IN_PARENT":
4284
+ return `<${info.tag}> not allowed under <${info.parent ?? "?"}> in ${info.mode} (action: ${info.action})${fmtLocationSuffix(info)}`;
4285
+ case "HTML_TEXT_NOT_ALLOWED_IN_PARENT":
4286
+ return `Non-whitespace text not allowed in ${info.mode}: ${JSON.stringify(info.snippet)}${fmtLocationSuffix(info)}`;
4287
+ case "HTML_VOID_ELEMENT_HAS_CLOSE_TAG":
4288
+ return `Void element <${info.tag}> has an explicit close tag${fmtLocationSuffix(info)}`;
4289
+ case "HTML_DUPLICATE_FORM":
4290
+ return `Nested <form> — the inner form will be dropped by the parser${fmtLocationSuffix(info)}`;
4291
+ case "HTML_NESTED_INTERACTIVE":
4292
+ return `<${info.tag}> nested inside another <${info.tag}> — adoption agency will reorder${fmtLocationSuffix(info)}`;
4293
+ case "HTML_MISNESTED_FORMATTING":
4294
+ return `Misnested formatting tag </${info.tag}> — adoption agency will reorder nodes${fmtLocationSuffix(info)}`;
4295
+ case "HTML_UNEXPECTED_END_TAG":
4296
+ return `Unexpected end tag </${info.tag}>${fmtLocationSuffix(info)}`;
2221
4297
  case "LINT_ERROR":
2222
4298
  return info.message;
2223
4299
  default:
2224
4300
  return id;
2225
4301
  }
2226
4302
  }
4303
+ function fmtLocationSuffix(info) {
4304
+ const loc = info?.location;
4305
+ if (!loc)
4306
+ return "";
4307
+ return ` at L${loc.line}:C${loc.column}`;
4308
+ }
2227
4309
 
2228
4310
  // src/components.js
2229
4311
  class Components {
@@ -2553,7 +4635,7 @@ class Stack {
2553
4635
  }
2554
4636
 
2555
4637
  // src/transactor.js
2556
- class State {
4638
+ class State2 {
2557
4639
  constructor(val) {
2558
4640
  this.val = val;
2559
4641
  this.changeSubs = [];
@@ -2576,7 +4658,7 @@ class Transactor {
2576
4658
  constructor(comps, rootValue) {
2577
4659
  this.comps = comps;
2578
4660
  this.transactions = [];
2579
- this.state = new State(rootValue);
4661
+ this.state = new State2(rootValue);
2580
4662
  this.onTransactionPushed = () => {};
2581
4663
  }
2582
4664
  pushTransaction(t) {
@@ -8780,10 +10862,11 @@ function check(app) {
8780
10862
  for (const Comp of app.comps.byId.values()) {
8781
10863
  const shadowViews = {};
8782
10864
  for (const name in Comp.views) {
10865
+ const rawView = Comp.views[name].rawView;
8783
10866
  const ctx = new LintParseContext;
8784
- ANode.parse(Comp.views[name].rawView, ctx);
10867
+ ANode.parse(rawView, ctx);
8785
10868
  ctx.compile(Comp.scope);
8786
- shadowViews[name] = { name, ctx };
10869
+ shadowViews[name] = { name, ctx, rawView };
8787
10870
  }
8788
10871
  const shadowComp = Object.create(Comp);
8789
10872
  shadowComp.views = shadowViews;