webpack 5.110.3 → 5.111.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/README.md +5 -0
  2. package/lib/APIPlugin.js +23 -7
  3. package/lib/AutomaticPrefetchPlugin.js +1 -1
  4. package/lib/Cache.js +8 -3
  5. package/lib/CacheFacade.js +1 -1
  6. package/lib/CircularModulesPlugin.js +157 -55
  7. package/lib/CleanPlugin.js +2 -2
  8. package/lib/Compilation.js +320 -302
  9. package/lib/Compiler.js +209 -46
  10. package/lib/ContextModule.js +17 -81
  11. package/lib/ContextModuleFactory.js +1 -1
  12. package/lib/CopyPlugin.js +1054 -0
  13. package/lib/DefinePlugin.js +24 -8
  14. package/lib/ExternalModule.js +41 -14
  15. package/lib/FileSystemInfo.js +17 -14
  16. package/lib/FlagDependencyExportsPlugin.js +45 -21
  17. package/lib/HotModuleReplacementPlugin.js +53 -7
  18. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  19. package/lib/MainTemplate.js +5 -1
  20. package/lib/Module.js +16 -7
  21. package/lib/MultiCompiler.js +1 -1
  22. package/lib/MultiWatching.js +1 -1
  23. package/lib/NormalModule.js +45 -12
  24. package/lib/NormalModuleFactory.js +1 -1
  25. package/lib/RuntimeGlobals.js +21 -7
  26. package/lib/RuntimeModule.js +28 -12
  27. package/lib/RuntimePlugin.js +30 -3
  28. package/lib/RuntimeTemplate.js +780 -475
  29. package/lib/SourceMapDevToolPlugin.js +1 -1
  30. package/lib/Watching.js +9 -0
  31. package/lib/WebpackOptionsApply.js +84 -91
  32. package/lib/asset/AssetGenerator.js +25 -8
  33. package/lib/asset/AssetModule.js +3 -0
  34. package/lib/asset/WebManifestParser.js +7 -5
  35. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  36. package/lib/cache/IdleFileCachePlugin.js +2 -2
  37. package/lib/cache/PackFileCacheStrategy.js +14 -1
  38. package/lib/config/browserslistTargetHandler.js +19 -0
  39. package/lib/config/defaults.js +86 -50
  40. package/lib/config/normalization.js +82 -12
  41. package/lib/config/target.js +10 -0
  42. package/lib/container/ContainerReferencePlugin.js +6 -0
  43. package/lib/container/RemoteRuntimeModule.js +9 -0
  44. package/lib/container/declaredRemotes.js +39 -0
  45. package/lib/css/CssGenerator.js +8 -0
  46. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  47. package/lib/css/CssLoadingRuntimeModule.js +94 -36
  48. package/lib/css/CssModule.js +1 -1
  49. package/lib/css/CssModulesPlugin.js +7 -6
  50. package/lib/css/CssParser.js +144 -11
  51. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  52. package/lib/css/cssMinify.js +11 -3
  53. package/lib/css/data.js +2814 -678
  54. package/lib/css/syntax.js +4082 -248
  55. package/lib/debug/ProfilingPlugin.js +4 -0
  56. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  57. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  58. package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
  59. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  60. package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
  61. package/lib/dependencies/CommonJsPlugin.js +19 -3
  62. package/lib/dependencies/CommonJsRequireDependency.js +14 -5
  63. package/lib/dependencies/CssIcssExportDependency.js +7 -1
  64. package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
  66. package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
  67. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +71 -13
  68. package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
  69. package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
  70. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  71. package/lib/dependencies/HarmonyImportDependency.js +6 -1
  72. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +8 -1
  73. package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
  74. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  75. package/lib/dependencies/HtmlEntryDependency.js +50 -0
  76. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  77. package/lib/dependencies/ImportMetaPlugin.js +59 -15
  78. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  79. package/lib/dependencies/WorkerDependency.js +1 -2
  80. package/lib/dependencies/WorkletDependency.js +1 -2
  81. package/lib/dll/DelegatedModule.js +18 -1
  82. package/lib/dll/DllReferencePlugin.js +11 -8
  83. package/lib/dll/LibManifestPlugin.js +1 -1
  84. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  85. package/lib/errors/DuplicateModulesWarning.js +12 -7
  86. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  87. package/lib/errors/ExternalStarReexportError.js +44 -0
  88. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  89. package/lib/errors/ModuleParseError.js +2 -1
  90. package/lib/errors/UnusedAssetsWarning.js +36 -0
  91. package/lib/errors/UnusedFederationWarning.js +35 -0
  92. package/lib/errors/UnusedModulesWarning.js +38 -0
  93. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  94. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  95. package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
  96. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
  97. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  98. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  99. package/lib/html/HtmlGenerator.js +11 -5
  100. package/lib/html/HtmlModulesPlugin.js +331 -62
  101. package/lib/html/HtmlParser.js +13 -6
  102. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  103. package/lib/html/data.js +121 -7
  104. package/lib/html/htmlMinify.js +84 -113
  105. package/lib/html/syntax.js +763 -426
  106. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  107. package/lib/index.js +3 -0
  108. package/lib/javascript/JavascriptModule.js +1 -0
  109. package/lib/javascript/JavascriptModulesPlugin.js +52 -24
  110. package/lib/javascript/JavascriptParser.js +1255 -728
  111. package/lib/javascript/StartupHelpers.js +27 -3
  112. package/lib/javascript/data.js +172 -0
  113. package/lib/javascript/grammar.js +5546 -0
  114. package/lib/javascript/parser.js +1494 -0
  115. package/lib/javascript/regexp.js +1762 -0
  116. package/lib/javascript/regexpData.js +51 -0
  117. package/lib/javascript/syntax.js +8696 -5225
  118. package/lib/library/ModuleLibraryPlugin.js +116 -5
  119. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  120. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  121. package/lib/optimize/ConcatenatedModule.js +97 -20
  122. package/lib/optimize/ConstExportsPlugin.js +50 -39
  123. package/lib/optimize/InlineExports.js +20 -123
  124. package/lib/optimize/MangleExportsPlugin.js +10 -0
  125. package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
  126. package/lib/optimize/RealContentHashPlugin.js +68 -9
  127. package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
  128. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  129. package/lib/performance/CacheEffectivenessPlugin.js +4 -3
  130. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  131. package/lib/performance/EvalUsagePlugin.js +5 -2
  132. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  133. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  134. package/lib/performance/TopLevelThisPlugin.js +5 -4
  135. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  136. package/lib/performance/UnusedFederationPlugin.js +147 -0
  137. package/lib/performance/UnusedModulesPlugin.js +141 -0
  138. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  139. package/lib/performance/isOnlyReexported.js +65 -0
  140. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  141. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
  142. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  143. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  144. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  145. package/lib/prefetch/ResourceHintPlugin.js +1 -2
  146. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  147. package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
  148. package/lib/rules/RuleSetCompiler.js +211 -4
  149. package/lib/runtime/AsyncModuleRuntimeModule.js +100 -66
  150. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  151. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  152. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  153. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  154. package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
  155. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  156. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  157. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  158. package/lib/runtime/GlobalRuntimeModule.js +9 -0
  159. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  160. package/lib/runtime/HelperRuntimeModule.js +10 -0
  161. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +330 -219
  162. package/lib/runtime/NonceRuntimeModule.js +9 -0
  163. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  164. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  165. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  166. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  167. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  168. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  169. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  170. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  171. package/lib/serialization/ObjectMiddleware.js +138 -106
  172. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  173. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  174. package/lib/sharing/ShareRuntimeModule.js +9 -0
  175. package/lib/sharing/declaredShared.js +47 -0
  176. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
  177. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  178. package/lib/util/SourceProcessor.js +76 -69
  179. package/lib/util/async.js +292 -0
  180. package/lib/util/buildDiagnostics.js +69 -0
  181. package/lib/util/fs.js +27 -1
  182. package/lib/util/handlerKeys.js +40 -0
  183. package/lib/util/identifier.js +20 -0
  184. package/lib/util/internalSerializables.js +4 -0
  185. package/lib/util/registerExternalSerializer.js +6 -45
  186. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
  187. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
  188. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
  189. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  190. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  191. package/package.json +22 -16
  192. package/schemas/WebpackOptions.check.js +1 -1
  193. package/schemas/WebpackOptions.json +379 -66
  194. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  195. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  196. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  197. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  198. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  199. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  200. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  201. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  202. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  203. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  204. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  205. package/types.d.ts +1414 -314
  206. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  207. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  208. package/lib/performance/EntrypointOverlapPlugin.js +0 -122
@@ -14,13 +14,14 @@ const GenericSourceProcessor = require("../util/SourceProcessor");
14
14
 
15
15
  const { deferredWrite, declineDeferredWrites } = GenericSourceProcessor;
16
16
 
17
- /** @import { CssEnvironment, CssProcessOptions, CssTransformOptions } from "../css/syntax" */
18
17
  /** @import { OutputHtmlOptions } from "../../declarations/WebpackOptions" */
19
18
 
