From eb265ea89eb306dada07def4fa92acfa8b2e7ad4 Mon Sep 17 00:00:00 2001 From: Ammar Ahmed Date: Fri, 22 May 2026 11:37:43 +0500 Subject: [PATCH] mobile: update linkedom version --- apps/mobile/worker.js | 9281 ++++++++++++++++++++++------------------- 1 file changed, 5077 insertions(+), 4204 deletions(-) diff --git a/apps/mobile/worker.js b/apps/mobile/worker.js index 82896cf08..ab720a2f1 100644 --- a/apps/mobile/worker.js +++ b/apps/mobile/worker.js @@ -1,4 +1,21 @@ -// used in Attr to signal changes +/* +This file is part of the Notesnook project (https://notesnook.com/) + +Copyright (C) 2023 Streetwriters (Private) Limited + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ const CHANGED = Symbol("changed"); // used in Element to setup once classList @@ -64,18 +81,11 @@ const UPGRADE = Symbol("upgrade"); // used to define generic values const VALUE = Symbol("value"); -// Generated using scripts/write-decode-map.ts -// prettier-ignore -var htmlDecodeTree = new Uint16Array([7489, 60, 213, 305, 650, 1181, 1403, 1488, 1653, 1758, 1954, 2006, 2063, 2634, 2705, 3489, 3693, 3849, 3878, 4298, 4648, 4833, 5141, 5277, 5315, 5343, 5413, 0, 0, 0, 0, 0, 0, 5483, 5837, 6541, 7186, 7645, 8062, 8288, 8624, 8845, 9152, 9211, 9282, 10276, 10514, 11528, 11848, 12238, 12310, 12986, 13881, 14252, 14590, 14888, 14961, 15072, 15150, 2048, 69, 77, 97, 98, 99, 102, 103, 108, 109, 110, 111, 112, 114, 115, 116, 117, 92, 98, 102, 109, 115, 127, 132, 139, 144, 149, 152, 166, 179, 185, 200, 207, 108, 105, 103, 32827, 198, 16582, 80, 32827, 38, 16422, 99, 117, 116, 101, 32827, 193, 16577, 114, 101, 118, 101, 59, 16642, 256, 105, 121, 120, 125, 114, 99, 32827, 194, 16578, 59, 17424, 114, 59, 49152, 55349, 56580, 114, 97, 118, 101, 32827, 192, 16576, 112, 104, 97, 59, 17297, 97, 99, 114, 59, 16640, 100, 59, 27219, 256, 103, 112, 157, 161, 111, 110, 59, 16644, 102, 59, 49152, 55349, 56632, 112, 108, 121, 70, 117, 110, 99, 116, 105, 111, 110, 59, 24673, 105, 110, 103, 32827, 197, 16581, 256, 99, 115, 190, 195, 114, 59, 49152, 55349, 56476, 105, 103, 110, 59, 25172, 105, 108, 100, 101, 32827, 195, 16579, 109, 108, 32827, 196, 16580, 1024, 97, 99, 101, 102, 111, 114, 115, 117, 229, 251, 254, 279, 284, 290, 295, 298, 256, 99, 114, 234, 242, 107, 115, 108, 97, 115, 104, 59, 25110, 374, 246, 248, 59, 27367, 101, 100, 59, 25350, 121, 59, 17425, 384, 99, 114, 116, 261, 267, 276, 97, 117, 115, 101, 59, 25141, 110, 111, 117, 108, 108, 105, 115, 59, 24876, 97, 59, 17298, 114, 59, 49152, 55349, 56581, 112, 102, 59, 49152, 55349, 56633, 101, 118, 101, 59, 17112, 99, 242, 275, 109, 112, 101, 113, 59, 25166, 1792, 72, 79, 97, 99, 100, 101, 102, 104, 105, 108, 111, 114, 115, 117, 333, 337, 342, 384, 414, 418, 437, 439, 442, 476, 533, 627, 632, 638, 99, 121, 59, 17447, 80, 89, 32827, 169, 16553, 384, 99, 112, 121, 349, 354, 378, 117, 116, 101, 59, 16646, 256, 59, 105, 359, 360, 25298, 116, 97, 108, 68, 105, 102, 102, 101, 114, 101, 110, 116, 105, 97, 108, 68, 59, 24901, 108, 101, 121, 115, 59, 24877, 512, 97, 101, 105, 111, 393, 398, 404, 408, 114, 111, 110, 59, 16652, 100, 105, 108, 32827, 199, 16583, 114, 99, 59, 16648, 110, 105, 110, 116, 59, 25136, 111, 116, 59, 16650, 256, 100, 110, 423, 429, 105, 108, 108, 97, 59, 16568, 116, 101, 114, 68, 111, 116, 59, 16567, 242, 383, 105, 59, 17319, 114, 99, 108, 101, 512, 68, 77, 80, 84, 455, 459, 465, 470, 111, 116, 59, 25241, 105, 110, 117, 115, 59, 25238, 108, 117, 115, 59, 25237, 105, 109, 101, 115, 59, 25239, 111, 256, 99, 115, 482, 504, 107, 119, 105, 115, 101, 67, 111, 110, 116, 111, 117, 114, 73, 110, 116, 101, 103, 114, 97, 108, 59, 25138, 101, 67, 117, 114, 108, 121, 256, 68, 81, 515, 527, 111, 117, 98, 108, 101, 81, 117, 111, 116, 101, 59, 24605, 117, 111, 116, 101, 59, 24601, 512, 108, 110, 112, 117, 542, 552, 583, 597, 111, 110, 256, 59, 101, 549, 550, 25143, 59, 27252, 384, 103, 105, 116, 559, 566, 570, 114, 117, 101, 110, 116, 59, 25185, 110, 116, 59, 25135, 111, 117, 114, 73, 110, 116, 101, 103, 114, 97, 108, 59, 25134, 256, 102, 114, 588, 590, 59, 24834, 111, 100, 117, 99, 116, 59, 25104, 110, 116, 101, 114, 67, 108, 111, 99, 107, 119, 105, 115, 101, 67, 111, 110, 116, 111, 117, 114, 73, 110, 116, 101, 103, 114, 97, 108, 59, 25139, 111, 115, 115, 59, 27183, 99, 114, 59, 49152, 55349, 56478, 112, 256, 59, 67, 644, 645, 25299, 97, 112, 59, 25165, 1408, 68, 74, 83, 90, 97, 99, 101, 102, 105, 111, 115, 672, 684, 688, 692, 696, 715, 727, 737, 742, 819, 1165, 256, 59, 111, 377, 677, 116, 114, 97, 104, 100, 59, 26897, 99, 121, 59, 17410, 99, 121, 59, 17413, 99, 121, 59, 17423, 384, 103, 114, 115, 703, 708, 711, 103, 101, 114, 59, 24609, 114, 59, 24993, 104, 118, 59, 27364, 256, 97, 121, 720, 725, 114, 111, 110, 59, 16654, 59, 17428, 108, 256, 59, 116, 733, 734, 25095, 97, 59, 17300, 114, 59, 49152, 55349, 56583, 256, 97, 102, 747, 807, 256, 99, 109, 752, 802, 114, 105, 116, 105, 99, 97, 108, 512, 65, 68, 71, 84, 768, 774, 790, 796, 99, 117, 116, 101, 59, 16564, 111, 372, 779, 781, 59, 17113, 98, 108, 101, 65, 99, 117, 116, 101, 59, 17117, 114, 97, 118, 101, 59, 16480, 105, 108, 100, 101, 59, 17116, 111, 110, 100, 59, 25284, 102, 101, 114, 101, 110, 116, 105, 97, 108, 68, 59, 24902, 1136, 829, 0, 0, 0, 834, 852, 0, 1029, 102, 59, 49152, 55349, 56635, 384, 59, 68, 69, 840, 841, 845, 16552, 111, 116, 59, 24796, 113, 117, 97, 108, 59, 25168, 98, 108, 101, 768, 67, 68, 76, 82, 85, 86, 867, 882, 898, 975, 994, 1016, 111, 110, 116, 111, 117, 114, 73, 110, 116, 101, 103, 114, 97, 236, 569, 111, 628, 889, 0, 0, 891, 187, 841, 110, 65, 114, 114, 111, 119, 59, 25043, 256, 101, 111, 903, 932, 102, 116, 384, 65, 82, 84, 912, 918, 929, 114, 114, 111, 119, 59, 25040, 105, 103, 104, 116, 65, 114, 114, 111, 119, 59, 25044, 101, 229, 714, 110, 103, 256, 76, 82, 939, 964, 101, 102, 116, 256, 65, 82, 947, 953, 114, 114, 111, 119, 59, 26616, 105, 103, 104, 116, 65, 114, 114, 111, 119, 59, 26618, 105, 103, 104, 116, 65, 114, 114, 111, 119, 59, 26617, 105, 103, 104, 116, 256, 65, 84, 984, 990, 114, 114, 111, 119, 59, 25042, 101, 101, 59, 25256, 112, 577, 1001, 0, 0, 1007, 114, 114, 111, 119, 59, 25041, 111, 119, 110, 65, 114, 114, 111, 119, 59, 25045, 101, 114, 116, 105, 99, 97, 108, 66, 97, 114, 59, 25125, 110, 768, 65, 66, 76, 82, 84, 97, 1042, 1066, 1072, 1118, 1151, 892, 114, 114, 111, 119, 384, 59, 66, 85, 1053, 1054, 1058, 24979, 97, 114, 59, 26899, 112, 65, 114, 114, 111, 119, 59, 25077, 114, 101, 118, 101, 59, 17169, 101, 102, 116, 722, 1082, 0, 1094, 0, 1104, 105, 103, 104, 116, 86, 101, 99, 116, 111, 114, 59, 26960, 101, 101, 86, 101, 99, 116, 111, 114, 59, 26974, 101, 99, 116, 111, 114, 256, 59, 66, 1113, 1114, 25021, 97, 114, 59, 26966, 105, 103, 104, 116, 468, 1127, 0, 1137, 101, 101, 86, 101, 99, 116, 111, 114, 59, 26975, 101, 99, 116, 111, 114, 256, 59, 66, 1146, 1147, 25025, 97, 114, 59, 26967, 101, 101, 256, 59, 65, 1158, 1159, 25252, 114, 114, 111, 119, 59, 24999, 256, 99, 116, 1170, 1175, 114, 59, 49152, 55349, 56479, 114, 111, 107, 59, 16656, 2048, 78, 84, 97, 99, 100, 102, 103, 108, 109, 111, 112, 113, 115, 116, 117, 120, 1213, 1216, 1220, 1227, 1246, 1250, 1255, 1262, 1269, 1313, 1327, 1334, 1362, 1373, 1376, 1381, 71, 59, 16714, 72, 32827, 208, 16592, 99, 117, 116, 101, 32827, 201, 16585, 384, 97, 105, 121, 1234, 1239, 1244, 114, 111, 110, 59, 16666, 114, 99, 32827, 202, 16586, 59, 17453, 111, 116, 59, 16662, 114, 59, 49152, 55349, 56584, 114, 97, 118, 101, 32827, 200, 16584, 101, 109, 101, 110, 116, 59, 25096, 256, 97, 112, 1274, 1278, 99, 114, 59, 16658, 116, 121, 595, 1286, 0, 0, 1298, 109, 97, 108, 108, 83, 113, 117, 97, 114, 101, 59, 26107, 101, 114, 121, 83, 109, 97, 108, 108, 83, 113, 117, 97, 114, 101, 59, 26027, 256, 103, 112, 1318, 1322, 111, 110, 59, 16664, 102, 59, 49152, 55349, 56636, 115, 105, 108, 111, 110, 59, 17301, 117, 256, 97, 105, 1340, 1353, 108, 256, 59, 84, 1346, 1347, 27253, 105, 108, 100, 101, 59, 25154, 108, 105, 98, 114, 105, 117, 109, 59, 25036, 256, 99, 105, 1367, 1370, 114, 59, 24880, 109, 59, 27251, 97, 59, 17303, 109, 108, 32827, 203, 16587, 256, 105, 112, 1386, 1391, 115, 116, 115, 59, 25091, 111, 110, 101, 110, 116, 105, 97, 108, 69, 59, 24903, 640, 99, 102, 105, 111, 115, 1413, 1416, 1421, 1458, 1484, 121, 59, 17444, 114, 59, 49152, 55349, 56585, 108, 108, 101, 100, 595, 1431, 0, 0, 1443, 109, 97, 108, 108, 83, 113, 117, 97, 114, 101, 59, 26108, 101, 114, 121, 83, 109, 97, 108, 108, 83, 113, 117, 97, 114, 101, 59, 26026, 880, 1466, 0, 1471, 0, 0, 1476, 102, 59, 49152, 55349, 56637, 65, 108, 108, 59, 25088, 114, 105, 101, 114, 116, 114, 102, 59, 24881, 99, 242, 1483, 1536, 74, 84, 97, 98, 99, 100, 102, 103, 111, 114, 115, 116, 1512, 1516, 1519, 1530, 1536, 1554, 1558, 1563, 1565, 1571, 1644, 1650, 99, 121, 59, 17411, 32827, 62, 16446, 109, 109, 97, 256, 59, 100, 1527, 1528, 17299, 59, 17372, 114, 101, 118, 101, 59, 16670, 384, 101, 105, 121, 1543, 1548, 1552, 100, 105, 108, 59, 16674, 114, 99, 59, 16668, 59, 17427, 111, 116, 59, 16672, 114, 59, 49152, 55349, 56586, 59, 25305, 112, 102, 59, 49152, 55349, 56638, 101, 97, 116, 101, 114, 768, 69, 70, 71, 76, 83, 84, 1589, 1604, 1614, 1622, 1627, 1638, 113, 117, 97, 108, 256, 59, 76, 1598, 1599, 25189, 101, 115, 115, 59, 25307, 117, 108, 108, 69, 113, 117, 97, 108, 59, 25191, 114, 101, 97, 116, 101, 114, 59, 27298, 101, 115, 115, 59, 25207, 108, 97, 110, 116, 69, 113, 117, 97, 108, 59, 27262, 105, 108, 100, 101, 59, 25203, 99, 114, 59, 49152, 55349, 56482, 59, 25195, 1024, 65, 97, 99, 102, 105, 111, 115, 117, 1669, 1675, 1686, 1691, 1694, 1706, 1726, 1738, 82, 68, 99, 121, 59, 17450, 256, 99, 116, 1680, 1684, 101, 107, 59, 17095, 59, 16478, 105, 114, 99, 59, 16676, 114, 59, 24844, 108, 98, 101, 114, 116, 83, 112, 97, 99, 101, 59, 24843, 496, 1711, 0, 1714, 102, 59, 24845, 105, 122, 111, 110, 116, 97, 108, 76, 105, 110, 101, 59, 25856, 256, 99, 116, 1731, 1733, 242, 1705, 114, 111, 107, 59, 16678, 109, 112, 324, 1744, 1752, 111, 119, 110, 72, 117, 109, 240, 303, 113, 117, 97, 108, 59, 25167, 1792, 69, 74, 79, 97, 99, 100, 102, 103, 109, 110, 111, 115, 116, 117, 1786, 1790, 1795, 1799, 1806, 1818, 1822, 1825, 1832, 1860, 1912, 1931, 1935, 1941, 99, 121, 59, 17429, 108, 105, 103, 59, 16690, 99, 121, 59, 17409, 99, 117, 116, 101, 32827, 205, 16589, 256, 105, 121, 1811, 1816, 114, 99, 32827, 206, 16590, 59, 17432, 111, 116, 59, 16688, 114, 59, 24849, 114, 97, 118, 101, 32827, 204, 16588, 384, 59, 97, 112, 1824, 1839, 1855, 256, 99, 103, 1844, 1847, 114, 59, 16682, 105, 110, 97, 114, 121, 73, 59, 24904, 108, 105, 101, 243, 989, 500, 1865, 0, 1890, 256, 59, 101, 1869, 1870, 25132, 256, 103, 114, 1875, 1880, 114, 97, 108, 59, 25131, 115, 101, 99, 116, 105, 111, 110, 59, 25282, 105, 115, 105, 98, 108, 101, 256, 67, 84, 1900, 1906, 111, 109, 109, 97, 59, 24675, 105, 109, 101, 115, 59, 24674, 384, 103, 112, 116, 1919, 1923, 1928, 111, 110, 59, 16686, 102, 59, 49152, 55349, 56640, 97, 59, 17305, 99, 114, 59, 24848, 105, 108, 100, 101, 59, 16680, 491, 1946, 0, 1950, 99, 121, 59, 17414, 108, 32827, 207, 16591, 640, 99, 102, 111, 115, 117, 1964, 1975, 1980, 1986, 2000, 256, 105, 121, 1969, 1973, 114, 99, 59, 16692, 59, 17433, 114, 59, 49152, 55349, 56589, 112, 102, 59, 49152, 55349, 56641, 483, 1991, 0, 1996, 114, 59, 49152, 55349, 56485, 114, 99, 121, 59, 17416, 107, 99, 121, 59, 17412, 896, 72, 74, 97, 99, 102, 111, 115, 2020, 2024, 2028, 2033, 2045, 2050, 2056, 99, 121, 59, 17445, 99, 121, 59, 17420, 112, 112, 97, 59, 17306, 256, 101, 121, 2038, 2043, 100, 105, 108, 59, 16694, 59, 17434, 114, 59, 49152, 55349, 56590, 112, 102, 59, 49152, 55349, 56642, 99, 114, 59, 49152, 55349, 56486, 1408, 74, 84, 97, 99, 101, 102, 108, 109, 111, 115, 116, 2085, 2089, 2092, 2128, 2147, 2483, 2488, 2503, 2509, 2615, 2631, 99, 121, 59, 17417, 32827, 60, 16444, 640, 99, 109, 110, 112, 114, 2103, 2108, 2113, 2116, 2125, 117, 116, 101, 59, 16697, 98, 100, 97, 59, 17307, 103, 59, 26602, 108, 97, 99, 101, 116, 114, 102, 59, 24850, 114, 59, 24990, 384, 97, 101, 121, 2135, 2140, 2145, 114, 111, 110, 59, 16701, 100, 105, 108, 59, 16699, 59, 17435, 256, 102, 115, 2152, 2416, 116, 1280, 65, 67, 68, 70, 82, 84, 85, 86, 97, 114, 2174, 2217, 2225, 2272, 2278, 2300, 2351, 2395, 912, 2410, 256, 110, 114, 2179, 2191, 103, 108, 101, 66, 114, 97, 99, 107, 101, 116, 59, 26600, 114, 111, 119, 384, 59, 66, 82, 2201, 2202, 2206, 24976, 97, 114, 59, 25060, 105, 103, 104, 116, 65, 114, 114, 111, 119, 59, 25030, 101, 105, 108, 105, 110, 103, 59, 25352, 111, 501, 2231, 0, 2243, 98, 108, 101, 66, 114, 97, 99, 107, 101, 116, 59, 26598, 110, 468, 2248, 0, 2258, 101, 101, 86, 101, 99, 116, 111, 114, 59, 26977, 101, 99, 116, 111, 114, 256, 59, 66, 2267, 2268, 25027, 97, 114, 59, 26969, 108, 111, 111, 114, 59, 25354, 105, 103, 104, 116, 256, 65, 86, 2287, 2293, 114, 114, 111, 119, 59, 24980, 101, 99, 116, 111, 114, 59, 26958, 256, 101, 114, 2305, 2327, 101, 384, 59, 65, 86, 2313, 2314, 2320, 25251, 114, 114, 111, 119, 59, 24996, 101, 99, 116, 111, 114, 59, 26970, 105, 97, 110, 103, 108, 101, 384, 59, 66, 69, 2340, 2341, 2345, 25266, 97, 114, 59, 27087, 113, 117, 97, 108, 59, 25268, 112, 384, 68, 84, 86, 2359, 2370, 2380, 111, 119, 110, 86, 101, 99, 116, 111, 114, 59, 26961, 101, 101, 86, 101, 99, 116, 111, 114, 59, 26976, 101, 99, 116, 111, 114, 256, 59, 66, 2390, 2391, 25023, 97, 114, 59, 26968, 101, 99, 116, 111, 114, 256, 59, 66, 2405, 2406, 25020, 97, 114, 59, 26962, 105, 103, 104, 116, 225, 924, 115, 768, 69, 70, 71, 76, 83, 84, 2430, 2443, 2453, 2461, 2466, 2477, 113, 117, 97, 108, 71, 114, 101, 97, 116, 101, 114, 59, 25306, 117, 108, 108, 69, 113, 117, 97, 108, 59, 25190, 114, 101, 97, 116, 101, 114, 59, 25206, 101, 115, 115, 59, 27297, 108, 97, 110, 116, 69, 113, 117, 97, 108, 59, 27261, 105, 108, 100, 101, 59, 25202, 114, 59, 49152, 55349, 56591, 256, 59, 101, 2493, 2494, 25304, 102, 116, 97, 114, 114, 111, 119, 59, 25050, 105, 100, 111, 116, 59, 16703, 384, 110, 112, 119, 2516, 2582, 2587, 103, 512, 76, 82, 108, 114, 2526, 2551, 2562, 2576, 101, 102, 116, 256, 65, 82, 2534, 2540, 114, 114, 111, 119, 59, 26613, 105, 103, 104, 116, 65, 114, 114, 111, 119, 59, 26615, 105, 103, 104, 116, 65, 114, 114, 111, 119, 59, 26614, 101, 102, 116, 256, 97, 114, 947, 2570, 105, 103, 104, 116, 225, 959, 105, 103, 104, 116, 225, 970, 102, 59, 49152, 55349, 56643, 101, 114, 256, 76, 82, 2594, 2604, 101, 102, 116, 65, 114, 114, 111, 119, 59, 24985, 105, 103, 104, 116, 65, 114, 114, 111, 119, 59, 24984, 384, 99, 104, 116, 2622, 2624, 2626, 242, 2124, 59, 25008, 114, 111, 107, 59, 16705, 59, 25194, 1024, 97, 99, 101, 102, 105, 111, 115, 117, 2650, 2653, 2656, 2679, 2684, 2693, 2699, 2702, 112, 59, 26885, 121, 59, 17436, 256, 100, 108, 2661, 2671, 105, 117, 109, 83, 112, 97, 99, 101, 59, 24671, 108, 105, 110, 116, 114, 102, 59, 24883, 114, 59, 49152, 55349, 56592, 110, 117, 115, 80, 108, 117, 115, 59, 25107, 112, 102, 59, 49152, 55349, 56644, 99, 242, 2678, 59, 17308, 1152, 74, 97, 99, 101, 102, 111, 115, 116, 117, 2723, 2727, 2733, 2752, 2836, 2841, 3473, 3479, 3486, 99, 121, 59, 17418, 99, 117, 116, 101, 59, 16707, 384, 97, 101, 121, 2740, 2745, 2750, 114, 111, 110, 59, 16711, 100, 105, 108, 59, 16709, 59, 17437, 384, 103, 115, 119, 2759, 2800, 2830, 97, 116, 105, 118, 101, 384, 77, 84, 86, 2771, 2783, 2792, 101, 100, 105, 117, 109, 83, 112, 97, 99, 101, 59, 24587, 104, 105, 256, 99, 110, 2790, 2776, 235, 2777, 101, 114, 121, 84, 104, 105, 238, 2777, 116, 101, 100, 256, 71, 76, 2808, 2822, 114, 101, 97, 116, 101, 114, 71, 114, 101, 97, 116, 101, 242, 1651, 101, 115, 115, 76, 101, 115, 243, 2632, 76, 105, 110, 101, 59, 16394, 114, 59, 49152, 55349, 56593, 512, 66, 110, 112, 116, 2850, 2856, 2871, 2874, 114, 101, 97, 107, 59, 24672, 66, 114, 101, 97, 107, 105, 110, 103, 83, 112, 97, 99, 101, 59, 16544, 102, 59, 24853, 1664, 59, 67, 68, 69, 71, 72, 76, 78, 80, 82, 83, 84, 86, 2901, 2902, 2922, 2940, 2977, 3051, 3076, 3166, 3204, 3238, 3288, 3425, 3461, 27372, 256, 111, 117, 2907, 2916, 110, 103, 114, 117, 101, 110, 116, 59, 25186, 112, 67, 97, 112, 59, 25197, 111, 117, 98, 108, 101, 86, 101, 114, 116, 105, 99, 97, 108, 66, 97, 114, 59, 25126, 384, 108, 113, 120, 2947, 2954, 2971, 101, 109, 101, 110, 116, 59, 25097, 117, 97, 108, 256, 59, 84, 2962, 2963, 25184, 105, 108, 100, 101, 59, 49152, 8770, 824, 105, 115, 116, 115, 59, 25092, 114, 101, 97, 116, 101, 114, 896, 59, 69, 70, 71, 76, 83, 84, 2998, 2999, 3005, 3017, 3027, 3032, 3045, 25199, 113, 117, 97, 108, 59, 25201, 117, 108, 108, 69, 113, 117, 97, 108, 59, 49152, 8807, 824, 114, 101, 97, 116, 101, 114, 59, 49152, 8811, 824, 101, 115, 115, 59, 25209, 108, 97, 110, 116, 69, 113, 117, 97, 108, 59, 49152, 10878, 824, 105, 108, 100, 101, 59, 25205, 117, 109, 112, 324, 3058, 3069, 111, 119, 110, 72, 117, 109, 112, 59, 49152, 8782, 824, 113, 117, 97, 108, 59, 49152, 8783, 824, 101, 256, 102, 115, 3082, 3111, 116, 84, 114, 105, 97, 110, 103, 108, 101, 384, 59, 66, 69, 3098, 3099, 3105, 25322, 97, 114, 59, 49152, 10703, 824, 113, 117, 97, 108, 59, 25324, 115, 768, 59, 69, 71, 76, 83, 84, 3125, 3126, 3132, 3140, 3147, 3160, 25198, 113, 117, 97, 108, 59, 25200, 114, 101, 97, 116, 101, 114, 59, 25208, 101, 115, 115, 59, 49152, 8810, 824, 108, 97, 110, 116, 69, 113, 117, 97, 108, 59, 49152, 10877, 824, 105, 108, 100, 101, 59, 25204, 101, 115, 116, 101, 100, 256, 71, 76, 3176, 3193, 114, 101, 97, 116, 101, 114, 71, 114, 101, 97, 116, 101, 114, 59, 49152, 10914, 824, 101, 115, 115, 76, 101, 115, 115, 59, 49152, 10913, 824, 114, 101, 99, 101, 100, 101, 115, 384, 59, 69, 83, 3218, 3219, 3227, 25216, 113, 117, 97, 108, 59, 49152, 10927, 824, 108, 97, 110, 116, 69, 113, 117, 97, 108, 59, 25312, 256, 101, 105, 3243, 3257, 118, 101, 114, 115, 101, 69, 108, 101, 109, 101, 110, 116, 59, 25100, 103, 104, 116, 84, 114, 105, 97, 110, 103, 108, 101, 384, 59, 66, 69, 3275, 3276, 3282, 25323, 97, 114, 59, 49152, 10704, 824, 113, 117, 97, 108, 59, 25325, 256, 113, 117, 3293, 3340, 117, 97, 114, 101, 83, 117, 256, 98, 112, 3304, 3321, 115, 101, 116, 256, 59, 69, 3312, 3315, 49152, 8847, 824, 113, 117, 97, 108, 59, 25314, 101, 114, 115, 101, 116, 256, 59, 69, 3331, 3334, 49152, 8848, 824, 113, 117, 97, 108, 59, 25315, 384, 98, 99, 112, 3347, 3364, 3406, 115, 101, 116, 256, 59, 69, 3355, 3358, 49152, 8834, 8402, 113, 117, 97, 108, 59, 25224, 99, 101, 101, 100, 115, 512, 59, 69, 83, 84, 3378, 3379, 3387, 3398, 25217, 113, 117, 97, 108, 59, 49152, 10928, 824, 108, 97, 110, 116, 69, 113, 117, 97, 108, 59, 25313, 105, 108, 100, 101, 59, 49152, 8831, 824, 101, 114, 115, 101, 116, 256, 59, 69, 3416, 3419, 49152, 8835, 8402, 113, 117, 97, 108, 59, 25225, 105, 108, 100, 101, 512, 59, 69, 70, 84, 3438, 3439, 3445, 3455, 25153, 113, 117, 97, 108, 59, 25156, 117, 108, 108, 69, 113, 117, 97, 108, 59, 25159, 105, 108, 100, 101, 59, 25161, 101, 114, 116, 105, 99, 97, 108, 66, 97, 114, 59, 25124, 99, 114, 59, 49152, 55349, 56489, 105, 108, 100, 101, 32827, 209, 16593, 59, 17309, 1792, 69, 97, 99, 100, 102, 103, 109, 111, 112, 114, 115, 116, 117, 118, 3517, 3522, 3529, 3541, 3547, 3552, 3559, 3580, 3586, 3616, 3618, 3634, 3647, 3652, 108, 105, 103, 59, 16722, 99, 117, 116, 101, 32827, 211, 16595, 256, 105, 121, 3534, 3539, 114, 99, 32827, 212, 16596, 59, 17438, 98, 108, 97, 99, 59, 16720, 114, 59, 49152, 55349, 56594, 114, 97, 118, 101, 32827, 210, 16594, 384, 97, 101, 105, 3566, 3570, 3574, 99, 114, 59, 16716, 103, 97, 59, 17321, 99, 114, 111, 110, 59, 17311, 112, 102, 59, 49152, 55349, 56646, 101, 110, 67, 117, 114, 108, 121, 256, 68, 81, 3598, 3610, 111, 117, 98, 108, 101, 81, 117, 111, 116, 101, 59, 24604, 117, 111, 116, 101, 59, 24600, 59, 27220, 256, 99, 108, 3623, 3628, 114, 59, 49152, 55349, 56490, 97, 115, 104, 32827, 216, 16600, 105, 364, 3639, 3644, 100, 101, 32827, 213, 16597, 101, 115, 59, 27191, 109, 108, 32827, 214, 16598, 101, 114, 256, 66, 80, 3659, 3680, 256, 97, 114, 3664, 3667, 114, 59, 24638, 97, 99, 256, 101, 107, 3674, 3676, 59, 25566, 101, 116, 59, 25524, 97, 114, 101, 110, 116, 104, 101, 115, 105, 115, 59, 25564, 1152, 97, 99, 102, 104, 105, 108, 111, 114, 115, 3711, 3719, 3722, 3727, 3730, 3732, 3741, 3760, 3836, 114, 116, 105, 97, 108, 68, 59, 25090, 121, 59, 17439, 114, 59, 49152, 55349, 56595, 105, 59, 17318, 59, 17312, 117, 115, 77, 105, 110, 117, 115, 59, 16561, 256, 105, 112, 3746, 3757, 110, 99, 97, 114, 101, 112, 108, 97, 110, 229, 1693, 102, 59, 24857, 512, 59, 101, 105, 111, 3769, 3770, 3808, 3812, 27323, 99, 101, 100, 101, 115, 512, 59, 69, 83, 84, 3784, 3785, 3791, 3802, 25210, 113, 117, 97, 108, 59, 27311, 108, 97, 110, 116, 69, 113, 117, 97, 108, 59, 25212, 105, 108, 100, 101, 59, 25214, 109, 101, 59, 24627, 256, 100, 112, 3817, 3822, 117, 99, 116, 59, 25103, 111, 114, 116, 105, 111, 110, 256, 59, 97, 549, 3833, 108, 59, 25117, 256, 99, 105, 3841, 3846, 114, 59, 49152, 55349, 56491, 59, 17320, 512, 85, 102, 111, 115, 3857, 3862, 3867, 3871, 79, 84, 32827, 34, 16418, 114, 59, 49152, 55349, 56596, 112, 102, 59, 24858, 99, 114, 59, 49152, 55349, 56492, 1536, 66, 69, 97, 99, 101, 102, 104, 105, 111, 114, 115, 117, 3902, 3907, 3911, 3936, 3955, 4007, 4010, 4013, 4246, 4265, 4276, 4286, 97, 114, 114, 59, 26896, 71, 32827, 174, 16558, 384, 99, 110, 114, 3918, 3923, 3926, 117, 116, 101, 59, 16724, 103, 59, 26603, 114, 256, 59, 116, 3932, 3933, 24992, 108, 59, 26902, 384, 97, 101, 121, 3943, 3948, 3953, 114, 111, 110, 59, 16728, 100, 105, 108, 59, 16726, 59, 17440, 256, 59, 118, 3960, 3961, 24860, 101, 114, 115, 101, 256, 69, 85, 3970, 3993, 256, 108, 113, 3975, 3982, 101, 109, 101, 110, 116, 59, 25099, 117, 105, 108, 105, 98, 114, 105, 117, 109, 59, 25035, 112, 69, 113, 117, 105, 108, 105, 98, 114, 105, 117, 109, 59, 26991, 114, 187, 3961, 111, 59, 17313, 103, 104, 116, 1024, 65, 67, 68, 70, 84, 85, 86, 97, 4033, 4075, 4083, 4130, 4136, 4187, 4231, 984, 256, 110, 114, 4038, 4050, 103, 108, 101, 66, 114, 97, 99, 107, 101, 116, 59, 26601, 114, 111, 119, 384, 59, 66, 76, 4060, 4061, 4065, 24978, 97, 114, 59, 25061, 101, 102, 116, 65, 114, 114, 111, 119, 59, 25028, 101, 105, 108, 105, 110, 103, 59, 25353, 111, 501, 4089, 0, 4101, 98, 108, 101, 66, 114, 97, 99, 107, 101, 116, 59, 26599, 110, 468, 4106, 0, 4116, 101, 101, 86, 101, 99, 116, 111, 114, 59, 26973, 101, 99, 116, 111, 114, 256, 59, 66, 4125, 4126, 25026, 97, 114, 59, 26965, 108, 111, 111, 114, 59, 25355, 256, 101, 114, 4141, 4163, 101, 384, 59, 65, 86, 4149, 4150, 4156, 25250, 114, 114, 111, 119, 59, 24998, 101, 99, 116, 111, 114, 59, 26971, 105, 97, 110, 103, 108, 101, 384, 59, 66, 69, 4176, 4177, 4181, 25267, 97, 114, 59, 27088, 113, 117, 97, 108, 59, 25269, 112, 384, 68, 84, 86, 4195, 4206, 4216, 111, 119, 110, 86, 101, 99, 116, 111, 114, 59, 26959, 101, 101, 86, 101, 99, 116, 111, 114, 59, 26972, 101, 99, 116, 111, 114, 256, 59, 66, 4226, 4227, 25022, 97, 114, 59, 26964, 101, 99, 116, 111, 114, 256, 59, 66, 4241, 4242, 25024, 97, 114, 59, 26963, 256, 112, 117, 4251, 4254, 102, 59, 24861, 110, 100, 73, 109, 112, 108, 105, 101, 115, 59, 26992, 105, 103, 104, 116, 97, 114, 114, 111, 119, 59, 25051, 256, 99, 104, 4281, 4284, 114, 59, 24859, 59, 25009, 108, 101, 68, 101, 108, 97, 121, 101, 100, 59, 27124, 1664, 72, 79, 97, 99, 102, 104, 105, 109, 111, 113, 115, 116, 117, 4324, 4337, 4343, 4349, 4377, 4382, 4433, 4438, 4449, 4455, 4533, 4539, 4543, 256, 67, 99, 4329, 4334, 72, 99, 121, 59, 17449, 121, 59, 17448, 70, 84, 99, 121, 59, 17452, 99, 117, 116, 101, 59, 16730, 640, 59, 97, 101, 105, 121, 4360, 4361, 4366, 4371, 4375, 27324, 114, 111, 110, 59, 16736, 100, 105, 108, 59, 16734, 114, 99, 59, 16732, 59, 17441, 114, 59, 49152, 55349, 56598, 111, 114, 116, 512, 68, 76, 82, 85, 4394, 4404, 4414, 4425, 111, 119, 110, 65, 114, 114, 111, 119, 187, 1054, 101, 102, 116, 65, 114, 114, 111, 119, 187, 2202, 105, 103, 104, 116, 65, 114, 114, 111, 119, 187, 4061, 112, 65, 114, 114, 111, 119, 59, 24977, 103, 109, 97, 59, 17315, 97, 108, 108, 67, 105, 114, 99, 108, 101, 59, 25112, 112, 102, 59, 49152, 55349, 56650, 626, 4461, 0, 0, 4464, 116, 59, 25114, 97, 114, 101, 512, 59, 73, 83, 85, 4475, 4476, 4489, 4527, 26017, 110, 116, 101, 114, 115, 101, 99, 116, 105, 111, 110, 59, 25235, 117, 256, 98, 112, 4495, 4510, 115, 101, 116, 256, 59, 69, 4503, 4504, 25231, 113, 117, 97, 108, 59, 25233, 101, 114, 115, 101, 116, 256, 59, 69, 4520, 4521, 25232, 113, 117, 97, 108, 59, 25234, 110, 105, 111, 110, 59, 25236, 99, 114, 59, 49152, 55349, 56494, 97, 114, 59, 25286, 512, 98, 99, 109, 112, 4552, 4571, 4617, 4619, 256, 59, 115, 4557, 4558, 25296, 101, 116, 256, 59, 69, 4557, 4565, 113, 117, 97, 108, 59, 25222, 256, 99, 104, 4576, 4613, 101, 101, 100, 115, 512, 59, 69, 83, 84, 4589, 4590, 4596, 4607, 25211, 113, 117, 97, 108, 59, 27312, 108, 97, 110, 116, 69, 113, 117, 97, 108, 59, 25213, 105, 108, 100, 101, 59, 25215, 84, 104, 225, 3980, 59, 25105, 384, 59, 101, 115, 4626, 4627, 4643, 25297, 114, 115, 101, 116, 256, 59, 69, 4636, 4637, 25219, 113, 117, 97, 108, 59, 25223, 101, 116, 187, 4627, 1408, 72, 82, 83, 97, 99, 102, 104, 105, 111, 114, 115, 4670, 4676, 4681, 4693, 4702, 4721, 4726, 4767, 4802, 4808, 4817, 79, 82, 78, 32827, 222, 16606, 65, 68, 69, 59, 24866, 256, 72, 99, 4686, 4690, 99, 121, 59, 17419, 121, 59, 17446, 256, 98, 117, 4698, 4700, 59, 16393, 59, 17316, 384, 97, 101, 121, 4709, 4714, 4719, 114, 111, 110, 59, 16740, 100, 105, 108, 59, 16738, 59, 17442, 114, 59, 49152, 55349, 56599, 256, 101, 105, 4731, 4745, 498, 4736, 0, 4743, 101, 102, 111, 114, 101, 59, 25140, 97, 59, 17304, 256, 99, 110, 4750, 4760, 107, 83, 112, 97, 99, 101, 59, 49152, 8287, 8202, 83, 112, 97, 99, 101, 59, 24585, 108, 100, 101, 512, 59, 69, 70, 84, 4779, 4780, 4786, 4796, 25148, 113, 117, 97, 108, 59, 25155, 117, 108, 108, 69, 113, 117, 97, 108, 59, 25157, 105, 108, 100, 101, 59, 25160, 112, 102, 59, 49152, 55349, 56651, 105, 112, 108, 101, 68, 111, 116, 59, 24795, 256, 99, 116, 4822, 4827, 114, 59, 49152, 55349, 56495, 114, 111, 107, 59, 16742, 2785, 4855, 4878, 4890, 4902, 0, 4908, 4913, 0, 0, 0, 0, 0, 4920, 4925, 4983, 4997, 0, 5119, 5124, 5130, 5136, 256, 99, 114, 4859, 4865, 117, 116, 101, 32827, 218, 16602, 114, 256, 59, 111, 4871, 4872, 24991, 99, 105, 114, 59, 26953, 114, 483, 4883, 0, 4886, 121, 59, 17422, 118, 101, 59, 16748, 256, 105, 121, 4894, 4899, 114, 99, 32827, 219, 16603, 59, 17443, 98, 108, 97, 99, 59, 16752, 114, 59, 49152, 55349, 56600, 114, 97, 118, 101, 32827, 217, 16601, 97, 99, 114, 59, 16746, 256, 100, 105, 4929, 4969, 101, 114, 256, 66, 80, 4936, 4957, 256, 97, 114, 4941, 4944, 114, 59, 16479, 97, 99, 256, 101, 107, 4951, 4953, 59, 25567, 101, 116, 59, 25525, 97, 114, 101, 110, 116, 104, 101, 115, 105, 115, 59, 25565, 111, 110, 256, 59, 80, 4976, 4977, 25283, 108, 117, 115, 59, 25230, 256, 103, 112, 4987, 4991, 111, 110, 59, 16754, 102, 59, 49152, 55349, 56652, 1024, 65, 68, 69, 84, 97, 100, 112, 115, 5013, 5038, 5048, 5060, 1000, 5074, 5079, 5107, 114, 114, 111, 119, 384, 59, 66, 68, 4432, 5024, 5028, 97, 114, 59, 26898, 111, 119, 110, 65, 114, 114, 111, 119, 59, 25029, 111, 119, 110, 65, 114, 114, 111, 119, 59, 24981, 113, 117, 105, 108, 105, 98, 114, 105, 117, 109, 59, 26990, 101, 101, 256, 59, 65, 5067, 5068, 25253, 114, 114, 111, 119, 59, 24997, 111, 119, 110, 225, 1011, 101, 114, 256, 76, 82, 5086, 5096, 101, 102, 116, 65, 114, 114, 111, 119, 59, 24982, 105, 103, 104, 116, 65, 114, 114, 111, 119, 59, 24983, 105, 256, 59, 108, 5113, 5114, 17362, 111, 110, 59, 17317, 105, 110, 103, 59, 16750, 99, 114, 59, 49152, 55349, 56496, 105, 108, 100, 101, 59, 16744, 109, 108, 32827, 220, 16604, 1152, 68, 98, 99, 100, 101, 102, 111, 115, 118, 5159, 5164, 5168, 5171, 5182, 5253, 5258, 5264, 5270, 97, 115, 104, 59, 25259, 97, 114, 59, 27371, 121, 59, 17426, 97, 115, 104, 256, 59, 108, 5179, 5180, 25257, 59, 27366, 256, 101, 114, 5187, 5189, 59, 25281, 384, 98, 116, 121, 5196, 5200, 5242, 97, 114, 59, 24598, 256, 59, 105, 5199, 5205, 99, 97, 108, 512, 66, 76, 83, 84, 5217, 5221, 5226, 5236, 97, 114, 59, 25123, 105, 110, 101, 59, 16508, 101, 112, 97, 114, 97, 116, 111, 114, 59, 26456, 105, 108, 100, 101, 59, 25152, 84, 104, 105, 110, 83, 112, 97, 99, 101, 59, 24586, 114, 59, 49152, 55349, 56601, 112, 102, 59, 49152, 55349, 56653, 99, 114, 59, 49152, 55349, 56497, 100, 97, 115, 104, 59, 25258, 640, 99, 101, 102, 111, 115, 5287, 5292, 5297, 5302, 5308, 105, 114, 99, 59, 16756, 100, 103, 101, 59, 25280, 114, 59, 49152, 55349, 56602, 112, 102, 59, 49152, 55349, 56654, 99, 114, 59, 49152, 55349, 56498, 512, 102, 105, 111, 115, 5323, 5328, 5330, 5336, 114, 59, 49152, 55349, 56603, 59, 17310, 112, 102, 59, 49152, 55349, 56655, 99, 114, 59, 49152, 55349, 56499, 1152, 65, 73, 85, 97, 99, 102, 111, 115, 117, 5361, 5365, 5369, 5373, 5380, 5391, 5396, 5402, 5408, 99, 121, 59, 17455, 99, 121, 59, 17415, 99, 121, 59, 17454, 99, 117, 116, 101, 32827, 221, 16605, 256, 105, 121, 5385, 5389, 114, 99, 59, 16758, 59, 17451, 114, 59, 49152, 55349, 56604, 112, 102, 59, 49152, 55349, 56656, 99, 114, 59, 49152, 55349, 56500, 109, 108, 59, 16760, 1024, 72, 97, 99, 100, 101, 102, 111, 115, 5429, 5433, 5439, 5451, 5455, 5469, 5472, 5476, 99, 121, 59, 17430, 99, 117, 116, 101, 59, 16761, 256, 97, 121, 5444, 5449, 114, 111, 110, 59, 16765, 59, 17431, 111, 116, 59, 16763, 498, 5460, 0, 5467, 111, 87, 105, 100, 116, 232, 2777, 97, 59, 17302, 114, 59, 24872, 112, 102, 59, 24868, 99, 114, 59, 49152, 55349, 56501, 3041, 5507, 5514, 5520, 0, 5552, 5558, 5567, 0, 0, 0, 0, 5574, 5595, 5611, 5727, 5741, 0, 5781, 5787, 5810, 5817, 0, 5822, 99, 117, 116, 101, 32827, 225, 16609, 114, 101, 118, 101, 59, 16643, 768, 59, 69, 100, 105, 117, 121, 5532, 5533, 5537, 5539, 5544, 5549, 25150, 59, 49152, 8766, 819, 59, 25151, 114, 99, 32827, 226, 16610, 116, 101, 32955, 180, 774, 59, 17456, 108, 105, 103, 32827, 230, 16614, 256, 59, 114, 178, 5562, 59, 49152, 55349, 56606, 114, 97, 118, 101, 32827, 224, 16608, 256, 101, 112, 5578, 5590, 256, 102, 112, 5583, 5588, 115, 121, 109, 59, 24885, 232, 5587, 104, 97, 59, 17329, 256, 97, 112, 5599, 99, 256, 99, 108, 5604, 5607, 114, 59, 16641, 103, 59, 27199, 612, 5616, 0, 0, 5642, 640, 59, 97, 100, 115, 118, 5626, 5627, 5631, 5633, 5639, 25127, 110, 100, 59, 27221, 59, 27228, 108, 111, 112, 101, 59, 27224, 59, 27226, 896, 59, 101, 108, 109, 114, 115, 122, 5656, 5657, 5659, 5662, 5695, 5711, 5721, 25120, 59, 27044, 101, 187, 5657, 115, 100, 256, 59, 97, 5669, 5670, 25121, 1121, 5680, 5682, 5684, 5686, 5688, 5690, 5692, 5694, 59, 27048, 59, 27049, 59, 27050, 59, 27051, 59, 27052, 59, 27053, 59, 27054, 59, 27055, 116, 256, 59, 118, 5701, 5702, 25119, 98, 256, 59, 100, 5708, 5709, 25278, 59, 27037, 256, 112, 116, 5716, 5719, 104, 59, 25122, 187, 185, 97, 114, 114, 59, 25468, 256, 103, 112, 5731, 5735, 111, 110, 59, 16645, 102, 59, 49152, 55349, 56658, 896, 59, 69, 97, 101, 105, 111, 112, 4801, 5755, 5757, 5762, 5764, 5767, 5770, 59, 27248, 99, 105, 114, 59, 27247, 59, 25162, 100, 59, 25163, 115, 59, 16423, 114, 111, 120, 256, 59, 101, 4801, 5778, 241, 5763, 105, 110, 103, 32827, 229, 16613, 384, 99, 116, 121, 5793, 5798, 5800, 114, 59, 49152, 55349, 56502, 59, 16426, 109, 112, 256, 59, 101, 4801, 5807, 241, 648, 105, 108, 100, 101, 32827, 227, 16611, 109, 108, 32827, 228, 16612, 256, 99, 105, 5826, 5832, 111, 110, 105, 110, 244, 626, 110, 116, 59, 27153, 2048, 78, 97, 98, 99, 100, 101, 102, 105, 107, 108, 110, 111, 112, 114, 115, 117, 5869, 5873, 5936, 5948, 5955, 5960, 6008, 6013, 6112, 6118, 6201, 6224, 5901, 6461, 6472, 6512, 111, 116, 59, 27373, 256, 99, 114, 5878, 5918, 107, 512, 99, 101, 112, 115, 5888, 5893, 5901, 5907, 111, 110, 103, 59, 25164, 112, 115, 105, 108, 111, 110, 59, 17398, 114, 105, 109, 101, 59, 24629, 105, 109, 256, 59, 101, 5914, 5915, 25149, 113, 59, 25293, 374, 5922, 5926, 101, 101, 59, 25277, 101, 100, 256, 59, 103, 5932, 5933, 25349, 101, 187, 5933, 114, 107, 256, 59, 116, 4956, 5943, 98, 114, 107, 59, 25526, 256, 111, 121, 5889, 5953, 59, 17457, 113, 117, 111, 59, 24606, 640, 99, 109, 112, 114, 116, 5971, 5979, 5985, 5988, 5992, 97, 117, 115, 256, 59, 101, 266, 265, 112, 116, 121, 118, 59, 27056, 115, 233, 5900, 110, 111, 245, 275, 384, 97, 104, 119, 5999, 6001, 6003, 59, 17330, 59, 24886, 101, 101, 110, 59, 25196, 114, 59, 49152, 55349, 56607, 103, 896, 99, 111, 115, 116, 117, 118, 119, 6029, 6045, 6067, 6081, 6101, 6107, 6110, 384, 97, 105, 117, 6036, 6038, 6042, 240, 1888, 114, 99, 59, 26095, 112, 187, 4977, 384, 100, 112, 116, 6052, 6056, 6061, 111, 116, 59, 27136, 108, 117, 115, 59, 27137, 105, 109, 101, 115, 59, 27138, 625, 6073, 0, 0, 6078, 99, 117, 112, 59, 27142, 97, 114, 59, 26117, 114, 105, 97, 110, 103, 108, 101, 256, 100, 117, 6093, 6098, 111, 119, 110, 59, 26045, 112, 59, 26035, 112, 108, 117, 115, 59, 27140, 101, 229, 5188, 229, 5293, 97, 114, 111, 119, 59, 26893, 384, 97, 107, 111, 6125, 6182, 6197, 256, 99, 110, 6130, 6179, 107, 384, 108, 115, 116, 6138, 1451, 6146, 111, 122, 101, 110, 103, 101, 59, 27115, 114, 105, 97, 110, 103, 108, 101, 512, 59, 100, 108, 114, 6162, 6163, 6168, 6173, 26036, 111, 119, 110, 59, 26046, 101, 102, 116, 59, 26050, 105, 103, 104, 116, 59, 26040, 107, 59, 25635, 433, 6187, 0, 6195, 434, 6191, 0, 6193, 59, 26002, 59, 26001, 52, 59, 26003, 99, 107, 59, 25992, 256, 101, 111, 6206, 6221, 256, 59, 113, 6211, 6214, 49152, 61, 8421, 117, 105, 118, 59, 49152, 8801, 8421, 116, 59, 25360, 512, 112, 116, 119, 120, 6233, 6238, 6247, 6252, 102, 59, 49152, 55349, 56659, 256, 59, 116, 5067, 6243, 111, 109, 187, 5068, 116, 105, 101, 59, 25288, 1536, 68, 72, 85, 86, 98, 100, 104, 109, 112, 116, 117, 118, 6277, 6294, 6314, 6331, 6359, 6363, 6380, 6399, 6405, 6410, 6416, 6433, 512, 76, 82, 108, 114, 6286, 6288, 6290, 6292, 59, 25943, 59, 25940, 59, 25942, 59, 25939, 640, 59, 68, 85, 100, 117, 6305, 6306, 6308, 6310, 6312, 25936, 59, 25958, 59, 25961, 59, 25956, 59, 25959, 512, 76, 82, 108, 114, 6323, 6325, 6327, 6329, 59, 25949, 59, 25946, 59, 25948, 59, 25945, 896, 59, 72, 76, 82, 104, 108, 114, 6346, 6347, 6349, 6351, 6353, 6355, 6357, 25937, 59, 25964, 59, 25955, 59, 25952, 59, 25963, 59, 25954, 59, 25951, 111, 120, 59, 27081, 512, 76, 82, 108, 114, 6372, 6374, 6376, 6378, 59, 25941, 59, 25938, 59, 25872, 59, 25868, 640, 59, 68, 85, 100, 117, 1725, 6391, 6393, 6395, 6397, 59, 25957, 59, 25960, 59, 25900, 59, 25908, 105, 110, 117, 115, 59, 25247, 108, 117, 115, 59, 25246, 105, 109, 101, 115, 59, 25248, 512, 76, 82, 108, 114, 6425, 6427, 6429, 6431, 59, 25947, 59, 25944, 59, 25880, 59, 25876, 896, 59, 72, 76, 82, 104, 108, 114, 6448, 6449, 6451, 6453, 6455, 6457, 6459, 25858, 59, 25962, 59, 25953, 59, 25950, 59, 25916, 59, 25892, 59, 25884, 256, 101, 118, 291, 6466, 98, 97, 114, 32827, 166, 16550, 512, 99, 101, 105, 111, 6481, 6486, 6490, 6496, 114, 59, 49152, 55349, 56503, 109, 105, 59, 24655, 109, 256, 59, 101, 5914, 5916, 108, 384, 59, 98, 104, 6504, 6505, 6507, 16476, 59, 27077, 115, 117, 98, 59, 26568, 364, 6516, 6526, 108, 256, 59, 101, 6521, 6522, 24610, 116, 187, 6522, 112, 384, 59, 69, 101, 303, 6533, 6535, 59, 27310, 256, 59, 113, 1756, 1755, 3297, 6567, 0, 6632, 6673, 6677, 6706, 0, 6711, 6736, 0, 0, 6836, 0, 0, 6849, 0, 0, 6945, 6958, 6989, 6994, 0, 7165, 0, 7180, 384, 99, 112, 114, 6573, 6578, 6621, 117, 116, 101, 59, 16647, 768, 59, 97, 98, 99, 100, 115, 6591, 6592, 6596, 6602, 6613, 6617, 25129, 110, 100, 59, 27204, 114, 99, 117, 112, 59, 27209, 256, 97, 117, 6607, 6610, 112, 59, 27211, 112, 59, 27207, 111, 116, 59, 27200, 59, 49152, 8745, 65024, 256, 101, 111, 6626, 6629, 116, 59, 24641, 238, 1683, 512, 97, 101, 105, 117, 6640, 6651, 6657, 6661, 496, 6645, 0, 6648, 115, 59, 27213, 111, 110, 59, 16653, 100, 105, 108, 32827, 231, 16615, 114, 99, 59, 16649, 112, 115, 256, 59, 115, 6668, 6669, 27212, 109, 59, 27216, 111, 116, 59, 16651, 384, 100, 109, 110, 6683, 6688, 6694, 105, 108, 32955, 184, 429, 112, 116, 121, 118, 59, 27058, 116, 33024, 162, 59, 101, 6701, 6702, 16546, 114, 228, 434, 114, 59, 49152, 55349, 56608, 384, 99, 101, 105, 6717, 6720, 6733, 121, 59, 17479, 99, 107, 256, 59, 109, 6727, 6728, 26387, 97, 114, 107, 187, 6728, 59, 17351, 114, 896, 59, 69, 99, 101, 102, 109, 115, 6751, 6752, 6754, 6763, 6820, 6826, 6830, 26059, 59, 27075, 384, 59, 101, 108, 6761, 6762, 6765, 17094, 113, 59, 25175, 101, 609, 6772, 0, 0, 6792, 114, 114, 111, 119, 256, 108, 114, 6780, 6785, 101, 102, 116, 59, 25018, 105, 103, 104, 116, 59, 25019, 640, 82, 83, 97, 99, 100, 6802, 6804, 6806, 6810, 6815, 187, 3911, 59, 25800, 115, 116, 59, 25243, 105, 114, 99, 59, 25242, 97, 115, 104, 59, 25245, 110, 105, 110, 116, 59, 27152, 105, 100, 59, 27375, 99, 105, 114, 59, 27074, 117, 98, 115, 256, 59, 117, 6843, 6844, 26211, 105, 116, 187, 6844, 748, 6855, 6868, 6906, 0, 6922, 111, 110, 256, 59, 101, 6861, 6862, 16442, 256, 59, 113, 199, 198, 621, 6873, 0, 0, 6882, 97, 256, 59, 116, 6878, 6879, 16428, 59, 16448, 384, 59, 102, 108, 6888, 6889, 6891, 25089, 238, 4448, 101, 256, 109, 120, 6897, 6902, 101, 110, 116, 187, 6889, 101, 243, 589, 487, 6910, 0, 6919, 256, 59, 100, 4795, 6914, 111, 116, 59, 27245, 110, 244, 582, 384, 102, 114, 121, 6928, 6932, 6935, 59, 49152, 55349, 56660, 111, 228, 596, 33024, 169, 59, 115, 341, 6941, 114, 59, 24855, 256, 97, 111, 6949, 6953, 114, 114, 59, 25013, 115, 115, 59, 26391, 256, 99, 117, 6962, 6967, 114, 59, 49152, 55349, 56504, 256, 98, 112, 6972, 6980, 256, 59, 101, 6977, 6978, 27343, 59, 27345, 256, 59, 101, 6985, 6986, 27344, 59, 27346, 100, 111, 116, 59, 25327, 896, 100, 101, 108, 112, 114, 118, 119, 7008, 7020, 7031, 7042, 7084, 7124, 7161, 97, 114, 114, 256, 108, 114, 7016, 7018, 59, 26936, 59, 26933, 624, 7026, 0, 0, 7029, 114, 59, 25310, 99, 59, 25311, 97, 114, 114, 256, 59, 112, 7039, 7040, 25014, 59, 26941, 768, 59, 98, 99, 100, 111, 115, 7055, 7056, 7062, 7073, 7077, 7080, 25130, 114, 99, 97, 112, 59, 27208, 256, 97, 117, 7067, 7070, 112, 59, 27206, 112, 59, 27210, 111, 116, 59, 25229, 114, 59, 27205, 59, 49152, 8746, 65024, 512, 97, 108, 114, 118, 7093, 7103, 7134, 7139, 114, 114, 256, 59, 109, 7100, 7101, 25015, 59, 26940, 121, 384, 101, 118, 119, 7111, 7124, 7128, 113, 624, 7118, 0, 0, 7122, 114, 101, 227, 7027, 117, 227, 7029, 101, 101, 59, 25294, 101, 100, 103, 101, 59, 25295, 101, 110, 32827, 164, 16548, 101, 97, 114, 114, 111, 119, 256, 108, 114, 7150, 7155, 101, 102, 116, 187, 7040, 105, 103, 104, 116, 187, 7101, 101, 228, 7133, 256, 99, 105, 7169, 7175, 111, 110, 105, 110, 244, 503, 110, 116, 59, 25137, 108, 99, 116, 121, 59, 25389, 2432, 65, 72, 97, 98, 99, 100, 101, 102, 104, 105, 106, 108, 111, 114, 115, 116, 117, 119, 122, 7224, 7227, 7231, 7261, 7273, 7285, 7306, 7326, 7340, 7351, 7419, 7423, 7437, 7547, 7569, 7595, 7611, 7622, 7629, 114, 242, 897, 97, 114, 59, 26981, 512, 103, 108, 114, 115, 7240, 7245, 7250, 7252, 103, 101, 114, 59, 24608, 101, 116, 104, 59, 24888, 242, 4403, 104, 256, 59, 118, 7258, 7259, 24592, 187, 2314, 363, 7265, 7271, 97, 114, 111, 119, 59, 26895, 97, 227, 789, 256, 97, 121, 7278, 7283, 114, 111, 110, 59, 16655, 59, 17460, 384, 59, 97, 111, 818, 7292, 7300, 256, 103, 114, 703, 7297, 114, 59, 25034, 116, 115, 101, 113, 59, 27255, 384, 103, 108, 109, 7313, 7316, 7320, 32827, 176, 16560, 116, 97, 59, 17332, 112, 116, 121, 118, 59, 27057, 256, 105, 114, 7331, 7336, 115, 104, 116, 59, 27007, 59, 49152, 55349, 56609, 97, 114, 256, 108, 114, 7347, 7349, 187, 2268, 187, 4126, 640, 97, 101, 103, 115, 118, 7362, 888, 7382, 7388, 7392, 109, 384, 59, 111, 115, 806, 7370, 7380, 110, 100, 256, 59, 115, 806, 7377, 117, 105, 116, 59, 26214, 97, 109, 109, 97, 59, 17373, 105, 110, 59, 25330, 384, 59, 105, 111, 7399, 7400, 7416, 16631, 100, 101, 33024, 247, 59, 111, 7399, 7408, 110, 116, 105, 109, 101, 115, 59, 25287, 110, 248, 7415, 99, 121, 59, 17490, 99, 623, 7430, 0, 0, 7434, 114, 110, 59, 25374, 111, 112, 59, 25357, 640, 108, 112, 116, 117, 119, 7448, 7453, 7458, 7497, 7509, 108, 97, 114, 59, 16420, 102, 59, 49152, 55349, 56661, 640, 59, 101, 109, 112, 115, 779, 7469, 7479, 7485, 7490, 113, 256, 59, 100, 850, 7475, 111, 116, 59, 25169, 105, 110, 117, 115, 59, 25144, 108, 117, 115, 59, 25108, 113, 117, 97, 114, 101, 59, 25249, 98, 108, 101, 98, 97, 114, 119, 101, 100, 103, 229, 250, 110, 384, 97, 100, 104, 4398, 7517, 7527, 111, 119, 110, 97, 114, 114, 111, 119, 243, 7299, 97, 114, 112, 111, 111, 110, 256, 108, 114, 7538, 7542, 101, 102, 244, 7348, 105, 103, 104, 244, 7350, 354, 7551, 7557, 107, 97, 114, 111, 247, 3906, 623, 7562, 0, 0, 7566, 114, 110, 59, 25375, 111, 112, 59, 25356, 384, 99, 111, 116, 7576, 7587, 7590, 256, 114, 121, 7581, 7585, 59, 49152, 55349, 56505, 59, 17493, 108, 59, 27126, 114, 111, 107, 59, 16657, 256, 100, 114, 7600, 7604, 111, 116, 59, 25329, 105, 256, 59, 102, 7610, 6166, 26047, 256, 97, 104, 7616, 7619, 114, 242, 1065, 97, 242, 4006, 97, 110, 103, 108, 101, 59, 27046, 256, 99, 105, 7634, 7637, 121, 59, 17503, 103, 114, 97, 114, 114, 59, 26623, 2304, 68, 97, 99, 100, 101, 102, 103, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 120, 7681, 7689, 7705, 7736, 1400, 7740, 7753, 7777, 7806, 7845, 7855, 7869, 7905, 7978, 7991, 8004, 8014, 8026, 256, 68, 111, 7686, 7476, 111, 244, 7305, 256, 99, 115, 7694, 7700, 117, 116, 101, 32827, 233, 16617, 116, 101, 114, 59, 27246, 512, 97, 105, 111, 121, 7714, 7719, 7729, 7734, 114, 111, 110, 59, 16667, 114, 256, 59, 99, 7725, 7726, 25174, 32827, 234, 16618, 108, 111, 110, 59, 25173, 59, 17485, 111, 116, 59, 16663, 256, 68, 114, 7745, 7749, 111, 116, 59, 25170, 59, 49152, 55349, 56610, 384, 59, 114, 115, 7760, 7761, 7767, 27290, 97, 118, 101, 32827, 232, 16616, 256, 59, 100, 7772, 7773, 27286, 111, 116, 59, 27288, 512, 59, 105, 108, 115, 7786, 7787, 7794, 7796, 27289, 110, 116, 101, 114, 115, 59, 25575, 59, 24851, 256, 59, 100, 7801, 7802, 27285, 111, 116, 59, 27287, 384, 97, 112, 115, 7813, 7817, 7831, 99, 114, 59, 16659, 116, 121, 384, 59, 115, 118, 7826, 7827, 7829, 25093, 101, 116, 187, 7827, 112, 256, 49, 59, 7837, 7844, 307, 7841, 7843, 59, 24580, 59, 24581, 24579, 256, 103, 115, 7850, 7852, 59, 16715, 112, 59, 24578, 256, 103, 112, 7860, 7864, 111, 110, 59, 16665, 102, 59, 49152, 55349, 56662, 384, 97, 108, 115, 7876, 7886, 7890, 114, 256, 59, 115, 7882, 7883, 25301, 108, 59, 27107, 117, 115, 59, 27249, 105, 384, 59, 108, 118, 7898, 7899, 7903, 17333, 111, 110, 187, 7899, 59, 17397, 512, 99, 115, 117, 118, 7914, 7923, 7947, 7971, 256, 105, 111, 7919, 7729, 114, 99, 187, 7726, 617, 7929, 0, 0, 7931, 237, 1352, 97, 110, 116, 256, 103, 108, 7938, 7942, 116, 114, 187, 7773, 101, 115, 115, 187, 7802, 384, 97, 101, 105, 7954, 7958, 7962, 108, 115, 59, 16445, 115, 116, 59, 25183, 118, 256, 59, 68, 565, 7968, 68, 59, 27256, 112, 97, 114, 115, 108, 59, 27109, 256, 68, 97, 7983, 7987, 111, 116, 59, 25171, 114, 114, 59, 26993, 384, 99, 100, 105, 7998, 8001, 7928, 114, 59, 24879, 111, 244, 850, 256, 97, 104, 8009, 8011, 59, 17335, 32827, 240, 16624, 256, 109, 114, 8019, 8023, 108, 32827, 235, 16619, 111, 59, 24748, 384, 99, 105, 112, 8033, 8036, 8039, 108, 59, 16417, 115, 244, 1390, 256, 101, 111, 8044, 8052, 99, 116, 97, 116, 105, 111, 238, 1369, 110, 101, 110, 116, 105, 97, 108, 229, 1401, 2529, 8082, 0, 8094, 0, 8097, 8103, 0, 0, 8134, 8140, 0, 8147, 0, 8166, 8170, 8192, 0, 8200, 8282, 108, 108, 105, 110, 103, 100, 111, 116, 115, 101, 241, 7748, 121, 59, 17476, 109, 97, 108, 101, 59, 26176, 384, 105, 108, 114, 8109, 8115, 8129, 108, 105, 103, 59, 32768, 64259, 617, 8121, 0, 0, 8125, 103, 59, 32768, 64256, 105, 103, 59, 32768, 64260, 59, 49152, 55349, 56611, 108, 105, 103, 59, 32768, 64257, 108, 105, 103, 59, 49152, 102, 106, 384, 97, 108, 116, 8153, 8156, 8161, 116, 59, 26221, 105, 103, 59, 32768, 64258, 110, 115, 59, 26033, 111, 102, 59, 16786, 496, 8174, 0, 8179, 102, 59, 49152, 55349, 56663, 256, 97, 107, 1471, 8183, 256, 59, 118, 8188, 8189, 25300, 59, 27353, 97, 114, 116, 105, 110, 116, 59, 27149, 256, 97, 111, 8204, 8277, 256, 99, 115, 8209, 8274, 945, 8218, 8240, 8248, 8261, 8264, 0, 8272, 946, 8226, 8229, 8231, 8234, 8236, 0, 8238, 32827, 189, 16573, 59, 24915, 32827, 188, 16572, 59, 24917, 59, 24921, 59, 24923, 435, 8244, 0, 8246, 59, 24916, 59, 24918, 692, 8254, 8257, 0, 0, 8259, 32827, 190, 16574, 59, 24919, 59, 24924, 53, 59, 24920, 438, 8268, 0, 8270, 59, 24922, 59, 24925, 56, 59, 24926, 108, 59, 24644, 119, 110, 59, 25378, 99, 114, 59, 49152, 55349, 56507, 2176, 69, 97, 98, 99, 100, 101, 102, 103, 105, 106, 108, 110, 111, 114, 115, 116, 118, 8322, 8329, 8351, 8357, 8368, 8372, 8432, 8437, 8442, 8447, 8451, 8466, 8504, 791, 8510, 8530, 8606, 256, 59, 108, 1613, 8327, 59, 27276, 384, 99, 109, 112, 8336, 8341, 8349, 117, 116, 101, 59, 16885, 109, 97, 256, 59, 100, 8348, 7386, 17331, 59, 27270, 114, 101, 118, 101, 59, 16671, 256, 105, 121, 8362, 8366, 114, 99, 59, 16669, 59, 17459, 111, 116, 59, 16673, 512, 59, 108, 113, 115, 1598, 1602, 8381, 8393, 384, 59, 113, 115, 1598, 1612, 8388, 108, 97, 110, 244, 1637, 512, 59, 99, 100, 108, 1637, 8402, 8405, 8421, 99, 59, 27305, 111, 116, 256, 59, 111, 8412, 8413, 27264, 256, 59, 108, 8418, 8419, 27266, 59, 27268, 256, 59, 101, 8426, 8429, 49152, 8923, 65024, 115, 59, 27284, 114, 59, 49152, 55349, 56612, 256, 59, 103, 1651, 1563, 109, 101, 108, 59, 24887, 99, 121, 59, 17491, 512, 59, 69, 97, 106, 1626, 8460, 8462, 8464, 59, 27282, 59, 27301, 59, 27300, 512, 69, 97, 101, 115, 8475, 8477, 8489, 8500, 59, 25193, 112, 256, 59, 112, 8483, 8484, 27274, 114, 111, 120, 187, 8484, 256, 59, 113, 8494, 8495, 27272, 256, 59, 113, 8494, 8475, 105, 109, 59, 25319, 112, 102, 59, 49152, 55349, 56664, 256, 99, 105, 8515, 8518, 114, 59, 24842, 109, 384, 59, 101, 108, 1643, 8526, 8528, 59, 27278, 59, 27280, 33536, 62, 59, 99, 100, 108, 113, 114, 1518, 8544, 8554, 8558, 8563, 8569, 256, 99, 105, 8549, 8551, 59, 27303, 114, 59, 27258, 111, 116, 59, 25303, 80, 97, 114, 59, 27029, 117, 101, 115, 116, 59, 27260, 640, 97, 100, 101, 108, 115, 8580, 8554, 8592, 1622, 8603, 496, 8585, 0, 8590, 112, 114, 111, 248, 8350, 114, 59, 27000, 113, 256, 108, 113, 1599, 8598, 108, 101, 115, 243, 8328, 105, 237, 1643, 256, 101, 110, 8611, 8621, 114, 116, 110, 101, 113, 113, 59, 49152, 8809, 65024, 197, 8618, 1280, 65, 97, 98, 99, 101, 102, 107, 111, 115, 121, 8644, 8647, 8689, 8693, 8698, 8728, 8733, 8751, 8808, 8829, 114, 242, 928, 512, 105, 108, 109, 114, 8656, 8660, 8663, 8667, 114, 115, 240, 5252, 102, 187, 8228, 105, 108, 244, 1705, 256, 100, 114, 8672, 8676, 99, 121, 59, 17482, 384, 59, 99, 119, 2292, 8683, 8687, 105, 114, 59, 26952, 59, 25005, 97, 114, 59, 24847, 105, 114, 99, 59, 16677, 384, 97, 108, 114, 8705, 8718, 8723, 114, 116, 115, 256, 59, 117, 8713, 8714, 26213, 105, 116, 187, 8714, 108, 105, 112, 59, 24614, 99, 111, 110, 59, 25273, 114, 59, 49152, 55349, 56613, 115, 256, 101, 119, 8739, 8745, 97, 114, 111, 119, 59, 26917, 97, 114, 111, 119, 59, 26918, 640, 97, 109, 111, 112, 114, 8762, 8766, 8771, 8798, 8803, 114, 114, 59, 25087, 116, 104, 116, 59, 25147, 107, 256, 108, 114, 8777, 8787, 101, 102, 116, 97, 114, 114, 111, 119, 59, 25001, 105, 103, 104, 116, 97, 114, 114, 111, 119, 59, 25002, 102, 59, 49152, 55349, 56665, 98, 97, 114, 59, 24597, 384, 99, 108, 116, 8815, 8820, 8824, 114, 59, 49152, 55349, 56509, 97, 115, 232, 8692, 114, 111, 107, 59, 16679, 256, 98, 112, 8834, 8839, 117, 108, 108, 59, 24643, 104, 101, 110, 187, 7259, 2785, 8867, 0, 8874, 0, 8888, 8901, 8910, 0, 8917, 8947, 0, 0, 8952, 8994, 9063, 9058, 9087, 0, 9094, 9130, 9140, 99, 117, 116, 101, 32827, 237, 16621, 384, 59, 105, 121, 1905, 8880, 8885, 114, 99, 32827, 238, 16622, 59, 17464, 256, 99, 120, 8892, 8895, 121, 59, 17461, 99, 108, 32827, 161, 16545, 256, 102, 114, 927, 8905, 59, 49152, 55349, 56614, 114, 97, 118, 101, 32827, 236, 16620, 512, 59, 105, 110, 111, 1854, 8925, 8937, 8942, 256, 105, 110, 8930, 8934, 110, 116, 59, 27148, 116, 59, 25133, 102, 105, 110, 59, 27100, 116, 97, 59, 24873, 108, 105, 103, 59, 16691, 384, 97, 111, 112, 8958, 8986, 8989, 384, 99, 103, 116, 8965, 8968, 8983, 114, 59, 16683, 384, 101, 108, 112, 1823, 8975, 8979, 105, 110, 229, 1934, 97, 114, 244, 1824, 104, 59, 16689, 102, 59, 25271, 101, 100, 59, 16821, 640, 59, 99, 102, 111, 116, 1268, 9004, 9009, 9021, 9025, 97, 114, 101, 59, 24837, 105, 110, 256, 59, 116, 9016, 9017, 25118, 105, 101, 59, 27101, 100, 111, 244, 8985, 640, 59, 99, 101, 108, 112, 1879, 9036, 9040, 9051, 9057, 97, 108, 59, 25274, 256, 103, 114, 9045, 9049, 101, 114, 243, 5475, 227, 9037, 97, 114, 104, 107, 59, 27159, 114, 111, 100, 59, 27196, 512, 99, 103, 112, 116, 9071, 9074, 9078, 9083, 121, 59, 17489, 111, 110, 59, 16687, 102, 59, 49152, 55349, 56666, 97, 59, 17337, 117, 101, 115, 116, 32827, 191, 16575, 256, 99, 105, 9098, 9103, 114, 59, 49152, 55349, 56510, 110, 640, 59, 69, 100, 115, 118, 1268, 9115, 9117, 9121, 1267, 59, 25337, 111, 116, 59, 25333, 256, 59, 118, 9126, 9127, 25332, 59, 25331, 256, 59, 105, 1911, 9134, 108, 100, 101, 59, 16681, 491, 9144, 0, 9148, 99, 121, 59, 17494, 108, 32827, 239, 16623, 768, 99, 102, 109, 111, 115, 117, 9164, 9175, 9180, 9185, 9191, 9205, 256, 105, 121, 9169, 9173, 114, 99, 59, 16693, 59, 17465, 114, 59, 49152, 55349, 56615, 97, 116, 104, 59, 16951, 112, 102, 59, 49152, 55349, 56667, 483, 9196, 0, 9201, 114, 59, 49152, 55349, 56511, 114, 99, 121, 59, 17496, 107, 99, 121, 59, 17492, 1024, 97, 99, 102, 103, 104, 106, 111, 115, 9227, 9238, 9250, 9255, 9261, 9265, 9269, 9275, 112, 112, 97, 256, 59, 118, 9235, 9236, 17338, 59, 17392, 256, 101, 121, 9243, 9248, 100, 105, 108, 59, 16695, 59, 17466, 114, 59, 49152, 55349, 56616, 114, 101, 101, 110, 59, 16696, 99, 121, 59, 17477, 99, 121, 59, 17500, 112, 102, 59, 49152, 55349, 56668, 99, 114, 59, 49152, 55349, 56512, 2944, 65, 66, 69, 72, 97, 98, 99, 100, 101, 102, 103, 104, 106, 108, 109, 110, 111, 112, 114, 115, 116, 117, 118, 9328, 9345, 9350, 9357, 9361, 9486, 9533, 9562, 9600, 9806, 9822, 9829, 9849, 9853, 9882, 9906, 9944, 10077, 10088, 10123, 10176, 10241, 10258, 384, 97, 114, 116, 9335, 9338, 9340, 114, 242, 2502, 242, 917, 97, 105, 108, 59, 26907, 97, 114, 114, 59, 26894, 256, 59, 103, 2452, 9355, 59, 27275, 97, 114, 59, 26978, 2403, 9381, 0, 9386, 0, 9393, 0, 0, 0, 0, 0, 9397, 9402, 0, 9414, 9416, 9421, 0, 9465, 117, 116, 101, 59, 16698, 109, 112, 116, 121, 118, 59, 27060, 114, 97, 238, 2124, 98, 100, 97, 59, 17339, 103, 384, 59, 100, 108, 2190, 9409, 9411, 59, 27025, 229, 2190, 59, 27269, 117, 111, 32827, 171, 16555, 114, 1024, 59, 98, 102, 104, 108, 112, 115, 116, 2201, 9438, 9446, 9449, 9451, 9454, 9457, 9461, 256, 59, 102, 2205, 9443, 115, 59, 26911, 115, 59, 26909, 235, 8786, 112, 59, 25003, 108, 59, 26937, 105, 109, 59, 26995, 108, 59, 24994, 384, 59, 97, 101, 9471, 9472, 9476, 27307, 105, 108, 59, 26905, 256, 59, 115, 9481, 9482, 27309, 59, 49152, 10925, 65024, 384, 97, 98, 114, 9493, 9497, 9501, 114, 114, 59, 26892, 114, 107, 59, 26482, 256, 97, 107, 9506, 9516, 99, 256, 101, 107, 9512, 9514, 59, 16507, 59, 16475, 256, 101, 115, 9521, 9523, 59, 27019, 108, 256, 100, 117, 9529, 9531, 59, 27023, 59, 27021, 512, 97, 101, 117, 121, 9542, 9547, 9558, 9560, 114, 111, 110, 59, 16702, 256, 100, 105, 9552, 9556, 105, 108, 59, 16700, 236, 2224, 226, 9513, 59, 17467, 512, 99, 113, 114, 115, 9571, 9574, 9581, 9597, 97, 59, 26934, 117, 111, 256, 59, 114, 3609, 5958, 256, 100, 117, 9586, 9591, 104, 97, 114, 59, 26983, 115, 104, 97, 114, 59, 26955, 104, 59, 25010, 640, 59, 102, 103, 113, 115, 9611, 9612, 2441, 9715, 9727, 25188, 116, 640, 97, 104, 108, 114, 116, 9624, 9636, 9655, 9666, 9704, 114, 114, 111, 119, 256, 59, 116, 2201, 9633, 97, 233, 9462, 97, 114, 112, 111, 111, 110, 256, 100, 117, 9647, 9652, 111, 119, 110, 187, 1114, 112, 187, 2406, 101, 102, 116, 97, 114, 114, 111, 119, 115, 59, 25031, 105, 103, 104, 116, 384, 97, 104, 115, 9677, 9686, 9694, 114, 114, 111, 119, 256, 59, 115, 2292, 2215, 97, 114, 112, 111, 111, 110, 243, 3992, 113, 117, 105, 103, 97, 114, 114, 111, 247, 8688, 104, 114, 101, 101, 116, 105, 109, 101, 115, 59, 25291, 384, 59, 113, 115, 9611, 2451, 9722, 108, 97, 110, 244, 2476, 640, 59, 99, 100, 103, 115, 2476, 9738, 9741, 9757, 9768, 99, 59, 27304, 111, 116, 256, 59, 111, 9748, 9749, 27263, 256, 59, 114, 9754, 9755, 27265, 59, 27267, 256, 59, 101, 9762, 9765, 49152, 8922, 65024, 115, 59, 27283, 640, 97, 100, 101, 103, 115, 9779, 9785, 9789, 9801, 9803, 112, 112, 114, 111, 248, 9414, 111, 116, 59, 25302, 113, 256, 103, 113, 9795, 9797, 244, 2441, 103, 116, 242, 9356, 244, 2459, 105, 237, 2482, 384, 105, 108, 114, 9813, 2273, 9818, 115, 104, 116, 59, 27004, 59, 49152, 55349, 56617, 256, 59, 69, 2460, 9827, 59, 27281, 353, 9833, 9846, 114, 256, 100, 117, 9650, 9838, 256, 59, 108, 2405, 9843, 59, 26986, 108, 107, 59, 25988, 99, 121, 59, 17497, 640, 59, 97, 99, 104, 116, 2632, 9864, 9867, 9873, 9878, 114, 242, 9665, 111, 114, 110, 101, 242, 7432, 97, 114, 100, 59, 26987, 114, 105, 59, 26106, 256, 105, 111, 9887, 9892, 100, 111, 116, 59, 16704, 117, 115, 116, 256, 59, 97, 9900, 9901, 25520, 99, 104, 101, 187, 9901, 512, 69, 97, 101, 115, 9915, 9917, 9929, 9940, 59, 25192, 112, 256, 59, 112, 9923, 9924, 27273, 114, 111, 120, 187, 9924, 256, 59, 113, 9934, 9935, 27271, 256, 59, 113, 9934, 9915, 105, 109, 59, 25318, 1024, 97, 98, 110, 111, 112, 116, 119, 122, 9961, 9972, 9975, 10010, 10031, 10049, 10055, 10064, 256, 110, 114, 9966, 9969, 103, 59, 26604, 114, 59, 25085, 114, 235, 2241, 103, 384, 108, 109, 114, 9983, 9997, 10004, 101, 102, 116, 256, 97, 114, 2534, 9991, 105, 103, 104, 116, 225, 2546, 97, 112, 115, 116, 111, 59, 26620, 105, 103, 104, 116, 225, 2557, 112, 97, 114, 114, 111, 119, 256, 108, 114, 10021, 10025, 101, 102, 244, 9453, 105, 103, 104, 116, 59, 25004, 384, 97, 102, 108, 10038, 10041, 10045, 114, 59, 27013, 59, 49152, 55349, 56669, 117, 115, 59, 27181, 105, 109, 101, 115, 59, 27188, 353, 10059, 10063, 115, 116, 59, 25111, 225, 4942, 384, 59, 101, 102, 10071, 10072, 6144, 26058, 110, 103, 101, 187, 10072, 97, 114, 256, 59, 108, 10084, 10085, 16424, 116, 59, 27027, 640, 97, 99, 104, 109, 116, 10099, 10102, 10108, 10117, 10119, 114, 242, 2216, 111, 114, 110, 101, 242, 7564, 97, 114, 256, 59, 100, 3992, 10115, 59, 26989, 59, 24590, 114, 105, 59, 25279, 768, 97, 99, 104, 105, 113, 116, 10136, 10141, 2624, 10146, 10158, 10171, 113, 117, 111, 59, 24633, 114, 59, 49152, 55349, 56513, 109, 384, 59, 101, 103, 2482, 10154, 10156, 59, 27277, 59, 27279, 256, 98, 117, 9514, 10163, 111, 256, 59, 114, 3615, 10169, 59, 24602, 114, 111, 107, 59, 16706, 33792, 60, 59, 99, 100, 104, 105, 108, 113, 114, 2091, 10194, 9785, 10204, 10208, 10213, 10218, 10224, 256, 99, 105, 10199, 10201, 59, 27302, 114, 59, 27257, 114, 101, 229, 9714, 109, 101, 115, 59, 25289, 97, 114, 114, 59, 26998, 117, 101, 115, 116, 59, 27259, 256, 80, 105, 10229, 10233, 97, 114, 59, 27030, 384, 59, 101, 102, 10240, 2349, 6171, 26051, 114, 256, 100, 117, 10247, 10253, 115, 104, 97, 114, 59, 26954, 104, 97, 114, 59, 26982, 256, 101, 110, 10263, 10273, 114, 116, 110, 101, 113, 113, 59, 49152, 8808, 65024, 197, 10270, 1792, 68, 97, 99, 100, 101, 102, 104, 105, 108, 110, 111, 112, 115, 117, 10304, 10309, 10370, 10382, 10387, 10400, 10405, 10408, 10458, 10466, 10468, 2691, 10483, 10498, 68, 111, 116, 59, 25146, 512, 99, 108, 112, 114, 10318, 10322, 10339, 10365, 114, 32827, 175, 16559, 256, 101, 116, 10327, 10329, 59, 26178, 256, 59, 101, 10334, 10335, 26400, 115, 101, 187, 10335, 256, 59, 115, 4155, 10344, 116, 111, 512, 59, 100, 108, 117, 4155, 10355, 10359, 10363, 111, 119, 238, 1164, 101, 102, 244, 2319, 240, 5073, 107, 101, 114, 59, 26030, 256, 111, 121, 10375, 10380, 109, 109, 97, 59, 27177, 59, 17468, 97, 115, 104, 59, 24596, 97, 115, 117, 114, 101, 100, 97, 110, 103, 108, 101, 187, 5670, 114, 59, 49152, 55349, 56618, 111, 59, 24871, 384, 99, 100, 110, 10415, 10420, 10441, 114, 111, 32827, 181, 16565, 512, 59, 97, 99, 100, 5220, 10429, 10432, 10436, 115, 244, 5799, 105, 114, 59, 27376, 111, 116, 32955, 183, 437, 117, 115, 384, 59, 98, 100, 10450, 6403, 10451, 25106, 256, 59, 117, 7484, 10456, 59, 27178, 355, 10462, 10465, 112, 59, 27355, 242, 8722, 240, 2689, 256, 100, 112, 10473, 10478, 101, 108, 115, 59, 25255, 102, 59, 49152, 55349, 56670, 256, 99, 116, 10488, 10493, 114, 59, 49152, 55349, 56514, 112, 111, 115, 187, 5533, 384, 59, 108, 109, 10505, 10506, 10509, 17340, 116, 105, 109, 97, 112, 59, 25272, 3072, 71, 76, 82, 86, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 108, 109, 111, 112, 114, 115, 116, 117, 118, 119, 10562, 10579, 10622, 10633, 10648, 10714, 10729, 10773, 10778, 10840, 10845, 10883, 10901, 10916, 10920, 11012, 11015, 11076, 11135, 11182, 11316, 11367, 11388, 11497, 256, 103, 116, 10567, 10571, 59, 49152, 8921, 824, 256, 59, 118, 10576, 3023, 49152, 8811, 8402, 384, 101, 108, 116, 10586, 10610, 10614, 102, 116, 256, 97, 114, 10593, 10599, 114, 114, 111, 119, 59, 25037, 105, 103, 104, 116, 97, 114, 114, 111, 119, 59, 25038, 59, 49152, 8920, 824, 256, 59, 118, 10619, 3143, 49152, 8810, 8402, 105, 103, 104, 116, 97, 114, 114, 111, 119, 59, 25039, 256, 68, 100, 10638, 10643, 97, 115, 104, 59, 25263, 97, 115, 104, 59, 25262, 640, 98, 99, 110, 112, 116, 10659, 10663, 10668, 10673, 10700, 108, 97, 187, 734, 117, 116, 101, 59, 16708, 103, 59, 49152, 8736, 8402, 640, 59, 69, 105, 111, 112, 3460, 10684, 10688, 10693, 10696, 59, 49152, 10864, 824, 100, 59, 49152, 8779, 824, 115, 59, 16713, 114, 111, 248, 3460, 117, 114, 256, 59, 97, 10707, 10708, 26222, 108, 256, 59, 115, 10707, 2872, 499, 10719, 0, 10723, 112, 32955, 160, 2871, 109, 112, 256, 59, 101, 3065, 3072, 640, 97, 101, 111, 117, 121, 10740, 10750, 10755, 10768, 10771, 496, 10745, 0, 10747, 59, 27203, 111, 110, 59, 16712, 100, 105, 108, 59, 16710, 110, 103, 256, 59, 100, 3454, 10762, 111, 116, 59, 49152, 10861, 824, 112, 59, 27202, 59, 17469, 97, 115, 104, 59, 24595, 896, 59, 65, 97, 100, 113, 115, 120, 2962, 10793, 10797, 10811, 10817, 10821, 10832, 114, 114, 59, 25047, 114, 256, 104, 114, 10803, 10806, 107, 59, 26916, 256, 59, 111, 5106, 5104, 111, 116, 59, 49152, 8784, 824, 117, 105, 246, 2915, 256, 101, 105, 10826, 10830, 97, 114, 59, 26920, 237, 2968, 105, 115, 116, 256, 59, 115, 2976, 2975, 114, 59, 49152, 55349, 56619, 512, 69, 101, 115, 116, 3013, 10854, 10873, 10876, 384, 59, 113, 115, 3004, 10861, 3041, 384, 59, 113, 115, 3004, 3013, 10868, 108, 97, 110, 244, 3042, 105, 237, 3050, 256, 59, 114, 2998, 10881, 187, 2999, 384, 65, 97, 112, 10890, 10893, 10897, 114, 242, 10609, 114, 114, 59, 25006, 97, 114, 59, 27378, 384, 59, 115, 118, 3981, 10908, 3980, 256, 59, 100, 10913, 10914, 25340, 59, 25338, 99, 121, 59, 17498, 896, 65, 69, 97, 100, 101, 115, 116, 10935, 10938, 10942, 10946, 10949, 10998, 11001, 114, 242, 10598, 59, 49152, 8806, 824, 114, 114, 59, 24986, 114, 59, 24613, 512, 59, 102, 113, 115, 3131, 10958, 10979, 10991, 116, 256, 97, 114, 10964, 10969, 114, 114, 111, 247, 10945, 105, 103, 104, 116, 97, 114, 114, 111, 247, 10896, 384, 59, 113, 115, 3131, 10938, 10986, 108, 97, 110, 244, 3157, 256, 59, 115, 3157, 10996, 187, 3126, 105, 237, 3165, 256, 59, 114, 3125, 11006, 105, 256, 59, 101, 3098, 3109, 105, 228, 3472, 256, 112, 116, 11020, 11025, 102, 59, 49152, 55349, 56671, 33152, 172, 59, 105, 110, 11033, 11034, 11062, 16556, 110, 512, 59, 69, 100, 118, 2953, 11044, 11048, 11054, 59, 49152, 8953, 824, 111, 116, 59, 49152, 8949, 824, 481, 2953, 11059, 11061, 59, 25335, 59, 25334, 105, 256, 59, 118, 3256, 11068, 481, 3256, 11073, 11075, 59, 25342, 59, 25341, 384, 97, 111, 114, 11083, 11107, 11113, 114, 512, 59, 97, 115, 116, 2939, 11093, 11098, 11103, 108, 108, 101, 236, 2939, 108, 59, 49152, 11005, 8421, 59, 49152, 8706, 824, 108, 105, 110, 116, 59, 27156, 384, 59, 99, 101, 3218, 11120, 11123, 117, 229, 3237, 256, 59, 99, 3224, 11128, 256, 59, 101, 3218, 11133, 241, 3224, 512, 65, 97, 105, 116, 11144, 11147, 11165, 11175, 114, 242, 10632, 114, 114, 384, 59, 99, 119, 11156, 11157, 11161, 24987, 59, 49152, 10547, 824, 59, 49152, 8605, 824, 103, 104, 116, 97, 114, 114, 111, 119, 187, 11157, 114, 105, 256, 59, 101, 3275, 3286, 896, 99, 104, 105, 109, 112, 113, 117, 11197, 11213, 11225, 11012, 2936, 11236, 11247, 512, 59, 99, 101, 114, 3378, 11206, 3383, 11209, 117, 229, 3397, 59, 49152, 55349, 56515, 111, 114, 116, 621, 11013, 0, 0, 11222, 97, 114, 225, 11094, 109, 256, 59, 101, 3438, 11231, 256, 59, 113, 3444, 3443, 115, 117, 256, 98, 112, 11243, 11245, 229, 3320, 229, 3339, 384, 98, 99, 112, 11254, 11281, 11289, 512, 59, 69, 101, 115, 11263, 11264, 3362, 11268, 25220, 59, 49152, 10949, 824, 101, 116, 256, 59, 101, 3355, 11275, 113, 256, 59, 113, 3363, 11264, 99, 256, 59, 101, 3378, 11287, 241, 3384, 512, 59, 69, 101, 115, 11298, 11299, 3423, 11303, 25221, 59, 49152, 10950, 824, 101, 116, 256, 59, 101, 3416, 11310, 113, 256, 59, 113, 3424, 11299, 512, 103, 105, 108, 114, 11325, 11327, 11333, 11335, 236, 3031, 108, 100, 101, 32827, 241, 16625, 231, 3139, 105, 97, 110, 103, 108, 101, 256, 108, 114, 11346, 11356, 101, 102, 116, 256, 59, 101, 3098, 11354, 241, 3110, 105, 103, 104, 116, 256, 59, 101, 3275, 11365, 241, 3287, 256, 59, 109, 11372, 11373, 17341, 384, 59, 101, 115, 11380, 11381, 11385, 16419, 114, 111, 59, 24854, 112, 59, 24583, 1152, 68, 72, 97, 100, 103, 105, 108, 114, 115, 11407, 11412, 11417, 11422, 11427, 11440, 11446, 11475, 11491, 97, 115, 104, 59, 25261, 97, 114, 114, 59, 26884, 112, 59, 49152, 8781, 8402, 97, 115, 104, 59, 25260, 256, 101, 116, 11432, 11436, 59, 49152, 8805, 8402, 59, 49152, 62, 8402, 110, 102, 105, 110, 59, 27102, 384, 65, 101, 116, 11453, 11457, 11461, 114, 114, 59, 26882, 59, 49152, 8804, 8402, 256, 59, 114, 11466, 11469, 49152, 60, 8402, 105, 101, 59, 49152, 8884, 8402, 256, 65, 116, 11480, 11484, 114, 114, 59, 26883, 114, 105, 101, 59, 49152, 8885, 8402, 105, 109, 59, 49152, 8764, 8402, 384, 65, 97, 110, 11504, 11508, 11522, 114, 114, 59, 25046, 114, 256, 104, 114, 11514, 11517, 107, 59, 26915, 256, 59, 111, 5095, 5093, 101, 97, 114, 59, 26919, 4691, 6805, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11565, 0, 11576, 11592, 11616, 11621, 11634, 11652, 6919, 0, 0, 11661, 11691, 0, 11720, 11726, 0, 11740, 11801, 11819, 11838, 11843, 256, 99, 115, 11569, 6807, 117, 116, 101, 32827, 243, 16627, 256, 105, 121, 11580, 11589, 114, 256, 59, 99, 6814, 11586, 32827, 244, 16628, 59, 17470, 640, 97, 98, 105, 111, 115, 6816, 11602, 11607, 456, 11610, 108, 97, 99, 59, 16721, 118, 59, 27192, 111, 108, 100, 59, 27068, 108, 105, 103, 59, 16723, 256, 99, 114, 11625, 11629, 105, 114, 59, 27071, 59, 49152, 55349, 56620, 879, 11641, 0, 0, 11644, 0, 11650, 110, 59, 17115, 97, 118, 101, 32827, 242, 16626, 59, 27073, 256, 98, 109, 11656, 3572, 97, 114, 59, 27061, 512, 97, 99, 105, 116, 11669, 11672, 11685, 11688, 114, 242, 6784, 256, 105, 114, 11677, 11680, 114, 59, 27070, 111, 115, 115, 59, 27067, 110, 229, 3666, 59, 27072, 384, 97, 101, 105, 11697, 11701, 11705, 99, 114, 59, 16717, 103, 97, 59, 17353, 384, 99, 100, 110, 11712, 11717, 461, 114, 111, 110, 59, 17343, 59, 27062, 112, 102, 59, 49152, 55349, 56672, 384, 97, 101, 108, 11732, 11735, 466, 114, 59, 27063, 114, 112, 59, 27065, 896, 59, 97, 100, 105, 111, 115, 118, 11754, 11755, 11758, 11784, 11789, 11792, 11798, 25128, 114, 242, 6790, 512, 59, 101, 102, 109, 11767, 11768, 11778, 11781, 27229, 114, 256, 59, 111, 11774, 11775, 24884, 102, 187, 11775, 32827, 170, 16554, 32827, 186, 16570, 103, 111, 102, 59, 25270, 114, 59, 27222, 108, 111, 112, 101, 59, 27223, 59, 27227, 384, 99, 108, 111, 11807, 11809, 11815, 242, 11777, 97, 115, 104, 32827, 248, 16632, 108, 59, 25240, 105, 364, 11823, 11828, 100, 101, 32827, 245, 16629, 101, 115, 256, 59, 97, 475, 11834, 115, 59, 27190, 109, 108, 32827, 246, 16630, 98, 97, 114, 59, 25405, 2785, 11870, 0, 11901, 0, 11904, 11933, 0, 11938, 11961, 0, 0, 11979, 3740, 0, 12051, 0, 0, 12075, 12220, 0, 12232, 114, 512, 59, 97, 115, 116, 1027, 11879, 11890, 3717, 33024, 182, 59, 108, 11885, 11886, 16566, 108, 101, 236, 1027, 617, 11896, 0, 0, 11899, 109, 59, 27379, 59, 27389, 121, 59, 17471, 114, 640, 99, 105, 109, 112, 116, 11915, 11919, 11923, 6245, 11927, 110, 116, 59, 16421, 111, 100, 59, 16430, 105, 108, 59, 24624, 101, 110, 107, 59, 24625, 114, 59, 49152, 55349, 56621, 384, 105, 109, 111, 11944, 11952, 11956, 256, 59, 118, 11949, 11950, 17350, 59, 17365, 109, 97, 244, 2678, 110, 101, 59, 26126, 384, 59, 116, 118, 11967, 11968, 11976, 17344, 99, 104, 102, 111, 114, 107, 187, 8189, 59, 17366, 256, 97, 117, 11983, 11999, 110, 256, 99, 107, 11989, 11997, 107, 256, 59, 104, 8692, 11995, 59, 24846, 246, 8692, 115, 1152, 59, 97, 98, 99, 100, 101, 109, 115, 116, 12019, 12020, 6408, 12025, 12029, 12036, 12038, 12042, 12046, 16427, 99, 105, 114, 59, 27171, 105, 114, 59, 27170, 256, 111, 117, 7488, 12034, 59, 27173, 59, 27250, 110, 32955, 177, 3741, 105, 109, 59, 27174, 119, 111, 59, 27175, 384, 105, 112, 117, 12057, 12064, 12069, 110, 116, 105, 110, 116, 59, 27157, 102, 59, 49152, 55349, 56673, 110, 100, 32827, 163, 16547, 1280, 59, 69, 97, 99, 101, 105, 110, 111, 115, 117, 3784, 12095, 12097, 12100, 12103, 12161, 12169, 12178, 12158, 12214, 59, 27315, 112, 59, 27319, 117, 229, 3801, 256, 59, 99, 3790, 12108, 768, 59, 97, 99, 101, 110, 115, 3784, 12121, 12127, 12134, 12136, 12158, 112, 112, 114, 111, 248, 12099, 117, 114, 108, 121, 101, 241, 3801, 241, 3790, 384, 97, 101, 115, 12143, 12150, 12154, 112, 112, 114, 111, 120, 59, 27321, 113, 113, 59, 27317, 105, 109, 59, 25320, 105, 237, 3807, 109, 101, 256, 59, 115, 12168, 3758, 24626, 384, 69, 97, 115, 12152, 12176, 12154, 240, 12149, 384, 100, 102, 112, 3820, 12185, 12207, 384, 97, 108, 115, 12192, 12197, 12202, 108, 97, 114, 59, 25390, 105, 110, 101, 59, 25362, 117, 114, 102, 59, 25363, 256, 59, 116, 3835, 12212, 239, 3835, 114, 101, 108, 59, 25264, 256, 99, 105, 12224, 12229, 114, 59, 49152, 55349, 56517, 59, 17352, 110, 99, 115, 112, 59, 24584, 768, 102, 105, 111, 112, 115, 117, 12250, 8930, 12255, 12261, 12267, 12273, 114, 59, 49152, 55349, 56622, 112, 102, 59, 49152, 55349, 56674, 114, 105, 109, 101, 59, 24663, 99, 114, 59, 49152, 55349, 56518, 384, 97, 101, 111, 12280, 12297, 12307, 116, 256, 101, 105, 12286, 12293, 114, 110, 105, 111, 110, 243, 1712, 110, 116, 59, 27158, 115, 116, 256, 59, 101, 12304, 12305, 16447, 241, 7961, 244, 3860, 2688, 65, 66, 72, 97, 98, 99, 100, 101, 102, 104, 105, 108, 109, 110, 111, 112, 114, 115, 116, 117, 120, 12352, 12369, 12373, 12377, 12512, 12558, 12587, 12615, 12642, 12658, 12686, 12806, 12821, 12836, 12841, 12888, 12910, 12914, 12944, 12976, 12983, 384, 97, 114, 116, 12359, 12362, 12364, 114, 242, 4275, 242, 989, 97, 105, 108, 59, 26908, 97, 114, 242, 7269, 97, 114, 59, 26980, 896, 99, 100, 101, 110, 113, 114, 116, 12392, 12405, 12408, 12415, 12431, 12436, 12492, 256, 101, 117, 12397, 12401, 59, 49152, 8765, 817, 116, 101, 59, 16725, 105, 227, 4462, 109, 112, 116, 121, 118, 59, 27059, 103, 512, 59, 100, 101, 108, 4049, 12425, 12427, 12429, 59, 27026, 59, 27045, 229, 4049, 117, 111, 32827, 187, 16571, 114, 1408, 59, 97, 98, 99, 102, 104, 108, 112, 115, 116, 119, 4060, 12460, 12463, 12471, 12473, 12476, 12478, 12480, 12483, 12487, 12490, 112, 59, 26997, 256, 59, 102, 4064, 12468, 115, 59, 26912, 59, 26931, 115, 59, 26910, 235, 8797, 240, 10030, 108, 59, 26949, 105, 109, 59, 26996, 108, 59, 24995, 59, 24989, 256, 97, 105, 12497, 12501, 105, 108, 59, 26906, 111, 256, 59, 110, 12507, 12508, 25142, 97, 108, 243, 3870, 384, 97, 98, 114, 12519, 12522, 12526, 114, 242, 6117, 114, 107, 59, 26483, 256, 97, 107, 12531, 12541, 99, 256, 101, 107, 12537, 12539, 59, 16509, 59, 16477, 256, 101, 115, 12546, 12548, 59, 27020, 108, 256, 100, 117, 12554, 12556, 59, 27022, 59, 27024, 512, 97, 101, 117, 121, 12567, 12572, 12583, 12585, 114, 111, 110, 59, 16729, 256, 100, 105, 12577, 12581, 105, 108, 59, 16727, 236, 4082, 226, 12538, 59, 17472, 512, 99, 108, 113, 115, 12596, 12599, 12605, 12612, 97, 59, 26935, 100, 104, 97, 114, 59, 26985, 117, 111, 256, 59, 114, 526, 525, 104, 59, 25011, 384, 97, 99, 103, 12622, 12639, 3908, 108, 512, 59, 105, 112, 115, 3960, 12632, 12635, 4252, 110, 229, 4283, 97, 114, 244, 4009, 116, 59, 26029, 384, 105, 108, 114, 12649, 4131, 12654, 115, 104, 116, 59, 27005, 59, 49152, 55349, 56623, 256, 97, 111, 12663, 12678, 114, 256, 100, 117, 12669, 12671, 187, 1147, 256, 59, 108, 4241, 12676, 59, 26988, 256, 59, 118, 12683, 12684, 17345, 59, 17393, 384, 103, 110, 115, 12693, 12793, 12796, 104, 116, 768, 97, 104, 108, 114, 115, 116, 12708, 12720, 12738, 12760, 12772, 12782, 114, 114, 111, 119, 256, 59, 116, 4060, 12717, 97, 233, 12488, 97, 114, 112, 111, 111, 110, 256, 100, 117, 12731, 12735, 111, 119, 238, 12670, 112, 187, 4242, 101, 102, 116, 256, 97, 104, 12746, 12752, 114, 114, 111, 119, 243, 4074, 97, 114, 112, 111, 111, 110, 243, 1361, 105, 103, 104, 116, 97, 114, 114, 111, 119, 115, 59, 25033, 113, 117, 105, 103, 97, 114, 114, 111, 247, 12491, 104, 114, 101, 101, 116, 105, 109, 101, 115, 59, 25292, 103, 59, 17114, 105, 110, 103, 100, 111, 116, 115, 101, 241, 7986, 384, 97, 104, 109, 12813, 12816, 12819, 114, 242, 4074, 97, 242, 1361, 59, 24591, 111, 117, 115, 116, 256, 59, 97, 12830, 12831, 25521, 99, 104, 101, 187, 12831, 109, 105, 100, 59, 27374, 512, 97, 98, 112, 116, 12850, 12861, 12864, 12882, 256, 110, 114, 12855, 12858, 103, 59, 26605, 114, 59, 25086, 114, 235, 4099, 384, 97, 102, 108, 12871, 12874, 12878, 114, 59, 27014, 59, 49152, 55349, 56675, 117, 115, 59, 27182, 105, 109, 101, 115, 59, 27189, 256, 97, 112, 12893, 12903, 114, 256, 59, 103, 12899, 12900, 16425, 116, 59, 27028, 111, 108, 105, 110, 116, 59, 27154, 97, 114, 242, 12771, 512, 97, 99, 104, 113, 12923, 12928, 4284, 12933, 113, 117, 111, 59, 24634, 114, 59, 49152, 55349, 56519, 256, 98, 117, 12539, 12938, 111, 256, 59, 114, 532, 531, 384, 104, 105, 114, 12951, 12955, 12960, 114, 101, 229, 12792, 109, 101, 115, 59, 25290, 105, 512, 59, 101, 102, 108, 12970, 4185, 6177, 12971, 26041, 116, 114, 105, 59, 27086, 108, 117, 104, 97, 114, 59, 26984, 59, 24862, 3425, 13013, 13019, 13023, 13100, 13112, 13169, 0, 13178, 13220, 0, 0, 13292, 13296, 0, 13352, 13384, 13402, 13485, 13489, 13514, 13553, 0, 13846, 0, 0, 13875, 99, 117, 116, 101, 59, 16731, 113, 117, 239, 10170, 1280, 59, 69, 97, 99, 101, 105, 110, 112, 115, 121, 4589, 13043, 13045, 13055, 13058, 13067, 13071, 13087, 13094, 13097, 59, 27316, 496, 13050, 0, 13052, 59, 27320, 111, 110, 59, 16737, 117, 229, 4606, 256, 59, 100, 4595, 13063, 105, 108, 59, 16735, 114, 99, 59, 16733, 384, 69, 97, 115, 13078, 13080, 13083, 59, 27318, 112, 59, 27322, 105, 109, 59, 25321, 111, 108, 105, 110, 116, 59, 27155, 105, 237, 4612, 59, 17473, 111, 116, 384, 59, 98, 101, 13108, 7495, 13109, 25285, 59, 27238, 896, 65, 97, 99, 109, 115, 116, 120, 13126, 13130, 13143, 13147, 13150, 13155, 13165, 114, 114, 59, 25048, 114, 256, 104, 114, 13136, 13138, 235, 8744, 256, 59, 111, 2614, 2612, 116, 32827, 167, 16551, 105, 59, 16443, 119, 97, 114, 59, 26921, 109, 256, 105, 110, 13161, 240, 110, 117, 243, 241, 116, 59, 26422, 114, 256, 59, 111, 13174, 8277, 49152, 55349, 56624, 512, 97, 99, 111, 121, 13186, 13190, 13201, 13216, 114, 112, 59, 26223, 256, 104, 121, 13195, 13199, 99, 121, 59, 17481, 59, 17480, 114, 116, 621, 13209, 0, 0, 13212, 105, 228, 5220, 97, 114, 97, 236, 11887, 32827, 173, 16557, 256, 103, 109, 13224, 13236, 109, 97, 384, 59, 102, 118, 13233, 13234, 13234, 17347, 59, 17346, 1024, 59, 100, 101, 103, 108, 110, 112, 114, 4779, 13253, 13257, 13262, 13270, 13278, 13281, 13286, 111, 116, 59, 27242, 256, 59, 113, 4785, 4784, 256, 59, 69, 13267, 13268, 27294, 59, 27296, 256, 59, 69, 13275, 13276, 27293, 59, 27295, 101, 59, 25158, 108, 117, 115, 59, 27172, 97, 114, 114, 59, 26994, 97, 114, 242, 4413, 512, 97, 101, 105, 116, 13304, 13320, 13327, 13335, 256, 108, 115, 13309, 13316, 108, 115, 101, 116, 109, 233, 13162, 104, 112, 59, 27187, 112, 97, 114, 115, 108, 59, 27108, 256, 100, 108, 5219, 13332, 101, 59, 25379, 256, 59, 101, 13340, 13341, 27306, 256, 59, 115, 13346, 13347, 27308, 59, 49152, 10924, 65024, 384, 102, 108, 112, 13358, 13363, 13378, 116, 99, 121, 59, 17484, 256, 59, 98, 13368, 13369, 16431, 256, 59, 97, 13374, 13375, 27076, 114, 59, 25407, 102, 59, 49152, 55349, 56676, 97, 256, 100, 114, 13389, 1026, 101, 115, 256, 59, 117, 13396, 13397, 26208, 105, 116, 187, 13397, 384, 99, 115, 117, 13408, 13433, 13471, 256, 97, 117, 13413, 13423, 112, 256, 59, 115, 4488, 13419, 59, 49152, 8851, 65024, 112, 256, 59, 115, 4532, 13429, 59, 49152, 8852, 65024, 117, 256, 98, 112, 13439, 13455, 384, 59, 101, 115, 4503, 4508, 13446, 101, 116, 256, 59, 101, 4503, 13453, 241, 4509, 384, 59, 101, 115, 4520, 4525, 13462, 101, 116, 256, 59, 101, 4520, 13469, 241, 4526, 384, 59, 97, 102, 4475, 13478, 1456, 114, 357, 13483, 1457, 187, 4476, 97, 114, 242, 4424, 512, 99, 101, 109, 116, 13497, 13502, 13506, 13509, 114, 59, 49152, 55349, 56520, 116, 109, 238, 241, 105, 236, 13333, 97, 114, 230, 4542, 256, 97, 114, 13518, 13525, 114, 256, 59, 102, 13524, 6079, 26118, 256, 97, 110, 13530, 13549, 105, 103, 104, 116, 256, 101, 112, 13539, 13546, 112, 115, 105, 108, 111, 238, 7904, 104, 233, 11951, 115, 187, 10322, 640, 98, 99, 109, 110, 112, 13563, 13662, 4617, 13707, 13710, 1152, 59, 69, 100, 101, 109, 110, 112, 114, 115, 13582, 13583, 13585, 13589, 13598, 13603, 13612, 13617, 13622, 25218, 59, 27333, 111, 116, 59, 27325, 256, 59, 100, 4570, 13594, 111, 116, 59, 27331, 117, 108, 116, 59, 27329, 256, 69, 101, 13608, 13610, 59, 27339, 59, 25226, 108, 117, 115, 59, 27327, 97, 114, 114, 59, 27001, 384, 101, 105, 117, 13629, 13650, 13653, 116, 384, 59, 101, 110, 13582, 13637, 13643, 113, 256, 59, 113, 4570, 13583, 101, 113, 256, 59, 113, 13611, 13608, 109, 59, 27335, 256, 98, 112, 13658, 13660, 59, 27349, 59, 27347, 99, 768, 59, 97, 99, 101, 110, 115, 4589, 13676, 13682, 13689, 13691, 13094, 112, 112, 114, 111, 248, 13050, 117, 114, 108, 121, 101, 241, 4606, 241, 4595, 384, 97, 101, 115, 13698, 13704, 13083, 112, 112, 114, 111, 248, 13082, 113, 241, 13079, 103, 59, 26218, 1664, 49, 50, 51, 59, 69, 100, 101, 104, 108, 109, 110, 112, 115, 13737, 13740, 13743, 4636, 13746, 13748, 13760, 13769, 13781, 13786, 13791, 13800, 13805, 32827, 185, 16569, 32827, 178, 16562, 32827, 179, 16563, 59, 27334, 256, 111, 115, 13753, 13756, 116, 59, 27326, 117, 98, 59, 27352, 256, 59, 100, 4642, 13765, 111, 116, 59, 27332, 115, 256, 111, 117, 13775, 13778, 108, 59, 26569, 98, 59, 27351, 97, 114, 114, 59, 27003, 117, 108, 116, 59, 27330, 256, 69, 101, 13796, 13798, 59, 27340, 59, 25227, 108, 117, 115, 59, 27328, 384, 101, 105, 117, 13812, 13833, 13836, 116, 384, 59, 101, 110, 4636, 13820, 13826, 113, 256, 59, 113, 4642, 13746, 101, 113, 256, 59, 113, 13799, 13796, 109, 59, 27336, 256, 98, 112, 13841, 13843, 59, 27348, 59, 27350, 384, 65, 97, 110, 13852, 13856, 13869, 114, 114, 59, 25049, 114, 256, 104, 114, 13862, 13864, 235, 8750, 256, 59, 111, 2603, 2601, 119, 97, 114, 59, 26922, 108, 105, 103, 32827, 223, 16607, 3041, 13905, 13917, 13920, 4814, 13939, 13945, 0, 13950, 14018, 0, 0, 0, 0, 0, 14043, 14083, 0, 14089, 14188, 0, 0, 0, 14215, 626, 13910, 0, 0, 13915, 103, 101, 116, 59, 25366, 59, 17348, 114, 235, 3679, 384, 97, 101, 121, 13926, 13931, 13936, 114, 111, 110, 59, 16741, 100, 105, 108, 59, 16739, 59, 17474, 108, 114, 101, 99, 59, 25365, 114, 59, 49152, 55349, 56625, 512, 101, 105, 107, 111, 13958, 13981, 14005, 14012, 498, 13963, 0, 13969, 101, 256, 52, 102, 4740, 4737, 97, 384, 59, 115, 118, 13976, 13977, 13979, 17336, 121, 109, 59, 17361, 256, 99, 110, 13986, 14002, 107, 256, 97, 115, 13992, 13998, 112, 112, 114, 111, 248, 4801, 105, 109, 187, 4780, 115, 240, 4766, 256, 97, 115, 14010, 13998, 240, 4801, 114, 110, 32827, 254, 16638, 492, 799, 14022, 8935, 101, 115, 33152, 215, 59, 98, 100, 14031, 14032, 14040, 16599, 256, 59, 97, 6415, 14037, 114, 59, 27185, 59, 27184, 384, 101, 112, 115, 14049, 14051, 14080, 225, 10829, 512, 59, 98, 99, 102, 1158, 14060, 14064, 14068, 111, 116, 59, 25398, 105, 114, 59, 27377, 256, 59, 111, 14073, 14076, 49152, 55349, 56677, 114, 107, 59, 27354, 225, 13154, 114, 105, 109, 101, 59, 24628, 384, 97, 105, 112, 14095, 14098, 14180, 100, 229, 4680, 896, 97, 100, 101, 109, 112, 115, 116, 14113, 14157, 14144, 14161, 14167, 14172, 14175, 110, 103, 108, 101, 640, 59, 100, 108, 113, 114, 14128, 14129, 14134, 14144, 14146, 26037, 111, 119, 110, 187, 7611, 101, 102, 116, 256, 59, 101, 10240, 14142, 241, 2350, 59, 25180, 105, 103, 104, 116, 256, 59, 101, 12970, 14155, 241, 4186, 111, 116, 59, 26092, 105, 110, 117, 115, 59, 27194, 108, 117, 115, 59, 27193, 98, 59, 27085, 105, 109, 101, 59, 27195, 101, 122, 105, 117, 109, 59, 25570, 384, 99, 104, 116, 14194, 14205, 14209, 256, 114, 121, 14199, 14203, 59, 49152, 55349, 56521, 59, 17478, 99, 121, 59, 17499, 114, 111, 107, 59, 16743, 256, 105, 111, 14219, 14222, 120, 244, 6007, 104, 101, 97, 100, 256, 108, 114, 14231, 14240, 101, 102, 116, 97, 114, 114, 111, 247, 2127, 105, 103, 104, 116, 97, 114, 114, 111, 119, 187, 3933, 2304, 65, 72, 97, 98, 99, 100, 102, 103, 104, 108, 109, 111, 112, 114, 115, 116, 117, 119, 14288, 14291, 14295, 14308, 14320, 14332, 14350, 14364, 14371, 14388, 14417, 14429, 14443, 14505, 14540, 14546, 14570, 14582, 114, 242, 1005, 97, 114, 59, 26979, 256, 99, 114, 14300, 14306, 117, 116, 101, 32827, 250, 16634, 242, 4432, 114, 483, 14314, 0, 14317, 121, 59, 17502, 118, 101, 59, 16749, 256, 105, 121, 14325, 14330, 114, 99, 32827, 251, 16635, 59, 17475, 384, 97, 98, 104, 14339, 14342, 14347, 114, 242, 5037, 108, 97, 99, 59, 16753, 97, 242, 5059, 256, 105, 114, 14355, 14360, 115, 104, 116, 59, 27006, 59, 49152, 55349, 56626, 114, 97, 118, 101, 32827, 249, 16633, 353, 14375, 14385, 114, 256, 108, 114, 14380, 14382, 187, 2391, 187, 4227, 108, 107, 59, 25984, 256, 99, 116, 14393, 14413, 623, 14399, 0, 0, 14410, 114, 110, 256, 59, 101, 14405, 14406, 25372, 114, 187, 14406, 111, 112, 59, 25359, 114, 105, 59, 26104, 256, 97, 108, 14422, 14426, 99, 114, 59, 16747, 32955, 168, 841, 256, 103, 112, 14434, 14438, 111, 110, 59, 16755, 102, 59, 49152, 55349, 56678, 768, 97, 100, 104, 108, 115, 117, 4427, 14456, 14461, 4978, 14481, 14496, 111, 119, 110, 225, 5043, 97, 114, 112, 111, 111, 110, 256, 108, 114, 14472, 14476, 101, 102, 244, 14381, 105, 103, 104, 244, 14383, 105, 384, 59, 104, 108, 14489, 14490, 14492, 17349, 187, 5114, 111, 110, 187, 14490, 112, 97, 114, 114, 111, 119, 115, 59, 25032, 384, 99, 105, 116, 14512, 14532, 14536, 623, 14518, 0, 0, 14529, 114, 110, 256, 59, 101, 14524, 14525, 25373, 114, 187, 14525, 111, 112, 59, 25358, 110, 103, 59, 16751, 114, 105, 59, 26105, 99, 114, 59, 49152, 55349, 56522, 384, 100, 105, 114, 14553, 14557, 14562, 111, 116, 59, 25328, 108, 100, 101, 59, 16745, 105, 256, 59, 102, 14128, 14568, 187, 6163, 256, 97, 109, 14575, 14578, 114, 242, 14504, 108, 32827, 252, 16636, 97, 110, 103, 108, 101, 59, 27047, 1920, 65, 66, 68, 97, 99, 100, 101, 102, 108, 110, 111, 112, 114, 115, 122, 14620, 14623, 14633, 14637, 14773, 14776, 14781, 14815, 14820, 14824, 14835, 14841, 14845, 14849, 14880, 114, 242, 1015, 97, 114, 256, 59, 118, 14630, 14631, 27368, 59, 27369, 97, 115, 232, 993, 256, 110, 114, 14642, 14647, 103, 114, 116, 59, 27036, 896, 101, 107, 110, 112, 114, 115, 116, 13539, 14662, 14667, 14674, 14685, 14692, 14742, 97, 112, 112, 225, 9237, 111, 116, 104, 105, 110, 231, 7830, 384, 104, 105, 114, 13547, 11976, 14681, 111, 112, 244, 12213, 256, 59, 104, 5047, 14690, 239, 12685, 256, 105, 117, 14697, 14701, 103, 109, 225, 13235, 256, 98, 112, 14706, 14724, 115, 101, 116, 110, 101, 113, 256, 59, 113, 14717, 14720, 49152, 8842, 65024, 59, 49152, 10955, 65024, 115, 101, 116, 110, 101, 113, 256, 59, 113, 14735, 14738, 49152, 8843, 65024, 59, 49152, 10956, 65024, 256, 104, 114, 14747, 14751, 101, 116, 225, 13980, 105, 97, 110, 103, 108, 101, 256, 108, 114, 14762, 14767, 101, 102, 116, 187, 2341, 105, 103, 104, 116, 187, 4177, 121, 59, 17458, 97, 115, 104, 187, 4150, 384, 101, 108, 114, 14788, 14802, 14807, 384, 59, 98, 101, 11754, 14795, 14799, 97, 114, 59, 25275, 113, 59, 25178, 108, 105, 112, 59, 25326, 256, 98, 116, 14812, 5224, 97, 242, 5225, 114, 59, 49152, 55349, 56627, 116, 114, 233, 14766, 115, 117, 256, 98, 112, 14831, 14833, 187, 3356, 187, 3417, 112, 102, 59, 49152, 55349, 56679, 114, 111, 240, 3835, 116, 114, 233, 14772, 256, 99, 117, 14854, 14859, 114, 59, 49152, 55349, 56523, 256, 98, 112, 14864, 14872, 110, 256, 69, 101, 14720, 14870, 187, 14718, 110, 256, 69, 101, 14738, 14878, 187, 14736, 105, 103, 122, 97, 103, 59, 27034, 896, 99, 101, 102, 111, 112, 114, 115, 14902, 14907, 14934, 14939, 14932, 14945, 14954, 105, 114, 99, 59, 16757, 256, 100, 105, 14912, 14929, 256, 98, 103, 14917, 14921, 97, 114, 59, 27231, 101, 256, 59, 113, 5626, 14927, 59, 25177, 101, 114, 112, 59, 24856, 114, 59, 49152, 55349, 56628, 112, 102, 59, 49152, 55349, 56680, 256, 59, 101, 5241, 14950, 97, 116, 232, 5241, 99, 114, 59, 49152, 55349, 56524, 2787, 6030, 14983, 0, 14987, 0, 14992, 15003, 0, 0, 15005, 15016, 15019, 15023, 0, 0, 15043, 15054, 0, 15064, 6108, 6111, 116, 114, 233, 6097, 114, 59, 49152, 55349, 56629, 256, 65, 97, 14996, 14999, 114, 242, 963, 114, 242, 2550, 59, 17342, 256, 65, 97, 15009, 15012, 114, 242, 952, 114, 242, 2539, 97, 240, 10003, 105, 115, 59, 25339, 384, 100, 112, 116, 6052, 15029, 15038, 256, 102, 108, 15034, 6057, 59, 49152, 55349, 56681, 105, 109, 229, 6066, 256, 65, 97, 15047, 15050, 114, 242, 974, 114, 242, 2561, 256, 99, 113, 15058, 6072, 114, 59, 49152, 55349, 56525, 256, 112, 116, 6102, 15068, 114, 233, 6100, 1024, 97, 99, 101, 102, 105, 111, 115, 117, 15088, 15101, 15112, 15116, 15121, 15125, 15131, 15137, 99, 256, 117, 121, 15094, 15099, 116, 101, 32827, 253, 16637, 59, 17487, 256, 105, 121, 15106, 15110, 114, 99, 59, 16759, 59, 17483, 110, 32827, 165, 16549, 114, 59, 49152, 55349, 56630, 99, 121, 59, 17495, 112, 102, 59, 49152, 55349, 56682, 99, 114, 59, 49152, 55349, 56526, 256, 99, 109, 15142, 15145, 121, 59, 17486, 108, 32827, 255, 16639, 1280, 97, 99, 100, 101, 102, 104, 105, 111, 115, 119, 15170, 15176, 15188, 15192, 15204, 15209, 15213, 15220, 15226, 15232, 99, 117, 116, 101, 59, 16762, 256, 97, 121, 15181, 15186, 114, 111, 110, 59, 16766, 59, 17463, 111, 116, 59, 16764, 256, 101, 116, 15197, 15201, 116, 114, 230, 5471, 97, 59, 17334, 114, 59, 49152, 55349, 56631, 99, 121, 59, 17462, 103, 114, 97, 114, 114, 59, 25053, 112, 102, 59, 49152, 55349, 56683, 99, 114, 59, 49152, 55349, 56527, 256, 106, 110, 15237, 15239, 59, 24589, 106, 59, 24588]); - -// Generated using scripts/write-decode-map.ts -// prettier-ignore -var xmlDecodeTree = new Uint16Array([512, 97, 103, 108, 113, 9, 21, 24, 27, 621, 15, 0, 0, 18, 112, 59, 16422, 111, 115, 59, 16423, 116, 59, 16446, 116, 59, 16444, 117, 111, 116, 59, 16418]); - // Adapted from https://github.com/mathiasbynens/he/blob/36afe179392226cf1b6ccdb16ebbb7a5a844d93a/src/he.js#L106-L134 var _a; const decodeMap = new Map([ [0, 65533], + // C1 Unicode control character reference replacements [128, 8364], [130, 8218], [131, 402], @@ -104,75 +114,590 @@ const decodeMap = new Map([ [158, 382], [159, 376] ]); +/** + * Polyfill for `String.fromCodePoint`. It is used to create a string from a Unicode code point. + */ const fromCodePoint = - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, node/no-unsupported-features/es-builtins + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, n/no-unsupported-features/es-builtins (_a = String.fromCodePoint) !== null && _a !== void 0 ? _a - : function (codePoint) { + : (codePoint) => { let output = ""; - if (codePoint > 0xffff) { - codePoint -= 0x10000; - output += String.fromCharCode(((codePoint >>> 10) & 0x3ff) | 0xd800); - codePoint = 0xdc00 | (codePoint & 0x3ff); + if (codePoint > 65535) { + codePoint -= 65536; + output += String.fromCharCode(((codePoint >>> 10) & 1023) | 55296); + codePoint = 56320 | (codePoint & 1023); } output += String.fromCharCode(codePoint); return output; }; +/** + * Replace the given code point with a replacement character if it is a + * surrogate or is outside the valid range. Otherwise return the code + * point unchanged. + */ function replaceCodePoint(codePoint) { var _a; - if ((codePoint >= 0xd800 && codePoint <= 0xdfff) || codePoint > 0x10ffff) { - return 0xfffd; + if ((codePoint >= 55296 && codePoint <= 57343) || codePoint > 1114111) { + return 65533; } return (_a = decodeMap.get(codePoint)) !== null && _a !== void 0 ? _a : codePoint; } +/* + * Shared base64 decode helper for generated decode data. + * Assumes global atob is available. + */ +function decodeBase64(input) { + const binary = + // eslint-disable-next-line n/no-unsupported-features/node-builtins + typeof atob === "function" + ? // Browser (and Node >=16) + // eslint-disable-next-line n/no-unsupported-features/node-builtins + atob(input) + : // Older Node versions (<16) + // eslint-disable-next-line n/no-unsupported-features/node-builtins + typeof Buffer.from === "function" + ? // eslint-disable-next-line n/no-unsupported-features/node-builtins + Buffer.from(input, "base64").toString("binary") + : // eslint-disable-next-line unicorn/no-new-buffer, n/no-deprecated-api + new Buffer(input, "base64").toString("binary"); + const evenLength = binary.length & -2; // Round down to even length + const out = new Uint16Array(evenLength / 2); + for (let index = 0, outIndex = 0; index < evenLength; index += 2) { + const lo = binary.charCodeAt(index); + const hi = binary.charCodeAt(index + 1); + out[outIndex++] = lo | (hi << 8); + } + return out; +} + +// Generated using scripts/write-decode-map.ts +const htmlDecodeTree = /* #__PURE__ */ decodeBase64( + "QR08ALkAAgH6AYsDNQR2BO0EPgXZBQEGLAbdBxMISQrvCmQLfQurDKQNLw4fD4YPpA+6D/IPAAAAAAAAAAAAAAAAKhBMEY8TmxUWF2EYLBkxGuAa3RsJHDscWR8YIC8jSCSIJcMl6ie3Ku8rEC0CLjoupS7kLgAIRU1hYmNmZ2xtbm9wcnN0dVQAWgBeAGUAaQBzAHcAfgCBAIQAhwCSAJoAoACsALMAbABpAGcAO4DGAMZAUAA7gCYAJkBjAHUAdABlADuAwQDBQHIiZXZlAAJhAAFpeW0AcgByAGMAO4DCAMJAEGRyAADgNdgE3XIAYQB2AGUAO4DAAMBA8CFoYZFj4SFjcgBhZAAAoFMqAAFncIsAjgBvAG4ABGFmAADgNdg43fAlbHlGdW5jdGlvbgCgYSBpAG4AZwA7gMUAxUAAAWNzpACoAHIAAOA12Jzc6SFnbgCgVCJpAGwAZABlADuAwwDDQG0AbAA7gMQAxEAABGFjZWZvcnN1xQDYANoA7QDxAPYA+QD8AAABY3LJAM8AayNzbGFzaAAAoBYidgHTANUAAKDnKmUAZAAAoAYjeQARZIABY3J0AOAA5QDrAGEidXNlAACgNSLuI291bGxpcwCgLCFhAJJjcgAA4DXYBd1wAGYAAOA12Dnd5SF2ZdhiYwDyAOoAbSJwZXEAAKBOIgAHSE9hY2RlZmhpbG9yc3UXARoBHwE6AVIBVQFiAWQBZgGCAakB6QHtAfIBYwB5ACdkUABZADuAqQCpQIABY3B5ACUBKAE1AfUhdGUGYWmg0iJ0KGFsRGlmZmVyZW50aWFsRAAAoEUhbCJleXMAAKAtIQACYWVpb0EBRAFKAU0B8iFvbgxhZABpAGwAO4DHAMdAcgBjAAhhbiJpbnQAAKAwIm8AdAAKYQABZG5ZAV0BaSJsbGEAuGB0I2VyRG90ALdg8gA5AWkAp2NyImNsZQAAAkRNUFRwAXQBeQF9AW8AdAAAoJkiaSJudXMAAKCWIuwhdXMAoJUiaSJtZXMAAKCXIm8AAAFjc4cBlAFrKndpc2VDb250b3VySW50ZWdyYWwAAKAyImUjQ3VybHkAAAFEUZwBpAFvJXVibGVRdW90ZQAAoB0gdSJvdGUAAKAZIAACbG5wdbABtgHNAdgBbwBuAGWgNyIAoHQqgAFnaXQAvAHBAcUB8iJ1ZW50AKBhIm4AdAAAoC8i7yV1ckludGVncmFsAKAuIgABZnLRAdMBAKACIe8iZHVjdACgECJuLnRlckNsb2Nrd2lzZUNvbnRvdXJJbnRlZ3JhbAAAoDMi7yFzcwCgLypjAHIAAOA12J7ccABDoNMiYQBwAACgTSKABURKU1phY2VmaW9zAAsCEgIVAhgCGwIsAjQCOQI9AnMCfwNvoEUh9CJyYWhkAKARKWMAeQACZGMAeQAFZGMAeQAPZIABZ3JzACECJQIoAuchZXIAoCEgcgAAoKEhaAB2AACg5CoAAWF5MAIzAvIhb24OYRRkbAB0oAciYQCUY3IAAOA12AfdAAFhZkECawIAAWNtRQJnAvIjaXRpY2FsAAJBREdUUAJUAl8CYwJjInV0ZQC0YG8AdAFZAloC2WJiJGxlQWN1dGUA3WJyImF2ZQBgYGkibGRlANxi7yFuZACgxCJmJWVyZW50aWFsRAAAoEYhcAR9AgAAAAAAAIECjgIAABoDZgAA4DXYO91EoagAhQKJAm8AdAAAoNwgcSJ1YWwAAKBQIuIhbGUAA0NETFJVVpkCqAK1Au8C/wIRA28AbgB0AG8AdQByAEkAbgB0AGUAZwByAGEA7ADEAW8AdAKvAgAAAACwAqhgbiNBcnJvdwAAoNMhAAFlb7kC0AJmAHQAgAFBUlQAwQLGAs0CciJyb3cAAKDQIekkZ2h0QXJyb3cAoNQhZQDlACsCbgBnAAABTFLWAugC5SFmdAABQVLcAuECciJyb3cAAKD4J+kkZ2h0QXJyb3cAoPon6SRnaHRBcnJvdwCg+SdpImdodAAAAUFU9gL7AnIicm93AACg0iFlAGUAAKCoInAAQQIGAwAAAAALA3Iicm93AACg0SFvJHduQXJyb3cAAKDVIWUlcnRpY2FsQmFyAACgJSJuAAADQUJMUlRhJAM2AzoDWgNxA3oDciJyb3cAAKGTIUJVLAMwA2EAcgAAoBMpcCNBcnJvdwAAoPUhciJldmUAEWPlIWZ00gJDAwAASwMAAFIDaSVnaHRWZWN0b3IAAKBQKWUkZVZlY3RvcgAAoF4p5SJjdG9yQqC9IWEAcgAAoFYpaSJnaHQA1AFiAwAAaQNlJGVWZWN0b3IAAKBfKeUiY3RvckKgwSFhAHIAAKBXKWUAZQBBoKQiciJyb3cAAKCnIXIAcgBvAPcAtAIAAWN0gwOHA3IA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YwAAoN8i4SFycnCgtiEAoD0pgKIqImJjZG9zACsVMBU6FT4VQRVyImNhcAAAoEgqAAFhdTQVNxVwAACgRipwAACgSipvAHQAAKCNInIAAKBFKgDgKiIA/gACYWxydksVURVuFXMVcgByAG2gtyEAoDwpeQCAAWV2dwBYFWUVaRVxAHACXxUAAAAAYxVyAGUA4wAXFXUA4wAZFWUAZQAAoM4iZSJkZ2UAAKDPImUAbgA7gKQApEBlI2Fycm93AAABbHJ7FX8V5SFmdACgtiFpImdodAAAoLchZQDkAG0VAAFjaYsVkRVvAG4AaQBuAPQAkwFuAHQAAKAxImwiY3R5AACgLSOACUFIYWJjZGVmaGlqbG9yc3R1d3oAuBW7Fb8V1RXgFegV+RUKFhUWHxZUFlcWZRbFFtsW7xb7FgUXChdyAPIAtAJhAHIAAKBlKQACZ2xyc8YVyhXOFdAV5yFlcgCgICDlIXRoAKA4IfIA9QxoAHagECAAoKMiawHZFd4VYSJyb3cAAKAPKWEA4wBfAgABYXnkFecV8iFvbg9hNGQAoUYhYW/tFfQVAAFnciEC8RVyAACgyiF0InNlcQAAoHcqgAFnbG0A/xUCFgUWO4CwALBAdABhALRjcCJ0eXYAAKCxKQABaXIOFhIW8yFodACgfykA4DXYId1hAHIAAAFschsWHRYAoMMhAKDCIYACYWVnc3YAKBauAjYWOhY+Fm0AAKHEIm9zLhY0Fm4AZABzoMQi9SFpdACgZiZhIm1tYQDdY2kAbgAAoPIiAKH3AGlvQxZRFmQAZQAAgfcAO29KFksW90BuI3RpbWVzAACgxyJuAPgAUBZjAHkAUmRjAG8CXhYAAAAAYhZyAG4AAKAeI28AcAAAoA0jgAJscHR1dwBuFnEWdRaSFp4W7CFhciRgZgAA4DXYVd0AotkCZW1wc30WhBaJFo0WcQBkoFAibwB0AACgUSJpIm51cwAAoDgi7CF1cwCgFCLxInVhcmUAoKEiYgBsAGUAYgBhAHIAdwBlAGQAZwDlANcAbgCAAWFkaAClFqoWtBZyAHIAbwD3APUMbwB3AG4AYQByAHIAbwB3APMA8xVhI3Jwb29uAAABbHK8FsAWZQBmAPQAHBZpAGcAaAD0AB4WYgHJFs8WawBhAHIAbwD3AJILbwLUFgAAAADYFnIAbgAAoB8jbwBwAACgDCOAAWNvdADhFukW7BYAAXJ55RboFgDgNdi53FVkbAAAoPYp8iFvaxFhAAFkcvMW9xZvAHQAAKDxImkA5qC/JVsSAAFhaP8WAhdyAPIANQNhAPIA1wvhIm5nbGUAoKYpAAFjaQ4XEBd5AF9k5yJyYXJyAKD/JwAJRGFjZGVmZ2xtbm9wcXJzdHV4MRc4F0YXWxcyBF4XaRd5F40XrBe0F78X2RcVGCEYLRg1GEAYAAFEbzUXgRZvAPQA+BUAAWNzPBdCF3UAdABlADuA6QDpQPQhZXIAoG4qAAJhaW95TRdQF1YXWhfyIW9uG2FyAGOgViI7gOoA6kDsIW9uAKBVIk1kbwB0ABdhAAFEcmIXZhdvAHQAAKBSIgDgNdgi3XKhmipuF3QXYQB2AGUAO4DoAOhAZKCWKm8AdAAAoJgqgKGZKmlscwCAF4UXhxfuInRlcnMAoOcjAKATIWSglSpvAHQAAKCXKoABYXBzAJMXlheiF2MAcgATYXQAeQBzogUinxcAAAAAoRdlAHQAAKAFInAAMaADIDMBqRerFwCgBCAAoAUgAAFnc7AXsRdLYXAAAKACIAABZ3C4F7sXbwBuABlhZgAA4DXYVt2AAWFscwDFF8sXzxdyAHOg1SJsAACg4yl1AHMAAKBxKmkAAKG1A2x21RfYF28AbgC1Y/VjAAJjc3V24BfoF/0XEBgAAWlv5BdWF3IAYwAAoFYiaQLuFwAAAADwF+0ADQThIW50AAFnbPUX+Rd0AHIAAKCWKuUhc3MAoJUqgAFhZWkAAxgGGAoYbABzAD1gcwB0AACgXyJ2AESgYSJEAACgeCrwImFyc2wAoOUpAAFEYRkYHRhvAHQAAKBTInIAcgAAoHEpgAFjZGkAJxgqGO0XcgAAoC8hbwD0AIwCAAFhaDEYMhi3YzuA8ADwQAABbXI5GD0YbAA7gOsA60BvAACgrCCAAWNpcABGGEgYSxhsACFgcwD0ACwEAAFlb08YVxhjAHQAYQB0AGkAbwDuABoEbgBlAG4AdABpAGEAbADlADME4Ql1GAAAgRgAAIMYiBgAAAAAoRilGAAAqhgAALsYvhjRGAAA1xgnGWwAbABpAG4AZwBkAG8AdABzAGUA8QBlF3kARGRtImFsZQAAoEAmgAFpbHIAjRiRGJ0Y7CFpZwCgA/tpApcYAAAAAJoYZwAAoAD7aQBnAACgBPsA4DXYI93sIWlnAKAB++whaWcA4GYAagCAAWFsdACvGLIYthh0AACgbSZpAGcAAKAC+24AcwAAoLElbwBmAJJh8AHCGAAAxhhmAADgNdhX3QABYWvJGMwYbADsAGsEdqDUIgCg2SphI3J0aW50AACgDSoAAWFv2hgiGQABY3PeGB8ZsQPnGP0YBRkSGRUZAAAdGbID7xjyGPQY9xj5GAAA+xg7gL0AvUAAoFMhO4C8ALxAAKBVIQCgWSEAoFshswEBGQAAAxkAoFQhAKBWIbQCCxkOGQAAAAAQGTuAvgC+QACgVyEAoFwhNQAAoFghtgEZGQAAGxkAoFohAKBdITgAAKBeIWwAAKBEIHcAbgAAoCIjYwByAADgNdi73IAIRWFiY2RlZmdpamxub3JzdHYARhlKGVoZXhlmGWkZkhmWGZkZnRmgGa0ZxhnLGc8Z4BkjGmygZyIAoIwqgAFjbXAAUBlTGVgZ9SF0ZfVhbQBhAOSgswM6FgCghipyImV2ZQAfYQABaXliGWUZcgBjAB1hM2RvAHQAIWGAoWUibHFzAMYEcBl6GfGhZSLOBAAAdhlsAGEAbgD0AN8EgKF+KmNkbACBGYQZjBljAACgqSpvAHQAb6CAKmyggioAoIQqZeDbIgD+cwAAoJQqcgAA4DXYJN3noGsirATtIWVsAKA3IWMAeQBTZIChdyJFYWoApxmpGasZAKCSKgCgpSoAoKQqAAJFYWVztBm2Gb0ZwhkAoGkicABwoIoq8iFveACgiipxoIgq8aCIKrUZaQBtAACg5yJwAGYAAOA12FjdYQB2AOUAYwIAAWNp0xnWGXIAAKAKIW0AAKFzImVs3BneGQCgjioAoJAqAIM+ADtjZGxxco0E6xn0GfgZ/BkBGgABY2nvGfEZAKCnKnIAAKB6Km8AdAAAoNci0CFhcgCglSl1ImVzdAAAoHwqgAJhZGVscwAKGvQZFhrVBCAa8AEPGgAAFBpwAHIAbwD4AFkZcgAAoHgpcQAAAWxxxAQbGmwAZQBzAPMASRlpAO0A5AQAAWVuJxouGnIjdG5lcXEAAOBpIgD+xQAsGgAFQWFiY2Vma29zeUAaQxpmGmoabRqDGocalhrCGtMacgDyAMwCAAJpbG1yShpOGlAaVBpyAHMA8ABxD2YAvWBpAGwA9AASBQABZHJYGlsaYwB5AEpkAKGUIWN3YBpkGmkAcgAAoEgpAKCtIWEAcgAAoA8h6SFyYyVhgAFhbHIAcxp7Gn8a8iF0c3WgZSZpAHQAAKBlJuwhaXAAoCYg4yFvbgCguSJyAADgNdgl3XMAAAFld4wakRphInJvdwAAoCUpYSJyb3cAAKAmKYACYW1vcHIAnxqjGqcauhq+GnIAcgAAoP8h9CFodACgOyJrAAABbHKsGrMaZSRmdGFycm93AACgqSHpJGdodGFycm93AKCqIWYAAOA12Fnd4iFhcgCgFSCAAWNsdADIGswa0BpyAADgNdi93GEAcwDoAGka8iFvaydhAAFicNca2xr1IWxsAKBDIOghZW4AoBAg4Qr2GgAA/RoAAAgbExsaGwAAIRs7GwAAAAA+G2IbmRuVG6sbAACyG80b0htjAHUAdABlADuA7QDtQAChYyBpeQEbBhtyAGMAO4DuAO5AOGQAAWN4CxsNG3kANWRjAGwAO4ChAKFAAAFmcssCFhsA4DXYJt1yAGEAdgBlADuA7ADsQIChSCFpbm8AJxsyGzYbAAFpbisbLxtuAHQAAKAMKnQAAKAtIuYhaW4AoNwpdABhAACgKSHsIWlnM2GAAWFvcABDG1sbXhuAAWNndABJG0sbWRtyACthgAFlbHAAcQVRG1UbaQBuAOUAyAVhAHIA9AByBWgAMWFmAACgtyJlAGQAtWEAoggiY2ZvdGkbbRt1G3kb4SFyZQCgBSFpAG4AdKAeImkAZQAAoN0pZABvAPQAWxsAoisiY2VscIEbhRuPG5QbYQBsAACguiIAAWdyiRuNG2UAcgDzACMQ4wCCG2EicmhrAACgFyryIW9kAKA8KgACY2dwdJ8boRukG6gbeQBRZG8AbgAvYWYAAOA12FrdYQC5Y3UAZQBzAHQAO4C/AL9AAAFjabUbuRtyAADgNdi+3G4AAKIIIkVkc3bCG8QbyBvQAwCg+SJvAHQAAKD1Inag9CIAoPMiaaBiIOwhZGUpYesB1hsAANkbYwB5AFZkbAA7gO8A70AAA2NmbW9zdeYb7hvyG/Ub+hsFHAABaXnqG+0bcgBjADVhOWRyAADgNdgn3eEhdGg3YnAAZgAA4DXYW93jAf8bAAADHHIAAOA12L/c8iFjeVhk6yFjeVRkAARhY2ZnaGpvcxUcGhwiHCYcKhwtHDAcNRzwIXBhdqC6A/BjAAFleR4cIRzkIWls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ZmdobG1vcHJzdHV3CiwNLBEsHSwnLDEsQCxLLFIsYix6LIQsjyzLLOgs7Sz/LAotcgDyAAkDYQByAACgYykAAWNyFSwbLHUAdABlADuA+gD6QPIACQ1yAOMBIywAACUseQBeZHYAZQBtYQABaXkrLDAscgBjADuA+wD7QENkgAFhYmgANyw6LD0scgDyANEO7CFhY3FhYQDyAOAOAAFpckQsSCzzIWh0AKB+KQDgNdgy3XIAYQB2AGUAO4D5APlAYQFWLF8scgAAAWxyWixcLACgvyEAoL4hbABrAACggCUAAWN0Zix2LG8CbCwAAAAAcyxyAG4AZaAcI3IAAKAcI28AcAAAoA8jcgBpAACg+CUAAWFsfiyBLGMAcgBrYTuAqACoQAABZ3CILIssbwBuAHNhZgAA4DXYZt0AA2FkaGxzdZksniynLLgsuyzFLHIAcgBvAPcACQ1vAHcAbgBhAHIAcgBvAPcA2A5hI3Jwb29uAAABbHKvLLMsZQBmAPQAWyxpAGcAaAD0AF0sdQDzAKYOaQAAocUDaGzBLMIs0mNvAG4AxWPwI2Fycm93cwCgyCGAAWNpdADRLOEs5CxvAtcsAAAAAN4scgBuAGWgHSNyAACgHSNvAHAAAKAOI24AZwBvYXIAaQAAoPklYwByAADgNdjK3IABZGlyAPMs9yz6LG8AdAAAoPAi7CFkZWlhaQBmoLUlAKC0JQABYW0DLQYtcgDyAMosbAA7gPwA/EDhIm5nbGUAoKcpgAdBQkRhY2RlZmxub3Byc3oAJy0qLTAtNC2bLZ0toS2/LcMtxy3TLdgt3C3gLfwtcgDyABADYQByAHag6CoAoOkqYQBzAOgA/gIAAW5yOC08LechcnQAoJwpgANla25wcnN0AJkpSC1NLVQtXi1iLYItYQBwAHAA4QAaHG8AdABoAGkAbgDnAKEXgAFoaXIAoSmzJFotbwBwAPQAdCVooJUh7wD4JgABaXVmLWotZwBtAOEAuygAAWJwbi14LXMjZXRuZXEAceCKIgD+AODLKgD+cyNldG5lcQBx4IsiAP4A4MwqAP4AAWhyhi2KLWUAdADhABIraSNhbmdsZQAAAWxyki2WLeUhZnQAoLIiaSJnaHQAAKCzInkAMmThIXNoAKCiIoABZWxyAKcttC24LWKiKCKuLQAAAACyLWEAcgAAoLsicQAAoFoi7CFpcACg7iIAAWJ0vC1eD2EA8gBfD3IAAOA12DPddAByAOkAlS1zAHUAAAFicM0t0C0A4IIi0iAA4IMi0iBwAGYAAOA12GfdcgBvAPAAWQt0AHIA6QCaLQABY3XkLegtcgAA4DXYy9wAAWJw7C30LW4AAAFFZXUt8S0A4IoiAP5uAAABRWV/LfktAOCLIgD+6SJnemFnAKCaKYADY2Vmb3BycwANLhAuJS4pLiMuLi40LukhcmN1YQABZGkULiEuAAFiZxguHC5hAHIAAKBfKmUAcaAnIgCgWSLlIXJwAKAYIXIAAOA12DTdcABmAADgNdho3WWgQCJhAHQA6ABqD2MAcgAA4DXYzNzjCuQRUC4AAFQuAABYLmIuAAAAAGMubS5wLnQuAAAAAIguki4AAJouJxIqEnQAcgDpAB0ScgAA4DXYNd0AAUFhWy5eLnIA8gDnAnIA8gCTB75jAAFBYWYuaS5yAPIA4AJyAPIAjAdhAPAAeh5pAHMAAKD7IoABZHB0APgReS6DLgABZmx9LoAuAOA12GnddQDzAP8RaQBtAOUABBIAAUFhiy6OLnIA8gDuAnIA8gCaBwABY3GVLgoScgAA4DXYzdwAAXB0nS6hLmwAdQDzACUScgDpACASAARhY2VmaW9zdbEuvC7ELsguzC7PLtQu2S5jAAABdXm2LrsudABlADuA/QD9QE9kAAFpecAuwy5yAGMAd2FLZG4AO4ClAKVAcgAA4DXYNt1jAHkAV2RwAGYAAOA12GrdYwByAADgNdjO3AABY23dLt8ueQBOZGwAO4D/AP9AAAVhY2RlZmhpb3N38y73Lv8uAi8MLxAvEy8YLx0vIi9jInV0ZQB6YQABYXn7Lv4u8iFvbn5hN2RvAHQAfGEAAWV0Bi8KL3QAcgDmAB8QYQC2Y3IAAOA12DfdYwB5ADZk5yJyYXJyAKDdIXAAZgAA4DXYa91jAHIAAOA12M/cAAFqbiYvKC8AoA0gagAAoAwg" +); + +// Generated using scripts/write-decode-map.ts +const xmlDecodeTree = /* #__PURE__ */ decodeBase64( + "AAJhZ2xxBwARABMAFQBtAg0AAAAAAA8AcAAmYG8AcwAnYHQAPmB0ADxg9SFvdCJg" +); + +/** + * Bit flags & masks for the binary trie encoding used for entity decoding. + * + * Bit layout (16 bits total): + * 15..14 VALUE_LENGTH (+1 encoding; 0 => no value) + * 13 FLAG13. If valueLength>0: semicolon required flag (implicit ';'). + * If valueLength==0: compact run flag. + * 12..7 BRANCH_LENGTH Branch length (0 => single branch in 6..0 if jumpOffset==char) OR run length (when compact run) + * 6..0 JUMP_TABLE Jump offset (jump table) OR single-branch char code OR first run char + */ +var BinTrieFlags; +(function (BinTrieFlags) { + BinTrieFlags[(BinTrieFlags["VALUE_LENGTH"] = 49152)] = "VALUE_LENGTH"; + BinTrieFlags[(BinTrieFlags["FLAG13"] = 8192)] = "FLAG13"; + BinTrieFlags[(BinTrieFlags["BRANCH_LENGTH"] = 8064)] = "BRANCH_LENGTH"; + BinTrieFlags[(BinTrieFlags["JUMP_TABLE"] = 127)] = "JUMP_TABLE"; +})(BinTrieFlags || (BinTrieFlags = {})); + var CharCodes$1; (function (CharCodes) { CharCodes[(CharCodes["NUM"] = 35)] = "NUM"; CharCodes[(CharCodes["SEMI"] = 59)] = "SEMI"; + CharCodes[(CharCodes["EQUALS"] = 61)] = "EQUALS"; CharCodes[(CharCodes["ZERO"] = 48)] = "ZERO"; CharCodes[(CharCodes["NINE"] = 57)] = "NINE"; CharCodes[(CharCodes["LOWER_A"] = 97)] = "LOWER_A"; CharCodes[(CharCodes["LOWER_F"] = 102)] = "LOWER_F"; CharCodes[(CharCodes["LOWER_X"] = 120)] = "LOWER_X"; - /** Bit that needs to be set to convert an upper case ASCII character to lower case */ - CharCodes[(CharCodes["To_LOWER_BIT"] = 32)] = "To_LOWER_BIT"; + CharCodes[(CharCodes["LOWER_Z"] = 122)] = "LOWER_Z"; + CharCodes[(CharCodes["UPPER_A"] = 65)] = "UPPER_A"; + CharCodes[(CharCodes["UPPER_F"] = 70)] = "UPPER_F"; + CharCodes[(CharCodes["UPPER_Z"] = 90)] = "UPPER_Z"; })(CharCodes$1 || (CharCodes$1 = {})); -var BinTrieFlags; -(function (BinTrieFlags) { - BinTrieFlags[(BinTrieFlags["VALUE_LENGTH"] = 49152)] = "VALUE_LENGTH"; - BinTrieFlags[(BinTrieFlags["BRANCH_LENGTH"] = 16256)] = "BRANCH_LENGTH"; - BinTrieFlags[(BinTrieFlags["JUMP_TABLE"] = 127)] = "JUMP_TABLE"; -})(BinTrieFlags || (BinTrieFlags = {})); -function determineBranch(decodeTree, current, nodeIdx, char) { +/** Bit that needs to be set to convert an upper case ASCII character to lower case */ +const TO_LOWER_BIT = 32; +function isNumber(code) { + return code >= CharCodes$1.ZERO && code <= CharCodes$1.NINE; +} +function isHexadecimalCharacter(code) { + return ( + (code >= CharCodes$1.UPPER_A && code <= CharCodes$1.UPPER_F) || + (code >= CharCodes$1.LOWER_A && code <= CharCodes$1.LOWER_F) + ); +} +function isAsciiAlphaNumeric(code) { + return ( + (code >= CharCodes$1.UPPER_A && code <= CharCodes$1.UPPER_Z) || + (code >= CharCodes$1.LOWER_A && code <= CharCodes$1.LOWER_Z) || + isNumber(code) + ); +} +/** + * Checks if the given character is a valid end character for an entity in an attribute. + * + * Attribute values that aren't terminated properly aren't parsed, and shouldn't lead to a parser error. + * See the example in https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state + */ +function isEntityInAttributeInvalidEnd(code) { + return code === CharCodes$1.EQUALS || isAsciiAlphaNumeric(code); +} +var EntityDecoderState; +(function (EntityDecoderState) { + EntityDecoderState[(EntityDecoderState["EntityStart"] = 0)] = "EntityStart"; + EntityDecoderState[(EntityDecoderState["NumericStart"] = 1)] = "NumericStart"; + EntityDecoderState[(EntityDecoderState["NumericDecimal"] = 2)] = + "NumericDecimal"; + EntityDecoderState[(EntityDecoderState["NumericHex"] = 3)] = "NumericHex"; + EntityDecoderState[(EntityDecoderState["NamedEntity"] = 4)] = "NamedEntity"; +})(EntityDecoderState || (EntityDecoderState = {})); +var DecodingMode; +(function (DecodingMode) { + /** Entities in text nodes that can end with any character. */ + DecodingMode[(DecodingMode["Legacy"] = 0)] = "Legacy"; + /** Only allow entities terminated with a semicolon. */ + DecodingMode[(DecodingMode["Strict"] = 1)] = "Strict"; + /** Entities in attributes have limitations on ending characters. */ + DecodingMode[(DecodingMode["Attribute"] = 2)] = "Attribute"; +})(DecodingMode || (DecodingMode = {})); +/** + * Token decoder with support of writing partial entities. + */ +class EntityDecoder { + constructor( + /** The tree used to decode entities. */ + // biome-ignore lint/correctness/noUnusedPrivateClassMembers: False positive + decodeTree, + /** + * The function that is called when a codepoint is decoded. + * + * For multi-byte named entities, this will be called multiple times, + * with the second codepoint, and the same `consumed` value. + * + * @param codepoint The decoded codepoint. + * @param consumed The number of bytes consumed by the decoder. + */ + emitCodePoint, + /** An object that is used to produce errors. */ + errors + ) { + this.decodeTree = decodeTree; + this.emitCodePoint = emitCodePoint; + this.errors = errors; + /** The current state of the decoder. */ + this.state = EntityDecoderState.EntityStart; + /** Characters that were consumed while parsing an entity. */ + this.consumed = 1; + /** + * The result of the entity. + * + * Either the result index of a numeric entity, or the codepoint of a + * numeric entity. + */ + this.result = 0; + /** The current index in the decode tree. */ + this.treeIndex = 0; + /** The number of characters that were consumed in excess. */ + this.excess = 1; + /** The mode in which the decoder is operating. */ + this.decodeMode = DecodingMode.Strict; + /** The number of characters that have been consumed in the current run. */ + this.runConsumed = 0; + } + /** Resets the instance to make it reusable. */ + startEntity(decodeMode) { + this.decodeMode = decodeMode; + this.state = EntityDecoderState.EntityStart; + this.result = 0; + this.treeIndex = 0; + this.excess = 1; + this.consumed = 1; + this.runConsumed = 0; + } + /** + * Write an entity to the decoder. This can be called multiple times with partial entities. + * If the entity is incomplete, the decoder will return -1. + * + * Mirrors the implementation of `getDecoder`, but with the ability to stop decoding if the + * entity is incomplete, and resume when the next string is written. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The offset at which the entity begins. Should be 0 if this is not the first call. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + write(input, offset) { + switch (this.state) { + case EntityDecoderState.EntityStart: { + if (input.charCodeAt(offset) === CharCodes$1.NUM) { + this.state = EntityDecoderState.NumericStart; + this.consumed += 1; + return this.stateNumericStart(input, offset + 1); + } + this.state = EntityDecoderState.NamedEntity; + return this.stateNamedEntity(input, offset); + } + case EntityDecoderState.NumericStart: { + return this.stateNumericStart(input, offset); + } + case EntityDecoderState.NumericDecimal: { + return this.stateNumericDecimal(input, offset); + } + case EntityDecoderState.NumericHex: { + return this.stateNumericHex(input, offset); + } + case EntityDecoderState.NamedEntity: { + return this.stateNamedEntity(input, offset); + } + } + } + /** + * Switches between the numeric decimal and hexadecimal states. + * + * Equivalent to the `Numeric character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericStart(input, offset) { + if (offset >= input.length) { + return -1; + } + if ((input.charCodeAt(offset) | TO_LOWER_BIT) === CharCodes$1.LOWER_X) { + this.state = EntityDecoderState.NumericHex; + this.consumed += 1; + return this.stateNumericHex(input, offset + 1); + } + this.state = EntityDecoderState.NumericDecimal; + return this.stateNumericDecimal(input, offset); + } + /** + * Parses a hexadecimal numeric entity. + * + * Equivalent to the `Hexademical character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericHex(input, offset) { + while (offset < input.length) { + const char = input.charCodeAt(offset); + if (isNumber(char) || isHexadecimalCharacter(char)) { + // Convert hex digit to value (0-15); 'a'/'A' -> 10. + const digit = + char <= CharCodes$1.NINE + ? char - CharCodes$1.ZERO + : (char | TO_LOWER_BIT) - CharCodes$1.LOWER_A + 10; + this.result = this.result * 16 + digit; + this.consumed++; + offset++; + } else { + return this.emitNumericEntity(char, 3); + } + } + return -1; // Incomplete entity + } + /** + * Parses a decimal numeric entity. + * + * Equivalent to the `Decimal character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericDecimal(input, offset) { + while (offset < input.length) { + const char = input.charCodeAt(offset); + if (isNumber(char)) { + this.result = this.result * 10 + (char - CharCodes$1.ZERO); + this.consumed++; + offset++; + } else { + return this.emitNumericEntity(char, 2); + } + } + return -1; // Incomplete entity + } + /** + * Validate and emit a numeric entity. + * + * Implements the logic from the `Hexademical character reference start + * state` and `Numeric character reference end state` in the HTML spec. + * + * @param lastCp The last code point of the entity. Used to see if the + * entity was terminated with a semicolon. + * @param expectedLength The minimum number of characters that should be + * consumed. Used to validate that at least one digit + * was consumed. + * @returns The number of characters that were consumed. + */ + emitNumericEntity(lastCp, expectedLength) { + var _a; + // Ensure we consumed at least one digit. + if (this.consumed <= expectedLength) { + (_a = this.errors) === null || _a === void 0 + ? void 0 + : _a.absenceOfDigitsInNumericCharacterReference(this.consumed); + return 0; + } + // Figure out if this is a legit end of the entity + if (lastCp === CharCodes$1.SEMI) { + this.consumed += 1; + } else if (this.decodeMode === DecodingMode.Strict) { + return 0; + } + this.emitCodePoint(replaceCodePoint(this.result), this.consumed); + if (this.errors) { + if (lastCp !== CharCodes$1.SEMI) { + this.errors.missingSemicolonAfterCharacterReference(); + } + this.errors.validateNumericCharacterReference(this.result); + } + return this.consumed; + } + /** + * Parses a named entity. + * + * Equivalent to the `Named character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNamedEntity(input, offset) { + const { decodeTree } = this; + let current = decodeTree[this.treeIndex]; + // The length is the number of bytes of the value, including the current byte. + let valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + while (offset < input.length) { + // Handle compact runs (possibly inline): valueLength == 0 and SEMI_REQUIRED bit set. + if (valueLength === 0 && (current & BinTrieFlags.FLAG13) !== 0) { + const runLength = + (current & BinTrieFlags.BRANCH_LENGTH) >> 7; /* 2..63 */ + // If we are starting a run, check the first char. + if (this.runConsumed === 0) { + const firstChar = current & BinTrieFlags.JUMP_TABLE; + if (input.charCodeAt(offset) !== firstChar) { + return this.result === 0 ? 0 : this.emitNotTerminatedNamedEntity(); + } + offset++; + this.excess++; + this.runConsumed++; + } + // Check remaining characters in the run. + while (this.runConsumed < runLength) { + if (offset >= input.length) { + return -1; + } + const charIndexInPacked = this.runConsumed - 1; + const packedWord = + decodeTree[this.treeIndex + 1 + (charIndexInPacked >> 1)]; + const expectedChar = + charIndexInPacked % 2 === 0 + ? packedWord & 0xff + : (packedWord >> 8) & 0xff; + if (input.charCodeAt(offset) !== expectedChar) { + this.runConsumed = 0; + return this.result === 0 ? 0 : this.emitNotTerminatedNamedEntity(); + } + offset++; + this.excess++; + this.runConsumed++; + } + this.runConsumed = 0; + this.treeIndex += 1 + (runLength >> 1); + current = decodeTree[this.treeIndex]; + valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + } + if (offset >= input.length) break; + const char = input.charCodeAt(offset); + /* + * Implicit semicolon handling for nodes that require a semicolon but + * don't have an explicit ';' branch stored in the trie. If we have + * a value on the current node, it requires a semicolon, and the + * current input character is a semicolon, emit the entity using the + * current node (without descending further). + */ + if ( + char === CharCodes$1.SEMI && + valueLength !== 0 && + (current & BinTrieFlags.FLAG13) !== 0 + ) { + return this.emitNamedEntityData( + this.treeIndex, + valueLength, + this.consumed + this.excess + ); + } + this.treeIndex = determineBranch( + decodeTree, + current, + this.treeIndex + Math.max(1, valueLength), + char + ); + if (this.treeIndex < 0) { + return this.result === 0 || + // If we are parsing an attribute + (this.decodeMode === DecodingMode.Attribute && + // We shouldn't have consumed any characters after the entity, + (valueLength === 0 || + // And there should be no invalid characters. + isEntityInAttributeInvalidEnd(char))) + ? 0 + : this.emitNotTerminatedNamedEntity(); + } + current = decodeTree[this.treeIndex]; + valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + // If the branch is a value, store it and continue + if (valueLength !== 0) { + // If the entity is terminated by a semicolon, we are done. + if (char === CharCodes$1.SEMI) { + return this.emitNamedEntityData( + this.treeIndex, + valueLength, + this.consumed + this.excess + ); + } + // If we encounter a non-terminated (legacy) entity while parsing strictly, then ignore it. + if ( + this.decodeMode !== DecodingMode.Strict && + (current & BinTrieFlags.FLAG13) === 0 + ) { + this.result = this.treeIndex; + this.consumed += this.excess; + this.excess = 0; + } + } + // Increment offset & excess for next iteration + offset++; + this.excess++; + } + return -1; + } + /** + * Emit a named entity that was not terminated with a semicolon. + * + * @returns The number of characters consumed. + */ + emitNotTerminatedNamedEntity() { + var _a; + const { result, decodeTree } = this; + const valueLength = (decodeTree[result] & BinTrieFlags.VALUE_LENGTH) >> 14; + this.emitNamedEntityData(result, valueLength, this.consumed); + (_a = this.errors) === null || _a === void 0 + ? void 0 + : _a.missingSemicolonAfterCharacterReference(); + return this.consumed; + } + /** + * Emit a named entity. + * + * @param result The index of the entity in the decode tree. + * @param valueLength The number of bytes in the entity. + * @param consumed The number of characters consumed. + * + * @returns The number of characters consumed. + */ + emitNamedEntityData(result, valueLength, consumed) { + const { decodeTree } = this; + this.emitCodePoint( + valueLength === 1 + ? decodeTree[result] & + ~(BinTrieFlags.VALUE_LENGTH | BinTrieFlags.FLAG13) + : decodeTree[result + 1], + consumed + ); + if (valueLength === 3) { + // For multi-byte values, we need to emit the second byte. + this.emitCodePoint(decodeTree[result + 2], consumed); + } + return consumed; + } + /** + * Signal to the parser that the end of the input was reached. + * + * Remaining data will be emitted and relevant errors will be produced. + * + * @returns The number of characters consumed. + */ + end() { + var _a; + switch (this.state) { + case EntityDecoderState.NamedEntity: { + // Emit a named entity if we have one. + return this.result !== 0 && + (this.decodeMode !== DecodingMode.Attribute || + this.result === this.treeIndex) + ? this.emitNotTerminatedNamedEntity() + : 0; + } + // Otherwise, emit a numeric entity if we have one. + case EntityDecoderState.NumericDecimal: { + return this.emitNumericEntity(0, 2); + } + case EntityDecoderState.NumericHex: { + return this.emitNumericEntity(0, 3); + } + case EntityDecoderState.NumericStart: { + (_a = this.errors) === null || _a === void 0 + ? void 0 + : _a.absenceOfDigitsInNumericCharacterReference(this.consumed); + return 0; + } + case EntityDecoderState.EntityStart: { + // Return 0 if we have no entity. + return 0; + } + } + } +} +/** + * Determines the branch of the current node that is taken given the current + * character. This function is used to traverse the trie. + * + * @param decodeTree The trie. + * @param current The current node. + * @param nodeIdx The index right after the current node and its value. + * @param char The current character. + * @returns The index of the next node, or -1 if no branch is taken. + */ +function determineBranch(decodeTree, current, nodeIndex, char) { const branchCount = (current & BinTrieFlags.BRANCH_LENGTH) >> 7; const jumpOffset = current & BinTrieFlags.JUMP_TABLE; // Case 1: Single branch encoded in jump offset if (branchCount === 0) { - return jumpOffset !== 0 && char === jumpOffset ? nodeIdx : -1; + return jumpOffset !== 0 && char === jumpOffset ? nodeIndex : -1; } // Case 2: Multiple branches encoded in jump table if (jumpOffset) { const value = char - jumpOffset; - return value < 0 || value > branchCount + return value < 0 || value >= branchCount ? -1 - : decodeTree[nodeIdx + value] - 1; + : decodeTree[nodeIndex + value] - 1; } - // Case 3: Multiple branches encoded in dictionary - // Binary search for the character. - let lo = nodeIdx; - let hi = lo + branchCount - 1; + // Case 3: Multiple branches encoded in packed dictionary (two keys per uint16) + const packedKeySlots = (branchCount + 1) >> 1; + /* + * Treat packed keys as a virtual sorted array of length `branchCount`. + * Key(i) = low byte for even i, high byte for odd i in slot i>>1. + */ + let lo = 0; + let hi = branchCount - 1; while (lo <= hi) { const mid = (lo + hi) >>> 1; - const midVal = decodeTree[mid]; - if (midVal < char) { + const slot = mid >> 1; + const packed = decodeTree[nodeIndex + slot]; + const midKey = (packed >> ((mid & 1) * 8)) & 0xff; + if (midKey < char) { lo = mid + 1; - } else if (midVal > char) { + } else if (midKey > char) { hi = mid - 1; } else { - return decodeTree[mid + branchCount]; + return decodeTree[nodeIndex + packedKeySlots + mid]; } } return -1; @@ -186,7 +711,7 @@ var CharCodes; CharCodes[(CharCodes["CarriageReturn"] = 13)] = "CarriageReturn"; CharCodes[(CharCodes["Space"] = 32)] = "Space"; CharCodes[(CharCodes["ExclamationMark"] = 33)] = "ExclamationMark"; - CharCodes[(CharCodes["Num"] = 35)] = "Num"; + CharCodes[(CharCodes["Number"] = 35)] = "Number"; CharCodes[(CharCodes["Amp"] = 38)] = "Amp"; CharCodes[(CharCodes["SingleQuote"] = 39)] = "SingleQuote"; CharCodes[(CharCodes["DoubleQuote"] = 34)] = "DoubleQuote"; @@ -238,13 +763,10 @@ var State; State[(State["InCommentLike"] = 21)] = "InCommentLike"; // Special tags State[(State["BeforeSpecialS"] = 22)] = "BeforeSpecialS"; - State[(State["SpecialStartSequence"] = 23)] = "SpecialStartSequence"; - State[(State["InSpecialTag"] = 24)] = "InSpecialTag"; - State[(State["BeforeEntity"] = 25)] = "BeforeEntity"; - State[(State["BeforeNumericEntity"] = 26)] = "BeforeNumericEntity"; - State[(State["InNamedEntity"] = 27)] = "InNamedEntity"; - State[(State["InNumericEntity"] = 28)] = "InNumericEntity"; - State[(State["InHexEntity"] = 29)] = "InHexEntity"; + State[(State["BeforeSpecialT"] = 23)] = "BeforeSpecialT"; + State[(State["SpecialStartSequence"] = 24)] = "SpecialStartSequence"; + State[(State["InSpecialTag"] = 25)] = "InSpecialTag"; + State[(State["InEntity"] = 26)] = "InEntity"; })(State || (State = {})); function isWhitespace$1(c) { return ( @@ -258,21 +780,12 @@ function isWhitespace$1(c) { function isEndOfTagSection(c) { return c === CharCodes.Slash || c === CharCodes.Gt || isWhitespace$1(c); } -function isNumber(c) { - return c >= CharCodes.Zero && c <= CharCodes.Nine; -} function isASCIIAlpha(c) { return ( (c >= CharCodes.LowerA && c <= CharCodes.LowerZ) || (c >= CharCodes.UpperA && c <= CharCodes.UpperZ) ); } -function isHexDigit(c) { - return ( - (c >= CharCodes.UpperA && c <= CharCodes.UpperF) || - (c >= CharCodes.LowerA && c <= CharCodes.LowerF) - ); -} var QuoteType; (function (QuoteType) { QuoteType[(QuoteType["NoValue"] = 0)] = "NoValue"; @@ -287,12 +800,16 @@ var QuoteType; * sequences with an increased offset. */ const Sequences = { - Cdata: new Uint8Array([0x43, 0x44, 0x41, 0x54, 0x41, 0x5b]), - CdataEnd: new Uint8Array([0x5d, 0x5d, 0x3e]), - CommentEnd: new Uint8Array([0x2d, 0x2d, 0x3e]), - ScriptEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74]), - StyleEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65]), - TitleEnd: new Uint8Array([0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65]) // ` + CommentEnd: new Uint8Array([0x2d, 0x2d, 0x3e]), // `-->` + ScriptEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74]), // ` this.emitCodePoint(cp, consumed) + ); } reset() { this.state = State.Text; @@ -350,18 +868,6 @@ class Tokenizer { this.parse(); } } - /** - * The current index within all of the written data. - */ - getIndex() { - return this.index; - } - /** - * The start of the current section. - */ - getSectionStart() { - return this.sectionStart; - } stateText(c) { if ( c === CharCodes.Lt || @@ -373,7 +879,7 @@ class Tokenizer { this.state = State.BeforeTagName; this.sectionStart = this.index; } else if (this.decodeEntities && c === CharCodes.Amp) { - this.state = State.BeforeEntity; + this.startEntity(); } } stateSpecialStartSequence(c) { @@ -418,7 +924,7 @@ class Tokenizer { if (this.currentSequence === Sequences.TitleEnd) { // We have to parse entities in tags. if (this.decodeEntities && c === CharCodes.Amp) { - this.state = State.BeforeEntity; + this.startEntity(); } } else if (this.fastForwardTo(CharCodes.Lt)) { // Outside of <title> tags, we can fast-forward. @@ -519,13 +1025,17 @@ class Tokenizer { } else if (this.isTagStartChar(c)) { const lower = c | 0x20; this.sectionStart = this.index; - if (!this.xmlMode && lower === Sequences.TitleEnd[2]) { - this.startSpecial(Sequences.TitleEnd, 3); + if (this.xmlMode) { + this.state = State.InTagName; + } else if (lower === Sequences.ScriptEnd[2]) { + this.state = State.BeforeSpecialS; + } else if ( + lower === Sequences.TitleEnd[2] || + lower === Sequences.XmpEnd[2] + ) { + this.state = State.BeforeSpecialT; } else { - this.state = - !this.xmlMode && lower === Sequences.ScriptEnd[2] - ? State.BeforeSpecialS - : State.InTagName; + this.state = State.InTagName; } } else if (c === CharCodes.Slash) { this.state = State.BeforeClosingTagName; @@ -577,7 +1087,6 @@ class Tokenizer { } else { this.state = State.Text; } - this.baseState = this.state; this.sectionStart = this.index + 1; } else if (c === CharCodes.Slash) { this.state = State.InSelfClosingTag; @@ -590,7 +1099,6 @@ class Tokenizer { if (c === CharCodes.Gt) { this.cbs.onselfclosingtag(this.index); this.state = State.Text; - this.baseState = State.Text; this.sectionStart = this.index + 1; this.isSpecial = false; // Reset special state, in case of self-closing special tags } else if (!isWhitespace$1(c)) { @@ -601,7 +1109,7 @@ class Tokenizer { stateInAttributeName(c) { if (c === CharCodes.Eq || isEndOfTagSection(c)) { this.cbs.onattribname(this.sectionStart, this.index); - this.sectionStart = -1; + this.sectionStart = this.index; this.state = State.AfterAttributeName; this.stateAfterAttributeName(c); } @@ -610,11 +1118,12 @@ class Tokenizer { if (c === CharCodes.Eq) { this.state = State.BeforeAttributeValue; } else if (c === CharCodes.Slash || c === CharCodes.Gt) { - this.cbs.onattribend(QuoteType.NoValue, this.index); + this.cbs.onattribend(QuoteType.NoValue, this.sectionStart); + this.sectionStart = -1; this.state = State.BeforeAttributeName; this.stateBeforeAttributeName(c); } else if (!isWhitespace$1(c)) { - this.cbs.onattribend(QuoteType.NoValue, this.index); + this.cbs.onattribend(QuoteType.NoValue, this.sectionStart); this.state = State.InAttributeName; this.sectionStart = this.index; } @@ -638,12 +1147,11 @@ class Tokenizer { this.sectionStart = -1; this.cbs.onattribend( quote === CharCodes.DoubleQuote ? QuoteType.Double : QuoteType.Single, - this.index + this.index + 1 ); this.state = State.BeforeAttributeName; } else if (this.decodeEntities && c === CharCodes.Amp) { - this.baseState = this.state; - this.state = State.BeforeEntity; + this.startEntity(); } } stateInAttributeValueDoubleQuotes(c) { @@ -660,8 +1168,7 @@ class Tokenizer { this.state = State.BeforeAttributeName; this.stateBeforeAttributeName(c); } else if (this.decodeEntities && c === CharCodes.Amp) { - this.baseState = this.state; - this.state = State.BeforeEntity; + this.startEntity(); } } stateBeforeDeclaration(c) { @@ -716,144 +1223,61 @@ class Tokenizer { this.stateInTagName(c); // Consume the token again } } - stateBeforeEntity(c) { - // Start excess with 1 to include the '&' - this.entityExcess = 1; - this.entityResult = 0; - if (c === CharCodes.Num) { - this.state = State.BeforeNumericEntity; - } else if (c === CharCodes.Amp); - else { - this.trieIndex = 0; - this.trieCurrent = this.entityTrie[0]; - this.state = State.InNamedEntity; - this.stateInNamedEntity(c); - } - } - stateInNamedEntity(c) { - this.entityExcess += 1; - this.trieIndex = determineBranch( - this.entityTrie, - this.trieCurrent, - this.trieIndex + 1, - c - ); - if (this.trieIndex < 0) { - this.emitNamedEntity(); - this.index--; - return; - } - this.trieCurrent = this.entityTrie[this.trieIndex]; - const masked = this.trieCurrent & BinTrieFlags.VALUE_LENGTH; - // If the branch is a value, store it and continue - if (masked) { - // The mask is the number of bytes of the value, including the current byte. - const valueLength = (masked >> 14) - 1; - // If we have a legacy entity while parsing strictly, just skip the number of bytes - if (!this.allowLegacyEntity() && c !== CharCodes.Semi) { - this.trieIndex += valueLength; - } else { - // Add 1 as we have already incremented the excess - const entityStart = this.index - this.entityExcess + 1; - if (entityStart > this.sectionStart) { - this.emitPartial(this.sectionStart, entityStart); - } - // If this is a surrogate pair, consume the next two bytes - this.entityResult = this.trieIndex; - this.trieIndex += valueLength; - this.entityExcess = 0; - this.sectionStart = this.index + 1; - if (valueLength === 0) { - this.emitNamedEntity(); - } - } - } - } - emitNamedEntity() { - this.state = this.baseState; - if (this.entityResult === 0) { - return; - } - const valueLength = - (this.entityTrie[this.entityResult] & BinTrieFlags.VALUE_LENGTH) >> 14; - switch (valueLength) { - case 1: - this.emitCodePoint( - this.entityTrie[this.entityResult] & ~BinTrieFlags.VALUE_LENGTH - ); + stateBeforeSpecialT(c) { + const lower = c | 0x20; + switch (lower) { + case Sequences.TitleEnd[3]: { + this.startSpecial(Sequences.TitleEnd, 4); break; - case 2: - this.emitCodePoint(this.entityTrie[this.entityResult + 1]); + } + case Sequences.TextareaEnd[3]: { + this.startSpecial(Sequences.TextareaEnd, 4); break; - case 3: { - this.emitCodePoint(this.entityTrie[this.entityResult + 1]); - this.emitCodePoint(this.entityTrie[this.entityResult + 2]); + } + case Sequences.XmpEnd[3]: { + this.startSpecial(Sequences.XmpEnd, 4); + break; + } + default: { + this.state = State.InTagName; + this.stateInTagName(c); // Consume the token again } } } - stateBeforeNumericEntity(c) { - if ((c | 0x20) === CharCodes.LowerX) { - this.entityExcess++; - this.state = State.InHexEntity; - } else { - this.state = State.InNumericEntity; - this.stateInNumericEntity(c); - } - } - emitNumericEntity(strict) { - const entityStart = this.index - this.entityExcess - 1; - const numberStart = - entityStart + 2 + Number(this.state === State.InHexEntity); - if (numberStart !== this.index) { - // Emit leading data if any - if (entityStart > this.sectionStart) { - this.emitPartial(this.sectionStart, entityStart); - } - this.sectionStart = this.index + Number(strict); - this.emitCodePoint(replaceCodePoint(this.entityResult)); - } - this.state = this.baseState; - } - stateInNumericEntity(c) { - if (c === CharCodes.Semi) { - this.emitNumericEntity(true); - } else if (isNumber(c)) { - this.entityResult = this.entityResult * 10 + (c - CharCodes.Zero); - this.entityExcess++; - } else { - if (this.allowLegacyEntity()) { - this.emitNumericEntity(false); - } else { - this.state = this.baseState; - } - this.index--; - } - } - stateInHexEntity(c) { - if (c === CharCodes.Semi) { - this.emitNumericEntity(true); - } else if (isNumber(c)) { - this.entityResult = this.entityResult * 16 + (c - CharCodes.Zero); - this.entityExcess++; - } else if (isHexDigit(c)) { - this.entityResult = - this.entityResult * 16 + ((c | 0x20) - CharCodes.LowerA + 10); - this.entityExcess++; - } else { - if (this.allowLegacyEntity()) { - this.emitNumericEntity(false); - } else { - this.state = this.baseState; - } - this.index--; - } - } - allowLegacyEntity() { - return ( - !this.xmlMode && - (this.baseState === State.Text || this.baseState === State.InSpecialTag) + startEntity() { + this.baseState = this.state; + this.state = State.InEntity; + this.entityStart = this.index; + this.entityDecoder.startEntity( + this.xmlMode + ? DecodingMode.Strict + : this.baseState === State.Text || this.baseState === State.InSpecialTag + ? DecodingMode.Legacy + : DecodingMode.Attribute ); } + stateInEntity() { + const indexInBuffer = this.index - this.offset; + const length = this.entityDecoder.write(this.buffer, indexInBuffer); + // If `length` is positive, we are done with the entity. + if (length >= 0) { + this.state = this.baseState; + if (length === 0) { + this.index -= 1; + } + } else { + if ( + indexInBuffer < this.buffer.length && + this.buffer.charCodeAt(indexInBuffer) === CharCodes.Amp + ) { + this.state = this.baseState; + this.index -= 1; + return; + } + // Mark buffer as consumed. + this.index = this.offset + this.buffer.length - 1; + } + } /** * Remove data that has already been consumed from the buffer. */ @@ -887,98 +1311,137 @@ class Tokenizer { parse() { while (this.shouldContinue()) { const c = this.buffer.charCodeAt(this.index - this.offset); - if (this.state === State.Text) { - this.stateText(c); - } else if (this.state === State.SpecialStartSequence) { - this.stateSpecialStartSequence(c); - } else if (this.state === State.InSpecialTag) { - this.stateInSpecialTag(c); - } else if (this.state === State.CDATASequence) { - this.stateCDATASequence(c); - } else if (this.state === State.InAttributeValueDq) { - this.stateInAttributeValueDoubleQuotes(c); - } else if (this.state === State.InAttributeName) { - this.stateInAttributeName(c); - } else if (this.state === State.InCommentLike) { - this.stateInCommentLike(c); - } else if (this.state === State.InSpecialComment) { - this.stateInSpecialComment(c); - } else if (this.state === State.BeforeAttributeName) { - this.stateBeforeAttributeName(c); - } else if (this.state === State.InTagName) { - this.stateInTagName(c); - } else if (this.state === State.InClosingTagName) { - this.stateInClosingTagName(c); - } else if (this.state === State.BeforeTagName) { - this.stateBeforeTagName(c); - } else if (this.state === State.AfterAttributeName) { - this.stateAfterAttributeName(c); - } else if (this.state === State.InAttributeValueSq) { - this.stateInAttributeValueSingleQuotes(c); - } else if (this.state === State.BeforeAttributeValue) { - this.stateBeforeAttributeValue(c); - } else if (this.state === State.BeforeClosingTagName) { - this.stateBeforeClosingTagName(c); - } else if (this.state === State.AfterClosingTagName) { - this.stateAfterClosingTagName(c); - } else if (this.state === State.BeforeSpecialS) { - this.stateBeforeSpecialS(c); - } else if (this.state === State.InAttributeValueNq) { - this.stateInAttributeValueNoQuotes(c); - } else if (this.state === State.InSelfClosingTag) { - this.stateInSelfClosingTag(c); - } else if (this.state === State.InDeclaration) { - this.stateInDeclaration(c); - } else if (this.state === State.BeforeDeclaration) { - this.stateBeforeDeclaration(c); - } else if (this.state === State.BeforeComment) { - this.stateBeforeComment(c); - } else if (this.state === State.InProcessingInstruction) { - this.stateInProcessingInstruction(c); - } else if (this.state === State.InNamedEntity) { - this.stateInNamedEntity(c); - } else if (this.state === State.BeforeEntity) { - this.stateBeforeEntity(c); - } else if (this.state === State.InHexEntity) { - this.stateInHexEntity(c); - } else if (this.state === State.InNumericEntity) { - this.stateInNumericEntity(c); - } else { - // `this._state === State.BeforeNumericEntity` - this.stateBeforeNumericEntity(c); + switch (this.state) { + case State.Text: { + this.stateText(c); + break; + } + case State.SpecialStartSequence: { + this.stateSpecialStartSequence(c); + break; + } + case State.InSpecialTag: { + this.stateInSpecialTag(c); + break; + } + case State.CDATASequence: { + this.stateCDATASequence(c); + break; + } + case State.InAttributeValueDq: { + this.stateInAttributeValueDoubleQuotes(c); + break; + } + case State.InAttributeName: { + this.stateInAttributeName(c); + break; + } + case State.InCommentLike: { + this.stateInCommentLike(c); + break; + } + case State.InSpecialComment: { + this.stateInSpecialComment(c); + break; + } + case State.BeforeAttributeName: { + this.stateBeforeAttributeName(c); + break; + } + case State.InTagName: { + this.stateInTagName(c); + break; + } + case State.InClosingTagName: { + this.stateInClosingTagName(c); + break; + } + case State.BeforeTagName: { + this.stateBeforeTagName(c); + break; + } + case State.AfterAttributeName: { + this.stateAfterAttributeName(c); + break; + } + case State.InAttributeValueSq: { + this.stateInAttributeValueSingleQuotes(c); + break; + } + case State.BeforeAttributeValue: { + this.stateBeforeAttributeValue(c); + break; + } + case State.BeforeClosingTagName: { + this.stateBeforeClosingTagName(c); + break; + } + case State.AfterClosingTagName: { + this.stateAfterClosingTagName(c); + break; + } + case State.BeforeSpecialS: { + this.stateBeforeSpecialS(c); + break; + } + case State.BeforeSpecialT: { + this.stateBeforeSpecialT(c); + break; + } + case State.InAttributeValueNq: { + this.stateInAttributeValueNoQuotes(c); + break; + } + case State.InSelfClosingTag: { + this.stateInSelfClosingTag(c); + break; + } + case State.InDeclaration: { + this.stateInDeclaration(c); + break; + } + case State.BeforeDeclaration: { + this.stateBeforeDeclaration(c); + break; + } + case State.BeforeComment: { + this.stateBeforeComment(c); + break; + } + case State.InProcessingInstruction: { + this.stateInProcessingInstruction(c); + break; + } + case State.InEntity: { + this.stateInEntity(); + break; + } } this.index++; } this.cleanup(); } finish() { - if (this.state === State.InNamedEntity) { - this.emitNamedEntity(); - } - // If there is remaining data, emit it in a reasonable way - if (this.sectionStart < this.index) { - this.handleTrailingData(); + if (this.state === State.InEntity) { + this.entityDecoder.end(); + this.state = this.baseState; } + this.handleTrailingData(); this.cbs.onend(); } /** Handle any trailing data. */ handleTrailingData() { const endIndex = this.buffer.length + this.offset; + // If there is no remaining data, we are done. + if (this.sectionStart >= endIndex) { + return; + } if (this.state === State.InCommentLike) { if (this.currentSequence === Sequences.CdataEnd) { this.cbs.oncdata(this.sectionStart, endIndex, 0); } else { this.cbs.oncomment(this.sectionStart, endIndex, 0); } - } else if ( - this.state === State.InNumericEntity && - this.allowLegacyEntity() - ) { - this.emitNumericEntity(false); - // All trailing data will have been consumed - } else if (this.state === State.InHexEntity && this.allowLegacyEntity()) { - this.emitNumericEntity(false); - // All trailing data will have been consumed } else if ( this.state === State.InTagName || this.state === State.BeforeAttributeName || @@ -994,24 +1457,24 @@ class Tokenizer { this.cbs.ontext(this.sectionStart, endIndex); } } - emitPartial(start, endIndex) { - if ( - this.baseState !== State.Text && - this.baseState !== State.InSpecialTag - ) { - this.cbs.onattribdata(start, endIndex); - } else { - this.cbs.ontext(start, endIndex); - } - } - emitCodePoint(cp) { + emitCodePoint(cp, consumed) { if ( this.baseState !== State.Text && this.baseState !== State.InSpecialTag ) { + if (this.sectionStart < this.entityStart) { + this.cbs.onattribdata(this.sectionStart, this.entityStart); + } + this.sectionStart = this.entityStart + consumed; + this.index = this.sectionStart - 1; this.cbs.onattribentity(cp); } else { - this.cbs.ontextentity(cp); + if (this.sectionStart < this.entityStart) { + this.cbs.ontext(this.sectionStart, this.entityStart); + } + this.sectionStart = this.entityStart + consumed; + this.index = this.sectionStart - 1; + this.cbs.ontextentity(cp, this.sectionStart); } } } @@ -1112,9 +1575,9 @@ const htmlIntegrationElements = new Set([ "title" ]); const reNameEnd = /\s|\//; -class Parser$1 { +let Parser$1 = class Parser { constructor(cbs, options = {}) { - var _a, _b, _c, _d, _e; + var _a, _b, _c, _d, _e, _f; this.options = options; /** The start index of the last event. */ this.startIndex = 0; @@ -1130,7 +1593,6 @@ class Parser$1 { this.attribvalue = ""; this.attribs = null; this.stack = []; - this.foreignContext = []; this.buffers = []; this.bufferOffset = 0; /** The index of the last written buffer. Used when resuming after a `pause()`. */ @@ -1138,20 +1600,26 @@ class Parser$1 { /** Indicates whether the parser has finished running / `.end` has been called. */ this.ended = false; this.cbs = cbs !== null && cbs !== void 0 ? cbs : {}; + this.htmlMode = !this.options.xmlMode; this.lowerCaseTagNames = (_a = options.lowerCaseTags) !== null && _a !== void 0 ? _a - : !options.xmlMode; + : this.htmlMode; this.lowerCaseAttributeNames = (_b = options.lowerCaseAttributeNames) !== null && _b !== void 0 ? _b - : !options.xmlMode; + : this.htmlMode; + this.recognizeSelfClosing = + (_c = options.recognizeSelfClosing) !== null && _c !== void 0 + ? _c + : !this.htmlMode; this.tokenizer = new ( - (_c = options.Tokenizer) !== null && _c !== void 0 ? _c : Tokenizer + (_d = options.Tokenizer) !== null && _d !== void 0 ? _d : Tokenizer )(this.options, this); - (_e = (_d = this.cbs).onparserinit) === null || _e === void 0 + this.foreignContext = [!this.htmlMode]; + (_f = (_e = this.cbs).onparserinit) === null || _f === void 0 ? void 0 - : _e.call(_d, this); + : _f.call(_e, this); } // Tokenizer event handlers /** @internal */ @@ -1165,21 +1633,20 @@ class Parser$1 { this.startIndex = endIndex; } /** @internal */ - ontextentity(cp) { + ontextentity(cp, endIndex) { var _a, _b; - /* - * Entities can be emitted on the character, or directly after. - * We use the section start here to get accurate indices. - */ - const idx = this.tokenizer.getSectionStart(); - this.endIndex = idx - 1; + this.endIndex = endIndex - 1; (_b = (_a = this.cbs).ontext) === null || _b === void 0 ? void 0 : _b.call(_a, fromCodePoint(cp)); - this.startIndex = idx; + this.startIndex = endIndex; } + /** + * Checks if the current tag is a void element. Override this if you want + * to specify your own additional void elements. + */ isVoidElement(name) { - return !this.options.xmlMode && voidElements$1.has(name); + return this.htmlMode && voidElements$1.has(name); } /** @internal */ onopentagname(start, endIndex) { @@ -1194,24 +1661,23 @@ class Parser$1 { var _a, _b, _c, _d; this.openTagStart = this.startIndex; this.tagname = name; - const impliesClose = !this.options.xmlMode && openImpliesClose.get(name); + const impliesClose = this.htmlMode && openImpliesClose.get(name); if (impliesClose) { - while ( - this.stack.length > 0 && - impliesClose.has(this.stack[this.stack.length - 1]) - ) { - const el = this.stack.pop(); + while (this.stack.length > 0 && impliesClose.has(this.stack[0])) { + const element = this.stack.shift(); (_b = (_a = this.cbs).onclosetag) === null || _b === void 0 ? void 0 - : _b.call(_a, el, true); + : _b.call(_a, element, true); } } if (!this.isVoidElement(name)) { - this.stack.push(name); - if (foreignContextElements.has(name)) { - this.foreignContext.push(true); - } else if (htmlIntegrationElements.has(name)) { - this.foreignContext.push(false); + this.stack.unshift(name); + if (this.htmlMode) { + if (foreignContextElements.has(name)) { + this.foreignContext.unshift(true); + } else if (htmlIntegrationElements.has(name)) { + this.foreignContext.unshift(false); + } } } (_d = (_c = this.cbs).onopentagname) === null || _d === void 0 @@ -1242,41 +1708,44 @@ class Parser$1 { } /** @internal */ onclosetag(start, endIndex) { - var _a, _b, _c, _d, _e, _f; + var _a, _b, _c, _d, _e, _f, _g, _h; this.endIndex = endIndex; let name = this.getSlice(start, endIndex); if (this.lowerCaseTagNames) { name = name.toLowerCase(); } - if (foreignContextElements.has(name) || htmlIntegrationElements.has(name)) { - this.foreignContext.pop(); + if ( + this.htmlMode && + (foreignContextElements.has(name) || htmlIntegrationElements.has(name)) + ) { + this.foreignContext.shift(); } if (!this.isVoidElement(name)) { - const pos = this.stack.lastIndexOf(name); + const pos = this.stack.indexOf(name); if (pos !== -1) { - if (this.cbs.onclosetag) { - let count = this.stack.length - pos; - while (count--) { - // We know the stack has sufficient elements. - this.cbs.onclosetag(this.stack.pop(), count !== 0); - } - } else this.stack.length = pos; - } else if (!this.options.xmlMode && name === "p") { + for (let index = 0; index <= pos; index++) { + const element = this.stack.shift(); + // We know the stack has sufficient elements. + (_b = (_a = this.cbs).onclosetag) === null || _b === void 0 + ? void 0 + : _b.call(_a, element, index !== pos); + } + } else if (this.htmlMode && name === "p") { // Implicit open before close this.emitOpenTag("p"); this.closeCurrentTag(true); } - } else if (!this.options.xmlMode && name === "br") { + } else if (this.htmlMode && name === "br") { // We can't use `emitOpenTag` for implicit open, as `br` would be implicitly closed. - (_b = (_a = this.cbs).onopentagname) === null || _b === void 0 + (_d = (_c = this.cbs).onopentagname) === null || _d === void 0 ? void 0 - : _b.call(_a, "br"); - (_d = (_c = this.cbs).onopentag) === null || _d === void 0 + : _d.call(_c, "br"); + (_f = (_e = this.cbs).onopentag) === null || _f === void 0 ? void 0 - : _d.call(_c, "br", {}, true); - (_f = (_e = this.cbs).onclosetag) === null || _f === void 0 + : _f.call(_e, "br", {}, true); + (_h = (_g = this.cbs).onclosetag) === null || _h === void 0 ? void 0 - : _f.call(_e, "br", false); + : _h.call(_g, "br", false); } // Set `startIndex` for next node this.startIndex = endIndex + 1; @@ -1284,11 +1753,7 @@ class Parser$1 { /** @internal */ onselfclosingtag(endIndex) { this.endIndex = endIndex; - if ( - this.options.xmlMode || - this.options.recognizeSelfClosing || - this.foreignContext[this.foreignContext.length - 1] - ) { + if (this.recognizeSelfClosing || this.foreignContext[0]) { this.closeCurrentTag(false); // Set `startIndex` for next node this.startIndex = endIndex + 1; @@ -1302,12 +1767,12 @@ class Parser$1 { const name = this.tagname; this.endOpenTag(isOpenImplied); // Self-closing tags will be on the top of the stack - if (this.stack[this.stack.length - 1] === name) { + if (this.stack[0] === name) { // If the opening tag isn't implied, the closing tag has to be implied. (_b = (_a = this.cbs).onclosetag) === null || _b === void 0 ? void 0 : _b.call(_a, name, !isOpenImplied); - this.stack.pop(); + this.stack.shift(); } } /** @internal */ @@ -1337,10 +1802,10 @@ class Parser$1 { quote === QuoteType.Double ? '"' : quote === QuoteType.Single - ? "'" - : quote === QuoteType.NoValue - ? undefined - : null + ? "'" + : quote === QuoteType.NoValue + ? undefined + : null ); if ( this.attribs && @@ -1351,8 +1816,8 @@ class Parser$1 { this.attribvalue = ""; } getInstructionName(value) { - const idx = value.search(reNameEnd); - let name = idx < 0 ? value : value.substr(0, idx); + const index = value.search(reNameEnd); + let name = index < 0 ? value : value.substr(0, index); if (this.lowerCaseTagNames) { name = name.toLowerCase(); } @@ -1398,7 +1863,7 @@ class Parser$1 { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; this.endIndex = endIndex; const value = this.getSlice(start, endIndex - offset); - if (this.options.xmlMode || this.options.recognizeCDATA) { + if (!this.htmlMode || this.options.recognizeCDATA) { (_b = (_a = this.cbs).oncdatastart) === null || _b === void 0 ? void 0 : _b.call(_a); @@ -1425,11 +1890,9 @@ class Parser$1 { if (this.cbs.onclosetag) { // Set the end index for all remaining tags this.endIndex = this.startIndex; - for ( - let i = this.stack.length; - i > 0; - this.cbs.onclosetag(this.stack[--i], true) - ); + for (let index = 0; index < this.stack.length; index++) { + this.cbs.onclosetag(this.stack[index], true); + } } (_b = (_a = this.cbs).onend) === null || _b === void 0 ? void 0 @@ -1454,6 +1917,8 @@ class Parser$1 { ? void 0 : _d.call(_c, this); this.buffers.length = 0; + this.foreignContext.length = 0; + this.foreignContext.unshift(!this.htmlMode); this.bufferOffset = 0; this.writeIndex = 0; this.ended = false; @@ -1472,15 +1937,15 @@ class Parser$1 { while (start - this.bufferOffset >= this.buffers[0].length) { this.shiftBuffer(); } - let str = this.buffers[0].slice( + let slice = this.buffers[0].slice( start - this.bufferOffset, end - this.bufferOffset ); while (end - this.bufferOffset > this.buffers[0].length) { this.shiftBuffer(); - str += this.buffers[0].slice(0, end - this.bufferOffset); + slice += this.buffers[0].slice(0, end - this.bufferOffset); } - return str; + return slice; } shiftBuffer() { this.bufferOffset += this.buffers[0].length; @@ -1516,7 +1981,7 @@ class Parser$1 { if (this.ended) { (_b = (_a = this.cbs).onerror) === null || _b === void 0 ? void 0 - : _b.call(_a, Error(".end() after done!")); + : _b.call(_a, new Error(".end() after done!")); return; } if (chunk) this.write(chunk); @@ -1557,1967 +2022,15 @@ class Parser$1 { done(chunk) { this.end(chunk); } -} - -/** Types of elements found in htmlparser2's DOM */ -var ElementType; -(function (ElementType) { - /** Type for the root element of a document */ - ElementType["Root"] = "root"; - /** Type for Text */ - ElementType["Text"] = "text"; - /** Type for <? ... ?> */ - ElementType["Directive"] = "directive"; - /** Type for <!-- ... --> */ - ElementType["Comment"] = "comment"; - /** Type for <script> tags */ - ElementType["Script"] = "script"; - /** Type for <style> tags */ - ElementType["Style"] = "style"; - /** Type for Any tag */ - ElementType["Tag"] = "tag"; - /** Type for <![CDATA[ ... ]]> */ - ElementType["CDATA"] = "cdata"; - /** Type for <!doctype ...> */ - ElementType["Doctype"] = "doctype"; -})(ElementType || (ElementType = {})); -/** - * Tests whether an element is a tag or not. - * - * @param elem Element to test - */ -function isTag$2(elem) { - return ( - elem.type === ElementType.Tag || - elem.type === ElementType.Script || - elem.type === ElementType.Style - ); -} -// Exports for backwards compatibility -/** Type for the root element of a document */ -const Root = ElementType.Root; -/** Type for Text */ -const Text$3 = ElementType.Text; -/** Type for <? ... ?> */ -const Directive = ElementType.Directive; -/** Type for <!-- ... --> */ -const Comment$3 = ElementType.Comment; -/** Type for <script> tags */ -const Script = ElementType.Script; -/** Type for <style> tags */ -const Style = ElementType.Style; -/** Type for Any tag */ -const Tag = ElementType.Tag; -/** Type for <![CDATA[ ... ]]> */ -const CDATA$1 = ElementType.CDATA; -/** Type for <!doctype ...> */ -const Doctype = ElementType.Doctype; - -var index = /*#__PURE__*/ Object.freeze({ - __proto__: null, - get ElementType() { - return ElementType; - }, - isTag: isTag$2, - Root: Root, - Text: Text$3, - Directive: Directive, - Comment: Comment$3, - Script: Script, - Style: Style, - Tag: Tag, - CDATA: CDATA$1, - Doctype: Doctype -}); - -/** - * This object will be used as the prototype for Nodes when creating a - * DOM-Level-1-compliant structure. - */ -class Node$2 { - constructor() { - /** Parent of the node */ - this.parent = null; - /** Previous sibling */ - this.prev = null; - /** Next sibling */ - this.next = null; - /** The start index of the node. Requires `withStartIndices` on the handler to be `true. */ - this.startIndex = null; - /** The end index of the node. Requires `withEndIndices` on the handler to be `true. */ - this.endIndex = null; - } - // Read-write aliases for properties - /** - * Same as {@link parent}. - * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. - */ - get parentNode() { - return this.parent; - } - set parentNode(parent) { - this.parent = parent; - } - /** - * Same as {@link prev}. - * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. - */ - get previousSibling() { - return this.prev; - } - set previousSibling(prev) { - this.prev = prev; - } - /** - * Same as {@link next}. - * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. - */ - get nextSibling() { - return this.next; - } - set nextSibling(next) { - this.next = next; - } - /** - * Clone this node, and optionally its children. - * - * @param recursive Clone child nodes as well. - * @returns A clone of the node. - */ - cloneNode(recursive = false) { - return cloneNode(this, recursive); - } -} -/** - * A node that contains some data. - */ -class DataNode extends Node$2 { - /** - * @param data The content of the data node - */ - constructor(data) { - super(); - this.data = data; - } - /** - * Same as {@link data}. - * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. - */ - get nodeValue() { - return this.data; - } - set nodeValue(data) { - this.data = data; - } -} -/** - * Text within the document. - */ -class Text$2 extends DataNode { - constructor() { - super(...arguments); - this.type = ElementType.Text; - } - get nodeType() { - return 3; - } -} -/** - * Comments within the document. - */ -class Comment$2 extends DataNode { - constructor() { - super(...arguments); - this.type = ElementType.Comment; - } - get nodeType() { - return 8; - } -} -/** - * Processing instructions, including doc types. - */ -class ProcessingInstruction extends DataNode { - constructor(name, data) { - super(data); - this.name = name; - this.type = ElementType.Directive; - } - get nodeType() { - return 1; - } -} -/** - * A `Node` that can have children. - */ -class NodeWithChildren extends Node$2 { - /** - * @param children Children of the node. Only certain node types can have children. - */ - constructor(children) { - super(); - this.children = children; - } - // Aliases - /** First child of the node. */ - get firstChild() { - var _a; - return (_a = this.children[0]) !== null && _a !== void 0 ? _a : null; - } - /** Last child of the node. */ - get lastChild() { - return this.children.length > 0 - ? this.children[this.children.length - 1] - : null; - } - /** - * Same as {@link children}. - * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. - */ - get childNodes() { - return this.children; - } - set childNodes(children) { - this.children = children; - } -} -class CDATA extends NodeWithChildren { - constructor() { - super(...arguments); - this.type = ElementType.CDATA; - } - get nodeType() { - return 4; - } -} -/** - * The root node of the document. - */ -class Document$2 extends NodeWithChildren { - constructor() { - super(...arguments); - this.type = ElementType.Root; - } - get nodeType() { - return 9; - } -} -/** - * An element within the DOM. - */ -class Element$2 extends NodeWithChildren { - /** - * @param name Name of the tag, eg. `div`, `span`. - * @param attribs Object mapping attribute names to attribute values. - * @param children Children of the node. - */ - constructor( - name, - attribs, - children = [], - type = name === "script" - ? ElementType.Script - : name === "style" - ? ElementType.Style - : ElementType.Tag - ) { - super(children); - this.name = name; - this.attribs = attribs; - this.type = type; - } - get nodeType() { - return 1; - } - // DOM Level 1 aliases - /** - * Same as {@link name}. - * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. - */ - get tagName() { - return this.name; - } - set tagName(name) { - this.name = name; - } - get attributes() { - return Object.keys(this.attribs).map((name) => { - var _a, _b; - return { - name, - value: this.attribs[name], - namespace: - (_a = this["x-attribsNamespace"]) === null || _a === void 0 - ? void 0 - : _a[name], - prefix: - (_b = this["x-attribsPrefix"]) === null || _b === void 0 - ? void 0 - : _b[name] - }; - }); - } -} -/** - * @param node Node to check. - * @returns `true` if the node is a `Element`, `false` otherwise. - */ -function isTag$1(node) { - return isTag$2(node); -} -/** - * @param node Node to check. - * @returns `true` if the node has the type `CDATA`, `false` otherwise. - */ -function isCDATA(node) { - return node.type === ElementType.CDATA; -} -/** - * @param node Node to check. - * @returns `true` if the node has the type `Text`, `false` otherwise. - */ -function isText(node) { - return node.type === ElementType.Text; -} -/** - * @param node Node to check. - * @returns `true` if the node has the type `Comment`, `false` otherwise. - */ -function isComment(node) { - return node.type === ElementType.Comment; -} -/** - * @param node Node to check. - * @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise. - */ -function isDirective(node) { - return node.type === ElementType.Directive; -} -/** - * @param node Node to check. - * @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise. - */ -function isDocument(node) { - return node.type === ElementType.Root; -} -/** - * @param node Node to check. - * @returns `true` if the node has children, `false` otherwise. - */ -function hasChildren(node) { - return Object.prototype.hasOwnProperty.call(node, "children"); -} -/** - * Clone a node, and optionally its children. - * - * @param recursive Clone child nodes as well. - * @returns A clone of the node. - */ -function cloneNode(node, recursive = false) { - let result; - if (isText(node)) { - result = new Text$2(node.data); - } else if (isComment(node)) { - result = new Comment$2(node.data); - } else if (isTag$1(node)) { - const children = recursive ? cloneChildren(node.children) : []; - const clone = new Element$2(node.name, { ...node.attribs }, children); - children.forEach((child) => (child.parent = clone)); - if (node.namespace != null) { - clone.namespace = node.namespace; - } - if (node["x-attribsNamespace"]) { - clone["x-attribsNamespace"] = { ...node["x-attribsNamespace"] }; - } - if (node["x-attribsPrefix"]) { - clone["x-attribsPrefix"] = { ...node["x-attribsPrefix"] }; - } - result = clone; - } else if (isCDATA(node)) { - const children = recursive ? cloneChildren(node.children) : []; - const clone = new CDATA(children); - children.forEach((child) => (child.parent = clone)); - result = clone; - } else if (isDocument(node)) { - const children = recursive ? cloneChildren(node.children) : []; - const clone = new Document$2(children); - children.forEach((child) => (child.parent = clone)); - if (node["x-mode"]) { - clone["x-mode"] = node["x-mode"]; - } - result = clone; - } else if (isDirective(node)) { - const instruction = new ProcessingInstruction(node.name, node.data); - if (node["x-name"] != null) { - instruction["x-name"] = node["x-name"]; - instruction["x-publicId"] = node["x-publicId"]; - instruction["x-systemId"] = node["x-systemId"]; - } - result = instruction; - } else { - throw new Error(`Not implemented yet: ${node.type}`); - } - result.startIndex = node.startIndex; - result.endIndex = node.endIndex; - if (node.sourceCodeLocation != null) { - result.sourceCodeLocation = node.sourceCodeLocation; - } - return result; -} -function cloneChildren(childs) { - const children = childs.map((child) => cloneNode(child, true)); - for (let i = 1; i < children.length; i++) { - children[i].prev = children[i - 1]; - children[i - 1].next = children[i]; - } - return children; -} - -// Default options -const defaultOpts = { - withStartIndices: false, - withEndIndices: false, - xmlMode: false }; -class DomHandler { - /** - * @param callback Called once parsing has completed. - * @param options Settings for the handler. - * @param elementCB Callback whenever a tag is closed. - */ - constructor(callback, options, elementCB) { - /** The elements of the DOM */ - this.dom = []; - /** The root element for the DOM */ - this.root = new Document$2(this.dom); - /** Indicated whether parsing has been completed. */ - this.done = false; - /** Stack of open tags. */ - this.tagStack = [this.root]; - /** A data node that is still being written to. */ - this.lastNode = null; - /** Reference to the parser instance. Used for location information. */ - this.parser = null; - // Make it possible to skip arguments, for backwards-compatibility - if (typeof options === "function") { - elementCB = options; - options = defaultOpts; - } - if (typeof callback === "object") { - options = callback; - callback = undefined; - } - this.callback = callback !== null && callback !== void 0 ? callback : null; - this.options = - options !== null && options !== void 0 ? options : defaultOpts; - this.elementCB = - elementCB !== null && elementCB !== void 0 ? elementCB : null; - } - onparserinit(parser) { - this.parser = parser; - } - // Resets the handler back to starting state - onreset() { - this.dom = []; - this.root = new Document$2(this.dom); - this.done = false; - this.tagStack = [this.root]; - this.lastNode = null; - this.parser = null; - } - // Signals the handler that parsing is done - onend() { - if (this.done) return; - this.done = true; - this.parser = null; - this.handleCallback(null); - } - onerror(error) { - this.handleCallback(error); - } - onclosetag() { - this.lastNode = null; - const elem = this.tagStack.pop(); - if (this.options.withEndIndices) { - elem.endIndex = this.parser.endIndex; - } - if (this.elementCB) this.elementCB(elem); - } - onopentag(name, attribs) { - const type = this.options.xmlMode ? ElementType.Tag : undefined; - const element = new Element$2(name, attribs, undefined, type); - this.addNode(element); - this.tagStack.push(element); - } - ontext(data) { - const { lastNode } = this; - if (lastNode && lastNode.type === ElementType.Text) { - lastNode.data += data; - if (this.options.withEndIndices) { - lastNode.endIndex = this.parser.endIndex; - } - } else { - const node = new Text$2(data); - this.addNode(node); - this.lastNode = node; - } - } - oncomment(data) { - if (this.lastNode && this.lastNode.type === ElementType.Comment) { - this.lastNode.data += data; - return; - } - const node = new Comment$2(data); - this.addNode(node); - this.lastNode = node; - } - oncommentend() { - this.lastNode = null; - } - oncdatastart() { - const text = new Text$2(""); - const node = new CDATA([text]); - this.addNode(node); - text.parent = node; - this.lastNode = text; - } - oncdataend() { - this.lastNode = null; - } - onprocessinginstruction(name, data) { - const node = new ProcessingInstruction(name, data); - this.addNode(node); - } - handleCallback(error) { - if (typeof this.callback === "function") { - this.callback(error, this.dom); - } else if (error) { - throw error; - } - } - addNode(node) { - const parent = this.tagStack[this.tagStack.length - 1]; - const previousSibling = parent.children[parent.children.length - 1]; - if (this.options.withStartIndices) { - node.startIndex = this.parser.startIndex; - } - if (this.options.withEndIndices) { - node.endIndex = this.parser.endIndex; - } - parent.children.push(node); - if (previousSibling) { - node.prev = previousSibling; - previousSibling.next = node; - } - node.parent = parent; - this.lastNode = null; - } -} - -const xmlReplacer = /["&'<>$\x80-\uFFFF]/g; -const xmlCodeMap = new Map([ - [34, """], - [38, "&"], - [39, "'"], - [60, "<"], - [62, ">"] -]); -// For compatibility with node < 4, we wrap `codePointAt` -const getCodePoint = - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - String.prototype.codePointAt != null - ? (str, index) => str.codePointAt(index) - : // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae - (c, index) => - (c.charCodeAt(index) & 0xfc00) === 0xd800 - ? (c.charCodeAt(index) - 0xd800) * 0x400 + - c.charCodeAt(index + 1) - - 0xdc00 + - 0x10000 - : c.charCodeAt(index); -/** - * Encodes all non-ASCII characters, as well as characters not valid in XML - * documents using XML entities. - * - * If a character has no equivalent entity, a - * numeric hexadecimal reference (eg. `ü`) will be used. - */ -function encodeXML(str) { - let ret = ""; - let lastIdx = 0; - let match; - while ((match = xmlReplacer.exec(str)) !== null) { - const i = match.index; - const char = str.charCodeAt(i); - const next = xmlCodeMap.get(char); - if (next !== undefined) { - ret += str.substring(lastIdx, i) + next; - lastIdx = i + 1; - } else { - ret += `${str.substring(lastIdx, i)}&#x${getCodePoint(str, i).toString( - 16 - )};`; - // Increase by 1 if we have a surrogate pair - lastIdx = xmlReplacer.lastIndex += Number((char & 0xfc00) === 0xd800); - } - } - return ret + str.substr(lastIdx); -} -function getEscaper(regex, map) { - return function escape(data) { - let match; - let lastIdx = 0; - let result = ""; - while ((match = regex.exec(data))) { - if (lastIdx !== match.index) { - result += data.substring(lastIdx, match.index); - } - // We know that this character will be in the map. - result += map.get(match[0].charCodeAt(0)); - // Every match will be of length 1 - lastIdx = match.index + 1; - } - return result + data.substring(lastIdx); - }; -} -/** - * Encodes all characters that have to be escaped in HTML attributes, - * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. - * - * @param data String to escape. - */ -const escapeAttribute = getEscaper( - /["&\u00A0]/g, - new Map([ - [34, """], - [38, "&"], - [160, " "] - ]) -); -/** - * Encodes all characters that have to be escaped in HTML text, - * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. - * - * @param data String to escape. - */ -const escapeText = getEscaper( - /[&<>\u00A0]/g, - new Map([ - [38, "&"], - [60, "<"], - [62, ">"], - [160, " "] - ]) -); - -/** The level of entities to support. */ -var EntityLevel; -(function (EntityLevel) { - /** Support only XML entities. */ - EntityLevel[(EntityLevel["XML"] = 0)] = "XML"; - /** Support HTML entities, which are a superset of XML entities. */ - EntityLevel[(EntityLevel["HTML"] = 1)] = "HTML"; -})(EntityLevel || (EntityLevel = {})); -/** Determines whether some entities are allowed to be written without a trailing `;`. */ -var DecodingMode; -(function (DecodingMode) { - /** Support legacy HTML entities. */ - DecodingMode[(DecodingMode["Legacy"] = 0)] = "Legacy"; - /** Do not support legacy HTML entities. */ - DecodingMode[(DecodingMode["Strict"] = 1)] = "Strict"; -})(DecodingMode || (DecodingMode = {})); -var EncodingMode; -(function (EncodingMode) { - /** - * The output is UTF-8 encoded. Only characters that need escaping within - * HTML will be escaped. - */ - EncodingMode[(EncodingMode["UTF8"] = 0)] = "UTF8"; - /** - * The output consists only of ASCII characters. Characters that need - * escaping within HTML, and characters that aren't ASCII characters will - * be escaped. - */ - EncodingMode[(EncodingMode["ASCII"] = 1)] = "ASCII"; - /** - * Encode all characters that have an equivalent entity, as well as all - * characters that are not ASCII characters. - */ - EncodingMode[(EncodingMode["Extensive"] = 2)] = "Extensive"; - /** - * Encode all characters that have to be escaped in HTML attributes, - * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. - */ - EncodingMode[(EncodingMode["Attribute"] = 3)] = "Attribute"; - /** - * Encode all characters that have to be escaped in HTML text, - * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. - */ - EncodingMode[(EncodingMode["Text"] = 4)] = "Text"; -})(EncodingMode || (EncodingMode = {})); - -const elementNames = new Map( - [ - "altGlyph", - "altGlyphDef", - "altGlyphItem", - "animateColor", - "animateMotion", - "animateTransform", - "clipPath", - "feBlend", - "feColorMatrix", - "feComponentTransfer", - "feComposite", - "feConvolveMatrix", - "feDiffuseLighting", - "feDisplacementMap", - "feDistantLight", - "feDropShadow", - "feFlood", - "feFuncA", - "feFuncB", - "feFuncG", - "feFuncR", - "feGaussianBlur", - "feImage", - "feMerge", - "feMergeNode", - "feMorphology", - "feOffset", - "fePointLight", - "feSpecularLighting", - "feSpotLight", - "feTile", - "feTurbulence", - "foreignObject", - "glyphRef", - "linearGradient", - "radialGradient", - "textPath" - ].map((val) => [val.toLowerCase(), val]) -); -const attributeNames = new Map( - [ - "definitionURL", - "attributeName", - "attributeType", - "baseFrequency", - "baseProfile", - "calcMode", - "clipPathUnits", - "diffuseConstant", - "edgeMode", - "filterUnits", - "glyphRef", - "gradientTransform", - "gradientUnits", - "kernelMatrix", - "kernelUnitLength", - "keyPoints", - "keySplines", - "keyTimes", - "lengthAdjust", - "limitingConeAngle", - "markerHeight", - "markerUnits", - "markerWidth", - "maskContentUnits", - "maskUnits", - "numOctaves", - "pathLength", - "patternContentUnits", - "patternTransform", - "patternUnits", - "pointsAtX", - "pointsAtY", - "pointsAtZ", - "preserveAlpha", - "preserveAspectRatio", - "primitiveUnits", - "refX", - "refY", - "repeatCount", - "repeatDur", - "requiredExtensions", - "requiredFeatures", - "specularConstant", - "specularExponent", - "spreadMethod", - "startOffset", - "stdDeviation", - "stitchTiles", - "surfaceScale", - "systemLanguage", - "tableValues", - "targetX", - "targetY", - "textLength", - "viewBox", - "viewTarget", - "xChannelSelector", - "yChannelSelector", - "zoomAndPan" - ].map((val) => [val.toLowerCase(), val]) -); - -/* - * Module dependencies - */ -const unencodedElements = new Set([ - "style", - "script", - "xmp", - "iframe", - "noembed", - "noframes", - "plaintext", - "noscript" -]); -function replaceQuotes(value) { - return value.replace(/"/g, """); -} -/** - * Format attributes - */ -function formatAttributes(attributes, opts) { - var _a; - if (!attributes) return; - const encode = - ((_a = opts.encodeEntities) !== null && _a !== void 0 - ? _a - : opts.decodeEntities) === false - ? replaceQuotes - : opts.xmlMode || opts.encodeEntities !== "utf8" - ? encodeXML - : escapeAttribute; - return Object.keys(attributes) - .map((key) => { - var _a, _b; - const value = (_a = attributes[key]) !== null && _a !== void 0 ? _a : ""; - if (opts.xmlMode === "foreign") { - /* Fix up mixed-case attribute names */ - key = - (_b = attributeNames.get(key)) !== null && _b !== void 0 ? _b : key; - } - if (!opts.emptyAttrs && !opts.xmlMode && value === "") { - return key; - } - return `${key}="${encode(value)}"`; - }) - .join(" "); -} -/** - * Self-enclosing tags - */ -const singleTag = new Set([ - "area", - "base", - "basefont", - "br", - "col", - "command", - "embed", - "frame", - "hr", - "img", - "input", - "isindex", - "keygen", - "link", - "meta", - "param", - "source", - "track", - "wbr" -]); -/** - * Renders a DOM node or an array of DOM nodes to a string. - * - * Can be thought of as the equivalent of the `outerHTML` of the passed node(s). - * - * @param node Node to be rendered. - * @param options Changes serialization behavior - */ -function render(node, options = {}) { - const nodes = "length" in node ? node : [node]; - let output = ""; - for (let i = 0; i < nodes.length; i++) { - output += renderNode(nodes[i], options); - } - return output; -} -function renderNode(node, options) { - switch (node.type) { - case Root: - return render(node.children, options); - // @ts-expect-error We don't use `Doctype` yet - case Doctype: - case Directive: - return renderDirective(node); - case Comment$3: - return renderComment(node); - case CDATA$1: - return renderCdata(node); - case Script: - case Style: - case Tag: - return renderTag(node, options); - case Text$3: - return renderText(node, options); - } -} -const foreignModeIntegrationPoints = new Set([ - "mi", - "mo", - "mn", - "ms", - "mtext", - "annotation-xml", - "foreignObject", - "desc", - "title" -]); -const foreignElements = new Set(["svg", "math"]); -function renderTag(elem, opts) { - var _a; - // Handle SVG / MathML in HTML - if (opts.xmlMode === "foreign") { - /* Fix up mixed-case element names */ - elem.name = - (_a = elementNames.get(elem.name)) !== null && _a !== void 0 - ? _a - : elem.name; - /* Exit foreign mode at integration points */ - if (elem.parent && foreignModeIntegrationPoints.has(elem.parent.name)) { - opts = { ...opts, xmlMode: false }; - } - } - if (!opts.xmlMode && foreignElements.has(elem.name)) { - opts = { ...opts, xmlMode: "foreign" }; - } - let tag = `<${elem.name}`; - const attribs = formatAttributes(elem.attribs, opts); - if (attribs) { - tag += ` ${attribs}`; - } - if ( - elem.children.length === 0 && - (opts.xmlMode - ? // In XML mode or foreign mode, and user hasn't explicitly turned off self-closing tags - opts.selfClosingTags !== false - : // User explicitly asked for self-closing tags, even in HTML mode - opts.selfClosingTags && singleTag.has(elem.name)) - ) { - if (!opts.xmlMode) tag += " "; - tag += "/>"; - } else { - tag += ">"; - if (elem.children.length > 0) { - tag += render(elem.children, opts); - } - if (opts.xmlMode || !singleTag.has(elem.name)) { - tag += `</${elem.name}>`; - } - } - return tag; -} -function renderDirective(elem) { - return `<${elem.data}>`; -} -function renderText(elem, opts) { - var _a; - let data = elem.data || ""; - // If entities weren't decoded, no need to encode them back - if ( - ((_a = opts.encodeEntities) !== null && _a !== void 0 - ? _a - : opts.decodeEntities) !== false && - !(!opts.xmlMode && elem.parent && unencodedElements.has(elem.parent.name)) - ) { - data = - opts.xmlMode || opts.encodeEntities !== "utf8" - ? encodeXML(data) - : escapeText(data); - } - return data; -} -function renderCdata(elem) { - return `<![CDATA[${elem.children[0].data}]]>`; -} -function renderComment(elem) { - return `<!--${elem.data}-->`; -} - -/** - * @category Stringify - * @deprecated Use the `dom-serializer` module directly. - * @param node Node to get the outer HTML of. - * @param options Options for serialization. - * @returns `node`'s outer HTML. - */ -function getOuterHTML(node, options) { - return render(node, options); -} -/** - * @category Stringify - * @deprecated Use the `dom-serializer` module directly. - * @param node Node to get the inner HTML of. - * @param options Options for serialization. - * @returns `node`'s inner HTML. - */ -function getInnerHTML(node, options) { - return hasChildren(node) - ? node.children.map((node) => getOuterHTML(node, options)).join("") - : ""; -} -/** - * Get a node's inner text. Same as `textContent`, but inserts newlines for `<br>` tags. - * - * @category Stringify - * @deprecated Use `textContent` instead. - * @param node Node to get the inner text of. - * @returns `node`'s inner text. - */ -function getText$1(node) { - if (Array.isArray(node)) return node.map(getText$1).join(""); - if (isTag$1(node)) - return node.name === "br" ? "\n" : getText$1(node.children); - if (isCDATA(node)) return getText$1(node.children); - if (isText(node)) return node.data; - return ""; -} -/** - * Get a node's text content. - * - * @category Stringify - * @param node Node to get the text content of. - * @returns `node`'s text content. - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent} - */ -function textContent(node) { - if (Array.isArray(node)) return node.map(textContent).join(""); - if (hasChildren(node) && !isComment(node)) { - return textContent(node.children); - } - if (isText(node)) return node.data; - return ""; -} -/** - * Get a node's inner text. - * - * @category Stringify - * @param node Node to get the inner text of. - * @returns `node`'s inner text. - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/innerText} - */ -function innerText(node) { - if (Array.isArray(node)) return node.map(innerText).join(""); - if (hasChildren(node) && (node.type === ElementType.Tag || isCDATA(node))) { - return innerText(node.children); - } - if (isText(node)) return node.data; - return ""; -} - -/** - * Get a node's children. - * - * @category Traversal - * @param elem Node to get the children of. - * @returns `elem`'s children, or an empty array. - */ -function getChildren$1(elem) { - return hasChildren(elem) ? elem.children : []; -} -/** - * Get a node's parent. - * - * @category Traversal - * @param elem Node to get the parent of. - * @returns `elem`'s parent node. - */ -function getParent$1(elem) { - return elem.parent || null; -} -/** - * Gets an elements siblings, including the element itself. - * - * Attempts to get the children through the element's parent first. If we don't - * have a parent (the element is a root node), we walk the element's `prev` & - * `next` to get all remaining nodes. - * - * @category Traversal - * @param elem Element to get the siblings of. - * @returns `elem`'s siblings. - */ -function getSiblings$1(elem) { - const parent = getParent$1(elem); - if (parent != null) return getChildren$1(parent); - const siblings = [elem]; - let { prev, next } = elem; - while (prev != null) { - siblings.unshift(prev); - ({ prev } = prev); - } - while (next != null) { - siblings.push(next); - ({ next } = next); - } - return siblings; -} -/** - * Gets an attribute from an element. - * - * @category Traversal - * @param elem Element to check. - * @param name Attribute name to retrieve. - * @returns The element's attribute value, or `undefined`. - */ -function getAttributeValue$1(elem, name) { - var _a; - return (_a = elem.attribs) === null || _a === void 0 ? void 0 : _a[name]; -} -/** - * Checks whether an element has an attribute. - * - * @category Traversal - * @param elem Element to check. - * @param name Attribute name to look for. - * @returns Returns whether `elem` has the attribute `name`. - */ -function hasAttrib$1(elem, name) { - return ( - elem.attribs != null && - Object.prototype.hasOwnProperty.call(elem.attribs, name) && - elem.attribs[name] != null - ); -} -/** - * Get the tag name of an element. - * - * @category Traversal - * @param elem The element to get the name for. - * @returns The tag name of `elem`. - */ -function getName$1(elem) { - return elem.name; -} -/** - * Returns the next element sibling of a node. - * - * @category Traversal - * @param elem The element to get the next sibling of. - * @returns `elem`'s next sibling that is a tag. - */ -function nextElementSibling$1(elem) { - let { next } = elem; - while (next !== null && !isTag$1(next)) ({ next } = next); - return next; -} -/** - * Returns the previous element sibling of a node. - * - * @category Traversal - * @param elem The element to get the previous sibling of. - * @returns `elem`'s previous sibling that is a tag. - */ -function prevElementSibling(elem) { - let { prev } = elem; - while (prev !== null && !isTag$1(prev)) ({ prev } = prev); - return prev; -} - -/** - * Remove an element from the dom - * - * @category Manipulation - * @param elem The element to be removed - */ -function removeElement(elem) { - if (elem.prev) elem.prev.next = elem.next; - if (elem.next) elem.next.prev = elem.prev; - if (elem.parent) { - const childs = elem.parent.children; - childs.splice(childs.lastIndexOf(elem), 1); - } -} -/** - * Replace an element in the dom - * - * @category Manipulation - * @param elem The element to be replaced - * @param replacement The element to be added - */ -function replaceElement(elem, replacement) { - const prev = (replacement.prev = elem.prev); - if (prev) { - prev.next = replacement; - } - const next = (replacement.next = elem.next); - if (next) { - next.prev = replacement; - } - const parent = (replacement.parent = elem.parent); - if (parent) { - const childs = parent.children; - childs[childs.lastIndexOf(elem)] = replacement; - elem.parent = null; - } -} -/** - * Append a child to an element. - * - * @category Manipulation - * @param elem The element to append to. - * @param child The element to be added as a child. - */ -function appendChild(elem, child) { - removeElement(child); - child.next = null; - child.parent = elem; - if (elem.children.push(child) > 1) { - const sibling = elem.children[elem.children.length - 2]; - sibling.next = child; - child.prev = sibling; - } else { - child.prev = null; - } -} -/** - * Append an element after another. - * - * @category Manipulation - * @param elem The element to append after. - * @param next The element be added. - */ -function append$2(elem, next) { - removeElement(next); - const { parent } = elem; - const currNext = elem.next; - next.next = currNext; - next.prev = elem; - elem.next = next; - next.parent = parent; - if (currNext) { - currNext.prev = next; - if (parent) { - const childs = parent.children; - childs.splice(childs.lastIndexOf(currNext), 0, next); - } - } else if (parent) { - parent.children.push(next); - } -} -/** - * Prepend a child to an element. - * - * @category Manipulation - * @param elem The element to prepend before. - * @param child The element to be added as a child. - */ -function prependChild(elem, child) { - removeElement(child); - child.parent = elem; - child.prev = null; - if (elem.children.unshift(child) !== 1) { - const sibling = elem.children[1]; - sibling.prev = child; - child.next = sibling; - } else { - child.next = null; - } -} -/** - * Prepend an element before another. - * - * @category Manipulation - * @param elem The element to prepend before. - * @param prev The element be added. - */ -function prepend(elem, prev) { - removeElement(prev); - const { parent } = elem; - if (parent) { - const childs = parent.children; - childs.splice(childs.indexOf(elem), 0, prev); - } - if (elem.prev) { - elem.prev.next = prev; - } - prev.parent = parent; - prev.prev = elem.prev; - prev.next = elem; - elem.prev = prev; -} - -/** - * Search a node and its children for nodes passing a test function. - * - * @category Querying - * @param test Function to test nodes on. - * @param node Node to search. Will be included in the result set if it matches. - * @param recurse Also consider child nodes. - * @param limit Maximum number of nodes to return. - * @returns All nodes passing `test`. - */ -function filter(test, node, recurse = true, limit = Infinity) { - if (!Array.isArray(node)) node = [node]; - return find(test, node, recurse, limit); -} -/** - * Search an array of node and its children for nodes passing a test function. - * - * @category Querying - * @param test Function to test nodes on. - * @param nodes Array of nodes to search. - * @param recurse Also consider child nodes. - * @param limit Maximum number of nodes to return. - * @returns All nodes passing `test`. - */ -function find(test, nodes, recurse, limit) { - const result = []; - for (const elem of nodes) { - if (test(elem)) { - result.push(elem); - if (--limit <= 0) break; - } - if (recurse && hasChildren(elem) && elem.children.length > 0) { - const children = find(test, elem.children, recurse, limit); - result.push(...children); - limit -= children.length; - if (limit <= 0) break; - } - } - return result; -} -/** - * Finds the first element inside of an array that matches a test function. - * - * @category Querying - * @param test Function to test nodes on. - * @param nodes Array of nodes to search. - * @returns The first node in the array that passes `test`. - * @deprecated Use `Array.prototype.find` directly. - */ -function findOneChild(test, nodes) { - return nodes.find(test); -} -/** - * Finds one element in a tree that passes a test. - * - * @category Querying - * @param test Function to test nodes on. - * @param nodes Array of nodes to search. - * @param recurse Also consider child nodes. - * @returns The first child node that passes `test`. - */ -function findOne$1(test, nodes, recurse = true) { - let elem = null; - for (let i = 0; i < nodes.length && !elem; i++) { - const checked = nodes[i]; - if (!isTag$1(checked)) { - continue; - } else if (test(checked)) { - elem = checked; - } else if (recurse && checked.children.length > 0) { - elem = findOne$1(test, checked.children, true); - } - } - return elem; -} -/** - * @category Querying - * @param test Function to test nodes on. - * @param nodes Array of nodes to search. - * @returns Whether a tree of nodes contains at least one node passing the test. - */ -function existsOne$1(test, nodes) { - return nodes.some( - (checked) => - isTag$1(checked) && - (test(checked) || - (checked.children.length > 0 && existsOne$1(test, checked.children))) - ); -} -/** - * Search and array of nodes and its children for elements passing a test function. - * - * Same as `find`, but limited to elements and with less options, leading to reduced complexity. - * - * @category Querying - * @param test Function to test nodes on. - * @param nodes Array of nodes to search. - * @returns All nodes passing `test`. - */ -function findAll$1(test, nodes) { - var _a; - const result = []; - const stack = nodes.filter(isTag$1); - let elem; - while ((elem = stack.shift())) { - const children = - (_a = elem.children) === null || _a === void 0 - ? void 0 - : _a.filter(isTag$1); - if (children && children.length > 0) { - stack.unshift(...children); - } - if (test(elem)) result.push(elem); - } - return result; -} - -const Checks = { - tag_name(name) { - if (typeof name === "function") { - return (elem) => isTag$1(elem) && name(elem.name); - } else if (name === "*") { - return isTag$1; - } - return (elem) => isTag$1(elem) && elem.name === name; - }, - tag_type(type) { - if (typeof type === "function") { - return (elem) => type(elem.type); - } - return (elem) => elem.type === type; - }, - tag_contains(data) { - if (typeof data === "function") { - return (elem) => isText(elem) && data(elem.data); - } - return (elem) => isText(elem) && elem.data === data; - } -}; -/** - * @param attrib Attribute to check. - * @param value Attribute value to look for. - * @returns A function to check whether the a node has an attribute with a - * particular value. - */ -function getAttribCheck(attrib, value) { - if (typeof value === "function") { - return (elem) => isTag$1(elem) && value(elem.attribs[attrib]); - } - return (elem) => isTag$1(elem) && elem.attribs[attrib] === value; -} -/** - * @param a First function to combine. - * @param b Second function to combine. - * @returns A function taking a node and returning `true` if either of the input - * functions returns `true` for the node. - */ -function combineFuncs(a, b) { - return (elem) => a(elem) || b(elem); -} -/** - * @param options An object describing nodes to look for. - * @returns A function executing all checks in `options` and returning `true` if - * any of them match a node. - */ -function compileTest(options) { - const funcs = Object.keys(options).map((key) => { - const value = options[key]; - return Object.prototype.hasOwnProperty.call(Checks, key) - ? Checks[key](value) - : getAttribCheck(key, value); - }); - return funcs.length === 0 ? null : funcs.reduce(combineFuncs); -} -/** - * @category Legacy Query Functions - * @param options An object describing nodes to look for. - * @param node The element to test. - * @returns Whether the element matches the description in `options`. - */ -function testElement(options, node) { - const test = compileTest(options); - return test ? test(node) : true; -} -/** - * @category Legacy Query Functions - * @param options An object describing nodes to look for. - * @param nodes Nodes to search through. - * @param recurse Also consider child nodes. - * @param limit Maximum number of nodes to return. - * @returns All nodes that match `options`. - */ -function getElements(options, nodes, recurse, limit = Infinity) { - const test = compileTest(options); - return test ? filter(test, nodes, recurse, limit) : []; -} -/** - * @category Legacy Query Functions - * @param id The unique ID attribute value to look for. - * @param nodes Nodes to search through. - * @param recurse Also consider child nodes. - * @returns The node with the supplied ID. - */ -function getElementById(id, nodes, recurse = true) { - if (!Array.isArray(nodes)) nodes = [nodes]; - return findOne$1(getAttribCheck("id", id), nodes, recurse); -} -/** - * @category Legacy Query Functions - * @param tagName Tag name to search for. - * @param nodes Nodes to search through. - * @param recurse Also consider child nodes. - * @param limit Maximum number of nodes to return. - * @returns All nodes with the supplied `tagName`. - */ -function getElementsByTagName( - tagName, - nodes, - recurse = true, - limit = Infinity -) { - return filter(Checks["tag_name"](tagName), nodes, recurse, limit); -} -/** - * @category Legacy Query Functions - * @param type Element type to look for. - * @param nodes Nodes to search through. - * @param recurse Also consider child nodes. - * @param limit Maximum number of nodes to return. - * @returns All nodes with the supplied `type`. - */ -function getElementsByTagType(type, nodes, recurse = true, limit = Infinity) { - return filter(Checks["tag_type"](type), nodes, recurse, limit); -} - -/** - * Given an array of nodes, remove any member that is contained by another. - * - * @category Helpers - * @param nodes Nodes to filter. - * @returns Remaining nodes that aren't subtrees of each other. - */ -function removeSubsets$1(nodes) { - let idx = nodes.length; - /* - * Check if each node (or one of its ancestors) is already contained in the - * array. - */ - while (--idx >= 0) { - const node = nodes[idx]; - /* - * Remove the node if it is not unique. - * We are going through the array from the end, so we only - * have to check nodes that precede the node under consideration in the array. - */ - if (idx > 0 && nodes.lastIndexOf(node, idx - 1) >= 0) { - nodes.splice(idx, 1); - continue; - } - for (let ancestor = node.parent; ancestor; ancestor = ancestor.parent) { - if (nodes.includes(ancestor)) { - nodes.splice(idx, 1); - break; - } - } - } - return nodes; -} -/** - * @category Helpers - * @see {@link http://dom.spec.whatwg.org/#dom-node-comparedocumentposition} - */ -var DocumentPosition; -(function (DocumentPosition) { - DocumentPosition[(DocumentPosition["DISCONNECTED"] = 1)] = "DISCONNECTED"; - DocumentPosition[(DocumentPosition["PRECEDING"] = 2)] = "PRECEDING"; - DocumentPosition[(DocumentPosition["FOLLOWING"] = 4)] = "FOLLOWING"; - DocumentPosition[(DocumentPosition["CONTAINS"] = 8)] = "CONTAINS"; - DocumentPosition[(DocumentPosition["CONTAINED_BY"] = 16)] = "CONTAINED_BY"; -})(DocumentPosition || (DocumentPosition = {})); -/** - * Compare the position of one node against another node in any other document. - * The return value is a bitmask with the values from {@link DocumentPosition}. - * - * Document order: - * > There is an ordering, document order, defined on all the nodes in the - * > document corresponding to the order in which the first character of the - * > XML representation of each node occurs in the XML representation of the - * > document after expansion of general entities. Thus, the document element - * > node will be the first node. Element nodes occur before their children. - * > Thus, document order orders element nodes in order of the occurrence of - * > their start-tag in the XML (after expansion of entities). The attribute - * > nodes of an element occur after the element and before its children. The - * > relative order of attribute nodes is implementation-dependent. - * - * Source: - * http://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-document-order - * - * @category Helpers - * @param nodeA The first node to use in the comparison - * @param nodeB The second node to use in the comparison - * @returns A bitmask describing the input nodes' relative position. - * - * See http://dom.spec.whatwg.org/#dom-node-comparedocumentposition for - * a description of these values. - */ -function compareDocumentPosition(nodeA, nodeB) { - const aParents = []; - const bParents = []; - if (nodeA === nodeB) { - return 0; - } - let current = hasChildren(nodeA) ? nodeA : nodeA.parent; - while (current) { - aParents.unshift(current); - current = current.parent; - } - current = hasChildren(nodeB) ? nodeB : nodeB.parent; - while (current) { - bParents.unshift(current); - current = current.parent; - } - const maxIdx = Math.min(aParents.length, bParents.length); - let idx = 0; - while (idx < maxIdx && aParents[idx] === bParents[idx]) { - idx++; - } - if (idx === 0) { - return DocumentPosition.DISCONNECTED; - } - const sharedParent = aParents[idx - 1]; - const siblings = sharedParent.children; - const aSibling = aParents[idx]; - const bSibling = bParents[idx]; - if (siblings.indexOf(aSibling) > siblings.indexOf(bSibling)) { - if (sharedParent === nodeB) { - return DocumentPosition.FOLLOWING | DocumentPosition.CONTAINED_BY; - } - return DocumentPosition.FOLLOWING; - } - if (sharedParent === nodeA) { - return DocumentPosition.PRECEDING | DocumentPosition.CONTAINS; - } - return DocumentPosition.PRECEDING; -} -/** - * Sort an array of nodes based on their relative position in the document and - * remove any duplicate nodes. If the array contains nodes that do not belong to - * the same document, sort order is unspecified. - * - * @category Helpers - * @param nodes Array of DOM nodes. - * @returns Collection of unique nodes, sorted in document order. - */ -function uniqueSort(nodes) { - nodes = nodes.filter((node, i, arr) => !arr.includes(node, i + 1)); - nodes.sort((a, b) => { - const relative = compareDocumentPosition(a, b); - if (relative & DocumentPosition.PRECEDING) { - return -1; - } else if (relative & DocumentPosition.FOLLOWING) { - return 1; - } - return 0; - }); - return nodes; -} - -/** - * Get the feed object from the root of a DOM tree. - * - * @category Feeds - * @param doc - The DOM to to extract the feed from. - * @returns The feed. - */ -function getFeed(doc) { - const feedRoot = getOneElement(isValidFeed, doc); - return !feedRoot - ? null - : feedRoot.name === "feed" - ? getAtomFeed(feedRoot) - : getRssFeed(feedRoot); -} -/** - * Parse an Atom feed. - * - * @param feedRoot The root of the feed. - * @returns The parsed feed. - */ -function getAtomFeed(feedRoot) { - var _a; - const childs = feedRoot.children; - const feed = { - type: "atom", - items: getElementsByTagName("entry", childs).map((item) => { - var _a; - const { children } = item; - const entry = { media: getMediaElements(children) }; - addConditionally(entry, "id", "id", children); - addConditionally(entry, "title", "title", children); - const href = - (_a = getOneElement("link", children)) === null || _a === void 0 - ? void 0 - : _a.attribs["href"]; - if (href) { - entry.link = href; - } - const description = - fetch("summary", children) || fetch("content", children); - if (description) { - entry.description = description; - } - const pubDate = fetch("updated", children); - if (pubDate) { - entry.pubDate = new Date(pubDate); - } - return entry; - }) - }; - addConditionally(feed, "id", "id", childs); - addConditionally(feed, "title", "title", childs); - const href = - (_a = getOneElement("link", childs)) === null || _a === void 0 - ? void 0 - : _a.attribs["href"]; - if (href) { - feed.link = href; - } - addConditionally(feed, "description", "subtitle", childs); - const updated = fetch("updated", childs); - if (updated) { - feed.updated = new Date(updated); - } - addConditionally(feed, "author", "email", childs, true); - return feed; -} -/** - * Parse a RSS feed. - * - * @param feedRoot The root of the feed. - * @returns The parsed feed. - */ -function getRssFeed(feedRoot) { - var _a, _b; - const childs = - (_b = - (_a = getOneElement("channel", feedRoot.children)) === null || - _a === void 0 - ? void 0 - : _a.children) !== null && _b !== void 0 - ? _b - : []; - const feed = { - type: feedRoot.name.substr(0, 3), - id: "", - items: getElementsByTagName("item", feedRoot.children).map((item) => { - const { children } = item; - const entry = { media: getMediaElements(children) }; - addConditionally(entry, "id", "guid", children); - addConditionally(entry, "title", "title", children); - addConditionally(entry, "link", "link", children); - addConditionally(entry, "description", "description", children); - const pubDate = fetch("pubDate", children); - if (pubDate) entry.pubDate = new Date(pubDate); - return entry; - }) - }; - addConditionally(feed, "title", "title", childs); - addConditionally(feed, "link", "link", childs); - addConditionally(feed, "description", "description", childs); - const updated = fetch("lastBuildDate", childs); - if (updated) { - feed.updated = new Date(updated); - } - addConditionally(feed, "author", "managingEditor", childs, true); - return feed; -} -const MEDIA_KEYS_STRING = ["url", "type", "lang"]; -const MEDIA_KEYS_INT = [ - "fileSize", - "bitrate", - "framerate", - "samplingrate", - "channels", - "duration", - "height", - "width" -]; -/** - * Get all media elements of a feed item. - * - * @param where Nodes to search in. - * @returns Media elements. - */ -function getMediaElements(where) { - return getElementsByTagName("media:content", where).map((elem) => { - const { attribs } = elem; - const media = { - medium: attribs["medium"], - isDefault: !!attribs["isDefault"] - }; - for (const attrib of MEDIA_KEYS_STRING) { - if (attribs[attrib]) { - media[attrib] = attribs[attrib]; - } - } - for (const attrib of MEDIA_KEYS_INT) { - if (attribs[attrib]) { - media[attrib] = parseInt(attribs[attrib], 10); - } - } - if (attribs["expression"]) { - media.expression = attribs["expression"]; - } - return media; - }); -} -/** - * Get one element by tag name. - * - * @param tagName Tag name to look for - * @param node Node to search in - * @returns The element or null - */ -function getOneElement(tagName, node) { - return getElementsByTagName(tagName, node, true, 1)[0]; -} -/** - * Get the text content of an element with a certain tag name. - * - * @param tagName Tag name to look for. - * @param where Node to search in. - * @param recurse Whether to recurse into child nodes. - * @returns The text content of the element. - */ -function fetch(tagName, where, recurse = false) { - return textContent(getElementsByTagName(tagName, where, recurse, 1)).trim(); -} -/** - * Adds a property to an object if it has a value. - * - * @param obj Object to be extended - * @param prop Property name - * @param tagName Tag name that contains the conditionally added property - * @param where Element to search for the property - * @param recurse Whether to recurse into child nodes. - */ -function addConditionally(obj, prop, tagName, where, recurse = false) { - const val = fetch(tagName, where, recurse); - if (val) obj[prop] = val; -} -/** - * Checks if an element is a feed root node. - * - * @param value The name of the element to check. - * @returns Whether an element is a feed root node. - */ -function isValidFeed(value) { - return value === "rss" || value === "feed" || value === "rdf:RDF"; -} - -var DomUtils = /*#__PURE__*/ Object.freeze({ - __proto__: null, - isTag: isTag$1, - isCDATA: isCDATA, - isText: isText, - isComment: isComment, - isDocument: isDocument, - hasChildren: hasChildren, - getOuterHTML: getOuterHTML, - getInnerHTML: getInnerHTML, - getText: getText$1, - textContent: textContent, - innerText: innerText, - getChildren: getChildren$1, - getParent: getParent$1, - getSiblings: getSiblings$1, - getAttributeValue: getAttributeValue$1, - hasAttrib: hasAttrib$1, - getName: getName$1, - nextElementSibling: nextElementSibling$1, - prevElementSibling: prevElementSibling, - removeElement: removeElement, - replaceElement: replaceElement, - appendChild: appendChild, - append: append$2, - prependChild: prependChild, - prepend: prepend, - filter: filter, - find: find, - findOneChild: findOneChild, - findOne: findOne$1, - existsOne: existsOne$1, - findAll: findAll$1, - testElement: testElement, - getElements: getElements, - getElementById: getElementById, - getElementsByTagName: getElementsByTagName, - getElementsByTagType: getElementsByTagType, - removeSubsets: removeSubsets$1, - get DocumentPosition() { - return DocumentPosition; - }, - compareDocumentPosition: compareDocumentPosition, - uniqueSort: uniqueSort, - getFeed: getFeed -}); - -// Helper methods -/** - * Parses the data, returns the resulting document. - * - * @param data The data that should be parsed. - * @param options Optional options for the parser and DOM builder. - */ -function parseDocument(data, options) { - const handler = new DomHandler(undefined, options); - new Parser$1(handler, options).end(data); - return handler.root; -} -/** - * Parses data, returns an array of the root nodes. - * - * Note that the root nodes still have a `Document` node as their parent. - * Use `parseDocument` to get the `Document` node instead. - * - * @param data The data that should be parsed. - * @param options Optional options for the parser and DOM builder. - * @deprecated Use `parseDocument` instead. - */ -function parseDOM(data, options) { - return parseDocument(data, options).children; -} -/** - * Creates a parser instance, with an attached DOM handler. - * - * @param cb A callback that will be called once parsing has been completed. - * @param options Optional options for the parser and DOM builder. - * @param elementCb An optional callback that will be called every time a tag has been completed inside of the DOM. - */ -function createDomStream(cb, options, elementCb) { - const handler = new DomHandler(cb, options, elementCb); - return new Parser$1(handler, options); -} -/** - * Parse a feed. - * - * @param feed The feed that should be parsed, as a string. - * @param options Optionally, options for parsing. When using this, you should set `xmlMode` to `true`. - */ -function parseFeed(feed, options = { xmlMode: true }) { - return getFeed(parseDOM(feed, options)); -} var HTMLParser2 = /*#__PURE__*/ Object.freeze({ __proto__: null, Parser: Parser$1, - DomHandler: DomHandler, - parseDocument: parseDocument, - parseDOM: parseDOM, - createDomStream: createDomStream, - ElementType: index, - getFeed: getFeed, - parseFeed: parseFeed, - DefaultHandler: DomHandler, - Tokenizer: Tokenizer, - DomUtils: DomUtils + get QuoteType() { + return QuoteType; + }, + Tokenizer: Tokenizer }); // Internal @@ -3527,6 +2040,7 @@ const NODE_END = -1; const ELEMENT_NODE = 1; const ATTRIBUTE_NODE = 2; const TEXT_NODE = 3; +const CDATA_SECTION_NODE = 4; const COMMENT_NODE = 8; const DOCUMENT_NODE = 9; const DOCUMENT_TYPE_NODE = 10; @@ -3570,6 +2084,7 @@ const BLOCK_ELEMENTS = new Set([ const SHOW_ALL = -1; const SHOW_ELEMENT = 1; const SHOW_TEXT = 4; +const SHOW_CDATA_SECTION = 8; const SHOW_COMMENT = 128; // Document position @@ -3588,7 +2103,6 @@ const { create: create$1, defineProperties, entries, - getOwnPropertyDescriptors, keys, setPrototypeOf } = Object; @@ -3628,6 +2142,30 @@ const setAdjacent = (prev, next) => { if (next) next[PREV] = prev; }; +/** + * @param {import("../interface/document.js").Document} ownerDocument + * @param {string} html + * @return {import("../interface/document-fragment.js").DocumentFragment} + */ +const htmlToFragment = (ownerDocument, html) => { + const fragment = ownerDocument.createDocumentFragment(); + + const elem = ownerDocument.createElement(""); + elem.innerHTML = html; + const { firstChild, lastChild } = elem; + + if (firstChild) { + knownSegment(fragment, firstChild, lastChild, fragment[END]); + + let child = firstChild; + do { + child.parentNode = fragment; + } while (child !== lastChild && (child = getEnd(child)[NEXT])); + } + + return fragment; +}; + const shadowRoots = new WeakMap(); let reactive = false; @@ -3811,11 +2349,23 @@ class CustomElementRegistry { const info = this.registry.get(localName); return info && info.Class; } + + /** + * @param {Function} Class **Class** of custom element + * @returns {string?} found tag name or null + */ + getName(Class) { + if (Classes.has(Class)) { + const { localName } = Classes.get(Class); + return localName; + } + return null; + } } const { Parser } = HTMLParser2; -const append$1 = (self, node, active) => { +const append$2 = (self, node, active) => { const end = self[END]; node.parentNode = self; knownBoundaries(end[PREV], node, end); @@ -3836,6 +2386,7 @@ const parseFromString = (document, isHTML, markupLanguage) => { let node = document; let ownerSVGElement = null; + let parsingCData = false; const content = new Parser( { @@ -3850,7 +2401,7 @@ const parseFromString = (document, isHTML, markupLanguage) => { let create = true; if (isHTML) { if (ownerSVGElement) { - node = append$1( + node = append$2( node, document.createElementNS(SVG_NAMESPACE, name), active @@ -3859,20 +2410,20 @@ const parseFromString = (document, isHTML, markupLanguage) => { create = false; } else if (name === "svg" || name === "SVG") { ownerSVGElement = document.createElementNS(SVG_NAMESPACE, name); - node = append$1(node, ownerSVGElement, active); + node = append$2(node, ownerSVGElement, active); create = false; } else if (active) { const ce = name.includes("-") ? name : attributes.is || ""; if (ce && registry.has(ce)) { const { Class } = registry.get(ce); - node = append$1(node, new Class(), active); + node = append$2(node, new Class(), active); delete attributes.is; create = false; } } } - if (create) node = append$1(node, document.createElement(name), false); + if (create) node = append$2(node, document.createElement(name), false); let end = node[END]; for (const name of keys(attributes)) @@ -3887,10 +2438,22 @@ const parseFromString = (document, isHTML, markupLanguage) => { // #text, #comment oncomment(data) { - append$1(node, document.createComment(data), active); + append$2(node, document.createComment(data), active); }, ontext(text) { - append$1(node, document.createTextNode(text), active); + if (parsingCData) { + append$2(node, document.createCDATASection(text), active); + } else { + append$2(node, document.createTextNode(text), active); + } + }, + + // #cdata + oncdatastart() { + parsingCData = true; + }, + oncdataend() { + parsingCData = false; }, // </tagName> @@ -3921,8 +2484,6 @@ const registerHTMLClass = (names, Class) => { } }; -const performance = globalThis.performance; - const loopSegment = ({ [NEXT]: next, [END]: end }, json) => { while (next !== end) { switch (next.nodeType) { @@ -3931,6 +2492,7 @@ const loopSegment = ({ [NEXT]: next, [END]: end }, json) => { break; case TEXT_NODE: case COMMENT_NODE: + case CDATA_SECTION_NODE: characterDataAsJSON(next, json); break; case ELEMENT_NODE: @@ -3979,6 +2541,7 @@ const elementAsJSON = (element, json) => { const createRecord = ( type, target, + element, addedNodes, removedNodes, attributeName, @@ -3989,7 +2552,9 @@ const createRecord = ( addedNodes, removedNodes, attributeName, - oldValue + oldValue, + previousSibling: element?.previousSibling || null, + nextSibling: element?.nextSibling || null }); const queueAttribute = ( @@ -4006,6 +2571,7 @@ const queueAttribute = ( createRecord( "attributes", target, + null, [], [], attributeName, @@ -4076,10 +2642,12 @@ const moCallback = (element, parentNode) => { if ( (parentNode && (target === parentNode || - (subtree && target.contains(parentNode)))) || + /* c8 ignore next */ (subtree && + target.contains(parentNode)))) || (!parentNode && ((subtree && - (target === ownerDocument || target.contains(element))) || + (target === ownerDocument || + /* c8 ignore next */ target.contains(element))) || (!subtree && target[characterData ? "childNodes" : "children"].includes( element @@ -4090,6 +2658,7 @@ const moCallback = (element, parentNode) => { createRecord( "childList", target, + element, parentNode ? [] : [element], parentNode ? [element] : [] ) @@ -4383,7 +2952,7 @@ const getParentNodeCount = ({ parentNode }) => { /** * @implements globalThis.Node */ -class Node$1 extends DOMEventTarget { +let Node$1 = class Node extends DOMEventTarget { static get ELEMENT_NODE() { return ELEMENT_NODE; } @@ -4393,6 +2962,9 @@ class Node$1 extends DOMEventTarget { static get TEXT_NODE() { return TEXT_NODE; } + static get CDATA_SECTION_NODE() { + return CDATA_SECTION_NODE; + } static get COMMENT_NODE() { return COMMENT_NODE; } @@ -4425,6 +2997,9 @@ class Node$1 extends DOMEventTarget { get TEXT_NODE() { return TEXT_NODE; } + get CDATA_SECTION_NODE() { + return CDATA_SECTION_NODE; + } get COMMENT_NODE() { return COMMENT_NODE; } @@ -4600,21 +3175,49 @@ class Node$1 extends DOMEventTarget { return this.parentNode; } + /** + * Calling it on an element inside a standard web page will return an HTMLDocument object representing the entire page (or <iframe>). + * Calling it on an element inside a shadow DOM will return the associated ShadowRoot. + * @return {ShadowRoot | HTMLDocument} + */ getRootNode() { let root = this; while (root.parentNode) root = root.parentNode; - return root.nodeType === DOCUMENT_NODE ? root.documentElement : root; + return root; } -} +}; + +const { replace } = ""; + +// escape +const ca = /[<>&\xA0]/g; + +const esca = { + "\xA0": " ", + "&": "&", + "<": "<", + ">": ">" +}; + +const pe = (m) => esca[m]; + +/** + * Safely escape HTML entities such as `&`, `<`, `>` only. + * @param {string} es the input to safely escape + * @returns {string} the escaped input, and it **throws** an error if + * the input type is unexpected, except for boolean and numbers, + * converted as string. + */ +const escape = (es) => replace.call(es, ca, pe); const QUOTE = /"/g; /** * @implements globalThis.Attr */ -class Attr$1 extends Node$1 { +let Attr$1 = class Attr extends Node$1 { constructor(ownerDocument, name, value = "") { - super(ownerDocument, "#attribute", ATTRIBUTE_NODE); + super(ownerDocument, name, ATTRIBUTE_NODE); this.ownerElement = null; this.name = $String(name); this[VALUE] = $String(value); @@ -4636,14 +3239,19 @@ class Attr$1 extends Node$1 { cloneNode() { const { ownerDocument, name, [VALUE]: value } = this; - return new Attr$1(ownerDocument, name, value); + return new Attr(ownerDocument, name, value); } toString() { const { name, [VALUE]: value } = this; - return emptyAttributes.has(name) && !value - ? name - : `${name}="${value.replace(QUOTE, """)}"`; + if (emptyAttributes.has(name) && !value) { + return ignoreCase(this) ? name : `${name}=""`; + } + const escapedValue = (ignoreCase(this) ? value : escape(value)).replace( + QUOTE, + """ + ); + return `${name}="${escapedValue}"`; } toJSON() { @@ -4651,7 +3259,7 @@ class Attr$1 extends Node$1 { attrAsJSON(this, json); return json; } -} +}; const isConnected = ({ ownerDocument, parentNode }) => { while (parentNode) { @@ -4678,6 +3286,7 @@ const previousSibling = ({ [PREV]: prev }) => { return prev[START]; case TEXT_NODE: case COMMENT_NODE: + case CDATA_SECTION_NODE: return prev; } return null; @@ -4689,8 +3298,9 @@ const nextSibling = (node) => { }; // https://dom.spec.whatwg.org/#nondocumenttypechildnode +// CharacterData, Element -const nextElementSibling = (node) => { +const nextElementSibling$1 = (node) => { let next = nextSibling(node); while (next && next.nodeType !== ELEMENT_NODE) next = nextSibling(next); return next; @@ -4703,6 +3313,7 @@ const previousElementSibling = (node) => { }; // https://dom.spec.whatwg.org/#childnode +// CharacterData, DocumentType, Element const asFragment = (ownerDocument, nodes) => { const fragment = ownerDocument.createDocumentFragment(); @@ -4728,6 +3339,7 @@ const after = (node, nodes) => { const replaceWith = (node, nodes) => { const { ownerDocument, parentNode } = node; if (parentNode) { + if (nodes.includes(node)) replaceWith(node, [(node = node.cloneNode())]); parentNode.insertBefore(asFragment(ownerDocument, nodes), node); node.remove(); } @@ -4752,7 +3364,7 @@ const remove = (prev, current, next) => { /** * @implements globalThis.CharacterData */ -class CharacterData$1 extends Node$1 { +let CharacterData$1 = class CharacterData extends Node$1 { constructor(ownerDocument, localName, nodeType, data) { super(ownerDocument, localName, nodeType); this[VALUE] = $String(data); @@ -4776,7 +3388,7 @@ class CharacterData$1 extends Node$1 { return previousElementSibling(this); } get nextElementSibling() { - return nextElementSibling(this); + return nextElementSibling$1(this); } before(...nodes) { @@ -4850,41 +3462,52 @@ class CharacterData$1 extends Node$1 { characterDataAsJSON(this, json); return json; } -} +}; + +/** + * @implements globalThis.CDATASection + */ +let CDATASection$1 = class CDATASection extends CharacterData$1 { + constructor(ownerDocument, data = "") { + super(ownerDocument, "#cdatasection", CDATA_SECTION_NODE, data); + } + + cloneNode() { + const { ownerDocument, [VALUE]: data } = this; + return new CDATASection(ownerDocument, data); + } + + toString() { + return `<![CDATA[${this[VALUE]}]]>`; + } +}; /** * @implements globalThis.Comment */ -class Comment$1 extends CharacterData$1 { +let Comment$2 = class Comment extends CharacterData$1 { constructor(ownerDocument, data = "") { super(ownerDocument, "#comment", COMMENT_NODE, data); } cloneNode() { const { ownerDocument, [VALUE]: data } = this; - return new Comment$1(ownerDocument, data); + return new Comment(ownerDocument, data); } toString() { return `<!--${this[VALUE]}-->`; } -} - -function getDefaultExportFromCjs(x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") - ? x["default"] - : x; -} - -var boolbase = { - trueFunc: function trueFunc() { - return true; - }, - falseFunc: function falseFunc() { - return false; - } }; +function trueFunc() { + return true; +} +function falseFunc() { + return false; +} + +/** Discriminants for selector token kinds. */ var SelectorType; (function (SelectorType) { SelectorType["Attribute"] = "attribute"; @@ -4900,6 +3523,7 @@ var SelectorType; SelectorType["Sibling"] = "sibling"; SelectorType["ColumnCombinator"] = "column-combinator"; })(SelectorType || (SelectorType = {})); +/** Operators available for attribute selectors. */ var AttributeAction; (function (AttributeAction) { AttributeAction["Any"] = "any"; @@ -4912,15 +3536,49 @@ var AttributeAction; AttributeAction["Start"] = "start"; })(AttributeAction || (AttributeAction = {})); -const reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/; +const reName = /^[^#\\]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\u00B0-\uFFFF-])+/; const reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi; +var CharCode; +(function (CharCode) { + CharCode[(CharCode["LeftParenthesis"] = 40)] = "LeftParenthesis"; + CharCode[(CharCode["RightParenthesis"] = 41)] = "RightParenthesis"; + CharCode[(CharCode["LeftSquareBracket"] = 91)] = "LeftSquareBracket"; + CharCode[(CharCode["RightSquareBracket"] = 93)] = "RightSquareBracket"; + CharCode[(CharCode["Comma"] = 44)] = "Comma"; + CharCode[(CharCode["Period"] = 46)] = "Period"; + CharCode[(CharCode["Colon"] = 58)] = "Colon"; + CharCode[(CharCode["SingleQuote"] = 39)] = "SingleQuote"; + CharCode[(CharCode["DoubleQuote"] = 34)] = "DoubleQuote"; + CharCode[(CharCode["Plus"] = 43)] = "Plus"; + CharCode[(CharCode["Tilde"] = 126)] = "Tilde"; + CharCode[(CharCode["QuestionMark"] = 63)] = "QuestionMark"; + CharCode[(CharCode["ExclamationMark"] = 33)] = "ExclamationMark"; + CharCode[(CharCode["Slash"] = 47)] = "Slash"; + CharCode[(CharCode["Equal"] = 61)] = "Equal"; + CharCode[(CharCode["Dollar"] = 36)] = "Dollar"; + CharCode[(CharCode["Pipe"] = 124)] = "Pipe"; + CharCode[(CharCode["Circumflex"] = 94)] = "Circumflex"; + CharCode[(CharCode["Asterisk"] = 42)] = "Asterisk"; + CharCode[(CharCode["GreaterThan"] = 62)] = "GreaterThan"; + CharCode[(CharCode["LessThan"] = 60)] = "LessThan"; + CharCode[(CharCode["Hash"] = 35)] = "Hash"; + CharCode[(CharCode["LowerI"] = 105)] = "LowerI"; + CharCode[(CharCode["LowerS"] = 115)] = "LowerS"; + CharCode[(CharCode["BackSlash"] = 92)] = "BackSlash"; + // Whitespace + CharCode[(CharCode["Space"] = 32)] = "Space"; + CharCode[(CharCode["Tab"] = 9)] = "Tab"; + CharCode[(CharCode["NewLine"] = 10)] = "NewLine"; + CharCode[(CharCode["FormFeed"] = 12)] = "FormFeed"; + CharCode[(CharCode["CarriageReturn"] = 13)] = "CarriageReturn"; +})(CharCode || (CharCode = {})); const actionTypes = new Map([ - [126 /* Tilde */, AttributeAction.Element], - [94 /* Circumflex */, AttributeAction.Start], - [36 /* Dollar */, AttributeAction.End], - [42 /* Asterisk */, AttributeAction.Any], - [33 /* ExclamationMark */, AttributeAction.Not], - [124 /* Pipe */, AttributeAction.Hyphen] + [CharCode.Tilde, AttributeAction.Element], + [CharCode.Circumflex, AttributeAction.Start], + [CharCode.Dollar, AttributeAction.End], + [CharCode.Asterisk, AttributeAction.Any], + [CharCode.ExclamationMark, AttributeAction.Not], + [CharCode.Pipe, AttributeAction.Hyphen] ]); // Pseudos, whose data property is parsed as well. const unpackPseudos = new Set([ @@ -4932,11 +3590,21 @@ const unpackPseudos = new Set([ "host", "host-context" ]); +/** + * Pseudo elements defined in CSS Level 1 and CSS Level 2 can be written with + * a single colon; eg. :before will turn into ::before. + * @see {@link https://www.w3.org/TR/2018/WD-selectors-4-20181121/#pseudo-element-syntax} + */ +const pseudosToPseudoElements = new Set([ + "before", + "after", + "first-line", + "first-letter" +]); /** * Checks whether a specific selector is a traversal. * This is useful eg. in swapping the order of elements that * are not traversals. - * * @param selector Selector to check. */ function isTraversal$1(selector) { @@ -4946,50 +3614,54 @@ function isTraversal$1(selector) { case SelectorType.Descendant: case SelectorType.Parent: case SelectorType.Sibling: - case SelectorType.ColumnCombinator: + case SelectorType.ColumnCombinator: { return true; - default: + } + case SelectorType.Attribute: + case SelectorType.Pseudo: + case SelectorType.PseudoElement: + case SelectorType.Tag: + case SelectorType.Universal: { return false; + } } } const stripQuotesFromPseudos = new Set(["contains", "icontains"]); // Unescape function taken from https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L152 function funescape(_, escaped, escapedWhitespace) { - const high = parseInt(escaped, 16) - 0x10000; + const high = Number.parseInt(escaped, 16) - 0x1_00_00; // NaN means non-codepoint - return high !== high || escapedWhitespace + return Number.isNaN(high) || escapedWhitespace ? escaped : high < 0 - ? // BMP codepoint - String.fromCharCode(high + 0x10000) - : // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode((high >> 10) | 0xd800, (high & 0x3ff) | 0xdc00); + ? // BMP codepoint + String.fromCharCode(high + 0x1_00_00) + : // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode((high >> 10) | 0xd8_00, (high & 0x3_ff) | 0xdc_00); } -function unescapeCSS(str) { - return str.replace(reEscape, funescape); +function unescapeCSS(cssString) { + return cssString.replace(reEscape, funescape); } function isQuote(c) { - return c === 39 /* SingleQuote */ || c === 34 /* DoubleQuote */; + return c === CharCode.SingleQuote || c === CharCode.DoubleQuote; } function isWhitespace(c) { return ( - c === 32 /* Space */ || - c === 9 /* Tab */ || - c === 10 /* NewLine */ || - c === 12 /* FormFeed */ || - c === 13 /* CarriageReturn */ + c === CharCode.Space || + c === CharCode.Tab || + c === CharCode.NewLine || + c === CharCode.FormFeed || + c === CharCode.CarriageReturn ); } /** - * Parses `selector`, optionally with the passed `options`. - * + * Parses `selector`. * @param selector Selector to parse. - * @param options Options for parsing. * @returns Returns a two-dimensional array. * The first dimension represents selectors separated by commas (eg. `sub1, sub2`), * the second contains the relevant tokens for that selector. */ -function parse$5(selector) { +function parse$3(selector) { const subselects = []; const endIndex = parseSelector(subselects, `${selector}`, 0); if (endIndex < selector.length) { @@ -5020,29 +3692,27 @@ function parseSelector(subselects, selector, selectorIndex) { function readValueWithParenthesis() { selectorIndex += 1; const start = selectorIndex; - let counter = 1; - for (; counter > 0 && selectorIndex < selector.length; selectorIndex++) { - if ( - selector.charCodeAt(selectorIndex) === 40 /* LeftParenthesis */ && - !isEscaped(selectorIndex) - ) { - counter++; - } else if ( - selector.charCodeAt(selectorIndex) === 41 /* RightParenthesis */ && - !isEscaped(selectorIndex) - ) { - counter--; + for (let counter = 1; selectorIndex < selector.length; selectorIndex++) { + switch (selector.charCodeAt(selectorIndex)) { + case CharCode.BackSlash: { + // Skip next character + selectorIndex += 1; + break; + } + case CharCode.LeftParenthesis: { + counter += 1; + break; + } + case CharCode.RightParenthesis: { + counter -= 1; + if (counter === 0) { + return unescapeCSS(selector.slice(start, selectorIndex++)); + } + break; + } } } - if (counter) { - throw new Error("Parenthesis not matched"); - } - return unescapeCSS(selector.slice(start, selectorIndex - 1)); - } - function isEscaped(pos) { - let slashCount = 0; - while (selector.charCodeAt(--pos) === 92 /* BackSlash */) slashCount++; - return (slashCount & 1) === 1; + throw new Error("Parenthesis not matched"); } function ensureNotTraversal() { if (tokens.length > 0 && isTraversal$1(tokens[tokens.length - 1])) { @@ -5079,7 +3749,7 @@ function parseSelector(subselects, selector, selectorIndex) { */ function finalizeSubselector() { if ( - tokens.length && + tokens.length > 0 && tokens[tokens.length - 1].type === SelectorType.Descendant ) { tokens.pop(); @@ -5097,11 +3767,11 @@ function parseSelector(subselects, selector, selectorIndex) { const firstChar = selector.charCodeAt(selectorIndex); switch (firstChar) { // Whitespace - case 32 /* Space */: - case 9 /* Tab */: - case 10 /* NewLine */: - case 12 /* FormFeed */: - case 13 /* CarriageReturn */: { + case CharCode.Space: + case CharCode.Tab: + case CharCode.NewLine: + case CharCode.FormFeed: + case CharCode.CarriageReturn: { if (tokens.length === 0 || tokens[0].type !== SelectorType.Descendant) { ensureNotTraversal(); tokens.push({ type: SelectorType.Descendant }); @@ -5110,41 +3780,41 @@ function parseSelector(subselects, selector, selectorIndex) { break; } // Traversals - case 62 /* GreaterThan */: { + case CharCode.GreaterThan: { addTraversal(SelectorType.Child); stripWhitespace(1); break; } - case 60 /* LessThan */: { + case CharCode.LessThan: { addTraversal(SelectorType.Parent); stripWhitespace(1); break; } - case 126 /* Tilde */: { + case CharCode.Tilde: { addTraversal(SelectorType.Sibling); stripWhitespace(1); break; } - case 43 /* Plus */: { + case CharCode.Plus: { addTraversal(SelectorType.Adjacent); stripWhitespace(1); break; } // Special attribute selectors: .class, #id - case 46 /* Period */: { + case CharCode.Period: { addSpecialAttribute("class", AttributeAction.Element); break; } - case 35 /* Hash */: { + case CharCode.Hash: { addSpecialAttribute("id", AttributeAction.Equals); break; } - case 91 /* LeftSquareBracket */: { + case CharCode.LeftSquareBracket: { stripWhitespace(1); // Determine attribute name and namespace let name; let namespace = null; - if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */) { + if (selector.charCodeAt(selectorIndex) === CharCode.Pipe) { // Equivalent to no namespace name = getName(1); } else if (selector.startsWith("*|", selectorIndex)) { @@ -5153,8 +3823,8 @@ function parseSelector(subselects, selector, selectorIndex) { } else { name = getName(0); if ( - selector.charCodeAt(selectorIndex) === 124 /* Pipe */ && - selector.charCodeAt(selectorIndex + 1) !== 61 /* Equal */ + selector.charCodeAt(selectorIndex) === CharCode.Pipe && + selector.charCodeAt(selectorIndex + 1) !== CharCode.Equal ) { namespace = name; name = getName(1); @@ -5168,11 +3838,11 @@ function parseSelector(subselects, selector, selectorIndex) { ); if (possibleAction) { action = possibleAction; - if (selector.charCodeAt(selectorIndex + 1) !== 61 /* Equal */) { + if (selector.charCodeAt(selectorIndex + 1) !== CharCode.Equal) { throw new Error("Expected `=`"); } stripWhitespace(2); - } else if (selector.charCodeAt(selectorIndex) === 61 /* Equal */) { + } else if (selector.charCodeAt(selectorIndex) === CharCode.Equal) { action = AttributeAction.Equals; stripWhitespace(1); } @@ -5182,46 +3852,56 @@ function parseSelector(subselects, selector, selectorIndex) { if (action !== "exists") { if (isQuote(selector.charCodeAt(selectorIndex))) { const quote = selector.charCodeAt(selectorIndex); - let sectionEnd = selectorIndex + 1; + selectorIndex += 1; + const sectionStart = selectorIndex; while ( - sectionEnd < selector.length && - (selector.charCodeAt(sectionEnd) !== quote || - isEscaped(sectionEnd)) + selectorIndex < selector.length && + selector.charCodeAt(selectorIndex) !== quote ) { - sectionEnd += 1; + selectorIndex += + // Skip next character if it is escaped + selector.charCodeAt(selectorIndex) === CharCode.BackSlash + ? 2 + : 1; } - if (selector.charCodeAt(sectionEnd) !== quote) { + if (selector.charCodeAt(selectorIndex) !== quote) { throw new Error("Attribute value didn't end"); } - value = unescapeCSS(selector.slice(selectorIndex + 1, sectionEnd)); - selectorIndex = sectionEnd + 1; + value = unescapeCSS(selector.slice(sectionStart, selectorIndex)); + selectorIndex += 1; } else { const valueStart = selectorIndex; while ( selectorIndex < selector.length && - ((!isWhitespace(selector.charCodeAt(selectorIndex)) && - selector.charCodeAt(selectorIndex) !== - 93) /* RightSquareBracket */ || - isEscaped(selectorIndex)) + !isWhitespace(selector.charCodeAt(selectorIndex)) && + selector.charCodeAt(selectorIndex) !== CharCode.RightSquareBracket ) { - selectorIndex += 1; + selectorIndex += + // Skip next character if it is escaped + selector.charCodeAt(selectorIndex) === CharCode.BackSlash + ? 2 + : 1; } value = unescapeCSS(selector.slice(valueStart, selectorIndex)); } stripWhitespace(0); // See if we have a force ignore flag - const forceIgnore = selector.charCodeAt(selectorIndex) | 0x20; - // If the forceIgnore flag is set (either `i` or `s`), use that value - if (forceIgnore === 115 /* LowerS */) { - ignoreCase = false; - stripWhitespace(1); - } else if (forceIgnore === 105 /* LowerI */) { - ignoreCase = true; - stripWhitespace(1); + switch (selector.charCodeAt(selectorIndex) | 0x20) { + // If the forceIgnore flag is set (either `i` or `s`), use that value + case CharCode.LowerI: { + ignoreCase = true; + stripWhitespace(1); + break; + } + case CharCode.LowerS: { + ignoreCase = false; + stripWhitespace(1); + break; + } } } if ( - selector.charCodeAt(selectorIndex) !== 93 /* RightSquareBracket */ + selector.charCodeAt(selectorIndex) !== CharCode.RightSquareBracket ) { throw new Error("Attribute selector didn't terminate"); } @@ -5237,21 +3917,29 @@ function parseSelector(subselects, selector, selectorIndex) { tokens.push(attributeSelector); break; } - case 58 /* Colon */: { - if (selector.charCodeAt(selectorIndex + 1) === 58 /* Colon */) { + case CharCode.Colon: { + if (selector.charCodeAt(selectorIndex + 1) === CharCode.Colon) { tokens.push({ type: SelectorType.PseudoElement, name: getName(2).toLowerCase(), data: - selector.charCodeAt(selectorIndex) === 40 /* LeftParenthesis */ + selector.charCodeAt(selectorIndex) === CharCode.LeftParenthesis ? readValueWithParenthesis() : null }); - continue; + break; } const name = getName(1).toLowerCase(); + if (pseudosToPseudoElements.has(name)) { + tokens.push({ + type: SelectorType.PseudoElement, + name, + data: null + }); + break; + } let data = null; - if (selector.charCodeAt(selectorIndex) === 40 /* LeftParenthesis */) { + if (selector.charCodeAt(selectorIndex) === CharCode.LeftParenthesis) { if (unpackPseudos.has(name)) { if (isQuote(selector.charCodeAt(selectorIndex + 1))) { throw new Error(`Pseudo-selector ${name} cannot be quoted`); @@ -5259,7 +3947,7 @@ function parseSelector(subselects, selector, selectorIndex) { data = []; selectorIndex = parseSelector(data, selector, selectorIndex + 1); if ( - selector.charCodeAt(selectorIndex) !== 41 /* RightParenthesis */ + selector.charCodeAt(selectorIndex) !== CharCode.RightParenthesis ) { throw new Error( `Missing closing parenthesis in :${name} (${selector})` @@ -5280,7 +3968,7 @@ function parseSelector(subselects, selector, selectorIndex) { tokens.push({ type: SelectorType.Pseudo, name, data }); break; } - case 44 /* Comma */: { + case CharCode.Comma: { finalizeSubselector(); tokens = []; stripWhitespace(1); @@ -5289,7 +3977,7 @@ function parseSelector(subselects, selector, selectorIndex) { default: { if (selector.startsWith("/*", selectorIndex)) { const endIndex = selector.indexOf("*/", selectorIndex + 2); - if (endIndex < 0) { + if (endIndex === -1) { throw new Error("Comment was not terminated"); } selectorIndex = endIndex + 2; @@ -5301,12 +3989,12 @@ function parseSelector(subselects, selector, selectorIndex) { } let namespace = null; let name; - if (firstChar === 42 /* Asterisk */) { + if (firstChar === CharCode.Asterisk) { selectorIndex += 1; name = "*"; - } else if (firstChar === 124 /* Pipe */) { + } else if (firstChar === CharCode.Pipe) { name = ""; - if (selector.charCodeAt(selectorIndex + 1) === 124 /* Pipe */) { + if (selector.charCodeAt(selectorIndex + 1) === CharCode.Pipe) { addTraversal(SelectorType.ColumnCombinator); stripWhitespace(2); break; @@ -5317,11 +4005,11 @@ function parseSelector(subselects, selector, selectorIndex) { break loop; } if ( - selector.charCodeAt(selectorIndex) === 124 /* Pipe */ && - selector.charCodeAt(selectorIndex + 1) !== 124 /* Pipe */ + selector.charCodeAt(selectorIndex) === CharCode.Pipe && + selector.charCodeAt(selectorIndex + 1) !== CharCode.Pipe ) { namespace = name; - if (selector.charCodeAt(selectorIndex + 1) === 42 /* Asterisk */) { + if (selector.charCodeAt(selectorIndex + 1) === CharCode.Asterisk) { name = "*"; selectorIndex += 2; } else { @@ -5340,104 +4028,1492 @@ function parseSelector(subselects, selector, selectorIndex) { return selectorIndex; } -const attribValChars = ["\\", '"']; -const pseudoValChars = [...attribValChars, "(", ")"]; -new Set(attribValChars.map((c) => c.charCodeAt(0))); -new Set(pseudoValChars.map((c) => c.charCodeAt(0))); -new Set( - [ - ...pseudoValChars, - "~", - "^", - "$", - "*", - "+", - "!", - "|", - ":", - "[", - "]", - " ", - "." - ].map((c) => c.charCodeAt(0)) +/** Types of elements found in htmlparser2's DOM */ +var ElementType; +(function (ElementType) { + /** Type for the root element of a document */ + ElementType["Root"] = "root"; + /** Type for Text */ + ElementType["Text"] = "text"; + /** Type for <? ... ?> */ + ElementType["Directive"] = "directive"; + /** Type for <!-- ... --> */ + ElementType["Comment"] = "comment"; + /** Type for <script> tags */ + ElementType["Script"] = "script"; + /** Type for <style> tags */ + ElementType["Style"] = "style"; + /** Type for Any tag */ + ElementType["Tag"] = "tag"; + /** Type for <![CDATA[ ... ]]> */ + ElementType["CDATA"] = "cdata"; + /** Type for <!doctype ...> */ + ElementType["Doctype"] = "doctype"; +})(ElementType || (ElementType = {})); +/** + * Tests whether an element is a tag or not. + * @param element Element to test + * @param element.type Node type discriminator to check. + */ +function isTag$2(element) { + return ( + element.type === ElementType.Tag || + element.type === ElementType.Script || + element.type === ElementType.Style + ); +} +// Exports for backwards compatibility +/** Type for the root element of a document */ +// eslint-disable-next-line prefer-destructuring +const Root = ElementType.Root; +/** Type for Text */ +// eslint-disable-next-line prefer-destructuring +const Text$2 = ElementType.Text; +/** Type for <? ... ?> */ +// eslint-disable-next-line prefer-destructuring +const Directive = ElementType.Directive; +/** Type for <!-- ... --> */ +// eslint-disable-next-line prefer-destructuring +const Comment$1 = ElementType.Comment; +/** Type for <script> tags */ +// eslint-disable-next-line prefer-destructuring +const Script = ElementType.Script; +/** Type for <style> tags */ +// eslint-disable-next-line prefer-destructuring +const Style = ElementType.Style; +/** Type for Any tag */ +// eslint-disable-next-line prefer-destructuring +const Tag = ElementType.Tag; +/** Type for <![CDATA[ ... ]]> */ +// eslint-disable-next-line prefer-destructuring +const CDATA = ElementType.CDATA; +/** Type for <!doctype ...> */ +// eslint-disable-next-line prefer-destructuring +const Doctype = ElementType.Doctype; + +/** + * Checks if `node` is an element node. + * @param node Node to check. + * @returns `true` if the node is an element node. + */ +function isTag$1(node) { + return isTag$2(node); +} +/** + * Checks if `node` is a CDATA node. + * @param node Node to check. + * @returns `true` if the node is a CDATA node. + */ +function isCDATA(node) { + return node.type === ElementType.CDATA; +} +/** + * Checks if `node` is a text node. + * @param node Node to check. + * @returns `true` if the node is a text node. + */ +function isText(node) { + return node.type === ElementType.Text; +} +/** + * Checks if `node` is a comment node. + * @param node Node to check. + * @returns `true` if the node is a comment node. + */ +function isComment(node) { + return node.type === ElementType.Comment; +} +/** + * Checks if `node` has children. + * @param node Node to check. + * @returns `true` if the node has children. + */ +function hasChildren(node) { + return Object.hasOwn(node, "children"); +} + +/** + * Search a node and its children for nodes passing a test function. If `node` is not an array, it will be wrapped in one. + * + * @category Querying + * @param test Function to test nodes on. + * @param node Node to search. Will be included in the result set if it matches. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes passing `test`. + */ +function filter(test, node, recurse = true, limit = Number.POSITIVE_INFINITY) { + return find(test, Array.isArray(node) ? node : [node], recurse, limit); +} +/** + * Search an array of nodes and their children for nodes passing a test function. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes passing `test`. + */ +function find(test, nodes, recurse, limit) { + const result = []; + /** Stack of the arrays we are looking at. */ + const nodeStack = [Array.isArray(nodes) ? nodes : [nodes]]; + /** Stack of the indices within the arrays. */ + const indexStack = [0]; + for (;;) { + // First, check if the current array has any more elements to look at. + if (indexStack[0] >= nodeStack[0].length) { + // If we have no more arrays to look at, we are done. + if (indexStack.length === 1) { + return result; + } + // Otherwise, remove the current array from the stack. + nodeStack.shift(); + indexStack.shift(); + // Loop back to the start to continue with the next array. + continue; + } + const element = nodeStack[0][indexStack[0]++]; + if (test(element)) { + result.push(element); + if (--limit <= 0) return result; + } + if (recurse && hasChildren(element) && element.children.length > 0) { + /* + * Add the children to the stack. We are depth-first, so this is + * the next array we look at. + */ + indexStack.unshift(0); + nodeStack.unshift(element.children); + } + } +} +/** + * Finds one element in a tree that passes a test. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Node or array of nodes to search. + * @param recurse Also consider child nodes. + * @returns The first node that passes `test`. + */ +function findOne$2(test, nodes, recurse = true) { + const searchedNodes = Array.isArray(nodes) ? nodes : [nodes]; + for (const node of searchedNodes) { + if (isTag$1(node) && test(node)) { + return node; + } + if (recurse && hasChildren(node) && node.children.length > 0) { + const found = findOne$2(test, node.children, true); + if (found) return found; + } + } + return null; +} +/** + * Checks if a tree of nodes contains at least one node passing a test. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @returns Whether a tree of nodes contains at least one node passing the test. + */ +function existsOne$1(test, nodes) { + return (Array.isArray(nodes) ? nodes : [nodes]).some( + (node) => + (isTag$1(node) && test(node)) || + (hasChildren(node) && existsOne$1(test, node.children)) + ); +} +/** + * Search an array of nodes and their children for elements passing a test function. + * + * Same as `find`, but limited to elements and with less options, leading to reduced complexity. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @returns All nodes passing `test`. + */ +function findAll$1(test, nodes) { + const result = []; + const nodeStack = [Array.isArray(nodes) ? nodes : [nodes]]; + const indexStack = [0]; + for (;;) { + if (indexStack[0] >= nodeStack[0].length) { + if (nodeStack.length === 1) { + return result; + } + // Otherwise, remove the current array from the stack. + nodeStack.shift(); + indexStack.shift(); + // Loop back to the start to continue with the next array. + continue; + } + const element = nodeStack[0][indexStack[0]++]; + if (isTag$1(element) && test(element)) result.push(element); + if (hasChildren(element) && element.children.length > 0) { + indexStack.unshift(0); + nodeStack.unshift(element.children); + } + } +} + +/** + * A map of functions to check nodes against. + */ +const Checks = { + tag_name(name) { + if (typeof name === "function") { + return (element) => isTag$1(element) && name(element.name); + } + if (name === "*") { + return isTag$1; + } + return (element) => isTag$1(element) && element.name === name; + }, + tag_type(type) { + if (typeof type === "function") { + return (element) => type(element.type); + } + return (element) => element.type === type; + }, + tag_contains(data) { + if (typeof data === "function") { + return (element) => isText(element) && data(element.data); + } + return (element) => isText(element) && element.data === data; + } +}; +/** + * Returns a function to check whether a node has an attribute with a particular + * value. + * + * @param attrib Attribute to check. + * @param value Attribute value to look for. + * @returns A function to check whether the a node has an attribute with a + * particular value. + */ +function getAttribCheck(attrib, value) { + if (typeof value === "function") { + return (element) => isTag$1(element) && value(element.attribs[attrib]); + } + return (element) => isTag$1(element) && element.attribs[attrib] === value; +} +/** + * Returns a function that returns `true` if either of the input functions + * returns `true` for a node. + * + * @param a First function to combine. + * @param b Second function to combine. + * @returns A function taking a node and returning `true` if either of the input + * functions returns `true` for the node. + */ +function combineFuncs(a, b) { + return (element) => a(element) || b(element); +} +/** + * Returns a function that executes all checks in `options` and returns `true` + * if any of them match a node. + * + * @param options An object describing nodes to look for. + * @returns A function that executes all checks in `options` and returns `true` + * if any of them match a node. + */ +function compileTest(options) { + const funcs = Object.keys(options).map((key) => { + const value = options[key]; + return Object.hasOwn(Checks, key) + ? Checks[key](value) + : getAttribCheck(key, value); + }); + return funcs.length === 0 ? null : funcs.reduce(combineFuncs); +} +/** + * Checks whether a node matches the description in `options`. + * + * @category Legacy Query Functions + * @param options An object describing nodes to look for. + * @param node The element to test. + * @returns Whether the element matches the description in `options`. + */ +function testElement(options, node) { + const test = compileTest(options); + return test ? test(node) : true; +} +/** + * Returns all nodes that match `options`. + * + * @category Legacy Query Functions + * @param options An object describing nodes to look for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes that match `options`. + */ +function getElements( + options, + nodes, + recurse, + limit = Number.POSITIVE_INFINITY +) { + const test = compileTest(options); + return test ? filter(test, nodes, recurse, limit) : []; +} +/** + * Returns the node with the supplied ID. + * + * @category Legacy Query Functions + * @param id The unique ID attribute value to look for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @returns The node with the supplied ID. + */ +function getElementById(id, nodes, recurse = true) { + if (!Array.isArray(nodes)) nodes = [nodes]; + return findOne$2(getAttribCheck("id", id), nodes, recurse); +} +/** + * Returns all nodes with the supplied `tagName`. + * + * @category Legacy Query Functions + * @param tagName Tag name to search for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes with the supplied `tagName`. + */ +function getElementsByTagName( + tagName, + nodes, + recurse = true, + limit = Number.POSITIVE_INFINITY +) { + return filter(Checks["tag_name"](tagName), nodes, recurse, limit); +} +/** + * Returns all nodes with the supplied `className`. + * + * @category Legacy Query Functions + * @param className Class name to search for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes with the supplied `className`. + */ +function getElementsByClassName( + className, + nodes, + recurse = true, + limit = Number.POSITIVE_INFINITY +) { + return filter(getAttribCheck("class", className), nodes, recurse, limit); +} +/** + * Returns all nodes with the supplied `type`. + * + * @category Legacy Query Functions + * @param type Element type to look for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes with the supplied `type`. + */ +function getElementsByTagType( + type, + nodes, + recurse = true, + limit = Number.POSITIVE_INFINITY +) { + return filter(Checks["tag_type"](type), nodes, recurse, limit); +} + +const xmlCodeMap = new Map([ + [34, """], + [38, "&"], + [39, "'"], + [60, "<"], + [62, ">"] +]); +// For compatibility with node < 4, we wrap `codePointAt` +/** + * Read a code point at a given index. + * @param input Input string to encode or decode. + * @param index Current read position in the input string. + */ +const getCodePoint = + typeof String.prototype.codePointAt === "function" + ? (input, index) => input.codePointAt(index) + : // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + (c, index) => + (c.charCodeAt(index) & 0xfc_00) === 0xd8_00 + ? (c.charCodeAt(index) - 0xd8_00) * 0x4_00 + + c.charCodeAt(index + 1) - + 0xdc_00 + + 0x1_00_00 + : c.charCodeAt(index); +/** + * Bitset for ASCII characters that need to be escaped in XML. + */ +const XML_BITSET_VALUE = 0x50_00_00_c4; // 32..63 -> 34 ("),38 (&),39 ('),60 (<),62 (>) +/** + * Encodes all non-ASCII characters, as well as characters not valid in XML + * documents using XML entities. Uses a fast bitset scan instead of RegExp. + * + * If a character has no equivalent entity, a numeric hexadecimal reference + * (eg. `ü`) will be used. + * @param input Input string to encode or decode. + */ +function encodeXML(input) { + let out; + let last = 0; + const { length } = input; + for (let index = 0; index < length; index++) { + const char = input.charCodeAt(index); + // Check for ASCII chars that don't need escaping + if ( + char < 0x80 && + (((XML_BITSET_VALUE >>> char) & 1) === 0 || char >= 64 || char < 32) + ) { + continue; + } + if (out === undefined) out = input.substring(0, index); + else if (last !== index) out += input.substring(last, index); + if (char < 64) { + // Known replacement + out += xmlCodeMap.get(char); + last = index + 1; + continue; + } + // Non-ASCII: encode as numeric entity (handle surrogate pair) + const cp = getCodePoint(input, index); + out += `&#x${cp.toString(16)};`; + if (cp !== char) index++; // Skip trailing surrogate + last = index + 1; + } + if (out === undefined) return input; + if (last < length) out += input.substr(last); + return out; +} +/** + * Creates a function that escapes all characters matched by the given regular + * expression using the given map of characters to escape to their entities. + * @param regex Regular expression to match characters to escape. + * @param map Map of characters to escape to their entities. + * @returns Function that escapes all characters matched by the given regular + * expression using the given map of characters to escape to their entities. + */ +function getEscaper(regex, map) { + return function escape(data) { + let match; + let lastIndex = 0; + let result = ""; + while ((match = regex.exec(data))) { + if (lastIndex !== match.index) { + result += data.substring(lastIndex, match.index); + } + // We know that this character will be in the map. + result += map.get(match[0].charCodeAt(0)); + // Every match will be of length 1 + lastIndex = match.index + 1; + } + return result + data.substring(lastIndex); + }; +} +/** + * Encodes all characters that have to be escaped in HTML attributes, + * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. + * @param data String to escape. + */ +const escapeAttribute = /* #__PURE__ */ getEscaper( + /["&\u00A0]/g, + new Map([ + [34, """], + [38, "&"], + [160, " "] + ]) +); +/** + * Encodes all characters that have to be escaped in HTML text, + * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. + * @param data String to escape. + */ +const escapeText = /* #__PURE__ */ getEscaper( + /[&<>\u00A0]/g, + new Map([ + [38, "&"], + [60, "<"], + [62, ">"], + [160, " "] + ]) ); -const procedure = new Map([ - [SelectorType.Universal, 50], - [SelectorType.Tag, 30], - [SelectorType.Attribute, 1], - [SelectorType.Pseudo, 0] +/** + * Mixed-case SVG and MathML element names recognized in foreign content. + */ +const elementNames = new Map( + [ + "altGlyph", + "altGlyphDef", + "altGlyphItem", + "animateColor", + "animateMotion", + "animateTransform", + "clipPath", + "feBlend", + "feColorMatrix", + "feComponentTransfer", + "feComposite", + "feConvolveMatrix", + "feDiffuseLighting", + "feDisplacementMap", + "feDistantLight", + "feDropShadow", + "feFlood", + "feFuncA", + "feFuncB", + "feFuncG", + "feFuncR", + "feGaussianBlur", + "feImage", + "feMerge", + "feMergeNode", + "feMorphology", + "feOffset", + "fePointLight", + "feSpecularLighting", + "feSpotLight", + "feTile", + "feTurbulence", + "foreignObject", + "glyphRef", + "linearGradient", + "radialGradient", + "textPath" + ].map((value) => [value.toLowerCase(), value]) +); +/** + * Mixed-case SVG and MathML attribute names recognized in foreign content. + */ +const attributeNames = new Map( + [ + "definitionURL", + "attributeName", + "attributeType", + "baseFrequency", + "baseProfile", + "calcMode", + "clipPathUnits", + "diffuseConstant", + "edgeMode", + "filterUnits", + "glyphRef", + "gradientTransform", + "gradientUnits", + "kernelMatrix", + "kernelUnitLength", + "keyPoints", + "keySplines", + "keyTimes", + "lengthAdjust", + "limitingConeAngle", + "markerHeight", + "markerUnits", + "markerWidth", + "maskContentUnits", + "maskUnits", + "numOctaves", + "pathLength", + "patternContentUnits", + "patternTransform", + "patternUnits", + "pointsAtX", + "pointsAtY", + "pointsAtZ", + "preserveAlpha", + "preserveAspectRatio", + "primitiveUnits", + "refX", + "refY", + "repeatCount", + "repeatDur", + "requiredExtensions", + "requiredFeatures", + "specularConstant", + "specularExponent", + "spreadMethod", + "startOffset", + "stdDeviation", + "stitchTiles", + "surfaceScale", + "systemLanguage", + "tableValues", + "targetX", + "targetY", + "textLength", + "viewBox", + "viewTarget", + "xChannelSelector", + "yChannelSelector", + "zoomAndPan" + ].map((value) => [value.toLowerCase(), value]) +); + +/* + * Module dependencies + */ +const unencodedElements = new Set([ + "style", + "script", + "xmp", + "iframe", + "noembed", + "noframes", + "plaintext", + "noscript" ]); -function isTraversal(token) { - return !procedure.has(token.type); +function replaceQuotes(value) { + return value.replace(/"/g, """); } -const attributes = new Map([ - [AttributeAction.Exists, 10], - [AttributeAction.Equals, 8], - [AttributeAction.Not, 7], - [AttributeAction.Start, 6], - [AttributeAction.End, 6], - [AttributeAction.Any, 5] +/** + * Format attributes + * @param attributes Attribute map to serialize. + * @param options Options that control this operation. + */ +function formatAttributes(attributes, options) { + if (!attributes) return; + const encode = + (options.encodeEntities ?? options.decodeEntities) === false + ? replaceQuotes + : !!options.xmlMode || options.encodeEntities !== "utf8" + ? encodeXML + : escapeAttribute; + return Object.keys(attributes) + .map((key) => { + const value = attributes[key]; + const normalizedValue = value == null ? "" : String(value); + if (options.xmlMode === "foreign") { + /* Fix up mixed-case attribute names */ + key = attributeNames.get(key) ?? key; + } + if (!(options.emptyAttrs || options.xmlMode) && normalizedValue === "") { + return key; + } + return `${key}="${encode(normalizedValue)}"`; + }) + .join(" "); +} +/** + * Self-enclosing tags + */ +const singleTag = new Set([ + "area", + "base", + "basefont", + "br", + "col", + "command", + "embed", + "frame", + "hr", + "img", + "input", + "isindex", + "keygen", + "link", + "meta", + "param", + "source", + "track", + "wbr" ]); /** - * Sort the parts of the passed selector, - * as there is potential for optimization - * (some types of selectors are faster than others) + * Renders a DOM node or an array of DOM nodes to a string. * - * @param arr Selector to sort + * Can be thought of as the equivalent of the `outerHTML` of the passed node(s). + * @param node Node to be rendered. + * @param options Changes serialization behavior */ -function sortByProcedure(arr) { - const procs = arr.map(getProcedure); - for (let i = 1; i < arr.length; i++) { - const procNew = procs[i]; - if (procNew < 0) continue; - for (let j = i - 1; j >= 0 && procNew < procs[j]; j--) { - const token = arr[j + 1]; - arr[j + 1] = arr[j]; - arr[j] = token; - procs[j + 1] = procs[j]; - procs[j] = procNew; +function render(node, options = {}) { + const nodes = "length" in node ? node : [node]; + let output = ""; + let index = 0; + while (index < nodes.length) { + output += renderNode(nodes[index], options); + index++; + } + return output; +} +function renderNode(node, options) { + switch (node.type) { + case Root: { + return render(node.children, options); + } + // @ts-expect-error We don't use `Doctype` yet + case Doctype: + case Directive: { + return renderDirective(node); + } + case Comment$1: { + return renderComment(node); + } + case CDATA: { + return renderCdata(node); + } + case Script: + case Style: + case Tag: { + return renderTag(node, options); + } + case Text$2: { + return renderText(node, options); } } } -function getProcedure(token) { - var _a, _b; - let proc = - (_a = procedure.get(token.type)) !== null && _a !== void 0 ? _a : -1; - if (token.type === SelectorType.Attribute) { - proc = - (_b = attributes.get(token.action)) !== null && _b !== void 0 ? _b : 4; - if (token.action === AttributeAction.Equals && token.name === "id") { - // Prefer ID selectors (eg. #ID) - proc = 9; +const foreignModeIntegrationPoints = new Set([ + "mi", + "mo", + "mn", + "ms", + "mtext", + "annotation-xml", + "foreignObject", + "desc", + "title" +]); +const foreignElements = new Set(["svg", "math"]); +function renderTag(element, options) { + // Handle SVG / MathML in HTML + if (options.xmlMode === "foreign") { + /* Fix up mixed-case element names */ + element.name = elementNames.get(element.name) ?? element.name; + /* Exit foreign mode at integration points */ + if ( + element.parent && + foreignModeIntegrationPoints.has(element.parent.name) + ) { + options = { ...options, xmlMode: false }; } - if (token.ignoreCase) { - /* - * IgnoreCase adds some overhead, prefer "normal" token - * this is a binary operation, to ensure it's still an int - */ - proc >>= 1; + } + if (!options.xmlMode && foreignElements.has(element.name)) { + options = { ...options, xmlMode: "foreign" }; + } + let tag = `<${element.name}`; + const attribs = formatAttributes(element.attribs, options); + if (attribs) { + tag += ` ${attribs}`; + } + if ( + element.children.length === 0 && + (options.xmlMode + ? // In XML mode or foreign mode, and user hasn't explicitly turned off self-closing tags + options.selfClosingTags !== false + : // User explicitly asked for self-closing tags, even in HTML mode + options.selfClosingTags && singleTag.has(element.name)) + ) { + if (!options.xmlMode) tag += " "; + tag += "/>"; + } else { + tag += ">"; + if (element.children.length > 0) { + tag += render(element.children, options); } - } else if (token.type === SelectorType.Pseudo) { - if (!token.data) { - proc = 3; - } else if (token.name === "has" || token.name === "contains") { - proc = 0; // Expensive in any case - } else if (Array.isArray(token.data)) { - // Eg. :matches, :not - proc = Math.min( - ...token.data.map((d) => Math.min(...d.map(getProcedure))) - ); - // If we have traversals, try to avoid executing this selector - if (proc < 0) { - proc = 0; + if (!!options.xmlMode || !singleTag.has(element.name)) { + tag += `</${element.name}>`; + } + } + return tag; +} +function renderDirective(element) { + return `<${element.data}>`; +} +function renderText(element, options) { + let data = element.data || ""; + // If entities weren't decoded, no need to encode them back + if ( + (options.encodeEntities ?? options.decodeEntities) !== false && + !( + !options.xmlMode && + element.parent && + unencodedElements.has(element.parent.name) + ) + ) { + data = + !!options.xmlMode || options.encodeEntities !== "utf8" + ? encodeXML(data) + : escapeText(data); + } + return data; +} +function renderCdata(element) { + return `<![CDATA[${element.children[0].data}]]>`; +} +function renderComment(element) { + return `<!--${element.data}-->`; +} + +/** + * @category Stringify + * @deprecated Use the `dom-serializer` module directly. + * @param node Node to get the outer HTML of. + * @param options Options for serialization. + * @returns `node`'s outer HTML. + */ +function getOuterHTML(node, options) { + return render(node, options); +} +/** + * @category Stringify + * @deprecated Use the `dom-serializer` module directly. + * @param node Node to get the inner HTML of. + * @param options Options for serialization. + * @returns `node`'s inner HTML. + */ +function getInnerHTML(node, options) { + return hasChildren(node) + ? node.children.map((node) => getOuterHTML(node, options)).join("") + : ""; +} +/** + * Get a node's inner text. Same as `textContent`, but inserts newlines for `<br>` tags. Ignores comments. + * + * @category Stringify + * @deprecated Use `textContent` instead. + * @param node Node to get the inner text of. + * @returns `node`'s inner text. + */ +function getText$1(node) { + if (Array.isArray(node)) return node.map(getText$1).join(""); + if (isTag$1(node)) + return node.name === "br" ? "\n" : getText$1(node.children); + if (isCDATA(node)) return getText$1(node.children); + if (isText(node)) return node.data; + return ""; +} +/** + * Get a node's text content. Ignores comments. + * + * @category Stringify + * @param node Node to get the text content of. + * @returns `node`'s text content. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent} + */ +function textContent(node) { + if (Array.isArray(node)) return node.map(textContent).join(""); + if (hasChildren(node) && !isComment(node)) { + return textContent(node.children); + } + if (isText(node)) return node.data; + return ""; +} +/** + * Get a node's inner text, ignoring `<script>` and `<style>` tags. Ignores comments. + * + * @category Stringify + * @param node Node to get the inner text of. + * @returns `node`'s inner text. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/innerText} + */ +function innerText(node) { + if (Array.isArray(node)) return node.map(innerText).join(""); + if (hasChildren(node) && (node.type === ElementType.Tag || isCDATA(node))) { + return innerText(node.children); + } + if (isText(node)) return node.data; + return ""; +} + +/** + * Get the feed object from the root of a DOM tree. + * + * @category Feeds + * @param document The DOM to extract the feed from. + * @returns The feed. + */ +function getFeed(document) { + const feedRoot = getOneElement(isValidFeed, document); + return feedRoot + ? feedRoot.name === "feed" + ? getAtomFeed(feedRoot) + : getRssFeed(feedRoot) + : null; +} +/** + * Parse an Atom feed. + * + * @param feedRoot The root of the feed. + * @returns The parsed feed. + */ +function getAtomFeed(feedRoot) { + const childs = feedRoot.children; + const feed = { + type: "atom", + items: getElementsByTagName("entry", childs).map((item) => { + const { children } = item; + const entry = { media: getMediaElements(children) }; + addConditionally(entry, "id", "id", children); + addConditionally(entry, "title", "title", children); + const href = getOneElement("link", children)?.attribs["href"]; + if (href) { + entry.link = href; + } + const description = + fetch("summary", children) || fetch("content", children); + if (description) { + entry.description = description; + } + const pubDate = fetch("updated", children); + if (pubDate) { + entry.pubDate = new Date(pubDate); + } + return entry; + }) + }; + addConditionally(feed, "id", "id", childs); + addConditionally(feed, "title", "title", childs); + const href = getOneElement("link", childs)?.attribs["href"]; + if (href) { + feed.link = href; + } + addConditionally(feed, "description", "subtitle", childs); + const updated = fetch("updated", childs); + if (updated) { + feed.updated = new Date(updated); + } + addConditionally(feed, "author", "email", childs, true); + return feed; +} +/** + * Parse a RSS feed. + * + * @param feedRoot The root of the feed. + * @returns The parsed feed. + */ +function getRssFeed(feedRoot) { + const childs = getOneElement("channel", feedRoot.children)?.children ?? []; + const feed = { + type: feedRoot.name.substr(0, 3), + id: "", + items: getElementsByTagName("item", feedRoot.children).map((item) => { + const { children } = item; + const entry = { media: getMediaElements(children) }; + addConditionally(entry, "id", "guid", children); + addConditionally(entry, "title", "title", children); + addConditionally(entry, "link", "link", children); + addConditionally(entry, "description", "description", children); + const pubDate = fetch("pubDate", children) || fetch("dc:date", children); + if (pubDate) entry.pubDate = new Date(pubDate); + return entry; + }) + }; + addConditionally(feed, "title", "title", childs); + addConditionally(feed, "link", "link", childs); + addConditionally(feed, "description", "description", childs); + const updated = fetch("lastBuildDate", childs); + if (updated) { + feed.updated = new Date(updated); + } + addConditionally(feed, "author", "managingEditor", childs, true); + return feed; +} +const MEDIA_KEYS_STRING = ["url", "type", "lang"]; +const MEDIA_KEYS_INT = [ + "fileSize", + "bitrate", + "framerate", + "samplingrate", + "channels", + "duration", + "height", + "width" +]; +/** + * Get all media elements of a feed item. + * + * @param where Nodes to search in. + * @returns Media elements. + */ +function getMediaElements(where) { + return getElementsByTagName("media:content", where).map((element) => { + const { attribs } = element; + const media = { + medium: attribs["medium"], + isDefault: !!attribs["isDefault"] + }; + for (const attrib of MEDIA_KEYS_STRING) { + if (attribs[attrib]) { + media[attrib] = attribs[attrib]; + } + } + for (const attrib of MEDIA_KEYS_INT) { + if (attribs[attrib]) { + media[attrib] = Number.parseInt(attribs[attrib], 10); + } + } + if (attribs["expression"]) { + media.expression = attribs["expression"]; + } + return media; + }); +} +/** + * Get one element by tag name. + * + * @param tagName Tag name to look for + * @param node Node to search in + * @returns The element or null + */ +function getOneElement(tagName, node) { + return getElementsByTagName(tagName, node, true, 1)[0]; +} +/** + * Get the text content of an element with a certain tag name. + * + * @param tagName Tag name to look for. + * @param where Node to search in. + * @param recurse Whether to recurse into child nodes. + * @returns The text content of the element. + */ +function fetch(tagName, where, recurse = false) { + return textContent(getElementsByTagName(tagName, where, recurse, 1)).trim(); +} +/** + * Adds a property to an object if it has a value. + * + * @param object Object to be extended. + * @param property Property name. + * @param tagName Tag name that contains the conditionally added property. + * @param where Element to search for the property. + * @param recurse Whether to recurse into child nodes. + */ +function addConditionally(object, property, tagName, where, recurse = false) { + const value = fetch(tagName, where, recurse); + if (value) object[property] = value; +} +/** + * Checks if an element is a feed root node. + * + * @param value The name of the element to check. + * @returns Whether an element is a feed root node. + */ +function isValidFeed(value) { + return value === "rss" || value === "feed" || value === "rdf:RDF"; +} + +/** + * Given an array of nodes, remove any member that is contained by another + * member. + * + * @category Helpers + * @param nodes Nodes to filter. + * @returns Remaining nodes that aren't contained by other nodes. + */ +function removeSubsets$1(nodes) { + let index = nodes.length; + /* + * Check if each node (or one of its ancestors) is already contained in the + * array. + */ + while (--index >= 0) { + const node = nodes[index]; + /* + * Remove the node if it is not unique. + * We are going through the array from the end, so we only + * have to check nodes that preceed the node under consideration in the array. + */ + if (index > 0 && nodes.lastIndexOf(node, index - 1) >= 0) { + nodes.splice(index, 1); + continue; + } + for (let ancestor = node.parent; ancestor; ancestor = ancestor.parent) { + if (nodes.includes(ancestor)) { + nodes.splice(index, 1); + break; } - } else { - proc = 2; } } - return proc; + return nodes; } +/** + * @category Helpers + * @see {@link http://dom.spec.whatwg.org/#dom-node-comparedocumentposition} + */ +var DocumentPosition; +(function (DocumentPosition) { + DocumentPosition[(DocumentPosition["DISCONNECTED"] = 1)] = "DISCONNECTED"; + DocumentPosition[(DocumentPosition["PRECEDING"] = 2)] = "PRECEDING"; + DocumentPosition[(DocumentPosition["FOLLOWING"] = 4)] = "FOLLOWING"; + DocumentPosition[(DocumentPosition["CONTAINS"] = 8)] = "CONTAINS"; + DocumentPosition[(DocumentPosition["CONTAINED_BY"] = 16)] = "CONTAINED_BY"; +})(DocumentPosition || (DocumentPosition = {})); +/** + * Compare the position of one node against another node in any other document, + * returning a bitmask with the values from {@link DocumentPosition}. + * + * Document order: + * > There is an ordering, document order, defined on all the nodes in the + * > document corresponding to the order in which the first character of the + * > XML representation of each node occurs in the XML representation of the + * > document after expansion of general entities. Thus, the document element + * > node will be the first node. Element nodes occur before their children. + * > Thus, document order orders element nodes in order of the occurrence of + * > their start-tag in the XML (after expansion of entities). The attribute + * > nodes of an element occur after the element and before its children. The + * > relative order of attribute nodes is implementation-dependent. + * + * Source: + * http://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-document-order + * + * @category Helpers + * @param nodeA The first node to use in the comparison + * @param nodeB The second node to use in the comparison + * @returns A bitmask describing the input nodes' relative position. + * + * See http://dom.spec.whatwg.org/#dom-node-comparedocumentposition for + * a description of these values. + */ +function compareDocumentPosition(nodeA, nodeB) { + const aParents = []; + const bParents = []; + if (nodeA === nodeB) { + return 0; + } + let current = hasChildren(nodeA) ? nodeA : nodeA.parent; + while (current) { + aParents.unshift(current); + current = current.parent; + } + current = hasChildren(nodeB) ? nodeB : nodeB.parent; + while (current) { + bParents.unshift(current); + current = current.parent; + } + const maxIndex = Math.min(aParents.length, bParents.length); + let index = 0; + while (index < maxIndex && aParents[index] === bParents[index]) { + index++; + } + if (index === 0) { + return DocumentPosition.DISCONNECTED; + } + const sharedParent = aParents[index - 1]; + const siblings = sharedParent.children; + const aSibling = aParents[index]; + const bSibling = bParents[index]; + if (siblings.indexOf(aSibling) > siblings.indexOf(bSibling)) { + if (sharedParent === nodeB) { + return DocumentPosition.FOLLOWING | DocumentPosition.CONTAINED_BY; + } + return DocumentPosition.FOLLOWING; + } + if (sharedParent === nodeA) { + return DocumentPosition.PRECEDING | DocumentPosition.CONTAINS; + } + return DocumentPosition.PRECEDING; +} +/** + * Sort an array of nodes based on their relative position in the document, + * removing any duplicate nodes. If the array contains nodes that do not belong + * to the same document, sort order is unspecified. + * + * @category Helpers + * @param nodes Array of DOM nodes. + * @returns Collection of unique nodes, sorted in document order. + */ +function uniqueSort(nodes) { + nodes = nodes.filter( + (node, index, array) => !array.includes(node, index + 1) + ); + nodes.sort((a, b) => { + const relative = compareDocumentPosition(a, b); + if (relative & DocumentPosition.PRECEDING) { + return -1; + } + if (relative & DocumentPosition.FOLLOWING) { + return 1; + } + return 0; + }); + return nodes; +} + +/** + * Remove an element from the dom + * + * @category Manipulation + * @param element The element to be removed. + */ +function removeElement(element) { + if (element.prev) element.prev.next = element.next; + if (element.next) element.next.prev = element.prev; + if (element.parent) { + const childs = element.parent.children; + const childsIndex = childs.lastIndexOf(element); + if (childsIndex !== -1) { + childs.splice(childsIndex, 1); + } + } + element.next = null; + element.prev = null; + element.parent = null; +} +/** + * Replace an element in the dom + * + * @category Manipulation + * @param element The element to be replaced. + * @param replacement The element to be added + */ +function replaceElement(element, replacement) { + replacement.prev = element.prev; + if (replacement.prev) { + replacement.prev.next = replacement; + } + replacement.next = element.next; + if (replacement.next) { + replacement.next.prev = replacement; + } + replacement.parent = element.parent; + if (replacement.parent) { + const { children } = replacement.parent; + const elementIndex = children.lastIndexOf(element); + if (elementIndex === -1) { + return; + } + children[elementIndex] = replacement; + element.parent = null; + } +} +/** + * Append a child to an element. + * + * @category Manipulation + * @param parent The element to append to. + * @param child The element to be added as a child. + */ +function appendChild(parent, child) { + removeElement(child); + child.next = null; + child.parent = parent; + if (parent.children.push(child) > 1) { + const sibling = parent.children[parent.children.length - 2]; + sibling.next = child; + child.prev = sibling; + } else { + child.prev = null; + } +} +/** + * Append an element after another. + * + * @category Manipulation + * @param element The element to append after. + * @param next The element be added. + */ +function append$1(element, next) { + removeElement(next); + const { parent } = element; + const currentNext = element.next; + next.next = currentNext; + next.prev = element; + element.next = next; + next.parent = parent; + if (currentNext) { + currentNext.prev = next; + if (parent) { + const childs = parent.children; + childs.splice(childs.lastIndexOf(currentNext), 0, next); + } + } else if (parent) { + parent.children.push(next); + } +} +/** + * Prepend a child to an element. + * + * @category Manipulation + * @param parent The element to prepend before. + * @param child The element to be added as a child. + */ +function prependChild(parent, child) { + removeElement(child); + child.parent = parent; + child.prev = null; + if (parent.children.unshift(child) === 1) { + child.next = null; + } else { + const sibling = parent.children[1]; + sibling.prev = child; + child.next = sibling; + } +} +/** + * Prepend an element before another. + * + * @category Manipulation + * @param element The element to prepend before. + * @param previous The element to be added. + */ +function prepend(element, previous) { + removeElement(previous); + const { parent } = element; + if (parent) { + const childs = parent.children; + childs.splice(childs.indexOf(element), 0, previous); + } + if (element.prev) { + element.prev.next = previous; + } + previous.parent = parent; + previous.prev = element.prev; + previous.next = element; + element.prev = previous; +} + +/** + * Get a node's children. + * + * @category Traversal + * @param element Node to get the children of. + * @returns `element`'s children, or an empty array. + */ +function getChildren$1(element) { + return hasChildren(element) ? element.children : []; +} +function getParent$1(element) { + return element.parent || null; +} +/** + * Gets an elements siblings, including the element itself. + * + * Attempts to get the children through the element's parent first. If we don't + * have a parent (the element is a root node), we walk the element's `prev` & + * `next` to get all remaining nodes. + * + * @category Traversal + * @param element Element to get the siblings of. + * @returns `element`'s siblings, including `element`. + */ +function getSiblings$1(element) { + const parent = getParent$1(element); + if (parent != null) return getChildren$1(parent); + const siblings = [element]; + let { prev, next } = element; + while (prev != null) { + siblings.unshift(prev); + ({ prev } = prev); + } + while (next != null) { + siblings.push(next); + ({ next } = next); + } + return siblings; +} +/** + * Gets an attribute from an element. + * + * @category Traversal + * @param element Element to check. + * @param name Attribute name to retrieve. + * @returns The element's attribute value, or `undefined`. + */ +function getAttributeValue$1(element, name) { + const { attribs } = element; + return attribs?.[name]; +} +/** + * Checks whether an element has an attribute. + * + * @category Traversal + * @param element Element to check. + * @param name Attribute name to look for. + * @returns Returns whether `element` has the attribute `name`. + */ +function hasAttrib$1(element, name) { + const { attribs } = element; + return ( + attribs != null && Object.hasOwn(attribs, name) && attribs[name] != null + ); +} +/** + * Get the tag name of an element. + * + * @category Traversal + * @param element The element to get the name for. + * @returns The tag name of `element`. + */ +function getName$1(element) { + return element.name; +} +/** + * Returns the next element sibling of a node. + * + * @category Traversal + * @param element The element to get the next sibling of. + * @returns `element`'s next sibling that is a tag, or `null` if there is no next + * sibling. + */ +function nextElementSibling(element) { + let { next } = element; + while (next !== null && !isTag$1(next)) ({ next } = next); + return next; +} +/** + * Returns the previous element sibling of a node. + * + * @category Traversal + * @param element The element to get the previous sibling of. + * @returns `element`'s previous sibling that is a tag, or `null` if there is no + * previous sibling. + */ +// eslint-disable-next-line unicorn/prevent-abbreviations -- Keep public API name for backwards compatibility. +function prevElementSibling(element) { + let { prev } = element; + while (prev !== null && !isTag$1(prev)) ({ prev } = prev); + return prev; +} + +var DomUtils = /*#__PURE__*/ Object.freeze({ + __proto__: null, + get DocumentPosition() { + return DocumentPosition; + }, + append: append$1, + appendChild: appendChild, + compareDocumentPosition: compareDocumentPosition, + existsOne: existsOne$1, + filter: filter, + find: find, + findAll: findAll$1, + findOne: findOne$2, + getAttributeValue: getAttributeValue$1, + getChildren: getChildren$1, + getElementById: getElementById, + getElements: getElements, + getElementsByClassName: getElementsByClassName, + getElementsByTagName: getElementsByTagName, + getElementsByTagType: getElementsByTagType, + getFeed: getFeed, + getInnerHTML: getInnerHTML, + getName: getName$1, + getOuterHTML: getOuterHTML, + getParent: getParent$1, + getSiblings: getSiblings$1, + getText: getText$1, + hasAttrib: hasAttrib$1, + innerText: innerText, + nextElementSibling: nextElementSibling, + prepend: prepend, + prependChild: prependChild, + prevElementSibling: prevElementSibling, + removeElement: removeElement, + removeSubsets: removeSubsets$1, + replaceElement: replaceElement, + testElement: testElement, + textContent: textContent, + uniqueSort: uniqueSort +}); /** * All reserved characters in a regex, used for escaping. @@ -5446,13 +5522,12 @@ function getProcedure(token) { * https://github.com/slevithan/xregexp/blob/95eeebeb8fac8754d54eafe2b4743661ac1cf028/src/xregexp.js#L794 */ const reChars = /[-[\]{}()*+?.,\\^$|#\s]/g; +const whitespaceRe = /\s/; function escapeRegex(value) { return value.replace(reChars, "\\$&"); } /** * Attributes that are case-insensitive in HTML. - * - * @private * @see https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors */ const caseInsensitiveAttributes = new Set([ @@ -5507,8 +5582,8 @@ function shouldIgnoreCase(selector, options) { return typeof selector.ignoreCase === "boolean" ? selector.ignoreCase : selector.ignoreCase === "quirks" - ? !!options.quirksMode - : !options.xmlMode && caseInsensitiveAttributes.has(selector.name); + ? !!options.quirksMode + : !options.xmlMode && caseInsensitiveAttributes.has(selector.name); } /** * Attribute selectors @@ -5520,590 +5595,248 @@ const attributeRules = { let { value } = data; if (shouldIgnoreCase(data, options)) { value = value.toLowerCase(); - return (elem) => { - const attr = adapter.getAttributeValue(elem, name); + return (element) => { + const attribute = adapter.getAttributeValue(element, name); return ( - attr != null && - attr.length === value.length && - attr.toLowerCase() === value && - next(elem) + attribute != null && + attribute.length === value.length && + attribute.toLowerCase() === value && + next(element) ); }; } - return (elem) => - adapter.getAttributeValue(elem, name) === value && next(elem); + return (element) => + adapter.getAttributeValue(element, name) === value && next(element); }, hyphen(next, data, options) { const { adapter } = options; const { name } = data; let { value } = data; - const len = value.length; + const { length } = value; if (shouldIgnoreCase(data, options)) { value = value.toLowerCase(); - return function hyphenIC(elem) { - const attr = adapter.getAttributeValue(elem, name); + return function hyphenIC(element) { + const attribute = adapter.getAttributeValue(element, name); return ( - attr != null && - (attr.length === len || attr.charAt(len) === "-") && - attr.substr(0, len).toLowerCase() === value && - next(elem) + attribute != null && + (attribute.length === length || attribute.charAt(length) === "-") && + attribute.substr(0, length).toLowerCase() === value && + next(element) ); }; } - return function hyphen(elem) { - const attr = adapter.getAttributeValue(elem, name); + return function hyphen(element) { + const attribute = adapter.getAttributeValue(element, name); return ( - attr != null && - (attr.length === len || attr.charAt(len) === "-") && - attr.substr(0, len) === value && - next(elem) + attribute != null && + (attribute.length === length || attribute.charAt(length) === "-") && + attribute.substr(0, length) === value && + next(element) ); }; }, element(next, data, options) { const { adapter } = options; const { name, value } = data; - if (/\s/.test(value)) { - return boolbase.falseFunc; + if (whitespaceRe.test(value)) { + return falseFunc; } const regex = new RegExp( `(?:^|\\s)${escapeRegex(value)}(?:$|\\s)`, shouldIgnoreCase(data, options) ? "i" : "" ); - return function element(elem) { - const attr = adapter.getAttributeValue(elem, name); + return function element(node) { + const attribute = adapter.getAttributeValue(node, name); return ( - attr != null && - attr.length >= value.length && - regex.test(attr) && - next(elem) + attribute != null && + attribute.length >= value.length && + regex.test(attribute) && + next(node) ); }; }, exists(next, { name }, { adapter }) { - return (elem) => adapter.hasAttrib(elem, name) && next(elem); + return (element) => adapter.hasAttrib(element, name) && next(element); }, start(next, data, options) { const { adapter } = options; const { name } = data; let { value } = data; - const len = value.length; - if (len === 0) { - return boolbase.falseFunc; + const { length } = value; + if (length === 0) { + return falseFunc; } if (shouldIgnoreCase(data, options)) { value = value.toLowerCase(); - return (elem) => { - const attr = adapter.getAttributeValue(elem, name); + return (element) => { + const attribute = adapter.getAttributeValue(element, name); return ( - attr != null && - attr.length >= len && - attr.substr(0, len).toLowerCase() === value && - next(elem) + attribute != null && + attribute.length >= length && + attribute.substr(0, length).toLowerCase() === value && + next(element) ); }; } - return (elem) => { - var _a; - return ( - !!((_a = adapter.getAttributeValue(elem, name)) === null || - _a === void 0 - ? void 0 - : _a.startsWith(value)) && next(elem) - ); - }; + return (element) => + !!adapter.getAttributeValue(element, name)?.startsWith(value) && + next(element); }, end(next, data, options) { const { adapter } = options; const { name } = data; let { value } = data; - const len = -value.length; - if (len === 0) { - return boolbase.falseFunc; + const length = -value.length; + if (length === 0) { + return falseFunc; } if (shouldIgnoreCase(data, options)) { value = value.toLowerCase(); - return (elem) => { - var _a; - return ( - ((_a = adapter.getAttributeValue(elem, name)) === null || - _a === void 0 - ? void 0 - : _a.substr(len).toLowerCase()) === value && next(elem) - ); - }; + return (element) => + adapter + .getAttributeValue(element, name) + ?.substr(length) + .toLowerCase() === value && next(element); } - return (elem) => { - var _a; - return ( - !!((_a = adapter.getAttributeValue(elem, name)) === null || - _a === void 0 - ? void 0 - : _a.endsWith(value)) && next(elem) - ); - }; + return (element) => + !!adapter.getAttributeValue(element, name)?.endsWith(value) && + next(element); }, any(next, data, options) { const { adapter } = options; const { name, value } = data; if (value === "") { - return boolbase.falseFunc; + return falseFunc; } if (shouldIgnoreCase(data, options)) { const regex = new RegExp(escapeRegex(value), "i"); - return function anyIC(elem) { - const attr = adapter.getAttributeValue(elem, name); + return function anyIC(element) { + const attribute = adapter.getAttributeValue(element, name); return ( - attr != null && - attr.length >= value.length && - regex.test(attr) && - next(elem) + attribute != null && + attribute.length >= value.length && + regex.test(attribute) && + next(element) ); }; } - return (elem) => { - var _a; - return ( - !!((_a = adapter.getAttributeValue(elem, name)) === null || - _a === void 0 - ? void 0 - : _a.includes(value)) && next(elem) - ); - }; + return (element) => + !!adapter.getAttributeValue(element, name)?.includes(value) && + next(element); }, not(next, data, options) { const { adapter } = options; const { name } = data; let { value } = data; if (value === "") { - return (elem) => !!adapter.getAttributeValue(elem, name) && next(elem); - } else if (shouldIgnoreCase(data, options)) { + return (element) => + !!adapter.getAttributeValue(element, name) && next(element); + } + if (shouldIgnoreCase(data, options)) { value = value.toLowerCase(); - return (elem) => { - const attr = adapter.getAttributeValue(elem, name); + return (element) => { + const attribute = adapter.getAttributeValue(element, name); return ( - (attr == null || - attr.length !== value.length || - attr.toLowerCase() !== value) && - next(elem) + (attribute == null || + attribute.length !== value.length || + attribute.toLowerCase() !== value) && + next(element) ); }; } - return (elem) => - adapter.getAttributeValue(elem, name) !== value && next(elem); + return (element) => + adapter.getAttributeValue(element, name) !== value && next(element); } }; -var lib = {}; - -var parse$4 = {}; - -// Following http://www.w3.org/TR/css3-selectors/#nth-child-pseudo -Object.defineProperty(parse$4, "__esModule", { value: true }); -parse$4.parse = void 0; -// Whitespace as per https://www.w3.org/TR/selectors-3/#lex is " \t\r\n\f" -var whitespace = new Set([9, 10, 12, 13, 32]); -var ZERO = "0".charCodeAt(0); -var NINE = "9".charCodeAt(0); /** - * Parses an expression. - * - * @throws An `Error` if parsing fails. - * @returns An array containing the integer step size and the integer offset of the nth rule. - * @example nthCheck.parse("2n+3"); // returns [2, 3] + * Find all elements matching the query. If not in XML mode, the query will ignore + * the contents of `<template>` elements. + * @param query - Function that returns true if the element matches the query. + * @param nodes - Nodes to query. If a node is an element, its children will be queried. + * @param options - Options for querying the document. + * @returns All matching elements. */ -function parse$3(formula) { - formula = formula.trim().toLowerCase(); - if (formula === "even") { - return [2, 0]; - } else if (formula === "odd") { - return [2, 1]; - } - // Parse [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]? - var idx = 0; - var a = 0; - var sign = readSign(); - var number = readNumber(); - if (idx < formula.length && formula.charAt(idx) === "n") { - idx++; - a = sign * (number !== null && number !== void 0 ? number : 1); - skipWhitespace(); - if (idx < formula.length) { - sign = readSign(); - skipWhitespace(); - number = readNumber(); - } else { - sign = number = 0; - } - } - // Throw if there is anything else - if (number === null || idx < formula.length) { - throw new Error("n-th rule couldn't be parsed ('" + formula + "')"); - } - return [a, sign * number]; - function readSign() { - if (formula.charAt(idx) === "-") { - idx++; - return -1; - } - if (formula.charAt(idx) === "+") { - idx++; - } - return 1; - } - function readNumber() { - var start = idx; - var value = 0; - while ( - idx < formula.length && - formula.charCodeAt(idx) >= ZERO && - formula.charCodeAt(idx) <= NINE - ) { - value = value * 10 + (formula.charCodeAt(idx) - ZERO); - idx++; - } - // Return `null` if we didn't read anything. - return idx === start ? null : value; - } - function skipWhitespace() { - while (idx < formula.length && whitespace.has(formula.charCodeAt(idx))) { - idx++; - } - } -} -parse$4.parse = parse$3; - -var compile$3 = {}; - -Object.defineProperty(compile$3, "__esModule", { value: true }); -compile$3.compile = void 0; -var boolbase_1 = boolbase; /** - * Returns a function that checks if an elements index matches the given rule - * highly optimized to return the fastest solution. - * - * @param parsed A tuple [a, b], as returned by `parse`. - * @returns A highly optimized function that returns whether an index matches the nth-check. - * @example - * const check = nthCheck.compile([2, 3]); - * - * check(0); // `false` - * check(1); // `false` - * check(2); // `true` - * check(3); // `false` - * check(4); // `true` - * check(5); // `false` - * check(6); // `true` + * Find the first element matching the query. If not in XML mode, the query will ignore + * the contents of `<template>` elements. + * @param query - Function that returns true if the element matches the query. + * @param nodes - Nodes to query. If a node is an element, its children will be queried. + * @param options - Options for querying the document. + * @returns The first matching element, or null if there was no match. */ -function compile$2(parsed) { - var a = parsed[0]; - // Subtract 1 from `b`, to convert from one- to zero-indexed. - var b = parsed[1] - 1; - /* - * When `b <= 0`, `a * n` won't be lead to any matches for `a < 0`. - * Besides, the specification states that no elements are - * matched when `a` and `b` are 0. - * - * `b < 0` here as we subtracted 1 from `b` above. - */ - if (b < 0 && a <= 0) return boolbase_1.falseFunc; - // When `a` is in the range -1..1, it matches any element (so only `b` is checked). - if (a === -1) - return function (index) { - return index <= b; - }; - if (a === 0) - return function (index) { - return index === b; - }; - // When `b <= 0` and `a === 1`, they match any element. - if (a === 1) - return b < 0 - ? boolbase_1.trueFunc - : function (index) { - return index >= b; - }; - /* - * Otherwise, modulo can be used to check if there is a match. - * - * Modulo doesn't care about the sign, so let's use `a`s absolute value. - */ - var absA = Math.abs(a); - // Get `b mod a`, + a if this is negative. - var bMod = ((b % absA) + absA) % absA; - return a > 1 - ? function (index) { - return index >= b && index % absA === bMod; +function findOne$1(query, nodes, options) { + const { adapter, xmlMode = false } = options; + /** Stack of the arrays we are looking at. */ + const nodeStack = [nodes]; + /** Stack of the indices within the arrays. */ + const indexStack = [0]; + for (;;) { + // First, check if the current array has any more elements to look at. + if (indexStack[0] >= nodeStack[0].length) { + // If we have no more arrays to look at, we are done. + if (nodeStack.length === 1) { + return null; } - : function (index) { - return index <= b && index % absA === bMod; - }; -} -compile$3.compile = compile$2; - -(function (exports) { - Object.defineProperty(exports, "__esModule", { value: true }); - exports.compile = exports.parse = void 0; - var parse_1 = parse$4; - Object.defineProperty(exports, "parse", { - enumerable: true, - get: function () { - return parse_1.parse; + nodeStack.shift(); + indexStack.shift(); + // Loop back to the start to continue with the next array. + continue; } - }); - var compile_1 = compile$3; - Object.defineProperty(exports, "compile", { - enumerable: true, - get: function () { - return compile_1.compile; + const element = nodeStack[0][indexStack[0]++]; + if (!adapter.isTag(element)) { + continue; + } + if (query(element)) { + return element; + } + if (xmlMode || adapter.getName(element) !== "template") { + /* + * Add the children to the stack. We are depth-first, so this is + * the next array we look at. + */ + const children = adapter.getChildren(element); + if (children.length > 0) { + nodeStack.unshift(children); + indexStack.unshift(0); + } } - }); - /** - * Parses and compiles a formula to a highly optimized function. - * Combination of `parse` and `compile`. - * - * If the formula doesn't match any elements, - * it returns [`boolbase`](https://github.com/fb55/boolbase)'s `falseFunc`. - * Otherwise, a function accepting an _index_ is returned, which returns - * whether or not the passed _index_ matches the formula. - * - * Note: The nth-rule starts counting at `1`, the returned function at `0`. - * - * @param formula The formula to compile. - * @example - * const check = nthCheck("2n+3"); - * - * check(0); // `false` - * check(1); // `false` - * check(2); // `true` - * check(3); // `false` - * check(4); // `true` - * check(5); // `false` - * check(6); // `true` - */ - function nthCheck(formula) { - return (0, compile_1.compile)((0, parse_1.parse)(formula)); } - exports.default = nthCheck; -})(lib); - -var getNCheck = /*@__PURE__*/ getDefaultExportFromCjs(lib); - -function getChildFunc(next, adapter) { - return (elem) => { - const parent = adapter.getParent(elem); - return parent != null && adapter.isTag(parent) && next(elem); - }; } -const filters = { - contains(next, text, { adapter }) { - return function contains(elem) { - return next(elem) && adapter.getText(elem).includes(text); - }; - }, - icontains(next, text, { adapter }) { - const itext = text.toLowerCase(); - return function icontains(elem) { - return next(elem) && adapter.getText(elem).toLowerCase().includes(itext); - }; - }, - // Location specific methods - "nth-child"(next, rule, { adapter, equals }) { - const func = getNCheck(rule); - if (func === boolbase.falseFunc) return boolbase.falseFunc; - if (func === boolbase.trueFunc) return getChildFunc(next, adapter); - return function nthChild(elem) { - const siblings = adapter.getSiblings(elem); - let pos = 0; - for (let i = 0; i < siblings.length; i++) { - if (equals(elem, siblings[i])) break; - if (adapter.isTag(siblings[i])) { - pos++; - } - } - return func(pos) && next(elem); - }; - }, - "nth-last-child"(next, rule, { adapter, equals }) { - const func = getNCheck(rule); - if (func === boolbase.falseFunc) return boolbase.falseFunc; - if (func === boolbase.trueFunc) return getChildFunc(next, adapter); - return function nthLastChild(elem) { - const siblings = adapter.getSiblings(elem); - let pos = 0; - for (let i = siblings.length - 1; i >= 0; i--) { - if (equals(elem, siblings[i])) break; - if (adapter.isTag(siblings[i])) { - pos++; - } - } - return func(pos) && next(elem); - }; - }, - "nth-of-type"(next, rule, { adapter, equals }) { - const func = getNCheck(rule); - if (func === boolbase.falseFunc) return boolbase.falseFunc; - if (func === boolbase.trueFunc) return getChildFunc(next, adapter); - return function nthOfType(elem) { - const siblings = adapter.getSiblings(elem); - let pos = 0; - for (let i = 0; i < siblings.length; i++) { - const currentSibling = siblings[i]; - if (equals(elem, currentSibling)) break; - if ( - adapter.isTag(currentSibling) && - adapter.getName(currentSibling) === adapter.getName(elem) - ) { - pos++; - } - } - return func(pos) && next(elem); - }; - }, - "nth-last-of-type"(next, rule, { adapter, equals }) { - const func = getNCheck(rule); - if (func === boolbase.falseFunc) return boolbase.falseFunc; - if (func === boolbase.trueFunc) return getChildFunc(next, adapter); - return function nthLastOfType(elem) { - const siblings = adapter.getSiblings(elem); - let pos = 0; - for (let i = siblings.length - 1; i >= 0; i--) { - const currentSibling = siblings[i]; - if (equals(elem, currentSibling)) break; - if ( - adapter.isTag(currentSibling) && - adapter.getName(currentSibling) === adapter.getName(elem) - ) { - pos++; - } - } - return func(pos) && next(elem); - }; - }, - // TODO determine the actual root element - root(next, _rule, { adapter }) { - return (elem) => { - const parent = adapter.getParent(elem); - return (parent == null || !adapter.isTag(parent)) && next(elem); - }; - }, - scope(next, rule, options, context) { - const { equals } = options; - if (!context || context.length === 0) { - // Equivalent to :root - return filters["root"](next, rule, options); - } - if (context.length === 1) { - // NOTE: can't be unpacked, as :has uses this for side-effects - return (elem) => equals(context[0], elem) && next(elem); - } - return (elem) => context.includes(elem) && next(elem); - }, - hover: dynamicStatePseudo("isHovered"), - visited: dynamicStatePseudo("isVisited"), - active: dynamicStatePseudo("isActive") -}; /** - * Dynamic state pseudos. These depend on optional Adapter methods. - * - * @param name The name of the adapter method to call. - * @returns Pseudo for the `filters` object. + * Get all element siblings after the provided node. + * @param element Element candidate being tested. + * @param adapter Adapter implementation used for DOM operations. */ -function dynamicStatePseudo(name) { - return function dynamicPseudo(next, _rule, { adapter }) { - const func = adapter[name]; - if (typeof func !== "function") { - return boolbase.falseFunc; - } - return function active(elem) { - return func(elem) && next(elem); - }; - }; -} - -// While filters are precompiled, pseudos get called when they are needed -const pseudos = { - empty(elem, { adapter }) { - return !adapter.getChildren(elem).some( - (elem) => - // FIXME: `getText` call is potentially expensive. - adapter.isTag(elem) || adapter.getText(elem) !== "" - ); - }, - "first-child"(elem, { adapter, equals }) { - if (adapter.prevElementSibling) { - return adapter.prevElementSibling(elem) == null; - } - const firstChild = adapter - .getSiblings(elem) - .find((elem) => adapter.isTag(elem)); - return firstChild != null && equals(elem, firstChild); - }, - "last-child"(elem, { adapter, equals }) { - const siblings = adapter.getSiblings(elem); - for (let i = siblings.length - 1; i >= 0; i--) { - if (equals(elem, siblings[i])) return true; - if (adapter.isTag(siblings[i])) break; - } - return false; - }, - "first-of-type"(elem, { adapter, equals }) { - const siblings = adapter.getSiblings(elem); - const elemName = adapter.getName(elem); - for (let i = 0; i < siblings.length; i++) { - const currentSibling = siblings[i]; - if (equals(elem, currentSibling)) return true; - if ( - adapter.isTag(currentSibling) && - adapter.getName(currentSibling) === elemName - ) { - break; - } - } - return false; - }, - "last-of-type"(elem, { adapter, equals }) { - const siblings = adapter.getSiblings(elem); - const elemName = adapter.getName(elem); - for (let i = siblings.length - 1; i >= 0; i--) { - const currentSibling = siblings[i]; - if (equals(elem, currentSibling)) return true; - if ( - adapter.isTag(currentSibling) && - adapter.getName(currentSibling) === elemName - ) { - break; - } - } - return false; - }, - "only-of-type"(elem, { adapter, equals }) { - const elemName = adapter.getName(elem); - return adapter - .getSiblings(elem) - .every( - (sibling) => - equals(elem, sibling) || - !adapter.isTag(sibling) || - adapter.getName(sibling) !== elemName - ); - }, - "only-child"(elem, { adapter, equals }) { - return adapter - .getSiblings(elem) - .every((sibling) => equals(elem, sibling) || !adapter.isTag(sibling)); - } -}; -function verifyPseudoArgs(func, name, subselect, argIndex) { - if (subselect === null) { - if (func.length > argIndex) { - throw new Error(`Pseudo-class :${name} requires an argument`); - } - } else if (func.length === argIndex) { - throw new Error(`Pseudo-class :${name} doesn't have any arguments`); - } +function getNextSiblings(element, adapter) { + const siblings = adapter.getSiblings(element); + if (siblings.length <= 1) { + return []; + } + const elementIndex = siblings.indexOf(element); + if (elementIndex === -1 || elementIndex === siblings.length - 1) { + return []; + } + return siblings.slice(elementIndex + 1).filter(adapter.isTag); +} +/** + * Get the parent element of a node. + * @param node Node to inspect. + * @param adapter Adapter implementation used for DOM operations. + */ +function getElementParent(node, adapter) { + const parent = adapter.getParent(node); + return parent != null && adapter.isTag(parent) ? parent : null; } +/** + * Only text controls can be made read-only, since for other controls (such + * as checkboxes and buttons) there is no useful distinction between being + * read-only and being disabled. + * @see {@link https://html.spec.whatwg.org/multipage/input.html#attr-input-readonly} + */ +const textControl = + "input:is([type=text i],[type=search i],[type=url i],[type=tel i],[type=email i],[type=password i],[type=date i],[type=month i],[type=week i],[type=time i],[type=datetime-local i],[type=number i])"; /** * Aliases are pseudos that are expressed as selectors. */ @@ -6118,13 +5851,22 @@ const aliases = { optgroup[disabled] > option, fieldset[disabled]:not(fieldset[disabled] legend:first-of-type *) )`, - enabled: ":not(:disabled)", + enabled: + ":is(button, input, select, textarea, optgroup, option, fieldset):not(:disabled)", checked: - ":is(:is(input[type=radio], input[type=checkbox])[checked], option:selected)", + ":is(:is(input[type=radio], input[type=checkbox])[checked], :selected)", required: ":is(input, select, textarea)[required]", optional: ":is(input, select, textarea):not([required])", + "read-only": `[readonly]:is(textarea, ${textControl})`, + "read-write": `:not([readonly]):is(textarea, ${textControl})`, // JQuery extensions - // https://html.spec.whatwg.org/multipage/form-elements.html#concept-option-selectedness + /** + * `:selected` matches option elements that have the `selected` attribute, + * or are the first option element in a select element that does not have + * the `multiple` attribute and does not have any option elements with the + * `selected` attribute. + * @see https://html.spec.whatwg.org/multipage/form-elements.html#concept-option-selectedness + */ selected: "option:is([selected], select:not([multiple]):not(:has(> option[selected])) > :first-of-type)", checkbox: "[type=checkbox]", @@ -6141,45 +5883,647 @@ const aliases = { text: "input:is(:not([type!='']), [type=text])" }; -/** Used as a placeholder for :has. Will be replaced with the actual element. */ -const PLACEHOLDER_ELEMENT = {}; -function ensureIsTag(next, adapter) { - if (next === boolbase.falseFunc) return boolbase.falseFunc; - return (elem) => adapter.isTag(elem) && next(elem); +/** + * Returns a function that checks if an elements index matches the given rule + * highly optimized to return the fastest solution. + * @param parsed A tuple [a, b], as returned by `parse`. + * @returns A highly optimized function that returns whether an index matches the nth-check. + * @example + * + * ```js + * const check = nthCheck.compile([2, 3]); + * + * check(0); // `false` + * check(1); // `false` + * check(2); // `true` + * check(3); // `false` + * check(4); // `true` + * check(5); // `false` + * check(6); // `true` + * ``` + */ +function compile$1(parsed) { + const a = parsed[0]; + // Subtract 1 from `b`, to convert from one- to zero-indexed. + const b = parsed[1] - 1; + /* + * When `b <= 0`, `a * n` won't be lead to any matches for `a < 0`. + * Besides, the specification states that no elements are + * matched when `a` and `b` are 0. + * + * `b < 0` here as we subtracted 1 from `b` above. + */ + if (b < 0 && a <= 0) return falseFunc; + // When `a` is in the range -1..1, it matches any element (so only `b` is checked). + if (a === -1) return (index) => index <= b; + if (a === 0) return (index) => index === b; + // When `b <= 0` and `a === 1`, they match any element. + if (a === 1) return b < 0 ? trueFunc : (index) => index >= b; + /* + * Otherwise, modulo can be used to check if there is a match. + * + * Modulo doesn't care about the sign, so let's use `a`s absolute value. + */ + const absA = Math.abs(a); + // Get `b mod a`, + a if this is negative. + const bModulo = ((b % absA) + absA) % absA; + return a > 1 + ? (index) => index >= b && index % absA === bModulo + : (index) => index <= b && index % absA === bModulo; } -function getNextSiblings(elem, adapter) { - const siblings = adapter.getSiblings(elem); - if (siblings.length <= 1) return []; - const elemIndex = siblings.indexOf(elem); - if (elemIndex < 0 || elemIndex === siblings.length - 1) return []; - return siblings.slice(elemIndex + 1).filter(adapter.isTag); + +// Following http://www.w3.org/TR/css3-selectors/#nth-child-pseudo +// Whitespace as per https://www.w3.org/TR/selectors-3/#lex is " \t\r\n\f" +const whitespace = new Set([9, 10, 12, 13, 32]); +const ZERO = "0".charCodeAt(0); +const NINE = "9".charCodeAt(0); +/** + * Parses an expression. + * @param formula CSS nth-formula to parse. + * @throws {Error} An `Error` if parsing fails. + * @returns An array containing the integer step size and the integer offset of the nth rule. + * @example nthCheck.parse("2n+3"); // returns [2, 3] + */ +function parse$2(formula) { + formula = formula.trim().toLowerCase(); + switch (formula) { + case "even": { + return [2, 0]; + } + case "odd": { + return [2, 1]; + } + } + // Parse [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]? + let index = 0; + let a = 0; + let sign = readSign(); + let number = readNumber(); + if (index < formula.length && formula.charAt(index) === "n") { + index++; + a = sign * (number ?? 1); + skipWhitespace(); + if (index < formula.length) { + sign = readSign(); + skipWhitespace(); + number = readNumber(); + } else { + sign = number = 0; + } + } + // Throw if there is anything else + if (number === null || index < formula.length) { + throw new Error(`n-th rule couldn't be parsed ('${formula}')`); + } + return [a, sign * number]; + function readSign() { + switch (formula.charAt(index)) { + case "-": { + index++; + return -1; + } + case "+": { + index++; + break; + } + } + return 1; + } + function readNumber() { + const start = index; + let value = 0; + while ( + index < formula.length && + formula.charCodeAt(index) >= ZERO && + formula.charCodeAt(index) <= NINE + ) { + value = value * 10 + (formula.charCodeAt(index) - ZERO); + index++; + } + // Return `null` if we didn't read anything. + return index === start ? null : value; + } + function skipWhitespace() { + while ( + index < formula.length && + whitespace.has(formula.charCodeAt(index)) + ) { + index++; + } + } } -function copyOptions(options) { - // Not copied: context, rootFunc - return { - xmlMode: !!options.xmlMode, - lowerCaseAttributeNames: !!options.lowerCaseAttributeNames, - lowerCaseTags: !!options.lowerCaseTags, - quirksMode: !!options.quirksMode, - cacheResults: !!options.cacheResults, - pseudos: options.pseudos, - adapter: options.adapter, - equals: options.equals + +/** + * Parses and compiles a formula to a highly optimized function. + * Combination of {@link parse} and {@link compile}. + * + * If the formula doesn't match any elements, + * it returns [`boolbase`](https://github.com/fb55/boolbase)'s `falseFunc`. + * Otherwise, a function accepting an _index_ is returned, which returns + * whether or not the passed _index_ matches the formula. + * + * Note: The nth-rule starts counting at `1`, the returned function at `0`. + * @param formula The formula to compile. + * @example + * const check = nthCheck("2n+3"); + * + * check(0); // `false` + * check(1); // `false` + * check(2); // `true` + * check(3); // `false` + * check(4); // `true` + * check(5); // `false` + * check(6); // `true` + */ +function nthCheck(formula) { + return compile$1(parse$2(formula)); +} + +/** + * Some selectors such as `:contains` and (non-relative) `:has` will only be + * able to match elements if their parents match the selector (as they contain + * a subset of the elements that the parent contains). + * + * This function wraps the given `matches` function in a function that caches + * the results of the parent elements, so that the `matches` function only + * needs to be called once for each subtree. + * @param next Matcher to run after this matcher succeeds. + * @param options Configuration object for cache behavior. + * @param options.adapter Adapter implementation used for DOM access. + * @param options.cacheResults Whether results should be memoized by input root. + * @param matches Compiled matcher function to wrap with caching. + */ +function cacheParentResults(next, { adapter, cacheResults }, matches) { + if (cacheResults === false || typeof WeakMap === "undefined") { + return (element) => next(element) && matches(element); + } + // Use a cache to avoid re-checking children of an element. + // @ts-expect-error `Node` is not extending object + const resultCache = new WeakMap(); + function addResultToCache(element) { + const result = matches(element); + resultCache.set(element, result); + return result; + } + return function cachedMatcher(element) { + if (!next(element)) { + return false; + } + if (resultCache.has(element)) { + return resultCache.get(element) ?? false; + } + // Check all of the element's parents. + let node = element; + do { + const parent = getElementParent(node, adapter); + if (parent === null) { + return addResultToCache(element); + } + node = parent; + } while (!resultCache.has(node)); + return resultCache.get(node) ? addResultToCache(element) : false; }; } + +/** + * Create a copy of options, omitting `context` and `rootFunc`. + * + * This is used when compiling nested selectors (e.g. inside `:is`, `:not`, + * `:nth-child(… of S)`) so that the parent compilation state doesn't leak. + */ +function copyOptions(options) { + // Omit context and rootFunc so parent compilation state doesn't leak. + const { context: _, rootFunc: __, ...copied } = options; + return copied; +} + +/** + * RFC 4647 extended filtering with pre-split subtags. + * @param tag - Lowercased subtags of the element's language value. + * @param range - Lowercased subtags of the language range to match against. + */ +function extendedFilter(tag, range) { + if (range[0] !== "*" && range[0] !== tag[0]) return false; + let tagIndex = 1; + for (let rangeIndex = 1; rangeIndex < range.length; rangeIndex++) { + if (range[rangeIndex] === "*") continue; + // Skip non-singleton tag subtags until we find a match. + while (tagIndex < tag.length && tag[tagIndex] !== range[rangeIndex]) { + if (tag[tagIndex++].length <= 1) return false; + } + if (tagIndex >= tag.length) return false; + tagIndex++; + } + return true; +} +/** @see {@link https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo} */ +const nthOfRegex = /^(.+?)\s+of\s+(.+)$/is; +function compileNth(reverse, ofType) { + return function nth(next, rule, options, context, compileToken) { + const { adapter, equals } = options; + const ofMatch = ofType ? null : rule.match(nthOfRegex); + const nthCheck$1 = nthCheck(ofMatch ? ofMatch[1].trim() : rule); + if (nthCheck$1 === falseFunc) return falseFunc; + const ofSelector = + ofMatch && compileToken + ? compileToken( + parse$3(ofMatch[2].trim()), + copyOptions(options), + context + ) + : undefined; + if (ofSelector === falseFunc) return falseFunc; + if (nthCheck$1 === trueFunc && !ofSelector) { + return (element) => + getElementParent(element, adapter) !== null && next(element); + } + const shouldCount = ofSelector + ? (_element, sibling) => ofSelector(sibling) + : ofType + ? (element, sibling) => + adapter.getName(sibling) === adapter.getName(element) + : trueFunc; + if (reverse) { + return function nthLast(element) { + if (ofSelector && !ofSelector(element)) return false; + const siblings = adapter.getSiblings(element); + let pos = 0; + for (let index = siblings.length - 1; index >= 0; index--) { + const sibling = siblings[index]; + if (equals(element, sibling)) break; + if (adapter.isTag(sibling) && shouldCount(element, sibling)) pos++; + } + return nthCheck$1(pos) && next(element); + }; + } + return function nth(element) { + if (ofSelector && !ofSelector(element)) return false; + const siblings = adapter.getSiblings(element); + let pos = 0; + for (const sibling of siblings) { + if (equals(element, sibling)) break; + if (adapter.isTag(sibling) && shouldCount(element, sibling)) pos++; + } + return nthCheck$1(pos) && next(element); + }; + }; +} +/** + * Pre-compiled pseudo filters. + */ +const filters = { + contains(next, text, options) { + const { getText } = options.adapter; + return cacheParentResults(next, options, (element) => + getText(element).includes(text) + ); + }, + icontains(next, text, options) { + const itext = text.toLowerCase(); + const { getText } = options.adapter; + return cacheParentResults(next, options, (element) => + getText(element).toLowerCase().includes(itext) + ); + }, + // Location specific methods + "nth-child": compileNth(false, false), + "nth-last-child": compileNth(true, false), + "nth-of-type": compileNth(false, true), + "nth-last-of-type": compileNth(true, true), + // TODO determine the actual root element + root(next, _rule, { adapter }) { + return (element) => + getElementParent(element, adapter) === null && next(element); + }, + scope(next, rule, options, context) { + const { equals } = options; + if (!context || context.length === 0) { + // Equivalent to :root + return filters["root"](next, rule, options); + } + if (context.length === 1) { + // NOTE: can't be unpacked, as :has uses this for side-effects + return (element) => equals(context[0], element) && next(element); + } + return (element) => context.includes(element) && next(element); + }, + lang(next, code, { adapter }) { + const ranges = code + .split(",") + .map((r) => r.trim()) + .filter((r) => r.length > 0) + .map((r) => + r + .replace(/^['"]|['"]$/g, "") + .toLowerCase() + .split("-") + ); + return function lang(element) { + let node = element; + while (node != null) { + const value = + adapter.getAttributeValue(node, "xml:lang") ?? + adapter.getAttributeValue(node, "lang"); + if (value != null) { + if (!value) { + return ranges.some((r) => r[0] === "") && next(element); + } + const tag = value.toLowerCase().split("-"); + return ranges.some((r) => extendedFilter(tag, r)) && next(element); + } + const parent = adapter.getParent(node); + node = parent != null && adapter.isTag(parent) ? parent : null; + } + return ranges.some((r) => r[0] === "") && next(element); + }; + }, + hover: dynamicStatePseudo("isHovered"), + visited: dynamicStatePseudo("isVisited"), + active: dynamicStatePseudo("isActive") +}; +/** + * Dynamic state pseudos. These depend on optional Adapter methods. + * @param name The name of the adapter method to call. + * @returns Pseudo for the `filters` object. + */ +function dynamicStatePseudo(name) { + return function dynamicPseudo(next, _rule, { adapter }) { + const filterFunction = adapter[name]; + if (typeof filterFunction !== "function") { + return falseFunc; + } + return function active(element) { + return filterFunction(element) && next(element); + }; + }; +} + +/** + * CSS limits the characters considered as whitespace to space, tab & line + * feed. We add carriage returns as htmlparser2 doesn't normalize them to + * line feeds. + * @see {@link https://www.w3.org/TR/css-text-3/#white-space} + */ +const isDocumentWhiteSpace = /^[ \t\r\n]*$/; +// While filters are precompiled, pseudos get called when they are needed +/** Runtime pseudo selector implementations. */ +const pseudos = { + empty(element, { adapter }) { + const children = adapter.getChildren(element); + return ( + // First, make sure the tag does not have any element children. + children.every((element) => !adapter.isTag(element)) && + // Then, check that the text content is only whitespace. + children.every((element) => + // FIXME: `getText` call is potentially expensive. + isDocumentWhiteSpace.test(adapter.getText(element)) + ) + ); + }, + "first-child"(element, { adapter, equals }) { + if (adapter.prevElementSibling) { + return adapter.prevElementSibling(element) == null; + } + const firstChild = adapter + .getSiblings(element) + .find((sibling) => adapter.isTag(sibling)); + return firstChild != null && equals(element, firstChild); + }, + "last-child"(element, { adapter, equals }) { + const siblings = adapter.getSiblings(element); + for (let index = siblings.length - 1; index >= 0; index--) { + if (equals(element, siblings[index])) { + return true; + } + if (adapter.isTag(siblings[index])) { + break; + } + } + return false; + }, + "first-of-type"(element, { adapter, equals }) { + const siblings = adapter.getSiblings(element); + const elementName = adapter.getName(element); + for (const currentSibling of siblings) { + if (equals(element, currentSibling)) { + return true; + } + if ( + adapter.isTag(currentSibling) && + adapter.getName(currentSibling) === elementName + ) { + break; + } + } + return false; + }, + "last-of-type"(element, { adapter, equals }) { + const siblings = adapter.getSiblings(element); + const elementName = adapter.getName(element); + for (let index = siblings.length - 1; index >= 0; index--) { + const currentSibling = siblings[index]; + if (equals(element, currentSibling)) { + return true; + } + if ( + adapter.isTag(currentSibling) && + adapter.getName(currentSibling) === elementName + ) { + break; + } + } + return false; + }, + "only-of-type"(element, { adapter, equals }) { + const elementName = adapter.getName(element); + return adapter + .getSiblings(element) + .every( + (sibling) => + equals(element, sibling) || + !adapter.isTag(sibling) || + adapter.getName(sibling) !== elementName + ); + }, + "only-child"(element, { adapter, equals }) { + return adapter + .getSiblings(element) + .every((sibling) => equals(element, sibling) || !adapter.isTag(sibling)); + } +}; +/** + * Validate pseudo selector argument arity. + * @param pseudoClassCondition Pseudo-function implementation to wrap. + * @param name Name of the pseudo selector. + * @param subselect Subselector passed to the pseudo-function. + * @param argumentIndex Index of the argument parser to apply. + */ +function verifyPseudoArguments( + pseudoClassCondition, + name, + subselect, + argumentIndex +) { + if (subselect === null) { + if (pseudoClassCondition.length > argumentIndex) { + throw new Error(`Pseudo-class :${name} requires an argument`); + } + } else if (pseudoClassCondition.length === argumentIndex) { + throw new Error(`Pseudo-class :${name} doesn't have any arguments`); + } +} + +/** + * Check whether a selector token performs traversal. + * @param token Selector token(s) to compile. + */ +function isTraversal(token) { + return token.type === "_flexibleDescendant" || isTraversal$1(token); +} +/** + * Sort the parts of the passed selector, as there is potential for + * optimization (some types of selectors are faster than others). + * @param array Selector to sort + */ +function sortRules(array) { + const ratings = array.map(getQuality); + for (let index = 1; index < array.length; index++) { + const procNew = ratings[index]; + if (procNew < 0) { + continue; + } + // Use insertion sort to move the token to the correct position. + for ( + let currentIndex = index; + currentIndex > 0 && procNew < ratings[currentIndex - 1]; + currentIndex-- + ) { + const token = array[currentIndex]; + array[currentIndex] = array[currentIndex - 1]; + array[currentIndex - 1] = token; + ratings[currentIndex] = ratings[currentIndex - 1]; + ratings[currentIndex - 1] = procNew; + } + } +} +function getAttributeQuality(token) { + switch (token.action) { + case AttributeAction.Exists: { + return 10; + } + case AttributeAction.Equals: { + // Prefer ID selectors (eg. #ID) + return token.name === "id" ? 9 : 8; + } + case AttributeAction.Not: { + return 7; + } + case AttributeAction.Start: { + return 6; + } + case AttributeAction.End: { + return 6; + } + case AttributeAction.Any: { + return 5; + } + case AttributeAction.Hyphen: { + return 4; + } + case AttributeAction.Element: { + return 3; + } + } +} +/** + * Determine the quality of the passed token. The higher the number, the + * faster the token is to execute. + * @param token Token to get the quality of. + * @returns The token's quality. + */ +function getQuality(token) { + switch (token.type) { + case SelectorType.Universal: { + return 50; + } + case SelectorType.Tag: { + return 30; + } + case SelectorType.Attribute: { + return Math.floor( + getAttributeQuality(token) / + // `ignoreCase` adds some overhead, half the result if applicable. + (token.ignoreCase ? 2 : 1) + ); + } + case SelectorType.Pseudo: { + return token.data + ? token.name === "has" || + token.name === "contains" || + token.name === "icontains" + ? // Expensive in any case — run as late as possible. + 0 + : Array.isArray(token.data) + ? // Eg. `:is`, `:not` + Math.max( + // If we have traversals, try to avoid executing this selector + 0, + Math.min( + ...token.data.map((d) => Math.min(...d.map(getQuality))) + ) + ) + : 2 + : 3; + } + default: { + return -1; + } + } +} +/** + * Check whether a token or nested token includes `:scope`. + * @param t Selector token under inspection. + */ +function includesScopePseudo(t) { + return ( + t.type === SelectorType.Pseudo && + (t.name === "scope" || + (Array.isArray(t.data) && + t.data.some((data) => data.some(includesScopePseudo)))) + ); +} + +/** Used as a placeholder for :has. Will be replaced with the actual element. */ +const PLACEHOLDER_ELEMENT = {}; +/** + * Check if the selector has any properties that rely on the current element. + * If not, we can cache the result of the selector. + * + * We can't cache selectors that start with a traversal (e.g. `>`, `+`, `~`), + * or include a `:scope`. + * @param selector - The selector to check. + * @returns Whether the selector has any properties that rely on the current element. + */ +function hasDependsOnCurrentElement(selector) { + return selector.some( + (sel) => + sel.length > 0 && (isTraversal(sel[0]) || sel.some(includesScopePseudo)) + ); +} const is$1 = (next, token, options, context, compileToken) => { - const func = compileToken(token, copyOptions(options), context); - return func === boolbase.trueFunc + const compiledToken = compileToken(token, copyOptions(options), context); + return compiledToken === trueFunc ? next - : func === boolbase.falseFunc - ? boolbase.falseFunc - : (elem) => func(elem) && next(elem); + : compiledToken === falseFunc + ? falseFunc + : (element) => compiledToken(element) && next(element); }; /* * :not, :has, :is, :matches and :where have to compile selectors * doing this in src/pseudos.ts would lead to circular dependencies, * so we add them here */ +/** Pseudo selectors that compile nested selectors. */ const subselects = { is: is$1, /** @@ -6188,48 +6532,84 @@ const subselects = { matches: is$1, where: is$1, not(next, token, options, context, compileToken) { - const func = compileToken(token, copyOptions(options), context); - return func === boolbase.falseFunc + const compiledToken = compileToken(token, copyOptions(options), context); + return compiledToken === falseFunc ? next - : func === boolbase.trueFunc - ? boolbase.falseFunc - : (elem) => !func(elem) && next(elem); + : compiledToken === trueFunc + ? falseFunc + : (element) => !compiledToken(element) && next(element); }, has(next, subselect, options, _context, compileToken) { const { adapter } = options; - const opts = copyOptions(options); - opts.relativeSelector = true; + const copiedOptions = copyOptions(options); + copiedOptions.relativeSelector = true; const context = subselect.some((s) => s.some(isTraversal)) ? // Used as a placeholder. Will be replaced with the actual element. [PLACEHOLDER_ELEMENT] : undefined; - const compiled = compileToken(subselect, opts, context); - if (compiled === boolbase.falseFunc) return boolbase.falseFunc; - const hasElement = ensureIsTag(compiled, adapter); - // If `compiled` is `trueFunc`, we can skip this. - if (context && compiled !== boolbase.trueFunc) { - /* - * `shouldTestNextSiblings` will only be true if the query starts with - * a traversal (sibling or adjacent). That means we will always have a context. - */ - const { shouldTestNextSiblings = false } = compiled; - return (elem) => { - if (!next(elem)) return false; - context[0] = elem; - const childs = adapter.getChildren(elem); - const nextElements = shouldTestNextSiblings - ? [...childs, ...getNextSiblings(elem, adapter)] - : childs; - return adapter.existsOne(hasElement, nextElements); - }; + const skipCache = hasDependsOnCurrentElement(subselect); + const compiled = compileToken(subselect, copiedOptions, context); + if (compiled === falseFunc) { + return falseFunc; } - return (elem) => - next(elem) && adapter.existsOne(hasElement, adapter.getChildren(elem)); + // If `compiled` is `trueFunc`, we can skip this. + if (context && compiled !== trueFunc) { + return skipCache + ? (element) => { + if (!next(element)) { + return false; + } + context[0] = element; + const childs = adapter.getChildren(element); + return ( + findOne$1( + compiled, + compiled.shouldTestNextSiblings + ? [...childs, ...getNextSiblings(element, adapter)] + : childs, + options + ) !== null + ); + } + : cacheParentResults(next, options, (element) => { + context[0] = element; + return ( + findOne$1(compiled, adapter.getChildren(element), options) !== + null + ); + }); + } + const hasOne = (element) => + findOne$1(compiled, adapter.getChildren(element), options) !== null; + return skipCache + ? (element) => next(element) && hasOne(element) + : cacheParentResults(next, options, hasOne); } }; +/* + * Pseudo selectors + * + * Pseudo selectors are available in three forms: + * + * 1. Filters are called when the selector is compiled and return a function + * that has to return either false, or the results of `next()`. + * 2. Pseudos are called on execution. They have to return a boolean. + * 3. Subselects work like filters, but have an embedded selector that will be run separately. + * + * Filters are great if you want to do some pre-processing, or change the call order + * of `next()` and your code. + * Pseudos should be used to implement simple checks. + */ +/** + * Compile a pseudo selector into an executable query function. + * @param next Matcher to run after this matcher succeeds. + * @param selector Selector used to match elements. + * @param options Options that control this operation. + * @param context Context nodes used to scope selector matching. + * @param compileToken Function used to compile nested selector tokens. + */ function compilePseudoSelector(next, selector, options, context, compileToken) { - var _a; const { name, data } = selector; if (Array.isArray(data)) { if (!(name in subselects)) { @@ -6237,8 +6617,7 @@ function compilePseudoSelector(next, selector, options, context, compileToken) { } return subselects[name](next, data, options, context, compileToken); } - const userPseudo = - (_a = options.pseudos) === null || _a === void 0 ? void 0 : _a[name]; + const userPseudo = options.pseudos?.[name]; const stringPseudo = typeof userPseudo === "string" ? userPseudo : aliases[name]; if (typeof stringPseudo === "string") { @@ -6246,42 +6625,45 @@ function compilePseudoSelector(next, selector, options, context, compileToken) { throw new Error(`Pseudo ${name} doesn't have any arguments`); } // The alias has to be parsed here, to make sure options are respected. - const alias = parse$5(stringPseudo); + const alias = parse$3(stringPseudo); return subselects["is"](next, alias, options, context, compileToken); } if (typeof userPseudo === "function") { - verifyPseudoArgs(userPseudo, name, data, 1); - return (elem) => userPseudo(elem, data) && next(elem); + verifyPseudoArguments(userPseudo, name, data, 1); + return (element) => userPseudo(element, data) && next(element); } if (name in filters) { - return filters[name](next, data, options, context); + return filters[name](next, data, options, context, compileToken); } if (name in pseudos) { const pseudo = pseudos[name]; - verifyPseudoArgs(pseudo, name, data, 2); - return (elem) => pseudo(elem, options, data) && next(elem); + verifyPseudoArguments(pseudo, name, data, 2); + return (element) => pseudo(element, options, data) && next(element); } throw new Error(`Unknown pseudo-class :${name}`); } -function getElementParent(node, adapter) { - const parent = adapter.getParent(node); - if (parent && adapter.isTag(parent)) { - return parent; - } - return null; -} /* * All available rules */ +/** + * Compile a single selector token. + * @param next Matcher to run after this matcher succeeds. + * @param selector Selector used to match elements. + * @param options Options that control this operation. + * @param context Context nodes used to scope selector matching. + * @param compileToken Function used to compile nested selector tokens. + * @param hasExpensiveSubselector Whether the selector contains expensive subselectors. + */ function compileGeneralSelector( next, selector, options, context, - compileToken + compileToken, + hasExpensiveSubselector ) { - const { adapter, equals } = options; + const { adapter, equals, cacheResults } = options; switch (selector.type) { case SelectorType.PseudoElement: { throw new Error("Pseudo-elements are not supported by css-select"); @@ -6320,15 +6702,19 @@ function compileGeneralSelector( if (!options.xmlMode || options.lowerCaseTags) { name = name.toLowerCase(); } - return function tag(elem) { - return adapter.getName(elem) === name && next(elem); + return function tag(element) { + return adapter.getName(element) === name && next(element); }; } // Traversal case SelectorType.Descendant: { - if (options.cacheResults === false || typeof WeakSet === "undefined") { - return function descendant(elem) { - let current = elem; + if ( + !hasExpensiveSubselector || + cacheResults === false || + typeof WeakMap === "undefined" + ) { + return function descendant(element) { + let current = element; while ((current = getElementParent(current, adapter))) { if (next(current)) { return true; @@ -6337,16 +6723,24 @@ function compileGeneralSelector( return false; }; } - // @ts-expect-error `ElementNode` is not extending object - const isFalseCache = new WeakSet(); - return function cachedDescendant(elem) { - let current = elem; + const resultCache = new WeakMap(); + return function cachedDescendant(element) { + let current = element; + let result; while ((current = getElementParent(current, adapter))) { - if (!isFalseCache.has(current)) { - if (adapter.isTag(current) && next(current)) { + const cached = resultCache.get(current); + if (cached === undefined) { + result ??= { matches: false }; + result.matches = next(current); + resultCache.set(current, result); + if (result.matches) { return true; } - isFalseCache.add(current); + } else { + if (result) { + result.matches = cached.matches; + } + return cached.matches; } } return false; @@ -6354,33 +6748,37 @@ function compileGeneralSelector( } case "_flexibleDescendant": { // Include element itself, only used while querying an array - return function flexibleDescendant(elem) { - let current = elem; + return function flexibleDescendant(element) { + let current = element; do { - if (next(current)) return true; - } while ((current = getElementParent(current, adapter))); + if (next(current)) { + return true; + } + current = getElementParent(current, adapter); + } while (current); return false; }; } case SelectorType.Parent: { - return function parent(elem) { + return function parent(element) { return adapter - .getChildren(elem) - .some((elem) => adapter.isTag(elem) && next(elem)); + .getChildren(element) + .some((element) => adapter.isTag(element) && next(element)); }; } case SelectorType.Child: { - return function child(elem) { - const parent = adapter.getParent(elem); - return parent != null && adapter.isTag(parent) && next(parent); + return function child(element) { + const parent = getElementParent(element, adapter); + return parent !== null && next(parent); }; } case SelectorType.Sibling: { - return function sibling(elem) { - const siblings = adapter.getSiblings(elem); - for (let i = 0; i < siblings.length; i++) { - const currentSibling = siblings[i]; - if (equals(elem, currentSibling)) break; + return function sibling(element) { + const siblings = adapter.getSiblings(element); + for (const currentSibling of siblings) { + if (equals(element, currentSibling)) { + break; + } if (adapter.isTag(currentSibling) && next(currentSibling)) { return true; } @@ -6390,17 +6788,19 @@ function compileGeneralSelector( } case SelectorType.Adjacent: { if (adapter.prevElementSibling) { - return function adjacent(elem) { - const previous = adapter.prevElementSibling(elem); + return function adjacent(element) { + // biome-ignore lint/style/noNonNullAssertion: checked by if statement + const previous = adapter.prevElementSibling(element); return previous != null && next(previous); }; } - return function adjacent(elem) { - const siblings = adapter.getSiblings(elem); + return function adjacent(element) { + const siblings = adapter.getSiblings(element); let lastElement; - for (let i = 0; i < siblings.length; i++) { - const currentSibling = siblings[i]; - if (equals(elem, currentSibling)) break; + for (const currentSibling of siblings) { + if (equals(element, currentSibling)) { + break; + } if (adapter.isTag(currentSibling)) { lastElement = currentSibling; } @@ -6419,29 +6819,6 @@ function compileGeneralSelector( } } -/** - * Compiles a selector to an executable function. - * - * @param selector Selector to compile. - * @param options Compilation options. - * @param context Optional context for the selector. - */ -function compile$1(selector, options, context) { - const next = compileUnsafe(selector, options, context); - return ensureIsTag(next, options.adapter); -} -function compileUnsafe(selector, options, context) { - const token = typeof selector === "string" ? parse$5(selector) : selector; - return compileToken(token, options, context); -} -function includesScopePseudo(t) { - return ( - t.type === SelectorType.Pseudo && - (t.name === "scope" || - (Array.isArray(t.data) && - t.data.some((data) => data.some(includesScopePseudo)))) - ); -} const DESCENDANT_TOKEN = { type: SelectorType.Descendant }; const FLEXIBLE_DESCENDANT_TOKEN = { type: "_flexibleDescendant" @@ -6457,12 +6834,11 @@ const SCOPE_TOKEN = { */ function absolutize(token, { adapter }, context) { // TODO Use better check if the context is a document - const hasContext = !!(context === null || context === void 0 - ? void 0 - : context.every((e) => { - const parent = adapter.isTag(e) && adapter.getParent(e); - return e === PLACEHOLDER_ELEMENT || (parent && adapter.isTag(parent)); - })); + const hasContext = !!context?.every( + (element) => + element === PLACEHOLDER_ELEMENT || + (adapter.isTag(element) && getElementParent(element, adapter) !== null) + ); for (const t of token) { if ( t.length > 0 && @@ -6477,10 +6853,18 @@ function absolutize(token, { adapter }, context) { t.unshift(SCOPE_TOKEN); } } -function compileToken(token, options, context) { - var _a; - token.forEach(sortByProcedure); - context = (_a = options.context) !== null && _a !== void 0 ? _a : context; +/** + * Compile a parsed selector token into an executable query function. + * @param token Selector token(s) to compile. + * @param options Options that control this operation. + * @param compilationContext Compilation context for relative selector handling. + */ +function compileToken(token, options, compilationContext) { + for (const rules of token) { + sortRules(rules); + } + const { context = compilationContext, rootFunc: rootFunction = trueFunc } = + options; const isArrayContext = Array.isArray(context); const finalContext = context && (Array.isArray(context) ? context : [context]); @@ -6493,107 +6877,113 @@ function compileToken(token, options, context) { ); } let shouldTestNextSiblings = false; - const query = token - .map((rules) => { - if (rules.length >= 2) { - const [first, second] = rules; - if (first.type !== SelectorType.Pseudo || first.name !== "scope"); - else if (isArrayContext && second.type === SelectorType.Descendant) { - rules[1] = FLEXIBLE_DESCENDANT_TOKEN; - } else if ( - second.type === SelectorType.Adjacent || - second.type === SelectorType.Sibling - ) { - shouldTestNextSiblings = true; - } + let query = falseFunc; + combineLoop: for (const rules of token) { + if (rules.length >= 2) { + const [first, second] = rules; + if (first.type !== SelectorType.Pseudo || first.name !== "scope"); + else if (isArrayContext && second.type === SelectorType.Descendant) { + rules[1] = FLEXIBLE_DESCENDANT_TOKEN; + } else if ( + second.type === SelectorType.Adjacent || + second.type === SelectorType.Sibling + ) { + shouldTestNextSiblings = true; } - return compileRules(rules, options, finalContext); - }) - .reduce(reduceRules, boolbase.falseFunc); + } + let next = rootFunction; + let hasExpensiveSubselector = false; + for (const rule of rules) { + next = compileGeneralSelector( + next, + rule, + options, + finalContext, + compileToken, + hasExpensiveSubselector + ); + const quality = getQuality(rule); + if (quality === 0) { + hasExpensiveSubselector = true; + } + // If the sub-selector won't match any elements, skip it. + if (next === falseFunc) { + continue combineLoop; + } + } + // If we have a function that always returns true, we can stop here. + if (next === rootFunction) { + return rootFunction; + } + query = query === falseFunc ? next : or(query, next); + } query.shouldTestNextSiblings = shouldTestNextSiblings; return query; } -function compileRules(rules, options, context) { - var _a; - return rules.reduce( - (previous, rule) => - previous === boolbase.falseFunc - ? boolbase.falseFunc - : compileGeneralSelector( - previous, - rule, - options, - context, - compileToken - ), - (_a = options.rootFunc) !== null && _a !== void 0 ? _a : boolbase.trueFunc - ); -} -function reduceRules(a, b) { - if (b === boolbase.falseFunc || a === boolbase.trueFunc) { - return a; - } - if (a === boolbase.falseFunc || b === boolbase.trueFunc) { - return b; - } - return function combine(elem) { - return a(elem) || b(elem); - }; +function or(a, b) { + return (element) => a(element) || b(element); } const defaultEquals = (a, b) => a === b; const defaultOptions = { - adapter: DomUtils, + adapter: { ...DomUtils, isTag: isTag$1 }, equals: defaultEquals }; function convertOptionFormats(options) { - var _a, _b, _c, _d; /* * We force one format of options to the other one. */ // @ts-expect-error Default options may have incompatible `Node` / `ElementNode`. - const opts = - options !== null && options !== void 0 ? options : defaultOptions; + const finalOptions = options ?? defaultOptions; // @ts-expect-error Same as above. - (_a = opts.adapter) !== null && _a !== void 0 - ? _a - : (opts.adapter = DomUtils); + finalOptions.adapter ??= defaultOptions.adapter; // @ts-expect-error `equals` does not exist on `Options` - (_b = opts.equals) !== null && _b !== void 0 - ? _b - : (opts.equals = - (_d = - (_c = opts.adapter) === null || _c === void 0 - ? void 0 - : _c.equals) !== null && _d !== void 0 - ? _d - : defaultEquals); - return opts; -} -function wrapCompile(func) { - return function addAdapter(selector, options, context) { - const opts = convertOptionFormats(options); - return func(selector, opts, context); - }; + finalOptions.equals ??= finalOptions.adapter?.equals ?? defaultEquals; + return finalOptions; } /** - * Compiles the query, returns a function. + * Compiles a selector to an executable function. + * + * The returned function checks if each passed node is an element. Use + * `_compileUnsafe` to skip this check. + * @param selector Selector to compile. + * @param options Compilation options. + * @param context Optional context for the selector. */ -const compile = wrapCompile(compile$1); +function compile(selector, options, context) { + const convertedOptions = convertOptionFormats(options); + const next = _compileUnsafe(selector, convertedOptions, context); + return next === falseFunc + ? falseFunc + : (element) => convertedOptions.adapter.isTag(element) && next(element); +} +/** + * Like `compile`, but does not add a check if elements are tags. + * @param selector Selector used to match elements. + * @param options Options that control this operation. + * @param context Context nodes used to scope selector matching. + */ +function _compileUnsafe(selector, options, context) { + return compileToken( + typeof selector === "string" ? parse$3(selector) : selector, + convertOptionFormats(options), + context + ); +} /** * Tests whether or not an element is matched by query. - * * @template Node The generic Node type for the DOM adapter being used. * @template ElementNode The Node type for elements for the DOM adapter being used. - * @param elem The element to test if it matches the query. + * @param element The element to test if it matches the query. * @param query can be either a CSS selector string or a compiled query function. * @param [options] options for querying the document. * @see compile for supported selector queries. - * @returns + * @returns Whether the element matches the query. */ -function is(elem, query, options) { - const opts = convertOptionFormats(options); - return (typeof query === "function" ? query : compile$1(query, opts))(elem); +function is(element, query, options) { + return (typeof query === "function" ? query : compile(query, options))( + element + ); } const { isArray } = Array; @@ -6703,33 +7093,10 @@ const matches = (element, selectors) => adapter }); -const { replace } = ""; - -// escape -const ca = /[<>&\xA0]/g; - -const esca = { - "\xA0": " ", - "&": "&", - "<": "<", - ">": ">" -}; - -const pe = (m) => esca[m]; - -/** - * Safely escape HTML entities such as `&`, `<`, `>` only. - * @param {string} es the input to safely escape - * @returns {string} the escaped input, and it **throws** an error if - * the input type is unexpected, except for boolean and numbers, - * converted as string. - */ -const escape = (es) => replace.call(es, ca, pe); - /** * @implements globalThis.Text */ -class Text$1 extends CharacterData$1 { +let Text$1 = class Text extends CharacterData$1 { constructor(ownerDocument, data = "") { super(ownerDocument, "#text", TEXT_NODE, data); } @@ -6754,15 +7121,16 @@ class Text$1 extends CharacterData$1 { cloneNode() { const { ownerDocument, [VALUE]: data } = this; - return new Text$1(ownerDocument, data); + return new Text(ownerDocument, data); } toString() { return escape(this[VALUE]); } -} +}; // https://dom.spec.whatwg.org/#interface-parentnode +// Document, DocumentFragment, Element const isNode = (node) => node instanceof Node$1; @@ -6779,7 +7147,7 @@ const insert = (parentNode, child, nodes) => { [typeof NEXT]: NodeStruct, [typeof PREV]: NodeStruct, [typeof START]: NodeStruct, - nodeType: typeof ATTRIBUTE_NODE | typeof DOCUMENT_FRAGMENT_NODE | typeof ELEMENT_NODE | typeof TEXT_NODE | typeof NODE_END | typeof COMMENT_NODE, + nodeType: typeof ATTRIBUTE_NODE | typeof DOCUMENT_FRAGMENT_NODE | typeof ELEMENT_NODE | typeof TEXT_NODE | typeof NODE_END | typeof COMMENT_NODE | typeof CDATA_SECTION_NODE, ownerDocument: Document, parentNode: ParentNode, }} NodeStruct */ @@ -6814,7 +7182,7 @@ class ParentNode extends Node$1 { let { firstElementChild } = this; while (firstElementChild) { children.push(firstElementChild); - firstElementChild = nextElementSibling(firstElementChild); + firstElementChild = nextElementSibling$1(firstElementChild); } return children; } @@ -6917,7 +7285,10 @@ class ParentNode extends Node$1 { let { [NEXT]: next, [END]: end } = this; while (next !== end) { if (next.nodeType === ELEMENT_NODE && matches(next)) return next; - next = next[NEXT]; + next = + next.nodeType === ELEMENT_NODE && next.localName === "template" + ? next[END] + : next[NEXT]; } return null; } @@ -6928,7 +7299,10 @@ class ParentNode extends Node$1 { let { [NEXT]: next, [END]: end } = this; while (next !== end) { if (next.nodeType === ELEMENT_NODE && matches(next)) elements.push(next); - next = next[NEXT]; + next = + next.nodeType === ELEMENT_NODE && next.localName === "template" + ? next[END] + : next[NEXT]; } return elements; } @@ -6976,6 +7350,7 @@ class ParentNode extends Node$1 { } case TEXT_NODE: case COMMENT_NODE: + case CDATA_SECTION_NODE: node.remove(); /* eslint no-fallthrough:0 */ // this covers DOCUMENT_TYPE_NODE too @@ -7018,6 +7393,7 @@ class ParentNode extends Node$1 { } // https://dom.spec.whatwg.org/#interface-nonelementparentnode +// Document, DocumentFragment class NonElementParentNode extends ParentNode { getElementById(id) { @@ -7055,16 +7431,16 @@ class NonElementParentNode extends ParentNode { /** * @implements globalThis.DocumentFragment */ -class DocumentFragment$1 extends NonElementParentNode { +let DocumentFragment$1 = class DocumentFragment extends NonElementParentNode { constructor(ownerDocument) { super(ownerDocument, "#document-fragment", DOCUMENT_FRAGMENT_NODE); } -} +}; /** * @implements globalThis.DocumentType */ -class DocumentType$1 extends Node$1 { +let DocumentType$1 = class DocumentType extends Node$1 { constructor(ownerDocument, name, publicId = "", systemId = "") { super(ownerDocument, "#document-type", DOCUMENT_TYPE_NODE); this.name = name; @@ -7074,7 +7450,7 @@ class DocumentType$1 extends Node$1 { cloneNode() { const { ownerDocument, name, publicId, systemId } = this; - return new DocumentType$1(ownerDocument, name, publicId, systemId); + return new DocumentType(ownerDocument, name, publicId, systemId); } toString() { @@ -7094,7 +7470,7 @@ class DocumentType$1 extends Node$1 { documentTypeAsJSON(this, json); return json; } -} +}; /** * @param {Node} node @@ -7113,12 +7489,23 @@ const setInnerHtml = (node, html) => { document[CUSTOM_ELEMENTS] = ownerDocument[CUSTOM_ELEMENTS]; const { childNodes } = parseFromString(document, ignoreCase(node), html); - node.replaceChildren(...childNodes); + node.replaceChildren(...childNodes.map(setOwnerDocument, ownerDocument)); }; +function setOwnerDocument(node) { + node.ownerDocument = this; + switch (node.nodeType) { + case ELEMENT_NODE: + case DOCUMENT_FRAGMENT_NODE: + node.childNodes.forEach(setOwnerDocument, this); + break; + } + return node; +} + var uhyphen = (camel) => camel - .replace(/(([A-Z0-9])([A-Z0-9][a-z]))|(([a-z])([A-Z]))/g, "$2$5-$3$6") + .replace(/(([A-Z0-9])([A-Z0-9][a-z]))|(([a-z0-9]+)([A-Z]))/g, "$2$5-$3$6") .toLowerCase(); const refs$1 = new WeakMap(); @@ -7314,7 +7701,7 @@ const handler$1 = { /** * @implements globalThis.CSSStyleDeclaration */ -class CSSStyleDeclaration$1 extends Map { +let CSSStyleDeclaration$1 = class CSSStyleDeclaration extends Map { constructor(element) { super(); refs.set(this, element); @@ -7347,7 +7734,9 @@ class CSSStyleDeclaration$1 extends Map { } [Symbol.iterator]() { - const keys = getKeys(this[PRIVATE]); + const self = this[PRIVATE]; + updateKeys(self); + const keys = getKeys(self); const { length } = keys; let i = 0; return { @@ -7369,7 +7758,7 @@ class CSSStyleDeclaration$1 extends Map { self.forEach(push, cssText); return cssText.join(";"); } -} +}; const { prototype } = CSSStyleDeclaration$1; @@ -7387,6 +7776,10 @@ const AT_TARGET = 2; const CAPTURING_PHASE = 1; const NONE = 0; +function getCurrentTarget(ev) { + return ev.currentTarget; +} + /** * @implements globalThis.Event */ @@ -7439,7 +7832,7 @@ class GlobalEvent { // simplified implementation, should be https://dom.spec.whatwg.org/#dom-event-composedpath composedPath() { - return this._path; + return this._path.map(getCurrentTarget); } stopPropagation() { @@ -7500,7 +7893,7 @@ class NamedNodeMap extends Array { /** * @implements globalThis.ShadowRoot */ -class ShadowRoot$1 extends NonElementParentNode { +let ShadowRoot$1 = class ShadowRoot extends NonElementParentNode { constructor(host) { super(host.ownerDocument, "#shadow-root", DOCUMENT_FRAGMENT_NODE); this.host = host; @@ -7512,7 +7905,7 @@ class ShadowRoot$1 extends NonElementParentNode { set innerHTML(html) { setInnerHtml(this, html); } -} +}; // https://dom.spec.whatwg.org/#interface-element @@ -7543,7 +7936,7 @@ const isVoid = ({ localName, ownerDocument }) => { /** * @implements globalThis.Element */ -class Element$1 extends ParentNode { +let Element$1 = class Element extends ParentNode { constructor(ownerDocument, localName) { super(ownerDocument, localName, ELEMENT_NODE); this[CLASS_LIST] = null; @@ -7564,12 +7957,15 @@ class Element$1 extends ParentNode { get nextSibling() { return nextSibling(this); } + get namespaceURI() { + return "http://www.w3.org/1999/xhtml"; + } get previousElementSibling() { return previousElementSibling(this); } get nextElementSibling() { - return nextElementSibling(this); + return nextElementSibling$1(this); } before(...nodes) { @@ -7600,7 +7996,7 @@ class Element$1 extends ParentNode { set className(value) { const { classList } = this; classList.clear(); - classList.add(...value.split(/\s+/)); + classList.add(...$String(value).split(/\s+/)); } get nodeName() { @@ -7618,6 +8014,19 @@ class Element$1 extends ParentNode { return this[DATASET] || (this[DATASET] = new DOMStringMap(this)); } + getBoundingClientRect() { + return { + x: 0, + y: 0, + bottom: 0, + height: 0, + left: 0, + right: 0, + top: 0, + width: 0 + }; + } + get nonce() { return stringAttribute.get(this, "nonce"); } @@ -7635,6 +8044,13 @@ class Element$1 extends ParentNode { set tabIndex(value) { numericAttribute.set(this, "tabindex", value); } + + get slot() { + return stringAttribute.get(this, "slot"); + } + set slot(value) { + stringAttribute.set(this, "slot", value); + } // </specialGetters> // <contentRelated> @@ -7663,7 +8079,9 @@ class Element$1 extends ParentNode { const text = []; let { [NEXT]: next, [END]: end } = this; while (next !== end) { - if (next.nodeType === TEXT_NODE) text.push(next.textContent); + const nodeType = next.nodeType; + if (nodeType === TEXT_NODE || nodeType === CDATA_SECTION_NODE) + text.push(next.textContent); next = next[NEXT]; } return text.join(""); @@ -7671,7 +8089,8 @@ class Element$1 extends ParentNode { set textContent(text) { this.replaceChildren(); - if (text) this.appendChild(new Text$1(this.ownerDocument, text)); + if (text != null && text !== "") + this.appendChild(new Text$1(this.ownerDocument, text)); } get innerHTML() { @@ -7709,7 +8128,10 @@ class Element$1 extends ParentNode { getAttribute(name) { if (name === "class") return this.className; const attribute = this.getAttributeNode(name); - return attribute && attribute.value; + return ( + attribute && + (ignoreCase(this) ? attribute.value : escape(attribute.value)) + ); } getAttributeNode(name) { @@ -7811,7 +8233,6 @@ class Element$1 extends ParentNode { // TODO: shadowRoot should be likely a specialized class that extends DocumentFragment // but until DSD is out, I am not sure I should spend time on this. const shadowRoot = new ShadowRoot$1(this); - shadowRoot.append(...this.childNodes); shadowRoots.set(this, { mode: init.mode, shadowRoot @@ -7860,9 +8281,10 @@ class Element$1 extends ParentNode { } insertAdjacentHTML(position, html) { - const template = this.ownerDocument.createElement("template"); - template.innerHTML = html; - this.insertAdjacentElement(position, template.content); + this.insertAdjacentElement( + position, + htmlToFragment(this.ownerDocument, html) + ); } insertAdjacentText(position, text) { @@ -7895,9 +8317,15 @@ class Element$1 extends ParentNode { parentNode = node; break; } - case ATTRIBUTE_NODE: + case ATTRIBUTE_NODE: { + const attr = next.cloneNode(deep); + attr.ownerElement = parentNode; + addNext(attr); + break; + } case TEXT_NODE: case COMMENT_NODE: + case CDATA_SECTION_NODE: addNext(next.cloneNode(deep)); break; } @@ -7951,6 +8379,7 @@ class Element$1 extends ParentNode { break; case TEXT_NODE: case COMMENT_NODE: + case CDATA_SECTION_NODE: out.push((isOpened ? ">" : "") + next); isOpened = false; break; @@ -7986,7 +8415,7 @@ class Element$1 extends ParentNode { return this.setAttributeNode(attr); } /* c8 ignore stop */ -} +}; const classNames = new WeakMap(); @@ -8003,7 +8432,7 @@ const handler = { /** * @implements globalThis.SVGElement */ -class SVGElement$1 extends Element$1 { +let SVGElement$1 = class SVGElement extends Element$1 { constructor(ownerDocument, localName, ownerSVGElement = null) { super(ownerDocument, localName); this.ownerSVGElement = ownerSVGElement; @@ -8019,10 +8448,14 @@ class SVGElement$1 extends Element$1 { set className(value) { const { classList } = this; classList.clear(); - classList.add(...value.split(/\s+/)); + classList.add(...$String(value).split(/\s+/)); } /* c8 ignore stop */ + get namespaceURI() { + return "http://www.w3.org/2000/svg"; + } + getAttribute(name) { return name === "class" ? [...this.classList].join(" ") @@ -8037,7 +8470,7 @@ class SVGElement$1 extends Element$1 { } super.setAttribute(name, value); } -} +}; /* c8 ignore start */ const illegalConstructor = () => { @@ -8050,6 +8483,12 @@ function Attr() { setPrototypeOf(Attr, Attr$1); Attr.prototype = Attr$1.prototype; +function CDATASection() { + illegalConstructor(); +} +setPrototypeOf(CDATASection, CDATASection$1); +CDATASection.prototype = CDATASection$1.prototype; + function CharacterData() { illegalConstructor(); } @@ -8059,8 +8498,8 @@ CharacterData.prototype = CharacterData$1.prototype; function Comment() { illegalConstructor(); } -setPrototypeOf(Comment, Comment$1); -Comment.prototype = Comment$1.prototype; +setPrototypeOf(Comment, Comment$2); +Comment.prototype = Comment$2.prototype; function DocumentFragment() { illegalConstructor(); @@ -8107,6 +8546,7 @@ SVGElement.prototype = SVGElement$1.prototype; const Facades = { Attr, + CDATASection, CharacterData, Comment, DocumentFragment, @@ -8183,7 +8623,13 @@ class HTMLElement extends Element$1 { this.dispatchEvent(new GlobalEvent("blur")); } click() { - this.dispatchEvent(new GlobalEvent("click")); + const clickEvent = new GlobalEvent("click", { + bubbles: true, + cancelable: true + }); + clickEvent.button = 0; + + this.dispatchEvent(clickEvent); } // Boolean getters @@ -8740,14 +9186,14 @@ class HTMLElement extends Element$1 { /* c8 ignore stop */ } -const tagName$e = "template"; +const tagName$h = "template"; /** * @implements globalThis.HTMLTemplateElement */ class HTMLTemplateElement extends HTMLElement { constructor(ownerDocument) { - super(ownerDocument, tagName$e); + super(ownerDocument, tagName$h); const content = this.ownerDocument.createDocumentFragment(); (this[CONTENT] = content)[PRIVATE] = this; } @@ -8761,7 +9207,7 @@ class HTMLTemplateElement extends HTMLElement { } } -registerHTMLClass(tagName$e, HTMLTemplateElement); +registerHTMLClass(tagName$h, HTMLTemplateElement); /** * @implements globalThis.HTMLHtmlElement @@ -8784,17 +9230,17 @@ class TextElement extends HTMLElement { toString() { const outerHTML = toString.call(this.cloneNode()); - return outerHTML.replace(/></, `>${this.textContent}<`); + return outerHTML.replace("><", () => `>${this.textContent}<`); } } -const tagName$d = "script"; +const tagName$g = "script"; /** * @implements globalThis.HTMLScriptElement */ class HTMLScriptElement extends TextElement { - constructor(ownerDocument, localName = tagName$d) { + constructor(ownerDocument, localName = tagName$g) { super(ownerDocument, localName); } @@ -8854,9 +9300,16 @@ class HTMLScriptElement extends TextElement { set async(value) { booleanAttribute.set(this, "async", value); } + + get text() { + return this.textContent; + } + set text(content) { + this.textContent = content; + } } -registerHTMLClass(tagName$d, HTMLScriptElement); +registerHTMLClass(tagName$g, HTMLScriptElement); /** * @implements globalThis.HTMLFrameElement @@ -8867,13 +9320,13 @@ class HTMLFrameElement extends HTMLElement { } } -const tagName$c = "iframe"; +const tagName$f = "iframe"; /** * @implements globalThis.HTMLIFrameElement */ class HTMLIFrameElement extends HTMLElement { - constructor(ownerDocument, localName = tagName$c) { + constructor(ownerDocument, localName = tagName$f) { super(ownerDocument, localName); } @@ -8884,10 +9337,52 @@ class HTMLIFrameElement extends HTMLElement { set src(value) { stringAttribute.set(this, "src", value); } + + get srcdoc() { + return stringAttribute.get(this, "srcdoc"); + } + set srcdoc(value) { + stringAttribute.set(this, "srcdoc", value); + } + + get name() { + return stringAttribute.get(this, "name"); + } + set name(value) { + stringAttribute.set(this, "name", value); + } + + get allow() { + return stringAttribute.get(this, "allow"); + } + set allow(value) { + stringAttribute.set(this, "allow", value); + } + + get allowFullscreen() { + return booleanAttribute.get(this, "allowfullscreen"); + } + set allowFullscreen(value) { + booleanAttribute.set(this, "allowfullscreen", value); + } + + get referrerPolicy() { + return stringAttribute.get(this, "referrerpolicy"); + } + set referrerPolicy(value) { + stringAttribute.set(this, "referrerpolicy", value); + } + + get loading() { + return stringAttribute.get(this, "loading"); + } + set loading(value) { + stringAttribute.set(this, "loading", value); + } /* c8 ignore stop */ } -registerHTMLClass(tagName$c, HTMLIFrameElement); +registerHTMLClass(tagName$f, HTMLIFrameElement); /** * @implements globalThis.HTMLObjectElement @@ -8916,72 +9411,90 @@ class HTMLBodyElement extends HTMLElement { } } +var lib = {}; + var CSSStyleDeclaration = {}; -var parse$2 = {}; +var parse$1 = {}; var CSSStyleSheet = {}; var StyleSheet = {}; -//.CommonJS -var CSSOM$c = {}; -///CommonJS +var hasRequiredStyleSheet; -/** - * @constructor - * @see http://dev.w3.org/csswg/cssom/#the-stylesheet-interface - */ -CSSOM$c.StyleSheet = function StyleSheet() { - this.parentStyleSheet = null; -}; +function requireStyleSheet() { + if (hasRequiredStyleSheet) return StyleSheet; + hasRequiredStyleSheet = 1; + //.CommonJS + var CSSOM = {}; + ///CommonJS -//.CommonJS -StyleSheet.StyleSheet = CSSOM$c.StyleSheet; + /** + * @constructor + * @see http://dev.w3.org/csswg/cssom/#the-stylesheet-interface + */ + CSSOM.StyleSheet = function StyleSheet() { + this.parentStyleSheet = null; + }; + + //.CommonJS + StyleSheet.StyleSheet = CSSOM.StyleSheet; + ///CommonJS + return StyleSheet; +} var CSSStyleRule = {}; var CSSRule = {}; -//.CommonJS -var CSSOM$b = {}; -///CommonJS +var hasRequiredCSSRule; -/** - * @constructor - * @see http://dev.w3.org/csswg/cssom/#the-cssrule-interface - * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule - */ -CSSOM$b.CSSRule = function CSSRule() { - this.parentRule = null; - this.parentStyleSheet = null; -}; +function requireCSSRule() { + if (hasRequiredCSSRule) return CSSRule; + hasRequiredCSSRule = 1; + //.CommonJS + var CSSOM = {}; + ///CommonJS -CSSOM$b.CSSRule.UNKNOWN_RULE = 0; // obsolete -CSSOM$b.CSSRule.STYLE_RULE = 1; -CSSOM$b.CSSRule.CHARSET_RULE = 2; // obsolete -CSSOM$b.CSSRule.IMPORT_RULE = 3; -CSSOM$b.CSSRule.MEDIA_RULE = 4; -CSSOM$b.CSSRule.FONT_FACE_RULE = 5; -CSSOM$b.CSSRule.PAGE_RULE = 6; -CSSOM$b.CSSRule.KEYFRAMES_RULE = 7; -CSSOM$b.CSSRule.KEYFRAME_RULE = 8; -CSSOM$b.CSSRule.MARGIN_RULE = 9; -CSSOM$b.CSSRule.NAMESPACE_RULE = 10; -CSSOM$b.CSSRule.COUNTER_STYLE_RULE = 11; -CSSOM$b.CSSRule.SUPPORTS_RULE = 12; -CSSOM$b.CSSRule.DOCUMENT_RULE = 13; -CSSOM$b.CSSRule.FONT_FEATURE_VALUES_RULE = 14; -CSSOM$b.CSSRule.VIEWPORT_RULE = 15; -CSSOM$b.CSSRule.REGION_STYLE_RULE = 16; + /** + * @constructor + * @see http://dev.w3.org/csswg/cssom/#the-cssrule-interface + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule + */ + CSSOM.CSSRule = function CSSRule() { + this.parentRule = null; + this.parentStyleSheet = null; + }; -CSSOM$b.CSSRule.prototype = { - constructor: CSSOM$b.CSSRule - //FIXME -}; + CSSOM.CSSRule.UNKNOWN_RULE = 0; // obsolete + CSSOM.CSSRule.STYLE_RULE = 1; + CSSOM.CSSRule.CHARSET_RULE = 2; // obsolete + CSSOM.CSSRule.IMPORT_RULE = 3; + CSSOM.CSSRule.MEDIA_RULE = 4; + CSSOM.CSSRule.FONT_FACE_RULE = 5; + CSSOM.CSSRule.PAGE_RULE = 6; + CSSOM.CSSRule.KEYFRAMES_RULE = 7; + CSSOM.CSSRule.KEYFRAME_RULE = 8; + CSSOM.CSSRule.MARGIN_RULE = 9; + CSSOM.CSSRule.NAMESPACE_RULE = 10; + CSSOM.CSSRule.COUNTER_STYLE_RULE = 11; + CSSOM.CSSRule.SUPPORTS_RULE = 12; + CSSOM.CSSRule.DOCUMENT_RULE = 13; + CSSOM.CSSRule.FONT_FEATURE_VALUES_RULE = 14; + CSSOM.CSSRule.VIEWPORT_RULE = 15; + CSSOM.CSSRule.REGION_STYLE_RULE = 16; -//.CommonJS -CSSRule.CSSRule = CSSOM$b.CSSRule; + CSSOM.CSSRule.prototype = { + constructor: CSSOM.CSSRule + //FIXME + }; + + //.CommonJS + CSSRule.CSSRule = CSSOM.CSSRule; + ///CommonJS + return CSSRule; +} var hasRequiredCSSStyleRule; @@ -8991,7 +9504,7 @@ function requireCSSStyleRule() { //.CommonJS var CSSOM = { CSSStyleDeclaration: requireCSSStyleDeclaration().CSSStyleDeclaration, - CSSRule: CSSRule.CSSRule + CSSRule: requireCSSRule().CSSRule }; ///CommonJS @@ -9182,7 +9695,7 @@ function requireCSSStyleSheet() { hasRequiredCSSStyleSheet = 1; //.CommonJS var CSSOM = { - StyleSheet: StyleSheet.StyleSheet, + StyleSheet: requireStyleSheet().StyleSheet, CSSStyleRule: requireCSSStyleRule().CSSStyleRule }; ///CommonJS @@ -9269,62 +9782,70 @@ var CSSImportRule = {}; var MediaList = {}; -//.CommonJS -var CSSOM$a = {}; -///CommonJS +var hasRequiredMediaList; -/** - * @constructor - * @see http://dev.w3.org/csswg/cssom/#the-medialist-interface - */ -CSSOM$a.MediaList = function MediaList() { - this.length = 0; -}; - -CSSOM$a.MediaList.prototype = { - constructor: CSSOM$a.MediaList, +function requireMediaList() { + if (hasRequiredMediaList) return MediaList; + hasRequiredMediaList = 1; + //.CommonJS + var CSSOM = {}; + ///CommonJS /** - * @return {string} + * @constructor + * @see http://dev.w3.org/csswg/cssom/#the-medialist-interface */ - get mediaText() { - return Array.prototype.join.call(this, ", "); - }, + CSSOM.MediaList = function MediaList() { + this.length = 0; + }; - /** - * @param {string} value - */ - set mediaText(value) { - var values = value.split(","); - var length = (this.length = values.length); - for (var i = 0; i < length; i++) { - this[i] = values[i].trim(); + CSSOM.MediaList.prototype = { + constructor: CSSOM.MediaList, + + /** + * @return {string} + */ + get mediaText() { + return Array.prototype.join.call(this, ", "); + }, + + /** + * @param {string} value + */ + set mediaText(value) { + var values = value.split(","); + var length = (this.length = values.length); + for (var i = 0; i < length; i++) { + this[i] = values[i].trim(); + } + }, + + /** + * @param {string} medium + */ + appendMedium: function (medium) { + if (Array.prototype.indexOf.call(this, medium) === -1) { + this[this.length] = medium; + this.length++; + } + }, + + /** + * @param {string} medium + */ + deleteMedium: function (medium) { + var index = Array.prototype.indexOf.call(this, medium); + if (index !== -1) { + Array.prototype.splice.call(this, index, 1); + } } - }, + }; - /** - * @param {string} medium - */ - appendMedium: function (medium) { - if (Array.prototype.indexOf.call(this, medium) === -1) { - this[this.length] = medium; - this.length++; - } - }, - - /** - * @param {string} medium - */ - deleteMedium: function (medium) { - var index = Array.prototype.indexOf.call(this, medium); - if (index !== -1) { - Array.prototype.splice.call(this, index, 1); - } - } -}; - -//.CommonJS -MediaList.MediaList = CSSOM$a.MediaList; + //.CommonJS + MediaList.MediaList = CSSOM.MediaList; + ///CommonJS + return MediaList; +} var hasRequiredCSSImportRule; @@ -9333,9 +9854,9 @@ function requireCSSImportRule() { hasRequiredCSSImportRule = 1; //.CommonJS var CSSOM = { - CSSRule: CSSRule.CSSRule, + CSSRule: requireCSSRule().CSSRule, CSSStyleSheet: requireCSSStyleSheet().CSSStyleSheet, - MediaList: MediaList.MediaList + MediaList: requireMediaList().MediaList }; ///CommonJS @@ -9471,190 +9992,224 @@ function requireCSSImportRule() { var CSSGroupingRule = {}; -//.CommonJS -var CSSOM$9 = { - CSSRule: CSSRule.CSSRule -}; -///CommonJS +var hasRequiredCSSGroupingRule; -/** - * @constructor - * @see https://drafts.csswg.org/cssom/#the-cssgroupingrule-interface - */ -CSSOM$9.CSSGroupingRule = function CSSGroupingRule() { - CSSOM$9.CSSRule.call(this); - this.cssRules = []; -}; +function requireCSSGroupingRule() { + if (hasRequiredCSSGroupingRule) return CSSGroupingRule; + hasRequiredCSSGroupingRule = 1; + //.CommonJS + var CSSOM = { + CSSRule: requireCSSRule().CSSRule + }; + ///CommonJS -CSSOM$9.CSSGroupingRule.prototype = new CSSOM$9.CSSRule(); -CSSOM$9.CSSGroupingRule.prototype.constructor = CSSOM$9.CSSGroupingRule; + /** + * @constructor + * @see https://drafts.csswg.org/cssom/#the-cssgroupingrule-interface + */ + CSSOM.CSSGroupingRule = function CSSGroupingRule() { + CSSOM.CSSRule.call(this); + this.cssRules = []; + }; -/** - * Used to insert a new CSS rule to a list of CSS rules. - * - * @example - * cssGroupingRule.cssText - * -> "body{margin:0;}" - * cssGroupingRule.insertRule("img{border:none;}", 1) - * -> 1 - * cssGroupingRule.cssText - * -> "body{margin:0;}img{border:none;}" - * - * @param {string} rule - * @param {number} [index] - * @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-insertrule - * @return {number} The index within the grouping rule's collection of the newly inserted rule. - */ -CSSOM$9.CSSGroupingRule.prototype.insertRule = function insertRule( - rule, - index -) { - if (index < 0 || index > this.cssRules.length) { - throw new RangeError("INDEX_SIZE_ERR"); - } - var cssRule = CSSOM$9.parse(rule).cssRules[0]; - cssRule.parentRule = this; - this.cssRules.splice(index, 0, cssRule); - return index; -}; + CSSOM.CSSGroupingRule.prototype = new CSSOM.CSSRule(); + CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule; -/** - * Used to delete a rule from the grouping rule. - * - * cssGroupingRule.cssText - * -> "img{border:none;}body{margin:0;}" - * cssGroupingRule.deleteRule(0) - * cssGroupingRule.cssText - * -> "body{margin:0;}" - * - * @param {number} index within the grouping rule's rule list of the rule to remove. - * @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-deleterule - */ -CSSOM$9.CSSGroupingRule.prototype.deleteRule = function deleteRule(index) { - if (index < 0 || index >= this.cssRules.length) { - throw new RangeError("INDEX_SIZE_ERR"); - } - this.cssRules.splice(index, 1)[0].parentRule = null; -}; + /** + * Used to insert a new CSS rule to a list of CSS rules. + * + * @example + * cssGroupingRule.cssText + * -> "body{margin:0;}" + * cssGroupingRule.insertRule("img{border:none;}", 1) + * -> 1 + * cssGroupingRule.cssText + * -> "body{margin:0;}img{border:none;}" + * + * @param {string} rule + * @param {number} [index] + * @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-insertrule + * @return {number} The index within the grouping rule's collection of the newly inserted rule. + */ + CSSOM.CSSGroupingRule.prototype.insertRule = function insertRule( + rule, + index + ) { + if (index < 0 || index > this.cssRules.length) { + throw new RangeError("INDEX_SIZE_ERR"); + } + var cssRule = CSSOM.parse(rule).cssRules[0]; + cssRule.parentRule = this; + this.cssRules.splice(index, 0, cssRule); + return index; + }; -//.CommonJS -CSSGroupingRule.CSSGroupingRule = CSSOM$9.CSSGroupingRule; + /** + * Used to delete a rule from the grouping rule. + * + * cssGroupingRule.cssText + * -> "img{border:none;}body{margin:0;}" + * cssGroupingRule.deleteRule(0) + * cssGroupingRule.cssText + * -> "body{margin:0;}" + * + * @param {number} index within the grouping rule's rule list of the rule to remove. + * @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-deleterule + */ + CSSOM.CSSGroupingRule.prototype.deleteRule = function deleteRule(index) { + if (index < 0 || index >= this.cssRules.length) { + throw new RangeError("INDEX_SIZE_ERR"); + } + this.cssRules.splice(index, 1)[0].parentRule = null; + }; + + //.CommonJS + CSSGroupingRule.CSSGroupingRule = CSSOM.CSSGroupingRule; + ///CommonJS + return CSSGroupingRule; +} var CSSMediaRule = {}; var CSSConditionRule = {}; -//.CommonJS -var CSSOM$8 = { - CSSRule: CSSRule.CSSRule, - CSSGroupingRule: CSSGroupingRule.CSSGroupingRule -}; -///CommonJS +var hasRequiredCSSConditionRule; -/** - * @constructor - * @see https://www.w3.org/TR/css-conditional-3/#the-cssconditionrule-interface - */ -CSSOM$8.CSSConditionRule = function CSSConditionRule() { - CSSOM$8.CSSGroupingRule.call(this); - this.cssRules = []; -}; +function requireCSSConditionRule() { + if (hasRequiredCSSConditionRule) return CSSConditionRule; + hasRequiredCSSConditionRule = 1; + //.CommonJS + var CSSOM = { + CSSRule: requireCSSRule().CSSRule, + CSSGroupingRule: requireCSSGroupingRule().CSSGroupingRule + }; + ///CommonJS -CSSOM$8.CSSConditionRule.prototype = new CSSOM$8.CSSGroupingRule(); -CSSOM$8.CSSConditionRule.prototype.constructor = CSSOM$8.CSSConditionRule; -CSSOM$8.CSSConditionRule.prototype.conditionText = ""; -CSSOM$8.CSSConditionRule.prototype.cssText = ""; + /** + * @constructor + * @see https://www.w3.org/TR/css-conditional-3/#the-cssconditionrule-interface + */ + CSSOM.CSSConditionRule = function CSSConditionRule() { + CSSOM.CSSGroupingRule.call(this); + this.cssRules = []; + }; -//.CommonJS -CSSConditionRule.CSSConditionRule = CSSOM$8.CSSConditionRule; + CSSOM.CSSConditionRule.prototype = new CSSOM.CSSGroupingRule(); + CSSOM.CSSConditionRule.prototype.constructor = CSSOM.CSSConditionRule; + CSSOM.CSSConditionRule.prototype.conditionText = ""; + CSSOM.CSSConditionRule.prototype.cssText = ""; -//.CommonJS -var CSSOM$7 = { - CSSRule: CSSRule.CSSRule, - CSSGroupingRule: CSSGroupingRule.CSSGroupingRule, - CSSConditionRule: CSSConditionRule.CSSConditionRule, - MediaList: MediaList.MediaList -}; -///CommonJS + //.CommonJS + CSSConditionRule.CSSConditionRule = CSSOM.CSSConditionRule; + ///CommonJS + return CSSConditionRule; +} -/** - * @constructor - * @see http://dev.w3.org/csswg/cssom/#cssmediarule - * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule - */ -CSSOM$7.CSSMediaRule = function CSSMediaRule() { - CSSOM$7.CSSConditionRule.call(this); - this.media = new CSSOM$7.MediaList(); -}; +var hasRequiredCSSMediaRule; -CSSOM$7.CSSMediaRule.prototype = new CSSOM$7.CSSConditionRule(); -CSSOM$7.CSSMediaRule.prototype.constructor = CSSOM$7.CSSMediaRule; -CSSOM$7.CSSMediaRule.prototype.type = 4; +function requireCSSMediaRule() { + if (hasRequiredCSSMediaRule) return CSSMediaRule; + hasRequiredCSSMediaRule = 1; + //.CommonJS + var CSSOM = { + CSSRule: requireCSSRule().CSSRule, + CSSGroupingRule: requireCSSGroupingRule().CSSGroupingRule, + CSSConditionRule: requireCSSConditionRule().CSSConditionRule, + MediaList: requireMediaList().MediaList + }; + ///CommonJS -// https://opensource.apple.com/source/WebCore/WebCore-7611.1.21.161.3/css/CSSMediaRule.cpp -Object.defineProperties(CSSOM$7.CSSMediaRule.prototype, { - conditionText: { - get: function () { - return this.media.mediaText; + /** + * @constructor + * @see http://dev.w3.org/csswg/cssom/#cssmediarule + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule + */ + CSSOM.CSSMediaRule = function CSSMediaRule() { + CSSOM.CSSConditionRule.call(this); + this.media = new CSSOM.MediaList(); + }; + + CSSOM.CSSMediaRule.prototype = new CSSOM.CSSConditionRule(); + CSSOM.CSSMediaRule.prototype.constructor = CSSOM.CSSMediaRule; + CSSOM.CSSMediaRule.prototype.type = 4; + + // https://opensource.apple.com/source/WebCore/WebCore-7611.1.21.161.3/css/CSSMediaRule.cpp + Object.defineProperties(CSSOM.CSSMediaRule.prototype, { + conditionText: { + get: function () { + return this.media.mediaText; + }, + set: function (value) { + this.media.mediaText = value; + }, + configurable: true, + enumerable: true }, - set: function (value) { - this.media.mediaText = value; - }, - configurable: true, - enumerable: true - }, - cssText: { - get: function () { - var cssTexts = []; - for (var i = 0, length = this.cssRules.length; i < length; i++) { - cssTexts.push(this.cssRules[i].cssText); - } - return "@media " + this.media.mediaText + " {" + cssTexts.join("") + "}"; - }, - configurable: true, - enumerable: true - } -}); + cssText: { + get: function () { + var cssTexts = []; + for (var i = 0, length = this.cssRules.length; i < length; i++) { + cssTexts.push(this.cssRules[i].cssText); + } + return ( + "@media " + this.media.mediaText + " {" + cssTexts.join("") + "}" + ); + }, + configurable: true, + enumerable: true + } + }); -//.CommonJS -CSSMediaRule.CSSMediaRule = CSSOM$7.CSSMediaRule; + //.CommonJS + CSSMediaRule.CSSMediaRule = CSSOM.CSSMediaRule; + ///CommonJS + return CSSMediaRule; +} var CSSSupportsRule = {}; -//.CommonJS -var CSSOM$6 = { - CSSRule: CSSRule.CSSRule, - CSSGroupingRule: CSSGroupingRule.CSSGroupingRule, - CSSConditionRule: CSSConditionRule.CSSConditionRule -}; -///CommonJS +var hasRequiredCSSSupportsRule; -/** - * @constructor - * @see https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface - */ -CSSOM$6.CSSSupportsRule = function CSSSupportsRule() { - CSSOM$6.CSSConditionRule.call(this); -}; +function requireCSSSupportsRule() { + if (hasRequiredCSSSupportsRule) return CSSSupportsRule; + hasRequiredCSSSupportsRule = 1; + //.CommonJS + var CSSOM = { + CSSRule: requireCSSRule().CSSRule, + CSSGroupingRule: requireCSSGroupingRule().CSSGroupingRule, + CSSConditionRule: requireCSSConditionRule().CSSConditionRule + }; + ///CommonJS -CSSOM$6.CSSSupportsRule.prototype = new CSSOM$6.CSSConditionRule(); -CSSOM$6.CSSSupportsRule.prototype.constructor = CSSOM$6.CSSSupportsRule; -CSSOM$6.CSSSupportsRule.prototype.type = 12; + /** + * @constructor + * @see https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface + */ + CSSOM.CSSSupportsRule = function CSSSupportsRule() { + CSSOM.CSSConditionRule.call(this); + }; -Object.defineProperty(CSSOM$6.CSSSupportsRule.prototype, "cssText", { - get: function () { - var cssTexts = []; + CSSOM.CSSSupportsRule.prototype = new CSSOM.CSSConditionRule(); + CSSOM.CSSSupportsRule.prototype.constructor = CSSOM.CSSSupportsRule; + CSSOM.CSSSupportsRule.prototype.type = 12; - for (var i = 0, length = this.cssRules.length; i < length; i++) { - cssTexts.push(this.cssRules[i].cssText); + Object.defineProperty(CSSOM.CSSSupportsRule.prototype, "cssText", { + get: function () { + var cssTexts = []; + + for (var i = 0, length = this.cssRules.length; i < length; i++) { + cssTexts.push(this.cssRules[i].cssText); + } + + return "@supports " + this.conditionText + " {" + cssTexts.join("") + "}"; } + }); - return "@supports " + this.conditionText + " {" + cssTexts.join("") + "}"; - } -}); - -//.CommonJS -CSSSupportsRule.CSSSupportsRule = CSSOM$6.CSSSupportsRule; + //.CommonJS + CSSSupportsRule.CSSSupportsRule = CSSOM.CSSSupportsRule; + ///CommonJS + return CSSSupportsRule; +} var CSSFontFaceRule = {}; @@ -9666,7 +10221,7 @@ function requireCSSFontFaceRule() { //.CommonJS var CSSOM = { CSSStyleDeclaration: requireCSSStyleDeclaration().CSSStyleDeclaration, - CSSRule: CSSRule.CSSRule + CSSRule: requireCSSRule().CSSRule }; ///CommonJS @@ -9702,40 +10257,48 @@ function requireCSSFontFaceRule() { var CSSHostRule = {}; -//.CommonJS -var CSSOM$5 = { - CSSRule: CSSRule.CSSRule -}; -///CommonJS +var hasRequiredCSSHostRule; -/** - * @constructor - * @see http://www.w3.org/TR/shadow-dom/#host-at-rule - */ -CSSOM$5.CSSHostRule = function CSSHostRule() { - CSSOM$5.CSSRule.call(this); - this.cssRules = []; -}; +function requireCSSHostRule() { + if (hasRequiredCSSHostRule) return CSSHostRule; + hasRequiredCSSHostRule = 1; + //.CommonJS + var CSSOM = { + CSSRule: requireCSSRule().CSSRule + }; + ///CommonJS -CSSOM$5.CSSHostRule.prototype = new CSSOM$5.CSSRule(); -CSSOM$5.CSSHostRule.prototype.constructor = CSSOM$5.CSSHostRule; -CSSOM$5.CSSHostRule.prototype.type = 1001; -//FIXME -//CSSOM.CSSHostRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; -//CSSOM.CSSHostRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; + /** + * @constructor + * @see http://www.w3.org/TR/shadow-dom/#host-at-rule + */ + CSSOM.CSSHostRule = function CSSHostRule() { + CSSOM.CSSRule.call(this); + this.cssRules = []; + }; -Object.defineProperty(CSSOM$5.CSSHostRule.prototype, "cssText", { - get: function () { - var cssTexts = []; - for (var i = 0, length = this.cssRules.length; i < length; i++) { - cssTexts.push(this.cssRules[i].cssText); + CSSOM.CSSHostRule.prototype = new CSSOM.CSSRule(); + CSSOM.CSSHostRule.prototype.constructor = CSSOM.CSSHostRule; + CSSOM.CSSHostRule.prototype.type = 1001; + //FIXME + //CSSOM.CSSHostRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; + //CSSOM.CSSHostRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; + + Object.defineProperty(CSSOM.CSSHostRule.prototype, "cssText", { + get: function () { + var cssTexts = []; + for (var i = 0, length = this.cssRules.length; i < length; i++) { + cssTexts.push(this.cssRules[i].cssText); + } + return "@host {" + cssTexts.join("") + "}"; } - return "@host {" + cssTexts.join("") + "}"; - } -}); + }); -//.CommonJS -CSSHostRule.CSSHostRule = CSSOM$5.CSSHostRule; + //.CommonJS + CSSHostRule.CSSHostRule = CSSOM.CSSHostRule; + ///CommonJS + return CSSHostRule; +} var CSSKeyframeRule = {}; @@ -9746,7 +10309,7 @@ function requireCSSKeyframeRule() { hasRequiredCSSKeyframeRule = 1; //.CommonJS var CSSOM = { - CSSRule: CSSRule.CSSRule, + CSSRule: requireCSSRule().CSSRule, CSSStyleDeclaration: requireCSSStyleDeclaration().CSSStyleDeclaration }; ///CommonJS @@ -9784,560 +10347,600 @@ function requireCSSKeyframeRule() { var CSSKeyframesRule = {}; -//.CommonJS -var CSSOM$4 = { - CSSRule: CSSRule.CSSRule -}; -///CommonJS +var hasRequiredCSSKeyframesRule; -/** - * @constructor - * @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframesRule - */ -CSSOM$4.CSSKeyframesRule = function CSSKeyframesRule() { - CSSOM$4.CSSRule.call(this); - this.name = ""; - this.cssRules = []; -}; +function requireCSSKeyframesRule() { + if (hasRequiredCSSKeyframesRule) return CSSKeyframesRule; + hasRequiredCSSKeyframesRule = 1; + //.CommonJS + var CSSOM = { + CSSRule: requireCSSRule().CSSRule + }; + ///CommonJS -CSSOM$4.CSSKeyframesRule.prototype = new CSSOM$4.CSSRule(); -CSSOM$4.CSSKeyframesRule.prototype.constructor = CSSOM$4.CSSKeyframesRule; -CSSOM$4.CSSKeyframesRule.prototype.type = 7; -//FIXME -//CSSOM.CSSKeyframesRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; -//CSSOM.CSSKeyframesRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; + /** + * @constructor + * @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframesRule + */ + CSSOM.CSSKeyframesRule = function CSSKeyframesRule() { + CSSOM.CSSRule.call(this); + this.name = ""; + this.cssRules = []; + }; -// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframesRule.cpp -Object.defineProperty(CSSOM$4.CSSKeyframesRule.prototype, "cssText", { - get: function () { - var cssTexts = []; - for (var i = 0, length = this.cssRules.length; i < length; i++) { - cssTexts.push(" " + this.cssRules[i].cssText); + CSSOM.CSSKeyframesRule.prototype = new CSSOM.CSSRule(); + CSSOM.CSSKeyframesRule.prototype.constructor = CSSOM.CSSKeyframesRule; + CSSOM.CSSKeyframesRule.prototype.type = 7; + //FIXME + //CSSOM.CSSKeyframesRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; + //CSSOM.CSSKeyframesRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; + + // http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframesRule.cpp + Object.defineProperty(CSSOM.CSSKeyframesRule.prototype, "cssText", { + get: function () { + var cssTexts = []; + for (var i = 0, length = this.cssRules.length; i < length; i++) { + cssTexts.push(" " + this.cssRules[i].cssText); + } + return ( + "@" + + (this._vendorPrefix || "") + + "keyframes " + + this.name + + " { \n" + + cssTexts.join("\n") + + "\n}" + ); } - return ( - "@" + - (this._vendorPrefix || "") + - "keyframes " + - this.name + - " { \n" + - cssTexts.join("\n") + - "\n}" - ); - } -}); + }); -//.CommonJS -CSSKeyframesRule.CSSKeyframesRule = CSSOM$4.CSSKeyframesRule; + //.CommonJS + CSSKeyframesRule.CSSKeyframesRule = CSSOM.CSSKeyframesRule; + ///CommonJS + return CSSKeyframesRule; +} var CSSValueExpression = {}; var CSSValue = {}; -//.CommonJS -var CSSOM$3 = {}; -///CommonJS +var hasRequiredCSSValue; -/** - * @constructor - * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue - * - * TODO: add if needed - */ -CSSOM$3.CSSValue = function CSSValue() {}; +function requireCSSValue() { + if (hasRequiredCSSValue) return CSSValue; + hasRequiredCSSValue = 1; + //.CommonJS + var CSSOM = {}; + ///CommonJS -CSSOM$3.CSSValue.prototype = { - constructor: CSSOM$3.CSSValue, + /** + * @constructor + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue + * + * TODO: add if needed + */ + CSSOM.CSSValue = function CSSValue() {}; - // @see: http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue - set cssText(text) { - var name = this._getConstructorName(); + CSSOM.CSSValue.prototype = { + constructor: CSSOM.CSSValue, - throw new Error( - 'DOMException: property "cssText" of "' + - name + - '" is readonly and can not be replaced with "' + - text + - '"!' - ); - }, + // @see: http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue + set cssText(text) { + var name = this._getConstructorName(); - get cssText() { - var name = this._getConstructorName(); + throw new Error( + 'DOMException: property "cssText" of "' + + name + + '" is readonly and can not be replaced with "' + + text + + '"!' + ); + }, - throw new Error('getter "cssText" of "' + name + '" is not implemented!'); - }, + get cssText() { + var name = this._getConstructorName(); - _getConstructorName: function () { - var s = this.constructor.toString(), - c = s.match(/function\s([^\(]+)/), - name = c[1]; + throw new Error('getter "cssText" of "' + name + '" is not implemented!'); + }, - return name; - } -}; + _getConstructorName: function () { + var s = this.constructor.toString(), + c = s.match(/function\s([^\(]+)/), + name = c[1]; -//.CommonJS -CSSValue.CSSValue = CSSOM$3.CSSValue; - -//.CommonJS -var CSSOM$2 = { - CSSValue: CSSValue.CSSValue -}; -///CommonJS - -/** - * @constructor - * @see http://msdn.microsoft.com/en-us/library/ms537634(v=vs.85).aspx - * - */ -CSSOM$2.CSSValueExpression = function CSSValueExpression(token, idx) { - this._token = token; - this._idx = idx; -}; - -CSSOM$2.CSSValueExpression.prototype = new CSSOM$2.CSSValue(); -CSSOM$2.CSSValueExpression.prototype.constructor = CSSOM$2.CSSValueExpression; - -/** - * parse css expression() value - * - * @return {Object} - * - error: - * or - * - idx: - * - expression: - * - * Example: - * - * .selector { - * zoom: expression(documentElement.clientWidth > 1000 ? '1000px' : 'auto'); - * } - */ -CSSOM$2.CSSValueExpression.prototype.parse = function () { - var token = this._token, - idx = this._idx; - - var character = "", - expression = "", - error = "", - info, - paren = []; - - for (; ; ++idx) { - character = token.charAt(idx); - - // end of token - if (character === "") { - error = "css expression error: unfinished expression!"; - break; + return name; } + }; - switch (character) { - case "(": - paren.push(character); - expression += character; + //.CommonJS + CSSValue.CSSValue = CSSOM.CSSValue; + ///CommonJS + return CSSValue; +} + +var hasRequiredCSSValueExpression; + +function requireCSSValueExpression() { + if (hasRequiredCSSValueExpression) return CSSValueExpression; + hasRequiredCSSValueExpression = 1; + //.CommonJS + var CSSOM = { + CSSValue: requireCSSValue().CSSValue + }; + ///CommonJS + + /** + * @constructor + * @see http://msdn.microsoft.com/en-us/library/ms537634(v=vs.85).aspx + * + */ + CSSOM.CSSValueExpression = function CSSValueExpression(token, idx) { + this._token = token; + this._idx = idx; + }; + + CSSOM.CSSValueExpression.prototype = new CSSOM.CSSValue(); + CSSOM.CSSValueExpression.prototype.constructor = CSSOM.CSSValueExpression; + + /** + * parse css expression() value + * + * @return {Object} + * - error: + * or + * - idx: + * - expression: + * + * Example: + * + * .selector { + * zoom: expression(documentElement.clientWidth > 1000 ? '1000px' : 'auto'); + * } + */ + CSSOM.CSSValueExpression.prototype.parse = function () { + var token = this._token, + idx = this._idx; + + var character = "", + expression = "", + error = "", + info, + paren = []; + + for (; ; ++idx) { + character = token.charAt(idx); + + // end of token + if (character === "") { + error = "css expression error: unfinished expression!"; break; + } - case ")": - paren.pop(character); - expression += character; - break; + switch (character) { + case "(": + paren.push(character); + expression += character; + break; - case "/": - if ((info = this._parseJSComment(token, idx))) { - // comment? - if (info.error) { - error = "css expression error: unfinished comment in expression!"; - } else { + case ")": + paren.pop(character); + expression += character; + break; + + case "/": + if ((info = this._parseJSComment(token, idx))) { + // comment? + if (info.error) { + error = "css expression error: unfinished comment in expression!"; + } else { + idx = info.idx; + // ignore the comment + } + } else if ((info = this._parseJSRexExp(token, idx))) { + // regexp idx = info.idx; - // ignore the comment + expression += info.text; + } else { + // other + expression += character; } - } else if ((info = this._parseJSRexExp(token, idx))) { - // regexp - idx = info.idx; - expression += info.text; - } else { - // other - expression += character; - } - break; + break; - case "'": - case '"': - info = this._parseJSString(token, idx, character); - if (info) { - // string - idx = info.idx; - expression += info.text; - } else { - expression += character; - } - break; + case "'": + case '"': + info = this._parseJSString(token, idx, character); + if (info) { + // string + idx = info.idx; + expression += info.text; + } else { + expression += character; + } + break; - default: - expression += character; + default: + expression += character; + break; + } + + if (error) { break; + } + + // end of expression + if (paren.length === 0) { + break; + } } + var ret; if (error) { - break; + ret = { + error: error + }; + } else { + ret = { + idx: idx, + expression: expression + }; } - // end of expression - if (paren.length === 0) { - break; + return ret; + }; + + /** + * + * @return {Object|false} + * - idx: + * - text: + * or + * - error: + * or + * false + * + */ + CSSOM.CSSValueExpression.prototype._parseJSComment = function (token, idx) { + var nextChar = token.charAt(idx + 1), + text; + + if (nextChar === "/" || nextChar === "*") { + var startIdx = idx, + endIdx, + commentEndChar; + + if (nextChar === "/") { + // line comment + commentEndChar = "\n"; + } else if (nextChar === "*") { + // block comment + commentEndChar = "*/"; + } + + endIdx = token.indexOf(commentEndChar, startIdx + 1 + 1); + if (endIdx !== -1) { + endIdx = endIdx + commentEndChar.length - 1; + text = token.substring(idx, endIdx + 1); + return { + idx: endIdx, + text: text + }; + } else { + var error = "css expression error: unfinished comment in expression!"; + return { + error: error + }; + } + } else { + return false; } - } + }; - var ret; - if (error) { - ret = { - error: error - }; - } else { - ret = { - idx: idx, - expression: expression - }; - } + /** + * + * @return {Object|false} + * - idx: + * - text: + * or + * false + * + */ + CSSOM.CSSValueExpression.prototype._parseJSString = function ( + token, + idx, + sep + ) { + var endIdx = this._findMatchedIdx(token, idx, sep), + text; - return ret; -}; + if (endIdx === -1) { + return false; + } else { + text = token.substring(idx, endIdx + sep.length); -/** - * - * @return {Object|false} - * - idx: - * - text: - * or - * - error: - * or - * false - * - */ -CSSOM$2.CSSValueExpression.prototype._parseJSComment = function (token, idx) { - var nextChar = token.charAt(idx + 1), - text; - - if (nextChar === "/" || nextChar === "*") { - var startIdx = idx, - endIdx, - commentEndChar; - - if (nextChar === "/") { - // line comment - commentEndChar = "\n"; - } else if (nextChar === "*") { - // block comment - commentEndChar = "*/"; - } - - endIdx = token.indexOf(commentEndChar, startIdx + 1 + 1); - if (endIdx !== -1) { - endIdx = endIdx + commentEndChar.length - 1; - text = token.substring(idx, endIdx + 1); return { idx: endIdx, text: text }; - } else { - var error = "css expression error: unfinished comment in expression!"; - return { - error: error - }; } - } else { - return false; - } -}; + }; -/** - * - * @return {Object|false} - * - idx: - * - text: - * or - * false - * - */ -CSSOM$2.CSSValueExpression.prototype._parseJSString = function ( - token, - idx, - sep -) { - var endIdx = this._findMatchedIdx(token, idx, sep), - text; + /** + * parse regexp in css expression + * + * @return {Object|false} + * - idx: + * - regExp: + * or + * false + */ - if (endIdx === -1) { - return false; - } else { - text = token.substring(idx, endIdx + sep.length); + /* - return { - idx: endIdx, - text: text - }; - } -}; + all legal RegExp + + /a/ + (/a/) + [/a/] + [12, /a/] -/** - * parse regexp in css expression - * - * @return {Object|false} - * - idx: - * - regExp: - * or - * false - */ + !/a/ -/* + +/a/ + -/a/ + * /a/ + / /a/ + %/a/ -all legal RegExp - -/a/ -(/a/) -[/a/] -[12, /a/] + ===/a/ + !==/a/ + ==/a/ + !=/a/ + >/a/ + >=/a/ + </a/ + <=/a/ -!/a/ + &/a/ + |/a/ + ^/a/ + ~/a/ + <</a/ + >>/a/ + >>>/a/ -+/a/ --/a/ -* /a/ -/ /a/ -%/a/ + &&/a/ + ||/a/ + ?/a/ + =/a/ + ,/a/ -===/a/ -!==/a/ -==/a/ -!=/a/ ->/a/ ->=/a/ -</a/ -<=/a/ + delete /a/ + in /a/ + instanceof /a/ + new /a/ + typeof /a/ + void /a/ -&/a/ -|/a/ -^/a/ -~/a/ -<</a/ ->>/a/ ->>>/a/ + */ + CSSOM.CSSValueExpression.prototype._parseJSRexExp = function (token, idx) { + var before = token.substring(0, idx).replace(/\s+$/, ""), + legalRegx = [ + /^$/, + /\($/, + /\[$/, + /\!$/, + /\+$/, + /\-$/, + /\*$/, + /\/\s+/, + /\%$/, + /\=$/, + /\>$/, + /<$/, + /\&$/, + /\|$/, + /\^$/, + /\~$/, + /\?$/, + /\,$/, + /delete$/, + /in$/, + /instanceof$/, + /new$/, + /typeof$/, + /void$/ + ]; -&&/a/ -||/a/ -?/a/ -=/a/ -,/a/ + var isLegal = legalRegx.some(function (reg) { + return reg.test(before); + }); - delete /a/ - in /a/ -instanceof /a/ - new /a/ - typeof /a/ - void /a/ - -*/ -CSSOM$2.CSSValueExpression.prototype._parseJSRexExp = function (token, idx) { - var before = token.substring(0, idx).replace(/\s+$/, ""), - legalRegx = [ - /^$/, - /\($/, - /\[$/, - /\!$/, - /\+$/, - /\-$/, - /\*$/, - /\/\s+/, - /\%$/, - /\=$/, - /\>$/, - /<$/, - /\&$/, - /\|$/, - /\^$/, - /\~$/, - /\?$/, - /\,$/, - /delete$/, - /in$/, - /instanceof$/, - /new$/, - /typeof$/, - /void$/ - ]; - - var isLegal = legalRegx.some(function (reg) { - return reg.test(before); - }); - - if (!isLegal) { - return false; - } else { - var sep = "/"; - - // same logic as string - return this._parseJSString(token, idx, sep); - } -}; - -/** - * - * find next sep(same line) index in `token` - * - * @return {Number} - * - */ -CSSOM$2.CSSValueExpression.prototype._findMatchedIdx = function ( - token, - idx, - sep -) { - var startIdx = idx, - endIdx; - - var NOT_FOUND = -1; - - while (true) { - endIdx = token.indexOf(sep, startIdx + 1); - - if (endIdx === -1) { - // not found - endIdx = NOT_FOUND; - break; + if (!isLegal) { + return false; } else { - var text = token.substring(idx + 1, endIdx), - matched = text.match(/\\+$/); - if (!matched || matched[0] % 2 === 0) { - // not escaped + var sep = "/"; + + // same logic as string + return this._parseJSString(token, idx, sep); + } + }; + + /** + * + * find next sep(same line) index in `token` + * + * @return {Number} + * + */ + CSSOM.CSSValueExpression.prototype._findMatchedIdx = function ( + token, + idx, + sep + ) { + var startIdx = idx, + endIdx; + + var NOT_FOUND = -1; + + while (true) { + endIdx = token.indexOf(sep, startIdx + 1); + + if (endIdx === -1) { + // not found + endIdx = NOT_FOUND; break; } else { - startIdx = endIdx; + var text = token.substring(idx + 1, endIdx), + matched = text.match(/\\+$/); + if (!matched || matched[0] % 2 === 0) { + // not escaped + break; + } else { + startIdx = endIdx; + } } } - } - // boundary must be in the same line(js string or regexp) - var nextNewLineIdx = token.indexOf("\n", idx + 1); - if (nextNewLineIdx < endIdx) { - endIdx = NOT_FOUND; - } + // boundary must be in the same line(js sting or regexp) + var nextNewLineIdx = token.indexOf("\n", idx + 1); + if (nextNewLineIdx < endIdx) { + endIdx = NOT_FOUND; + } - return endIdx; -}; + return endIdx; + }; -//.CommonJS -CSSValueExpression.CSSValueExpression = CSSOM$2.CSSValueExpression; + //.CommonJS + CSSValueExpression.CSSValueExpression = CSSOM.CSSValueExpression; + ///CommonJS + return CSSValueExpression; +} var CSSDocumentRule = {}; var MatcherList = {}; -//.CommonJS -var CSSOM$1 = {}; -///CommonJS +var hasRequiredMatcherList; -/** - * @constructor - * @see https://developer.mozilla.org/en/CSS/@-moz-document - */ -CSSOM$1.MatcherList = function MatcherList() { - this.length = 0; -}; - -CSSOM$1.MatcherList.prototype = { - constructor: CSSOM$1.MatcherList, +function requireMatcherList() { + if (hasRequiredMatcherList) return MatcherList; + hasRequiredMatcherList = 1; + //.CommonJS + var CSSOM = {}; + ///CommonJS /** - * @return {string} + * @constructor + * @see https://developer.mozilla.org/en/CSS/@-moz-document */ - get matcherText() { - return Array.prototype.join.call(this, ", "); - }, + CSSOM.MatcherList = function MatcherList() { + this.length = 0; + }; + + CSSOM.MatcherList.prototype = { + constructor: CSSOM.MatcherList, + + /** + * @return {string} + */ + get matcherText() { + return Array.prototype.join.call(this, ", "); + }, + + /** + * @param {string} value + */ + set matcherText(value) { + // just a temporary solution, actually it may be wrong by just split the value with ',', because a url can include ','. + var values = value.split(","); + var length = (this.length = values.length); + for (var i = 0; i < length; i++) { + this[i] = values[i].trim(); + } + }, + + /** + * @param {string} matcher + */ + appendMatcher: function (matcher) { + if (Array.prototype.indexOf.call(this, matcher) === -1) { + this[this.length] = matcher; + this.length++; + } + }, + + /** + * @param {string} matcher + */ + deleteMatcher: function (matcher) { + var index = Array.prototype.indexOf.call(this, matcher); + if (index !== -1) { + Array.prototype.splice.call(this, index, 1); + } + } + }; + + //.CommonJS + MatcherList.MatcherList = CSSOM.MatcherList; + ///CommonJS + return MatcherList; +} + +var hasRequiredCSSDocumentRule; + +function requireCSSDocumentRule() { + if (hasRequiredCSSDocumentRule) return CSSDocumentRule; + hasRequiredCSSDocumentRule = 1; + //.CommonJS + var CSSOM = { + CSSRule: requireCSSRule().CSSRule, + MatcherList: requireMatcherList().MatcherList + }; + ///CommonJS /** - * @param {string} value + * @constructor + * @see https://developer.mozilla.org/en/CSS/@-moz-document */ - set matcherText(value) { - // just a temporary solution, actually it may be wrong by just split the value with ',', because a url can include ','. - var values = value.split(","); - var length = (this.length = values.length); - for (var i = 0; i < length; i++) { - this[i] = values[i].trim(); + CSSOM.CSSDocumentRule = function CSSDocumentRule() { + CSSOM.CSSRule.call(this); + this.matcher = new CSSOM.MatcherList(); + this.cssRules = []; + }; + + CSSOM.CSSDocumentRule.prototype = new CSSOM.CSSRule(); + CSSOM.CSSDocumentRule.prototype.constructor = CSSOM.CSSDocumentRule; + CSSOM.CSSDocumentRule.prototype.type = 10; + //FIXME + //CSSOM.CSSDocumentRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; + //CSSOM.CSSDocumentRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; + + Object.defineProperty(CSSOM.CSSDocumentRule.prototype, "cssText", { + get: function () { + var cssTexts = []; + for (var i = 0, length = this.cssRules.length; i < length; i++) { + cssTexts.push(this.cssRules[i].cssText); + } + return ( + "@-moz-document " + + this.matcher.matcherText + + " {" + + cssTexts.join("") + + "}" + ); } - }, + }); - /** - * @param {string} matcher - */ - appendMatcher: function (matcher) { - if (Array.prototype.indexOf.call(this, matcher) === -1) { - this[this.length] = matcher; - this.length++; - } - }, - - /** - * @param {string} matcher - */ - deleteMatcher: function (matcher) { - var index = Array.prototype.indexOf.call(this, matcher); - if (index !== -1) { - Array.prototype.splice.call(this, index, 1); - } - } -}; - -//.CommonJS -MatcherList.MatcherList = CSSOM$1.MatcherList; - -//.CommonJS -var CSSOM = { - CSSRule: CSSRule.CSSRule, - MatcherList: MatcherList.MatcherList -}; -///CommonJS - -/** - * @constructor - * @see https://developer.mozilla.org/en/CSS/@-moz-document - */ -CSSOM.CSSDocumentRule = function CSSDocumentRule() { - CSSOM.CSSRule.call(this); - this.matcher = new CSSOM.MatcherList(); - this.cssRules = []; -}; - -CSSOM.CSSDocumentRule.prototype = new CSSOM.CSSRule(); -CSSOM.CSSDocumentRule.prototype.constructor = CSSOM.CSSDocumentRule; -CSSOM.CSSDocumentRule.prototype.type = 10; -//FIXME -//CSSOM.CSSDocumentRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; -//CSSOM.CSSDocumentRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; - -Object.defineProperty(CSSOM.CSSDocumentRule.prototype, "cssText", { - get: function () { - var cssTexts = []; - for (var i = 0, length = this.cssRules.length; i < length; i++) { - cssTexts.push(this.cssRules[i].cssText); - } - return ( - "@-moz-document " + - this.matcher.matcherText + - " {" + - cssTexts.join("") + - "}" - ); - } -}); - -//.CommonJS -CSSDocumentRule.CSSDocumentRule = CSSOM.CSSDocumentRule; + //.CommonJS + CSSDocumentRule.CSSDocumentRule = CSSOM.CSSDocumentRule; + ///CommonJS + return CSSDocumentRule; +} var hasRequiredParse; function requireParse() { - if (hasRequiredParse) return parse$2; + if (hasRequiredParse) return parse$1; hasRequiredParse = 1; //.CommonJS var CSSOM = {}; @@ -10794,24 +11397,24 @@ function requireParse() { }; //.CommonJS - parse$2.parse = CSSOM.parse; + parse$1.parse = CSSOM.parse; // The following modules cannot be included sooner due to the mutual dependency with parse.js CSSOM.CSSStyleSheet = requireCSSStyleSheet().CSSStyleSheet; CSSOM.CSSStyleRule = requireCSSStyleRule().CSSStyleRule; CSSOM.CSSImportRule = requireCSSImportRule().CSSImportRule; - CSSOM.CSSGroupingRule = CSSGroupingRule.CSSGroupingRule; - CSSOM.CSSMediaRule = CSSMediaRule.CSSMediaRule; - CSSOM.CSSConditionRule = CSSConditionRule.CSSConditionRule; - CSSOM.CSSSupportsRule = CSSSupportsRule.CSSSupportsRule; + CSSOM.CSSGroupingRule = requireCSSGroupingRule().CSSGroupingRule; + CSSOM.CSSMediaRule = requireCSSMediaRule().CSSMediaRule; + CSSOM.CSSConditionRule = requireCSSConditionRule().CSSConditionRule; + CSSOM.CSSSupportsRule = requireCSSSupportsRule().CSSSupportsRule; CSSOM.CSSFontFaceRule = requireCSSFontFaceRule().CSSFontFaceRule; - CSSOM.CSSHostRule = CSSHostRule.CSSHostRule; + CSSOM.CSSHostRule = requireCSSHostRule().CSSHostRule; CSSOM.CSSStyleDeclaration = requireCSSStyleDeclaration().CSSStyleDeclaration; CSSOM.CSSKeyframeRule = requireCSSKeyframeRule().CSSKeyframeRule; - CSSOM.CSSKeyframesRule = CSSKeyframesRule.CSSKeyframesRule; - CSSOM.CSSValueExpression = CSSValueExpression.CSSValueExpression; - CSSOM.CSSDocumentRule = CSSDocumentRule.CSSDocumentRule; + CSSOM.CSSKeyframesRule = requireCSSKeyframesRule().CSSKeyframesRule; + CSSOM.CSSValueExpression = requireCSSValueExpression().CSSValueExpression; + CSSOM.CSSDocumentRule = requireCSSDocumentRule().CSSDocumentRule; ///CommonJS - return parse$2; + return parse$1; } var hasRequiredCSSStyleDeclaration; @@ -10969,35 +11572,126 @@ function requireCSSStyleDeclaration() { return CSSStyleDeclaration; } -//.CommonJS -({ - CSSStyleSheet: requireCSSStyleSheet().CSSStyleSheet, - CSSRule: CSSRule.CSSRule, - CSSStyleRule: requireCSSStyleRule().CSSStyleRule, - CSSGroupingRule: CSSGroupingRule.CSSGroupingRule, - CSSConditionRule: CSSConditionRule.CSSConditionRule, - CSSMediaRule: CSSMediaRule.CSSMediaRule, - CSSSupportsRule: CSSSupportsRule.CSSSupportsRule, - CSSStyleDeclaration: requireCSSStyleDeclaration().CSSStyleDeclaration, - CSSKeyframeRule: requireCSSKeyframeRule().CSSKeyframeRule, - CSSKeyframesRule: CSSKeyframesRule.CSSKeyframesRule -}); +var clone = {}; -requireCSSStyleDeclaration().CSSStyleDeclaration; -requireCSSStyleRule().CSSStyleRule; -requireCSSImportRule().CSSImportRule; -requireCSSFontFaceRule().CSSFontFaceRule; -requireCSSStyleSheet().CSSStyleSheet; -requireCSSKeyframeRule().CSSKeyframeRule; -var parse$1 = requireParse().parse; +var hasRequiredClone; -const tagName$b = "style"; +function requireClone() { + if (hasRequiredClone) return clone; + hasRequiredClone = 1; + //.CommonJS + var CSSOM = { + CSSStyleSheet: requireCSSStyleSheet().CSSStyleSheet, + CSSRule: requireCSSRule().CSSRule, + CSSStyleRule: requireCSSStyleRule().CSSStyleRule, + CSSGroupingRule: requireCSSGroupingRule().CSSGroupingRule, + CSSConditionRule: requireCSSConditionRule().CSSConditionRule, + CSSMediaRule: requireCSSMediaRule().CSSMediaRule, + CSSSupportsRule: requireCSSSupportsRule().CSSSupportsRule, + CSSStyleDeclaration: requireCSSStyleDeclaration().CSSStyleDeclaration, + CSSKeyframeRule: requireCSSKeyframeRule().CSSKeyframeRule, + CSSKeyframesRule: requireCSSKeyframesRule().CSSKeyframesRule + }; + ///CommonJS + + /** + * Produces a deep copy of stylesheet — the instance variables of stylesheet are copied recursively. + * @param {CSSStyleSheet|CSSOM.CSSStyleSheet} stylesheet + * @nosideeffects + * @return {CSSOM.CSSStyleSheet} + */ + CSSOM.clone = function clone(stylesheet) { + var cloned = new CSSOM.CSSStyleSheet(); + + var rules = stylesheet.cssRules; + if (!rules) { + return cloned; + } + + for (var i = 0, rulesLength = rules.length; i < rulesLength; i++) { + var rule = rules[i]; + var ruleClone = (cloned.cssRules[i] = new rule.constructor()); + + var style = rule.style; + if (style) { + var styleClone = (ruleClone.style = new CSSOM.CSSStyleDeclaration()); + for (var j = 0, styleLength = style.length; j < styleLength; j++) { + var name = (styleClone[j] = style[j]); + styleClone[name] = style[name]; + styleClone._importants[name] = style.getPropertyPriority(name); + } + styleClone.length = style.length; + } + + if (rule.hasOwnProperty("keyText")) { + ruleClone.keyText = rule.keyText; + } + + if (rule.hasOwnProperty("selectorText")) { + ruleClone.selectorText = rule.selectorText; + } + + if (rule.hasOwnProperty("mediaText")) { + ruleClone.mediaText = rule.mediaText; + } + + if (rule.hasOwnProperty("conditionText")) { + ruleClone.conditionText = rule.conditionText; + } + + if (rule.hasOwnProperty("cssRules")) { + ruleClone.cssRules = clone(rule).cssRules; + } + } + + return cloned; + }; + + //.CommonJS + clone.clone = CSSOM.clone; + ///CommonJS + return clone; +} + +var hasRequiredLib; + +function requireLib() { + if (hasRequiredLib) return lib; + hasRequiredLib = 1; + + lib.CSSStyleDeclaration = requireCSSStyleDeclaration().CSSStyleDeclaration; + lib.CSSRule = requireCSSRule().CSSRule; + lib.CSSGroupingRule = requireCSSGroupingRule().CSSGroupingRule; + lib.CSSConditionRule = requireCSSConditionRule().CSSConditionRule; + lib.CSSStyleRule = requireCSSStyleRule().CSSStyleRule; + lib.MediaList = requireMediaList().MediaList; + lib.CSSMediaRule = requireCSSMediaRule().CSSMediaRule; + lib.CSSSupportsRule = requireCSSSupportsRule().CSSSupportsRule; + lib.CSSImportRule = requireCSSImportRule().CSSImportRule; + lib.CSSFontFaceRule = requireCSSFontFaceRule().CSSFontFaceRule; + lib.CSSHostRule = requireCSSHostRule().CSSHostRule; + lib.StyleSheet = requireStyleSheet().StyleSheet; + lib.CSSStyleSheet = requireCSSStyleSheet().CSSStyleSheet; + lib.CSSKeyframesRule = requireCSSKeyframesRule().CSSKeyframesRule; + lib.CSSKeyframeRule = requireCSSKeyframeRule().CSSKeyframeRule; + lib.MatcherList = requireMatcherList().MatcherList; + lib.CSSDocumentRule = requireCSSDocumentRule().CSSDocumentRule; + lib.CSSValue = requireCSSValue().CSSValue; + lib.CSSValueExpression = requireCSSValueExpression().CSSValueExpression; + lib.parse = requireParse().parse; + lib.clone = requireClone().clone; + return lib; +} + +var libExports = requireLib(); + +const tagName$e = "style"; /** * @implements globalThis.HTMLStyleElement */ class HTMLStyleElement extends TextElement { - constructor(ownerDocument, localName = tagName$b) { + constructor(ownerDocument, localName = tagName$e) { super(ownerDocument, localName); this[SHEET] = null; } @@ -11007,7 +11701,7 @@ class HTMLStyleElement extends TextElement { if (sheet !== null) { return sheet; } - return (this[SHEET] = parse$1(this.textContent)); + return (this[SHEET] = libExports.parse(this.textContent)); } get innerHTML() { @@ -11033,7 +11727,7 @@ class HTMLStyleElement extends TextElement { } } -registerHTMLClass(tagName$b, HTMLStyleElement); +registerHTMLClass(tagName$e, HTMLStyleElement); /** * @implements globalThis.HTMLTimeElement @@ -11042,8 +11736,20 @@ class HTMLTimeElement extends HTMLElement { constructor(ownerDocument, localName = "time") { super(ownerDocument, localName); } + + /** + * @type {string} + */ + get dateTime() { + return stringAttribute.get(this, "datetime"); + } + set dateTime(value) { + stringAttribute.set(this, "datetime", value); + } } +registerHTMLClass("time", HTMLTimeElement); + /** * @implements globalThis.HTMLFieldSetElement */ @@ -11134,13 +11840,13 @@ class HTMLDataListElement extends HTMLElement { } } -const tagName$a = "input"; +const tagName$d = "input"; /** * @implements globalThis.HTMLInputElement */ class HTMLInputElement extends HTMLElement { - constructor(ownerDocument, localName = tagName$a) { + constructor(ownerDocument, localName = tagName$d) { super(ownerDocument, localName); } @@ -11179,10 +11885,17 @@ class HTMLInputElement extends HTMLElement { set type(value) { this.setAttribute("type", value); } + + get value() { + return stringAttribute.get(this, "value"); + } + set value(value) { + stringAttribute.set(this, "value", value); + } /* c8 ignore stop */ } -registerHTMLClass(tagName$a, HTMLInputElement); +registerHTMLClass(tagName$d, HTMLInputElement); /** * @implements globalThis.HTMLParamElement @@ -11211,19 +11924,19 @@ class HTMLAudioElement extends HTMLElement { } } -const tagName$9 = "h1"; +const tagName$c = "h1"; /** * @implements globalThis.HTMLHeadingElement */ class HTMLHeadingElement extends HTMLElement { - constructor(ownerDocument, localName = tagName$9) { + constructor(ownerDocument, localName = tagName$c) { super(ownerDocument, localName); } } registerHTMLClass( - [tagName$9, "h2", "h3", "h4", "h5", "h6"], + [tagName$c, "h2", "h3", "h4", "h5", "h6"], HTMLHeadingElement ); @@ -11261,13 +11974,13 @@ var Canvas$1 = { createCanvas: (width, height) => new Canvas(width, height) }; const { createCanvas } = Canvas$1; -const tagName$8 = "canvas"; +const tagName$b = "canvas"; /** * @implements globalThis.HTMLCanvasElement */ class HTMLCanvasElement extends HTMLElement { - constructor(ownerDocument, localName = tagName$8) { + constructor(ownerDocument, localName = tagName$b) { super(ownerDocument, localName); this[IMAGE] = createCanvas(300, 150); } @@ -11299,7 +12012,7 @@ class HTMLCanvasElement extends HTMLElement { } } -registerHTMLClass(tagName$8, HTMLCanvasElement); +registerHTMLClass(tagName$b, HTMLCanvasElement); /** * @implements globalThis.HTMLLegendElement @@ -11310,15 +12023,37 @@ class HTMLLegendElement extends HTMLElement { } } +const tagName$a = "option"; + /** * @implements globalThis.HTMLOptionElement */ class HTMLOptionElement extends HTMLElement { - constructor(ownerDocument, localName = "option") { + constructor(ownerDocument, localName = tagName$a) { super(ownerDocument, localName); } + + /* c8 ignore start */ + get value() { + return stringAttribute.get(this, "value"); + } + set value(value) { + stringAttribute.set(this, "value", value); + } + /* c8 ignore stop */ + + get selected() { + return booleanAttribute.get(this, "selected"); + } + set selected(value) { + const option = this.parentElement?.querySelector("option[selected]"); + if (option && option !== this) option.selected = false; + booleanAttribute.set(this, "selected", value); + } } +registerHTMLClass(tagName$a, HTMLOptionElement); + /** * @implements globalThis.HTMLSpanElement */ @@ -11355,18 +12090,18 @@ class HTMLTableCellElement extends HTMLElement { } } -const tagName$7 = "title"; +const tagName$9 = "title"; /** * @implements globalThis.HTMLTitleElement */ class HTMLTitleElement extends TextElement { - constructor(ownerDocument, localName = tagName$7) { + constructor(ownerDocument, localName = tagName$9) { super(ownerDocument, localName); } } -registerHTMLClass(tagName$7, HTMLTitleElement); +registerHTMLClass(tagName$9, HTMLTitleElement); /** * @implements globalThis.HTMLOutputElement @@ -11404,13 +12139,13 @@ class HTMLMenuElement extends HTMLElement { } } -const tagName$6 = "select"; +const tagName$8 = "select"; /** * @implements globalThis.HTMLSelectElement */ class HTMLSelectElement extends HTMLElement { - constructor(ownerDocument, localName = tagName$6) { + constructor(ownerDocument, localName = tagName$8) { super(ownerDocument, localName); } @@ -11441,9 +12176,13 @@ class HTMLSelectElement extends HTMLElement { this.setAttribute("name", value); } /* c8 ignore stop */ + + get value() { + return this.querySelector("option[selected]")?.value; + } } -registerHTMLClass(tagName$6, HTMLSelectElement); +registerHTMLClass(tagName$8, HTMLSelectElement); /** * @implements globalThis.HTMLBRElement @@ -11454,13 +12193,13 @@ class HTMLBRElement extends HTMLElement { } } -const tagName$5 = "button"; +const tagName$7 = "button"; /** * @implements globalThis.HTMLButtonElement */ class HTMLButtonElement extends HTMLElement { - constructor(ownerDocument, localName = tagName$5) { + constructor(ownerDocument, localName = tagName$7) { super(ownerDocument, localName); } @@ -11488,7 +12227,7 @@ class HTMLButtonElement extends HTMLElement { /* c8 ignore stop */ } -registerHTMLClass(tagName$5, HTMLButtonElement); +registerHTMLClass(tagName$7, HTMLButtonElement); /** * @implements globalThis.HTMLMapElement @@ -11517,13 +12256,13 @@ class HTMLDListElement extends HTMLElement { } } -const tagName$4 = "textarea"; +const tagName$6 = "textarea"; /** * @implements globalThis.HTMLTextAreaElement */ class HTMLTextAreaElement extends TextElement { - constructor(ownerDocument, localName = tagName$4) { + constructor(ownerDocument, localName = tagName$6) { super(ownerDocument, localName); } @@ -11565,7 +12304,7 @@ class HTMLTextAreaElement extends TextElement { /* c8 ignore stop */ } -registerHTMLClass(tagName$4, HTMLTextAreaElement); +registerHTMLClass(tagName$6, HTMLTextAreaElement); /** * @implements globalThis.HTMLFontElement @@ -11585,13 +12324,13 @@ class HTMLDivElement extends HTMLElement { } } -const tagName$3 = "link"; +const tagName$5 = "link"; /** * @implements globalThis.HTMLLinkElement */ class HTMLLinkElement extends HTMLElement { - constructor(ownerDocument, localName = tagName$3) { + constructor(ownerDocument, localName = tagName$5) { super(ownerDocument, localName); } @@ -11604,7 +12343,7 @@ class HTMLLinkElement extends HTMLElement { } get href() { - return stringAttribute.get(this, "href"); + return stringAttribute.get(this, "href").trim(); } set href(value) { stringAttribute.set(this, "href", value); @@ -11640,17 +12379,73 @@ class HTMLLinkElement extends HTMLElement { /* c8 ignore stop */ } -registerHTMLClass(tagName$3, HTMLLinkElement); +registerHTMLClass(tagName$5, HTMLLinkElement); + +const tagName$4 = "slot"; /** * @implements globalThis.HTMLSlotElement */ class HTMLSlotElement extends HTMLElement { - constructor(ownerDocument, localName = "slot") { + constructor(ownerDocument, localName = tagName$4) { super(ownerDocument, localName); } + + /* c8 ignore start */ + get name() { + return this.getAttribute("name"); + } + set name(value) { + this.setAttribute("name", value); + } + + assign() {} + + assignedNodes(options) { + const isNamedSlot = !!this.name; + const hostChildNodes = this.getRootNode().host?.childNodes ?? []; + let slottables; + + if (isNamedSlot) { + slottables = [...hostChildNodes].filter( + (node) => node.slot === this.name + ); + } else { + slottables = [...hostChildNodes].filter((node) => !node.slot); + } + + if (options?.flatten) { + const result = []; + + // Element and Text nodes are slottables. A slot can be a slottable. + for (let slottable of slottables) { + if (slottable.localName === "slot") { + result.push(...slottable.assignedNodes({ flatten: true })); + } else { + result.push(slottable); + } + } + + slottables = result; + } + + // If no assigned nodes are found, it returns the slot's fallback content. + return slottables.length ? slottables : [...this.childNodes]; + } + + assignedElements(options) { + const slottables = this.assignedNodes(options).filter( + (n) => n.nodeType === 1 + ); + + // If no assigned elements are found, it returns the slot's fallback content. + return slottables.length ? slottables : [...this.children]; + } + /* c8 ignore stop */ } +registerHTMLClass(tagName$4, HTMLSlotElement); + /** * @implements globalThis.HTMLFormElement */ @@ -11660,13 +12455,13 @@ class HTMLFormElement extends HTMLElement { } } -const tagName$2 = "img"; +const tagName$3 = "img"; /** * @implements globalThis.HTMLImageElement */ class HTMLImageElement extends HTMLElement { - constructor(ownerDocument, localName = tagName$2) { + constructor(ownerDocument, localName = tagName$3) { super(ownerDocument, localName); } @@ -11722,7 +12517,7 @@ class HTMLImageElement extends HTMLElement { /* c8 ignore stop */ } -registerHTMLClass(tagName$2, HTMLImageElement); +registerHTMLClass(tagName$3, HTMLImageElement); /** * @implements globalThis.HTMLPreElement @@ -11742,15 +12537,55 @@ class HTMLUListElement extends HTMLElement { } } +const tagName$2 = "meta"; /** * @implements globalThis.HTMLMetaElement */ class HTMLMetaElement extends HTMLElement { - constructor(ownerDocument, localName = "meta") { + constructor(ownerDocument, localName = tagName$2) { super(ownerDocument, localName); } + + /* c8 ignore start */ + get name() { + return stringAttribute.get(this, "name"); + } + set name(value) { + stringAttribute.set(this, "name", value); + } + + get httpEquiv() { + return stringAttribute.get(this, "http-equiv"); + } + set httpEquiv(value) { + stringAttribute.set(this, "http-equiv", value); + } + + get content() { + return stringAttribute.get(this, "content"); + } + set content(value) { + stringAttribute.set(this, "content", value); + } + + get charset() { + return stringAttribute.get(this, "charset"); + } + set charset(value) { + stringAttribute.set(this, "charset", value); + } + + get media() { + return stringAttribute.get(this, "media"); + } + set media(value) { + stringAttribute.set(this, "media", value); + } + /* c8 ignore stop */ } +registerHTMLClass(tagName$2, HTMLMetaElement); + /** * @implements globalThis.HTMLPictureElement */ @@ -11799,14 +12634,14 @@ class HTMLAnchorElement extends HTMLElement { /* c8 ignore start */ // copy paste from img.src, already covered get href() { - return encodeURI(stringAttribute.get(this, "href")); + return encodeURI(decodeURI(stringAttribute.get(this, "href"))).trim(); } set href(value) { stringAttribute.set(this, "href", decodeURI(value)); } get download() { - return encodeURI(stringAttribute.get(this, "download")); + return encodeURI(decodeURI(stringAttribute.get(this, "download"))); } set download(value) { stringAttribute.set(this, "download", decodeURI(value)); @@ -11825,6 +12660,13 @@ class HTMLAnchorElement extends HTMLElement { set type(value) { stringAttribute.set(this, "type", value); } + + get rel() { + return stringAttribute.get(this, "rel"); + } + set rel(value) { + stringAttribute.set(this, "rel", value); + } /* c8 ignore stop */ } @@ -12036,15 +12878,12 @@ const Mime = { /** * @implements globalThis.CustomEvent */ -const GlobalCustomEvent = - typeof CustomEvent === "function" - ? CustomEvent - : class CustomEvent extends GlobalEvent { - constructor(type, eventInitDict = {}) { - super(type, eventInitDict); - this.detail = eventInitDict.detail; - } - }; +class CustomEvent extends GlobalEvent { + constructor(type, eventInitDict = {}) { + super(type, eventInitDict); + this.detail = eventInitDict.detail; + } +} /* c8 ignore stop */ @@ -12127,6 +12966,13 @@ class Range { this[END] = getEnd(node); } + // TODO: SVG elements should then create contextual fragments + // that return SVG nodes + selectNodeContents(node) { + this.selectNode(node); + this.commonAncestorContainer = node; + } + surroundContents(parentNode) { parentNode.replaceChildren(this.extractContents()); } @@ -12169,10 +13015,22 @@ class Range { } createContextualFragment(html) { - const template = this.commonAncestorContainer.createElement("template"); - template.innerHTML = html; - this.selectNode(template.content); - return template.content; + const { commonAncestorContainer: doc } = this; + const isSVG = "ownerSVGElement" in doc; + const document = isSVG ? doc.ownerDocument : doc; + let content = htmlToFragment(document, html); + if (isSVG) { + const childNodes = [...content.childNodes]; + content = document.createDocumentFragment(); + Object.setPrototypeOf(content, SVGElement$1.prototype); + content.ownerSVGElement = document; + for (const child of childNodes) { + Object.setPrototypeOf(child, SVGElement$1.prototype); + child.ownerSVGElement = document; + content.appendChild(child); + } + } else this.selectNode(content); + return content; } cloneRange() { @@ -12191,6 +13049,8 @@ const isOK = ({ nodeType }, mask) => { return mask & SHOW_TEXT; case COMMENT_NODE: return mask & SHOW_COMMENT; + case CDATA_SECTION_NODE: + return mask & SHOW_CDATA_SECTION; } return 0; }; @@ -12210,7 +13070,7 @@ class TreeWalker { end = documentElement[END]; } const nodes = []; - while (next !== end) { + while (next && next !== end) { if (isOK(next, whatToShow)) nodes.push(next); next = next[NEXT]; } @@ -12230,7 +13090,7 @@ const query = (method, ownerDocument, selectors) => { }; const globalExports = assign({}, Facades, HTMLClasses, { - CustomEvent: GlobalCustomEvent, + CustomEvent, Event: GlobalEvent, EventTarget: DOMEventTarget, InputEvent, @@ -12243,7 +13103,7 @@ const window = new WeakMap(); /** * @implements globalThis.Document */ -class Document$1 extends NonElementParentNode { +let Document$1 = class Document extends NonElementParentNode { constructor(type) { super(null, "#document", DOCUMENT_NODE); this[CUSTOM_ELEMENTS] = { active: false, registry: null }; @@ -12306,7 +13166,7 @@ class Document$1 extends NonElementParentNode { this[CUSTOM_ELEMENTS] = new CustomElementRegistry(this); return this[CUSTOM_ELEMENTS]; case "performance": - return performance; + return globalThis.performance; case "DOMParser": return this[DOM_PARSER]; case "Image": @@ -12367,8 +13227,11 @@ class Document$1 extends NonElementParentNode { createAttribute(name) { return new Attr$1(this, name); } + createCDATASection(data) { + return new CDATASection$1(this, data); + } createComment(textContent) { - return new Comment$1(this, textContent); + return new Comment$2(this, textContent); } createDocumentFragment() { return new DocumentFragment$1(this); @@ -12396,7 +13259,7 @@ class Document$1 extends NonElementParentNode { createEvent(name) { const event = create$1( - name === "Event" ? new GlobalEvent("") : new GlobalCustomEvent("") + name === "Event" ? new GlobalEvent("") : new CustomEvent("") ); event.initEvent = event.initCustomEvent = ( type, @@ -12404,6 +13267,8 @@ class Document$1 extends NonElementParentNode { cancelable = false, detail ) => { + event.bubbles = !!canBubble; + defineProperties(event, { type: { value: type }, canBubble: { value: canBubble }, @@ -12487,7 +13352,7 @@ class Document$1 extends NonElementParentNode { : this.createElement(localName, options); } /* c8 ignore stop */ -} +}; setPrototypeOf( (globalExports.Document = function Document() { @@ -12569,13 +13434,12 @@ class HTMLDocument extends Document$1 { */ get title() { const { head } = this; - let title = head.getElementsByTagName("title").shift(); - return title ? title.textContent : ""; + return head.getElementsByTagName("title").at(0)?.textContent || ""; } set title(textContent) { const { head } = this; - let title = head.getElementsByTagName("title").shift(); + let title = head.getElementsByTagName("title").at(0); if (title) title.textContent = textContent; else { head.insertBefore( @@ -12638,6 +13502,8 @@ class DOMParser { else document = new XMLDocument(); document[DOM_PARSER] = DOMParser; if (globals) document[GLOBALS] = globals; + if (isHTML && markupLanguage === "...") + markupLanguage = "<!doctype html><html><head></head><body></body></html>"; return markupLanguage ? parseFromString(document, isHTML, markupLanguage) : document; @@ -12709,7 +13575,10 @@ const parseJSON = (value) => { append(parentNode, new Text$1(document, array[i++]), end); break; case COMMENT_NODE: - append(parentNode, new Comment$1(document, array[i++]), end); + append(parentNode, new Comment$2(document, array[i++]), end); + break; + case CDATA_SECTION_NODE: + append(parentNode, new CDATASection$1(document, array[i++]), end); break; case DOCUMENT_TYPE_NODE: { const args = [document]; @@ -12760,6 +13629,9 @@ class NodeFilter { static get SHOW_COMMENT() { return SHOW_COMMENT; } + static get SHOW_CDATA_SECTION() { + return SHOW_CDATA_SECTION; + } static get SHOW_TEXT() { return SHOW_TEXT; } @@ -12776,9 +13648,10 @@ setPrototypeOf(Document, Document$1).prototype = Document$1.prototype; export { Attr, + CDATASection, CharacterData, Comment, - GlobalCustomEvent as CustomEvent, + CustomEvent, DOMParser, Document, DocumentFragment,