webpack 5.112.0 → 5.112.1
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/bin/webpack.js +13 -7
- package/lib/Compilation.js +152 -60
- package/lib/Compiler.js +12 -25
- package/lib/asset/AssetBytesGenerator.js +14 -6
- package/lib/asset/AssetBytesParser.js +10 -8
- package/lib/asset/AssetGenerator.js +36 -48
- package/lib/asset/AssetModule.js +11 -0
- package/lib/asset/AssetModulesPlugin.js +5 -4
- package/lib/asset/AssetParser.js +8 -8
- package/lib/asset/AssetSourceGenerator.js +16 -8
- package/lib/asset/AssetSourceParser.js +10 -8
- package/lib/asset/WebManifestGenerator.js +11 -6
- package/lib/asset/WebManifestParser.js +3 -3
- package/lib/async-modules/AsyncModuleHelpers.js +8 -2
- package/lib/async-modules/InferAsyncModulesPlugin.js +7 -2
- package/lib/cache/CacheFacade.js +1 -1
- package/lib/cache/PackFileCacheStrategy.js +6 -10
- package/lib/cache/ResolverCachePlugin.js +58 -8
- package/lib/config/WebpackOptionsApply.js +8 -28
- package/lib/config/cli.js +9 -6
- package/lib/config/defaults.js +24 -13
- package/lib/config/getClaimedAssetTypes.js +2 -2
- package/lib/config/target.js +1 -1
- package/lib/context/ContextModule.js +1 -1
- package/lib/context/ContextModuleFactory.js +1 -1
- package/lib/context/ContextReplacementPlugin.js +3 -9
- package/lib/css/CssGenerator.js +40 -37
- package/lib/css/CssModule.js +10 -0
- package/lib/css/CssModulesPlugin.js +2 -2
- package/lib/css/CssParser.js +33 -32
- package/lib/css/conventions.js +1 -1
- package/lib/css/data.js +224 -219
- package/lib/css/syntax-parser.js +1159 -298
- package/lib/css/syntax-printer.js +90 -35
- package/lib/debug/ProfilingPlugin.js +65 -43
- package/lib/define/DefinePlugin.js +10 -15
- package/lib/define/DotenvPlugin.js +10 -6
- package/lib/define/EnvironmentPlugin.js +4 -2
- package/lib/dependencies/amd/AMDDefineDependencyParserPlugin.js +1 -2
- package/lib/dependencies/amd/AMDRequireDependenciesBlockParserPlugin.js +4 -1
- package/lib/dependencies/commonjs/CommonJsExportRequireDependency.js +1 -4
- package/lib/dependencies/commonjs/CommonJsExportsParserPlugin.js +18 -33
- package/lib/dependencies/commonjs/CommonJsImportsParserPlugin.js +1 -3
- package/lib/dependencies/commonjs/CommonJsObjectExportDependency.js +4 -4
- package/lib/dependencies/commonjs/CommonJsPlugin.js +2 -5
- package/lib/dependencies/commonjs/RequireEnsureDependenciesBlockParserPlugin.js +4 -1
- package/lib/dependencies/context/ImportMetaContextDependencyParserPlugin.js +1 -2
- package/lib/dependencies/context/ImportMetaGlobDependencyParserPlugin.js +4 -7
- package/lib/dependencies/context/ImportMetaGlobHelpers.js +8 -10
- package/lib/dependencies/core/CachedConstDependency.js +9 -6
- package/lib/dependencies/css/CssIcssExportDependency.js +6 -7
- package/lib/dependencies/css/CssIcssImportDependency.js +1 -3
- package/lib/dependencies/css/CssUrlDependency.js +2 -6
- package/lib/dependencies/esm/ESMDetectionParserPlugin.js +2 -4
- package/lib/dependencies/esm/ESMExportExpressionDependency.js +2 -2
- package/lib/dependencies/esm/ESMExportImportedSpecifierDependency.js +16 -18
- package/lib/dependencies/esm/ESMExportSpecifierDependency.js +20 -3
- package/lib/dependencies/esm/ESMExports.js +2 -10
- package/lib/dependencies/esm/ESMImportDependency.js +17 -2
- package/lib/dependencies/esm/ESMImportDependencyParserPlugin.js +6 -17
- package/lib/dependencies/esm/ESMImportGuard.js +11 -23
- package/lib/dependencies/esm/ESMImportSideEffectDependency.js +1 -1
- package/lib/dependencies/esm/ESMImportSpecifierDependency.js +4 -1
- package/lib/dependencies/esm/ESMLiveExportDependency.js +311 -0
- package/lib/dependencies/esm/ESMLiveExportParserPlugin.js +862 -0
- package/lib/dependencies/esm/ESMModulesPlugin.js +1 -3
- package/lib/dependencies/esm/TopLevelAwaitDependency.js +1 -8
- package/lib/dependencies/helpers/DynamicExports.js +4 -6
- package/lib/dependencies/html/HtmlEntryDependency.js +5 -14
- package/lib/dependencies/html/HtmlInlineHtmlDependency.js +1 -4
- package/lib/dependencies/html/HtmlInlineScriptDependency.js +2 -6
- package/lib/dependencies/html/HtmlInlineStyleDependency.js +1 -4
- package/lib/dependencies/import/ImportParserPlugin.js +3 -6
- package/lib/dependencies/import-meta/ImportMetaPlugin.js +4 -6
- package/lib/dependencies/url/URLParserPlugin.js +1 -1
- package/lib/dependencies/worker/WorkerAndWorkletPlugin.js +51 -20
- package/lib/devtool/ModuleFilenameHelpers.js +1 -1
- package/lib/devtool/SourceMapDevToolPlugin.js +1 -1
- package/lib/dll/DelegatedModule.js +3 -3
- package/lib/dll/DllModule.js +3 -1
- package/lib/dll/DllReferencePlugin.js +1 -4
- package/lib/errors/AbstractMethodError.js +1 -1
- package/lib/errors/ErrorHelpers.js +2 -1
- package/lib/errors/HookWebpackError.js +2 -1
- package/lib/errors/JSONParseError.js +4 -4
- package/lib/errors/WebpackError.js +3 -2
- package/lib/esm/ModuleChunkFormatPlugin.js +36 -1
- package/lib/externals/ExternalModule.js +12 -9
- package/lib/externals/ExternalModuleFactoryPlugin.js +1 -2
- package/lib/externals/ExternalsPlugin.js +1 -1
- package/lib/fs/FileSystemInfo.js +4 -4
- package/lib/graph/AsyncDependenciesBlock.js +1 -1
- package/lib/graph/ChunkGraph.js +5 -0
- package/lib/graph/Dependency.js +8 -2
- package/lib/graph/ExportsInfo.js +1 -1
- package/lib/graph/ModuleGraph.js +14 -3
- package/lib/graph/buildChunkGraph.js +17 -19
- package/lib/graph/findGraphRoots.js +1 -1
- package/lib/hmr/HotModuleReplacement.runtime.js +10 -9
- package/lib/hmr/HotModuleReplacementPlugin.js +5 -11
- package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +16 -19
- package/lib/hmr/LazyCompilationPlugin.js +1 -7
- package/lib/html/HtmlGenerator.js +25 -17
- package/lib/html/HtmlModule.js +11 -1
- package/lib/html/HtmlModulesPlugin.js +12 -11
- package/lib/html/HtmlParser.js +10 -9
- package/lib/html/builtinEmbeddedRenderer.js +31 -33
- package/lib/html/data.js +42 -21
- package/lib/html/htmlMinify.js +4 -1
- package/lib/html/syntax-parser.js +34 -35
- package/lib/html/syntax-printer.js +2 -3
- package/lib/html/xmlMinify.js +4 -1
- package/lib/ids/HashedModuleIdsPlugin.js +1 -1
- package/lib/index.js +13 -12
- package/lib/javascript/APIPlugin.js +7 -13
- package/lib/javascript/BasicEvaluatedExpression.js +5 -5
- package/lib/javascript/CommonJsChunkFormatPlugin.js +2 -7
- package/lib/javascript/ConstPlugin.js +1 -1
- package/lib/javascript/JavascriptGenerator.js +16 -11
- package/lib/javascript/JavascriptMetaInfoPlugin.js +3 -15
- package/lib/javascript/JavascriptModule.js +10 -0
- package/lib/javascript/JavascriptModulesPlugin.js +2 -4
- package/lib/javascript/JavascriptParser.js +99 -11
- package/lib/javascript/ScopeAnalyzer.js +183 -107
- package/lib/javascript/UseStrictPlugin.js +2 -5
- package/lib/javascript/jsMinify.js +1 -1
- package/lib/javascript/regexp.js +2 -2
- package/lib/javascript/syntax-parser.js +2114 -1506
- package/lib/javascript/syntax-printer-data.js +167 -1
- package/lib/javascript/syntax-printer.js +9554 -2782
- package/lib/json/JsonGenerator.js +15 -7
- package/lib/json/JsonModule.js +11 -0
- package/lib/json/JsonParser.js +7 -6
- package/lib/library/AssignLibraryPlugin.js +1 -1
- package/lib/library/JsonpLibraryPlugin.js +1 -1
- package/lib/library/ModuleLibraryPlugin.js +399 -23
- package/lib/loaders/LoaderRunner.js +76 -38
- package/lib/loaders/loadLoader.js +16 -10
- package/lib/module/Generator.js +17 -9
- package/lib/module/Module.js +2 -2
- package/lib/module/NormalModule.js +7 -5
- package/lib/module/NormalModuleFactory.js +11 -17
- package/lib/module/Parser.js +9 -2
- package/lib/module/extractSourceMap.js +69 -18
- package/lib/module/findCaseMismatch.js +2 -2
- package/lib/node/ExternalModuleInitFragment.js +2 -2
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +4 -12
- package/lib/node/ReadFileCompileWasmPlugin.js +2 -6
- package/lib/node/nodeConsole.js +4 -3
- package/lib/optimize/CircularModulesPlugin.js +1 -1
- package/lib/optimize/ConcatenatedModule.js +2 -6
- package/lib/optimize/FlagDependencyExportsPlugin.js +6 -11
- package/lib/optimize/FlagDependencyUsagePlugin.js +28 -3
- package/lib/optimize/InlineExports.js +4 -7
- package/lib/optimize/LazyBarrels.js +41 -5
- package/lib/optimize/ModuleConcatenationPlugin.js +8 -10
- package/lib/optimize/RealContentHashPlugin.js +2 -6
- package/lib/optimize/SideEffectsFlagPlugin.js +7 -21
- package/lib/optimize/SplitChunksPlugin.js +11 -24
- package/lib/optimize/TupleQueue.js +1 -1
- package/lib/output/CleanPlugin.js +3 -1
- package/lib/output/CopyPlugin.js +3 -4
- package/lib/performance/EvalUsagePlugin.js +1 -3
- package/lib/performance/HotspotsPlugin.js +33 -9
- package/lib/performance/PureAnnotationsPlugin.js +16 -10
- package/lib/performance/TopLevelThisPlugin.js +17 -9
- package/lib/prefetch/ResourceHintPlugin.js +1 -1
- package/lib/provide/ProvidedDependency.js +36 -4
- package/lib/rules/BasicEffectRulePlugin.js +1 -1
- package/lib/rules/RuleSetCompiler.js +15 -5
- package/lib/rules/UseEffectRulePlugin.js +1 -3
- package/lib/runtime/AsyncModuleRuntimeModule.js +7 -1
- package/lib/runtime/GetChunkFilenameRuntimeModule.js +1 -5
- package/lib/runtime/RuntimeGlobals.js +6 -0
- package/lib/runtime/RuntimePlugin.js +2 -0
- package/lib/schemes/HttpUriPlugin.js +1 -2
- package/lib/schemes/VirtualUrlPlugin.js +3 -1
- package/lib/serialization/AggregateErrorSerializer.js +3 -3
- package/lib/serialization/BinaryMiddleware.js +4 -1
- package/lib/serialization/ErrorObjectSerializer.js +2 -5
- package/lib/serialization/ObjectMiddleware.js +17 -15
- package/lib/serialization/PlainObjectSerializer.js +3 -7
- package/lib/serialization/Serializer.js +21 -11
- package/lib/serialization/SerializerMiddleware.js +8 -6
- package/lib/stats/DefaultStatsFactoryPlugin.js +35 -35
- package/lib/stats/DefaultStatsPresetPlugin.js +2 -6
- package/lib/stats/DefaultStatsPrinterPlugin.js +12 -11
- package/lib/stats/StatsFactory.js +194 -24
- package/lib/stats/StatsPrinter.js +126 -13
- package/lib/template/DependencyTemplate.js +1 -1
- package/lib/template/RuntimeTemplate.js +13 -32
- package/lib/template/Template.js +1 -1
- package/lib/util/SourceProcessor.js +98 -15
- package/lib/util/WeakTupleMap.js +10 -4
- package/lib/util/cleverMerge.js +61 -33
- package/lib/util/comparators.js +9 -5
- package/lib/util/dataURL.js +2 -0
- package/lib/util/deprecation.js +4 -3
- package/lib/util/globUtils.js +1 -4
- package/lib/util/internalSerializables.js +2 -0
- package/lib/util/makeSerializable.js +6 -4
- package/lib/util/memoize.js +1 -1
- package/lib/util/parseJson.js +2 -2
- package/lib/util/serialization.js +31 -27
- package/lib/wasm/AsyncWasmModule.js +12 -2
- package/lib/wasm/AsyncWebAssemblyGenerator.js +12 -4
- package/lib/wasm/AsyncWebAssemblyJavascriptGenerator.js +13 -5
- package/lib/wasm/AsyncWebAssemblyParser.js +7 -5
- package/lib/wasm/UniversalCompileAsyncWasmPlugin.js +2 -6
- package/lib/wasm-sync/SyncWasmModule.js +16 -1
- package/lib/wasm-sync/WebAssemblyGenerator.js +15 -10
- package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +13 -5
- package/lib/wasm-sync/WebAssemblyParser.js +10 -12
- package/lib/web/FetchCompileAsyncWasmPlugin.js +4 -12
- package/lib/web/FetchCompileWasmPlugin.js +2 -6
- package/package.json +16 -18
- package/schemas/WebpackOptions.check.js +3 -3
- package/schemas/WebpackOptions.json +2 -2
- package/schemas/plugins/BannerPlugin.check.js +3 -3
- package/schemas/plugins/HtmlGeneratorOptions.check.js +3 -3
- package/schemas/plugins/HtmlParserOptions.check.js +3 -3
- package/schemas/plugins/IgnorePlugin.check.js +3 -3
- package/schemas/plugins/LoaderOptionsPlugin.check.js +3 -3
- package/schemas/plugins/ManifestPlugin.check.js +3 -3
- package/schemas/plugins/ProgressPlugin.check.js +3 -3
- package/schemas/plugins/SSRManifestPlugin.check.js +3 -3
- package/schemas/plugins/SourceMapDevToolPlugin.check.js +3 -3
- package/schemas/plugins/WatchIgnorePlugin.check.js +3 -3
- package/schemas/plugins/asset/AssetGeneratorOptions.check.js +3 -3
- package/schemas/plugins/asset/AssetInlineGeneratorOptions.check.js +3 -3
- package/schemas/plugins/asset/AssetParserOptions.check.js +3 -3
- package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +3 -3
- package/schemas/plugins/container/ContainerPlugin.check.js +3 -3
- package/schemas/plugins/container/ContainerReferencePlugin.check.js +3 -3
- package/schemas/plugins/container/ExternalsType.check.js +3 -3
- package/schemas/plugins/container/ModuleFederationPlugin.check.js +3 -3
- package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +3 -3
- package/schemas/plugins/css/CssGeneratorOptions.check.js +3 -3
- package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +3 -3
- package/schemas/plugins/css/CssModuleParserOptions.check.js +3 -3
- package/schemas/plugins/css/CssParserOptions.check.js +3 -3
- package/schemas/plugins/debug/ProfilingPlugin.check.js +3 -3
- package/schemas/plugins/define/DotenvPluginOptions.check.js +7 -0
- package/schemas/plugins/define/DotenvPluginOptions.json +3 -0
- package/schemas/plugins/dll/DllPlugin.check.js +3 -3
- package/schemas/plugins/dll/DllReferencePlugin.check.js +3 -3
- package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +3 -3
- package/schemas/plugins/ids/OccurrenceChunkIdsPlugin.check.js +3 -3
- package/schemas/plugins/ids/OccurrenceModuleIdsPlugin.check.js +3 -3
- package/schemas/plugins/json/JsonModulesPluginGenerator.check.js +3 -3
- package/schemas/plugins/json/JsonModulesPluginParser.check.js +3 -3
- package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.js +3 -3
- package/schemas/plugins/optimize/LimitChunkCountPlugin.check.js +3 -3
- package/schemas/plugins/optimize/MergeDuplicateChunksPlugin.check.js +3 -3
- package/schemas/plugins/optimize/MinChunkSizePlugin.check.js +3 -3
- package/schemas/plugins/output/CleanOptions.check.js +7 -0
- package/schemas/plugins/output/CleanOptions.json +3 -0
- package/schemas/plugins/schemes/HttpUriPlugin.check.js +3 -3
- package/schemas/plugins/schemes/VirtualUrlPlugin.check.js +3 -3
- package/schemas/plugins/sharing/ConsumeSharedPlugin.check.js +3 -3
- package/schemas/plugins/sharing/ProvideSharedPlugin.check.js +3 -3
- package/schemas/plugins/sharing/SharePlugin.check.js +3 -3
- package/types.d.ts +1482 -358
package/lib/css/syntax-parser.js
CHANGED
|
@@ -285,6 +285,8 @@ const CC_LOW_LINE = "_".charCodeAt(0);
|
|
|
285
285
|
const CC_LOWER_A = "a".charCodeAt(0);
|
|
286
286
|
const CC_LOWER_D = "d".charCodeAt(0);
|
|
287
287
|
const CC_LOWER_F = "f".charCodeAt(0);
|
|
288
|
+
const CC_LOWER_I = "i".charCodeAt(0);
|
|
289
|
+
const CC_LOWER_S = "s".charCodeAt(0);
|
|
288
290
|
const CC_LOWER_E = "e".charCodeAt(0);
|
|
289
291
|
const CC_LOWER_U = "u".charCodeAt(0);
|
|
290
292
|
const CC_LOWER_R = "r".charCodeAt(0);
|
|
@@ -1790,13 +1792,13 @@ const _NO_SKIP_TYPES = new Uint8Array(32);
|
|
|
1790
1792
|
// rules, the common case. Every consumer reads these lists read-only, so one
|
|
1791
1793
|
// instance replaces an empty array per rule, and freezing makes a push fail.
|
|
1792
1794
|
const _EMPTY_LIST = /** @type {Rule[]} */ (
|
|
1793
|
-
/** @type {
|
|
1795
|
+
/** @type {Rule[] | ReadonlyArray<never>} */ (Object.freeze([]))
|
|
1794
1796
|
);
|
|
1795
1797
|
// `consumeABlock`'s and `consumeABlocksContentsInto`'s results, written instead
|
|
1796
1798
|
// of returned — see there. Read them immediately; the next block overwrites them.
|
|
1797
1799
|
/** @type {Declaration[]} */
|
|
1798
1800
|
let _blockDecls = /** @type {Declaration[]} */ (
|
|
1799
|
-
/** @type {
|
|
1801
|
+
/** @type {Declaration[] | Rule[]} */ (_EMPTY_LIST)
|
|
1800
1802
|
);
|
|
1801
1803
|
/** @type {Rule[]} */
|
|
1802
1804
|
let _blockRules = _EMPTY_LIST;
|
|
@@ -1804,7 +1806,7 @@ let _blockStart = 0;
|
|
|
1804
1806
|
let _blockEnd = 0;
|
|
1805
1807
|
/** @type {Declaration[]} */
|
|
1806
1808
|
let _bcDecls = /** @type {Declaration[]} */ (
|
|
1807
|
-
/** @type {
|
|
1809
|
+
/** @type {Declaration[] | Rule[]} */ (_EMPTY_LIST)
|
|
1808
1810
|
);
|
|
1809
1811
|
/** @type {Rule[]} */
|
|
1810
1812
|
let _bcRules = _EMPTY_LIST;
|
|
@@ -1888,7 +1890,9 @@ let _declBodies = [];
|
|
|
1888
1890
|
/** @type {Node[][]} */
|
|
1889
1891
|
let _ruleBodies = [];
|
|
1890
1892
|
|
|
1891
|
-
let _locConverter = /** @type {LocConverter} */ (
|
|
1893
|
+
let _locConverter = /** @type {LocConverter} */ (
|
|
1894
|
+
/** @type {LocConverter | null} */ (null)
|
|
1895
|
+
);
|
|
1892
1896
|
// The caller's input before §3.3 replaced its NULs, the same length, which
|
|
1893
1897
|
// `A.source` slices so a node reads exactly as written.
|
|
1894
1898
|
let _originalInput = "";
|
|
@@ -1896,9 +1900,10 @@ let _originalInput = "";
|
|
|
1896
1900
|
// Node refs are integers here but typed `Node` across the parser; these are
|
|
1897
1901
|
// identity casts that just satisfy the type system at the boundary.
|
|
1898
1902
|
/** @type {(n: Node) => number} */
|
|
1899
|
-
const _nodeIndex = (n) =>
|
|
1903
|
+
const _nodeIndex = (n) =>
|
|
1904
|
+
/** @type {number} */ (/** @type {number | Node} */ (n));
|
|
1900
1905
|
/** @type {(i: number) => Node} */
|
|
1901
|
-
const _nodeRef = (i) => /** @type {Node} */ (/** @type {
|
|
1906
|
+
const _nodeRef = (i) => /** @type {Node} */ (/** @type {Node | number} */ (i));
|
|
1902
1907
|
|
|
1903
1908
|
/** @param {number} need minimum capacity */
|
|
1904
1909
|
const _grow = (need) => {
|
|
@@ -2105,6 +2110,16 @@ const _setValue = (r, list) => {
|
|
|
2105
2110
|
}
|
|
2106
2111
|
_listPool.push(list);
|
|
2107
2112
|
};
|
|
2113
|
+
/**
|
|
2114
|
+
* Empties the body arrays between top-level nodes by popping: `length = 0`
|
|
2115
|
+
* drops the backing store, so the next rule's first push reallocates it.
|
|
2116
|
+
*/
|
|
2117
|
+
const _dropBodies = () => {
|
|
2118
|
+
for (let k = _declBodies.length; k > 0; k--) {
|
|
2119
|
+
_declBodies.pop();
|
|
2120
|
+
_ruleBodies.pop();
|
|
2121
|
+
}
|
|
2122
|
+
};
|
|
2108
2123
|
/** @type {(r: Node, decls: Node[], childRules: Node[]) => void} */
|
|
2109
2124
|
const _setBody = (r, decls, childRules) => {
|
|
2110
2125
|
_bodyIdx[_nodeIndex(r)] = _declBodies.length + 1;
|
|
@@ -2583,7 +2598,7 @@ const normalizeIntoTokenStream = (input, pos, onComment) => {
|
|
|
2583
2598
|
// Shared frozen empty list for a block body with no declarations / child rules,
|
|
2584
2599
|
// so equal-empty reads return one reference (mirrors `_EMPTY_LIST`).
|
|
2585
2600
|
const _READER_EMPTY = /** @type {Rule[]} */ (
|
|
2586
|
-
/** @type {
|
|
2601
|
+
/** @type {Rule[] | ReadonlyArray<never>} */ (Object.freeze([]))
|
|
2587
2602
|
);
|
|
2588
2603
|
|
|
2589
2604
|
/**
|
|
@@ -2651,7 +2666,7 @@ const _readRefList = (store, list) => {
|
|
|
2651
2666
|
// that reader's `_store` snapshot by `_i`. Created once rather than per store,
|
|
2652
2667
|
// so all readers share one hidden map and stay monomorphic across parses.
|
|
2653
2668
|
const NODE_READER_PROTO = /** @type {NodeReader} */ ({
|
|
2654
|
-
_store: /** @type {NodeStore} */ (/** @type {
|
|
2669
|
+
_store: /** @type {NodeStore} */ (/** @type {NodeStore | null} */ (null)),
|
|
2655
2670
|
_i: 0,
|
|
2656
2671
|
get type() {
|
|
2657
2672
|
return this._store.types[this._i];
|
|
@@ -2880,7 +2895,9 @@ const _finishStore = () => {
|
|
|
2880
2895
|
_ruleBodies = [];
|
|
2881
2896
|
_listPool.length = 0;
|
|
2882
2897
|
_S._input = "";
|
|
2883
|
-
_locConverter = /** @type {LocConverter} */ (
|
|
2898
|
+
_locConverter = /** @type {LocConverter} */ (
|
|
2899
|
+
/** @type {LocConverter | null} */ (null)
|
|
2900
|
+
);
|
|
2884
2901
|
return store;
|
|
2885
2902
|
};
|
|
2886
2903
|
|
|
@@ -3271,8 +3288,8 @@ const consumeAQualifiedRule = (ts, stopToken, nested = false) => {
|
|
|
3271
3288
|
// two non-whitespace tokens the `--foo: {` disambiguation below needs.
|
|
3272
3289
|
const skip = _skipSelectorPrelude;
|
|
3273
3290
|
// Non-skip: first two non-whitespace prelude nodes (computed at the `{`).
|
|
3274
|
-
let first = /** @type {Node} */ (/** @type {
|
|
3275
|
-
let second = /** @type {Node} */ (/** @type {
|
|
3291
|
+
let first = /** @type {Node} */ (/** @type {Node | number} */ (0));
|
|
3292
|
+
let second = /** @type {Node} */ (/** @type {Node | number} */ (0));
|
|
3276
3293
|
// Skip mode: the same two tokens tracked by token type + start, so a dropped
|
|
3277
3294
|
// leaf selector token needs no materialized node just for the disambiguation.
|
|
3278
3295
|
// `0` (no token type) = unset.
|
|
@@ -4445,7 +4462,7 @@ const TOP_LEVEL_CONSUMERS = {
|
|
|
4445
4462
|
* @property {boolean=} convertLengthUnits rewrite a length into a shorter unit it is exactly equal in (`16px` -> `1pc`); off by default because it earns nothing once the asset is compressed, and only read while printing. A time is always rewritten
|
|
4446
4463
|
* @property {boolean=} convertApproximateColors write a polar or Lab color as the nearest hex even where that hex only approximates it: a channel too near a `.5` boundary for two engines to round it alike, and a color outside the sRGB gamut, which hex can only clip. Off by default, and only read while printing; a space engines read through transfers of their own (`a98-rgb`, `prophoto-rgb`) is left alone either way
|
|
4447
4464
|
* @property {boolean=} mergeDistantRules give a rule the selectors of a later one printing the same block, and an at-rule the block of a later one stating the same condition, past the rules between them; off by default, since it reorders the cascade and is sound only where nothing between declares what the block being moved does for an element it can match — a condition between counting for what its own rules declare
|
|
4448
|
-
* @property {boolean=} dropOverriddenDeclarations drop a declaration a later one in the same block overrides even where
|
|
4465
|
+
* @property {boolean=} dropOverriddenDeclarations drop a declaration a later one in the same block overrides even where no target is selected, wherever Chromium, Gecko and WebKit each read the later value; off by default, and only read while printing. With a `browserslist` selection the drop is already made wherever every browser it names is known to read the later value, so this widens the case where no target is selected — a selection naming a browser the tables do not cover still answers for the whole of it
|
|
4449
4466
|
* @property {boolean=} rewriteCustomProperties shorten a custom property's value the way any other value is shortened (`--x:#ffffff` -> `#fff`); off by default because `getPropertyValue()` hands that text back, and only read while printing. What it may rewrite is what any other value's tokens may be, a color in a substitution's fallback included — that being the property's value rather than the function's own argument
|
|
4450
4467
|
* @property {EmbeddedSourceRenderer=} renderEmbeddedSource renders source this stylesheet embeds: the payload of a `url()` `data:` URL whose media type names a language webpack knows (SVG, CSS, HTML, JSON, JavaScript). Absent, a data URL is emitted exactly as written
|
|
4451
4468
|
* @property {{ [name: string]: string }=} pseudoClasses each pseudo-class to write as a class instead (`{ "focus-visible": "focus-visible" }`), so a script can apply it where the engine does not. Only read while printing
|
|
@@ -4475,8 +4492,38 @@ const TOP_LEVEL_CONSUMERS = {
|
|
|
4475
4492
|
// recursive call sites monomorphic and allocates no closure per parse.
|
|
4476
4493
|
/** @typedef {import("../util/SourceProcessor").CompiledVisitorBucket<CssPath>} CompiledVisitorBucket */
|
|
4477
4494
|
/** @type {CompiledVisitorMap} */
|
|
4478
|
-
let _visitors = /** @type {CompiledVisitorMap} */ (
|
|
4495
|
+
let _visitors = /** @type {CompiledVisitorMap} */ (
|
|
4496
|
+
/** @type {CompiledVisitorMap | never[]} */ ([])
|
|
4497
|
+
);
|
|
4479
4498
|
let _recurseBlocks = true;
|
|
4499
|
+
// WHY: a block of declarations alone prints the same wherever its source text
|
|
4500
|
+
// and the few rules read around it are the same, and half the blocks a sheet
|
|
4501
|
+
// holds are written again; each body is composed once and handed back after.
|
|
4502
|
+
/** @type {Map<string, string> | null} */
|
|
4503
|
+
let _blockMemo = null;
|
|
4504
|
+
/** @type {Node | null} the rule `_blockMemoBody` was found for */
|
|
4505
|
+
let _blockMemoNode = null;
|
|
4506
|
+
/** @type {string | undefined} the body found for it, undefined to compose one */
|
|
4507
|
+
let _blockMemoBody;
|
|
4508
|
+
/** @type {string} the key a miss stores its body under, "" for none */
|
|
4509
|
+
let _blockMemoKey = "";
|
|
4510
|
+
// The tables a block is looked up in, one per what encloses it: the top level's
|
|
4511
|
+
// is `_blockMemo`. `_blockMemoTable` is the last one keyed, and
|
|
4512
|
+
// `_blockMemoKeyTable` the one `_blockMemoKey` belongs to.
|
|
4513
|
+
/** @type {Map<string, Map<string, string>>} */
|
|
4514
|
+
const _blockMemoScopes = new Map();
|
|
4515
|
+
/** @type {Map<string, string>} */
|
|
4516
|
+
let _blockMemoTable = new Map();
|
|
4517
|
+
/** @type {Map<string, string>} */
|
|
4518
|
+
let _blockMemoKeyTable = _blockMemoTable;
|
|
4519
|
+
// The same for one declaration, where its block is not one written before.
|
|
4520
|
+
/** @type {Map<string, string> | null} */
|
|
4521
|
+
let _declarationMemo = null;
|
|
4522
|
+
/** @type {string} the key the declaration being walked stores its text under */
|
|
4523
|
+
let _declarationMemoKey = "";
|
|
4524
|
+
// The declaration memo's keys whose value is one component.
|
|
4525
|
+
/** @type {Set<string> | null} */
|
|
4526
|
+
let _singleValueKeys = null;
|
|
4480
4527
|
// Printing needs a faithful serialization, so it keeps dropped input as `NodeType.Raw`
|
|
4481
4528
|
// nodes; a walk-only parse leaves this false and allocates none.
|
|
4482
4529
|
let _printing = false;
|
|
@@ -4518,7 +4565,7 @@ const _grammarOnComment = (_src, start, end) => {
|
|
|
4518
4565
|
_S._currentNode = node;
|
|
4519
4566
|
_currentParent = null;
|
|
4520
4567
|
_currentIndex = 0;
|
|
4521
|
-
const bucket =
|
|
4568
|
+
const bucket = _commentBucket;
|
|
4522
4569
|
const e = bucket.enter;
|
|
4523
4570
|
for (let i = 0; i < e.length; i++) e[i](A);
|
|
4524
4571
|
const x = bucket.exit;
|
|
@@ -4572,6 +4619,76 @@ const _mayBeMathFunction = (start) => {
|
|
|
4572
4619
|
return (_MATH_NAME_FIRST_LETTERS & (1 << (first - 0x61))) !== 0;
|
|
4573
4620
|
};
|
|
4574
4621
|
|
|
4622
|
+
// The leaves the CSS printer writes as their source text, whitespace as `_SEP`
|
|
4623
|
+
// and an identifier or hash outside a value (`_printVerbatimLeaf`).
|
|
4624
|
+
const _VERBATIM_LEAVES = new Uint8Array(32);
|
|
4625
|
+
_VERBATIM_LEAVES[NodeType.Whitespace] = 1;
|
|
4626
|
+
_VERBATIM_LEAVES[NodeType.Delim] = 1;
|
|
4627
|
+
_VERBATIM_LEAVES[NodeType.Comma] = 1;
|
|
4628
|
+
_VERBATIM_LEAVES[NodeType.Colon] = 1;
|
|
4629
|
+
_VERBATIM_LEAVES[NodeType.Ident] = 1;
|
|
4630
|
+
_VERBATIM_LEAVES[NodeType.Hash] = 1;
|
|
4631
|
+
/** @type {EXPECTED_FUNCTION | null} */
|
|
4632
|
+
let _verbatimLeafPrinter = null;
|
|
4633
|
+
|
|
4634
|
+
/**
|
|
4635
|
+
* Name the printer that writes `_VERBATIM_LEAVES` as their source text, so a
|
|
4636
|
+
* walk printing through it stores their text without calling it.
|
|
4637
|
+
* @param {EXPECTED_FUNCTION} printer the CSS printer
|
|
4638
|
+
* @returns {void}
|
|
4639
|
+
*/
|
|
4640
|
+
const setVerbatimLeafPrinter = (printer) => {
|
|
4641
|
+
_verbatimLeafPrinter = printer;
|
|
4642
|
+
};
|
|
4643
|
+
|
|
4644
|
+
/**
|
|
4645
|
+
* Store what the CSS printer writes for a `_VERBATIM_LEAVES` node, without a
|
|
4646
|
+
* call through it: they are half the nodes a stylesheet holds. Most print as
|
|
4647
|
+
* their source, which the writer reads only once something asks for it.
|
|
4648
|
+
* @param {number} ty the node's type
|
|
4649
|
+
* @param {Node} node the node
|
|
4650
|
+
* @param {Node | null} parent its parent
|
|
4651
|
+
* @param {PrintContext} writer the print context
|
|
4652
|
+
* @returns {boolean} false to call the printer instead
|
|
4653
|
+
*/
|
|
4654
|
+
const _printVerbatimLeaf = (ty, node, parent, writer) => {
|
|
4655
|
+
if (ty === NodeType.Whitespace) {
|
|
4656
|
+
writer.printedAs(node, _SEP);
|
|
4657
|
+
return true;
|
|
4658
|
+
}
|
|
4659
|
+
// An identifier is a keyword and a hash a color the printer may rewrite only
|
|
4660
|
+
// in a value, and their escapes are respelled anywhere.
|
|
4661
|
+
const ident = ty === NodeType.Ident || ty === NodeType.Hash;
|
|
4662
|
+
if (ident && parent !== null && _within[NodeType.Declaration] !== 0) {
|
|
4663
|
+
return false;
|
|
4664
|
+
}
|
|
4665
|
+
const i = _nodeIndex(node);
|
|
4666
|
+
const start = _starts[i];
|
|
4667
|
+
const end = _ends[i];
|
|
4668
|
+
// The end of the input is where `_printedSource` resolves a trailing escape.
|
|
4669
|
+
if (end === _S._input.length) {
|
|
4670
|
+
const text = _printedSource(node);
|
|
4671
|
+
if (ident) {
|
|
4672
|
+
if (text.includes("\\")) return false;
|
|
4673
|
+
writer.printedAs(node, text);
|
|
4674
|
+
} else {
|
|
4675
|
+
writer.printedAs(node, text === "\\" ? "\\\n" : text);
|
|
4676
|
+
}
|
|
4677
|
+
return true;
|
|
4678
|
+
}
|
|
4679
|
+
if (ident) {
|
|
4680
|
+
if (_rangeHasEscape(start, end)) return false;
|
|
4681
|
+
} else if (
|
|
4682
|
+
end - start === 1 &&
|
|
4683
|
+
_S._input.charCodeAt(start) === CC_REVERSE_SOLIDUS
|
|
4684
|
+
) {
|
|
4685
|
+
writer.printedAs(node, "\\\n");
|
|
4686
|
+
return true;
|
|
4687
|
+
}
|
|
4688
|
+
writer.printedSource(node, _printedSource);
|
|
4689
|
+
return true;
|
|
4690
|
+
};
|
|
4691
|
+
|
|
4575
4692
|
/**
|
|
4576
4693
|
* Walk a component-value subtree; children are already materialized. Fetches
|
|
4577
4694
|
* the node's visitor bucket once (reused for enter + exit) and uses index
|
|
@@ -4665,7 +4782,15 @@ const _walkValue = (node, parent, index, writer) => {
|
|
|
4665
4782
|
_within[ty]--;
|
|
4666
4783
|
_S._inColorOperand = previousColorOperand;
|
|
4667
4784
|
}
|
|
4668
|
-
|
|
4785
|
+
if (
|
|
4786
|
+
b !== undefined ||
|
|
4787
|
+
writer === undefined ||
|
|
4788
|
+
_VERBATIM_LEAVES[ty] === 0 ||
|
|
4789
|
+
writer._printer !== _verbatimLeafPrinter ||
|
|
4790
|
+
!_printVerbatimLeaf(ty, node, parent, writer)
|
|
4791
|
+
) {
|
|
4792
|
+
_exitNode(node, parent, index, b, writer);
|
|
4793
|
+
}
|
|
4669
4794
|
if (enteredMath) _S._mathFunctionDepth--;
|
|
4670
4795
|
if (enteredStepped) _S._steppedFunctionDepth--;
|
|
4671
4796
|
if (enteredSupports) {
|
|
@@ -4871,6 +4996,74 @@ const _enterAtRulePrelude = (i0) => {
|
|
|
4871
4996
|
}
|
|
4872
4997
|
};
|
|
4873
4998
|
|
|
4999
|
+
/**
|
|
5000
|
+
* The key a declaration prints under: its source, with the at-rules that read
|
|
5001
|
+
* one as a descriptor.
|
|
5002
|
+
* @param {Node} node the declaration
|
|
5003
|
+
* @param {number} i0 its node index
|
|
5004
|
+
* @returns {string} the key, "" where it is not one to reuse
|
|
5005
|
+
*/
|
|
5006
|
+
const _declarationMemoKeyOf = (node, i0) => {
|
|
5007
|
+
const start = _starts[i0];
|
|
5008
|
+
const end = _ends[i0];
|
|
5009
|
+
const input = _S._input;
|
|
5010
|
+
if (end === input.length) return "";
|
|
5011
|
+
const text = input.slice(start, end);
|
|
5012
|
+
// A comment kept in the value is written where it stands, once.
|
|
5013
|
+
if (text.includes("/*")) return "";
|
|
5014
|
+
// Bare where no descriptor at-rule is around, which no other key can equal:
|
|
5015
|
+
// those start with a letter naming one, and no source holds a NUL.
|
|
5016
|
+
return !_S._inPropertyRule && !_S._inFunctionRule && !_S._inFeatureValuesRule
|
|
5017
|
+
? text
|
|
5018
|
+
: `${_S._inPropertyRule ? "p" : ""}${_S._inFunctionRule ? "f" : ""}${
|
|
5019
|
+
_S._inFeatureValuesRule ? "v" : ""
|
|
5020
|
+
}\0${text}`;
|
|
5021
|
+
};
|
|
5022
|
+
|
|
5023
|
+
/**
|
|
5024
|
+
* The key a qualified rule's block of declarations is composed under: its
|
|
5025
|
+
* source, with what the walk around it decides of how it prints.
|
|
5026
|
+
* @param {number} i0 the rule's node index
|
|
5027
|
+
* @param {Node | null} parent the node it sits in
|
|
5028
|
+
* @returns {string} the key, "" where the block is not one to reuse
|
|
5029
|
+
*/
|
|
5030
|
+
const _blockMemoKeyOf = (i0, parent) => {
|
|
5031
|
+
const start = _aux1[i0];
|
|
5032
|
+
const end = _ends[i0];
|
|
5033
|
+
const input = _S._input;
|
|
5034
|
+
if (start === -1 || end === input.length) return "";
|
|
5035
|
+
// A comment kept in the block is written where it stands, once.
|
|
5036
|
+
const block = input.slice(start, end);
|
|
5037
|
+
if (block.includes("/*")) return "";
|
|
5038
|
+
let around = "";
|
|
5039
|
+
if (parent !== null) {
|
|
5040
|
+
const p = _nodeIndex(parent);
|
|
5041
|
+
if (_types[p] !== NodeType.AtRule) return "";
|
|
5042
|
+
around = input.slice(_starts[p], _aux0[p]);
|
|
5043
|
+
}
|
|
5044
|
+
// What is around it picks the table, so the key is the block alone and no
|
|
5045
|
+
// copy of it is built per lookup.
|
|
5046
|
+
if (
|
|
5047
|
+
around.length === 0 &&
|
|
5048
|
+
!_S._inPropertyRule &&
|
|
5049
|
+
!_S._inFunctionRule &&
|
|
5050
|
+
!_S._inFeatureValuesRule
|
|
5051
|
+
) {
|
|
5052
|
+
_blockMemoTable = /** @type {Map<string, string>} */ (_blockMemo);
|
|
5053
|
+
return block;
|
|
5054
|
+
}
|
|
5055
|
+
const scope = `${_S._inPropertyRule ? "p" : ""}${_S._inFunctionRule ? "f" : ""}${
|
|
5056
|
+
_S._inFeatureValuesRule ? "v" : ""
|
|
5057
|
+
}${around}`;
|
|
5058
|
+
let table = _blockMemoScopes.get(scope);
|
|
5059
|
+
if (table === undefined) {
|
|
5060
|
+
table = new Map();
|
|
5061
|
+
_blockMemoScopes.set(scope, table);
|
|
5062
|
+
}
|
|
5063
|
+
_blockMemoTable = table;
|
|
5064
|
+
return block;
|
|
5065
|
+
};
|
|
5066
|
+
|
|
4874
5067
|
/**
|
|
4875
5068
|
* Walk a structural subtree; an at-rule / qualified-rule's block was parsed
|
|
4876
5069
|
* eagerly (§5.4.4), so its `value` holds the nested rules / declarations. When
|
|
@@ -4920,9 +5113,24 @@ const _walkRule = (node, parent, index, writer) => {
|
|
|
4920
5113
|
const bi = _bodyIdx[i0];
|
|
4921
5114
|
if (bi !== 0) {
|
|
4922
5115
|
const decls = _declBodies[bi - 1];
|
|
4923
|
-
|
|
4924
|
-
|
|
5116
|
+
const key =
|
|
5117
|
+
_blockMemo !== null &&
|
|
5118
|
+
ty === NodeType.QualifiedRule &&
|
|
5119
|
+
decls.length !== 0 &&
|
|
5120
|
+
_ruleBodies[bi - 1].length === 0
|
|
5121
|
+
? _blockMemoKeyOf(i0, parent)
|
|
5122
|
+
: "";
|
|
5123
|
+
const table = _blockMemoTable;
|
|
5124
|
+
const memo = key === "" ? undefined : table.get(key);
|
|
5125
|
+
if (memo === undefined) {
|
|
5126
|
+
for (let i = 0; i < decls.length; i++) {
|
|
5127
|
+
_walkRule(decls[i], node, i, writer);
|
|
5128
|
+
}
|
|
4925
5129
|
}
|
|
5130
|
+
_blockMemoNode = node;
|
|
5131
|
+
_blockMemoBody = memo;
|
|
5132
|
+
_blockMemoKey = memo === undefined ? key : "";
|
|
5133
|
+
_blockMemoKeyTable = table;
|
|
4926
5134
|
const ch = _ruleBodies[bi - 1];
|
|
4927
5135
|
for (let i = 0; i < ch.length; i++) _walkRule(ch[i], node, i, writer);
|
|
4928
5136
|
}
|
|
@@ -4931,6 +5139,28 @@ const _walkRule = (node, parent, index, writer) => {
|
|
|
4931
5139
|
_S._inFunctionRule = prevFunction;
|
|
4932
5140
|
_S._inFeatureValuesRule = prevFeatureValues;
|
|
4933
5141
|
} else if (ty === NodeType.Declaration) {
|
|
5142
|
+
const key =
|
|
5143
|
+
_declarationMemo !== null && b === undefined
|
|
5144
|
+
? _declarationMemoKeyOf(node, i0)
|
|
5145
|
+
: "";
|
|
5146
|
+
if (key !== "") {
|
|
5147
|
+
const memo = /** @type {Map<string, string>} */ (_declarationMemo).get(
|
|
5148
|
+
key
|
|
5149
|
+
);
|
|
5150
|
+
if (memo !== undefined) {
|
|
5151
|
+
_within[ty]--;
|
|
5152
|
+
// Its value's tokens print no text, so a box merge reads what it
|
|
5153
|
+
// needs of them off the flags.
|
|
5154
|
+
if (_mayBeMergeableName(node)) {
|
|
5155
|
+
_flags[i0] |= /** @type {Set<string>} */ (_singleValueKeys).has(key)
|
|
5156
|
+
? _FLAG_MEMO_PRINTED | _FLAG_SINGLE_VALUE
|
|
5157
|
+
: _FLAG_MEMO_PRINTED;
|
|
5158
|
+
}
|
|
5159
|
+
/** @type {PrintContext} */ (writer).printedAs(node, memo);
|
|
5160
|
+
return;
|
|
5161
|
+
}
|
|
5162
|
+
_declarationMemoKey = key;
|
|
5163
|
+
}
|
|
4934
5164
|
const vs = _listStarts[i0];
|
|
4935
5165
|
const ve = vs + _listLens[i0];
|
|
4936
5166
|
// A declaration's value is a value context (its hashes are colors, not
|
|
@@ -4978,6 +5208,47 @@ const _walkRule = (node, parent, index, writer) => {
|
|
|
4978
5208
|
_within[ty]--;
|
|
4979
5209
|
}
|
|
4980
5210
|
_exitNode(node, parent, index, b, writer);
|
|
5211
|
+
if (_declarationMemoKey !== "") {
|
|
5212
|
+
const context = /** @type {PrintContext} */ (writer);
|
|
5213
|
+
const printed = context.get(node);
|
|
5214
|
+
if (!_mayBeMergeableName(node)) {
|
|
5215
|
+
/** @type {Map<string, string>} */ (_declarationMemo).set(
|
|
5216
|
+
_declarationMemoKey,
|
|
5217
|
+
printed
|
|
5218
|
+
);
|
|
5219
|
+
} else if (printed.includes(":")) {
|
|
5220
|
+
/** @type {Map<string, string>} */ (_declarationMemo).set(
|
|
5221
|
+
_declarationMemoKey,
|
|
5222
|
+
printed
|
|
5223
|
+
);
|
|
5224
|
+
if (_valueComponents(A, node, context).length === 1) {
|
|
5225
|
+
/** @type {Set<string>} */ (_singleValueKeys).add(_declarationMemoKey);
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
5228
|
+
_declarationMemoKey = "";
|
|
5229
|
+
}
|
|
5230
|
+
};
|
|
5231
|
+
|
|
5232
|
+
// What a declaration printed from the memo carries in its flags, past the
|
|
5233
|
+
// public `Flag` bits: that its value's tokens printed nothing, and whether that
|
|
5234
|
+
// value is one component, which is all a box merge reads of them.
|
|
5235
|
+
const _FLAG_MEMO_PRINTED = 8;
|
|
5236
|
+
const _FLAG_SINGLE_VALUE = 16;
|
|
5237
|
+
|
|
5238
|
+
/**
|
|
5239
|
+
* Whether a declaration's value is one component, as `_valueComponents` splits
|
|
5240
|
+
* it, answered off its flags where it printed from the memo.
|
|
5241
|
+
* @param {CssPath} path the accessor
|
|
5242
|
+
* @param {Node} node the declaration
|
|
5243
|
+
* @param {PrintContext} writer the print context (children's printed text)
|
|
5244
|
+
* @returns {boolean} true when it is one component
|
|
5245
|
+
*/
|
|
5246
|
+
const _isSingleValue = (path, node, writer) => {
|
|
5247
|
+
const flags = _flags[_nodeIndex(node)];
|
|
5248
|
+
if ((flags & _FLAG_MEMO_PRINTED) !== 0) {
|
|
5249
|
+
return (flags & _FLAG_SINGLE_VALUE) !== 0;
|
|
5250
|
+
}
|
|
5251
|
+
return _valueComponents(path, node, writer).length === 1;
|
|
4981
5252
|
};
|
|
4982
5253
|
|
|
4983
5254
|
// WHY: nested-block streaming.
|
|
@@ -5078,8 +5349,8 @@ const _frameChainKey = Array.from({ length: _STREAM_MAX_DEPTH }, () => null);
|
|
|
5078
5349
|
* travels outward — only `scope` is replaced, by one standing for more — so the
|
|
5079
5350
|
* collected and the streamed path split a rule the same way, which is what makes
|
|
5080
5351
|
* the two agree on what a duplicate is.
|
|
5081
|
-
* @typedef {{ scope: RuleScope, key: string, at: number, len: number }} RuleSpan
|
|
5082
|
-
* @typedef {{ prefix: string, rules: Map<string,
|
|
5352
|
+
* @typedef {{ scope: RuleScope, key: string, at: number, len: number, taken: TakenPiece | null }} RuleSpan
|
|
5353
|
+
* @typedef {{ prefix: string, rules: Map<string, RuleSpan>, selectors: Map<string, RuleSpan | RuleSpan[]>, inner: Map<string, RuleScope>, noShadow: boolean }} RuleScope
|
|
5083
5354
|
* @typedef {{ bodyAt: number, prelude: string, keyPrelude: string, qualified: boolean, spans: RuleSpan[] }} BlockSpans
|
|
5084
5355
|
*/
|
|
5085
5356
|
// A span no later copy is read against: it is there to be cut, not to key a
|
|
@@ -5090,14 +5361,108 @@ const UNKEYED = "";
|
|
|
5090
5361
|
/** @type {BlockSpans[]} */
|
|
5091
5362
|
const _blockSpans = [];
|
|
5092
5363
|
const _NO_RULE_SPANS = /** @type {RuleSpan[]} */ (
|
|
5093
|
-
/** @type {
|
|
5364
|
+
/** @type {RuleSpan[] | ReadonlyArray<never>} */ (Object.freeze([]))
|
|
5094
5365
|
);
|
|
5095
5366
|
const _NO_BLOCK_SPANS = /** @type {BlockSpans[]} */ (
|
|
5096
|
-
/** @type {
|
|
5367
|
+
/** @type {BlockSpans[] | ReadonlyArray<never>} */ (Object.freeze([]))
|
|
5097
5368
|
);
|
|
5098
5369
|
/**
|
|
5099
|
-
*
|
|
5370
|
+
* A top-level node's text as written out, which later rules cut dead rules from.
|
|
5371
|
+
* A cut is recorded against the text the piece last held, so a run of cuts builds
|
|
5372
|
+
* the text once, when something reads it, rather than once per cut.
|
|
5100
5373
|
*/
|
|
5374
|
+
class TakenPiece {
|
|
5375
|
+
/**
|
|
5376
|
+
* @param {number} piece the writer's index for it
|
|
5377
|
+
* @param {string} text the text it went out as
|
|
5378
|
+
* @param {number} empties its length with every rule it holds cut, less one, or -1
|
|
5379
|
+
*/
|
|
5380
|
+
constructor(piece, text, empties) {
|
|
5381
|
+
/** @type {number} */
|
|
5382
|
+
this.piece = piece;
|
|
5383
|
+
/** @type {RuleSpan[]} */
|
|
5384
|
+
this.spans = [];
|
|
5385
|
+
/** @type {number} */
|
|
5386
|
+
this.empties = empties;
|
|
5387
|
+
/** @type {string} */
|
|
5388
|
+
this._text = text;
|
|
5389
|
+
/** @type {number[] | null} the ranges of `_text` cut since, as sorted start, end pairs */
|
|
5390
|
+
this._cuts = null;
|
|
5391
|
+
/** @type {number} */
|
|
5392
|
+
this.length = text.length;
|
|
5393
|
+
}
|
|
5394
|
+
|
|
5395
|
+
/**
|
|
5396
|
+
* @returns {string} what the piece reads now
|
|
5397
|
+
*/
|
|
5398
|
+
get text() {
|
|
5399
|
+
const cuts = this._cuts;
|
|
5400
|
+
if (cuts !== null) {
|
|
5401
|
+
/** @type {string[]} */
|
|
5402
|
+
const parts = [];
|
|
5403
|
+
let from = 0;
|
|
5404
|
+
for (let i = 0; i < cuts.length; i += 2) {
|
|
5405
|
+
parts.push(this._text.slice(from, cuts[i]));
|
|
5406
|
+
from = cuts[i + 1];
|
|
5407
|
+
}
|
|
5408
|
+
parts.push(this._text.slice(from));
|
|
5409
|
+
this._text = parts.join("");
|
|
5410
|
+
this._cuts = null;
|
|
5411
|
+
}
|
|
5412
|
+
return this._text;
|
|
5413
|
+
}
|
|
5414
|
+
|
|
5415
|
+
/**
|
|
5416
|
+
* @param {string} value what the piece reads from now on
|
|
5417
|
+
*/
|
|
5418
|
+
set text(value) {
|
|
5419
|
+
this._text = value;
|
|
5420
|
+
this._cuts = null;
|
|
5421
|
+
this.length = value.length;
|
|
5422
|
+
}
|
|
5423
|
+
|
|
5424
|
+
/**
|
|
5425
|
+
* @param {number} at an offset in what the piece reads now
|
|
5426
|
+
* @returns {number} the code unit there, read without building the text
|
|
5427
|
+
*/
|
|
5428
|
+
charCodeAt(at) {
|
|
5429
|
+
return this._text.charCodeAt(this._uncut(at));
|
|
5430
|
+
}
|
|
5431
|
+
|
|
5432
|
+
/**
|
|
5433
|
+
* Take `len` code units out at `from`, offsets in what the piece reads now.
|
|
5434
|
+
* @param {number} from where the cut starts
|
|
5435
|
+
* @param {number} len how much it takes
|
|
5436
|
+
* @returns {void}
|
|
5437
|
+
*/
|
|
5438
|
+
cut(from, len) {
|
|
5439
|
+
const start = this._uncut(from);
|
|
5440
|
+
const end = this._uncut(from + len - 1) + 1;
|
|
5441
|
+
const cuts = this._cuts === null ? [] : this._cuts;
|
|
5442
|
+
// The ranges cut before inside this one are taken with it.
|
|
5443
|
+
let at = 0;
|
|
5444
|
+
while (at < cuts.length && cuts[at] < start) at += 2;
|
|
5445
|
+
let past = at;
|
|
5446
|
+
while (past < cuts.length && cuts[past + 1] <= end) past += 2;
|
|
5447
|
+
cuts.splice(at, past - at, start, end);
|
|
5448
|
+
this._cuts = cuts;
|
|
5449
|
+
this.length -= len;
|
|
5450
|
+
}
|
|
5451
|
+
|
|
5452
|
+
/**
|
|
5453
|
+
* @param {number} at an offset in what the piece reads now
|
|
5454
|
+
* @returns {number} the same offset in `_text`
|
|
5455
|
+
*/
|
|
5456
|
+
_uncut(at) {
|
|
5457
|
+
const cuts = this._cuts;
|
|
5458
|
+
if (cuts === null) return at;
|
|
5459
|
+
let offset = at;
|
|
5460
|
+
for (let i = 0; i < cuts.length && cuts[i] <= offset; i += 2) {
|
|
5461
|
+
offset += cuts[i + 1] - cuts[i];
|
|
5462
|
+
}
|
|
5463
|
+
return offset;
|
|
5464
|
+
}
|
|
5465
|
+
}
|
|
5101
5466
|
// Every rule taken so far, sheet-wide, by what encloses it and then by the text
|
|
5102
5467
|
// it printed to — neither of which changes once written (see `RuleSpan`).
|
|
5103
5468
|
/** @type {Map<string, RuleScope> | null} */
|
|
@@ -5123,7 +5488,8 @@ const _ruleScopeFor = (prefix) => {
|
|
|
5123
5488
|
prefix,
|
|
5124
5489
|
rules: new Map(),
|
|
5125
5490
|
selectors: new Map(),
|
|
5126
|
-
inner: new Map()
|
|
5491
|
+
inner: new Map(),
|
|
5492
|
+
noShadow: _NO_SHADOW_SCOPE_RE.test(prefix)
|
|
5127
5493
|
};
|
|
5128
5494
|
scopes.set(prefix, scope);
|
|
5129
5495
|
}
|
|
@@ -5406,10 +5772,7 @@ const _streamEmitChild = (d, child) => {
|
|
|
5406
5772
|
const opener = _namedLayerOpener(text);
|
|
5407
5773
|
if (opener === null) {
|
|
5408
5774
|
if (_frameSeenLayers[d] !== null) {
|
|
5409
|
-
_forgetLayersWritten(
|
|
5410
|
-
/** @type {Map<string, SeenLayer>} */ (_frameSeenLayers[d]),
|
|
5411
|
-
text
|
|
5412
|
-
);
|
|
5775
|
+
_forgetLayersWritten(_frameSeenLayers[d], text);
|
|
5413
5776
|
}
|
|
5414
5777
|
} else {
|
|
5415
5778
|
let layers = _frameSeenLayers[d];
|
|
@@ -5855,7 +6218,7 @@ const _streamConsumeBlock = (ts, rule) => {
|
|
|
5855
6218
|
/** @type {HeldTopLevel | null} */
|
|
5856
6219
|
let _heldTopLevel = null;
|
|
5857
6220
|
|
|
5858
|
-
/** @typedef {{ taken: TakenPiece, span: RuleSpan, entry: RuleEntry, prelude: number,
|
|
6221
|
+
/** @typedef {{ taken: TakenPiece, span: RuleSpan, entry: RuleEntry, prelude: number, grown: boolean }} PriorTopLevel the top-level rule last written out, the piece it stands in, how far into it its block starts, and whether a later rule's selectors joined its list */
|
|
5859
6222
|
|
|
5860
6223
|
// The rule written out before the held one, kept so a join only its settled
|
|
5861
6224
|
// block qualifies for can still be made. Null when that was not one whole rule.
|
|
@@ -5943,18 +6306,23 @@ const _drainTopLevelSpans = (node) => {
|
|
|
5943
6306
|
const _topLevelSpans = (own, text) => {
|
|
5944
6307
|
if (own === undefined) return null;
|
|
5945
6308
|
if (own === _WHOLE_TEXT_SPANS) {
|
|
5946
|
-
return [
|
|
6309
|
+
return [
|
|
6310
|
+
{ scope: _rootScope(), key: text, at: 0, len: text.length, taken: null }
|
|
6311
|
+
];
|
|
5947
6312
|
}
|
|
5948
6313
|
/** @type {RuleSpan[]} */
|
|
5949
6314
|
const out = own.qualified
|
|
5950
|
-
? [{ scope: _rootScope(), key: text, at: 0, len: text.length }]
|
|
6315
|
+
? [{ scope: _rootScope(), key: text, at: 0, len: text.length, taken: null }]
|
|
5951
6316
|
: [];
|
|
5952
|
-
|
|
6317
|
+
const spans = own.spans;
|
|
6318
|
+
for (let i = 0; i < spans.length; i++) {
|
|
6319
|
+
const span = spans[i];
|
|
5953
6320
|
out.push({
|
|
5954
6321
|
scope: _enclosingRuleScope(span.scope, own.keyPrelude),
|
|
5955
6322
|
key: span.key,
|
|
5956
6323
|
at: own.bodyAt + span.at,
|
|
5957
|
-
len: span.len
|
|
6324
|
+
len: span.len,
|
|
6325
|
+
taken: null
|
|
5958
6326
|
});
|
|
5959
6327
|
}
|
|
5960
6328
|
return out;
|
|
@@ -5985,8 +6353,7 @@ const _takeDeduped = (writer, piece, text, spans, own, chain) => {
|
|
|
5985
6353
|
DROPPABLE_WHEN_EMPTY_AT_RULES.has(_atRuleName(own.prelude))))
|
|
5986
6354
|
? own.bodyAt
|
|
5987
6355
|
: -1;
|
|
5988
|
-
|
|
5989
|
-
const taken = { piece, text, spans: [], empties };
|
|
6356
|
+
const taken = new TakenPiece(piece, text, empties);
|
|
5990
6357
|
_noteSpans(writer, taken, spans, chain);
|
|
5991
6358
|
return taken;
|
|
5992
6359
|
};
|
|
@@ -6005,18 +6372,23 @@ const _noteSpans = (writer, taken, spans, chain) => {
|
|
|
6005
6372
|
// `taken.spans` holds, and one not yet pushed would keep its old offset.
|
|
6006
6373
|
for (const span of spans) {
|
|
6007
6374
|
if (chain.length !== 0) span.scope = _enclosingRuleScope(span.scope, chain);
|
|
6375
|
+
span.taken = taken;
|
|
6008
6376
|
taken.spans.push(span);
|
|
6009
6377
|
}
|
|
6010
6378
|
for (const span of spans) {
|
|
6011
6379
|
if (span.key === UNKEYED) continue;
|
|
6012
6380
|
const rules = span.scope.rules;
|
|
6013
6381
|
const before = rules.get(span.key);
|
|
6014
|
-
if (before !== undefined)
|
|
6015
|
-
|
|
6382
|
+
if (before !== undefined) {
|
|
6383
|
+
_cutSpan(writer, /** @type {TakenPiece} */ (before.taken), before);
|
|
6384
|
+
}
|
|
6385
|
+
rules.set(span.key, span);
|
|
6016
6386
|
}
|
|
6017
6387
|
// After every copy is taken back, so an earlier rule a cut here left flat is
|
|
6018
6388
|
// read as flat. A distant merge moves a block up past others, out of this order.
|
|
6019
6389
|
if (!_S._transforms.removeDeadRules || _mergingDistantRules) return;
|
|
6390
|
+
// TODO add an option to make this opt-in: over the CSS corpus it costs ~10% of
|
|
6391
|
+
// minify CPU for 248 of 2,456,527 gzip bytes.
|
|
6020
6392
|
for (const span of spans) {
|
|
6021
6393
|
if (span.key !== UNKEYED && span.len !== 0) {
|
|
6022
6394
|
_shadowEarlierRule(writer, taken, span);
|
|
@@ -6032,6 +6404,29 @@ const _ROLLBACK_RE = /^revert(?:-[a-z]+)?$/i;
|
|
|
6032
6404
|
// blocks are gathered into one without their rules noted, so none is there.
|
|
6033
6405
|
const _NO_SHADOW_SCOPE_RE = /@(?:-[a-z]+-)?keyframes|@layer/i;
|
|
6034
6406
|
|
|
6407
|
+
// What each prior `_shadowEarlierRule` compared against declares, with the text
|
|
6408
|
+
// that was read from, so a prior a later rule writes nothing of is passed over.
|
|
6409
|
+
/** @type {Map<RuleSpan, { text: string, names: Set<string> }>} */
|
|
6410
|
+
const _shadowDeclared = new Map();
|
|
6411
|
+
|
|
6412
|
+
/**
|
|
6413
|
+
* The names a printed flat rule's declarations write, as `_cascadeName` reads
|
|
6414
|
+
* them.
|
|
6415
|
+
* @param {string} rule the rule's printed text
|
|
6416
|
+
* @param {number} open where its `{` sits
|
|
6417
|
+
* @returns {Set<string>} the names
|
|
6418
|
+
*/
|
|
6419
|
+
const _declaredNames = (rule, open) => {
|
|
6420
|
+
/** @type {Set<string>} */
|
|
6421
|
+
const names = new Set();
|
|
6422
|
+
for (const declaration of _splitPrintedDeclarations(
|
|
6423
|
+
rule.slice(open + 1, -1)
|
|
6424
|
+
)) {
|
|
6425
|
+
if (declaration.indexOf(":") > 0) names.add(_cascadeName(declaration));
|
|
6426
|
+
}
|
|
6427
|
+
return names;
|
|
6428
|
+
};
|
|
6429
|
+
|
|
6035
6430
|
/**
|
|
6036
6431
|
* The declarations of a printed block body, split on the `;` between them; a
|
|
6037
6432
|
* nested block is a piece of its own.
|
|
@@ -6114,24 +6509,30 @@ const _readWherever = (values, earlier) => {
|
|
|
6114
6509
|
* @returns {void}
|
|
6115
6510
|
*/
|
|
6116
6511
|
const _shadowEarlierRule = (writer, taken, span) => {
|
|
6117
|
-
const
|
|
6118
|
-
const
|
|
6512
|
+
const whole = taken.text;
|
|
6513
|
+
const at = span.at;
|
|
6514
|
+
const brace = whole.indexOf("{", at);
|
|
6119
6515
|
// Only a qualified rule: an at-rule is no one cascade. One a later cut
|
|
6120
6516
|
// leaves flat is read as one, so every rule is noted, flat or not.
|
|
6121
6517
|
if (
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6518
|
+
brace <= at ||
|
|
6519
|
+
brace >= at + span.len ||
|
|
6520
|
+
whole.charCodeAt(at) === CC_AT_SIGN ||
|
|
6521
|
+
span.scope.noShadow
|
|
6125
6522
|
) {
|
|
6126
6523
|
return;
|
|
6127
6524
|
}
|
|
6128
|
-
const
|
|
6525
|
+
const open = brace - at;
|
|
6526
|
+
const selector = whole.slice(at, brace);
|
|
6129
6527
|
const selectors = span.scope.selectors;
|
|
6130
|
-
const
|
|
6131
|
-
|
|
6132
|
-
|
|
6528
|
+
const noted = selectors.get(selector);
|
|
6529
|
+
// A lone prior is held bare: almost every selector is written once.
|
|
6530
|
+
if (noted === undefined) {
|
|
6531
|
+
selectors.set(selector, span);
|
|
6133
6532
|
return;
|
|
6134
6533
|
}
|
|
6534
|
+
const priors = Array.isArray(noted) ? noted : [noted];
|
|
6535
|
+
const text = whole.slice(at, at + span.len);
|
|
6135
6536
|
// Per name, the later values and whether one every target reads is among
|
|
6136
6537
|
// them, and whether one of those is `!important`.
|
|
6137
6538
|
/** @type {Map<string, { values: Set<string>, read: boolean, important: boolean }>} */
|
|
@@ -6161,11 +6562,24 @@ const _shadowEarlierRule = (writer, taken, span) => {
|
|
|
6161
6562
|
}
|
|
6162
6563
|
}
|
|
6163
6564
|
for (const prior of priors) {
|
|
6164
|
-
if (prior.
|
|
6165
|
-
const
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6565
|
+
if (prior.len === 0) continue;
|
|
6566
|
+
const priorTaken = /** @type {TakenPiece} */ (prior.taken);
|
|
6567
|
+
const before = priorTaken.text.slice(prior.at, prior.at + prior.len);
|
|
6568
|
+
// A prior writing none of the names this rule writes keeps all it has, so
|
|
6569
|
+
// it is not split again for every later rule under its selector.
|
|
6570
|
+
let declared = _shadowDeclared.get(prior);
|
|
6571
|
+
if (declared === undefined || declared.text !== before) {
|
|
6572
|
+
declared = { text: before, names: _declaredNames(before, open) };
|
|
6573
|
+
_shadowDeclared.set(prior, declared);
|
|
6574
|
+
}
|
|
6575
|
+
let shared = false;
|
|
6576
|
+
for (const name of later.keys()) {
|
|
6577
|
+
if (declared.names.has(name)) {
|
|
6578
|
+
shared = true;
|
|
6579
|
+
break;
|
|
6580
|
+
}
|
|
6581
|
+
}
|
|
6582
|
+
if (!shared) continue;
|
|
6169
6583
|
/* istanbul ignore if -- @preserve: a join grows a list only before its rule
|
|
6170
6584
|
is noted unless distant merges are on, which skip this; kept as the guard */
|
|
6171
6585
|
if (
|
|
@@ -6207,18 +6621,17 @@ const _shadowEarlierRule = (writer, taken, span) => {
|
|
|
6207
6621
|
}
|
|
6208
6622
|
if (!dropped) continue;
|
|
6209
6623
|
if (kept.length === 0) {
|
|
6210
|
-
_cutSpan(writer,
|
|
6624
|
+
_cutSpan(writer, priorTaken, prior);
|
|
6211
6625
|
continue;
|
|
6212
6626
|
}
|
|
6213
|
-
_rewriteSpan(
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6627
|
+
_rewriteSpan(writer, priorTaken, prior, `${selector}{${kept.join(";")}}`);
|
|
6628
|
+
_rekeyShrunkSpan(writer, priorTaken, prior);
|
|
6629
|
+
}
|
|
6630
|
+
if (priors === noted) {
|
|
6631
|
+
priors.push(span);
|
|
6632
|
+
} else {
|
|
6633
|
+
selectors.set(selector, [/** @type {RuleSpan} */ (noted), span]);
|
|
6220
6634
|
}
|
|
6221
|
-
priors.push({ taken, span });
|
|
6222
6635
|
};
|
|
6223
6636
|
|
|
6224
6637
|
/**
|
|
@@ -6315,15 +6728,7 @@ const _joinGatheredSeam = (writer, taken, at, entry) => {
|
|
|
6315
6728
|
) {
|
|
6316
6729
|
return;
|
|
6317
6730
|
}
|
|
6318
|
-
if (
|
|
6319
|
-
!_lendSelectorsTo(
|
|
6320
|
-
writer,
|
|
6321
|
-
taken,
|
|
6322
|
-
before,
|
|
6323
|
-
prelude,
|
|
6324
|
-
first.text.slice(0, first.prelude)
|
|
6325
|
-
)
|
|
6326
|
-
) {
|
|
6731
|
+
if (!_lendSelectorsTo(writer, taken, before, prelude, _entryPrelude(first))) {
|
|
6327
6732
|
return;
|
|
6328
6733
|
}
|
|
6329
6734
|
_cutSpan(writer, taken, after);
|
|
@@ -6335,18 +6740,19 @@ const _joinGatheredSeam = (writer, taken, at, entry) => {
|
|
|
6335
6740
|
* it, so this runs until none is left.
|
|
6336
6741
|
* @param {PrintContext} writer the print context
|
|
6337
6742
|
* @param {TakenPiece} taken the piece the cut was made in
|
|
6743
|
+
* @param {RuleSpan[]} held the rules that held what was cut, the only ones it can have emptied
|
|
6338
6744
|
* @returns {void}
|
|
6339
6745
|
*/
|
|
6340
|
-
const _cutEmptiedSpans = (writer, taken) => {
|
|
6746
|
+
const _cutEmptiedSpans = (writer, taken, held) => {
|
|
6341
6747
|
if (!_S._transforms.removeDeadRules) return;
|
|
6342
6748
|
// Every span is a rule dropped empty wherever it stands: a qualified rule, or
|
|
6343
6749
|
// one of the at-rules `DROPPABLE_WHEN_EMPTY_AT_RULES` names (`_collectRuleSpans`).
|
|
6344
|
-
for (const other of
|
|
6750
|
+
for (const other of held) {
|
|
6345
6751
|
const end = other.at + other.len;
|
|
6346
6752
|
if (
|
|
6347
6753
|
other.len > 2 &&
|
|
6348
|
-
taken.
|
|
6349
|
-
taken.
|
|
6754
|
+
taken.charCodeAt(end - 1) === CC_RIGHT_CURLY &&
|
|
6755
|
+
taken.charCodeAt(end - 2) === CC_LEFT_CURLY
|
|
6350
6756
|
) {
|
|
6351
6757
|
_cutSpan(writer, taken, other);
|
|
6352
6758
|
return;
|
|
@@ -6369,17 +6775,17 @@ const _cutSpan = (writer, taken, span) => {
|
|
|
6369
6775
|
// The rule stood last in its block, so the `;` in front of it is one the
|
|
6370
6776
|
// printer drops itself — it goes with the rule rather than being left behind.
|
|
6371
6777
|
if (
|
|
6372
|
-
taken.
|
|
6373
|
-
taken.
|
|
6778
|
+
taken.charCodeAt(from + len) === CC_RIGHT_CURLY &&
|
|
6779
|
+
taken.charCodeAt(from - 1) === CC_SEMICOLON
|
|
6374
6780
|
) {
|
|
6375
6781
|
from -= 1;
|
|
6376
6782
|
len += 1;
|
|
6377
6783
|
}
|
|
6378
|
-
taken.
|
|
6379
|
-
if (taken.empties !== -1 && taken.
|
|
6784
|
+
taken.cut(from, len);
|
|
6785
|
+
if (taken.empties !== -1 && taken.length === taken.empties + 1) {
|
|
6380
6786
|
taken.text = "";
|
|
6381
6787
|
}
|
|
6382
|
-
writer.
|
|
6788
|
+
writer.deferRetractable(taken.piece, taken);
|
|
6383
6789
|
const end = from + len;
|
|
6384
6790
|
/** @type {RuleSpan[] | null} */
|
|
6385
6791
|
let shrunk = null;
|
|
@@ -6401,8 +6807,8 @@ const _cutSpan = (writer, taken, span) => {
|
|
|
6401
6807
|
span.len = 0;
|
|
6402
6808
|
if (shrunk !== null) {
|
|
6403
6809
|
for (const other of shrunk) _rekeyShrunkSpan(writer, taken, other);
|
|
6810
|
+
_cutEmptiedSpans(writer, taken, shrunk);
|
|
6404
6811
|
}
|
|
6405
|
-
_cutEmptiedSpans(writer, taken);
|
|
6406
6812
|
};
|
|
6407
6813
|
|
|
6408
6814
|
/**
|
|
@@ -6419,15 +6825,14 @@ const _rekeyShrunkSpan = (writer, taken, span) => {
|
|
|
6419
6825
|
const rules = span.scope.rules;
|
|
6420
6826
|
const other = rules.get(key);
|
|
6421
6827
|
_rekeySpan(taken, span);
|
|
6422
|
-
if (other === undefined || other
|
|
6423
|
-
|
|
6424
|
-
}
|
|
6828
|
+
if (other === undefined || other === span || other.len === 0) return;
|
|
6829
|
+
const otherTaken = /** @type {TakenPiece} */ (other.taken);
|
|
6425
6830
|
const earlier =
|
|
6426
|
-
|
|
6427
|
-
(
|
|
6831
|
+
otherTaken.piece < taken.piece ||
|
|
6832
|
+
(otherTaken.piece === taken.piece && other.at < span.at);
|
|
6428
6833
|
if (earlier) {
|
|
6429
|
-
rules.set(key,
|
|
6430
|
-
_cutSpan(writer,
|
|
6834
|
+
rules.set(key, span);
|
|
6835
|
+
_cutSpan(writer, otherTaken, other);
|
|
6431
6836
|
} else {
|
|
6432
6837
|
_cutSpan(writer, taken, span);
|
|
6433
6838
|
}
|
|
@@ -6647,13 +7052,13 @@ const _priorOf = (taken, entry) => {
|
|
|
6647
7052
|
return null;
|
|
6648
7053
|
}
|
|
6649
7054
|
// A rule whose selectors may not join a list is still a neighbor: the copy
|
|
6650
|
-
// that only restates it goes whatever its block holds.
|
|
7055
|
+
// that only restates it goes whatever its block holds. Whether they may is
|
|
7056
|
+
// asked of `entry` once a later rule prints the same block.
|
|
6651
7057
|
return {
|
|
6652
7058
|
taken,
|
|
6653
7059
|
span,
|
|
6654
7060
|
entry,
|
|
6655
7061
|
prelude: entry.prelude,
|
|
6656
|
-
listable: _entryListable(entry),
|
|
6657
7062
|
grown: false
|
|
6658
7063
|
};
|
|
6659
7064
|
};
|
|
@@ -6682,12 +7087,9 @@ const _settlePrior = (writer) => {
|
|
|
6682
7087
|
const _rekeySpan = (taken, span) => {
|
|
6683
7088
|
if (span.key === UNKEYED) return;
|
|
6684
7089
|
const rules = span.scope.rules;
|
|
6685
|
-
|
|
6686
|
-
if (registered !== undefined && registered.span === span) {
|
|
6687
|
-
rules.delete(span.key);
|
|
6688
|
-
}
|
|
7090
|
+
if (rules.get(span.key) === span) rules.delete(span.key);
|
|
6689
7091
|
span.key = taken.text.slice(span.at, span.at + span.len);
|
|
6690
|
-
if (!rules.has(span.key)) rules.set(span.key,
|
|
7092
|
+
if (!rules.has(span.key)) rules.set(span.key, span);
|
|
6691
7093
|
};
|
|
6692
7094
|
|
|
6693
7095
|
/**
|
|
@@ -6727,7 +7129,10 @@ const _spanEntry = (text, prelude) => ({
|
|
|
6727
7129
|
listKind: LIST_KIND_SELECTOR,
|
|
6728
7130
|
children: null,
|
|
6729
7131
|
head: "",
|
|
6730
|
-
unordered: false
|
|
7132
|
+
unordered: false,
|
|
7133
|
+
list: null,
|
|
7134
|
+
block: null,
|
|
7135
|
+
declarations: null
|
|
6731
7136
|
});
|
|
6732
7137
|
|
|
6733
7138
|
/**
|
|
@@ -6832,7 +7237,9 @@ const _joinsNeighbor = (writer, before, rule) => {
|
|
|
6832
7237
|
return same && _foldsNeighborBody(writer, before, rule);
|
|
6833
7238
|
}
|
|
6834
7239
|
if (!same) {
|
|
6835
|
-
if (!before.
|
|
7240
|
+
if (!_entryListable(before.entry) || !_entryListable(rule.entry)) {
|
|
7241
|
+
return false;
|
|
7242
|
+
}
|
|
6836
7243
|
const selector = tail.slice(second.at, second.at + rule.prelude);
|
|
6837
7244
|
if (
|
|
6838
7245
|
!_lendSelectorsTo(writer, before.taken, first, before.prelude, selector)
|
|
@@ -6918,14 +7325,11 @@ const _joinsPrior = (writer, prior, held) =>
|
|
|
6918
7325
|
*/
|
|
6919
7326
|
const _joinsPriorEntry = (writer, prior, entry, parted) => {
|
|
6920
7327
|
if (!_S._transforms.mergeRules) return false;
|
|
6921
|
-
if (entry.prelude === -1 || entry.atRule
|
|
6922
|
-
return false;
|
|
6923
|
-
}
|
|
7328
|
+
if (entry.prelude === -1 || entry.atRule) return false;
|
|
6924
7329
|
// A kept comment between the two was written above the later rule, which is
|
|
6925
7330
|
// read where it still stands rather than here, the flush having cleared it.
|
|
6926
7331
|
if (parted) return false;
|
|
6927
7332
|
const span = prior.span;
|
|
6928
|
-
if (!prior.listable) return false;
|
|
6929
7333
|
// Read where the rule now stands, never where it was taken: a cut inside its
|
|
6930
7334
|
// block, or a list this already grew, leaves the entry it went out as stale.
|
|
6931
7335
|
if (span.len <= prior.prelude) return false;
|
|
@@ -6942,6 +7346,8 @@ const _joinsPriorEntry = (writer, prior, entry, parted) => {
|
|
|
6942
7346
|
) {
|
|
6943
7347
|
return false;
|
|
6944
7348
|
}
|
|
7349
|
+
// After the blocks compare, which almost none do: the shape test is a regex.
|
|
7350
|
+
if (!_entryListable(entry) || !_entryListable(prior.entry)) return false;
|
|
6945
7351
|
// The same rule twice is one rule: nothing stands between them, so the later
|
|
6946
7352
|
// copy only restates what the earlier already says.
|
|
6947
7353
|
if (
|
|
@@ -6963,7 +7369,7 @@ const _joinsPriorEntry = (writer, prior, entry, parted) => {
|
|
|
6963
7369
|
prior.taken,
|
|
6964
7370
|
span,
|
|
6965
7371
|
prior.prelude,
|
|
6966
|
-
|
|
7372
|
+
_entryPrelude(entry)
|
|
6967
7373
|
)
|
|
6968
7374
|
) {
|
|
6969
7375
|
return false;
|
|
@@ -7161,13 +7567,7 @@ const _mergeIntoDistantRule = (writer, entry) => {
|
|
|
7161
7567
|
// grew is longer than the one that was taken.
|
|
7162
7568
|
const preludeNow = span.len - block.length;
|
|
7163
7569
|
if (
|
|
7164
|
-
!_lendSelectorsTo(
|
|
7165
|
-
writer,
|
|
7166
|
-
taken,
|
|
7167
|
-
span,
|
|
7168
|
-
preludeNow,
|
|
7169
|
-
entry.text.slice(0, entry.prelude)
|
|
7170
|
-
)
|
|
7570
|
+
!_lendSelectorsTo(writer, taken, span, preludeNow, _entryPrelude(entry))
|
|
7171
7571
|
) {
|
|
7172
7572
|
return false;
|
|
7173
7573
|
}
|
|
@@ -7227,13 +7627,11 @@ const _orderDistantLists = (writer) => {
|
|
|
7227
7627
|
* Merge the box families whose four longhands two joined blocks wrote between
|
|
7228
7628
|
* them, as `_mergeBoxLonghands` does for one block, so the join prints what the
|
|
7229
7629
|
* one rule written whole would.
|
|
7230
|
-
* @param {
|
|
7231
|
-
* @returns {
|
|
7630
|
+
* @param {PrintedDeclaration[]} declarations the joined block's declarations
|
|
7631
|
+
* @returns {PrintedDeclaration[]} them, each family it could merge merged
|
|
7232
7632
|
*/
|
|
7233
|
-
const _mergeJoinedBoxLonghands = (
|
|
7234
|
-
if (!_S._transforms.mergeLonghands) return
|
|
7235
|
-
const declarations = _blockDeclarations(body);
|
|
7236
|
-
if (declarations === null) return body;
|
|
7633
|
+
const _mergeJoinedBoxLonghands = (declarations) => {
|
|
7634
|
+
if (!_S._transforms.mergeLonghands) return declarations;
|
|
7237
7635
|
/** @type {Map<string, number>} */
|
|
7238
7636
|
const at = new Map();
|
|
7239
7637
|
/** @type {Set<string>} */
|
|
@@ -7285,13 +7683,29 @@ const _mergeJoinedBoxLonghands = (body) => {
|
|
|
7285
7683
|
const box = _collapseBox(values);
|
|
7286
7684
|
if (box === null) continue;
|
|
7287
7685
|
if (texts === null) texts = declarations.map((one) => one.text);
|
|
7288
|
-
texts[first] =
|
|
7289
|
-
|
|
7686
|
+
texts[first] = `${shorthand}:${_joinSlots(box)}${
|
|
7687
|
+
important ? "!important" : ""
|
|
7688
|
+
}`;
|
|
7290
7689
|
for (const index of indexes) if (index !== first) texts[index] = "";
|
|
7291
7690
|
}
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7691
|
+
if (texts === null) return declarations;
|
|
7692
|
+
/** @type {PrintedDeclaration[]} */
|
|
7693
|
+
const out = [];
|
|
7694
|
+
for (let i = 0; i < texts.length; i++) {
|
|
7695
|
+
const text = texts[i];
|
|
7696
|
+
if (text.length === 0) continue;
|
|
7697
|
+
if (text === declarations[i].text) {
|
|
7698
|
+
out.push(declarations[i]);
|
|
7699
|
+
continue;
|
|
7700
|
+
}
|
|
7701
|
+
const colon = text.indexOf(":");
|
|
7702
|
+
out.push({
|
|
7703
|
+
property: text.slice(0, colon),
|
|
7704
|
+
value: text.slice(colon + 1),
|
|
7705
|
+
text
|
|
7706
|
+
});
|
|
7707
|
+
}
|
|
7708
|
+
return out;
|
|
7295
7709
|
};
|
|
7296
7710
|
|
|
7297
7711
|
/**
|
|
@@ -7304,7 +7718,7 @@ const _mergeJoinedBoxLonghands = (body) => {
|
|
|
7304
7718
|
const _joinedAtRuleSpans = (merged) => {
|
|
7305
7719
|
// An at-rule's entry is always built with its children, never `null`.
|
|
7306
7720
|
const children = /** @type {RuleEntry[]} */ (merged.children);
|
|
7307
|
-
const prelude =
|
|
7721
|
+
const prelude = _entryPrelude(merged);
|
|
7308
7722
|
/** @type {RuleSpan[]} */
|
|
7309
7723
|
const spans = [];
|
|
7310
7724
|
let at = 0;
|
|
@@ -7322,7 +7736,8 @@ const _joinedAtRuleSpans = (merged) => {
|
|
|
7322
7736
|
scope: _rootScope(),
|
|
7323
7737
|
key: child.text,
|
|
7324
7738
|
at,
|
|
7325
|
-
len: child.text.length
|
|
7739
|
+
len: child.text.length,
|
|
7740
|
+
taken: null
|
|
7326
7741
|
});
|
|
7327
7742
|
} else {
|
|
7328
7743
|
const inner = _joinedAtRuleSpans(child);
|
|
@@ -7332,7 +7747,8 @@ const _joinedAtRuleSpans = (merged) => {
|
|
|
7332
7747
|
scope: _rootScope(),
|
|
7333
7748
|
key: UNKEYED,
|
|
7334
7749
|
at,
|
|
7335
|
-
len: child.text.length
|
|
7750
|
+
len: child.text.length,
|
|
7751
|
+
taken: null
|
|
7336
7752
|
});
|
|
7337
7753
|
}
|
|
7338
7754
|
for (const span of inner.spans) {
|
|
@@ -7340,7 +7756,8 @@ const _joinedAtRuleSpans = (merged) => {
|
|
|
7340
7756
|
scope: _enclosingRuleScope(span.scope, inner.keyPrelude),
|
|
7341
7757
|
key: span.key,
|
|
7342
7758
|
at: at + inner.bodyAt + span.at,
|
|
7343
|
-
len: span.len
|
|
7759
|
+
len: span.len,
|
|
7760
|
+
taken: null
|
|
7344
7761
|
});
|
|
7345
7762
|
}
|
|
7346
7763
|
}
|
|
@@ -7388,7 +7805,7 @@ const _joinedSpans = (before, beforeOwn, entry, own, merged) => {
|
|
|
7388
7805
|
) {
|
|
7389
7806
|
return _WHOLE_TEXT_SPANS;
|
|
7390
7807
|
}
|
|
7391
|
-
const prelude =
|
|
7808
|
+
const prelude = _entryPrelude(merged);
|
|
7392
7809
|
const length = entry.text.length - entry.prelude - 2;
|
|
7393
7810
|
const at = merged.text.length - 1 - length - (merged.prelude + 1);
|
|
7394
7811
|
const shift = at + own.bodyAt - (entry.prelude + 1);
|
|
@@ -7399,7 +7816,8 @@ const _joinedSpans = (before, beforeOwn, entry, own, merged) => {
|
|
|
7399
7816
|
scope: span.scope,
|
|
7400
7817
|
key: span.key,
|
|
7401
7818
|
at: span.at + shift,
|
|
7402
|
-
len: span.len
|
|
7819
|
+
len: span.len,
|
|
7820
|
+
taken: null
|
|
7403
7821
|
});
|
|
7404
7822
|
}
|
|
7405
7823
|
return {
|
|
@@ -7444,8 +7862,7 @@ const _takeTopLevel = (node, writer, offset, line, column) => {
|
|
|
7444
7862
|
const at = writer.takeRetractable(node, offset, line, column, own);
|
|
7445
7863
|
_settlePrior(writer);
|
|
7446
7864
|
if (_topLevelRules !== null) {
|
|
7447
|
-
|
|
7448
|
-
const taken = { piece: at, text: own, spans: [], empties: -1 };
|
|
7865
|
+
const taken = new TakenPiece(at, own, -1);
|
|
7449
7866
|
if (_prefixPieces === null) _prefixPieces = new Map();
|
|
7450
7867
|
_prefixPieces.set(at, taken);
|
|
7451
7868
|
_topLevelRules.push(taken);
|
|
@@ -7697,8 +8114,7 @@ const _walkTopLevel = (node, writer) => {
|
|
|
7697
8114
|
_nodeCount = 0;
|
|
7698
8115
|
_flatTop = 0;
|
|
7699
8116
|
// Body indices recycle with node ids.
|
|
7700
|
-
|
|
7701
|
-
_ruleBodies.length = 0;
|
|
8117
|
+
_dropBodies();
|
|
7702
8118
|
if (_walkStopped && writer === undefined) throw WALK_STOPPED;
|
|
7703
8119
|
};
|
|
7704
8120
|
|
|
@@ -7712,8 +8128,7 @@ const _recycleTopLevel = (node) => {
|
|
|
7712
8128
|
if (_flatTop > _flatPeak) _flatPeak = _flatTop;
|
|
7713
8129
|
_nodeCount = 0;
|
|
7714
8130
|
_flatTop = 0;
|
|
7715
|
-
|
|
7716
|
-
_ruleBodies.length = 0;
|
|
8131
|
+
_dropBodies();
|
|
7717
8132
|
};
|
|
7718
8133
|
|
|
7719
8134
|
// The store buffers grow to the largest single top-level rule ever parsed and
|
|
@@ -8048,6 +8463,21 @@ const grammar = (input, visitors, writer, options) => {
|
|
|
8048
8463
|
}
|
|
8049
8464
|
_visitors = visitors;
|
|
8050
8465
|
_commentBucket = visitors[NodeType.Comment];
|
|
8466
|
+
_blockMemo =
|
|
8467
|
+
writer !== undefined &&
|
|
8468
|
+
writer.options.mode === "minify" &&
|
|
8469
|
+
visitors.length === 0 &&
|
|
8470
|
+
_unusedSymbols === null &&
|
|
8471
|
+
!_S._prefixingOn &&
|
|
8472
|
+
!_colorFallbacksNeeded &&
|
|
8473
|
+
_S._renderEmbeddedSource === undefined &&
|
|
8474
|
+
_S._deferEmbeddedSource === undefined
|
|
8475
|
+
? new Map()
|
|
8476
|
+
: null;
|
|
8477
|
+
_declarationMemo = _blockMemo === null ? null : new Map();
|
|
8478
|
+
_blockMemoScopes.clear();
|
|
8479
|
+
_singleValueKeys = _blockMemo === null ? null : new Set();
|
|
8480
|
+
_declarationMemoKey = "";
|
|
8051
8481
|
_walkStopped = false;
|
|
8052
8482
|
|
|
8053
8483
|
// WHY: the comment sink fires the `Comment` visitor bucket and, while
|
|
@@ -8210,6 +8640,15 @@ const grammar = (input, visitors, writer, options) => {
|
|
|
8210
8640
|
_blockSpans.length = 0;
|
|
8211
8641
|
_ruleScopes = null;
|
|
8212
8642
|
_rootRuleScope = null;
|
|
8643
|
+
_shadowDeclared.clear();
|
|
8644
|
+
_blockMemo = null;
|
|
8645
|
+
_blockMemoScopes.clear();
|
|
8646
|
+
_blockMemoTable = _blockMemoKeyTable = new Map();
|
|
8647
|
+
_declarationMemo = null;
|
|
8648
|
+
_singleValueKeys = null;
|
|
8649
|
+
_blockMemoNode = null;
|
|
8650
|
+
_blockMemoBody = undefined;
|
|
8651
|
+
_blockMemoKey = "";
|
|
8213
8652
|
// Each holds a piece of the sheet just printed, so the last one printed
|
|
8214
8653
|
// would be held until the next parse replaces them.
|
|
8215
8654
|
_distantRules.clear();
|
|
@@ -8221,7 +8660,9 @@ const grammar = (input, visitors, writer, options) => {
|
|
|
8221
8660
|
_anonymousLayers = 0;
|
|
8222
8661
|
_S._input = "";
|
|
8223
8662
|
_originalInput = "";
|
|
8224
|
-
_locConverter = /** @type {LocConverter} */ (
|
|
8663
|
+
_locConverter = /** @type {LocConverter} */ (
|
|
8664
|
+
/** @type {LocConverter | null} */ (null)
|
|
8665
|
+
);
|
|
8225
8666
|
_declBodies.length = 0;
|
|
8226
8667
|
_ruleBodies.length = 0;
|
|
8227
8668
|
_flatTop = 0;
|
|
@@ -8230,7 +8671,9 @@ const grammar = (input, visitors, writer, options) => {
|
|
|
8230
8671
|
_flatGrowHint = _flatPeak;
|
|
8231
8672
|
_flat = EMPTY_I32;
|
|
8232
8673
|
}
|
|
8233
|
-
_visitors = /** @type {CompiledVisitorMap} */ (
|
|
8674
|
+
_visitors = /** @type {CompiledVisitorMap} */ (
|
|
8675
|
+
/** @type {CompiledVisitorMap | never[]} */ ([])
|
|
8676
|
+
);
|
|
8234
8677
|
_commentBucket = undefined;
|
|
8235
8678
|
if (_capacity > _SHRINK_CAPACITY) {
|
|
8236
8679
|
// +1: node ids are 1-based and grow fires at `id >= capacity`.
|
|
@@ -8891,6 +9334,10 @@ const _landsAlike = (value, shorter) => {
|
|
|
8891
9334
|
* @returns {string} the rounded number, or `num`
|
|
8892
9335
|
*/
|
|
8893
9336
|
const _roundSignificant = (num, unit = "") => {
|
|
9337
|
+
// A number written in at most six characters carries at most six significant
|
|
9338
|
+
// digits, a sign and dot only taking away, so rounding hands back what it was
|
|
9339
|
+
// given. Almost every number is this short.
|
|
9340
|
+
if (num.length <= _SIGNIFICANT_DIGITS) return num;
|
|
8894
9341
|
const digits =
|
|
8895
9342
|
unit === "" ||
|
|
8896
9343
|
unit === "%" ||
|
|
@@ -8898,15 +9345,24 @@ const _roundSignificant = (num, unit = "") => {
|
|
|
8898
9345
|
ANGLE_UNITS.has(unit)
|
|
8899
9346
|
? _SIGNIFICANT_DIGITS
|
|
8900
9347
|
: _SCALED_LENGTH_DIGITS;
|
|
8901
|
-
// A number written in at most six characters carries at most six significant
|
|
8902
|
-
// digits, a sign and dot only taking away, so rounding hands back what it was
|
|
8903
|
-
// given. Almost every number is this short.
|
|
8904
|
-
if (num.length <= _SIGNIFICANT_DIGITS) return num;
|
|
8905
9348
|
if (num.includes("e") || num.includes("E")) return num;
|
|
8906
9349
|
const value = Number(num);
|
|
8907
9350
|
if (!Number.isFinite(value) || Math.abs(value) >= _ROUNDING_LIMIT) return num;
|
|
8908
9351
|
let rounded = value.toPrecision(digits);
|
|
8909
|
-
if (
|
|
9352
|
+
if (unit === "%") {
|
|
9353
|
+
// Gecko parses a percentage as a single-precision fraction laid out in 1/60px,
|
|
9354
|
+
// so the digits must reach that float: `14.285714%` drifts, `14.2857143%` not.
|
|
9355
|
+
const parsed = Math.fround(value / 100);
|
|
9356
|
+
for (
|
|
9357
|
+
let more = digits;
|
|
9358
|
+
more < _SCALED_LENGTH_DIGITS &&
|
|
9359
|
+
Math.fround(Number(rounded) / 100) !== parsed;
|
|
9360
|
+
more++
|
|
9361
|
+
) {
|
|
9362
|
+
rounded = value.toPrecision(more + 1);
|
|
9363
|
+
}
|
|
9364
|
+
if (Math.fround(Number(rounded) / 100) !== parsed) return num;
|
|
9365
|
+
} else if (digits === _SCALED_LENGTH_DIGITS) {
|
|
8910
9366
|
// The fewest digits landing where the written length does, asked again of
|
|
8911
9367
|
// each answer until it holds, which is what a second pass would ask.
|
|
8912
9368
|
let from = value;
|
|
@@ -9651,6 +10107,17 @@ const _readByEveryEngine = (profile) => {
|
|
|
9651
10107
|
return true;
|
|
9652
10108
|
};
|
|
9653
10109
|
|
|
10110
|
+
/**
|
|
10111
|
+
* Whether the targets read an ability: the selection's browsers, or with none
|
|
10112
|
+
* each engine shipping today, which is what `dropOverriddenDeclarations` assumes.
|
|
10113
|
+
* @param {number | undefined} profile its `getSupportProfiles()` row
|
|
10114
|
+
* @returns {boolean} true when the later value it names is read
|
|
10115
|
+
*/
|
|
10116
|
+
const _readsOverridingValue = (profile) =>
|
|
10117
|
+
_prefixBrowsers === null
|
|
10118
|
+
? profile !== undefined && _readByEveryEngine(profile)
|
|
10119
|
+
: _readsAll(profile);
|
|
10120
|
+
|
|
9654
10121
|
/**
|
|
9655
10122
|
* The vendor spellings at least one target browser still needs for a construct —
|
|
9656
10123
|
* a target at version V needs spelling S when some `[browser, from, to]` of S has
|
|
@@ -10776,6 +11243,20 @@ const _minifyPolarColorFunction = (
|
|
|
10776
11243
|
fn === "lab" || fn === "lch"
|
|
10777
11244
|
? _labToLinearSrgb(l, a, b)
|
|
10778
11245
|
: _oklabToLinearSrgb(l, a, b);
|
|
11246
|
+
// WHY: a hex mixed in `oklch` reaches it through a conversion, and Chromium
|
|
11247
|
+
// reads a hue there as missing below a chroma of 0.02 — so `color-mix(in
|
|
11248
|
+
// oklch, currentColor 35%, #0000)` paints hue 0 where `oklch()` named one.
|
|
11249
|
+
if (fn === "oklch" && (a !== 0 || b !== 0)) {
|
|
11250
|
+
const space = getColorSpaceModel().get(fn);
|
|
11251
|
+
const clamped = linear.map((c) => Math.min(1, Math.max(0, c)));
|
|
11252
|
+
if (
|
|
11253
|
+
space !== undefined &&
|
|
11254
|
+
space.uncertainHue !== null &&
|
|
11255
|
+
space.uncertainHue(space.to(clamped))
|
|
11256
|
+
) {
|
|
11257
|
+
return null;
|
|
11258
|
+
}
|
|
11259
|
+
}
|
|
10779
11260
|
// `_channelByte` decides the gamut from the encoded value, where the
|
|
10780
11261
|
// question is whether clamping would move the byte.
|
|
10781
11262
|
raw = linear.map((c) => _gammaEncode(c) * 255);
|
|
@@ -10999,7 +11480,7 @@ const _resolveColor = (text) => {
|
|
|
10999
11480
|
}
|
|
11000
11481
|
// Every call that answers records them, so a non-null answer is one.
|
|
11001
11482
|
const raw = /** @type {number[]} */ (
|
|
11002
|
-
/** @type {
|
|
11483
|
+
/** @type {number[] | null} */ (_fallbackChannels)
|
|
11003
11484
|
);
|
|
11004
11485
|
return {
|
|
11005
11486
|
linear: raw.map((channel) => _gammaDecode(channel / 255)),
|
|
@@ -11832,7 +12313,7 @@ const _CUSTOM_MEDIA_REFERENCE_RE = /^\(\s*(--[^\s()]+)\s*\)$/;
|
|
|
11832
12313
|
// The same, anywhere in a printed `(…)` group.
|
|
11833
12314
|
const _NESTED_CUSTOM_MEDIA_REFERENCE_RE = /\(\s*(--[^\s()]+)\s*\)/g;
|
|
11834
12315
|
// A media type: an identifier, which no keyword between conditions is.
|
|
11835
|
-
const _MEDIA_TYPE_RE = /^-?[a-
|
|
12316
|
+
const _MEDIA_TYPE_RE = /^-?[a-zA-Z_\u0080-][\w\u0080--]*$/;
|
|
11836
12317
|
|
|
11837
12318
|
/**
|
|
11838
12319
|
* @param {string} token a printed query token
|
|
@@ -12388,10 +12869,12 @@ const _foldPseudoNames = (parts) => {
|
|
|
12388
12869
|
// not, `linearGradient` being an SVG element, and nor does an id, class or
|
|
12389
12870
|
// attribute value. A functional pseudo folds its own name alone.
|
|
12390
12871
|
if (second !== -1 && parts[second] === ":") {
|
|
12391
|
-
|
|
12392
|
-
|
|
12393
|
-
part
|
|
12394
|
-
|
|
12872
|
+
if (_S._transforms.foldCase && !part.includes("(")) {
|
|
12873
|
+
const lowered = asciiLowercaseName(part);
|
|
12874
|
+
if (lowered !== part) {
|
|
12875
|
+
part = lowered;
|
|
12876
|
+
parts[i] = lowered;
|
|
12877
|
+
}
|
|
12395
12878
|
}
|
|
12396
12879
|
// Folded first, so the legacy name below is matched against the folded
|
|
12397
12880
|
// text rather than folded a second time.
|
|
@@ -12453,6 +12936,16 @@ const _isCompoundText = (selector) => {
|
|
|
12453
12936
|
* @param {string[]} parts a selector's printed parts, rewritten in place
|
|
12454
12937
|
*/
|
|
12455
12938
|
const _unwrapLoneIs = (parts) => {
|
|
12939
|
+
// Almost no selector holds an `:is()`, and the walk below reads every part.
|
|
12940
|
+
let candidate = false;
|
|
12941
|
+
for (let i = 0; i < parts.length && !candidate; i++) {
|
|
12942
|
+
const part = parts[i];
|
|
12943
|
+
candidate =
|
|
12944
|
+
part.length > 4 &&
|
|
12945
|
+
part.charCodeAt(2) === CC_LEFT_PARENTHESIS &&
|
|
12946
|
+
(part.charCodeAt(0) | 0x20) === CC_LOWER_I;
|
|
12947
|
+
}
|
|
12948
|
+
if (!candidate) return;
|
|
12456
12949
|
let before = -1;
|
|
12457
12950
|
// Past a pseudo-element a compound takes only a few pseudo-classes, which an
|
|
12458
12951
|
// `:is()` there may hold and a bare compound may not.
|
|
@@ -12473,12 +12966,16 @@ const _unwrapLoneIs = (parts) => {
|
|
|
12473
12966
|
) {
|
|
12474
12967
|
pastElement = true;
|
|
12475
12968
|
}
|
|
12476
|
-
const
|
|
12477
|
-
if (
|
|
12969
|
+
const isCall =
|
|
12478
12970
|
!pastElement &&
|
|
12479
12971
|
call.length > 4 &&
|
|
12480
|
-
|
|
12481
|
-
call.charCodeAt(
|
|
12972
|
+
(call.charCodeAt(0) | 0x20) === CC_LOWER_I &&
|
|
12973
|
+
(call.charCodeAt(1) | 0x20) === CC_LOWER_S &&
|
|
12974
|
+
call.charCodeAt(2) === CC_LEFT_PARENTHESIS &&
|
|
12975
|
+
call.charCodeAt(call.length - 1) === CC_RIGHT_PARENTHESIS;
|
|
12976
|
+
const inner = isCall ? call.slice(3, -1) : "";
|
|
12977
|
+
if (
|
|
12978
|
+
isCall &&
|
|
12482
12979
|
_isCompoundText(inner) &&
|
|
12483
12980
|
!inner.includes("::") &&
|
|
12484
12981
|
!_LEGACY_PSEUDO_ELEMENT_RE.test(inner) &&
|
|
@@ -12697,7 +13194,8 @@ const _dropRedundantSupportsParens = (parts) => {
|
|
|
12697
13194
|
continue;
|
|
12698
13195
|
}
|
|
12699
13196
|
let text = part;
|
|
12700
|
-
|
|
13197
|
+
// Only an opening pair is one to drop, which almost no condition holds.
|
|
13198
|
+
while (text.includes("((")) {
|
|
12701
13199
|
const close = _matchingParens(text);
|
|
12702
13200
|
if (close === null) break;
|
|
12703
13201
|
let at = -1;
|
|
@@ -12725,6 +13223,7 @@ const _dropRedundantSupportsParens = (parts) => {
|
|
|
12725
13223
|
}
|
|
12726
13224
|
if (groups !== 1) return;
|
|
12727
13225
|
const text = parts[only];
|
|
13226
|
+
if (text.charCodeAt(1) !== CC_LEFT_PARENTHESIS) return;
|
|
12728
13227
|
const close = _matchingParens(text);
|
|
12729
13228
|
if (
|
|
12730
13229
|
close !== null &&
|
|
@@ -13581,6 +14080,25 @@ const _foldFollowingLonghands = (path, items, texts, superseded) => {
|
|
|
13581
14080
|
}
|
|
13582
14081
|
return written.has(base) && _prefixedPropertyRemovable(base, property);
|
|
13583
14082
|
};
|
|
14083
|
+
// Each declaration's property, read once: the walk back from every longhand
|
|
14084
|
+
// asks again of the ones before it, and a fold keeps the property it rewrites.
|
|
14085
|
+
/** @type {(string | undefined)[]} */
|
|
14086
|
+
const properties = [];
|
|
14087
|
+
/**
|
|
14088
|
+
* The property a declaration sets, read through `_canonicalProperty`.
|
|
14089
|
+
* @param {number} at the declaration's index
|
|
14090
|
+
* @returns {string} its property
|
|
14091
|
+
*/
|
|
14092
|
+
const propertyAt = (at) => {
|
|
14093
|
+
let property = properties[at];
|
|
14094
|
+
if (property === undefined) {
|
|
14095
|
+
property = _canonicalProperty(
|
|
14096
|
+
_printedProperty(texts[at], texts[at].indexOf(":"))
|
|
14097
|
+
);
|
|
14098
|
+
properties[at] = property;
|
|
14099
|
+
}
|
|
14100
|
+
return property;
|
|
14101
|
+
};
|
|
13584
14102
|
for (let i = 0; i < items.length; i++) {
|
|
13585
14103
|
// A dropped declaration prints nothing, so nothing stands where it stood.
|
|
13586
14104
|
if (texts[i].length === 0 || superseded.has(i)) continue;
|
|
@@ -13591,7 +14109,15 @@ const _foldFollowingLonghands = (path, items, texts, superseded) => {
|
|
|
13591
14109
|
if (dropsWithPrefix(i)) continue;
|
|
13592
14110
|
if (
|
|
13593
14111
|
shorthand !== -1 &&
|
|
13594
|
-
_foldIntoEarlier(
|
|
14112
|
+
_foldIntoEarlier(
|
|
14113
|
+
path,
|
|
14114
|
+
items,
|
|
14115
|
+
texts,
|
|
14116
|
+
superseded,
|
|
14117
|
+
i,
|
|
14118
|
+
dropsWithPrefix,
|
|
14119
|
+
propertyAt
|
|
14120
|
+
)
|
|
13595
14121
|
) {
|
|
13596
14122
|
superseded.add(i);
|
|
13597
14123
|
continue;
|
|
@@ -13615,29 +14141,37 @@ let _anyLonghand = null;
|
|
|
13615
14141
|
* @param {Set<number>} superseded the indices already dropped
|
|
13616
14142
|
* @param {number} from the longhand's index
|
|
13617
14143
|
* @param {(at: number) => boolean} drops whether a declaration is dropped later
|
|
14144
|
+
* @param {(at: number) => string} propertyAt the property a declaration sets, read through `_canonicalProperty`
|
|
13618
14145
|
* @returns {boolean} true when it was folded into one before it
|
|
13619
14146
|
*/
|
|
13620
|
-
const _foldIntoEarlier = (
|
|
14147
|
+
const _foldIntoEarlier = (
|
|
14148
|
+
path,
|
|
14149
|
+
items,
|
|
14150
|
+
texts,
|
|
14151
|
+
superseded,
|
|
14152
|
+
from,
|
|
14153
|
+
drops,
|
|
14154
|
+
propertyAt
|
|
14155
|
+
) => {
|
|
13621
14156
|
if (_anyLonghand === null) {
|
|
13622
14157
|
_anyLonghand = new Set();
|
|
13623
14158
|
for (const longhands of getShorthandLonghands().values()) {
|
|
13624
14159
|
for (const longhand of longhands) _anyLonghand.add(longhand);
|
|
13625
14160
|
}
|
|
13626
14161
|
}
|
|
13627
|
-
const property =
|
|
13628
|
-
|
|
13629
|
-
|
|
13630
|
-
|
|
14162
|
+
const property = propertyAt(from);
|
|
14163
|
+
const bare =
|
|
14164
|
+
property.charCodeAt(0) === CC_HYPHEN_MINUS
|
|
14165
|
+
? property.replace(_VENDOR_ITEM_PREFIX_RE, "")
|
|
14166
|
+
: property;
|
|
14167
|
+
if (!_anyLonghand.has(bare)) {
|
|
13631
14168
|
return false;
|
|
13632
14169
|
}
|
|
13633
14170
|
for (let at = from - 1; at >= 0; at--) {
|
|
13634
14171
|
if (texts[at].length === 0 || superseded.has(at)) continue;
|
|
13635
14172
|
if (path.type(items[at]) !== NodeType.Declaration) return false;
|
|
13636
14173
|
if (drops(at)) continue;
|
|
13637
|
-
|
|
13638
|
-
_printedProperty(texts[at], texts[at].indexOf(":"))
|
|
13639
|
-
);
|
|
13640
|
-
if (_orderMatters(property, other)) {
|
|
14174
|
+
if (_orderMatters(property, propertyAt(at))) {
|
|
13641
14175
|
return _foldInto(path, items, texts, at, from);
|
|
13642
14176
|
}
|
|
13643
14177
|
}
|
|
@@ -14570,9 +15104,9 @@ const _familyValue = (property, longhands, values) => {
|
|
|
14570
15104
|
* @returns {boolean} true when no target is left reading the earlier one
|
|
14571
15105
|
*/
|
|
14572
15106
|
const _valueReadByTarget = (property, value) => {
|
|
14573
|
-
// No selection names no browser to answer for, so
|
|
14574
|
-
//
|
|
14575
|
-
if (_prefixBrowsers === null) return
|
|
15107
|
+
// No selection names no browser to answer for, so the earlier one stands
|
|
15108
|
+
// unless the option assumes each engine shipping today, read against below.
|
|
15109
|
+
if (_prefixBrowsers === null && !_dropOverriddenDeclarations) return false;
|
|
14576
15110
|
// A selection naming a browser the tables do not cover answers for less than
|
|
14577
15111
|
// the whole of it. Naming a browser states a target, which the option that
|
|
14578
15112
|
// assumes one does not override, so this stands whatever it says.
|
|
@@ -14582,7 +15116,7 @@ const _valueReadByTarget = (property, value) => {
|
|
|
14582
15116
|
const substitutions = _heldSubstitutions(value);
|
|
14583
15117
|
if (substitutions !== null) {
|
|
14584
15118
|
for (const name of substitutions) {
|
|
14585
|
-
if (!
|
|
15119
|
+
if (!_readsOverridingValue(_valueSupportedFrom(name))) return false;
|
|
14586
15120
|
}
|
|
14587
15121
|
return true;
|
|
14588
15122
|
}
|
|
@@ -14592,7 +15126,7 @@ const _valueReadByTarget = (property, value) => {
|
|
|
14592
15126
|
const components = _splitPrintedComponents(value);
|
|
14593
15127
|
if (components.length > 1) return _textDecorationRead(components);
|
|
14594
15128
|
}
|
|
14595
|
-
return
|
|
15129
|
+
return _readsOverridingValue(
|
|
14596
15130
|
_valueSupportedFrom(`${property} ${toLowerCaseIfNeeded(value)}`)
|
|
14597
15131
|
);
|
|
14598
15132
|
}
|
|
@@ -14604,9 +15138,10 @@ const _valueReadByTarget = (property, value) => {
|
|
|
14604
15138
|
return false;
|
|
14605
15139
|
}
|
|
14606
15140
|
const fn = toLowerCaseIfNeeded(value.slice(0, open));
|
|
14607
|
-
if (!
|
|
15141
|
+
if (!_readsOverridingValue(_valueSupportedFrom(fn))) return false;
|
|
14608
15142
|
if (fn.endsWith("gradient")) {
|
|
14609
|
-
|
|
15143
|
+
// A one-stop gradient is CSS Images 4's, which not every engine reads yet.
|
|
15144
|
+
return _gradientArgumentsRead(value.slice(open + 1, -1), 2);
|
|
14610
15145
|
}
|
|
14611
15146
|
const args = value.slice(open + 1, -1).match(_COLOR_ARGUMENT_RE);
|
|
14612
15147
|
if (args === null) return false;
|
|
@@ -14660,33 +15195,61 @@ const _GRADIENT_AMOUNT_RE = /^[+-]?(?:\d+\.?\d*|\.\d+)([a-z]+|%)?$/i;
|
|
|
14660
15195
|
* line, shape or position of keywords and amounts, and stops of a color every
|
|
14661
15196
|
* engine names. A call inside, or an interpolation space, is not asked here.
|
|
14662
15197
|
* @param {string} inner the printed arguments
|
|
15198
|
+
* @param {number} stopsNeeded how many color stops the arguments must hold
|
|
14663
15199
|
* @returns {boolean} true when the target reads every one
|
|
14664
15200
|
*/
|
|
14665
|
-
const _gradientArgumentsRead = (inner) => {
|
|
14666
|
-
|
|
14667
|
-
|
|
15201
|
+
const _gradientArgumentsRead = (inner, stopsNeeded) => {
|
|
15202
|
+
const args = _splitTopLevelArguments(inner);
|
|
15203
|
+
let stops = 0;
|
|
15204
|
+
for (let index = 0; index < args.length; index++) {
|
|
15205
|
+
// A line, shape or position opens the list alone; a stop is one color
|
|
15206
|
+
// and its amounts. Anything else, an empty argument too, is invalid.
|
|
15207
|
+
if (args[index].trim() === "") return false;
|
|
15208
|
+
let words = 0;
|
|
15209
|
+
let colors = 0;
|
|
15210
|
+
for (const component of _splitPrintedComponents(args[index].trim())) {
|
|
14668
15211
|
const lowered = toLowerCaseIfNeeded(component);
|
|
14669
|
-
if (_GRADIENT_KEYWORDS.has(lowered))
|
|
15212
|
+
if (_GRADIENT_KEYWORDS.has(lowered)) {
|
|
15213
|
+
if (lowered === "transparent" || lowered === "currentcolor") {
|
|
15214
|
+
colors++;
|
|
15215
|
+
} else {
|
|
15216
|
+
words++;
|
|
15217
|
+
}
|
|
15218
|
+
if (words !== 0 && (index !== 0 || colors !== 0)) return false;
|
|
15219
|
+
if (colors > 1) return false;
|
|
15220
|
+
continue;
|
|
15221
|
+
}
|
|
14670
15222
|
const amount = _GRADIENT_AMOUNT_RE.exec(lowered);
|
|
14671
15223
|
if (amount !== null) {
|
|
14672
15224
|
// A unit some target does not read drops the gradient there.
|
|
14673
15225
|
const unit = amount[1];
|
|
14674
15226
|
if (unit === undefined || unit === "%") continue;
|
|
14675
|
-
if (
|
|
14676
|
-
|
|
15227
|
+
if (!_readsOverridingValue(_valueSupportedFrom(`unit ${unit}`))) {
|
|
15228
|
+
return false;
|
|
15229
|
+
}
|
|
15230
|
+
continue;
|
|
14677
15231
|
}
|
|
15232
|
+
let color = false;
|
|
14678
15233
|
if (_LONE_HEX_RE.test(component)) {
|
|
14679
|
-
if (
|
|
14680
|
-
|
|
14681
|
-
|
|
14682
|
-
|
|
14683
|
-
|
|
14684
|
-
|
|
15234
|
+
if (
|
|
15235
|
+
component.length !== 4 &&
|
|
15236
|
+
component.length !== 7 &&
|
|
15237
|
+
!_S._hexAlphaAllowed
|
|
15238
|
+
) {
|
|
15239
|
+
return false;
|
|
15240
|
+
}
|
|
15241
|
+
color = true;
|
|
15242
|
+
} else if (
|
|
15243
|
+
getColorNameToRgb().has(lowered) &&
|
|
15244
|
+
!LATER_COLOR_NAMES.has(lowered)
|
|
15245
|
+
) {
|
|
15246
|
+
color = true;
|
|
14685
15247
|
}
|
|
14686
|
-
return false;
|
|
15248
|
+
if (!color || ++colors > 1 || words !== 0) return false;
|
|
14687
15249
|
}
|
|
15250
|
+
if (colors !== 0) stops++;
|
|
14688
15251
|
}
|
|
14689
|
-
return
|
|
15252
|
+
return stops >= stopsNeeded;
|
|
14690
15253
|
};
|
|
14691
15254
|
|
|
14692
15255
|
/**
|
|
@@ -14714,7 +15277,7 @@ const _textDecorationRead = (components) => {
|
|
|
14714
15277
|
);
|
|
14715
15278
|
if (keywords.includes(toLowerCaseIfNeeded(written))) continue;
|
|
14716
15279
|
// A color or an amount, read as a gradient's stop or length is.
|
|
14717
|
-
if (!_gradientArgumentsRead(written)) return false;
|
|
15280
|
+
if (!_gradientArgumentsRead(written, 0)) return false;
|
|
14718
15281
|
}
|
|
14719
15282
|
return true;
|
|
14720
15283
|
};
|
|
@@ -14794,6 +15357,17 @@ const _writeIsDead = (path, writer, earlier, later, keyframe) => {
|
|
|
14794
15357
|
);
|
|
14795
15358
|
};
|
|
14796
15359
|
|
|
15360
|
+
/**
|
|
15361
|
+
* A property's first word, what an unnamed property of its family starts with:
|
|
15362
|
+
* `margin` for `margin-top`.
|
|
15363
|
+
* @param {string} name a property
|
|
15364
|
+
* @returns {string} the word before its first `-`
|
|
15365
|
+
*/
|
|
15366
|
+
const _firstPropertyWord = (name) => {
|
|
15367
|
+
const dash = name.indexOf("-");
|
|
15368
|
+
return dash === -1 ? name : name.slice(0, dash);
|
|
15369
|
+
};
|
|
15370
|
+
|
|
14797
15371
|
/**
|
|
14798
15372
|
* Merge a box family's four longhands into their shorthand, which sets exactly
|
|
14799
15373
|
* those four (see `BOX_LONGHANDS`) — so the rule computes the same either way.
|
|
@@ -14869,10 +15443,9 @@ const _mergeBoxLonghands = (
|
|
|
14869
15443
|
// merges the same before and after it is reordered. A pair family states no
|
|
14870
15444
|
// prefix at all — its longhands are the two names — so a property no dataset
|
|
14871
15445
|
// names is read by either one's first segment.
|
|
14872
|
-
const
|
|
14873
|
-
|
|
14874
|
-
const
|
|
14875
|
-
const families = [prefix, ...longhands.map(head)];
|
|
15446
|
+
const prefix =
|
|
15447
|
+
BOX_FAMILY_PREFIX.get(shorthand) || _firstPropertyWord(shorthand);
|
|
15448
|
+
const families = [prefix, ...longhands.map(_firstPropertyWord)];
|
|
14876
15449
|
let blocked = false;
|
|
14877
15450
|
for (
|
|
14878
15451
|
let i = ordered[0] + 1;
|
|
@@ -14904,15 +15477,14 @@ const _mergeBoxLonghands = (
|
|
|
14904
15477
|
if (indexes.some((i) => _isImportant(decls[i]) !== important)) continue;
|
|
14905
15478
|
const values = [];
|
|
14906
15479
|
for (const i of indexes) {
|
|
14907
|
-
|
|
14908
|
-
if (components.length !== 1) break;
|
|
15480
|
+
if (!_isSingleValue(path, decls[i], writer)) break;
|
|
14909
15481
|
// What the declaration prints, not what its tokens spell: a zero length
|
|
14910
15482
|
// loses its unit as a declaration is written, and a token knows no property.
|
|
14911
15483
|
const text = writer.get(decls[i]);
|
|
14912
15484
|
const colon = text.indexOf(":");
|
|
14913
15485
|
values.push(
|
|
14914
15486
|
colon === -1
|
|
14915
|
-
?
|
|
15487
|
+
? _valueComponents(path, decls[i], writer)[0]
|
|
14916
15488
|
: text.slice(colon + 1, _printedValueEnd(text, colon))
|
|
14917
15489
|
);
|
|
14918
15490
|
}
|
|
@@ -15027,7 +15599,7 @@ const _mergeBoxLonghands = (
|
|
|
15027
15599
|
};
|
|
15028
15600
|
|
|
15029
15601
|
// A `<custom-ident>` as printed; one the printer keeps escaped fails it.
|
|
15030
|
-
const _GRID_IDENT_RE = /^(?:--|-?[a-
|
|
15602
|
+
const _GRID_IDENT_RE = /^(?:--|-?[a-zA-Z_\u0080-\uFFFF])[-\w\u0080-\uFFFF]*$/;
|
|
15031
15603
|
const _GRID_INTEGER_RE = /^[-+]?\d+$/;
|
|
15032
15604
|
|
|
15033
15605
|
/**
|
|
@@ -15358,6 +15930,14 @@ const MERGE_TABLES = [
|
|
|
15358
15930
|
* concatenated: its own, or one a child carries. The run that grew it settles
|
|
15359
15931
|
* it where the run ends (`_settleJoinedSeams`), so a join stays what it costs
|
|
15360
15932
|
* to append rather than re-reading the list it has
|
|
15933
|
+
* @property {string | null} list its prelude where a join wrote it, so the next
|
|
15934
|
+
* join reads or appends to it rather than cutting it back out of `text`, which
|
|
15935
|
+
* would flatten the whole run so far; null to read it off `text`
|
|
15936
|
+
* @property {string | null} block the text from its `{` on, held beside `list`
|
|
15937
|
+
* for the same reason
|
|
15938
|
+
* @property {PrintedDeclaration[] | null} declarations its block's declarations
|
|
15939
|
+
* where a join of two blocks under one prelude wrote them, so the next join
|
|
15940
|
+
* reads them rather than parsing the whole block again; null to parse `text`
|
|
15361
15941
|
*/
|
|
15362
15942
|
|
|
15363
15943
|
// Each printed rule the merge can join -> its entry, by node id. Emptied per
|
|
@@ -15450,7 +16030,10 @@ const _opaqueEntry = (text) => ({
|
|
|
15450
16030
|
listKind: LIST_KIND_SELECTOR,
|
|
15451
16031
|
children: null,
|
|
15452
16032
|
head: "",
|
|
15453
|
-
unordered: false
|
|
16033
|
+
unordered: false,
|
|
16034
|
+
list: null,
|
|
16035
|
+
block: null,
|
|
16036
|
+
declarations: null
|
|
15454
16037
|
});
|
|
15455
16038
|
|
|
15456
16039
|
/**
|
|
@@ -15462,7 +16045,7 @@ const _opaqueEntry = (text) => ({
|
|
|
15462
16045
|
const _entryListable = (entry) => {
|
|
15463
16046
|
if (entry.listable === LIST_UNKNOWN) {
|
|
15464
16047
|
entry.listable = _isJoinablePrelude(
|
|
15465
|
-
|
|
16048
|
+
_entryPrelude(entry),
|
|
15466
16049
|
entry.listKind === LIST_KIND_KEYFRAME,
|
|
15467
16050
|
entry.listKind === LIST_KIND_NESTED
|
|
15468
16051
|
)
|
|
@@ -15501,22 +16084,33 @@ const _STRING = String.raw`"(?:[^"\\]|\\[\s\S])*"|'(?:[^'\\]|\\[\s\S])*'`;
|
|
|
15501
16084
|
const _ATTRIBUTE = String.raw`\[(?:${_IDENT}\|)?${_IDENT}(?:[~|^$*]?=(?:${_IDENT}|${_STRING})(?: [iI])?)?\]`;
|
|
15502
16085
|
// CSS whitespace: U+00A0 is an identifier's character, not a separator.
|
|
15503
16086
|
const _SPACE = "[ \\t\\n\\f\\r]";
|
|
15504
|
-
|
|
16087
|
+
/**
|
|
16088
|
+
* A pattern matching the word in any ASCII case, where an `i` flag would make V8
|
|
16089
|
+
* case-fold the whole `\u00A0-\uFFFF` class too, costing milliseconds to compile.
|
|
16090
|
+
* @param {string} word a lowercase word
|
|
16091
|
+
* @returns {string} the pattern
|
|
16092
|
+
*/
|
|
16093
|
+
const _anyCase = (word) =>
|
|
16094
|
+
word.replace(/[a-z]/g, (letter) => `[${letter}${letter.toUpperCase()}]`);
|
|
16095
|
+
const _LEGACY_ELEMENT_NAMES = [...LEGACY_PSEUDO_ELEMENTS]
|
|
16096
|
+
.map(_anyCase)
|
|
16097
|
+
.join("|");
|
|
15505
16098
|
// A pseudo-class with no selector inside it: argument-less, or the `An+B` of an
|
|
15506
16099
|
// `:nth-*()`, whose grammar is closed — the one argument a shape may carry.
|
|
15507
16100
|
const _PSEUDO_CLASS = String.raw`:(?!(?:${_LEGACY_ELEMENT_NAMES})(?![-\w]))(?:(?:${[
|
|
15508
16101
|
...NTH_PSEUDO_FUNCTIONS
|
|
15509
|
-
]
|
|
15510
|
-
|
|
15511
|
-
)})\(${_SPACE}*(
|
|
16102
|
+
]
|
|
16103
|
+
.map(_anyCase)
|
|
16104
|
+
.join("|")})\(${_SPACE}*(?:${_anyCase("odd")}|${_anyCase(
|
|
16105
|
+
"even"
|
|
16106
|
+
)}|[-+]?(?:\d*[nN](?:${_SPACE}*[-+]${_SPACE}*\d+)?|\d+))${_SPACE}*\)|[-\w]+(?![-\w(]))`;
|
|
15512
16107
|
// A pseudo-element ends the selector it is in: anything after it is no shape
|
|
15513
16108
|
// an engine parses.
|
|
15514
16109
|
const _PSEUDO_ELEMENT = String.raw`(?:::[-\w]+|:(?:${_LEGACY_ELEMENT_NAMES}))(?![-\w(])`;
|
|
15515
16110
|
const _COMPOUND = `(?:\\*|${_IDENT}|[.#]${_IDENT}|${_ATTRIBUTE})(?:[.#]${_IDENT}|${_ATTRIBUTE}|${_PSEUDO_CLASS})*`;
|
|
15516
16111
|
const _COMBINATOR = `(?:${_SPACE}*[>+~]${_SPACE}*|${_SPACE}+)`;
|
|
15517
16112
|
const _JOINABLE_SELECTOR_RE = new RegExp(
|
|
15518
|
-
`^(?:${_COMPOUND}${_COMBINATOR})*${_COMPOUND}(?:${_PSEUDO_ELEMENT})
|
|
15519
|
-
"i"
|
|
16113
|
+
`^(?:${_COMPOUND}${_COMBINATOR})*${_COMPOUND}(?:${_PSEUDO_ELEMENT})?$`
|
|
15520
16114
|
);
|
|
15521
16115
|
|
|
15522
16116
|
// The same, for a rule nested in another: `&` joins there because an engine that
|
|
@@ -15524,8 +16118,7 @@ const _JOINABLE_SELECTOR_RE = new RegExp(
|
|
|
15524
16118
|
// dropped together rather than one taking the other down.
|
|
15525
16119
|
const _NESTED_COMPOUND = `(?:&(?:${_COMPOUND})?|${_COMPOUND})`;
|
|
15526
16120
|
const _JOINABLE_NESTED_RE = new RegExp(
|
|
15527
|
-
`^(?:${_NESTED_COMPOUND}${_COMBINATOR})*${_NESTED_COMPOUND}(?:${_PSEUDO_ELEMENT})
|
|
15528
|
-
"i"
|
|
16121
|
+
`^(?:${_NESTED_COMPOUND}${_COMBINATOR})*${_NESTED_COMPOUND}(?:${_PSEUDO_ELEMENT})?$`
|
|
15529
16122
|
);
|
|
15530
16123
|
|
|
15531
16124
|
// A keyframe selector is a percentage or `to` — `from` is already printed `0%`.
|
|
@@ -15717,6 +16310,8 @@ const _blockProperties = (body) => {
|
|
|
15717
16310
|
// The `!important` a printed declaration ends in, whatever it was written as.
|
|
15718
16311
|
const _PRINTED_IMPORTANT_RE = /!\s*important$/i;
|
|
15719
16312
|
|
|
16313
|
+
/** @typedef {{ property: string, value: string, text: string }} PrintedDeclaration one declaration of a printed block: its lowercased property, its value and its whole text */
|
|
16314
|
+
|
|
15720
16315
|
/**
|
|
15721
16316
|
* The declarations one printed block holds, each as the whole of what it is
|
|
15722
16317
|
* written as. Built on the same walk `_blockProperties` makes, since what a
|
|
@@ -15724,10 +16319,10 @@ const _PRINTED_IMPORTANT_RE = /!\s*important$/i;
|
|
|
15724
16319
|
* else — a nested rule of its own, whose declarations are read at its place
|
|
15725
16320
|
* rather than at the block's.
|
|
15726
16321
|
* @param {string} body the block's printed body, between its braces
|
|
15727
|
-
* @returns {
|
|
16322
|
+
* @returns {PrintedDeclaration[] | null} the declarations, in order, or null
|
|
15728
16323
|
*/
|
|
15729
16324
|
const _blockDeclarations = (body) => {
|
|
15730
|
-
/** @type {
|
|
16325
|
+
/** @type {PrintedDeclaration[]} */
|
|
15731
16326
|
const out = [];
|
|
15732
16327
|
let depth = 0;
|
|
15733
16328
|
let quote = 0;
|
|
@@ -15807,6 +16402,28 @@ const _rangeEquals = (a, aStart, aEnd, b, bStart, bEnd) => {
|
|
|
15807
16402
|
return true;
|
|
15808
16403
|
};
|
|
15809
16404
|
|
|
16405
|
+
/**
|
|
16406
|
+
* A rule's prelude, read from where a join holds it.
|
|
16407
|
+
* @param {RuleEntry} entry the rule
|
|
16408
|
+
* @returns {string} its prelude, as printed
|
|
16409
|
+
*/
|
|
16410
|
+
const _entryPrelude = (entry) =>
|
|
16411
|
+
entry.list === null ? entry.text.slice(0, entry.prelude) : entry.list;
|
|
16412
|
+
|
|
16413
|
+
/**
|
|
16414
|
+
* Whether two rules' blocks say the same, each read from where it is held.
|
|
16415
|
+
* @param {RuleEntry} a one rule
|
|
16416
|
+
* @param {RuleEntry} b another
|
|
16417
|
+
* @returns {boolean} true when the blocks are equal
|
|
16418
|
+
*/
|
|
16419
|
+
const _blocksEqual = (a, b) => {
|
|
16420
|
+
const aText = a.block === null ? a.text : a.block;
|
|
16421
|
+
const aStart = a.block === null ? a.prelude : 0;
|
|
16422
|
+
const bText = b.block === null ? b.text : b.block;
|
|
16423
|
+
const bStart = b.block === null ? b.prelude : 0;
|
|
16424
|
+
return _rangeEquals(aText, aStart, aText.length, bText, bStart, bText.length);
|
|
16425
|
+
};
|
|
16426
|
+
|
|
15810
16427
|
// A layer with no name: the one at-rule prelude that is not the same rule twice.
|
|
15811
16428
|
const ANONYMOUS_LAYER_RE = /^@layer[ \t\n\r\f]*$/i;
|
|
15812
16429
|
|
|
@@ -15902,7 +16519,11 @@ const _joinedHead = (joined) => {
|
|
|
15902
16519
|
* @returns {string} the rule the block prints as
|
|
15903
16520
|
*/
|
|
15904
16521
|
const _joinedBlockText = (prelude, head, joined) => {
|
|
15905
|
-
|
|
16522
|
+
const last = joined[joined.length - 1];
|
|
16523
|
+
let lastText = last.text;
|
|
16524
|
+
// Read off the block where a join holds one: the text before it is a list a
|
|
16525
|
+
// run of joins is still growing, which reading any of the text flattens.
|
|
16526
|
+
if (last.block !== null) return `${prelude}{${head}${lastText}}`;
|
|
15906
16527
|
while (
|
|
15907
16528
|
lastText.length !== 0 &&
|
|
15908
16529
|
lastText.charCodeAt(lastText.length - 1) === CC_SEMICOLON
|
|
@@ -15943,16 +16564,16 @@ const _joinRuleEntries = (before, entry, owned) => {
|
|
|
15943
16564
|
// cutting each one's prelude and block out to answer that is two pieces of
|
|
15944
16565
|
// string per meeting for an answer that is usually no.
|
|
15945
16566
|
const preludesEqual = _rangeEquals(
|
|
15946
|
-
before.text,
|
|
16567
|
+
before.list === null ? before.text : before.list,
|
|
15947
16568
|
0,
|
|
15948
16569
|
before.prelude,
|
|
15949
|
-
entry.text,
|
|
16570
|
+
entry.list === null ? entry.text : entry.list,
|
|
15950
16571
|
0,
|
|
15951
16572
|
entry.prelude
|
|
15952
16573
|
);
|
|
15953
16574
|
if (before.atRule) {
|
|
15954
16575
|
if (!preludesEqual) return null;
|
|
15955
|
-
const beforePrelude =
|
|
16576
|
+
const beforePrelude = _entryPrelude(before);
|
|
15956
16577
|
// CSS Cascade 5 §6.4.1: every `@layer {` opens a layer of its own, and a
|
|
15957
16578
|
// later layer beats an earlier one whatever the selectors say — so joining
|
|
15958
16579
|
// the two hands the block back to specificity.
|
|
@@ -16036,17 +16657,13 @@ const _joinRuleEntries = (before, entry, owned) => {
|
|
|
16036
16657
|
listKind: LIST_KIND_SELECTOR,
|
|
16037
16658
|
children: joined,
|
|
16038
16659
|
head,
|
|
16039
|
-
unordered
|
|
16660
|
+
unordered,
|
|
16661
|
+
list: beforePrelude,
|
|
16662
|
+
block: null,
|
|
16663
|
+
declarations: null
|
|
16040
16664
|
};
|
|
16041
16665
|
}
|
|
16042
|
-
const blocksEqual =
|
|
16043
|
-
before.text,
|
|
16044
|
-
before.prelude,
|
|
16045
|
-
before.text.length,
|
|
16046
|
-
entry.text,
|
|
16047
|
-
entry.prelude,
|
|
16048
|
-
entry.text.length
|
|
16049
|
-
);
|
|
16666
|
+
const blocksEqual = _blocksEqual(before, entry);
|
|
16050
16667
|
// The same selector twice is one rule: nothing stands between them, so its
|
|
16051
16668
|
// declarations are read in the order they were written either way.
|
|
16052
16669
|
if (preludesEqual) {
|
|
@@ -16056,12 +16673,14 @@ const _joinRuleEntries = (before, entry, owned) => {
|
|
|
16056
16673
|
// Declarations after a nested rule are the implicit `& {…}` the engine
|
|
16057
16674
|
// builds for them, which is a rule the sheet did not have.
|
|
16058
16675
|
if (!before.plain) return null;
|
|
16059
|
-
const beforePrelude =
|
|
16060
|
-
const body = before.text.slice(before.prelude + 1, -1);
|
|
16676
|
+
const beforePrelude = _entryPrelude(before);
|
|
16061
16677
|
const rest = entry.text.slice(entry.prelude + 1, -1);
|
|
16062
16678
|
// One block holds a property once, so two blocks join only where the later
|
|
16063
16679
|
// declaration is one the earlier could not have been read behind.
|
|
16064
|
-
const earlier =
|
|
16680
|
+
const earlier =
|
|
16681
|
+
before.declarations === null
|
|
16682
|
+
? _blockDeclarations(before.text.slice(before.prelude + 1, -1))
|
|
16683
|
+
: before.declarations;
|
|
16065
16684
|
if (earlier === null) return null;
|
|
16066
16685
|
// The later block's declarations, and only where it holds nothing else: a
|
|
16067
16686
|
// nested rule leaves the properties readable but not their values.
|
|
@@ -16109,19 +16728,42 @@ const _joinRuleEntries = (before, entry, owned) => {
|
|
|
16109
16728
|
}
|
|
16110
16729
|
const kept =
|
|
16111
16730
|
dropped.size === 0
|
|
16112
|
-
?
|
|
16113
|
-
: earlier
|
|
16114
|
-
|
|
16115
|
-
|
|
16116
|
-
|
|
16117
|
-
|
|
16118
|
-
|
|
16119
|
-
|
|
16120
|
-
|
|
16121
|
-
|
|
16122
|
-
|
|
16123
|
-
|
|
16124
|
-
|
|
16731
|
+
? earlier
|
|
16732
|
+
: earlier.filter((_, at) => !dropped.has(at));
|
|
16733
|
+
const added =
|
|
16734
|
+
later !== null
|
|
16735
|
+
? later
|
|
16736
|
+
: rest.length === 0
|
|
16737
|
+
? []
|
|
16738
|
+
: _blockDeclarations(rest);
|
|
16739
|
+
/** @type {PrintedDeclaration[] | null} */
|
|
16740
|
+
let declarations = null;
|
|
16741
|
+
let joined;
|
|
16742
|
+
// Carried as a list only where reading the joined text back would split it
|
|
16743
|
+
// the same way, which a quote the split reads as left open would not.
|
|
16744
|
+
if (
|
|
16745
|
+
added === null ||
|
|
16746
|
+
!_lastDeclarationCloses(added) ||
|
|
16747
|
+
(before.declarations === null && !_lastDeclarationCloses(earlier))
|
|
16748
|
+
) {
|
|
16749
|
+
const keptText = kept.map((one) => one.text).join(";");
|
|
16750
|
+
joined = _orderJoinedBody(
|
|
16751
|
+
keptText.length === 0 || rest.length === 0
|
|
16752
|
+
? keptText + rest
|
|
16753
|
+
: _mergeJoinedBody(`${keptText};${rest}`),
|
|
16754
|
+
before.plain && entry.plain
|
|
16755
|
+
);
|
|
16756
|
+
} else {
|
|
16757
|
+
declarations = _orderJoinedDeclarations(
|
|
16758
|
+
kept.length === 0 || added.length === 0
|
|
16759
|
+
? [...kept, ...added]
|
|
16760
|
+
: _mergeJoinedBoxLonghands([...kept, ...added]),
|
|
16761
|
+
before.plain && entry.plain
|
|
16762
|
+
);
|
|
16763
|
+
// Each block already dropped the `;` its own `}` made redundant, so the
|
|
16764
|
+
// one that is no longer last needs it back.
|
|
16765
|
+
joined = declarations.map((one) => one.text).join(";");
|
|
16766
|
+
}
|
|
16125
16767
|
return {
|
|
16126
16768
|
text: `${beforePrelude}{${joined}}`,
|
|
16127
16769
|
prelude: before.prelude,
|
|
@@ -16136,7 +16778,10 @@ const _joinRuleEntries = (before, entry, owned) => {
|
|
|
16136
16778
|
head: "",
|
|
16137
16779
|
// The two preludes are equal, so the list this keeps is the one `before`
|
|
16138
16780
|
// already carried — settled or not.
|
|
16139
|
-
unordered: before.unordered
|
|
16781
|
+
unordered: before.unordered,
|
|
16782
|
+
list: beforePrelude,
|
|
16783
|
+
block: null,
|
|
16784
|
+
declarations
|
|
16140
16785
|
};
|
|
16141
16786
|
}
|
|
16142
16787
|
if (!blocksEqual || !_entryListable(before) || !_entryListable(entry)) {
|
|
@@ -16145,12 +16790,11 @@ const _joinRuleEntries = (before, entry, owned) => {
|
|
|
16145
16790
|
// Concatenated, never canonicalized here: a run of joins would then re-read
|
|
16146
16791
|
// the whole list once per rule. It is noted as a list still to settle, and
|
|
16147
16792
|
// the run that grew it orders it once where it ends.
|
|
16148
|
-
const list = `${
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
)}`;
|
|
16793
|
+
const list = `${_entryPrelude(before)},${_entryPrelude(entry)}`;
|
|
16794
|
+
const block =
|
|
16795
|
+
before.block === null ? before.text.slice(before.prelude) : before.block;
|
|
16152
16796
|
return {
|
|
16153
|
-
text: list +
|
|
16797
|
+
text: list + block,
|
|
16154
16798
|
prelude: list.length,
|
|
16155
16799
|
atRule: false,
|
|
16156
16800
|
plain: true,
|
|
@@ -16158,13 +16802,30 @@ const _joinRuleEntries = (before, entry, owned) => {
|
|
|
16158
16802
|
listKind: before.listKind,
|
|
16159
16803
|
children: null,
|
|
16160
16804
|
head: "",
|
|
16161
|
-
unordered: true
|
|
16805
|
+
unordered: true,
|
|
16806
|
+
list,
|
|
16807
|
+
block,
|
|
16808
|
+
declarations: null
|
|
16162
16809
|
};
|
|
16163
16810
|
};
|
|
16164
16811
|
|
|
16165
16812
|
/**
|
|
16166
|
-
*
|
|
16167
|
-
*
|
|
16813
|
+
* `_mergeJoinedBoxLonghands` over a joined block's text.
|
|
16814
|
+
* @param {string} body the joined block's declarations
|
|
16815
|
+
* @returns {string} the body, each family it could merge merged
|
|
16816
|
+
*/
|
|
16817
|
+
const _mergeJoinedBody = (body) => {
|
|
16818
|
+
if (!_S._transforms.mergeLonghands) return body;
|
|
16819
|
+
const declarations = _blockDeclarations(body);
|
|
16820
|
+
if (declarations === null) return body;
|
|
16821
|
+
const merged = _mergeJoinedBoxLonghands(declarations);
|
|
16822
|
+
return merged === declarations
|
|
16823
|
+
? body
|
|
16824
|
+
: merged.map((one) => one.text).join(";");
|
|
16825
|
+
};
|
|
16826
|
+
|
|
16827
|
+
/**
|
|
16828
|
+
* `_orderJoinedDeclarations` over a joined block's text.
|
|
16168
16829
|
* @param {string} body the joined body, its braces excluded
|
|
16169
16830
|
* @param {boolean} plain whether it holds declarations and nothing else
|
|
16170
16831
|
* @returns {string} the body, reordered where that is allowed
|
|
@@ -16172,10 +16833,64 @@ const _joinRuleEntries = (before, entry, owned) => {
|
|
|
16172
16833
|
const _orderJoinedBody = (body, plain) => {
|
|
16173
16834
|
if (!plain || !_S._transforms.reorderDeclarations) return body;
|
|
16174
16835
|
const declarations = _blockDeclarations(body);
|
|
16175
|
-
if (declarations === null
|
|
16176
|
-
const
|
|
16177
|
-
|
|
16178
|
-
|
|
16836
|
+
if (declarations === null) return body;
|
|
16837
|
+
const ordered = _orderJoinedDeclarations(declarations, plain);
|
|
16838
|
+
return ordered === declarations
|
|
16839
|
+
? body
|
|
16840
|
+
: ordered.map((one) => one.text).join(";");
|
|
16841
|
+
};
|
|
16842
|
+
|
|
16843
|
+
/**
|
|
16844
|
+
* Whether the last of a printed block's declarations leaves the split that read
|
|
16845
|
+
* them where it started: outside a string and every bracket. Only the last can
|
|
16846
|
+
* end elsewhere, since the split parts the others only there.
|
|
16847
|
+
* @param {PrintedDeclaration[]} declarations the declarations, in order
|
|
16848
|
+
* @returns {boolean} true when a text joined after them is read on its own
|
|
16849
|
+
*/
|
|
16850
|
+
const _lastDeclarationCloses = (declarations) => {
|
|
16851
|
+
if (declarations.length === 0) return true;
|
|
16852
|
+
const text = declarations[declarations.length - 1].text;
|
|
16853
|
+
let depth = 0;
|
|
16854
|
+
let quote = 0;
|
|
16855
|
+
for (let i = 0; i < text.length; i++) {
|
|
16856
|
+
const cc = text.charCodeAt(i);
|
|
16857
|
+
if (quote !== 0) {
|
|
16858
|
+
if (cc === CC_REVERSE_SOLIDUS) {
|
|
16859
|
+
i++;
|
|
16860
|
+
} else if (cc === quote) {
|
|
16861
|
+
quote = 0;
|
|
16862
|
+
}
|
|
16863
|
+
} else if (cc === CC_QUOTATION_MARK || cc === CC_APOSTROPHE) {
|
|
16864
|
+
quote = cc;
|
|
16865
|
+
} else if (
|
|
16866
|
+
cc === CC_LEFT_PARENTHESIS ||
|
|
16867
|
+
cc === CC_LEFT_SQUARE ||
|
|
16868
|
+
cc === CC_LEFT_CURLY
|
|
16869
|
+
) {
|
|
16870
|
+
depth++;
|
|
16871
|
+
} else if (
|
|
16872
|
+
cc === CC_RIGHT_PARENTHESIS ||
|
|
16873
|
+
cc === CC_RIGHT_SQUARE ||
|
|
16874
|
+
cc === CC_RIGHT_CURLY
|
|
16875
|
+
) {
|
|
16876
|
+
depth--;
|
|
16877
|
+
}
|
|
16878
|
+
}
|
|
16879
|
+
return quote === 0 && depth === 0;
|
|
16880
|
+
};
|
|
16881
|
+
|
|
16882
|
+
/**
|
|
16883
|
+
* A joined style rule's declarations in the order `_declarationOrder` prints
|
|
16884
|
+
* one in, which each half was already in but the two concatenated need not be.
|
|
16885
|
+
* @param {PrintedDeclaration[]} declarations the joined block's declarations
|
|
16886
|
+
* @param {boolean} plain whether it holds declarations and nothing else
|
|
16887
|
+
* @returns {PrintedDeclaration[]} them, reordered where that is allowed
|
|
16888
|
+
*/
|
|
16889
|
+
const _orderJoinedDeclarations = (declarations, plain) => {
|
|
16890
|
+
if (!plain || !_S._transforms.reorderDeclarations) return declarations;
|
|
16891
|
+
if (declarations.length < 2) return declarations;
|
|
16892
|
+
const order = _declarationOrder(declarations.map((one) => one.text));
|
|
16893
|
+
return order === null ? declarations : order.map((at) => declarations[at]);
|
|
16179
16894
|
};
|
|
16180
16895
|
|
|
16181
16896
|
// The group rules whose declarations, nested in a style rule, are the implicit
|
|
@@ -16237,7 +16952,7 @@ const _noteStreamedLayerClose = (d, opener, at) => {
|
|
|
16237
16952
|
layers.set(opener, {
|
|
16238
16953
|
at,
|
|
16239
16954
|
subtree: false,
|
|
16240
|
-
taken:
|
|
16955
|
+
taken: new TakenPiece(at, "}", -1)
|
|
16241
16956
|
});
|
|
16242
16957
|
};
|
|
16243
16958
|
|
|
@@ -16500,7 +17215,7 @@ const _nothingBetweenShadows = (items, texts, from, to, declared, subjects) => {
|
|
|
16500
17215
|
// selectors and pseudos are gone: what either holds may look like a combinator.
|
|
16501
17216
|
const _SUBJECT_STRIP_RE = new RegExp(
|
|
16502
17217
|
`${_ATTRIBUTE}|${_PSEUDO_CLASS}|${_PSEUDO_ELEMENT}`,
|
|
16503
|
-
"
|
|
17218
|
+
"g"
|
|
16504
17219
|
);
|
|
16505
17220
|
const _SUBJECT_TYPE_RE = /(?:^|[\s>+~])([-\w\u00A0-\uFFFF]+)[^\s>+~]*$/;
|
|
16506
17221
|
|
|
@@ -16532,11 +17247,11 @@ const _subjectTypes = (prelude) => {
|
|
|
16532
17247
|
* @returns {Set<string> | null} the type names
|
|
16533
17248
|
*/
|
|
16534
17249
|
const _entrySubjectTypes = (entry) => {
|
|
16535
|
-
if (!entry.atRule) return _subjectTypes(
|
|
17250
|
+
if (!entry.atRule) return _subjectTypes(_entryPrelude(entry));
|
|
16536
17251
|
/** @type {Set<string>} */
|
|
16537
17252
|
const out = new Set();
|
|
16538
17253
|
for (const child of /** @type {RuleEntry[]} */ (entry.children)) {
|
|
16539
|
-
const types = _subjectTypes(
|
|
17254
|
+
const types = _subjectTypes(_entryPrelude(child));
|
|
16540
17255
|
if (types === null) return null;
|
|
16541
17256
|
for (const type of types) out.add(type);
|
|
16542
17257
|
}
|
|
@@ -16565,7 +17280,7 @@ const _subjectsDisjoint = (a, b) => {
|
|
|
16565
17280
|
* @returns {boolean} true where its block may be read for what it declares
|
|
16566
17281
|
*/
|
|
16567
17282
|
const _readableCondition = (entry) => {
|
|
16568
|
-
const name = _atRuleName(
|
|
17283
|
+
const name = _atRuleName(_entryPrelude(entry));
|
|
16569
17284
|
return name !== "layer" && MERGEABLE_AT_RULES.has(name);
|
|
16570
17285
|
};
|
|
16571
17286
|
|
|
@@ -16604,7 +17319,7 @@ const _atRuleDeclaredProperties = (entry) => {
|
|
|
16604
17319
|
* @returns {void}
|
|
16605
17320
|
*/
|
|
16606
17321
|
const _mergeDistantAtRule = (items, texts, held, entry, at) => {
|
|
16607
|
-
const prelude =
|
|
17322
|
+
const prelude = _entryPrelude(entry);
|
|
16608
17323
|
// WHY: a layer's place in the cascade is where its name is first written, not
|
|
16609
17324
|
// what its prelude states, so two blocks naming one are not the pair of equal
|
|
16610
17325
|
// conditions this joins. `_mergeNamedLayerBlocks` gathers those under the rule
|
|
@@ -16712,7 +17427,12 @@ const _dropRulesWrittenAgain = (items, texts) => {
|
|
|
16712
17427
|
/** @type {Map<string, number[]> | null} */
|
|
16713
17428
|
let held = null;
|
|
16714
17429
|
for (let i = 0; i < items.length; i++) {
|
|
16715
|
-
if (
|
|
17430
|
+
if (
|
|
17431
|
+
texts[i].length === 0 ||
|
|
17432
|
+
_types[_nodeIndex(items[i])] === NodeType.Declaration
|
|
17433
|
+
) {
|
|
17434
|
+
continue;
|
|
17435
|
+
}
|
|
16716
17436
|
const entry = _ruleEntryOf(items[i], texts[i]);
|
|
16717
17437
|
// Keyframes of one selector are not one cascade in every engine: an older
|
|
16718
17438
|
// one reads only the last block written for it.
|
|
@@ -16724,7 +17444,7 @@ const _dropRulesWrittenAgain = (items, texts) => {
|
|
|
16724
17444
|
) {
|
|
16725
17445
|
continue;
|
|
16726
17446
|
}
|
|
16727
|
-
const prelude =
|
|
17447
|
+
const prelude = _entryPrelude(entry);
|
|
16728
17448
|
if (held === null) held = new Map();
|
|
16729
17449
|
const earlier = held.get(prelude);
|
|
16730
17450
|
if (earlier === undefined) {
|
|
@@ -17106,17 +17826,19 @@ const _canonicalSelectorList = (prelude) => {
|
|
|
17106
17826
|
if (!prelude.includes(",")) return prelude;
|
|
17107
17827
|
const list = _splitSelectorList(prelude);
|
|
17108
17828
|
if (list.length < 2) return prelude;
|
|
17109
|
-
//
|
|
17110
|
-
// distinct, and already in order —
|
|
17111
|
-
//
|
|
17112
|
-
|
|
17113
|
-
|
|
17114
|
-
|
|
17115
|
-
|
|
17116
|
-
|
|
17829
|
+
// Strictly increasing answers both questions the common case turns on —
|
|
17830
|
+
// every selector distinct, and already in order — without a set: only two
|
|
17831
|
+
// equal selectors compare as zero.
|
|
17832
|
+
let i = 1;
|
|
17833
|
+
while (i < list.length && _compareSelectors(list[i - 1], list[i]) < 0) i++;
|
|
17834
|
+
if (i === list.length) return prelude;
|
|
17835
|
+
list.sort(_compareSelectors);
|
|
17836
|
+
let kept = 1;
|
|
17837
|
+
for (let j = 1; j < list.length; j++) {
|
|
17838
|
+
if (list[j] !== list[kept - 1]) list[kept++] = list[j];
|
|
17117
17839
|
}
|
|
17118
|
-
|
|
17119
|
-
return
|
|
17840
|
+
list.length = kept;
|
|
17841
|
+
return list.join(",");
|
|
17120
17842
|
};
|
|
17121
17843
|
|
|
17122
17844
|
/**
|
|
@@ -17155,10 +17877,13 @@ const _settleJoinedSeams = (entry) => {
|
|
|
17155
17877
|
const head = _joinedHead(settled);
|
|
17156
17878
|
return {
|
|
17157
17879
|
...entry,
|
|
17158
|
-
text: _joinedBlockText(
|
|
17880
|
+
text: _joinedBlockText(_entryPrelude(entry), head, settled),
|
|
17159
17881
|
children: settled,
|
|
17160
17882
|
head,
|
|
17161
|
-
unordered: false
|
|
17883
|
+
unordered: false,
|
|
17884
|
+
list: null,
|
|
17885
|
+
block: null,
|
|
17886
|
+
declarations: null
|
|
17162
17887
|
};
|
|
17163
17888
|
};
|
|
17164
17889
|
|
|
@@ -17173,7 +17898,7 @@ const _settleJoinedSeams = (entry) => {
|
|
|
17173
17898
|
const _canonicalizeJoined = (entry) => {
|
|
17174
17899
|
if (entry.atRule) return _settleJoinedSeams(entry);
|
|
17175
17900
|
if (entry.prelude === -1) return entry;
|
|
17176
|
-
const prelude =
|
|
17901
|
+
const prelude = _entryPrelude(entry);
|
|
17177
17902
|
const canonical = _canonicalSelectorList(prelude);
|
|
17178
17903
|
if (canonical === prelude) {
|
|
17179
17904
|
entry.unordered = false;
|
|
@@ -17183,7 +17908,10 @@ const _canonicalizeJoined = (entry) => {
|
|
|
17183
17908
|
...entry,
|
|
17184
17909
|
text: canonical + entry.text.slice(entry.prelude),
|
|
17185
17910
|
prelude: canonical.length,
|
|
17186
|
-
unordered: false
|
|
17911
|
+
unordered: false,
|
|
17912
|
+
list: null,
|
|
17913
|
+
block: null,
|
|
17914
|
+
declarations: null
|
|
17187
17915
|
};
|
|
17188
17916
|
};
|
|
17189
17917
|
|
|
@@ -17410,9 +18138,7 @@ const _rulePrelude = (path, writer, minify, outParts) => {
|
|
|
17410
18138
|
}
|
|
17411
18139
|
const list = _canonicalSelectorList(prelude);
|
|
17412
18140
|
if (_readsThroughGoneEngine(list)) {
|
|
17413
|
-
/** @type {Set<Node>} */ (_unusedRules).add(
|
|
17414
|
-
/** @type {Node} */ (_S._currentNode)
|
|
17415
|
-
);
|
|
18141
|
+
/** @type {Set<Node>} */ (_unusedRules).add(_S._currentNode);
|
|
17416
18142
|
return list;
|
|
17417
18143
|
}
|
|
17418
18144
|
if (_unusedSymbols === null) return list;
|
|
@@ -17420,9 +18146,7 @@ const _rulePrelude = (path, writer, minify, outParts) => {
|
|
|
17420
18146
|
// Marked rather than dropped here: the rule's own printer takes it out, the
|
|
17421
18147
|
// same way it takes out one whose block ends up empty.
|
|
17422
18148
|
if (kept !== null) return kept;
|
|
17423
|
-
/** @type {Set<Node>} */ (_unusedRules).add(
|
|
17424
|
-
/** @type {Node} */ (_S._currentNode)
|
|
17425
|
-
);
|
|
18149
|
+
/** @type {Set<Node>} */ (_unusedRules).add(_S._currentNode);
|
|
17426
18150
|
return list;
|
|
17427
18151
|
}
|
|
17428
18152
|
if (
|
|
@@ -17435,9 +18159,7 @@ const _rulePrelude = (path, writer, minify, outParts) => {
|
|
|
17435
18159
|
unescapeIdentifier(prelude.slice(_rawName(path.node).length + 1).trim())
|
|
17436
18160
|
)
|
|
17437
18161
|
) {
|
|
17438
|
-
/** @type {Set<Node>} */ (_unusedRules).add(
|
|
17439
|
-
/** @type {Node} */ (_S._currentNode)
|
|
17440
|
-
);
|
|
18162
|
+
/** @type {Set<Node>} */ (_unusedRules).add(_S._currentNode);
|
|
17441
18163
|
}
|
|
17442
18164
|
return prelude;
|
|
17443
18165
|
};
|
|
@@ -17904,6 +18626,39 @@ const _canonicalProperty = (property) => {
|
|
|
17904
18626
|
const _orderMatters = (a, b) => {
|
|
17905
18627
|
if (a === b || a === "all" || b === "all") return true;
|
|
17906
18628
|
if (a.startsWith("--") || b.startsWith("--")) return false;
|
|
18629
|
+
let row = _orderMattersMemo.get(a);
|
|
18630
|
+
let matters = row === undefined ? undefined : row.get(b);
|
|
18631
|
+
if (matters !== undefined) return matters;
|
|
18632
|
+
matters = _computeOrderMatters(a, b);
|
|
18633
|
+
// The names are the author's, so a sheet of made-up ones starts again.
|
|
18634
|
+
if (_orderMattersEntries === _ORDER_MATTERS_ENTRIES) {
|
|
18635
|
+
_orderMattersMemo.clear();
|
|
18636
|
+
_orderMattersEntries = 0;
|
|
18637
|
+
row = undefined;
|
|
18638
|
+
}
|
|
18639
|
+
if (row === undefined) {
|
|
18640
|
+
row = new Map();
|
|
18641
|
+
_orderMattersMemo.set(a, row);
|
|
18642
|
+
}
|
|
18643
|
+
row.set(b, matters);
|
|
18644
|
+
_orderMattersEntries++;
|
|
18645
|
+
return matters;
|
|
18646
|
+
};
|
|
18647
|
+
|
|
18648
|
+
// `_orderMatters` by its first property, then its second: a sheet names few
|
|
18649
|
+
// properties, and the walks back over a block ask of the same pairs again.
|
|
18650
|
+
/** @type {Map<string, Map<string, boolean>>} */
|
|
18651
|
+
const _orderMattersMemo = new Map();
|
|
18652
|
+
let _orderMattersEntries = 0;
|
|
18653
|
+
const _ORDER_MATTERS_ENTRIES = 1 << 15;
|
|
18654
|
+
|
|
18655
|
+
/**
|
|
18656
|
+
* `_orderMatters` without the memo.
|
|
18657
|
+
* @param {string} a a property, read through `_canonicalProperty`
|
|
18658
|
+
* @param {string} b another
|
|
18659
|
+
* @returns {boolean} true when the two must keep their order
|
|
18660
|
+
*/
|
|
18661
|
+
const _computeOrderMatters = (a, b) => {
|
|
17907
18662
|
// A corner's radius is no side's: `border-bottom` sets no `-radius` it starts.
|
|
17908
18663
|
if (
|
|
17909
18664
|
a.charCodeAt(0) !== CC_HYPHEN_MINUS &&
|
|
@@ -17912,7 +18667,7 @@ const _orderMatters = (a, b) => {
|
|
|
17912
18667
|
) {
|
|
17913
18668
|
return false;
|
|
17914
18669
|
}
|
|
17915
|
-
if (a
|
|
18670
|
+
if (_extendsProperty(a, b) || _extendsProperty(b, a)) return true;
|
|
17916
18671
|
// A vendor property no standard one aliases says nothing of what it sets
|
|
17917
18672
|
// beyond its words: `-webkit-border-before` is a border side.
|
|
17918
18673
|
if (
|
|
@@ -17938,6 +18693,18 @@ const _orderMatters = (a, b) => {
|
|
|
17938
18693
|
);
|
|
17939
18694
|
};
|
|
17940
18695
|
|
|
18696
|
+
/**
|
|
18697
|
+
* Whether a property name is another's followed by more words: `margin-top` of
|
|
18698
|
+
* `margin`. Read in place, as a `${base}-` prefix would be built on every call.
|
|
18699
|
+
* @param {string} name a property
|
|
18700
|
+
* @param {string} base another
|
|
18701
|
+
* @returns {boolean} true when `name` starts with `base` and a `-`
|
|
18702
|
+
*/
|
|
18703
|
+
const _extendsProperty = (name, base) =>
|
|
18704
|
+
name.length > base.length &&
|
|
18705
|
+
name.charCodeAt(base.length) === CC_HYPHEN_MINUS &&
|
|
18706
|
+
name.startsWith(base);
|
|
18707
|
+
|
|
17941
18708
|
// A box side, corner or axis a property names, physical or flow-relative.
|
|
17942
18709
|
const _PHYSICAL_SIDE_RE =
|
|
17943
18710
|
/-(?:top|right|bottom|left|x|y)(?=-|$)|^(?:(?:min|max)-)?(?:top|right|bottom|left|width|height)$|-(?:width|height)$/;
|
|
@@ -17967,6 +18734,11 @@ const _blocksMerge = (between, later, families) => {
|
|
|
17967
18734
|
);
|
|
17968
18735
|
};
|
|
17969
18736
|
|
|
18737
|
+
// The properties `_sideRoot` reads as `inset`'s and as `size`'s sides.
|
|
18738
|
+
const _INSET_SIDE_RE = /^(?:top|right|bottom|left)$/;
|
|
18739
|
+
const _SIZE_PROPERTY_RE =
|
|
18740
|
+
/^(?:(?:min|max)-)?(?:width|height|inline-size|block-size)$/;
|
|
18741
|
+
|
|
17970
18742
|
/**
|
|
17971
18743
|
* The word a property's sides share: `margin` for `margin-left` and
|
|
17972
18744
|
* `margin-inline-start`, `inset` for `top`, `size` for `width` and `inline-size`.
|
|
@@ -17974,11 +18746,12 @@ const _blocksMerge = (between, later, families) => {
|
|
|
17974
18746
|
* @returns {string} that word
|
|
17975
18747
|
*/
|
|
17976
18748
|
const _sideRoot = (property) => {
|
|
17977
|
-
const bare =
|
|
17978
|
-
|
|
17979
|
-
|
|
17980
|
-
|
|
17981
|
-
|
|
18749
|
+
const bare =
|
|
18750
|
+
property.charCodeAt(0) === CC_HYPHEN_MINUS
|
|
18751
|
+
? property.replace(_VENDOR_ITEM_PREFIX_RE, "")
|
|
18752
|
+
: property;
|
|
18753
|
+
if (_INSET_SIDE_RE.test(bare)) return "inset";
|
|
18754
|
+
if (_SIZE_PROPERTY_RE.test(bare)) return "size";
|
|
17982
18755
|
const dash = bare.indexOf("-");
|
|
17983
18756
|
return dash === -1 ? bare : bare.slice(0, dash);
|
|
17984
18757
|
};
|
|
@@ -18031,9 +18804,26 @@ const _declarationOrder = (texts) => {
|
|
|
18031
18804
|
rankOf.push(rank);
|
|
18032
18805
|
}
|
|
18033
18806
|
if (!ranked) return null;
|
|
18034
|
-
|
|
18035
|
-
|
|
18036
|
-
|
|
18807
|
+
// Already in rank order, which half of all blocks are: the stable sort would
|
|
18808
|
+
// hand every index back where it stands.
|
|
18809
|
+
let inOrder = true;
|
|
18810
|
+
for (let i = 1; i < rankOf.length && inOrder; i++) {
|
|
18811
|
+
if (rankOf[i] < rankOf[i - 1]) inOrder = false;
|
|
18812
|
+
}
|
|
18813
|
+
if (inOrder) return null;
|
|
18814
|
+
// A stable insertion sort by rank: blocks are short, and this allocates no
|
|
18815
|
+
// comparator and no copy as `Array#sort` does.
|
|
18816
|
+
/** @type {number[]} */
|
|
18817
|
+
const order = [];
|
|
18818
|
+
for (let i = 0; i < rankOf.length; i++) {
|
|
18819
|
+
let at = order.length;
|
|
18820
|
+
order.push(i);
|
|
18821
|
+
while (at > 0 && rankOf[order[at - 1]] > rankOf[i]) {
|
|
18822
|
+
order[at] = order[at - 1];
|
|
18823
|
+
at--;
|
|
18824
|
+
}
|
|
18825
|
+
order[at] = i;
|
|
18826
|
+
}
|
|
18037
18827
|
let moved = false;
|
|
18038
18828
|
for (let i = 0; i < order.length; i++) {
|
|
18039
18829
|
if (order[i] !== i) moved = true;
|
|
@@ -18227,7 +19017,8 @@ const _composeBlockBody = (
|
|
|
18227
19017
|
for (const node of held) pendingRules.add(node);
|
|
18228
19018
|
}
|
|
18229
19019
|
}
|
|
18230
|
-
|
|
19020
|
+
// A block of declarations alone, most of them, holds no rule to join or drop.
|
|
19021
|
+
if (minify && items !== decls) {
|
|
18231
19022
|
// Before the joins, so a rule it takes out stands in none of their way;
|
|
18232
19023
|
// and again after any join, which can write a rule again in its turn.
|
|
18233
19024
|
if (_S._transforms.removeDeadRules) {
|
|
@@ -18430,6 +19221,7 @@ const _composeBlockBody = (
|
|
|
18430
19221
|
for (let i = 0; i < properties.length; i++) {
|
|
18431
19222
|
if (properties[i].length === 0) continue;
|
|
18432
19223
|
present.add(properties[i]);
|
|
19224
|
+
(_isImportant(items[i]) ? importantAt : plainAt).set(properties[i], i);
|
|
18433
19225
|
// A value is only ever asked for against its own property, so the
|
|
18434
19226
|
// two share one set.
|
|
18435
19227
|
if (values[i].length !== 0) {
|
|
@@ -18488,7 +19280,32 @@ const _composeBlockBody = (
|
|
|
18488
19280
|
? _prefixedPropertyName(property)
|
|
18489
19281
|
: undefined;
|
|
18490
19282
|
if (base !== undefined) {
|
|
18491
|
-
|
|
19283
|
+
// An engine still reading the vendor name as an alias cascades the
|
|
19284
|
+
// two as one property, so it is dead only behind a twin that wins.
|
|
19285
|
+
const importantBase = importantAt.get(base);
|
|
19286
|
+
const plainBase = plainAt.get(base);
|
|
19287
|
+
const important = _isImportant(items[i]);
|
|
19288
|
+
const baseWins = important
|
|
19289
|
+
? importantBase !== undefined && importantBase > i
|
|
19290
|
+
: importantBase !== undefined ||
|
|
19291
|
+
(plainBase !== undefined && plainBase > i);
|
|
19292
|
+
// ...or behind one of the same importance saying the same thing.
|
|
19293
|
+
const twinAt = important ? importantBase : plainBase;
|
|
19294
|
+
const sameTwin =
|
|
19295
|
+
twinAt !== undefined &&
|
|
19296
|
+
(important || importantBase === undefined) &&
|
|
19297
|
+
texts[twinAt].slice(
|
|
19298
|
+
base.length + 1,
|
|
19299
|
+
_printedValueEnd(texts[twinAt], base.length)
|
|
19300
|
+
) ===
|
|
19301
|
+
texts[i].slice(
|
|
19302
|
+
property.length + 1,
|
|
19303
|
+
_printedValueEnd(texts[i], property.length)
|
|
19304
|
+
);
|
|
19305
|
+
if (
|
|
19306
|
+
(baseWins || sameTwin) &&
|
|
19307
|
+
_prefixedPropertyRemovable(base, property)
|
|
19308
|
+
) {
|
|
18492
19309
|
if (droppedPrefix === null) droppedPrefix = new Set();
|
|
18493
19310
|
droppedPrefix.add(i);
|
|
18494
19311
|
continue;
|
|
@@ -18588,6 +19405,10 @@ const _composeBlockBody = (
|
|
|
18588
19405
|
: null;
|
|
18589
19406
|
/** @type {string[]} */
|
|
18590
19407
|
const pieceTexts = [];
|
|
19408
|
+
// The body before its last piece, and that piece: the `;` a `}` makes
|
|
19409
|
+
// redundant is cut off the piece, as reading the body's end would flatten it.
|
|
19410
|
+
let prior = "";
|
|
19411
|
+
let last = "";
|
|
18591
19412
|
for (let i = 0; i < texts.length; i++) {
|
|
18592
19413
|
const isBlock =
|
|
18593
19414
|
bodies !== 0 && path.type(items[i]) !== NodeType.Declaration;
|
|
@@ -18630,6 +19451,8 @@ const _composeBlockBody = (
|
|
|
18630
19451
|
}
|
|
18631
19452
|
body += nl;
|
|
18632
19453
|
const at = body.length;
|
|
19454
|
+
prior = body;
|
|
19455
|
+
last = text;
|
|
18633
19456
|
body += text;
|
|
18634
19457
|
if (minify && isBlock) {
|
|
18635
19458
|
if (spans === null) spans = [];
|
|
@@ -18639,18 +19462,15 @@ const _composeBlockBody = (
|
|
|
18639
19462
|
if (pieces !== null) {
|
|
18640
19463
|
const order = _declarationOrder(pieceTexts);
|
|
18641
19464
|
for (let i = 0; i < pieces.length; i++) {
|
|
18642
|
-
|
|
19465
|
+
prior = body;
|
|
19466
|
+
last = pieces[order === null ? i : order[i]];
|
|
19467
|
+
body += last;
|
|
18643
19468
|
}
|
|
18644
19469
|
}
|
|
18645
19470
|
// Drop the redundant `;` a following `}` — or, at top level, the end of the
|
|
18646
19471
|
// input — makes so, when minifying.
|
|
18647
|
-
if (minify) {
|
|
18648
|
-
|
|
18649
|
-
body.length !== 0 &&
|
|
18650
|
-
body.charCodeAt(body.length - 1) === CC_SEMICOLON
|
|
18651
|
-
) {
|
|
18652
|
-
body = body.slice(0, -1);
|
|
18653
|
-
}
|
|
19472
|
+
if (minify && last.charCodeAt(last.length - 1) === CC_SEMICOLON) {
|
|
19473
|
+
body = prior + last.slice(0, -1);
|
|
18654
19474
|
}
|
|
18655
19475
|
|
|
18656
19476
|
return {
|
|
@@ -19199,7 +20019,7 @@ const _S = {
|
|
|
19199
20019
|
// The walk's current position (`A.node` / `A.parent` read these; module-level
|
|
19200
20020
|
// so the accessor methods' defaults avoid self-referential `this` typing).
|
|
19201
20021
|
/** @type {Node} */
|
|
19202
|
-
_currentNode: /** @type {Node} */ (/** @type {
|
|
20022
|
+
_currentNode: /** @type {Node} */ (/** @type {Node | number} */ (0)),
|
|
19203
20023
|
// The declaration `_inKeywordOnlyValue` last answered for, and its answer: one
|
|
19204
20024
|
// value's identifiers all ask it, and the read is a pointer compare after the
|
|
19205
20025
|
// first. Cleared with the rest of the parse state, so no node outlives it.
|
|
@@ -19499,10 +20319,10 @@ const A = {
|
|
|
19499
20319
|
field(i, field, n = _S._currentNode) {
|
|
19500
20320
|
const k = _nodeIndex(n);
|
|
19501
20321
|
if (i < 0 || i >= A.fieldCount(field, n)) {
|
|
19502
|
-
return
|
|
20322
|
+
return _nodeRef(0);
|
|
19503
20323
|
}
|
|
19504
20324
|
if (_LIST_FIELD[_types[k]] === field) {
|
|
19505
|
-
return
|
|
20325
|
+
return _nodeRef(_flat[_listStarts[k] + i]);
|
|
19506
20326
|
}
|
|
19507
20327
|
return (field === Field.declarations ? _declBodies : _ruleBodies)[
|
|
19508
20328
|
_bodyIdx[k] - 1
|
|
@@ -19519,7 +20339,7 @@ const A = {
|
|
|
19519
20339
|
const item = A.field(i, field, n);
|
|
19520
20340
|
if (A.name(item) === name) return item;
|
|
19521
20341
|
}
|
|
19522
|
-
return
|
|
20342
|
+
return _nodeRef(0);
|
|
19523
20343
|
},
|
|
19524
20344
|
/**
|
|
19525
20345
|
* `important` is a container's bit, cleared when its id is reused; a token's
|
|
@@ -19698,7 +20518,13 @@ const _collectRuleSpans = (spans, item, text, at, path, inner) => {
|
|
|
19698
20518
|
// it — the parent first, so a cut that takes the whole rule is seen before
|
|
19699
20519
|
// anything inside it.
|
|
19700
20520
|
if (path.type(item) === NodeType.QualifiedRule) {
|
|
19701
|
-
spans.push({
|
|
20521
|
+
spans.push({
|
|
20522
|
+
scope: _rootScope(),
|
|
20523
|
+
key: text,
|
|
20524
|
+
at,
|
|
20525
|
+
len: text.length,
|
|
20526
|
+
taken: null
|
|
20527
|
+
});
|
|
19702
20528
|
} else if (
|
|
19703
20529
|
inner !== undefined &&
|
|
19704
20530
|
inner.prelude.charCodeAt(0) === CC_AT_SIGN &&
|
|
@@ -19706,7 +20532,13 @@ const _collectRuleSpans = (spans, item, text, at, path, inner) => {
|
|
|
19706
20532
|
) {
|
|
19707
20533
|
// Not a rule of its own — a condition its body is read under — so it is
|
|
19708
20534
|
// noted only to be cut once the cuts inside it have left it empty.
|
|
19709
|
-
spans.push({
|
|
20535
|
+
spans.push({
|
|
20536
|
+
scope: _rootScope(),
|
|
20537
|
+
key: UNKEYED,
|
|
20538
|
+
at,
|
|
20539
|
+
len: text.length,
|
|
20540
|
+
taken: null
|
|
20541
|
+
});
|
|
19710
20542
|
}
|
|
19711
20543
|
if (inner === undefined) return;
|
|
19712
20544
|
const base = at + inner.bodyAt;
|
|
@@ -19715,7 +20547,8 @@ const _collectRuleSpans = (spans, item, text, at, path, inner) => {
|
|
|
19715
20547
|
scope: _enclosingRuleScope(span.scope, inner.keyPrelude),
|
|
19716
20548
|
key: span.key,
|
|
19717
20549
|
at: base + span.at,
|
|
19718
|
-
len: span.len
|
|
20550
|
+
len: span.len,
|
|
20551
|
+
taken: null
|
|
19719
20552
|
});
|
|
19720
20553
|
}
|
|
19721
20554
|
};
|
|
@@ -19764,6 +20597,7 @@ module.exports._NUMERIC_RE = _NUMERIC_RE;
|
|
|
19764
20597
|
module.exports._atKeywordOf = _atKeywordOf;
|
|
19765
20598
|
module.exports._printedSource = _printedSource;
|
|
19766
20599
|
module.exports._rawName = _rawName;
|
|
20600
|
+
module.exports._setVerbatimLeafPrinter = setVerbatimLeafPrinter;
|
|
19767
20601
|
module.exports._trimCssWhiteSpace = _trimCssWhiteSpace;
|
|
19768
20602
|
module.exports._declarationsOf = _declarationsOf;
|
|
19769
20603
|
module.exports._rulesOf = _rulesOf;
|
|
@@ -19773,6 +20607,33 @@ module.exports._S = _S;
|
|
|
19773
20607
|
module.exports._SEP = _SEP;
|
|
19774
20608
|
module.exports._keepKeywordComments = _keepKeywordComments;
|
|
19775
20609
|
module.exports._TRIM_COMBINATORS = _TRIM_COMBINATORS;
|
|
20610
|
+
/**
|
|
20611
|
+
* The body a reused block composes to, for the rule being printed.
|
|
20612
|
+
* @param {Node} node the rule
|
|
20613
|
+
* @returns {string | undefined} the body, or undefined to compose it
|
|
20614
|
+
*/
|
|
20615
|
+
module.exports._memoizedBlockBody = (node) =>
|
|
20616
|
+
_blockMemoNode === node ? _blockMemoBody : undefined;
|
|
20617
|
+
/**
|
|
20618
|
+
* Done with the rule the walk looked a block up for: keep the body it composed
|
|
20619
|
+
* where the walk asked for one, and forget the rule — node ids are reused.
|
|
20620
|
+
* @param {Node} node the rule
|
|
20621
|
+
* @param {string | null} body its composed body, null to keep none
|
|
20622
|
+
* @returns {void}
|
|
20623
|
+
*/
|
|
20624
|
+
module.exports._memoizeBlockBody = (node, body) => {
|
|
20625
|
+
if (
|
|
20626
|
+
_blockMemoNode === node &&
|
|
20627
|
+
body !== null &&
|
|
20628
|
+
_blockMemoKey !== "" &&
|
|
20629
|
+
_blockMemo !== null
|
|
20630
|
+
) {
|
|
20631
|
+
_blockMemoKeyTable.set(_blockMemoKey, body);
|
|
20632
|
+
}
|
|
20633
|
+
_blockMemoNode = null;
|
|
20634
|
+
_blockMemoBody = undefined;
|
|
20635
|
+
_blockMemoKey = "";
|
|
20636
|
+
};
|
|
19776
20637
|
module.exports._TRIM_CONDITIONS = _TRIM_CONDITIONS;
|
|
19777
20638
|
module.exports._TRIM_MATH = _TRIM_MATH;
|
|
19778
20639
|
module.exports._TRIM_NOTHING = _TRIM_NOTHING;
|