20
19
  /**
21
20
  * Renders one nested body this document embeds — an inline `<style>`, every
22
21
  * `style=""` (handed over as a whole stylesheet), a `<script>` holding JSON or
23
- * JavaScript, an `<svg>` subtree, and the document an `<iframe srcdoc>` holds. Returning the input unchanged declines
22
+ * JavaScript, every event handler attribute (`as` says it is a function body
23
+ * rather than a script), an `<svg>` subtree, and the document an
24
+ * `<iframe srcdoc>` holds. Returning the input unchanged declines
24
25
  * it. Synchronous: it is called from inside the print walk, so a caller with an
25
26
  * async minifier collects the bodies in a walk-only pass first and looks the
26
27
  * results up here.
@@ -47,6 +48,13 @@ const SVG_TYPE = "svg";
47
48
  // it is offered as CSS — with `as` saying which production it is, the same
48
49
  // vocabulary `module.parser.css.as` uses.
49
50
  const BLOCK_CONTENTS = "block-contents";
51
+ // An `onclick=""` is that shape one language over: JavaScript, but a function
52
+ // body — the production the `return` cancelling an event is written in.
53
+ const EVENT_HANDLER = "event-handler";
54
+ // JavaScript's two top level productions. Which one a body is decides whether
55
+ // `import` parses, whether it is strict, and whether `-->` opens a comment.
56
+ const MODULE_SCRIPT = "module";
57
+ const CLASSIC_SCRIPT = "script";
50
58
 
51
59
  const {
52
60
  askEmbeddedRenderer,
@@ -65,6 +73,10 @@ const EMBEDDED_LANGUAGES = [
65
73
  HTML_TYPE
66
74
  ];
67
75
 
76
+ const {
77
+ builtinEmbeddedRenderer,
78
+ stripJsonWhitespace
79
+ } = require("./builtinEmbeddedRenderer");
68
80
  const {
69
81
  ADDRESS_DIV_P,
70
82
  APPLET_MARQUEE_OBJECT,
@@ -87,6 +99,7 @@ const {
87
99
  EMPTY_REMOVABLE_ATTRIBUTES,
88
100
  ENUMERATED_ATTRIBUTE_NAMES,
89
101
  ENUMERATED_KEYWORDS,
102
+ EVENT_HANDLER_ATTRIBUTES,
90
103
  FONT_BREAKOUT_ATTRS,
91
104
  FOREIGN_ATTR_NS,
92
105
  FOREIGN_BREAKOUT,
@@ -149,22 +162,20 @@ const {
149
162
  VOID,
150
163
  VOID_FORMATTING
151
164
  } = require("./data");
165
+ const htmlMinify = require("./htmlMinify");
152
166
 
153
167
  // cspell:ignore apos notpre noncharacter noncharacters DFFF FFFE CCLS ALNUM
154
168
 
155
169
  // #region html entities
156
- // The contents of this region are auto-generated by
157
- // `tooling/generate-html-entities.js` from `tooling/html-entities.json`.
158
- // Do not edit by hand — re-run the generator (via `yarn fix:special`) to refresh.
159
- //
160
- // WHATWG named character references. Keys are entity names WITHOUT the
161
- // leading `&` (some end with `;`, others omit it for legacy entities that
162
- // match without a closing semicolon). Values are the decoded character
163
- // strings (1–2 UTF-16 code units).
164
- // Built on a null prototype so bracket lookups (`HTML_ENTITIES[name]`)
165
- // can't be poisoned by inherited `Object.prototype` keys like `toString`,
166
- // `constructor`, or `__proto__` — without this, `&toString;` would falsely
167
- // look like a matched named character reference.
170
+ // Auto-generated by `tooling/generate-html-data.js` from
171
+ // `tooling/html-entities.json` — run `yarn fix:special` to refresh.
172
+
173
+ // WHATWG named character references, keyed without the leading `&`: the keys
174
+ // that do not end in `;` are the legacy names matching unterminated.
175
+
176
+ // Null-prototype, so `&toString;` cannot reach an inherited `Object.prototype`
177
+ // key and read back as a matched reference.
178
+
168
179
  // prettier-ignore
169
180
  // cspell:disable-next-line
170
181
  const HTML_ENTITIES = /** @type {Readonly<Record<string, string>>} */ (Object.freeze(Object.assign(Object.create(null), {"AElig":"Æ","AElig;":"Æ","AMP":"&","AMP;":"&","Aacute":"Á","Aacute;":"Á","Abreve;":"Ă","Acirc":"Â","Acirc;":"Â","Acy;":"А","Afr;":"𝔄","Agrave":"À","Agrave;":"À","Alpha;":"Α","Amacr;":"Ā","And;":"⩓","Aogon;":"Ą","Aopf;":"𝔸","ApplyFunction;":"⁡","Aring":"Å","Aring;":"Å","Ascr;":"𝒜","Assign;":"≔","Atilde":"Ã","Atilde;":"Ã","Auml":"Ä","Auml;":"Ä","Backslash;":"∖","Barv;":"⫧","Barwed;":"⌆","Bcy;":"Б","Because;":"∵","Bernoullis;":"ℬ","Beta;":"Β","Bfr;":"𝔅","Bopf;":"𝔹","Breve;":"˘","Bscr;":"ℬ","Bumpeq;":"≎","CHcy;":"Ч","COPY":"©","COPY;":"©","Cacute;":"Ć","Cap;":"⋒","CapitalDifferentialD;":"ⅅ","Cayleys;":"ℭ","Ccaron;":"Č","Ccedil":"Ç","Ccedil;":"Ç","Ccirc;":"Ĉ","Cconint;":"∰","Cdot;":"Ċ","Cedilla;":"¸","CenterDot;":"·","Cfr;":"ℭ","Chi;":"Χ","CircleDot;":"⊙","CircleMinus;":"⊖","CirclePlus;":"⊕","CircleTimes;":"⊗","ClockwiseContourIntegral;":"∲","CloseCurlyDoubleQuote;":"”","CloseCurlyQuote;":"’","Colon;":"∷","Colone;":"⩴","Congruent;":"≡","Conint;":"∯","ContourIntegral;":"∮","Copf;":"ℂ","Coproduct;":"∐","CounterClockwiseContourIntegral;":"∳","Cross;":"⨯","Cscr;":"𝒞","Cup;":"⋓","CupCap;":"≍","DD;":"ⅅ","DDotrahd;":"⤑","DJcy;":"Ђ","DScy;":"Ѕ","DZcy;":"Џ","Dagger;":"‡","Darr;":"↡","Dashv;":"⫤","Dcaron;":"Ď","Dcy;":"Д","Del;":"∇","Delta;":"Δ","Dfr;":"𝔇","DiacriticalAcute;":"´","DiacriticalDot;":"˙","DiacriticalDoubleAcute;":"˝","DiacriticalGrave;":"`","DiacriticalTilde;":"˜","Diamond;":"⋄","DifferentialD;":"ⅆ","Dopf;":"𝔻","Dot;":"¨","DotDot;":"⃜","DotEqual;":"≐","DoubleContourIntegral;":"∯","DoubleDot;":"¨","DoubleDownArrow;":"⇓","DoubleLeftArrow;":"⇐","DoubleLeftRightArrow;":"⇔","DoubleLeftTee;":"⫤","DoubleLongLeftArrow;":"⟸","DoubleLongLeftRightArrow;":"⟺","DoubleLongRightArrow;":"⟹","DoubleRightArrow;":"⇒","DoubleRightTee;":"⊨","DoubleUpArrow;":"⇑","DoubleUpDownArrow;":"⇕","DoubleVerticalBar;":"∥","DownArrow;":"↓","DownArrowBar;":"⤓","DownArrowUpArrow;":"⇵","DownBreve;":"̑","DownLeftRightVector;":"⥐","DownLeftTeeVector;":"⥞","DownLeftVector;":"↽","DownLeftVectorBar;":"⥖","DownRightTeeVector;":"⥟","DownRightVector;":"⇁","DownRightVectorBar;":"⥗","DownTee;":"⊤","DownTeeArrow;":"↧","Downarrow;":"⇓","Dscr;":"𝒟","Dstrok;":"Đ","ENG;":"Ŋ","ETH":"Ð","ETH;":"Ð","Eacute":"É","Eacute;":"É","Ecaron;":"Ě","Ecirc":"Ê","Ecirc;":"Ê","Ecy;":"Э","Edot;":"Ė","Efr;":"𝔈","Egrave":"È","Egrave;":"È","Element;":"∈","Emacr;":"Ē","EmptySmallSquare;":"◻","EmptyVerySmallSquare;":"▫","Eogon;":"Ę","Eopf;":"𝔼","Epsilon;":"Ε","Equal;":"⩵","EqualTilde;":"≂","Equilibrium;":"⇌","Escr;":"ℰ","Esim;":"⩳","Eta;":"Η","Euml":"Ë","Euml;":"Ë","Exists;":"∃","ExponentialE;":"ⅇ","Fcy;":"Ф","Ffr;":"𝔉","FilledSmallSquare;":"◼","FilledVerySmallSquare;":"▪","Fopf;":"𝔽","ForAll;":"∀","Fouriertrf;":"ℱ","Fscr;":"ℱ","GJcy;":"Ѓ","GT":">","GT;":">","Gamma;":"Γ","Gammad;":"Ϝ","Gbreve;":"Ğ","Gcedil;":"Ģ","Gcirc;":"Ĝ","Gcy;":"Г","Gdot;":"Ġ","Gfr;":"𝔊","Gg;":"⋙","Gopf;":"𝔾","GreaterEqual;":"≥","GreaterEqualLess;":"⋛","GreaterFullEqual;":"≧","GreaterGreater;":"⪢","GreaterLess;":"≷","GreaterSlantEqual;":"⩾","GreaterTilde;":"≳","Gscr;":"𝒢","Gt;":"≫","HARDcy;":"Ъ","Hacek;":"ˇ","Hat;":"^","Hcirc;":"Ĥ","Hfr;":"ℌ","HilbertSpace;":"ℋ","Hopf;":"ℍ","HorizontalLine;":"─","Hscr;":"ℋ","Hstrok;":"Ħ","HumpDownHump;":"≎","HumpEqual;":"≏","IEcy;":"Е","IJlig;":"IJ","IOcy;":"Ё","Iacute":"Í","Iacute;":"Í","Icirc":"Î","Icirc;":"Î","Icy;":"И","Idot;":"İ","Ifr;":"ℑ","Igrave":"Ì","Igrave;":"Ì","Im;":"ℑ","Imacr;":"Ī","ImaginaryI;":"ⅈ","Implies;":"⇒","Int;":"∬","Integral;":"∫","Intersection;":"⋂","InvisibleComma;":"⁣","InvisibleTimes;":"⁢","Iogon;":"Į","Iopf;":"𝕀","Iota;":"Ι","Iscr;":"ℐ","Itilde;":"Ĩ","Iukcy;":"І","Iuml":"Ï","Iuml;":"Ï","Jcirc;":"Ĵ","Jcy;":"Й","Jfr;":"𝔍","Jopf;":"𝕁","Jscr;":"𝒥","Jsercy;":"Ј","Jukcy;":"Є","KHcy;":"Х","KJcy;":"Ќ","Kappa;":"Κ","Kcedil;":"Ķ","Kcy;":"К","Kfr;":"𝔎","Kopf;":"𝕂","Kscr;":"𝒦","LJcy;":"Љ","LT":"<","LT;":"<","Lacute;":"Ĺ","Lambda;":"Λ","Lang;":"⟪","Laplacetrf;":"ℒ","Larr;":"↞","Lcaron;":"Ľ","Lcedil;":"Ļ","Lcy;":"Л","LeftAngleBracket;":"⟨","LeftArrow;":"←","LeftArrowBar;":"⇤","LeftArrowRightArrow;":"⇆","LeftCeiling;":"⌈","LeftDoubleBracket;":"⟦","LeftDownTeeVector;":"⥡","LeftDownVector;":"⇃","LeftDownVectorBar;":"⥙","LeftFloor;":"⌊","LeftRightArrow;":"↔","LeftRightVector;":"⥎","LeftTee;":"⊣","LeftTeeArrow;":"↤","LeftTeeVector;":"⥚","LeftTriangle;":"⊲","LeftTriangleBar;":"⧏","LeftTriangleEqual;":"⊴","LeftUpDownVector;":"⥑","LeftUpTeeVector;":"⥠","LeftUpVector;":"↿","LeftUpVectorBar;":"⥘","LeftVector;":"↼","LeftVectorBar;":"⥒","Leftarrow;":"⇐","Leftrightarrow;":"⇔","LessEqualGreater;":"⋚","LessFullEqual;":"≦","LessGreater;":"≶","LessLess;":"⪡","LessSlantEqual;":"⩽","LessTilde;":"≲","Lfr;":"𝔏","Ll;":"⋘","Lleftarrow;":"⇚","Lmidot;":"Ŀ","LongLeftArrow;":"⟵","LongLeftRightArrow;":"⟷","LongRightArrow;":"⟶","Longleftarrow;":"⟸","Longleftrightarrow;":"⟺","Longrightarrow;":"⟹","Lopf;":"𝕃","LowerLeftArrow;":"↙","LowerRightArrow;":"↘","Lscr;":"ℒ","Lsh;":"↰","Lstrok;":"Ł","Lt;":"≪","Map;":"⤅","Mcy;":"М","MediumSpace;":" ","Mellintrf;":"ℳ","Mfr;":"𝔐","MinusPlus;":"∓","Mopf;":"𝕄","Mscr;":"ℳ","Mu;":"Μ","NJcy;":"Њ","Nacute;":"Ń","Ncaron;":"Ň","Ncedil;":"Ņ","Ncy;":"Н","NegativeMediumSpace;":"​","NegativeThickSpace;":"​","NegativeThinSpace;":"​","NegativeVeryThinSpace;":"​","NestedGreaterGreater;":"≫","NestedLessLess;":"≪","NewLine;":"\n","Nfr;":"𝔑","NoBreak;":"⁠","NonBreakingSpace;":" ","Nopf;":"ℕ","Not;":"⫬","NotCongruent;":"≢","NotCupCap;":"≭","NotDoubleVerticalBar;":"∦","NotElement;":"∉","NotEqual;":"≠","NotEqualTilde;":"≂̸","NotExists;":"∄","NotGreater;":"≯","NotGreaterEqual;":"≱","NotGreaterFullEqual;":"≧̸","NotGreaterGreater;":"≫̸","NotGreaterLess;":"≹","NotGreaterSlantEqual;":"⩾̸","NotGreaterTilde;":"≵","NotHumpDownHump;":"≎̸","NotHumpEqual;":"≏̸","NotLeftTriangle;":"⋪","NotLeftTriangleBar;":"⧏̸","NotLeftTriangleEqual;":"⋬","NotLess;":"≮","NotLessEqual;":"≰","NotLessGreater;":"≸","NotLessLess;":"≪̸","NotLessSlantEqual;":"⩽̸","NotLessTilde;":"≴","NotNestedGreaterGreater;":"⪢̸","NotNestedLessLess;":"⪡̸","NotPrecedes;":"⊀","NotPrecedesEqual;":"⪯̸","NotPrecedesSlantEqual;":"⋠","NotReverseElement;":"∌","NotRightTriangle;":"⋫","NotRightTriangleBar;":"⧐̸","NotRightTriangleEqual;":"⋭","NotSquareSubset;":"⊏̸","NotSquareSubsetEqual;":"⋢","NotSquareSuperset;":"⊐̸","NotSquareSupersetEqual;":"⋣","NotSubset;":"⊂⃒","NotSubsetEqual;":"⊈","NotSucceeds;":"⊁","NotSucceedsEqual;":"⪰̸","NotSucceedsSlantEqual;":"⋡","NotSucceedsTilde;":"≿̸","NotSuperset;":"⊃⃒","NotSupersetEqual;":"⊉","NotTilde;":"≁","NotTildeEqual;":"≄","NotTildeFullEqual;":"≇","NotTildeTilde;":"≉","NotVerticalBar;":"∤","Nscr;":"𝒩","Ntilde":"Ñ","Ntilde;":"Ñ","Nu;":"Ν","OElig;":"Œ","Oacute":"Ó","Oacute;":"Ó","Ocirc":"Ô","Ocirc;":"Ô","Ocy;":"О","Odblac;":"Ő","Ofr;":"𝔒","Ograve":"Ò","Ograve;":"Ò","Omacr;":"Ō","Omega;":"Ω","Omicron;":"Ο","Oopf;":"𝕆","OpenCurlyDoubleQuote;":"“","OpenCurlyQuote;":"‘","Or;":"⩔","Oscr;":"𝒪","Oslash":"Ø","Oslash;":"Ø","Otilde":"Õ","Otilde;":"Õ","Otimes;":"⨷","Ouml":"Ö","Ouml;":"Ö","OverBar;":"‾","OverBrace;":"⏞","OverBracket;":"⎴","OverParenthesis;":"⏜","PartialD;":"∂","Pcy;":"П","Pfr;":"𝔓","Phi;":"Φ","Pi;":"Π","PlusMinus;":"±","Poincareplane;":"ℌ","Popf;":"ℙ","Pr;":"⪻","Precedes;":"≺","PrecedesEqual;":"⪯","PrecedesSlantEqual;":"≼","PrecedesTilde;":"≾","Prime;":"″","Product;":"∏","Proportion;":"∷","Proportional;":"∝","Pscr;":"𝒫","Psi;":"Ψ","QUOT":"\"","QUOT;":"\"","Qfr;":"𝔔","Qopf;":"ℚ","Qscr;":"𝒬","RBarr;":"⤐","REG":"®","REG;":"®","Racute;":"Ŕ","Rang;":"⟫","Rarr;":"↠","Rarrtl;":"⤖","Rcaron;":"Ř","Rcedil;":"Ŗ","Rcy;":"Р","Re;":"ℜ","ReverseElement;":"∋","ReverseEquilibrium;":"⇋","ReverseUpEquilibrium;":"⥯","Rfr;":"ℜ","Rho;":"Ρ","RightAngleBracket;":"⟩","RightArrow;":"→","RightArrowBar;":"⇥","RightArrowLeftArrow;":"⇄","RightCeiling;":"⌉","RightDoubleBracket;":"⟧","RightDownTeeVector;":"⥝","RightDownVector;":"⇂","RightDownVectorBar;":"⥕","RightFloor;":"⌋","RightTee;":"⊢","RightTeeArrow;":"↦","RightTeeVector;":"⥛","RightTriangle;":"⊳","RightTriangleBar;":"⧐","RightTriangleEqual;":"⊵","RightUpDownVector;":"⥏","RightUpTeeVector;":"⥜","RightUpVector;":"↾","RightUpVectorBar;":"⥔","RightVector;":"⇀","RightVectorBar;":"⥓","Rightarrow;":"⇒","Ropf;":"ℝ","RoundImplies;":"⥰","Rrightarrow;":"⇛","Rscr;":"ℛ","Rsh;":"↱","RuleDelayed;":"⧴","SHCHcy;":"Щ","SHcy;":"Ш","SOFTcy;":"Ь","Sacute;":"Ś","Sc;":"⪼","Scaron;":"Š","Scedil;":"Ş","Scirc;":"Ŝ","Scy;":"С","Sfr;":"𝔖","ShortDownArrow;":"↓","ShortLeftArrow;":"←","ShortRightArrow;":"→","ShortUpArrow;":"↑","Sigma;":"Σ","SmallCircle;":"∘","Sopf;":"𝕊","Sqrt;":"√","Square;":"□","SquareIntersection;":"⊓","SquareSubset;":"⊏","SquareSubsetEqual;":"⊑","SquareSuperset;":"⊐","SquareSupersetEqual;":"⊒","SquareUnion;":"⊔","Sscr;":"𝒮","Star;":"⋆","Sub;":"⋐","Subset;":"⋐","SubsetEqual;":"⊆","Succeeds;":"≻","SucceedsEqual;":"⪰","SucceedsSlantEqual;":"≽","SucceedsTilde;":"≿","SuchThat;":"∋","Sum;":"∑","Sup;":"⋑","Superset;":"⊃","SupersetEqual;":"⊇","Supset;":"⋑","THORN":"Þ","THORN;":"Þ","TRADE;":"™","TSHcy;":"Ћ","TScy;":"Ц","Tab;":"\t","Tau;":"Τ","Tcaron;":"Ť","Tcedil;":"Ţ","Tcy;":"Т","Tfr;":"𝔗","Therefore;":"∴","Theta;":"Θ","ThickSpace;":"  ","ThinSpace;":" ","Tilde;":"∼","TildeEqual;":"≃","TildeFullEqual;":"≅","TildeTilde;":"≈","Topf;":"𝕋","TripleDot;":"⃛","Tscr;":"𝒯","Tstrok;":"Ŧ","Uacute":"Ú","Uacute;":"Ú","Uarr;":"↟","Uarrocir;":"⥉","Ubrcy;":"Ў","Ubreve;":"Ŭ","Ucirc":"Û","Ucirc;":"Û","Ucy;":"У","Udblac;":"Ű","Ufr;":"𝔘","Ugrave":"Ù","Ugrave;":"Ù","Umacr;":"Ū","UnderBar;":"_","UnderBrace;":"⏟","UnderBracket;":"⎵","UnderParenthesis;":"⏝","Union;":"⋃","UnionPlus;":"⊎","Uogon;":"Ų","Uopf;":"𝕌","UpArrow;":"↑","UpArrowBar;":"⤒","UpArrowDownArrow;":"⇅","UpDownArrow;":"↕","UpEquilibrium;":"⥮","UpTee;":"⊥","UpTeeArrow;":"↥","Uparrow;":"⇑","Updownarrow;":"⇕","UpperLeftArrow;":"↖","UpperRightArrow;":"↗","Upsi;":"ϒ","Upsilon;":"Υ","Uring;":"Ů","Uscr;":"𝒰","Utilde;":"Ũ","Uuml":"Ü","Uuml;":"Ü","VDash;":"⊫","Vbar;":"⫫","Vcy;":"В","Vdash;":"⊩","Vdashl;":"⫦","Vee;":"⋁","Verbar;":"‖","Vert;":"‖","VerticalBar;":"∣","VerticalLine;":"|","VerticalSeparator;":"❘","VerticalTilde;":"≀","VeryThinSpace;":" ","Vfr;":"𝔙","Vopf;":"𝕍","Vscr;":"𝒱","Vvdash;":"⊪","Wcirc;":"Ŵ","Wedge;":"⋀","Wfr;":"𝔚","Wopf;":"𝕎","Wscr;":"𝒲","Xfr;":"𝔛","Xi;":"Ξ","Xopf;":"𝕏","Xscr;":"𝒳","YAcy;":"Я","YIcy;":"Ї","YUcy;":"Ю","Yacute":"Ý","Yacute;":"Ý","Ycirc;":"Ŷ","Ycy;":"Ы","Yfr;":"𝔜","Yopf;":"𝕐","Yscr;":"𝒴","Yuml;":"Ÿ","ZHcy;":"Ж","Zacute;":"Ź","Zcaron;":"Ž","Zcy;":"З","Zdot;":"Ż","ZeroWidthSpace;":"​","Zeta;":"Ζ","Zfr;":"ℨ","Zopf;":"ℤ","Zscr;":"𝒵","aacute":"á","aacute;":"á","abreve;":"ă","ac;":"∾","acE;":"∾̳","acd;":"∿","acirc":"â","acirc;":"â","acute":"´","acute;":"´","acy;":"а","aelig":"æ","aelig;":"æ","af;":"⁡","afr;":"𝔞","agrave":"à","agrave;":"à","alefsym;":"ℵ","aleph;":"ℵ","alpha;":"α","amacr;":"ā","amalg;":"⨿","amp":"&","amp;":"&","and;":"∧","andand;":"⩕","andd;":"⩜","andslope;":"⩘","andv;":"⩚","ang;":"∠","ange;":"⦤","angle;":"∠","angmsd;":"∡","angmsdaa;":"⦨","angmsdab;":"⦩","angmsdac;":"⦪","angmsdad;":"⦫","angmsdae;":"⦬","angmsdaf;":"⦭","angmsdag;":"⦮","angmsdah;":"⦯","angrt;":"∟","angrtvb;":"⊾","angrtvbd;":"⦝","angsph;":"∢","angst;":"Å","angzarr;":"⍼","aogon;":"ą","aopf;":"𝕒","ap;":"≈","apE;":"⩰","apacir;":"⩯","ape;":"≊","apid;":"≋","apos;":"'","approx;":"≈","approxeq;":"≊","aring":"å","aring;":"å","ascr;":"𝒶","ast;":"*","asymp;":"≈","asympeq;":"≍","atilde":"ã","atilde;":"ã","auml":"ä","auml;":"ä","awconint;":"∳","awint;":"⨑","bNot;":"⫭","backcong;":"≌","backepsilon;":"϶","backprime;":"‵","backsim;":"∽","backsimeq;":"⋍","barvee;":"⊽","barwed;":"⌅","barwedge;":"⌅","bbrk;":"⎵","bbrktbrk;":"⎶","bcong;":"≌","bcy;":"б","bdquo;":"„","becaus;":"∵","because;":"∵","bemptyv;":"⦰","bepsi;":"϶","bernou;":"ℬ","beta;":"β","beth;":"ℶ","between;":"≬","bfr;":"𝔟","bigcap;":"⋂","bigcirc;":"◯","bigcup;":"⋃","bigodot;":"⨀","bigoplus;":"⨁","bigotimes;":"⨂","bigsqcup;":"⨆","bigstar;":"★","bigtriangledown;":"▽","bigtriangleup;":"△","biguplus;":"⨄","bigvee;":"⋁","bigwedge;":"⋀","bkarow;":"⤍","blacklozenge;":"⧫","blacksquare;":"▪","blacktriangle;":"▴","blacktriangledown;":"▾","blacktriangleleft;":"◂","blacktriangleright;":"▸","blank;":"␣","blk12;":"▒","blk14;":"░","blk34;":"▓","block;":"█","bne;":"=⃥","bnequiv;":"≡⃥","bnot;":"⌐","bopf;":"𝕓","bot;":"⊥","bottom;":"⊥","bowtie;":"⋈","boxDL;":"╗","boxDR;":"╔","boxDl;":"╖","boxDr;":"╓","boxH;":"═","boxHD;":"╦","boxHU;":"╩","boxHd;":"╤","boxHu;":"╧","boxUL;":"╝","boxUR;":"╚","boxUl;":"╜","boxUr;":"╙","boxV;":"║","boxVH;":"╬","boxVL;":"╣","boxVR;":"╠","boxVh;":"╫","boxVl;":"╢","boxVr;":"╟","boxbox;":"⧉","boxdL;":"╕","boxdR;":"╒","boxdl;":"┐","boxdr;":"┌","boxh;":"─","boxhD;":"╥","boxhU;":"╨","boxhd;":"┬","boxhu;":"┴","boxminus;":"⊟","boxplus;":"⊞","boxtimes;":"⊠","boxuL;":"╛","boxuR;":"╘","boxul;":"┘","boxur;":"└","boxv;":"│","boxvH;":"╪","boxvL;":"╡","boxvR;":"╞","boxvh;":"┼","boxvl;":"┤","boxvr;":"├","bprime;":"‵","breve;":"˘","brvbar":"¦","brvbar;":"¦","bscr;":"𝒷","bsemi;":"⁏","bsim;":"∽","bsime;":"⋍","bsol;":"\\","bsolb;":"⧅","bsolhsub;":"⟈","bull;":"•","bullet;":"•","bump;":"≎","bumpE;":"⪮","bumpe;":"≏","bumpeq;":"≏","cacute;":"ć","cap;":"∩","capand;":"⩄","capbrcup;":"⩉","capcap;":"⩋","capcup;":"⩇","capdot;":"⩀","caps;":"∩︀","caret;":"⁁","caron;":"ˇ","ccaps;":"⩍","ccaron;":"č","ccedil":"ç","ccedil;":"ç","ccirc;":"ĉ","ccups;":"⩌","ccupssm;":"⩐","cdot;":"ċ","cedil":"¸","cedil;":"¸","cemptyv;":"⦲","cent":"¢","cent;":"¢","centerdot;":"·","cfr;":"𝔠","chcy;":"ч","check;":"✓","checkmark;":"✓","chi;":"χ","cir;":"○","cirE;":"⧃","circ;":"ˆ","circeq;":"≗","circlearrowleft;":"↺","circlearrowright;":"↻","circledR;":"®","circledS;":"Ⓢ","circledast;":"⊛","circledcirc;":"⊚","circleddash;":"⊝","cire;":"≗","cirfnint;":"⨐","cirmid;":"⫯","cirscir;":"⧂","clubs;":"♣","clubsuit;":"♣","colon;":":","colone;":"≔","coloneq;":"≔","comma;":",","commat;":"@","comp;":"∁","compfn;":"∘","complement;":"∁","complexes;":"ℂ","cong;":"≅","congdot;":"⩭","conint;":"∮","copf;":"𝕔","coprod;":"∐","copy":"©","copy;":"©","copysr;":"℗","crarr;":"↵","cross;":"✗","cscr;":"𝒸","csub;":"⫏","csube;":"⫑","csup;":"⫐","csupe;":"⫒","ctdot;":"⋯","cudarrl;":"⤸","cudarrr;":"⤵","cuepr;":"⋞","cuesc;":"⋟","cularr;":"↶","cularrp;":"⤽","cup;":"∪","cupbrcap;":"⩈","cupcap;":"⩆","cupcup;":"⩊","cupdot;":"⊍","cupor;":"⩅","cups;":"∪︀","curarr;":"↷","curarrm;":"⤼","curlyeqprec;":"⋞","curlyeqsucc;":"⋟","curlyvee;":"⋎","curlywedge;":"⋏","curren":"¤","curren;":"¤","curvearrowleft;":"↶","curvearrowright;":"↷","cuvee;":"⋎","cuwed;":"⋏","cwconint;":"∲","cwint;":"∱","cylcty;":"⌭","dArr;":"⇓","dHar;":"⥥","dagger;":"†","daleth;":"ℸ","darr;":"↓","dash;":"‐","dashv;":"⊣","dbkarow;":"⤏","dblac;":"˝","dcaron;":"ď","dcy;":"д","dd;":"ⅆ","ddagger;":"‡","ddarr;":"⇊","ddotseq;":"⩷","deg":"°","deg;":"°","delta;":"δ","demptyv;":"⦱","dfisht;":"⥿","dfr;":"𝔡","dharl;":"⇃","dharr;":"⇂","diam;":"⋄","diamond;":"⋄","diamondsuit;":"♦","diams;":"♦","die;":"¨","digamma;":"ϝ","disin;":"⋲","div;":"÷","divide":"÷","divide;":"÷","divideontimes;":"⋇","divonx;":"⋇","djcy;":"ђ","dlcorn;":"⌞","dlcrop;":"⌍","dollar;":"$","dopf;":"𝕕","dot;":"˙","doteq;":"≐","doteqdot;":"≑","dotminus;":"∸","dotplus;":"∔","dotsquare;":"⊡","doublebarwedge;":"⌆","downarrow;":"↓","downdownarrows;":"⇊","downharpoonleft;":"⇃","downharpoonright;":"⇂","drbkarow;":"⤐","drcorn;":"⌟","drcrop;":"⌌","dscr;":"𝒹","dscy;":"ѕ","dsol;":"⧶","dstrok;":"đ","dtdot;":"⋱","dtri;":"▿","dtrif;":"▾","duarr;":"⇵","duhar;":"⥯","dwangle;":"⦦","dzcy;":"џ","dzigrarr;":"⟿","eDDot;":"⩷","eDot;":"≑","eacute":"é","eacute;":"é","easter;":"⩮","ecaron;":"ě","ecir;":"≖","ecirc":"ê","ecirc;":"ê","ecolon;":"≕","ecy;":"э","edot;":"ė","ee;":"ⅇ","efDot;":"≒","efr;":"𝔢","eg;":"⪚","egrave":"è","egrave;":"è","egs;":"⪖","egsdot;":"⪘","el;":"⪙","elinters;":"⏧","ell;":"ℓ","els;":"⪕","elsdot;":"⪗","emacr;":"ē","empty;":"∅","emptyset;":"∅","emptyv;":"∅","emsp13;":" ","emsp14;":" ","emsp;":" ","eng;":"ŋ","ensp;":" ","eogon;":"ę","eopf;":"𝕖","epar;":"⋕","eparsl;":"⧣","eplus;":"⩱","epsi;":"ε","epsilon;":"ε","epsiv;":"ϵ","eqcirc;":"≖","eqcolon;":"≕","eqsim;":"≂","eqslantgtr;":"⪖","eqslantless;":"⪕","equals;":"=","equest;":"≟","equiv;":"≡","equivDD;":"⩸","eqvparsl;":"⧥","erDot;":"≓","erarr;":"⥱","escr;":"ℯ","esdot;":"≐","esim;":"≂","eta;":"η","eth":"ð","eth;":"ð","euml":"ë","euml;":"ë","euro;":"€","excl;":"!","exist;":"∃","expectation;":"ℰ","exponentiale;":"ⅇ","fallingdotseq;":"≒","fcy;":"ф","female;":"♀","ffilig;":"ffi","fflig;":"ff","ffllig;":"ffl","ffr;":"𝔣","filig;":"fi","fjlig;":"fj","flat;":"♭","fllig;":"fl","fltns;":"▱","fnof;":"ƒ","fopf;":"𝕗","forall;":"∀","fork;":"⋔","forkv;":"⫙","fpartint;":"⨍","frac12":"½","frac12;":"½","frac13;":"⅓","frac14":"¼","frac14;":"¼","frac15;":"⅕","frac16;":"⅙","frac18;":"⅛","frac23;":"⅔","frac25;":"⅖","frac34":"¾","frac34;":"¾","frac35;":"⅗","frac38;":"⅜","frac45;":"⅘","frac56;":"⅚","frac58;":"⅝","frac78;":"⅞","frasl;":"⁄","frown;":"⌢","fscr;":"𝒻","gE;":"≧","gEl;":"⪌","gacute;":"ǵ","gamma;":"γ","gammad;":"ϝ","gap;":"⪆","gbreve;":"ğ","gcirc;":"ĝ","gcy;":"г","gdot;":"ġ","ge;":"≥","gel;":"⋛","geq;":"≥","geqq;":"≧","geqslant;":"⩾","ges;":"⩾","gescc;":"⪩","gesdot;":"⪀","gesdoto;":"⪂","gesdotol;":"⪄","gesl;":"⋛︀","gesles;":"⪔","gfr;":"𝔤","gg;":"≫","ggg;":"⋙","gimel;":"ℷ","gjcy;":"ѓ","gl;":"≷","glE;":"⪒","gla;":"⪥","glj;":"⪤","gnE;":"≩","gnap;":"⪊","gnapprox;":"⪊","gne;":"⪈","gneq;":"⪈","gneqq;":"≩","gnsim;":"⋧","gopf;":"𝕘","grave;":"`","gscr;":"ℊ","gsim;":"≳","gsime;":"⪎","gsiml;":"⪐","gt":">","gt;":">","gtcc;":"⪧","gtcir;":"⩺","gtdot;":"⋗","gtlPar;":"⦕","gtquest;":"⩼","gtrapprox;":"⪆","gtrarr;":"⥸","gtrdot;":"⋗","gtreqless;":"⋛","gtreqqless;":"⪌","gtrless;":"≷","gtrsim;":"≳","gvertneqq;":"≩︀","gvnE;":"≩︀","hArr;":"⇔","hairsp;":" ","half;":"½","hamilt;":"ℋ","hardcy;":"ъ","harr;":"↔","harrcir;":"⥈","harrw;":"↭","hbar;":"ℏ","hcirc;":"ĥ","hearts;":"♥","heartsuit;":"♥","hellip;":"…","hercon;":"⊹","hfr;":"𝔥","hksearow;":"⤥","hkswarow;":"⤦","hoarr;":"⇿","homtht;":"∻","hookleftarrow;":"↩","hookrightarrow;":"↪","hopf;":"𝕙","horbar;":"―","hscr;":"𝒽","hslash;":"ℏ","hstrok;":"ħ","hybull;":"⁃","hyphen;":"‐","iacute":"í","iacute;":"í","ic;":"⁣","icirc":"î","icirc;":"î","icy;":"и","iecy;":"е","iexcl":"¡","iexcl;":"¡","iff;":"⇔","ifr;":"𝔦","igrave":"ì","igrave;":"ì","ii;":"ⅈ","iiiint;":"⨌","iiint;":"∭","iinfin;":"⧜","iiota;":"℩","ijlig;":"ij","imacr;":"ī","image;":"ℑ","imagline;":"ℐ","imagpart;":"ℑ","imath;":"ı","imof;":"⊷","imped;":"Ƶ","in;":"∈","incare;":"℅","infin;":"∞","infintie;":"⧝","inodot;":"ı","int;":"∫","intcal;":"⊺","integers;":"ℤ","intercal;":"⊺","intlarhk;":"⨗","intprod;":"⨼","iocy;":"ё","iogon;":"į","iopf;":"𝕚","iota;":"ι","iprod;":"⨼","iquest":"¿","iquest;":"¿","iscr;":"𝒾","isin;":"∈","isinE;":"⋹","isindot;":"⋵","isins;":"⋴","isinsv;":"⋳","isinv;":"∈","it;":"⁢","itilde;":"ĩ","iukcy;":"і","iuml":"ï","iuml;":"ï","jcirc;":"ĵ","jcy;":"й","jfr;":"𝔧","jmath;":"ȷ","jopf;":"𝕛","jscr;":"𝒿","jsercy;":"ј","jukcy;":"є","kappa;":"κ","kappav;":"ϰ","kcedil;":"ķ","kcy;":"к","kfr;":"𝔨","kgreen;":"ĸ","khcy;":"х","kjcy;":"ќ","kopf;":"𝕜","kscr;":"𝓀","lAarr;":"⇚","lArr;":"⇐","lAtail;":"⤛","lBarr;":"⤎","lE;":"≦","lEg;":"⪋","lHar;":"⥢","lacute;":"ĺ","laemptyv;":"⦴","lagran;":"ℒ","lambda;":"λ","lang;":"⟨","langd;":"⦑","langle;":"⟨","lap;":"⪅","laquo":"«","laquo;":"«","larr;":"←","larrb;":"⇤","larrbfs;":"⤟","larrfs;":"⤝","larrhk;":"↩","larrlp;":"↫","larrpl;":"⤹","larrsim;":"⥳","larrtl;":"↢","lat;":"⪫","latail;":"⤙","late;":"⪭","lates;":"⪭︀","lbarr;":"⤌","lbbrk;":"❲","lbrace;":"{","lbrack;":"[","lbrke;":"⦋","lbrksld;":"⦏","lbrkslu;":"⦍","lcaron;":"ľ","lcedil;":"ļ","lceil;":"⌈","lcub;":"{","lcy;":"л","ldca;":"⤶","ldquo;":"“","ldquor;":"„","ldrdhar;":"⥧","ldrushar;":"⥋","ldsh;":"↲","le;":"≤","leftarrow;":"←","leftarrowtail;":"↢","leftharpoondown;":"↽","leftharpoonup;":"↼","leftleftarrows;":"⇇","leftrightarrow;":"↔","leftrightarrows;":"⇆","leftrightharpoons;":"⇋","leftrightsquigarrow;":"↭","leftthreetimes;":"⋋","leg;":"⋚","leq;":"≤","leqq;":"≦","leqslant;":"⩽","les;":"⩽","lescc;":"⪨","lesdot;":"⩿","lesdoto;":"⪁","lesdotor;":"⪃","lesg;":"⋚︀","lesges;":"⪓","lessapprox;":"⪅","lessdot;":"⋖","lesseqgtr;":"⋚","lesseqqgtr;":"⪋","lessgtr;":"≶","lesssim;":"≲","lfisht;":"⥼","lfloor;":"⌊","lfr;":"𝔩","lg;":"≶","lgE;":"⪑","lhard;":"↽","lharu;":"↼","lharul;":"⥪","lhblk;":"▄","ljcy;":"љ","ll;":"≪","llarr;":"⇇","llcorner;":"⌞","llhard;":"⥫","lltri;":"◺","lmidot;":"ŀ","lmoust;":"⎰","lmoustache;":"⎰","lnE;":"≨","lnap;":"⪉","lnapprox;":"⪉","lne;":"⪇","lneq;":"⪇","lneqq;":"≨","lnsim;":"⋦","loang;":"⟬","loarr;":"⇽","lobrk;":"⟦","longleftarrow;":"⟵","longleftrightarrow;":"⟷","longmapsto;":"⟼","longrightarrow;":"⟶","looparrowleft;":"↫","looparrowright;":"↬","lopar;":"⦅","lopf;":"𝕝","loplus;":"⨭","lotimes;":"⨴","lowast;":"∗","lowbar;":"_","loz;":"◊","lozenge;":"◊","lozf;":"⧫","lpar;":"(","lparlt;":"⦓","lrarr;":"⇆","lrcorner;":"⌟","lrhar;":"⇋","lrhard;":"⥭","lrm;":"‎","lrtri;":"⊿","lsaquo;":"‹","lscr;":"𝓁","lsh;":"↰","lsim;":"≲","lsime;":"⪍","lsimg;":"⪏","lsqb;":"[","lsquo;":"‘","lsquor;":"‚","lstrok;":"ł","lt":"<","lt;":"<","ltcc;":"⪦","ltcir;":"⩹","ltdot;":"⋖","lthree;":"⋋","ltimes;":"⋉","ltlarr;":"⥶","ltquest;":"⩻","ltrPar;":"⦖","ltri;":"◃","ltrie;":"⊴","ltrif;":"◂","lurdshar;":"⥊","luruhar;":"⥦","lvertneqq;":"≨︀","lvnE;":"≨︀","mDDot;":"∺","macr":"¯","macr;":"¯","male;":"♂","malt;":"✠","maltese;":"✠","map;":"↦","mapsto;":"↦","mapstodown;":"↧","mapstoleft;":"↤","mapstoup;":"↥","marker;":"▮","mcomma;":"⨩","mcy;":"м","mdash;":"—","measuredangle;":"∡","mfr;":"𝔪","mho;":"℧","micro":"µ","micro;":"µ","mid;":"∣","midast;":"*","midcir;":"⫰","middot":"·","middot;":"·","minus;":"−","minusb;":"⊟","minusd;":"∸","minusdu;":"⨪","mlcp;":"⫛","mldr;":"…","mnplus;":"∓","models;":"⊧","mopf;":"𝕞","mp;":"∓","mscr;":"𝓂","mstpos;":"∾","mu;":"μ","multimap;":"⊸","mumap;":"⊸","nGg;":"⋙̸","nGt;":"≫⃒","nGtv;":"≫̸","nLeftarrow;":"⇍","nLeftrightarrow;":"⇎","nLl;":"⋘̸","nLt;":"≪⃒","nLtv;":"≪̸","nRightarrow;":"⇏","nVDash;":"⊯","nVdash;":"⊮","nabla;":"∇","nacute;":"ń","nang;":"∠⃒","nap;":"≉","napE;":"⩰̸","napid;":"≋̸","napos;":"ʼn","napprox;":"≉","natur;":"♮","natural;":"♮","naturals;":"ℕ","nbsp":" ","nbsp;":" ","nbump;":"≎̸","nbumpe;":"≏̸","ncap;":"⩃","ncaron;":"ň","ncedil;":"ņ","ncong;":"≇","ncongdot;":"⩭̸","ncup;":"⩂","ncy;":"н","ndash;":"–","ne;":"≠","neArr;":"⇗","nearhk;":"⤤","nearr;":"↗","nearrow;":"↗","nedot;":"≐̸","nequiv;":"≢","nesear;":"⤨","nesim;":"≂̸","nexist;":"∄","nexists;":"∄","nfr;":"𝔫","ngE;":"≧̸","nge;":"≱","ngeq;":"≱","ngeqq;":"≧̸","ngeqslant;":"⩾̸","nges;":"⩾̸","ngsim;":"≵","ngt;":"≯","ngtr;":"≯","nhArr;":"⇎","nharr;":"↮","nhpar;":"⫲","ni;":"∋","nis;":"⋼","nisd;":"⋺","niv;":"∋","njcy;":"њ","nlArr;":"⇍","nlE;":"≦̸","nlarr;":"↚","nldr;":"‥","nle;":"≰","nleftarrow;":"↚","nleftrightarrow;":"↮","nleq;":"≰","nleqq;":"≦̸","nleqslant;":"⩽̸","nles;":"⩽̸","nless;":"≮","nlsim;":"≴","nlt;":"≮","nltri;":"⋪","nltrie;":"⋬","nmid;":"∤","nopf;":"𝕟","not":"¬","not;":"¬","notin;":"∉","notinE;":"⋹̸","notindot;":"⋵̸","notinva;":"∉","notinvb;":"⋷","notinvc;":"⋶","notni;":"∌","notniva;":"∌","notnivb;":"⋾","notnivc;":"⋽","npar;":"∦","nparallel;":"∦","nparsl;":"⫽⃥","npart;":"∂̸","npolint;":"⨔","npr;":"⊀","nprcue;":"⋠","npre;":"⪯̸","nprec;":"⊀","npreceq;":"⪯̸","nrArr;":"⇏","nrarr;":"↛","nrarrc;":"⤳̸","nrarrw;":"↝̸","nrightarrow;":"↛","nrtri;":"⋫","nrtrie;":"⋭","nsc;":"⊁","nsccue;":"⋡","nsce;":"⪰̸","nscr;":"𝓃","nshortmid;":"∤","nshortparallel;":"∦","nsim;":"≁","nsime;":"≄","nsimeq;":"≄","nsmid;":"∤","nspar;":"∦","nsqsube;":"⋢","nsqsupe;":"⋣","nsub;":"⊄","nsubE;":"⫅̸","nsube;":"⊈","nsubset;":"⊂⃒","nsubseteq;":"⊈","nsubseteqq;":"⫅̸","nsucc;":"⊁","nsucceq;":"⪰̸","nsup;":"⊅","nsupE;":"⫆̸","nsupe;":"⊉","nsupset;":"⊃⃒","nsupseteq;":"⊉","nsupseteqq;":"⫆̸","ntgl;":"≹","ntilde":"ñ","ntilde;":"ñ","ntlg;":"≸","ntriangleleft;":"⋪","ntrianglelefteq;":"⋬","ntriangleright;":"⋫","ntrianglerighteq;":"⋭","nu;":"ν","num;":"#","numero;":"№","numsp;":" ","nvDash;":"⊭","nvHarr;":"⤄","nvap;":"≍⃒","nvdash;":"⊬","nvge;":"≥⃒","nvgt;":">⃒","nvinfin;":"⧞","nvlArr;":"⤂","nvle;":"≤⃒","nvlt;":"<⃒","nvltrie;":"⊴⃒","nvrArr;":"⤃","nvrtrie;":"⊵⃒","nvsim;":"∼⃒","nwArr;":"⇖","nwarhk;":"⤣","nwarr;":"↖","nwarrow;":"↖","nwnear;":"⤧","oS;":"Ⓢ","oacute":"ó","oacute;":"ó","oast;":"⊛","ocir;":"⊚","ocirc":"ô","ocirc;":"ô","ocy;":"о","odash;":"⊝","odblac;":"ő","odiv;":"⨸","odot;":"⊙","odsold;":"⦼","oelig;":"œ","ofcir;":"⦿","ofr;":"𝔬","ogon;":"˛","ograve":"ò","ograve;":"ò","ogt;":"⧁","ohbar;":"⦵","ohm;":"Ω","oint;":"∮","olarr;":"↺","olcir;":"⦾","olcross;":"⦻","oline;":"‾","olt;":"⧀","omacr;":"ō","omega;":"ω","omicron;":"ο","omid;":"⦶","ominus;":"⊖","oopf;":"𝕠","opar;":"⦷","operp;":"⦹","oplus;":"⊕","or;":"∨","orarr;":"↻","ord;":"⩝","order;":"ℴ","orderof;":"ℴ","ordf":"ª","ordf;":"ª","ordm":"º","ordm;":"º","origof;":"⊶","oror;":"⩖","orslope;":"⩗","orv;":"⩛","oscr;":"ℴ","oslash":"ø","oslash;":"ø","osol;":"⊘","otilde":"õ","otilde;":"õ","otimes;":"⊗","otimesas;":"⨶","ouml":"ö","ouml;":"ö","ovbar;":"⌽","par;":"∥","para":"¶","para;":"¶","parallel;":"∥","parsim;":"⫳","parsl;":"⫽","part;":"∂","pcy;":"п","percnt;":"%","period;":".","permil;":"‰","perp;":"⊥","pertenk;":"‱","pfr;":"𝔭","phi;":"φ","phiv;":"ϕ","phmmat;":"ℳ","phone;":"☎","pi;":"π","pitchfork;":"⋔","piv;":"ϖ","planck;":"ℏ","planckh;":"ℎ","plankv;":"ℏ","plus;":"+","plusacir;":"⨣","plusb;":"⊞","pluscir;":"⨢","plusdo;":"∔","plusdu;":"⨥","pluse;":"⩲","plusmn":"±","plusmn;":"±","plussim;":"⨦","plustwo;":"⨧","pm;":"±","pointint;":"⨕","popf;":"𝕡","pound":"£","pound;":"£","pr;":"≺","prE;":"⪳","prap;":"⪷","prcue;":"≼","pre;":"⪯","prec;":"≺","precapprox;":"⪷","preccurlyeq;":"≼","preceq;":"⪯","precnapprox;":"⪹","precneqq;":"⪵","precnsim;":"⋨","precsim;":"≾","prime;":"′","primes;":"ℙ","prnE;":"⪵","prnap;":"⪹","prnsim;":"⋨","prod;":"∏","profalar;":"⌮","profline;":"⌒","profsurf;":"⌓","prop;":"∝","propto;":"∝","prsim;":"≾","prurel;":"⊰","pscr;":"𝓅","psi;":"ψ","puncsp;":" ","qfr;":"𝔮","qint;":"⨌","qopf;":"𝕢","qprime;":"⁗","qscr;":"𝓆","quaternions;":"ℍ","quatint;":"⨖","quest;":"?","questeq;":"≟","quot":"\"","quot;":"\"","rAarr;":"⇛","rArr;":"⇒","rAtail;":"⤜","rBarr;":"⤏","rHar;":"⥤","race;":"∽̱","racute;":"ŕ","radic;":"√","raemptyv;":"⦳","rang;":"⟩","rangd;":"⦒","range;":"⦥","rangle;":"⟩","raquo":"»","raquo;":"»","rarr;":"→","rarrap;":"⥵","rarrb;":"⇥","rarrbfs;":"⤠","rarrc;":"⤳","rarrfs;":"⤞","rarrhk;":"↪","rarrlp;":"↬","rarrpl;":"⥅","rarrsim;":"⥴","rarrtl;":"↣","rarrw;":"↝","ratail;":"⤚","ratio;":"∶","rationals;":"ℚ","rbarr;":"⤍","rbbrk;":"❳","rbrace;":"}","rbrack;":"]","rbrke;":"⦌","rbrksld;":"⦎","rbrkslu;":"⦐","rcaron;":"ř","rcedil;":"ŗ","rceil;":"⌉","rcub;":"}","rcy;":"р","rdca;":"⤷","rdldhar;":"⥩","rdquo;":"”","rdquor;":"”","rdsh;":"↳","real;":"ℜ","realine;":"ℛ","realpart;":"ℜ","reals;":"ℝ","rect;":"▭","reg":"®","reg;":"®","rfisht;":"⥽","rfloor;":"⌋","rfr;":"𝔯","rhard;":"⇁","rharu;":"⇀","rharul;":"⥬","rho;":"ρ","rhov;":"ϱ","rightarrow;":"→","rightarrowtail;":"↣","rightharpoondown;":"⇁","rightharpoonup;":"⇀","rightleftarrows;":"⇄","rightleftharpoons;":"⇌","rightrightarrows;":"⇉","rightsquigarrow;":"↝","rightthreetimes;":"⋌","ring;":"˚","risingdotseq;":"≓","rlarr;":"⇄","rlhar;":"⇌","rlm;":"‏","rmoust;":"⎱","rmoustache;":"⎱","rnmid;":"⫮","roang;":"⟭","roarr;":"⇾","robrk;":"⟧","ropar;":"⦆","ropf;":"𝕣","roplus;":"⨮","rotimes;":"⨵","rpar;":")","rpargt;":"⦔","rppolint;":"⨒","rrarr;":"⇉","rsaquo;":"›","rscr;":"𝓇","rsh;":"↱","rsqb;":"]","rsquo;":"’","rsquor;":"’","rthree;":"⋌","rtimes;":"⋊","rtri;":"▹","rtrie;":"⊵","rtrif;":"▸","rtriltri;":"⧎","ruluhar;":"⥨","rx;":"℞","sacute;":"ś","sbquo;":"‚","sc;":"≻","scE;":"⪴","scap;":"⪸","scaron;":"š","sccue;":"≽","sce;":"⪰","scedil;":"ş","scirc;":"ŝ","scnE;":"⪶","scnap;":"⪺","scnsim;":"⋩","scpolint;":"⨓","scsim;":"≿","scy;":"с","sdot;":"⋅","sdotb;":"⊡","sdote;":"⩦","seArr;":"⇘","searhk;":"⤥","searr;":"↘","searrow;":"↘","sect":"§","sect;":"§","semi;":";","seswar;":"⤩","setminus;":"∖","setmn;":"∖","sext;":"✶","sfr;":"𝔰","sfrown;":"⌢","sharp;":"♯","shchcy;":"щ","shcy;":"ш","shortmid;":"∣","shortparallel;":"∥","shy":"­","shy;":"­","sigma;":"σ","sigmaf;":"ς","sigmav;":"ς","sim;":"∼","simdot;":"⩪","sime;":"≃","simeq;":"≃","simg;":"⪞","simgE;":"⪠","siml;":"⪝","simlE;":"⪟","simne;":"≆","simplus;":"⨤","simrarr;":"⥲","slarr;":"←","smallsetminus;":"∖","smashp;":"⨳","smeparsl;":"⧤","smid;":"∣","smile;":"⌣","smt;":"⪪","smte;":"⪬","smtes;":"⪬︀","softcy;":"ь","sol;":"/","solb;":"⧄","solbar;":"⌿","sopf;":"𝕤","spades;":"♠","spadesuit;":"♠","spar;":"∥","sqcap;":"⊓","sqcaps;":"⊓︀","sqcup;":"⊔","sqcups;":"⊔︀","sqsub;":"⊏","sqsube;":"⊑","sqsubset;":"⊏","sqsubseteq;":"⊑","sqsup;":"⊐","sqsupe;":"⊒","sqsupset;":"⊐","sqsupseteq;":"⊒","squ;":"□","square;":"□","squarf;":"▪","squf;":"▪","srarr;":"→","sscr;":"𝓈","ssetmn;":"∖","ssmile;":"⌣","sstarf;":"⋆","star;":"☆","starf;":"★","straightepsilon;":"ϵ","straightphi;":"ϕ","strns;":"¯","sub;":"⊂","subE;":"⫅","subdot;":"⪽","sube;":"⊆","subedot;":"⫃","submult;":"⫁","subnE;":"⫋","subne;":"⊊","subplus;":"⪿","subrarr;":"⥹","subset;":"⊂","subseteq;":"⊆","subseteqq;":"⫅","subsetneq;":"⊊","subsetneqq;":"⫋","subsim;":"⫇","subsub;":"⫕","subsup;":"⫓","succ;":"≻","succapprox;":"⪸","succcurlyeq;":"≽","succeq;":"⪰","succnapprox;":"⪺","succneqq;":"⪶","succnsim;":"⋩","succsim;":"≿","sum;":"∑","sung;":"♪","sup1":"¹","sup1;":"¹","sup2":"²","sup2;":"²","sup3":"³","sup3;":"³","sup;":"⊃","supE;":"⫆","supdot;":"⪾","supdsub;":"⫘","supe;":"⊇","supedot;":"⫄","suphsol;":"⟉","suphsub;":"⫗","suplarr;":"⥻","supmult;":"⫂","supnE;":"⫌","supne;":"⊋","supplus;":"⫀","supset;":"⊃","supseteq;":"⊇","supseteqq;":"⫆","supsetneq;":"⊋","supsetneqq;":"⫌","supsim;":"⫈","supsub;":"⫔","supsup;":"⫖","swArr;":"⇙","swarhk;":"⤦","swarr;":"↙","swarrow;":"↙","swnwar;":"⤪","szlig":"ß","szlig;":"ß","target;":"⌖","tau;":"τ","tbrk;":"⎴","tcaron;":"ť","tcedil;":"ţ","tcy;":"т","tdot;":"⃛","telrec;":"⌕","tfr;":"𝔱","there4;":"∴","therefore;":"∴","theta;":"θ","thetasym;":"ϑ","thetav;":"ϑ","thickapprox;":"≈","thicksim;":"∼","thinsp;":" ","thkap;":"≈","thksim;":"∼","thorn":"þ","thorn;":"þ","tilde;":"˜","times":"×","times;":"×","timesb;":"⊠","timesbar;":"⨱","timesd;":"⨰","tint;":"∭","toea;":"⤨","top;":"⊤","topbot;":"⌶","topcir;":"⫱","topf;":"𝕥","topfork;":"⫚","tosa;":"⤩","tprime;":"‴","trade;":"™","triangle;":"▵","triangledown;":"▿","triangleleft;":"◃","trianglelefteq;":"⊴","triangleq;":"≜","triangleright;":"▹","trianglerighteq;":"⊵","tridot;":"◬","trie;":"≜","triminus;":"⨺","triplus;":"⨹","trisb;":"⧍","tritime;":"⨻","trpezium;":"⏢","tscr;":"𝓉","tscy;":"ц","tshcy;":"ћ","tstrok;":"ŧ","twixt;":"≬","twoheadleftarrow;":"↞","twoheadrightarrow;":"↠","uArr;":"⇑","uHar;":"⥣","uacute":"ú","uacute;":"ú","uarr;":"↑","ubrcy;":"ў","ubreve;":"ŭ","ucirc":"û","ucirc;":"û","ucy;":"у","udarr;":"⇅","udblac;":"ű","udhar;":"⥮","ufisht;":"⥾","ufr;":"𝔲","ugrave":"ù","ugrave;":"ù","uharl;":"↿","uharr;":"↾","uhblk;":"▀","ulcorn;":"⌜","ulcorner;":"⌜","ulcrop;":"⌏","ultri;":"◸","umacr;":"ū","uml":"¨","uml;":"¨","uogon;":"ų","uopf;":"𝕦","uparrow;":"↑","updownarrow;":"↕","upharpoonleft;":"↿","upharpoonright;":"↾","uplus;":"⊎","upsi;":"υ","upsih;":"ϒ","upsilon;":"υ","upuparrows;":"⇈","urcorn;":"⌝","urcorner;":"⌝","urcrop;":"⌎","uring;":"ů","urtri;":"◹","uscr;":"𝓊","utdot;":"⋰","utilde;":"ũ","utri;":"▵","utrif;":"▴","uuarr;":"⇈","uuml":"ü","uuml;":"ü","uwangle;":"⦧","vArr;":"⇕","vBar;":"⫨","vBarv;":"⫩","vDash;":"⊨","vangrt;":"⦜","varepsilon;":"ϵ","varkappa;":"ϰ","varnothing;":"∅","varphi;":"ϕ","varpi;":"ϖ","varpropto;":"∝","varr;":"↕","varrho;":"ϱ","varsigma;":"ς","varsubsetneq;":"⊊︀","varsubsetneqq;":"⫋︀","varsupsetneq;":"⊋︀","varsupsetneqq;":"⫌︀","vartheta;":"ϑ","vartriangleleft;":"⊲","vartriangleright;":"⊳","vcy;":"в","vdash;":"⊢","vee;":"∨","veebar;":"⊻","veeeq;":"≚","vellip;":"⋮","verbar;":"|","vert;":"|","vfr;":"𝔳","vltri;":"⊲","vnsub;":"⊂⃒","vnsup;":"⊃⃒","vopf;":"𝕧","vprop;":"∝","vrtri;":"⊳","vscr;":"𝓋","vsubnE;":"⫋︀","vsubne;":"⊊︀","vsupnE;":"⫌︀","vsupne;":"⊋︀","vzigzag;":"⦚","wcirc;":"ŵ","wedbar;":"⩟","wedge;":"∧","wedgeq;":"≙","weierp;":"℘","wfr;":"𝔴","wopf;":"𝕨","wp;":"℘","wr;":"≀","wreath;":"≀","wscr;":"𝓌","xcap;":"⋂","xcirc;":"◯","xcup;":"⋃","xdtri;":"▽","xfr;":"𝔵","xhArr;":"⟺","xharr;":"⟷","xi;":"ξ","xlArr;":"⟸","xlarr;":"⟵","xmap;":"⟼","xnis;":"⋻","xodot;":"⨀","xopf;":"𝕩","xoplus;":"⨁","xotime;":"⨂","xrArr;":"⟹","xrarr;":"⟶","xscr;":"𝓍","xsqcup;":"⨆","xuplus;":"⨄","xutri;":"△","xvee;":"⋁","xwedge;":"⋀","yacute":"ý","yacute;":"ý","yacy;":"я","ycirc;":"ŷ","ycy;":"ы","yen":"¥","yen;":"¥","yfr;":"𝔶","yicy;":"ї","yopf;":"𝕪","yscr;":"𝓎","yucy;":"ю","yuml":"ÿ","yuml;":"ÿ","zacute;":"ź","zcaron;":"ž","zcy;":"з","zdot;":"ż","zeetrf;":"ℨ","zeta;":"ζ","zfr;":"𝔷","zhcy;":"ж","zigrarr;":"⇝","zopf;":"𝕫","zscr;":"𝓏","zwj;":"‍","zwnj;":"‌"})));
