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.
- package/README.md +5 -0
- package/lib/APIPlugin.js +23 -7
- package/lib/AutomaticPrefetchPlugin.js +1 -1
- package/lib/Cache.js +8 -3
- package/lib/CacheFacade.js +1 -1
- package/lib/CircularModulesPlugin.js +157 -55
- package/lib/CleanPlugin.js +2 -2
- package/lib/Compilation.js +320 -302
- package/lib/Compiler.js +209 -46
- package/lib/ContextModule.js +17 -81
- package/lib/ContextModuleFactory.js +1 -1
- package/lib/CopyPlugin.js +1054 -0
- package/lib/DefinePlugin.js +24 -8
- package/lib/ExternalModule.js +41 -14
- package/lib/FileSystemInfo.js +17 -14
- package/lib/FlagDependencyExportsPlugin.js +45 -21
- package/lib/HotModuleReplacementPlugin.js +53 -7
- package/lib/JavascriptMetaInfoPlugin.js +5 -3
- package/lib/MainTemplate.js +5 -1
- package/lib/Module.js +16 -7
- package/lib/MultiCompiler.js +1 -1
- package/lib/MultiWatching.js +1 -1
- package/lib/NormalModule.js +45 -12
- package/lib/NormalModuleFactory.js +1 -1
- package/lib/RuntimeGlobals.js +21 -7
- package/lib/RuntimeModule.js +28 -12
- package/lib/RuntimePlugin.js +30 -3
- package/lib/RuntimeTemplate.js +780 -475
- package/lib/SourceMapDevToolPlugin.js +1 -1
- package/lib/Watching.js +9 -0
- package/lib/WebpackOptionsApply.js +84 -91
- package/lib/asset/AssetGenerator.js +25 -8
- package/lib/asset/AssetModule.js +3 -0
- package/lib/asset/WebManifestParser.js +7 -5
- package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
- package/lib/cache/IdleFileCachePlugin.js +2 -2
- package/lib/cache/PackFileCacheStrategy.js +14 -1
- package/lib/config/browserslistTargetHandler.js +19 -0
- package/lib/config/defaults.js +86 -50
- package/lib/config/normalization.js +82 -12
- package/lib/config/target.js +10 -0
- package/lib/container/ContainerReferencePlugin.js +6 -0
- package/lib/container/RemoteRuntimeModule.js +9 -0
- package/lib/container/declaredRemotes.js +39 -0
- package/lib/css/CssGenerator.js +8 -0
- package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
- package/lib/css/CssLoadingRuntimeModule.js +94 -36
- package/lib/css/CssModule.js +1 -1
- package/lib/css/CssModulesPlugin.js +7 -6
- package/lib/css/CssParser.js +144 -11
- package/lib/css/CssServerStylesRuntimeModule.js +9 -0
- package/lib/css/cssMinify.js +11 -3
- package/lib/css/data.js +2814 -678
- package/lib/css/syntax.js +4082 -248
- package/lib/debug/ProfilingPlugin.js +4 -0
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
- package/lib/dependencies/AMDRuntimeModules.js +18 -0
- package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
- package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
- package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
- package/lib/dependencies/CommonJsPlugin.js +19 -3
- package/lib/dependencies/CommonJsRequireDependency.js +14 -5
- package/lib/dependencies/CssIcssExportDependency.js +7 -1
- package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
- package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +71 -13
- package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
- package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
- package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
- package/lib/dependencies/HarmonyImportDependency.js +6 -1
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +8 -1
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
- package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
- package/lib/dependencies/HtmlEntryDependency.js +50 -0
- package/lib/dependencies/ImportMetaMainDependency.js +104 -0
- package/lib/dependencies/ImportMetaPlugin.js +59 -15
- package/lib/dependencies/SystemRuntimeModule.js +9 -0
- package/lib/dependencies/WorkerDependency.js +1 -2
- package/lib/dependencies/WorkletDependency.js +1 -2
- package/lib/dll/DelegatedModule.js +18 -1
- package/lib/dll/DllReferencePlugin.js +11 -8
- package/lib/dll/LibManifestPlugin.js +1 -1
- package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
- package/lib/errors/DuplicateModulesWarning.js +12 -7
- package/lib/errors/EmptyCopyPatternWarning.js +26 -0
- package/lib/errors/ExternalStarReexportError.js +44 -0
- package/lib/errors/MissingSourceMapsWarning.js +36 -0
- package/lib/errors/ModuleParseError.js +2 -1
- package/lib/errors/UnusedAssetsWarning.js +36 -0
- package/lib/errors/UnusedFederationWarning.js +35 -0
- package/lib/errors/UnusedModulesWarning.js +38 -0
- package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
- package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
- package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
- package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
- package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
- package/lib/html/HtmlGenerator.js +11 -5
- package/lib/html/HtmlModulesPlugin.js +331 -62
- package/lib/html/HtmlParser.js +13 -6
- package/lib/html/builtinEmbeddedRenderer.js +107 -0
- package/lib/html/data.js +121 -7
- package/lib/html/htmlMinify.js +84 -113
- package/lib/html/syntax.js +763 -426
- package/lib/ids/HashedModuleIdsPlugin.js +2 -1
- package/lib/index.js +3 -0
- package/lib/javascript/JavascriptModule.js +1 -0
- package/lib/javascript/JavascriptModulesPlugin.js +52 -24
- package/lib/javascript/JavascriptParser.js +1255 -728
- package/lib/javascript/StartupHelpers.js +27 -3
- package/lib/javascript/data.js +172 -0
- package/lib/javascript/grammar.js +5546 -0
- package/lib/javascript/parser.js +1494 -0
- package/lib/javascript/regexp.js +1762 -0
- package/lib/javascript/regexpData.js +51 -0
- package/lib/javascript/syntax.js +8696 -5225
- package/lib/library/ModuleLibraryPlugin.js +116 -5
- package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
- package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
- package/lib/optimize/ConcatenatedModule.js +97 -20
- package/lib/optimize/ConstExportsPlugin.js +50 -39
- package/lib/optimize/InlineExports.js +20 -123
- package/lib/optimize/MangleExportsPlugin.js +10 -0
- package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
- package/lib/optimize/RealContentHashPlugin.js +68 -9
- package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
- package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
- package/lib/performance/CacheEffectivenessPlugin.js +4 -3
- package/lib/performance/DuplicateModulesPlugin.js +57 -13
- package/lib/performance/EvalUsagePlugin.js +5 -2
- package/lib/performance/MissingSourceMapsPlugin.js +115 -0
- package/lib/performance/PureAnnotationsPlugin.js +6 -3
- package/lib/performance/TopLevelThisPlugin.js +5 -4
- package/lib/performance/UnusedAssetsPlugin.js +109 -0
- package/lib/performance/UnusedFederationPlugin.js +147 -0
- package/lib/performance/UnusedModulesPlugin.js +141 -0
- package/lib/performance/UnusedReexportsPlugin.js +1 -55
- package/lib/performance/isOnlyReexported.js +65 -0
- package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
- package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
- package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
- package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
- package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
- package/lib/prefetch/ResourceHintPlugin.js +1 -2
- package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
- package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
- package/lib/rules/RuleSetCompiler.js +211 -4
- package/lib/runtime/AsyncModuleRuntimeModule.js +100 -66
- package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
- package/lib/runtime/BaseUriRuntimeModule.js +9 -0
- package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
- package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
- package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
- package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
- package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
- package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
- package/lib/runtime/GlobalRuntimeModule.js +9 -0
- package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
- package/lib/runtime/HelperRuntimeModule.js +10 -0
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +330 -219
- package/lib/runtime/NonceRuntimeModule.js +9 -0
- package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
- package/lib/runtime/PublicPathRuntimeModule.js +9 -0
- package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
- package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
- package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
- package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
- package/lib/runtime/SystemContextRuntimeModule.js +9 -0
- package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
- package/lib/serialization/ObjectMiddleware.js +138 -106
- package/lib/sharing/ConsumeSharedPlugin.js +12 -0
- package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
- package/lib/sharing/ShareRuntimeModule.js +9 -0
- package/lib/sharing/declaredShared.js +47 -0
- package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
- package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
- package/lib/util/SourceProcessor.js +76 -69
- package/lib/util/async.js +292 -0
- package/lib/util/buildDiagnostics.js +69 -0
- package/lib/util/fs.js +27 -1
- package/lib/util/handlerKeys.js +40 -0
- package/lib/util/identifier.js +20 -0
- package/lib/util/internalSerializables.js +4 -0
- package/lib/util/registerExternalSerializer.js +6 -45
- package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
- package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
- package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
- package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
- package/package.json +22 -16
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +379 -66
- package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
- package/schemas/plugins/ManifestPlugin.check.js +1 -1
- package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
- package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
- package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
- package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
- package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
- package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
- package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
- package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
- package/types.d.ts +1414 -314
- package/lib/dependencies/ExportBindingInitFragment.js +0 -191
- package/lib/errors/EntrypointOverlapWarning.js +0 -45
- package/lib/performance/EntrypointOverlapPlugin.js +0 -122
package/lib/html/syntax.js
CHANGED
|
@@ -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,
|
|
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
|
-
//
|
|
157
|
-
// `tooling/
|
|
158
|
-
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
|
|
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)
|
|
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
|
|
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.
|
|
8947
|
-
* @property {EmbeddedSourceRenderer=} renderEmbeddedSource renders each nested body this document embeds — an inline `<style>`, every `style=""` (
|
|
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
|
-
*
|
|
8953
|
-
*
|
|
8954
|
-
*
|
|
8955
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
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, """)}"`;
|
|
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 `
|
|
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
|
|
9513
|
-
//
|
|
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
|
|
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
|
|
9532
|
-
*
|
|
9533
|
-
*
|
|
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 =
|
|
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`
|
|
9582
|
-
*
|
|
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(
|
|
9590
|
-
|
|
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
|
-
//
|
|
9648
|
-
|
|
9649
|
-
|
|
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
|
|
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
|
-
*
|
|
9798
|
-
*
|
|
9799
|
-
*
|
|
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
|
|
9898
|
+
* @returns {string} the rendered text, the marker standing for it, or the text as written
|
|
9865
9899
|
*/
|
|
9866
|
-
const
|
|
9867
|
-
|
|
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 <
|
|
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
|
-
*
|
|
9923
|
-
*
|
|
9924
|
-
*
|
|
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
|
|
9961
|
+
* @returns {string} the rendered declarations, or the value as written
|
|
9927
9962
|
*/
|
|
9928
9963
|
const _minifyStyleAttribute = (raw) => {
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
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
|
-
|
|
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
|
|
10193
|
-
*
|
|
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}
|
|
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,
|
|
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
|
|
10227
|
-
// in place and only a list that
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
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,
|
|
10262
|
-
*
|
|
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
|
-
* @
|
|
10265
|
-
* @returns {string} the ordered list
|
|
10296
|
+
* @returns {string} the ordered set
|
|
10266
10297
|
*/
|
|
10267
|
-
const _sortedTokenList = (collapsed
|
|
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
|
-
|
|
10392
|
-
|
|
10393
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
10469
|
+
// The value the spec matches is the one the parser read, so a reference
|
|
10470
|
+
// is decoded first: `text/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
|
-
*
|
|
10459
|
-
*
|
|
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
|
|
10499
|
+
* @returns {string} the rendered body, the marker standing for it, or the body as written
|
|
10465
10500
|
*/
|
|
10466
|
-
const _minifyInlineJson = (json) =>
|
|
10467
|
-
|
|
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
|
|
10539
|
-
*
|
|
10540
|
-
* @param {HtmlElement} 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
|
|
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
|
-
|
|
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
|
-
*
|
|
10612
|
-
*
|
|
10613
|
-
*
|
|
10614
|
-
*
|
|
10615
|
-
|
|
10616
|
-
|
|
10617
|
-
|
|
10618
|
-
|
|
10619
|
-
|
|
10620
|
-
|
|
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
|
-
|
|
10628
|
-
if (
|
|
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
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
|
|
10640
|
-
if (
|
|
10641
|
-
|
|
10642
|
-
|
|
10643
|
-
|
|
10644
|
-
|
|
10645
|
-
|
|
10646
|
-
|
|
10647
|
-
|
|
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
|
-
|
|
10940
|
-
|
|
10941
|
-
|
|
10942
|
-
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
|
|
10947
|
-
|
|
10948
|
-
|
|
10949
|
-
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
10964
|
-
|
|
10965
|
-
|
|
10966
|
-
|
|
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
|
-
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
|
|
10980
|
-
|
|
10981
|
-
|
|
10982
|
-
|
|
10983
|
-
|
|
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
|
-
(
|
|
11236
|
+
(value === "" ||
|
|
11016
11237
|
(html &&
|
|
11017
11238
|
_transforms.collapseBooleanAttributes &&
|
|
11018
|
-
|
|
11019
|
-
|
|
11020
|
-
|
|
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(
|
|
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 — `&&`
|
|
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
|
-
|
|
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
|
-
((
|
|
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
|
-
(
|
|
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
|
-
|
|
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
|
-
((
|
|
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
|
|
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
|
-
//
|
|
12079
|
-
//
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12085
|
-
|
|
12086
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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`
|
|
13300
|
-
//
|
|
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;
|