@@ -289,6 +300,12 @@ const CC_GREATER_THAN = 0x3e;
289
300
  const CC_QUESTION_MARK = 0x3f;
290
301
  const CC_LEFT_SQUARE_BRACKET = 0x5b;
291
302
  const CC_RIGHT_SQUARE_BRACKET = 0x5d;
303
+ const CC_LEFT_PARENTHESIS = 0x28;
304
+ const CC_RIGHT_PARENTHESIS = 0x29;
305
+ const CC_ASTERISK = 0x2a;
306
+ const CC_REVERSE_SOLIDUS = 0x5c;
307
+ const CC_LEFT_CURLY_BRACKET = 0x7b;
308
+ const CC_RIGHT_CURLY_BRACKET = 0x7d;
292
309
  const CC_LOW_LINE = 0x5f;
293
310
  const CC_GRAVE_ACCENT = 0x60;
294
311
  const CC_NO_BREAK_SPACE = 0xa0;
@@ -4912,6 +4929,10 @@ let _attrCount = 0;
4912
4929
  // (§13.2.6.4.4, §13.2.6.4.7). The merged names are not in the element's source
4913
4930
  // open tag, so the printer rebuilds that tag instead of echoing it.
4914
4931
  const _mergedAttrNodes = new Set();
4932
+ // Attribute runs whose start tag dropped a duplicate name and spells one no
4933
+ // HTML vocabulary does: the printer hands those back whole (see `_isWordSpan`).
4934
+ /** @type {Set<number>} */
4935
+ const _foreignSyntaxAttrRuns = new Set();
4915
4936
  // A processing instruction's target; its data rides in `_nodeStrings` like a
4916
4937
  // comment's. A map, since a second string column per node would cost more.
4917
4938
  /** @type {Map<HtmlNodeRef, string>} */
@@ -4983,6 +5004,32 @@ const _allocAttr = (name, value, nameStart, nameEnd, valueStart, valueEnd) => {
4983
5004
  return i;
4984
5005
  };
4985
5006
 
5007
+ /**
5008
+ * Whether a span reads as HTML vocabulary rather than as another language's
5009
+ * text: an attribute name or list token starts with an ASCII letter, `_` or
5010
+ * `-`, and no delimiter a template engine wraps a statement in appears in it.
5011
+ * @param {string} text the string holding the span
5012
+ * @param {number} start first index
5013
+ * @param {number} end index after the last
5014
+ * @returns {boolean} true when the span is a word
5015
+ */
5016
+ const _isWordSpan = (text, start, end) => {
5017
+ const first = text.charCodeAt(start);
5018
+ if (
5019
+ !(first >= 0x61 && first <= 0x7a) &&
5020
+ !(first >= 0x41 && first <= 0x5a) &&
5021
+ first !== 0x5f &&
5022
+ first !== 0x2d
5023
+ ) {
5024
+ return false;
5025
+ }
5026
+ for (let i = start + 1; i < end; i++) {
5027
+ const c = text.charCodeAt(i);
5028
+ if (c === 0x7b || c === 0x7d || c === 0x3c || c === 0x3e) return false;
5029
+ }
5030
+ return true;
5031
+ };
5032
+
4986
5033
  /** @type {(i: number) => string} */
4987
5034
  const _attrValueOf = (i) => {
4988
5035
  const v = _attrValues[i];
@@ -5106,6 +5153,7 @@ const _resetAstColumns = () => {
5106
5153
  _nodeHighWater = 0;
5107
5154
  _attrCount = 0;
5108
5155
  _mergedAttrNodes.clear();
5156
+ _foreignSyntaxAttrRuns.clear();
5109
5157
  _piTargets.clear();
5110
5158
  _doctypePublicId = null;
5111
5159
  _doctypeSystemId = null;
@@ -5150,6 +5198,7 @@ const _releaseAstColumns = () => {
5150
5198
  _nodeHighWater = 0;
5151
5199
  _attrCount = 0;
5152
5200
  _mergedAttrNodes.clear();
5201
+ _foreignSyntaxAttrRuns.clear();
5153
5202
  _piTargets.clear();
5154
5203
  _htmlSource = "";
5155
5204
  _doctypePublicId = null;
@@ -5945,6 +5994,9 @@ let head = 0;
5945
5994
  let form = 0;
5946
5995
  let framesetOk = true;
5947
5996
  let pendAttrStart = 0;
5997
+ // Whether §13.2.5.33 dropped a repeated name from the tag being read; a tag
5998
+ // that dropped none needs no word test, keeping it off the per-attribute path.
5999
+ let pendAttrDropped = false;
5948
6000
  let fosterParenting = false;
5949
6001
  /** @type {number[]} */
5950
6002
  const templateModes = [];
@@ -7383,6 +7435,9 @@ const startTagInBody = (t) => {
7383
7435
  isSpecial(node) &&
7384
7436
  !(_namespaceOf(node) === NS_HTML && ADDRESS_DIV_P.has(_tagNameOf(node)))
7385
7437
  ) {
7438
+ // A list-item-scope boundary (`ul`, `ol`, a table cell) keeps every item
7439
+ // below it out of reach of any `</li>`, whatever the print writes or drops.
7440
+ if (isBoundaryForKind(node, SCOPE_LIST_ITEM)) break;
7386
7441
  // Inlined rather than a call: this runs for every `<li>` in a list.
7387
7442
  for (let j = i - 1; j >= 0 && !_printFromSource; j--) {
7388
7443
  const below = open[j];
@@ -8516,7 +8571,10 @@ const handleAttributeToken = (
8516
8571
  quoteType
8517
8572
  ) => {
8518
8573
  const name = internLowerName(ATTR_NAME_INTERN, input, nameStart, nameEnd);
8519
- if (pendAttrStart === 0) pendAttrStart = _attrCount + 1;
8574
+ if (pendAttrStart === 0) {
8575
+ pendAttrStart = _attrCount + 1;
8576
+ pendAttrDropped = false;
8577
+ }
8520
8578
  // Drop duplicate attribute names (per spec). Plain loop avoids a
8521
8579
  // per-attribute closure allocation on this hot path.
8522
8580
  let dup = false;
@@ -8526,6 +8584,7 @@ const handleAttributeToken = (
8526
8584
  break;
8527
8585
  }
8528
8586
  }
8587
+ if (dup) pendAttrDropped = true;
8529
8588
  if (!dup) {
8530
8589
  // The raw (undecoded) value is read from the source by offset on
8531
8590
  // demand: consumers re-resolve requests from it and the offsets must
@@ -8560,6 +8619,7 @@ const handleStartTagToken = (
8560
8619
  if (eofInTag) {
8561
8620
  // Any attribute slots already allocated for it are orphaned.
8562
8621
  pendAttrStart = 0;
8622
+ pendAttrDropped = false;
8563
8623
  return end;
8564
8624
  }
8565
8625
  const name = internLowerName(TAG_NAME_INTERN, input, nameStart, nameEnd);
@@ -8570,7 +8630,18 @@ const handleStartTagToken = (
8570
8630
  // `t.attrs` runs synchronously within this dispatch.
8571
8631
  tok.attrs.start = pendAttrStart;
8572
8632
  tok.attrs.count = pendAttrStart === 0 ? 0 : _attrCount + 1 - pendAttrStart;
8633
+ // Only a name the run kept is tested: a dropped one repeats one of them.
8634
+ if (pendAttrDropped) {
8635
+ for (let i = pendAttrStart; i <= _attrCount; i++) {
8636
+ const attributeName = _attrNames[i];
8637
+ if (!_isWordSpan(attributeName, 0, attributeName.length)) {
8638
+ _foreignSyntaxAttrRuns.add(pendAttrStart);
8639
+ break;
8640
+ }
8641
+ }
8642
+ }
8573
8643
  pendAttrStart = 0;
8644
+ pendAttrDropped = false;
8574
8645
  tok.selfClosing = selfClosing;
8575
8646
  tok.swallowNewline = false;
8576
8647
  tok.pos.start = start;
@@ -8600,6 +8671,7 @@ const handleEndTagToken = (input, start, end, nameStart, nameEnd) => {
8600
8671
  }
8601
8672
  // End tags drop any parsed attributes (the slots are orphaned).
8602
8673
  pendAttrStart = 0;
8674
+ pendAttrDropped = false;
8603
8675
  tok.type = TOKEN_END_TAG;
8604
8676
  tok.name = name;
8605
8677
  tok.pos.start = start;
@@ -8685,6 +8757,7 @@ const parseHtml = (input, pos = 0, options = {}) => {
8685
8757
  form = 0;
8686
8758
  framesetOk = true;
8687
8759
  pendAttrStart = 0;
8760
+ pendAttrDropped = false;
8688
8761
  fosterParenting = false;
8689
8762
  _fosteredLog = null;
8690
8763
  _printFromSource = false;
@@ -8913,14 +8986,13 @@ const mirrorSelectedContent = (node, select) => {
8913
8986
  * What the minifying printer may rewrite. Every entry is on unless it is
8914
8987
  * `false`, so a document one transform breaks can still be minified by the rest.
8915
8988
  * @typedef {object} HtmlTransformOptions
8916
- * @property {boolean=} collapseBooleanAttributes write a boolean attribute spelled with its own name (`disabled="disabled"`) as the bare name
8989
+ * @property {(boolean | "all")=} collapseBooleanAttributes write a boolean attribute as the bare name its presence already means; `true` only the spellings the spec canonicalizes, `"all"` any value
8917
8990
  * @property {(boolean | "all" | "some" | string | RegExp | ((comment: string) => boolean))=} comments which comments survive: `"some"` (the default) the ones that carry something, `true` / `"all"` every one, `false` none, or the ones a pattern matches / a predicate accepts, over the comment's own text. A comment a parser or a server reads is kept whatever this says
8918
- * @property {boolean=} minifyJson strip the whitespace between a JSON `<script>`'s tokens
8919
- * @property {boolean=} minifyStyles run the CSS minifier over an inline `<style>` and every `style=""`
8920
8991
  * @property {boolean=} normalizeAttributeQuotes drop or re-pick an attribute value's quotes
8921
8992
  * @property {boolean=} normalizeEnumeratedAttributes fold an enumerated value to the keyword it names
8922
8993
  * @property {boolean=} normalizeListAttributes normalize a space-, comma- or descriptor-separated list value (`class`, `rel`, `srcset`, `sizes`, the viewport `content`)
8923
8994
  * @property {boolean=} normalizeNumericAttributes write an integer attribute the one way its rules read it
8995
+ * @property {boolean=} normalizeUrlAttributes drop the whitespace around a URL value (`href`, `src`, `action`, …), which resolving the URL skips over
8924
8996
  * @property {boolean=} removeOptionalTags leave out an optional tag other than the `<html>` / `<head>` / `<body>` shell, which is `removeImpliedTags`
8925
8997
  */
8926
8998
 
@@ -8929,31 +9001,27 @@ const mirrorSelectedContent = (node, select) => {
8929
9001
  * @property {string=} fragmentContext context element tag name for fragment parsing (see `parseHtml`); the HTML analog of the CSS parser's `as` parse-mode option
8930
9002
  * @property {HtmlAstSkip=} skip node kinds to omit from the AST for speed/memory (see `HtmlAstSkip`)
8931
9003
  * @property {boolean=} minimize print the safely-minified serialization (nodes rebuilt from source, inert comments dropped, opening-tag whitespace collapsed) as `process` walks, and return it (default false = walk only, return `""`)
8932
- * @property {CssEnvironment=} environment CSS's, not HTML's: handed to the CSS minifier that runs over an inline `<style>` and every `style=""`, so the inline copy of a declaration agrees with the `.css` asset
8933
- * @property {boolean=} convertLengthUnits CSS's too, handed over with `environment` (see `HtmlPrintOptions`)
8934
- * @property {boolean=} rewriteCustomProperties CSS's too, handed over with `environment` (see `HtmlPrintOptions`)
8935
- * @property {CssTransformOptions=} cssTransforms CSS's per-transform switches too, handed over with `environment` (see `HtmlPrintOptions`)
8936
9004
  * @property {HtmlTransformOptions=} transforms which of the meaning-preserving rewrites the minifying print makes; each is on unless it is `false`
8937
9005
  * @property {(boolean | "conservative" | "smart" | "all")=} collapseWhitespace collapse each run of whitespace in text to a single space, except where an ancestor renders it verbatim; `"smart"` also drops what sits against a block edge and `"all"` drops every edge (default false)
8938
9006
  * @property {boolean=} removeEmptyAttributes drop an attribute whose empty value leaves it in the state its absence gives (default false)
8939
9007
  * @property {boolean=} removeEmptyElements drop an element with no children and no attributes, unless its bare form is meaningful (default false)
8940
9008
  * @property {boolean=} mergeStyles print a run of adjacent `<style>` elements as one sheet, which removes elements (default false)
9009
+ * @property {boolean=} mergeScripts print a run of adjacent bare `<script>` elements whose bodies this print writes itself as one, which removes elements, hoists a later body's declarations into the ones before it, and lets a failing body end the whole run (default false)
8941
9010
  * @property {boolean=} sortAttributes print an element's attributes commonest name first, ties by name, which nothing in HTML reads (default false)
8942
9011
  * @property {boolean=} sortTokenLists print every token list the DOM reads as a set (`class`, `rel`, `part`, …) in token order (default false)
8943
9012
  * @property {(boolean | "smart" | "all")=} removeRedundantAttributes drop an attribute whose value is the element's own default; `true` is `"smart"`, and `"all"` also drops the spec defaults a selector can match (default false)
8944
9013
  * @property {(boolean | "smart" | "all")=} removeImpliedTags how much of the `<html>` / `<head>` / `<body>` shell §13.1.2.4 lets the parser imply may be left out: `"smart"` leaves out only the `<html>` start tag, `true` (or `"all"`) all six, `false` none (default `"smart"`)
8945
9014
  * @property {boolean=} deferSrcdoc whether an `<iframe srcdoc>` is among what `deferEmbeddedSource` collects (default true); false for a caller that minifies them itself, which keeps the attribute on the normal path and its shorter delimiter
8946
- * @property {DeferredEmbeddedSource[]=} deferEmbeddedSource collects what `renderEmbeddedSource` would be offered instead of offering it, for a caller whose renderer is asynchronous: the print leaves a marker for each and `finish` puts the answers in their place, so one parse serves both. A `style=""` stays with the built-in CSS minifier, whose text this print reads back to decide how the attribute is written. Takes precedence over `renderEmbeddedSource`
8947
- * @property {EmbeddedSourceRenderer=} renderEmbeddedSource renders each nested body this document embeds — an inline `<style>`, every `style=""` (handed over as a whole stylesheet, SVG's and MathML's included), a `<script>` holding JSON or JavaScript, an `<svg>` subtree, and the document an `<iframe srcdoc>` holds (decoded, and written back escaped). Replaces the built-in CSS and JSON minifiers wherever it answers, and returning anything but text falls back to them; it is the only way inline JavaScript, SVG and a nested document are reached at all
9015
+ * @property {DeferredEmbeddedSource[]=} deferEmbeddedSource collects what `renderEmbeddedSource` would be offered instead of offering it, for a caller whose renderer is asynchronous: the print leaves a marker for each and `finish` puts the answers in their place, so one parse serves both. Takes precedence over `renderEmbeddedSource`
9016
+ * @property {EmbeddedSourceRenderer=} renderEmbeddedSource renders each nested body this document embeds — an inline `<style>`, every `style=""` (as the block's contents it is, SVG's and MathML's included), a `<script>` holding JSON or JavaScript (with `as` naming which production of it the body is — `"module"` for a `<script type=module>`, `"script"` for a classic one), every event handler attribute, with `as: "event-handler"` saying it is a function body rather than a script — the production a `return` at its top level is in, which a renderer whose engine takes only whole scripts wraps before it reads — an `<svg>` subtree, and the document an `<iframe srcdoc>` holds (decoded, and written back escaped). The only way any of them is minified: webpack minifies nothing here itself, and `builtinEmbeddedRenderer` is its own CSS and JSON minifiers for a caller to pass; returning anything but text leaves a body as written
8948
9017
  */
8949
9018
 
8950
9019
  /**
8951
- * What the HTML printer may be told, on top of the `mode` every language has.
8952
- * The first two are not HTML's own: an inline `<style>` and every `style=""` run
8953
- * through the CSS minifier, so `optimization.minimize.css` rides along to reach
8954
- * it (see `lib/config/defaults.js`) and the two must not disagree about what the
8955
- * target can read. The rest is `optimization.minimize.html`.
8956
- * @typedef {Pick<CssProcessOptions, "environment" | "convertLengthUnits" | "rewriteCustomProperties"> & { cssTransforms?: CssTransformOptions, transforms?: HtmlTransformOptions, collapseWhitespace?: boolean | "conservative" | "smart" | "all", mergeStyles?: boolean, removeEmptyAttributes?: boolean, removeEmptyElements?: boolean, removeRedundantAttributes?: boolean | "smart" | "all", sortAttributes?: boolean, sortTokenLists?: boolean, removeImpliedTags?: boolean | "smart" | "all", renderEmbeddedSource?: EmbeddedSourceRenderer, deferEmbeddedSource?: DeferredEmbeddedSource[], deferSrcdoc?: boolean }} HtmlPrintOptions
9020
+ * What the HTML printer may be told, on top of the `mode` every language has:
9021
+ * `optimization.minimize.html`, and the renderer every nested body goes through.
9022
+ * `optimization.minimize.css` reaches inline CSS through `builtinEmbeddedRenderer`,
9023
+ * which `htmlMinify` passes (see `lib/config/defaults.js`).
9024
+ * @typedef {{ transforms?: HtmlTransformOptions, collapseWhitespace?: boolean | "conservative" | "smart" | "all", mergeStyles?: boolean, mergeScripts?: boolean, removeEmptyAttributes?: boolean, removeEmptyElements?: boolean, removeRedundantAttributes?: boolean | "smart" | "all", sortAttributes?: boolean, sortTokenLists?: boolean, removeImpliedTags?: boolean | "smart" | "all", renderEmbeddedSource?: EmbeddedSourceRenderer, deferEmbeddedSource?: DeferredEmbeddedSource[], deferSrcdoc?: boolean }} HtmlPrintOptions
8957
9025
  */
8958
9026
 
8959
9027
  /** @typedef {import("../util/SourceProcessor").PrintContext<HtmlPath, HtmlNodeRef, HtmlPrintOptions>} PrintContext */
@@ -8976,6 +9044,18 @@ const _hasOpenReference = (s) => {
8976
9044
  return true;
8977
9045
  };
8978
9046
 
9047
+ /**
9048
+ * Whether the tag printed after this text would fuse with its tail: a `<` runs
9049
+ * into the next tag's name, and a `</` meets that tag's `<` as a bogus comment,
9050
+ * which consumes to the next `>` and takes the text with it.
9051
+ * @param {string} s source text
9052
+ * @returns {boolean} true when the text cannot be emitted as written
9053
+ */
9054
+ const _tailFusesWithNextTag = (s) => {
9055
+ const tail = s.charCodeAt(s.length - 1);
9056
+ return tail === 60 || (tail === 47 && s.charCodeAt(s.length - 2) === 60);
9057
+ };
9058
+
8979
9059
  /**
8980
9060
  * Whether the `&` at `i` would be consumed as a character reference when the
8981
9061
  * text is read back (§13.2.5.72): only before `#` or a name the table holds.
@@ -9070,16 +9150,36 @@ const _escapeTextContent = (s, minify) => {
9070
9150
  * @returns {string} serialized opening tag
9071
9151
  */
9072
9152
  const _synthesizeOpenTag = (path) => {
9073
- let out = `<${path.tagName()}`;
9153
+ const tagName = path.tagName();
9154
+ let out = `<${tagName}`;
9155
+ // Looked up once for the tag, as the attribute loop does for a written one.
9156
+ const enumeratedOn =
9157
+ _minifying && path.namespace(path.node) === NS_HTML
9158
+ ? ENUMERATED_KEYWORDS[tagName]
9159
+ : undefined;
9074
9160
  for (const attribute of path.attributes()) {
9075
9161
  const name =
9076
9162
  attribute.serializedName !== undefined
9077
9163
  ? attribute.serializedName
9078
9164
  : attribute.name;
9079
- out +=
9080
- attribute.value === ""
9081
- ? ` ${name}`
9082
- : ` ${name}="${attribute.value.replace(/"/g, "&quot;")}"`;
9165
+ if (attribute.value === "") {
9166
+ out += ` ${name}`;
9167
+ continue;
9168
+ }
9169
+ // Nothing was written here for this tag, so there is no source spelling to
9170
+ // beat: the shortest one wins outright.
9171
+ if (!_minifying || !_transforms.normalizeAttributeQuotes) {
9172
+ out += ` ${name}="${attribute.value.replace(/"/g, "&quot;")}"`;
9173
+ continue;
9174
+ }
9175
+ const value = _rewriteAttributeValue(
9176
+ tagName,
9177
+ name,
9178
+ attribute.value,
9179
+ false,
9180
+ enumeratedOn
9181
+ );
9182
+ out += ` ${name}=${_minimalAttributeValue(decodeEntities(value, true))}`;
9083
9183
  }
9084
9184
  return `${out}>`;
9085
9185
  };
@@ -9384,36 +9484,17 @@ const _canOmitColgroupStart = (path, node) => {
9384
9484
  return !_canOmitEndTag(path, "colgroup", previous);
9385
9485
  };
9386
9486
 
9387
- // The CSS abilities of the target, forwarded into the nested CSS minifier so an
9388
- // inline `<style>` or `style=""` is gated exactly like a `.css` asset. Set per
9389
- // print, since the printer is the only place the options are in scope.
9390
- /** @type {CssEnvironment | undefined} */
9391
- let _cssEnvironment;
9392
-
9393
- // Whether the nested CSS minifier may rewrite a length's unit — forwarded like
9394
- // `_cssEnvironment` so inline CSS agrees with the `.css` assets.
9395
- let _cssConvertLengthUnits = false;
9396
-
9397
- // And whether it may shorten a custom property's value, forwarded the same way.
9398
- let _cssRewriteCustomProperties = false;
9399
-
9400
- // And which of its rewrites it makes at all, forwarded the same way — inline CSS
9401
- // is minified by the same switches a `.css` asset is.
9402
- /** @type {CssTransformOptions | undefined} */
9403
- let _cssTransforms;
9404
-
9405
9487
  // Every rewrite on, which is what a print with no `transforms` option makes and
9406
9488
  // what the walk-only passes hold. Frozen, since it is shared rather than copied.
9407
9489
  /** @type {Required<HtmlTransformOptions>} */
9408
9490
  const _ALL_TRANSFORMS = Object.freeze({
9409
9491
  collapseBooleanAttributes: true,
9410
9492
  comments: "some",
9411
- minifyJson: true,
9412
- minifyStyles: true,
9413
9493
  normalizeAttributeQuotes: true,
9414
9494
  normalizeEnumeratedAttributes: true,
9415
9495
  normalizeListAttributes: true,
9416
9496
  normalizeNumericAttributes: true,
9497
+ normalizeUrlAttributes: true,
9417
9498
  removeOptionalTags: true
9418
9499
  });
9419
9500
 
@@ -9494,13 +9575,8 @@ const pickTransforms = (options) => {
9494
9575
  return out;
9495
9576
  };
9496
9577
 
9497
- // Minified `style` attributes by raw text — a pure function of the value and
9498
- // the options above, which a document repeats far more often than it adds one.
9499
- /** @type {Map<string, string>} */
9500
- const _styleAttributeCache = new Map();
9501
-
9502
9578
  // How far text whitespace may be collapsed (see `HtmlProcessOptions`) — set per
9503
- // print, like `_cssEnvironment`. "none" is off; the rest name how much of the
9579
+ // print, like `_minifying`. "none" is off; the rest name how much of the
9504
9580
  // whitespace against a boundary no line box reaches goes with it.
9505
9581
  /** @type {"none" | "conservative" | "smart" | "all"} */
9506
9582
  let _collapseWhitespace = "none";
@@ -9509,38 +9585,53 @@ let _collapseWhitespace = "none";
9509
9585
  // have to predict what it will drop.
9510
9586
  let _minifying = false;
9511
9587
 
9512
- // The caller's renderer for source nested in this document, set per print. It
9513
- // replaces the built-in CSS/JSON minifiers and is the only way inline
9514
- // JavaScript and SVG are reached — webpack ships no minifier for either.
9588
+ // The caller's renderer for source nested in this document, set per print: the
9589
+ // only way any of it is minified, `builtinEmbeddedRenderer` being webpack's own.
9515
9590
  /** @type {EmbeddedSourceRenderer | undefined} */
9516
9591
  let _renderEmbeddedSource;
9517
9592
 
9518
9593
  // Where an asynchronous caller's embedded sources are recorded instead of
9519
- // rendered, set per print. A body whose text this print reads back to decide
9520
- // what to emit is still minified by the built-in for that decision — only the
9521
- // text that reaches the output is deferred.
9594
+ // rendered, set per print; what the print decides from a body reads its source.
9522
9595
  /** @type {DeferredEmbeddedSource[] | undefined} */
9523
9596
  let _deferEmbeddedSource;
9524
9597
 
9525
9598
  // Whether an `<iframe srcdoc>` is among what is deferred. A caller minifying
9526
9599
  // them itself keeps the attribute on the normal path, which re-quotes it to
9527
9600
  // whichever delimiter its content makes shorter.
9601
+ /**
9602
+ * One attribute, written with whichever delimiter its value needs fewer escapes
9603
+ * inside — a minified document is mostly `"`, so one holding a `"` is shorter
9604
+ * quoted with `'`. Where neither costs anything the source's own is kept.
9605
+ * @param {string} name the attribute name
9606
+ * @param {string} value the value to write
9607
+ * @param {string} source the delimiter the source spelled it with, if any
9608
+ * @returns {string} the attribute, delimiter and all
9609
+ */
9610
+ const _writeQuotedAttribute = (name, value, source) => {
9611
+ const double = value.includes('"');
9612
+ const single = value.includes("'");
9613
+ const quote =
9614
+ double !== single ? (double ? 39 : 34) : source === "'" ? 39 : 34;
9615
+ const delimiter = String.fromCharCode(quote);
9616
+
9617
+ return ` ${name}=${delimiter}${escapeAttribute(value, quote, true)}${delimiter}`;
9618
+ };
9619
+
9528
9620
  let _deferSrcdoc = true;
9529
9621
 
9530
9622
  /**
9531
- * Hand one nested body to the caller's renderer, which must be present.
9532
- * Anything it throws is a renderer that did not answer: a document must not
9533
- * fail to serialize because something inside it did not parse.
9623
+ * Hand one nested body to the caller's renderer. Anything it throws is a
9624
+ * renderer that did not answer: a document must not fail to serialize because
9625
+ * something inside it did not parse.
9534
9626
  * @param {string} source the nested body
9535
9627
  * @param {string} type its language, e.g. `"css"` / `"javascript"` / `"svg"`
9536
9628
  * @param {string=} as which production of that language it is, for one with more than one
9537
- * @returns {string | null} the rendered body, or null when it declined
9629
+ * @returns {string | null} the rendered body, or null when there is no renderer or it declined
9538
9630
  */
9539
9631
  const _renderEmbeddedOrNull = (source, type, as) => {
9632
+ if (_renderEmbeddedSource === undefined) return null;
9540
9633
  try {
9541
- const rendered = /** @type {EmbeddedSourceRenderer} */ (
9542
- _renderEmbeddedSource
9543
- )(source, {
9634
+ const rendered = _renderEmbeddedSource(source, {
9544
9635
  type,
9545
9636
  hostType: HTML_TYPE,
9546
9637
  ...(as === undefined ? undefined : { as })
@@ -9578,19 +9669,23 @@ const _deferEmbedded = (source, type, build, as) => {
9578
9669
  };
9579
9670
 
9580
9671
  /**
9581
- * `_renderEmbeddedOrNull` for a body webpack has no minifier of its own for, so
9582
- * a renderer that declines leaves it exactly as written.
9672
+ * `_renderEmbeddedOrNull` with the body left exactly as written where the
9673
+ * renderer declines it, deferred to the caller's where one collects.
9583
9674
  * @param {string} source the nested body
9584
9675
  * @param {string} type its language, e.g. `"css"` / `"javascript"` / `"svg"`
9676
+ * @param {string=} as which production of that language it is, for one with more than one
9585
9677
  * @returns {string} the rendered body, or the original
9586
9678
  */
9587
- const _renderEmbedded = (source, type) => {
9679
+ const _renderEmbedded = (source, type, as) => {
9588
9680
  if (_deferEmbeddedSource !== undefined) {
9589
- return _deferEmbedded(source, type, (rendered) =>
9590
- typeof rendered === "string" ? rendered : source
9681
+ return _deferEmbedded(
9682
+ source,
9683
+ type,
9684
+ (rendered) => (typeof rendered === "string" ? rendered : source),
9685
+ as
9591
9686
  );
9592
9687
  }
9593
- const rendered = _renderEmbeddedOrNull(source, type);
9688
+ const rendered = _renderEmbeddedOrNull(source, type, as);
9594
9689
  return rendered === null ? source : rendered;
9595
9690
  };
9596
9691
 
@@ -9644,11 +9739,13 @@ let _sortTokenLists = false;
9644
9739
  // `document.styleSheets` and a `:nth-child` selector read.
9645
9740
  let _mergeStyles = false;
9646
9741
 
9647
- // A run of adjacent `<style>` elements prints as one, so the elements after the
9648
- // first print nothing at all. Filled by the first one's text as it prints, which
9649
- // is before any of theirs does; null until a document actually has a run.
9742
+ // Print a run of adjacent bare `<script>` elements as one.
9743
+ let _mergeScripts = false;
9744
+
9745
+ // A run of adjacent `<style>` or `<script>` prints as one, so the elements
9746
+ // after the first print nothing; null until a document has a run.
9650
9747
  /** @type {Set<HtmlElement> | null} */
9651
- let _absorbedStyles = null;
9748
+ let _absorbed = null;
9652
9749
 
9653
9750
  // Foster parenting puts a node before the table it was written inside, so tree
9654
9751
  // order and source order disagree there. Recorded where it happens.
@@ -9794,79 +9891,14 @@ const _canOmitStartTag = (path, name, node, open) => {
9794
9891
  };
9795
9892
 
9796
9893
  /**
9797
- * Minify a `<style>` body with webpack's own CSS minifier — the one that runs on
9798
- * CSS assets, so an inline sheet is held to the same rules. `null` when it
9799
- * declines the text, which a caller joining two sheets has to tell apart from a
9800
- * sheet that was already minimal: text the minifier cannot parse may be
9801
- * unterminated, and then it swallows whatever is concatenated after it.
9802
- * @param {string} css the element's text
9803
- * @param {{ text: string }=} decided filled with the text this print may read back, which is the built-in's rather than the marker when the caller's renderer is deferred
9804
- * @returns {string | null} the minified text, or null
9805
- */
9806
- const _minifyStyleBody = (css, decided) => {
9807
- if (!_transforms.minifyStyles) return null;
9808
- if (css.trim() === "") return css;
9809
- try {
9810
- if (_deferEmbeddedSource !== undefined) {
9811
- // The built-in still runs: what this print does next is decided by
9812
- // reading the minified text back (whether a run merges), and a marker
9813
- // cannot be read. Only the text that reaches the output is the caller's,
9814
- // and `decided` carries the readable text to whoever needs it.
9815
- const builtin = _builtinStyleBody(css);
9816
- if (builtin === null) return null;
9817
- if (decided !== undefined) decided.text = builtin;
9818
- return _deferEmbedded(css, CSS_TYPE, (rendered) =>
9819
- typeof rendered === "string" ? rendered : builtin
9820
- );
9821
- }
9822
- if (_renderEmbeddedSource !== undefined) {
9823
- // Declining falls back to the built-in, so a renderer that covers some
9824
- // languages does not turn the ones it does not cover off.
9825
- const rendered = _renderEmbeddedOrNull(css, CSS_TYPE);
9826
- if (rendered !== null) return rendered;
9827
- }
9828
- return _builtinStyleBody(css);
9829
- } catch (_err) {
9830
- return null;
9831
- }
9832
- };
9833
-
9834
- /**
9835
- * The CSS minify webpack ships, for a body no caller's renderer answered for.
9836
- * @param {string} css the element's text
9837
- * @param {("stylesheet" | "block-contents")=} as which production it is — a `style=""` holds a block's contents, an element a stylesheet
9838
- * @returns {string | null} the minified text, or null
9839
- */
9840
- const _builtinStyleBody = (css, as) => {
9841
- try {
9842
- const cssSyntax = _cssSyntax || (_cssSyntax = require("../css/syntax"));
9843
- const options = {
9844
- environment: _cssEnvironment,
9845
- convertLengthUnits: _cssConvertLengthUnits,
9846
- rewriteCustomProperties: _cssRewriteCustomProperties,
9847
- transforms: _cssTransforms
9848
- };
9849
-
9850
- return new cssSyntax.SourceProcessor().process(css, {
9851
- mode: "minify",
9852
- ...options,
9853
- as
9854
- }).code;
9855
- } catch (_err) {
9856
- return null;
9857
- }
9858
- };
9859
-
9860
- /**
9861
- * `_minifyStyleBody`, with text it rejects handed back untouched rather than
9862
- * failing the build.
9894
+ * Offer a `<style>` body to the renderer, blank text kept as written. Webpack
9895
+ * minifies no CSS here itself: `builtinEmbeddedRenderer` is what a caller
9896
+ * passes for that.
9863
9897
  * @param {string} css the element's text
9864
- * @returns {string} the minified text
9898
+ * @returns {string} the rendered text, the marker standing for it, or the text as written
9865
9899
  */
9866
- const _minifyInlineCss = (css) => {
9867
- const minified = _minifyStyleBody(css);
9868
- return minified === null ? css : minified;
9869
- };
9900
+ const _minifyStyleBody = (css) =>
9901
+ css.trim() === "" ? css : _renderEmbedded(css, CSS_TYPE);
9870
9902
 
9871
9903
  // The throwaway rule a `style` attribute's declaration list is minified inside.
9872
9904
  // The selector is only ever written and read back here, so it is the shortest
@@ -9881,9 +9913,10 @@ const _minifyInlineCss = (css) => {
9881
9913
  * @param {string} value its rewritten value
9882
9914
  * @param {string} rawValue its value as the source spelled it
9883
9915
  * @param {string | null} decoded the value decoded, for one carrying character references, or null
9916
+ * @param {boolean} quoted whether the source spelled the value with a delimiter, which is two characters this has to beat
9884
9917
  * @returns {{ text: string, unquotedTail: boolean } | null} what to emit, or null to leave the source alone
9885
9918
  */
9886
- const _writeAttribute = (attributeName, value, rawValue, decoded) => {
9919
+ const _writeAttribute = (attributeName, value, rawValue, decoded, quoted) => {
9887
9920
  const minimal =
9888
9921
  _transforms.normalizeAttributeQuotes && decoded !== null
9889
9922
  ? _minimalAttributeValue(decoded)
@@ -9893,7 +9926,8 @@ const _writeAttribute = (attributeName, value, rawValue, decoded) => {
9893
9926
 
9894
9927
  if (
9895
9928
  minimal !== null &&
9896
- minimal.length < (unquotable ? value.length : rawValue.length + 2)
9929
+ minimal.length <
9930
+ (unquotable ? value.length : rawValue.length + (quoted ? 2 : 0))
9897
9931
  ) {
9898
9932
  const opened = minimal.charCodeAt(0);
9899
9933
 
@@ -9919,54 +9953,17 @@ const _writeAttribute = (attributeName, value, rawValue, decoded) => {
9919
9953
  };
9920
9954
 
9921
9955
  /**
9922
- * Minify a `style` attribute's declaration list with webpack's CSS minifier, as
9923
- * the block-contents production it is — which is what gives the list the
9924
- * duplicate-drop and shorthand merges a rule's block gets.
9956
+ * Offer a `style` attribute's declaration list to the renderer as the
9957
+ * block-contents production it is, which gives it the merges a rule's block
9958
+ * gets. The deferring path offers it at the attribute instead, where the shape
9959
+ * an answer has to land in is known.
9925
9960
  * @param {string} raw raw (undecoded) attribute value
9926
- * @returns {string} the minified declarations
9961
+ * @returns {string} the rendered declarations, or the value as written
9927
9962
  */
9928
9963
  const _minifyStyleAttribute = (raw) => {
9929
- // Ahead of the memo: with the switch off nothing is minified, so there is
9930
- // nothing to keep and nothing to read back.
9931
- if (!_transforms.minifyStyles) return raw;
9932
- // A caller's renderer is handed every `style=""` the document holds, so it is
9933
- // not a function of the value alone and nothing about it may be reused.
9934
- if (_renderEmbeddedSource !== undefined) {
9935
- return _minifyStyleAttributeUncached(raw);
9936
- }
9937
- const memoized = _styleAttributeCache.get(raw);
9938
- if (memoized !== undefined) return memoized;
9939
- const minified = _minifyStyleAttributeUncached(raw);
9940
- _styleAttributeCache.set(raw, minified);
9941
- return minified;
9942
- };
9943
-
9944
- /**
9945
- * `_minifyStyleAttribute` without the memo — every path here runs the CSS
9946
- * minifier, and every return is safe to keep, none of them reading state the
9947
- * print goes on to change.
9948
- * @param {string} raw raw (undecoded) attribute value
9949
- * @returns {string} the minified declarations
9950
- */
9951
- const _minifyStyleAttributeUncached = (raw) => {
9952
- if (raw.trim() === "") return raw;
9953
-
9954
- // Offered as the CSS it is, with `as` saying which production — the wrapper a
9955
- // declaration list needs for the transforms a block's contents get is the CSS
9956
- // layer's own business. The deferring path offers it at the attribute
9957
- // instead, where the shape an answer has to land in is known.
9958
- if (
9959
- _renderEmbeddedSource !== undefined &&
9960
- _deferEmbeddedSource === undefined
9961
- ) {
9962
- const rendered = _renderEmbeddedOrNull(raw, CSS_TYPE, BLOCK_CONTENTS);
9963
-
9964
- if (rendered !== null) return rendered;
9965
- }
9966
-
9967
- const out = _builtinStyleBody(raw, BLOCK_CONTENTS);
9968
-
9969
- return out === null ? raw : out;
9964
+ if (_deferEmbeddedSource !== undefined || raw.trim() === "") return raw;
9965
+ const rendered = _renderEmbeddedOrNull(raw, CSS_TYPE, BLOCK_CONTENTS);
9966
+ return rendered === null ? raw : rendered;
9970
9967
  };
9971
9968
 
9972
9969
  /**
@@ -10049,10 +10046,11 @@ const _isRedundantAttribute = (markers, defaults, tagName, name, value) => {
10049
10046
  // `<script type>`: only a spelling that names JavaScript, which is what the
10050
10047
  // element already runs. `module` and the empty spelling say something.
10051
10048
  if (tagName === "script" && name === "type") {
10049
+ // Read the way `_scriptType` reads it, or the two disagree about which
10050
+ // `<script>` this is and the body's handler and this one part ways.
10051
+ const type = _asciiLowerCase(_asciiTrim(decodeEntities(value, true)));
10052
10052
  return (
10053
- lowered !== "" &&
10054
- lowered !== "module" &&
10055
- JAVASCRIPT_SCRIPT_TYPES.has(lowered)
10053
+ type !== "" && type !== "module" && JAVASCRIPT_SCRIPT_TYPES.has(type)
10056
10054
  );
10057
10055
  }
10058
10056
  if (markers !== undefined && markers[name] === lowered) return true;
@@ -10154,6 +10152,20 @@ const _isBooleanAttribute = (tagName, name) => {
10154
10152
  return elements === null || elements.has(tagName);
10155
10153
  };
10156
10154
 
10155
+ /**
10156
+ * Whether an attribute is an event handler on this element, so its value is
10157
+ * JavaScript rather than text. `null` in the table means the attribute is a
10158
+ * handler on every element.
10159
+ * @param {string} tagName lowercased element name
10160
+ * @param {string} name lowercased attribute name
10161
+ * @returns {boolean} true when the value is a handler body
10162
+ */
10163
+ const _isEventHandlerAttribute = (tagName, name) => {
10164
+ const elements = EVENT_HANDLER_ATTRIBUTES.get(name);
10165
+ if (elements === undefined) return false;
10166
+ return elements === null || elements.has(tagName);
10167
+ };
10168
+
10157
10169
  /**
10158
10170
  * Whether a space-separated list names the same token twice, read span by span
10159
10171
  * so nothing is allocated. The lists are short — `class` is a handful of tokens
@@ -10187,17 +10199,33 @@ const _repeatsAToken = (list) => {
10187
10199
  return false;
10188
10200
  };
10189
10201
 
10202
+ /**
10203
+ * Whether every token of a collapsed list is a word, which is what makes the
10204
+ * list the set the DOM reflects rather than another language's text.
10205
+ * @param {string} list a collapsed, trimmed token list
10206
+ * @returns {boolean} true when no token holds a foreign delimiter
10207
+ */
10208
+ const _tokensAreWords = (list) => {
10209
+ const length = list.length;
10210
+ for (let start = 0; start < length;) {
10211
+ let end = list.indexOf(" ", start);
10212
+ if (end === -1) end = length;
10213
+ if (!_isWordSpan(list, start, end)) return false;
10214
+ start = end + 1;
10215
+ }
10216
+ return true;
10217
+ };
10218
+
10190
10219
  /**
10191
10220
  * Collapse an ASCII-whitespace-separated token list (`class`) to single spaces,
10192
- * and — where the DOM reflects the list as a `DOMTokenList`, an ordered *set*,
10193
- * so a repeat was never a second token — drop a token already in it. Order is
10194
- * kept either way: the first spelling of each token stays put.
10221
+ * and — where every token is a word, so the list is the ordered *set* the DOM
10222
+ * reflects — drop a token already in it. Order is kept unless `sort` asks.
10195
10223
  * @param {string} raw raw (undecoded) value
10196
- * @param {boolean} unique whether a repeated token may go (`DOM_TOKEN_LIST_ATTRIBUTES`)
10224
+ * @param {boolean} isSet whether the DOM reflects the list as a `DOMTokenList`
10197
10225
  * @param {boolean} sort whether to print the tokens in order (`sortTokenLists`)
10198
10226
  * @returns {string} the collapsed list
10199
10227
  */
10200
- const _normalizeTokenList = (raw, unique, sort) => {
10228
+ const _normalizeTokenList = (raw, isSet, sort) => {
10201
10229
  // One walk answers "already collapsed?" — the common already-minified list
10202
10230
  // rewrites nothing, so it must not pay the trim + regex replace either.
10203
10231
  let dirty = false;
@@ -10222,12 +10250,16 @@ const _normalizeTokenList = (raw, unique, sort) => {
10222
10250
  if (!dirty && previousSpace && raw.length !== 0) dirty = true;
10223
10251
  const collapsed = dirty ? _asciiTrim(raw).replace(/[\t\n\f\r ]+/g, " ") : raw;
10224
10252
  if (dirty ? !collapsed.includes(" ") : !hasSpace) return collapsed;
10253
+ if (!isSet) return collapsed;
10225
10254
  // Cutting the list into tokens is the allocation this runs often enough to
10226
- // care about, and almost no list repeats one — so the check reads the spans
10227
- // in place and only a list that does pay for the pieces. Sorting needs them
10228
- // either way.
10229
- if (!sort && !(unique && _repeatsAToken(collapsed))) return collapsed;
10230
- if (sort) return _sortedTokenList(collapsed, unique);
10255
+ // care about, and almost no list repeats one — so the checks read the spans
10256
+ // in place and only a list that folds pays for the pieces.
10257
+ if (sort) {
10258
+ return _tokensAreWords(collapsed) ? _sortedTokenList(collapsed) : collapsed;
10259
+ }
10260
+ if (!_repeatsAToken(collapsed) || !_tokensAreWords(collapsed)) {
10261
+ return collapsed;
10262
+ }
10231
10263
  return [...new Set(collapsed.split(" "))].join(" ");
10232
10264
  };
10233
10265
 
@@ -10258,13 +10290,12 @@ const _compareTokens = (list, aStart, aEnd, bStart, bEnd) => {
10258
10290
  };
10259
10291
 
10260
10292
  /**
10261
- * `collapsed`'s tokens in sorted order, deduplicated when it is a set. They are
10262
- * ordered where they sit, so the pieces `split` would build are never built.
10293
+ * `collapsed`'s tokens in sorted order, with a repeat dropped. They are ordered
10294
+ * where they sit, so the pieces `split` would build are never built.
10263
10295
  * @param {string} collapsed a single-space-separated list
10264
- * @param {boolean} unique whether repeats collapse
10265
- * @returns {string} the ordered list
10296
+ * @returns {string} the ordered set
10266
10297
  */
10267
- const _sortedTokenList = (collapsed, unique) => {
10298
+ const _sortedTokenList = (collapsed) => {
10268
10299
  const starts = _tokenSpanStarts;
10269
10300
  const ends = _tokenSpanEnds;
10270
10301
  let count = 0;
@@ -10296,7 +10327,6 @@ const _sortedTokenList = (collapsed, unique) => {
10296
10327
  let out = "";
10297
10328
  for (let i = 0; i < count; i++) {
10298
10329
  if (
10299
- unique &&
10300
10330
  i !== 0 &&
10301
10331
  _compareTokens(
10302
10332
  collapsed,
@@ -10388,16 +10418,20 @@ const _rewriteAttributeValue = (element, name, raw, viewport, enumeratedOn) => {
10388
10418
  return _transforms.normalizeListAttributes ? _normalizeSrcset(raw) : raw;
10389
10419
  }
10390
10420
  if (name === "style") return _minifyStyleAttribute(raw);
10391
- const tokenListOn = _transforms.normalizeListAttributes
10392
- ? TOKEN_LIST_ATTRIBUTES.get(name)
10393
- : undefined;
10421
+ // A list `sortTokenLists` reorders is read whatever `normalizeListAttributes`
10422
+ // says: another order rewrites the separators between the tokens anyway.
10423
+ const tokenListOn =
10424
+ _transforms.normalizeListAttributes ||
10425
+ (_sortTokenLists && DOM_TOKEN_LIST_ATTRIBUTES.has(name))
10426
+ ? TOKEN_LIST_ATTRIBUTES.get(name)
10427
+ : undefined;
10394
10428
  if (
10395
10429
  tokenListOn !== undefined &&
10396
10430
  (tokenListOn === null || tokenListOn.has(element))
10397
10431
  ) {
10398
10432
  // Only the lists the DOM reflects as a `DOMTokenList` are sets, so only
10399
- // they may be reordered — `ping` is the order its requests go out in and
10400
- // `accesskey` the order its keys are tried.
10433
+ // they may be reordered or have a repeat folded away — `ping` is the order
10434
+ // its requests go out in and `accesskey` the order its keys are tried.
10401
10435
  const isSet = DOM_TOKEN_LIST_ATTRIBUTES.has(name);
10402
10436
  return _normalizeTokenList(raw, isSet, _sortTokenLists && isSet);
10403
10437
  }
@@ -10405,7 +10439,9 @@ const _rewriteAttributeValue = (element, name, raw, viewport, enumeratedOn) => {
10405
10439
  if (viewport && name === "content") return _normalizeViewport(raw);
10406
10440
  if (COMMA_LIST_ATTRIBUTES.has(name)) return _normalizeCommaList(raw);
10407
10441
  }
10408
- const urlOn = URL_ATTRIBUTES.get(name);
10442
+ const urlOn = _transforms.normalizeUrlAttributes
10443
+ ? URL_ATTRIBUTES.get(name)
10444
+ : undefined;
10409
10445
  if (urlOn !== undefined && (urlOn === null || urlOn.has(element))) {
10410
10446
  return _asciiTrim(raw);
10411
10447
  }
@@ -10430,7 +10466,9 @@ const _rewriteAttributeValue = (element, name, raw, viewport, enumeratedOn) => {
10430
10466
  const _scriptType = (path, element) => {
10431
10467
  for (const attribute of path.attributes(element)) {
10432
10468
  if (attribute.name === "type") {
10433
- return _asciiLowerCase(_asciiTrim(attribute.value));
10469
+ // The value the spec matches is the one the parser read, so a reference
10470
+ // is decoded first: `text&#47;javascript` runs, it is not a data block.
10471
+ return _asciiLowerCase(_asciiTrim(decodeEntities(attribute.value, true)));
10434
10472
  }
10435
10473
  }
10436
10474
  return "";
@@ -10455,64 +10493,13 @@ const _JSON_SUBTYPE_REGEXP =
10455
10493
  /^[!#$%&'*+.^_`|~\w-]+\/[!#$%&'*+.^_`|~\w-]*\+json$/;
10456
10494
 
10457
10495
  /**
10458
- * Strip the whitespace between a JSON body's tokens. Every literal is copied
10459
- * byte for byte — re-serializing would reorder nothing but would round numbers
10460
- * through a double, drop a duplicate key and rewrite escapes, none of which is
10461
- * this transform's to do. Escapes are also the security case: unescaping a
10462
- * `<` lets a string close the `<script>` early.
10496
+ * Offer a JSON `<script>` body to the renderer, blank text kept as written;
10497
+ * `stripJsonWhitespace` is what webpack's own answers with.
10463
10498
  * @param {string} json a `<script>` body
10464
- * @returns {string} the stripped body
10499
+ * @returns {string} the rendered body, the marker standing for it, or the body as written
10465
10500
  */
10466
- const _minifyInlineJson = (json) => {
10467
- if (!_transforms.minifyJson) return json;
10468
- if (json.trim() === "") return json;
10469
- if (_deferEmbeddedSource !== undefined) {
10470
- return _deferEmbedded(json, JSON_TYPE, (rendered) =>
10471
- typeof rendered === "string" ? rendered : _builtinInlineJson(json)
10472
- );
10473
- }
10474
- if (_renderEmbeddedSource !== undefined) {
10475
- const rendered = _renderEmbeddedOrNull(json, JSON_TYPE);
10476
- if (rendered !== null) return rendered;
10477
- }
10478
- return _builtinInlineJson(json);
10479
- };
10480
-
10481
- /**
10482
- * The JSON strip webpack ships, for a body no caller's renderer answered for.
10483
- * @param {string} json a `<script>` body
10484
- * @returns {string} the stripped body
10485
- */
10486
- const _builtinInlineJson = (json) => {
10487
- try {
10488
- JSON.parse(json);
10489
- } catch (_err) {
10490
- // Not JSON after all (a template, a placeholder) — not ours to touch.
10491
- return json;
10492
- }
10493
- let out = "";
10494
- let inString = false;
10495
- let escaped = false;
10496
- for (let i = 0; i < json.length; i++) {
10497
- const c = json.charCodeAt(i);
10498
- if (inString) {
10499
- out += json[i];
10500
- if (escaped) escaped = false;
10501
- else if (c === 0x5c) escaped = true;
10502
- else if (c === 0x22) inString = false;
10503
- continue;
10504
- }
10505
- if (c === 0x22) {
10506
- inString = true;
10507
- out += json[i];
10508
- continue;
10509
- }
10510
- // JSON whitespace (RFC 8259): tab, LF, CR, space.
10511
- if (c === 0x09 || c === 0x0a || c === 0x0d || c === 0x20) continue;
10512
- out += json[i];
10513
- }
10514
- return out;
10515
- };
10501
+ const _minifyInlineJson = (json) =>
10502
+ json.trim() === "" ? json : _renderEmbedded(json, JSON_TYPE);
10516
10503
 
10517
10504
  /**
10518
10505
  * Whether a `<style>` element's body is CSS: the attribute is optional, and the
@@ -10535,12 +10522,12 @@ const _isCssStyleElement = (path, element) => {
10535
10522
  const _SHEET_LEADING_AT_RULE_REGEXP = /@(?:charset|import|namespace)\b/i;
10536
10523
 
10537
10524
  /**
10538
- * A `<style>`'s only child when that is one text node — the shape a merge needs,
10539
- * since `<style>` is parsed as raw text and anything else means it is empty.
10540
- * @param {HtmlElement} element the `<style>` element
10525
+ * A literal-text element's only child when that is one text node — the shape a
10526
+ * merge needs, since anything else means the element is empty.
10527
+ * @param {HtmlElement} element a `<style>` or `<script>`
10541
10528
  * @returns {HtmlNodeRef} the text node, or 0
10542
10529
  */
10543
- const _styleTextChild = (element) => {
10530
+ const _onlyTextChild = (element) => {
10544
10531
  const first = _nodeFirstChildren[element];
10545
10532
  return first !== 0 &&
10546
10533
  _nodeTypes[first] === NodeType.Text &&
@@ -10598,7 +10585,7 @@ const _mergeableStyleAfter = (path, element) => {
10598
10585
  return type === NodeType.Element &&
10599
10586
  path.namespace(next) === NS_HTML &&
10600
10587
  path.tagName(next) === "style" &&
10601
- _styleTextChild(next) !== 0 &&
10588
+ _onlyTextChild(next) !== 0 &&
10602
10589
  _isCssStyleElement(path, next) &&
10603
10590
  _sameAttributes(path, element, next)
10604
10591
  ? next
@@ -10608,43 +10595,265 @@ const _mergeableStyleAfter = (path, element) => {
10608
10595
  };
10609
10596
 
10610
10597
  /**
10611
- * The text the first `<style>` of a run prints: every sheet in it, each minified
10612
- * on its own and then joined. Marks the rest of the run absorbed, which is what
10613
- * makes their tags and text print as nothing — it runs first because a run's
10614
- * first element prints before any of the others in both print paths.
10615
- *
10616
- * Each sheet is minified before it is joined, never after: only text the
10617
- * minifier accepted is known to be terminated, and appending to a sheet that is
10618
- * not makes the next one part of the last rule of this one. A sheet after the
10619
- * first carrying `@import` (or `@charset` / `@namespace`) is not folded either —
10620
- * those only apply at the top of a sheet, and would silently stop applying.
10598
+ * Whether a sheet ends outside every string, comment and bracket, so a sheet
10599
+ * appended to it starts rules of its own rather than finishing this one's last.
10600
+ * @param {string} css the sheet's text
10601
+ * @returns {boolean} true when another sheet may follow it
10602
+ */
10603
+ const _sheetEndsCleanly = (css) => {
10604
+ let depth = 0;
10605
+ for (let i = 0; i < css.length; i++) {
10606
+ const c = css.charCodeAt(i);
10607
+ if (c === CC_REVERSE_SOLIDUS) {
10608
+ i++;
10609
+ } else if (c === CC_SOLIDUS && css.charCodeAt(i + 1) === CC_ASTERISK) {
10610
+ const close = css.indexOf("*/", i + 2);
10611
+ if (close === -1) return false;
10612
+ i = close + 1;
10613
+ } else if (c === CC_QUOTATION_MARK || c === CC_APOSTROPHE) {
10614
+ // A string ends at its quote, or at a newline as a bad string does.
10615
+ for (i++; i < css.length; i++) {
10616
+ const d = css.charCodeAt(i);
10617
+ if (d === CC_REVERSE_SOLIDUS) i++;
10618
+ else if (d === c || d === CC_LF) break;
10619
+ }
10620
+ if (i >= css.length) return false;
10621
+ } else if (
10622
+ c === CC_LEFT_CURLY_BRACKET ||
10623
+ c === CC_LEFT_PARENTHESIS ||
10624
+ c === CC_LEFT_SQUARE_BRACKET
10625
+ ) {
10626
+ depth++;
10627
+ } else if (
10628
+ depth !== 0 &&
10629
+ (c === CC_RIGHT_CURLY_BRACKET ||
10630
+ c === CC_RIGHT_PARENTHESIS ||
10631
+ c === CC_RIGHT_SQUARE_BRACKET)
10632
+ ) {
10633
+ depth--;
10634
+ }
10635
+ }
10636
+ return depth === 0;
10637
+ };
10638
+
10639
+ /**
10640
+ * The text the first `<style>` of a run prints: every sheet in it, each offered
10641
+ * on its own and then joined, the rest of the run marked absorbed so their tags
10642
+ * and text print as nothing. Whether a sheet joins is read off its source, since
10643
+ * an answer may be a marker: one not ending cleanly would swallow the next, and
10644
+ * one after the first carrying `@import` (or `@charset` / `@namespace`) would
10645
+ * silently stop applying those.
10621
10646
  * @param {HtmlPath} path the accessor
10622
10647
  * @param {HtmlElement} element the run's first `<style>`
10623
10648
  * @param {string} css its own text
10624
10649
  * @returns {string} the run's text
10625
10650
  */
10626
10651
  const _mergedStyleRun = (path, element, css) => {
10627
- const head = _minifyStyleBody(css);
10628
- if (head === null) return css;
10629
- let out = head;
10652
+ let out = _minifyStyleBody(css);
10653
+ if (!_sheetEndsCleanly(css)) return out;
10630
10654
  for (
10631
10655
  let next = _mergeableStyleAfter(path, element);
10632
10656
  next !== 0;
10633
10657
  next = _mergeableStyleAfter(path, next)
10634
10658
  ) {
10635
- const decided = { text: "" };
10636
- const body = _minifyStyleBody(
10637
- _nodeStrings[/** @type {HtmlNodeRef} */ (_styleTextChild(next))],
10638
- decided
10639
- );
10640
- if (body === null) break;
10641
- // Read the built-in's text, not the marker: whether this sheet may be
10642
- // absorbed decides what its own element prints, so it cannot wait for an
10643
- // answer.
10644
- if (_SHEET_LEADING_AT_RULE_REGEXP.test(decided.text || body)) break;
10645
- if (_absorbedStyles === null) _absorbedStyles = new Set();
10646
- _absorbedStyles.add(next);
10647
- out += body;
10659
+ const text =
10660
+ _nodeStrings[/** @type {HtmlNodeRef} */ (_onlyTextChild(next))];
10661
+ if (!_sheetEndsCleanly(text) || _SHEET_LEADING_AT_RULE_REGEXP.test(text)) {
10662
+ break;
10663
+ }
10664
+ if (_absorbed === null) _absorbed = new Set();
10665
+ _absorbed.add(next);
10666
+ out += _minifyStyleBody(text);
10667
+ }
10668
+ return out;
10669
+ };
10670
+
10671
+ /**
10672
+ * Whether a script body ends where another can be appended after it. A body
10673
+ * still inside a string, template or block comment would swallow the next one;
10674
+ * a trailing line comment is fine because the join writes a newline first. The
10675
+ * body is read rather than parsed, so a regex literal can be taken for a string
10676
+ * or a comment — the answer holds for a body that parses, and one that does not
10677
+ * takes its whole run with it however this reads.
10678
+ * @param {string} js the script's text
10679
+ * @returns {boolean} true when nothing is left open
10680
+ */
10681
+ const _scriptEndsClean = (js) => {
10682
+ let state = 0; // 0 none, 1 line comment, 2 block comment, 3 ' 4 " 5 `
10683
+ // Read by code unit: a body is scanned whole, and `js[i]` would allocate a
10684
+ // one-character string at every position of it.
10685
+ for (let i = 0; i < js.length; i++) {
10686
+ const c = js.charCodeAt(i);
10687
+ if (state === 0) {
10688
+ if (c === 47 /* / */) {
10689
+ const next = js.charCodeAt(i + 1);
10690
+ if (next === 47) {
10691
+ state = 1;
10692
+ i++;
10693
+ } else if (next === 42 /* * */) {
10694
+ state = 2;
10695
+ i++;
10696
+ }
10697
+ } else if (c === 39 /* ' */) {
10698
+ state = 3;
10699
+ } else if (c === 34 /* " */) {
10700
+ state = 4;
10701
+ } else if (c === 96 /* ` */) {
10702
+ state = 5;
10703
+ }
10704
+ } else if (state === 1) {
10705
+ // Every line terminator ends a line comment, not just the two HTML
10706
+ // normalizes text to — a `"` past one really does open a string.
10707
+ if (c === 10 || c === 13 || c === 0x2028 || c === 0x2029) state = 0;
10708
+ } else if (state === 2) {
10709
+ if (c === 42 && js.charCodeAt(i + 1) === 47) {
10710
+ state = 0;
10711
+ i++;
10712
+ }
10713
+ } else if (c === 92 /* \\ */) {
10714
+ i++;
10715
+ } else if (
10716
+ (state === 3 && c === 39) ||
10717
+ (state === 4 && c === 34) ||
10718
+ (state === 5 && c === 96)
10719
+ ) {
10720
+ state = 0;
10721
+ }
10722
+ }
10723
+ return state === 0 || state === 1;
10724
+ };
10725
+
10726
+ // ECMAScript's own whitespace and line terminators, which are wider than the
10727
+ // HTML ones: a BOM, a form feed and U+2028 all sit before a directive.
10728
+ const JS_WHITESPACE_REGEXP = /\s/;
10729
+ const JS_LINE_TERMINATOR_REGEXP = /[\n\r\u2028\u2029]/;
10730
+ const BOM_REGEXP = /^\uFEFF/;
10731
+
10732
+ /**
10733
+ * Whether a script body opens with what only a script's own start carries: a
10734
+ * hashbang, or a directive prologue — the leading string `"use strict"` is one.
10735
+ * Appended after another body neither means that any more.
10736
+ * @param {string} js the script's text
10737
+ * @returns {boolean} true when the body must start a script of its own
10738
+ */
10739
+ const _opensAScript = (js) => {
10740
+ // A hashbang is only one at the very start, a BOM aside.
10741
+ if (js.replace(BOM_REGEXP, "").startsWith("#!")) return true;
10742
+ let i = 0;
10743
+ while (i < js.length) {
10744
+ const c = js[i];
10745
+ if (JS_WHITESPACE_REGEXP.test(c)) {
10746
+ i++;
10747
+ } else if (c === "/" && js[i + 1] === "/") {
10748
+ i += 2;
10749
+ while (i < js.length && !JS_LINE_TERMINATOR_REGEXP.test(js[i])) i++;
10750
+ } else if (c === "/" && js[i + 1] === "*") {
10751
+ const end = js.indexOf("*/", i + 2);
10752
+ if (end === -1) return true;
10753
+ i = end + 2;
10754
+ } else {
10755
+ break;
10756
+ }
10757
+ }
10758
+ return js[i] === '"' || js[i] === "'";
10759
+ };
10760
+
10761
+ /**
10762
+ * Whether a body opens with `-->` still on its first line. That is a single
10763
+ * line comment only where nothing but whitespace and same-line comments comes
10764
+ * before it on the line, which an appended body no longer begins.
10765
+ * @param {string} js the script's text
10766
+ * @returns {boolean} true when appending the body would change what `-->` means
10767
+ */
10768
+ const _opensWithHtmlCloseComment = (js) => {
10769
+ let i = 0;
10770
+ while (i < js.length) {
10771
+ const c = js[i];
10772
+ if (JS_LINE_TERMINATOR_REGEXP.test(c)) return false;
10773
+ if (JS_WHITESPACE_REGEXP.test(c)) {
10774
+ i++;
10775
+ } else if (c === "/" && js[i + 1] === "*") {
10776
+ const end = js.indexOf("*/", i + 2);
10777
+ // One spanning a line terminator ends the line it opened, so what
10778
+ // follows starts a line of its own.
10779
+ if (end === -1 || JS_LINE_TERMINATOR_REGEXP.test(js.slice(i + 2, end))) {
10780
+ return false;
10781
+ }
10782
+ i = end + 2;
10783
+ } else {
10784
+ return js.startsWith("-->", i);
10785
+ }
10786
+ }
10787
+ return false;
10788
+ };
10789
+
10790
+ /**
10791
+ * The `<script>` that may be folded into `element`: the next sibling, when only
10792
+ * whitespace lies between them and neither carries a single attribute. Bare is
10793
+ * the whole test — a `src`, `type`, `nonce`, `async` or `id` all say the two
10794
+ * elements are not interchangeable with one.
10795
+ * @param {HtmlPath} path the accessor
10796
+ * @param {HtmlElement} element a `<script>` element
10797
+ * @returns {HtmlElement} the next `<script>` of the run, or 0
10798
+ */
10799
+ const _mergeableScriptAfter = (path, element) => {
10800
+ if (path.attributeCount(element) !== 0) return 0;
10801
+ for (
10802
+ let next = _nodeNextSiblings[element];
10803
+ next !== 0;
10804
+ next = _nodeNextSiblings[next]
10805
+ ) {
10806
+ const type = _nodeTypes[next];
10807
+ if (type === NodeType.Text) {
10808
+ if (!isAllWs(_nodeStrings[next])) return 0;
10809
+ continue;
10810
+ }
10811
+ return type === NodeType.Element &&
10812
+ path.namespace(next) === NS_HTML &&
10813
+ path.tagName(next) === "script" &&
10814
+ path.attributeCount(next) === 0 &&
10815
+ _onlyTextChild(next) !== 0
10816
+ ? next
10817
+ : 0;
10818
+ }
10819
+ return 0;
10820
+ };
10821
+
10822
+ /**
10823
+ * The text the first `<script>` of a run prints: every body in it, joined by a
10824
+ * newline and a `;`. The newline ends a trailing line comment and the `;` keeps
10825
+ * the next body from continuing the last statement — `var a = 1` followed by
10826
+ * `(f)()` is one call without it.
10827
+ * @param {HtmlPath} path the accessor
10828
+ * @param {HtmlElement} element the run's first `<script>`
10829
+ * @param {string} js its own text
10830
+ * @returns {string} the run's text
10831
+ */
10832
+ const _mergedScriptRun = (path, element, js) => {
10833
+ // A deferred body is a stand-in the caller swaps out after the print, so the
10834
+ // text read here is neither the code that runs nor what a guard can judge.
10835
+ if (_deferEmbeddedSource !== undefined) return js;
10836
+ // Asked before the body is scanned: a lone `<script>` is the common case and
10837
+ // scanning it whole to then find nothing to fold into is the whole cost.
10838
+ const first = _mergeableScriptAfter(path, element);
10839
+ if (first === 0) return js;
10840
+ // A prologue reaches whatever is appended after it, so a strict first body
10841
+ // would put the rest of the run in strict mode too.
10842
+ if (!_scriptEndsClean(js) || _opensAScript(js)) return js;
10843
+ let out = js;
10844
+ for (let next = first; next !== 0; next = _mergeableScriptAfter(path, next)) {
10845
+ const body =
10846
+ _nodeStrings[/** @type {HtmlNodeRef} */ (_onlyTextChild(next))];
10847
+ if (
10848
+ !_scriptEndsClean(body) ||
10849
+ _opensAScript(body) ||
10850
+ _opensWithHtmlCloseComment(body)
10851
+ ) {
10852
+ break;
10853
+ }
10854
+ if (_absorbed === null) _absorbed = new Set();
10855
+ _absorbed.add(next);
10856
+ out += `\n;${body}`;
10648
10857
  }
10649
10858
  return out;
10650
10859
  };
@@ -10848,6 +11057,15 @@ const _minifyOpenTag = (path, open) => {
10848
11057
  // content keeps its source bytes: SVG admits element names no adjustment table
10849
11058
  // would case-correct on the way back in.
10850
11059
  const html = path.namespace() === NS_HTML;
11060
+ // Rebuilding a tag another language wrote would print the spec's duplicate
11061
+ // drop into the output, which a re-parse of the source makes again anyway.
11062
+ if (
11063
+ count !== 0 &&
11064
+ _foreignSyntaxAttrRuns.size !== 0 &&
11065
+ _foreignSyntaxAttrRuns.has(path.attributeAt(0))
11066
+ ) {
11067
+ return open;
11068
+ }
10851
11069
  const nameEnd = path.nameEnd() - tagStart;
10852
11070
  // A bare `<name>` — half of all tags — is what the rest would rebuild byte
10853
11071
  // for byte; decided before the name is sliced, so it allocates nothing.
@@ -10870,6 +11088,9 @@ const _minifyOpenTag = (path, open) => {
10870
11088
  const isViewportMeta =
10871
11089
  html && path.tagName() === "meta" && _isViewportMeta(path);
10872
11090
  let unquotedTail = false;
11091
+ // Only a foreign element's surviving `/>` reads it, so only there is a
11092
+ // deferred answer held to the shape the built-in was written in.
11093
+ const tailIsRead = !html && open.charCodeAt(open.length - 2) === 47;
10873
11094
  let consumedEnd = path.nameEnd();
10874
11095
  // HTML only, which is also what keeps `consumedEnd` meaningful: it is read
10875
11096
  // once more below, and only for a foreign element's `/>`.
@@ -10936,53 +11157,53 @@ const _minifyOpenTag = (path, open) => {
10936
11157
  consumedEnd = valueEnd;
10937
11158
  continue;
10938
11159
  }
10939
- if (quoted) {
10940
- const hasReference = rawValue.includes("&");
10941
- // A whole document, so it is offered decoded and written back escaped —
10942
- // the one attribute whose reference-carrying value is still rewritten,
10943
- // since a document is mostly references. The renderer cannot parse it
10944
- // here (the walk is mid-parse), so it looks up what a walk-only pass
10945
- // prepared, exactly as an async minifier does.
10946
- if (
10947
- html &&
10948
- (_renderEmbeddedSource !== undefined ||
10949
- (_deferEmbeddedSource !== undefined && _deferSrcdoc)) &&
10950
- attributeName === "srcdoc" &&
10951
- elementName === "iframe" &&
10952
- rawValue !== ""
10953
- ) {
10954
- const document = decodeEntities(rawValue, true);
10955
- // The whole attribute is deferred, not the document inside it: what
10956
- // escaping it needs is decided by what it holds, which is the answer.
10957
- // The same test the gate above makes: with both renderers set, a
10958
- // caller asking for `srcdoc` on the normal path gets it there.
10959
- if (_deferEmbeddedSource !== undefined && _deferSrcdoc) {
10960
- // Declining leaves the attribute exactly as it was written, down to
10961
- // the delimiter: re-escaping it into double quotes would lengthen a
10962
- // value the source spelled with single ones.
10963
- const delimiter = open[valueStart - tagStart - 1];
10964
- const asWritten = ` ${attributeName}=${delimiter}${rawValue}${delimiter}`;
10965
-
10966
- out += _deferEmbedded(document, HTML_TYPE, (rendered) =>
10967
- typeof rendered !== "string" || rendered === document
10968
- ? asWritten
10969
- : ` ${attributeName}="${escapeAttribute(rendered, 34, true)}"`
10970
- );
10971
- unquotedTail = false;
10972
- consumedEnd = valueEnd;
10973
- continue;
10974
- }
11160
+ // A whole document, so it is offered decoded and written back escaped —
11161
+ // the one attribute whose reference-carrying value is still rewritten.
11162
+ if (
11163
+ html &&
11164
+ (_renderEmbeddedSource !== undefined ||
11165
+ (_deferEmbeddedSource !== undefined && _deferSrcdoc)) &&
11166
+ attributeName === "srcdoc" &&
11167
+ elementName === "iframe" &&
11168
+ rawValue !== ""
11169
+ ) {
11170
+ const document = decodeEntities(rawValue, true);
11171
+ // The whole attribute is deferred, not the document inside it: what
11172
+ // escaping it needs is decided by what it holds, which is the answer.
11173
+ if (_deferEmbeddedSource !== undefined && _deferSrcdoc) {
11174
+ // Declining leaves the attribute as written, delimiter and all: a bare
11175
+ // value has none, and quoting one would only lengthen it.
11176
+ const delimiter = quoted ? open[valueStart - tagStart - 1] : "";
11177
+ const asWritten = ` ${attributeName}=${delimiter}${rawValue}${delimiter}`;
11178
+
11179
+ out += _deferEmbedded(document, HTML_TYPE, (rendered) =>
11180
+ typeof rendered !== "string" || rendered === document
11181
+ ? asWritten
11182
+ : _writeQuotedAttribute(attributeName, rendered, delimiter)
11183
+ );
11184
+ unquotedTail = false;
11185
+ consumedEnd = valueEnd;
11186
+ continue;
11187
+ }
10975
11188
 
10976
- // The synchronous renderer: `_renderEmbedded` defers where a collector
10977
- // is set, and this attribute is the one kept off that path.
10978
- const rendered = _renderEmbeddedOrNull(document, HTML_TYPE);
10979
- if (rendered !== null && rendered !== document) {
10980
- out += ` ${attributeName}="${escapeAttribute(rendered, 34, true)}"`;
10981
- unquotedTail = false;
10982
- consumedEnd = valueEnd;
10983
- continue;
10984
- }
11189
+ // The synchronous renderer: `_renderEmbedded` defers where a collector
11190
+ // is set, and this attribute is the one kept off that path.
11191
+ const rendered = _renderEmbeddedOrNull(document, HTML_TYPE);
11192
+ if (rendered !== null && rendered !== document) {
11193
+ out += _writeQuotedAttribute(
11194
+ attributeName,
11195
+ rendered,
11196
+ quoted ? open[valueStart - tagStart - 1] : ""
11197
+ );
11198
+ unquotedTail = false;
11199
+ consumedEnd = valueEnd;
11200
+ continue;
10985
11201
  }
11202
+ }
11203
+ // Where nothing below can change the value: foreign content rewrites only
11204
+ // `style`, and a bare value is already the shortest spelling of itself.
11205
+ if (quoted || html || attributeName === "style" || rawValue.includes("&")) {
11206
+ const hasReference = rawValue.includes("&");
10986
11207
  // A character reference would decode to something these grammars read
10987
11208
  // differently, so only a reference-free value is rewritten.
10988
11209
  let value = rawValue;
@@ -11012,12 +11233,13 @@ const _minifyOpenTag = (path, open) => {
11012
11233
  // the switch that names the rest of them.
11013
11234
  if (
11014
11235
  _transforms.normalizeAttributeQuotes &&
11015
- (rawValue === "" ||
11236
+ (value === "" ||
11016
11237
  (html &&
11017
11238
  _transforms.collapseBooleanAttributes &&
11018
- rawValue.length === attributeName.length &&
11019
- _isBooleanAttribute(elementName, attributeName) &&
11020
- _asciiLowerCase(rawValue) === attributeName))
11239
+ (_transforms.collapseBooleanAttributes === "all" ||
11240
+ (rawValue.length === attributeName.length &&
11241
+ _asciiLowerCase(rawValue) === attributeName)) &&
11242
+ _isBooleanAttribute(elementName, attributeName)))
11021
11243
  ) {
11022
11244
  out += ` ${attributeName}`;
11023
11245
  unquotedTail = false;
@@ -11046,38 +11268,136 @@ const _minifyOpenTag = (path, open) => {
11046
11268
  */
11047
11269
  const writeStyle = (minified) =>
11048
11270
  declarations !== null
11049
- ? _writeAttribute(attributeName, rawValue, rawValue, minified)
11050
- : _writeAttribute(attributeName, minified, rawValue, spellable);
11271
+ ? _writeAttribute(attributeName, rawValue, rawValue, minified, quoted)
11272
+ : _writeAttribute(
11273
+ attributeName,
11274
+ minified,
11275
+ rawValue,
11276
+ spellable,
11277
+ quoted
11278
+ );
11051
11279
  const written = isStyle
11052
11280
  ? writeStyle(declarations !== null ? declarations : value)
11053
- : _writeAttribute(attributeName, value, rawValue, spellable);
11281
+ : _writeAttribute(attributeName, value, rawValue, spellable, quoted);
11282
+ // The JavaScript an event handler holds, offered decoded — `&amp;&amp;`
11283
+ // is an operator to JavaScript rather than an entity. No built-in.
11284
+ const handler =
11285
+ !isStyle &&
11286
+ (_renderEmbeddedSource !== undefined ||
11287
+ _deferEmbeddedSource !== undefined) &&
11288
+ _isEventHandlerAttribute(elementName, attributeName)
11289
+ ? hasReference
11290
+ ? spellable
11291
+ : rawValue
11292
+ : null;
11293
+
11294
+ if (handler !== null && _asciiTrim(handler) !== "") {
11295
+ const delimiter = quoted ? open[valueStart - tagStart - 1] : "";
11296
+ // A foreign `/>` reads back whether this value ends unquoted, which a
11297
+ // deferred answer is not there to decide: the source's quoting stands.
11298
+ const holdQuoted = tailIsRead && _deferEmbeddedSource !== undefined;
11299
+ // Declining leaves the attribute as an untapped run writes it, which is
11300
+ // the source spelling wherever nothing shorter was found.
11301
+ const asWritten =
11302
+ written === null || holdQuoted
11303
+ ? ` ${attributeName}=${delimiter}${rawValue}${delimiter}`
11304
+ : written.text;
11305
+ const declinedTail =
11306
+ !holdQuoted && written !== null && written.unquotedTail;
11307
+ /**
11308
+ * The answer is only written where it spells shorter than the source
11309
+ * does: a minifier ends a statement it was handed without one, so a
11310
+ * handler as short as `onclick="x"` comes back a byte longer.
11311
+ * @param {string | null | undefined} rendered what the renderer answered
11312
+ * @returns {{ text: string, unquotedTail: boolean } | null} what to emit, or null where nothing it answered is written
11313
+ */
11314
+ const writeHandler = (rendered) => {
11315
+ if (typeof rendered !== "string") return null;
11316
+
11317
+ // The answer is source text, so it is escaped for the delimiter it
11318
+ // lands in — an `&` in it opens a reference where it is not.
11319
+ const answered = holdQuoted
11320
+ ? {
11321
+ text: _writeQuotedAttribute(attributeName, rendered, delimiter),
11322
+ unquotedTail: false
11323
+ }
11324
+ : _writeAttribute(
11325
+ attributeName,
11326
+ escapeAttribute(rendered, CC_QUOTATION_MARK, true),
11327
+ rawValue,
11328
+ rendered,
11329
+ quoted
11330
+ );
11331
+
11332
+ return answered !== null && answered.text.length < asWritten.length
11333
+ ? answered
11334
+ : null;
11335
+ };
11336
+
11337
+ if (_deferEmbeddedSource !== undefined) {
11338
+ out += _deferEmbedded(
11339
+ handler,
11340
+ JAVASCRIPT_TYPE,
11341
+ (rendered) => {
11342
+ const answered = writeHandler(rendered);
11343
+
11344
+ return answered === null ? asWritten : answered.text;
11345
+ },
11346
+ EVENT_HANDLER
11347
+ );
11348
+ unquotedTail = declinedTail;
11349
+ } else {
11350
+ const answered = writeHandler(
11351
+ _renderEmbeddedOrNull(handler, JAVASCRIPT_TYPE, EVENT_HANDLER)
11352
+ );
11054
11353
 
11354
+ out += answered === null ? asWritten : answered.text;
11355
+ unquotedTail =
11356
+ answered === null ? declinedTail : answered.unquotedTail;
11357
+ }
11358
+ consumedEnd = valueEnd;
11359
+ continue;
11360
+ }
11361
+
11362
+ // Offered whatever the built-in made of it: a list already at its
11363
+ // shortest is one `_writeAttribute` declines, not one to ask nobody about.
11364
+ if (isStyle && _deferEmbeddedSource !== undefined) {
11365
+ // Declining leaves the attribute as written, delimiter and all — an
11366
+ // answer nothing beats is the renderer keeping what it was given.
11367
+ const delimiter = quoted ? open[valueStart - tagStart - 1] : "";
11368
+ const asWritten = ` ${attributeName}=${delimiter}${rawValue}${delimiter}`;
11369
+ // What stands until an answer arrives, and the tag ending it commits
11370
+ // to: the built-in's text where it beat the source, else the source.
11371
+ const standing = written !== null ? written.text : asWritten;
11372
+ const standingTail = written !== null && written.unquotedTail;
11373
+
11374
+ // The list is deferred, not the shape around it: the tag ending is
11375
+ // read back before an answer arrives, so one changing it is declined.
11376
+ out += _deferEmbedded(
11377
+ // Decoded when the source spelled it with references, since that
11378
+ // is the list itself rather than one attribute's spelling.
11379
+ spellable !== null ? spellable : rawValue,
11380
+ CSS_TYPE,
11381
+ (rendered) => {
11382
+ if (typeof rendered !== "string") return standing;
11383
+
11384
+ const answered = writeStyle(rendered);
11385
+ // Declining ends the value quoted: this is the branch the
11386
+ // source spelled with a delimiter.
11387
+ const tail = answered !== null && answered.unquotedTail;
11388
+
11389
+ if (tailIsRead && tail !== standingTail) return standing;
11390
+
11391
+ return answered !== null ? answered.text : asWritten;
11392
+ },
11393
+ BLOCK_CONTENTS
11394
+ );
11395
+ unquotedTail = standingTail;
11396
+ consumedEnd = valueEnd;
11397
+ continue;
11398
+ }
11055
11399
  if (written !== null) {
11056
- // The list is deferred, not the shape around it: whether this value
11057
- // leaves the tag ending unquoted is read back when the tag closes and
11058
- // cannot wait for an answer, so one that would land in the other shape
11059
- // is declined and the built-in's text stands.
11060
- out =
11061
- isStyle && _deferEmbeddedSource !== undefined
11062
- ? out +
11063
- _deferEmbedded(
11064
- // Decoded when the source spelled it with references, since
11065
- // that is the list itself rather than one attribute's spelling.
11066
- spellable !== null ? spellable : rawValue,
11067
- CSS_TYPE,
11068
- (rendered) => {
11069
- if (typeof rendered !== "string") return written.text;
11070
-
11071
- const answered = writeStyle(rendered);
11072
-
11073
- return answered !== null &&
11074
- answered.unquotedTail === written.unquotedTail
11075
- ? answered.text
11076
- : written.text;
11077
- },
11078
- BLOCK_CONTENTS
11079
- )
11080
- : out + written.text;
11400
+ out += written.text;
11081
11401
  unquotedTail = written.unquotedTail;
11082
11402
  consumedEnd = valueEnd;
11083
11403
  continue;
@@ -11260,7 +11580,7 @@ const _streamTags = (path, minify) => {
11260
11580
  // carrying nothing at all.
11261
11581
  if (
11262
11582
  minify &&
11263
- ((_absorbedStyles !== null && _absorbedStyles.has(path.node)) ||
11583
+ ((_absorbed !== null && _absorbed.has(path.node)) ||
11264
11584
  _isRemovableEmptyElement(path, path.node))
11265
11585
  ) {
11266
11586
  _streamOpen = "";
@@ -11726,7 +12046,7 @@ const _digest = (root) => {
11726
12046
  // Same as a comment: an element the print drops joins what surrounds it.
11727
12047
  if (
11728
12048
  _isRemovableEmptyElement(A, node) ||
11729
- (_absorbedStyles !== null && _absorbedStyles.has(node))
12049
+ (_absorbed !== null && _absorbed.has(node))
11730
12050
  ) {
11731
12051
  continue;
11732
12052
  }
@@ -11761,7 +12081,13 @@ const _digest = (root) => {
11761
12081
  continue;
11762
12082
  }
11763
12083
  const name = a.serializedName || a.name;
11764
- if (REWRITABLE_ATTRIBUTES.has(a.name) || a.name === "srcdoc") {
12084
+ // A handler joins the two the printer rewrites wholesale: a renderer's
12085
+ // answer is other text for the same behavior, so comparing it says nothing.
12086
+ if (
12087
+ REWRITABLE_ATTRIBUTES.has(a.name) ||
12088
+ a.name === "srcdoc" ||
12089
+ _isEventHandlerAttribute(elementName, a.name)
12090
+ ) {
11765
12091
  attributes.push(`${name}=${_DIGEST_OPAQUE}`);
11766
12092
  continue;
11767
12093
  }
@@ -11945,7 +12271,7 @@ const printer = (path, writer) => {
11945
12271
  // carrying nothing at all.
11946
12272
  if (
11947
12273
  minify &&
11948
- ((_absorbedStyles !== null && _absorbedStyles.has(path.node)) ||
12274
+ ((_absorbed !== null && _absorbed.has(path.node)) ||
11949
12275
  _isRemovableEmptyElement(path, path.node))
11950
12276
  ) {
11951
12277
  return "";
@@ -12052,9 +12378,6 @@ const printer = (path, writer) => {
12052
12378
  // Literal-text elements (`script` / `style` / …) keep their body raw;
12053
12379
  // every other text node is escaped (the WHATWG text split).
12054
12380
  const parent = path.parentOf();
12055
- // TODO minify an inline `<script>` too: terser reaches webpack only
12056
- // through `minimizer-webpack-plugin` and its API is async, so it needs
12057
- // a JS-minify hook on the options rather than a call from here.
12058
12381
  if (parent !== 0 && LITERAL_TEXT_PARENTS.has(path.tagName(parent))) {
12059
12382
  if (!minify) return data;
12060
12383
  const literalName = path.tagName(parent);
@@ -12066,7 +12389,7 @@ const printer = (path, writer) => {
12066
12389
  }
12067
12390
  // The run's first sheet prints the whole run; the rest printed
12068
12391
  // into it here, before their own text or tags are reached.
12069
- return _absorbedStyles !== null && _absorbedStyles.has(parent)
12392
+ return _absorbed !== null && _absorbed.has(parent)
12070
12393
  ? ""
12071
12394
  : _mergedStyleRun(path, parent, data);
12072
12395
  }
@@ -12075,16 +12398,23 @@ const printer = (path, writer) => {
12075
12398
  if (JSON_SCRIPT_TYPES.has(type) || _JSON_SUBTYPE_REGEXP.test(type)) {
12076
12399
  return _minifyInlineJson(data);
12077
12400
  }
12078
- // No built-in: webpack ships no JS minifier, so an inline script is
12079
- // touched only by a caller's renderer.
12080
- if (
12081
- (_renderEmbeddedSource !== undefined ||
12082
- _deferEmbeddedSource !== undefined) &&
12083
- JAVASCRIPT_SCRIPT_TYPES.has(type) &&
12084
- data.trim() !== ""
12085
- ) {
12086
- return _renderEmbedded(data, JAVASCRIPT_TYPE);
12401
+ // A bare `<script>` is the classic one a run may fold into, and
12402
+ // the run's first prints all of it — the rest printed into it here.
12403
+ let body = data;
12404
+ if (_mergeScripts && path.attributeCount(parent) === 0) {
12405
+ if (_absorbed !== null && _absorbed.has(parent)) return "";
12406
+ body = _mergedScriptRun(path, parent, data);
12407
+ }
12408
+ // Webpack ships no JS minifier, so an inline script is touched only
12409
+ // by a caller's renderer; the built-in declines it.
12410
+ if (JAVASCRIPT_SCRIPT_TYPES.has(type) && body.trim() !== "") {
12411
+ return _renderEmbedded(
12412
+ body,
12413
+ JAVASCRIPT_TYPE,
12414
+ type === MODULE_SCRIPT ? MODULE_SCRIPT : CLASSIC_SCRIPT
12415
+ );
12087
12416
  }
12417
+ return body;
12088
12418
  }
12089
12419
  return data;
12090
12420
  }
@@ -12150,7 +12480,7 @@ const printer = (path, writer) => {
12150
12480
  // without changing length — so it is excluded by name.
12151
12481
  if (
12152
12482
  raw.length === data.length &&
12153
- raw.charCodeAt(raw.length - 1) !== 60 &&
12483
+ !_tailFusesWithNextTag(raw) &&
12154
12484
  !(inputHasCr && raw.includes("\r")) &&
12155
12485
  !_hasOpenReference(raw)
12156
12486
  ) {
@@ -12730,16 +13060,6 @@ const grammar = (input, visitors, writer, options) => {
12730
13060
  writer !== undefined && writer.options.removeEmptyAttributes === true;
12731
13061
  _removeEmptyElements =
12732
13062
  writer !== undefined && writer.options.removeEmptyElements === true;
12733
- // With the rest rather than in `printer`: they are the print's, not the
12734
- // node's, and that runs once per node.
12735
- _cssEnvironment =
12736
- writer === undefined ? undefined : writer.options.environment;
12737
- _cssConvertLengthUnits =
12738
- writer !== undefined && writer.options.convertLengthUnits === true;
12739
- _cssRewriteCustomProperties =
12740
- writer !== undefined && writer.options.rewriteCustomProperties === true;
12741
- _cssTransforms =
12742
- writer === undefined ? undefined : writer.options.cssTransforms;
12743
13063
  _transforms = _transformsFrom(
12744
13064
  writer === undefined ? undefined : writer.options.transforms
12745
13065
  );
@@ -12766,9 +13086,10 @@ const grammar = (input, visitors, writer, options) => {
12766
13086
  _sortTokenLists =
12767
13087
  writer !== undefined && writer.options.sortTokenLists === true;
12768
13088
  _mergeStyles = writer !== undefined && writer.options.mergeStyles === true;
13089
+ _mergeScripts = writer !== undefined && writer.options.mergeScripts === true;
12769
13090
  // Node ids are per-parse, so a set kept from the last one would name this
12770
13091
  // one's nodes. Dropped rather than cleared: most documents never fill it.
12771
- _absorbedStyles = null;
13092
+ _absorbed = null;
12772
13093
  // Counted from the parse this call is about to run, so it cannot be kept.
12773
13094
  _attributeFrequencies = null;
12774
13095
  _attributeRanks = null;
@@ -12812,7 +13133,7 @@ const grammar = (input, visitors, writer, options) => {
12812
13133
  : declineDeferredWrites(writer.result(), _deferEmbeddedSource);
12813
13134
  // Both are keyed by node id, which the next parse hands out afresh.
12814
13135
  _emptyElements.clear();
12815
- _absorbedStyles = null;
13136
+ _absorbed = null;
12816
13137
  if (_digest(parseHtml(printed, 0, options)) !== digest) {
12817
13138
  writer.replaceAll(input);
12818
13139
  }
@@ -12830,8 +13151,6 @@ const grammar = (input, visitors, writer, options) => {
12830
13151
  // Keyed by this parse's interned names, so it must not outlive it.
12831
13152
  _attributeFrequencies = null;
12832
13153
  _attributeRanks = null;
12833
- // Keyed by this print's options, and holding slices of its input.
12834
- _styleAttributeCache.clear();
12835
13154
  _emptyElements.clear();
12836
13155
  _streamEligible = false;
12837
13156
  _streaming = false;
@@ -13296,8 +13615,8 @@ const parseMsapplicationTask = (input) => {
13296
13615
  };
13297
13616
 
13298
13617
  // CSS syntax is loaded on first `parseCssUrls` call, not at module load —
13299
- // `HtmlGenerator` deliberately defers it the same way, and most documents
13300
- // never carry a URL-bearing SVG presentation attribute.
13618
+ // `HtmlGenerator` defers it the same way, and most documents carry no
13619
+ // URL-bearing SVG presentation attribute.
13301
13620
  /** @type {typeof import("../css/syntax") | undefined} */
13302
13621
  let _cssSyntax;
13303
13622
 
@@ -13722,7 +14041,22 @@ const A = {
13722
14041
  };
13723
14042
 
13724
14043
  module.exports.A = A;
14044
+ // The `as` a `style=""` is offered under: a block's contents rather than a
14045
+ // whole stylesheet, which is what gives it a rule block's merges.
14046
+ module.exports.BLOCK_CONTENTS = BLOCK_CONTENTS;
14047
+ // The `as` a classic `<script>` is offered under — the production every
14048
+ // JavaScript engine reads by default.
14049
+ module.exports.CLASSIC_SCRIPT = CLASSIC_SCRIPT;
13725
14050
  module.exports.EMBEDDED_LANGUAGES = EMBEDDED_LANGUAGES;
14051
+ // The `as` an event handler attribute is offered under, read by a renderer
14052
+ // whose engine takes only whole scripts.
14053
+ module.exports.EVENT_HANDLER = EVENT_HANDLER;
14054
+ // Neither a JSON `<script>` body nor an `<svg>` subtree is a module source
14055
+ // type, so both name themselves here.
14056
+ module.exports.JSON_TYPE = JSON_TYPE;
14057
+ // The `as` a `<script type=module>` is offered under: the goal symbol decides
14058
+ // what parses, so a renderer cannot read it off the body.
14059
+ module.exports.MODULE_SCRIPT = MODULE_SCRIPT;
13726
14060
  module.exports.NS_HTML = NS_HTML;
13727
14061
  module.exports.NS_MATHML = NS_MATHML;
13728
14062
  module.exports.NS_SVG = NS_SVG;
@@ -13737,11 +14071,13 @@ module.exports.SourceProcessor = SourceProcessor;
13737
14071
  module.exports.askEmbeddedRenderer = askEmbeddedRenderer;
13738
14072
  module.exports.baseTag = baseTag;
13739
14073
  module.exports.buildHeadTags = buildHeadTags;
14074
+ module.exports.builtinEmbeddedRenderer = builtinEmbeddedRenderer;
13740
14075
  module.exports.collectEmbeddedDiagnostics = collectEmbeddedDiagnostics;
13741
14076
  module.exports.decodeEntities = decodeEntities;
13742
14077
  module.exports.embeddedText = embeddedText;
13743
14078
  module.exports.escapeAttribute = escapeAttribute;
13744
14079
  module.exports.escapeText = escapeText;
14080
+ module.exports.htmlMinify = htmlMinify;
13745
14081
  module.exports.isAsciiWhitespace = isSpace;
13746
14082
  module.exports.metaTag = metaTag;
13747
14083
  // WHATWG "ASCII whitespace" (tab / LF / FF / CR / space) — the tokenizer's
@@ -13753,4 +14089,5 @@ module.exports.parseSrc = parseSrc;
13753
14089
  module.exports.parseSrcset = parseSrcset;
13754
14090
  module.exports.pickTransforms = pickTransforms;
13755
14091
  module.exports.printer = printer;
14092
+ module.exports.stripJsonWhitespace = stripJsonWhitespace;
13756
14093
  module.exports.tokenize = tokenize;