@depup/webpack 5.109.2-depup.0 → 5.110.3-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/changes.json +7 -7
- package/lib/APIPlugin.js +123 -17
- package/lib/AsyncDependenciesBlock.js +10 -7
- package/lib/AutomaticPrefetchPlugin.js +1 -1
- package/lib/BannerPlugin.js +10 -6
- package/lib/CacheFacade.js +6 -6
- package/lib/Chunk.js +14 -11
- package/lib/ChunkGraph.js +46 -35
- package/lib/ChunkGroup.js +7 -7
- package/lib/ChunkTemplate.js +35 -44
- package/lib/CircularModulesPlugin.js +205 -28
- package/lib/CleanPlugin.js +4 -7
- package/lib/CodeGenerationResults.js +11 -8
- package/lib/CompatibilityPlugin.js +7 -7
- package/lib/Compilation.js +688 -409
- package/lib/Compiler.js +53 -38
- package/lib/ConcatenationScope.js +107 -8
- package/lib/ConditionalInitFragment.js +3 -3
- package/lib/ConstPlugin.js +13 -11
- package/lib/ContextExclusionPlugin.js +1 -1
- package/lib/ContextModule.js +146 -54
- package/lib/ContextModuleFactory.js +46 -14
- package/lib/ContextReplacementPlugin.js +12 -14
- package/lib/DefinePlugin.js +121 -37
- package/lib/DependenciesBlock.js +9 -6
- package/lib/Dependency.js +36 -16
- package/lib/DependencyTemplate.js +11 -12
- package/lib/DependencyTemplates.js +3 -3
- package/lib/DotenvPlugin.js +91 -26
- package/lib/DynamicEntryPlugin.js +8 -4
- package/lib/EntryOptionPlugin.js +8 -4
- package/lib/EntryPlugin.js +2 -2
- package/lib/Entrypoint.js +6 -2
- package/lib/EnvironmentPlugin.js +2 -2
- package/lib/EvalDevToolModulePlugin.js +8 -4
- package/lib/EvalSourceMapDevToolPlugin.js +15 -8
- package/lib/ExportsInfo.js +111 -14
- package/lib/ExportsInfoApiPlugin.js +2 -4
- package/lib/ExternalModule.js +232 -77
- package/lib/ExternalModuleFactoryPlugin.js +97 -38
- package/lib/ExternalsPlugin.js +10 -6
- package/lib/FileSystemInfo.js +44 -70
- package/lib/FlagAllModulesAsUsedPlugin.js +2 -3
- package/lib/FlagDependencyExportsPlugin.js +76 -19
- package/lib/FlagDependencyUsagePlugin.js +40 -49
- package/lib/FlagEntryExportAsUsedPlugin.js +1 -1
- package/lib/Generator.js +36 -15
- package/lib/HotModuleReplacementPlugin.js +16 -44
- package/lib/IgnorePlugin.js +8 -4
- package/lib/IgnoreWarningsPlugin.js +2 -2
- package/lib/InitFragment.js +8 -4
- package/lib/JavascriptMetaInfoPlugin.js +35 -4
- package/lib/LazyBarrel.js +3 -4
- package/lib/LibraryTemplatePlugin.js +10 -6
- package/lib/LoaderOptionsPlugin.js +7 -3
- package/lib/LoaderTargetPlugin.js +1 -1
- package/lib/MainTemplate.js +49 -42
- package/lib/ManifestPlugin.js +12 -11
- package/lib/Module.js +62 -33
- package/lib/ModuleFactory.js +3 -3
- package/lib/ModuleFilenameHelpers.js +9 -4
- package/lib/ModuleGraph.js +195 -21
- package/lib/ModuleGraphConnection.js +6 -13
- package/lib/ModuleInfoHeaderPlugin.js +8 -10
- package/lib/ModuleTemplate.js +62 -63
- package/lib/MultiCompiler.js +130 -64
- package/lib/MultiStats.js +40 -9
- package/lib/MultiWatching.js +3 -3
- package/lib/NoEmitOnErrorsPlugin.js +1 -1
- package/lib/NodeStuffPlugin.js +29 -19
- package/lib/NormalModule.js +152 -103
- package/lib/NormalModuleFactory.js +555 -110
- package/lib/NormalModuleReplacementPlugin.js +5 -8
- package/lib/NullFactory.js +6 -2
- package/lib/OptionsApply.js +7 -3
- package/lib/Parser.js +7 -3
- package/lib/PlatformPlugin.js +2 -2
- package/lib/PrefetchPlugin.js +1 -1
- package/lib/ProgressPlugin.js +16 -13
- package/lib/ProvidePlugin.js +3 -5
- package/lib/RawModule.js +25 -17
- package/lib/RecordIdsPlugin.js +3 -3
- package/lib/RequestShortener.js +1 -1
- package/lib/ResolverFactory.js +2 -2
- package/lib/RuntimeGlobals.js +22 -10
- package/lib/RuntimeModule.js +29 -19
- package/lib/RuntimePlugin.js +335 -169
- package/lib/RuntimeTemplate.js +2761 -316
- package/lib/SelfModuleFactory.js +7 -3
- package/lib/SourceMapDevToolModuleOptionsPlugin.js +6 -2
- package/lib/SourceMapDevToolPlugin.js +30 -20
- package/lib/Stats.js +3 -4
- package/lib/Template.js +32 -22
- package/lib/TemplatedPathPlugin.js +96 -14
- package/lib/UseStrictPlugin.js +4 -6
- package/lib/WarnCaseSensitiveModulesPlugin.js +4 -4
- package/lib/WarnDeprecatedOptionPlugin.js +1 -1
- package/lib/WarnNoModeSetPlugin.js +1 -1
- package/lib/WatchIgnorePlugin.js +8 -6
- package/lib/Watching.js +8 -8
- package/lib/WebpackIsIncludedPlugin.js +2 -4
- package/lib/WebpackOptionsApply.js +308 -18
- package/lib/WebpackOptionsDefaulter.js +6 -2
- package/lib/asset/AssetBytesGenerator.js +12 -10
- package/lib/asset/AssetBytesParser.js +2 -4
- package/lib/asset/AssetGenerator.js +188 -95
- package/lib/asset/AssetModule.js +7 -3
- package/lib/asset/AssetModulesPlugin.js +110 -38
- package/lib/asset/AssetParser.js +9 -7
- package/lib/asset/AssetSourceGenerator.js +60 -13
- package/lib/asset/AssetSourceParser.js +2 -4
- package/lib/asset/RawDataUrlModule.js +24 -16
- package/lib/asset/WebManifestGenerator.js +8 -10
- package/lib/asset/WebManifestParser.js +24 -10
- package/lib/async-modules/AsyncModuleHelpers.js +12 -6
- package/lib/async-modules/AwaitDependenciesInitFragment.js +2 -2
- package/lib/async-modules/InferAsyncModulesPlugin.js +2 -2
- package/lib/async-modules/isGeneratorLowered.js +4 -4
- package/lib/buildChunkGraph.js +36 -27
- package/lib/bun/BunTargetPlugin.js +1 -1
- package/lib/cache/AddBuildDependenciesPlugin.js +1 -1
- package/lib/cache/AddManagedPathsPlugin.js +1 -1
- package/lib/cache/IdleFileCachePlugin.js +2 -2
- package/lib/cache/MemoryCachePlugin.js +18 -10
- package/lib/cache/MemoryWithGcCachePlugin.js +34 -22
- package/lib/cache/PackFileCacheStrategy.js +30 -23
- package/lib/cache/ResolverCachePlugin.js +38 -18
- package/lib/cache/getLazyHashedEtag.js +1 -2
- package/lib/cache/mergeEtags.js +1 -1
- package/lib/cli.js +1 -3
- package/lib/config/browserslistTargetHandler.js +41 -5
- package/lib/config/defaults.js +270 -78
- package/lib/config/defineConfig.js +10 -2
- package/lib/config/getClaimedAssetTypes.js +65 -0
- package/lib/config/normalization.js +46 -16
- package/lib/config/target.js +46 -3
- package/lib/container/ContainerEntryDependency.js +1 -1
- package/lib/container/ContainerEntryModule.js +24 -15
- package/lib/container/ContainerEntryModuleFactory.js +7 -3
- package/lib/container/ContainerPlugin.js +9 -10
- package/lib/container/ContainerReferencePlugin.js +6 -2
- package/lib/container/FallbackDependency.js +1 -1
- package/lib/container/FallbackModule.js +24 -17
- package/lib/container/FallbackModuleFactory.js +7 -3
- package/lib/container/HoistContainerReferencesPlugin.js +6 -11
- package/lib/container/ModuleFederationPlugin.js +7 -24
- package/lib/container/RemoteModule.js +27 -19
- package/lib/container/RemoteRuntimeModule.js +10 -8
- package/lib/container/moduleFederationHooks.js +32 -0
- package/lib/css/CssGenerator.js +171 -43
- package/lib/css/CssInjectStyleRuntimeModule.js +7 -5
- package/lib/css/CssLoadingRuntimeModule.js +84 -32
- package/lib/css/CssModule.js +10 -7
- package/lib/css/CssModulesPlugin.js +172 -100
- package/lib/css/CssParser.js +1113 -568
- package/lib/css/CssServerStylesRuntimeModule.js +54 -0
- package/lib/css/cssMinify.js +168 -0
- package/lib/css/data.js +5334 -0
- package/lib/css/syntax.js +9647 -232
- package/lib/debug/ProfilingPlugin.js +14 -9
- package/lib/deno/DenoTargetPlugin.js +1 -1
- package/lib/dependencies/AMDDefineDependency.js +112 -87
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +30 -17
- package/lib/dependencies/AMDPlugin.js +9 -7
- package/lib/dependencies/AMDRequireArrayDependency.js +5 -5
- package/lib/dependencies/AMDRequireContextDependency.js +2 -2
- package/lib/dependencies/AMDRequireDependenciesBlock.js +1 -1
- package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +25 -14
- package/lib/dependencies/AMDRequireDependency.js +8 -7
- package/lib/dependencies/AMDRequireItemDependency.js +1 -1
- package/lib/dependencies/AMDRuntimeModules.js +21 -1
- package/lib/dependencies/BuildTimeConstDependency.js +102 -0
- package/lib/dependencies/CachedConstDependency.js +11 -8
- package/lib/dependencies/CommonJsDependencyHelpers.js +67 -46
- package/lib/dependencies/CommonJsExportRequireDependency.js +121 -45
- package/lib/dependencies/CommonJsExportsDependency.js +53 -49
- package/lib/dependencies/CommonJsExportsParserPlugin.js +207 -25
- package/lib/dependencies/CommonJsFullRequireDependency.js +119 -34
- package/lib/dependencies/CommonJsImportsParserPlugin.js +100 -50
- package/lib/dependencies/CommonJsObjectExportDependency.js +188 -0
- package/lib/dependencies/CommonJsPlugin.js +35 -6
- package/lib/dependencies/CommonJsRequireContextDependency.js +5 -6
- package/lib/dependencies/CommonJsRequireDependency.js +170 -27
- package/lib/dependencies/CommonJsSelfReferenceDependency.js +63 -38
- package/lib/dependencies/ConstDependency.js +8 -9
- package/lib/dependencies/ContextDependency.js +12 -8
- package/lib/dependencies/ContextDependencyHelpers.js +14 -9
- package/lib/dependencies/ContextDependencyTemplateAsId.js +4 -4
- package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +24 -11
- package/lib/dependencies/ContextElementDependency.js +31 -12
- package/lib/dependencies/CreateRequireParserPlugin.js +12 -7
- package/lib/dependencies/CreateScriptUrlDependency.js +4 -4
- package/lib/dependencies/CssIcssExportDependency.js +56 -28
- package/lib/dependencies/CssIcssImportDependency.js +17 -13
- package/lib/dependencies/CssIcssSymbolDependency.js +9 -10
- package/lib/dependencies/CssImportDependency.js +18 -9
- package/lib/dependencies/CssUrlDependency.js +17 -13
- package/lib/dependencies/DllEntryDependency.js +1 -1
- package/lib/dependencies/DynamicExports.js +2 -2
- package/lib/dependencies/ExportBindingInitFragment.js +36 -9
- package/lib/dependencies/ExportsInfoDependency.js +7 -8
- package/lib/dependencies/ExternalModuleDependency.js +9 -5
- package/lib/dependencies/ExternalModuleInitFragment.js +2 -2
- package/lib/dependencies/ExternalModuleInitFragmentDependency.js +8 -5
- package/lib/dependencies/HarmonyAcceptDependency.js +5 -5
- package/lib/dependencies/HarmonyCompatibilityDependency.js +52 -17
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +11 -7
- package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +23 -14
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +80 -12
- package/lib/dependencies/HarmonyExportExpressionDependency.js +23 -18
- package/lib/dependencies/HarmonyExportHeaderDependency.js +7 -7
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +286 -80
- package/lib/dependencies/HarmonyExportInitFragment.js +18 -6
- package/lib/dependencies/HarmonyExportSpecifierDependency.js +51 -14
- package/lib/dependencies/HarmonyExports.js +7 -4
- package/lib/dependencies/HarmonyImportDependency.js +121 -60
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +124 -38
- package/lib/dependencies/HarmonyImportGuard.js +20 -30
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +152 -9
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +97 -49
- package/lib/dependencies/HarmonyModulesPlugin.js +7 -3
- package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -3
- package/lib/dependencies/HtmlEntryDependency.js +49 -31
- package/lib/dependencies/HtmlInlineHtmlDependency.js +7 -8
- package/lib/dependencies/HtmlInlineScriptDependency.js +11 -8
- package/lib/dependencies/HtmlInlineStyleDependency.js +7 -10
- package/lib/dependencies/HtmlSourceDependency.js +22 -14
- package/lib/dependencies/ImportContextDependency.js +45 -5
- package/lib/dependencies/ImportDependency.js +33 -50
- package/lib/dependencies/ImportEagerDependency.js +6 -9
- package/lib/dependencies/ImportMetaContextDependency.js +2 -2
- package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +14 -13
- package/lib/dependencies/ImportMetaContextPlugin.js +7 -3
- package/lib/dependencies/ImportMetaGlobDependency.js +2 -2
- package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +2 -3
- package/lib/dependencies/ImportMetaGlobHelpers.js +19 -22
- package/lib/dependencies/ImportMetaHotAcceptDependency.js +1 -1
- package/lib/dependencies/ImportMetaHotDeclineDependency.js +1 -1
- package/lib/dependencies/ImportMetaPlugin.js +154 -71
- package/lib/dependencies/ImportMetaResolveDependency.js +3 -4
- package/lib/dependencies/ImportParserPlugin.js +73 -49
- package/lib/dependencies/ImportPhase.js +12 -5
- package/lib/dependencies/ImportPlugin.js +7 -3
- package/lib/dependencies/ImportWeakDependency.js +6 -9
- package/lib/dependencies/JsonExportsDependency.js +11 -7
- package/lib/dependencies/LoaderDependency.js +2 -2
- package/lib/dependencies/LoaderImportDependency.js +2 -2
- package/lib/dependencies/LoaderPlugin.js +11 -7
- package/lib/dependencies/LocalModuleDependency.js +5 -5
- package/lib/dependencies/LocalModulesHelpers.js +1 -1
- package/lib/dependencies/ModuleDecoratorDependency.js +6 -7
- package/lib/dependencies/ModuleDependency.js +9 -6
- package/lib/dependencies/ModuleDependencyTemplateAsId.js +4 -4
- package/lib/dependencies/ModuleDependencyTemplateAsRequireId.js +3 -3
- package/lib/dependencies/ModuleHotAcceptDependency.js +1 -1
- package/lib/dependencies/ModuleHotDeclineDependency.js +1 -1
- package/lib/dependencies/ModuleInitFragmentDependency.js +24 -10
- package/lib/dependencies/NullDependency.js +3 -3
- package/lib/dependencies/ProvidedDependency.js +14 -10
- package/lib/dependencies/PureExpressionDependency.js +9 -10
- package/lib/dependencies/RequireContextDependency.js +2 -2
- package/lib/dependencies/RequireContextDependencyParserPlugin.js +2 -4
- package/lib/dependencies/RequireContextPlugin.js +8 -4
- package/lib/dependencies/RequireEnsureDependenciesBlock.js +2 -2
- package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +5 -8
- package/lib/dependencies/RequireEnsureDependency.js +8 -7
- package/lib/dependencies/RequireEnsurePlugin.js +7 -3
- package/lib/dependencies/RequireHeaderDependency.js +50 -12
- package/lib/dependencies/RequireIncludeDependency.js +6 -6
- package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +2 -3
- package/lib/dependencies/RequireIncludePlugin.js +7 -3
- package/lib/dependencies/RequireJsStuffPlugin.js +7 -3
- package/lib/dependencies/RequireResolveContextDependency.js +2 -2
- package/lib/dependencies/RequireResolveDependency.js +4 -4
- package/lib/dependencies/RequireResolveHeaderDependency.js +4 -4
- package/lib/dependencies/RuntimeRequirementsDependency.js +5 -6
- package/lib/dependencies/StaticExportsDependency.js +2 -2
- package/lib/dependencies/SystemPlugin.js +10 -6
- package/lib/dependencies/SystemRuntimeModule.js +10 -0
- package/lib/dependencies/TopLevelAwaitDependency.js +11 -7
- package/lib/dependencies/URLContextDependency.js +2 -2
- package/lib/dependencies/URLDependency.js +110 -64
- package/lib/dependencies/URLPlugin.js +7 -3
- package/lib/dependencies/UnsupportedDependency.js +4 -4
- package/lib/dependencies/WebAssemblyExportImportedDependency.js +3 -4
- package/lib/dependencies/WebAssemblyImportDependency.js +5 -5
- package/lib/dependencies/WebpackIsIncludedDependency.js +6 -6
- package/lib/dependencies/WorkerAndWorkletPlugin.js +47 -28
- package/lib/dependencies/WorkerDependency.js +22 -22
- package/lib/dependencies/WorkletDependency.js +18 -21
- package/lib/dependencies/getFunctionExpression.js +8 -4
- package/lib/dependencies/importOptionsCheck.js +47 -0
- package/lib/dependencies/processExportInfo.js +5 -5
- package/lib/dll/DelegatedModule.js +34 -22
- package/lib/dll/DelegatedModuleFactoryPlugin.js +15 -7
- package/lib/dll/DelegatedPlugin.js +2 -2
- package/lib/dll/DllEntryPlugin.js +2 -2
- package/lib/dll/DllModule.js +22 -15
- package/lib/dll/DllModuleFactory.js +7 -3
- package/lib/dll/DllPlugin.js +7 -5
- package/lib/dll/DllReferencePlugin.js +10 -7
- package/lib/dll/LibManifestPlugin.js +5 -5
- package/lib/electron/ElectronTargetPlugin.js +53 -49
- package/lib/errors/AsyncChunkWaterfallWarning.js +36 -0
- package/lib/errors/AsyncDependencyToInitialChunkError.js +2 -2
- package/lib/errors/BroadContextsWarning.js +43 -0
- package/lib/errors/BuildCycleError.js +1 -1
- package/lib/errors/CacheEffectivenessWarning.js +55 -0
- package/lib/errors/ChunkRenderError.js +1 -1
- package/lib/errors/CircularDependenciesWarning.js +38 -0
- package/lib/errors/CodeGenerationError.js +1 -1
- package/lib/errors/CommentCompilationWarning.js +1 -1
- package/lib/errors/ConflictingResourceHintsWarning.js +35 -0
- package/lib/errors/DotenvFileError.js +29 -0
- package/lib/errors/DuplicateModulesWarning.js +45 -0
- package/lib/errors/DynamicExportsWarning.js +30 -0
- package/lib/errors/EmbeddedSourceMapsWarning.js +25 -0
- package/lib/errors/EntrypointOverlapWarning.js +45 -0
- package/lib/errors/EnvironmentNotSupportAsyncWarning.js +2 -2
- package/lib/errors/EvalUsageWarning.js +28 -0
- package/lib/errors/HookWebpackError.js +5 -5
- package/lib/errors/HotspotsWarning.js +57 -0
- package/lib/errors/IgnoreErrorModuleFactory.js +7 -3
- package/lib/errors/ImportedBindingAssignmentError.js +30 -0
- package/lib/errors/InlinedAssetsWarning.js +36 -0
- package/lib/errors/InvalidDependenciesModuleWarning.js +1 -1
- package/lib/errors/LargeModulesWarning.js +45 -0
- package/lib/errors/LegacyJavascriptWarning.js +48 -0
- package/lib/errors/MissingSideEffectsWarning.js +36 -0
- package/lib/errors/MixedExportsWarning.js +41 -0
- package/lib/errors/ModuleDependencyError.js +13 -16
- package/lib/errors/ModuleDependencyWarning.js +5 -15
- package/lib/errors/ModuleHashingError.js +1 -1
- package/lib/errors/ModuleNotFoundError.js +2 -2
- package/lib/errors/ModuleParseError.js +1 -2
- package/lib/errors/ModuleRestoreError.js +1 -1
- package/lib/errors/ModuleStoreError.js +1 -1
- package/lib/errors/NodeStuffInWebError.js +1 -1
- package/lib/errors/OsDependentRuleWarning.js +31 -0
- package/lib/errors/PureAnnotationsWarning.js +36 -0
- package/lib/errors/RedundantDynamicImportWarning.js +31 -0
- package/lib/errors/ScopeHoistingBailoutsWarning.js +41 -0
- package/lib/errors/SplitChunksCappedWarning.js +41 -0
- package/lib/errors/TinyChunksWarning.js +40 -0
- package/lib/errors/TopLevelThisWarning.js +34 -0
- package/lib/errors/UnsplitVendorsWarning.js +42 -0
- package/lib/errors/UnsupportedFeatureWarning.js +1 -1
- package/lib/errors/UnusedAliasesWarning.js +29 -0
- package/lib/errors/UnusedDefinesWarning.js +29 -0
- package/lib/errors/UnusedExternalsWarning.js +29 -0
- package/lib/errors/UnusedReexportsWarning.js +42 -0
- package/lib/errors/UnusedRuleWarning.js +29 -0
- package/lib/errors/WebpackError.js +9 -5
- package/lib/errors/deriveStackFromNestedError.js +90 -0
- package/lib/esm/ExportWebpackRequireRuntimeModule.js +2 -0
- package/lib/esm/ModuleChunkFormatPlugin.js +37 -19
- package/lib/esm/ModuleChunkLoadingPlugin.js +86 -51
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +161 -62
- package/lib/hmr/HotModuleReplacement.runtime.js +24 -5
- package/lib/hmr/HotModuleReplacementRuntimeModule.js +1 -1
- package/lib/hmr/LazyCompilationPlugin.js +45 -24
- package/lib/hmr/lazyCompilationBackend.js +9 -6
- package/lib/hmr/parserHooks.js +56 -0
- package/lib/html/HtmlGenerator.js +277 -77
- package/lib/html/HtmlModule.js +7 -3
- package/lib/html/HtmlModulesPlugin.js +366 -200
- package/lib/html/HtmlParser.js +31 -86
- package/lib/html/data.js +1928 -0
- package/lib/html/htmlMinify.js +288 -0
- package/lib/html/syntax.js +6034 -1384
- package/lib/ids/ChunkModuleIdRangePlugin.js +3 -3
- package/lib/ids/DeterministicChunkIdsPlugin.js +1 -1
- package/lib/ids/DeterministicModuleIdsPlugin.js +2 -2
- package/lib/ids/HashedModuleIdsPlugin.js +6 -2
- package/lib/ids/IdHelpers.js +7 -8
- package/lib/ids/NamedChunkIdsPlugin.js +1 -1
- package/lib/ids/NamedModuleIdsPlugin.js +1 -1
- package/lib/ids/NaturalChunkIdsPlugin.js +2 -2
- package/lib/ids/NaturalModuleIdsPlugin.js +1 -1
- package/lib/ids/OccurrenceChunkIdsPlugin.js +7 -3
- package/lib/ids/OccurrenceModuleIdsPlugin.js +7 -3
- package/lib/ids/SyncModuleIdsPlugin.js +4 -4
- package/lib/index.js +10 -0
- package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +3 -3
- package/lib/javascript/BasicEvaluatedExpression.js +18 -14
- package/lib/javascript/ChunkFormatHelpers.js +6 -6
- package/lib/javascript/ChunkHelpers.js +1 -1
- package/lib/javascript/CommonJsChunkFormatPlugin.js +11 -5
- package/lib/javascript/EnableChunkLoadingPlugin.js +2 -2
- package/lib/javascript/JavascriptGenerator.js +65 -165
- package/lib/javascript/JavascriptModule.js +9 -3
- package/lib/javascript/JavascriptModulesPlugin.js +103 -123
- package/lib/javascript/JavascriptParser.js +242 -99
- package/lib/javascript/JavascriptParserHelpers.js +10 -7
- package/lib/javascript/ScopeAnalyzer.js +1094 -0
- package/lib/javascript/StartupHelpers.js +55 -9
- package/lib/javascript/syntax.js +2678 -232
- package/lib/json/JsonData.js +8 -4
- package/lib/json/JsonGenerator.js +38 -16
- package/lib/json/JsonModule.js +7 -3
- package/lib/json/JsonModulesPlugin.js +1 -1
- package/lib/json/JsonParser.js +5 -6
- package/lib/library/AbstractLibraryPlugin.js +20 -14
- package/lib/library/AmdLibraryPlugin.js +11 -7
- package/lib/library/AssignLibraryPlugin.js +19 -13
- package/lib/library/EnableLibraryPlugin.js +2 -2
- package/lib/library/ExportPropertyLibraryPlugin.js +15 -8
- package/lib/library/JsonpLibraryPlugin.js +11 -7
- package/lib/library/ModuleLibraryPlugin.js +256 -64
- package/lib/library/SystemLibraryPlugin.js +12 -8
- package/lib/library/UmdLibraryPlugin.js +62 -25
- package/lib/loaders/LoaderRunner.js +47 -6
- package/lib/loaders/loadLoader.js +8 -4
- package/lib/logging/createConsoleLogger.js +7 -4
- package/lib/node/CommonJsChunkLoadingPlugin.js +36 -22
- package/lib/node/NodeEnvironmentPlugin.js +17 -3
- package/lib/node/NodeSourcePlugin.js +1 -1
- package/lib/node/NodeTargetPlugin.js +4 -3
- package/lib/node/NodeTemplatePlugin.js +1 -1
- package/lib/node/NodeWatchFileSystem.js +70 -9
- package/lib/node/ReadFileChunkLoadingRuntimeModule.js +35 -38
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +65 -19
- package/lib/node/ReadFileCompileWasmPlugin.js +28 -16
- package/lib/node/RequireChunkLoadingRuntimeModule.js +35 -38
- package/lib/node/nodeConsole.js +7 -3
- package/lib/optimize/AggressiveMergingPlugin.js +2 -2
- package/lib/optimize/AggressiveSplittingPlugin.js +9 -6
- package/lib/optimize/ConcatenatedModule.js +1030 -476
- package/lib/optimize/ConstExportsPlugin.js +16 -7
- package/lib/optimize/EnsureChunkConditionsPlugin.js +3 -3
- package/lib/optimize/FlagIncludedChunksPlugin.js +3 -4
- package/lib/optimize/InlineExports.js +130 -5
- package/lib/optimize/InnerGraph.js +28 -12
- package/lib/optimize/InnerGraphPlugin.js +23 -18
- package/lib/optimize/LimitChunkCountPlugin.js +7 -3
- package/lib/optimize/MangleExportsPlugin.js +7 -8
- package/lib/optimize/MergeDuplicateChunksPlugin.js +7 -3
- package/lib/optimize/MinChunkSizePlugin.js +7 -3
- package/lib/optimize/ModuleConcatenationPlugin.js +51 -35
- package/lib/optimize/RealContentHashPlugin.js +121 -41
- package/lib/optimize/RemoveEmptyChunksPlugin.js +2 -2
- package/lib/optimize/RemoveParentModulesPlugin.js +4 -4
- package/lib/optimize/RuntimeChunkPlugin.js +2 -2
- package/lib/optimize/SideEffectsFlagPlugin.js +262 -39
- package/lib/optimize/SplitChunksPlugin.js +86 -24
- package/lib/performance/AssetsOverSizeLimitWarning.js +10 -2
- package/lib/performance/AsyncChunkWaterfallsPlugin.js +136 -0
- package/lib/performance/BroadContextsPlugin.js +142 -0
- package/lib/performance/CacheEffectivenessPlugin.js +125 -0
- package/lib/performance/ConflictingResourceHintsPlugin.js +99 -0
- package/lib/performance/DuplicateModulesPlugin.js +93 -0
- package/lib/performance/DuplicatePackagesPlugin.js +119 -0
- package/lib/performance/DuplicatePackagesWarning.js +84 -0
- package/lib/performance/DynamicExportsPlugin.js +120 -0
- package/lib/performance/EmbeddedSourceMapsPlugin.js +71 -0
- package/lib/performance/EntrypointOverlapPlugin.js +122 -0
- package/lib/performance/EntrypointsOverSizeLimitWarning.js +1 -1
- package/lib/performance/EvalUsagePlugin.js +115 -0
- package/lib/performance/HotspotsPlugin.js +296 -0
- package/lib/performance/InlinedAssetsPlugin.js +99 -0
- package/lib/performance/LargeModulesPlugin.js +126 -0
- package/lib/performance/LegacyJavascriptPlugin.js +139 -0
- package/lib/performance/MissingSideEffectsPlugin.js +138 -0
- package/lib/performance/MixedExportsPlugin.js +136 -0
- package/lib/performance/OsDependentRuleWarningPlugin.js +178 -0
- package/lib/performance/PureAnnotationsPlugin.js +219 -0
- package/lib/performance/RedundantDynamicImportsPlugin.js +225 -0
- package/lib/performance/RuntimeInLargeChunkWarning.js +27 -0
- package/lib/performance/ScopeHoistingBailoutsPlugin.js +164 -0
- package/lib/performance/SizeLimitsPlugin.js +139 -7
- package/lib/performance/SplitChunksCappedPlugin.js +99 -0
- package/lib/performance/TinyChunksPlugin.js +128 -0
- package/lib/performance/TopLevelThisPlugin.js +208 -0
- package/lib/performance/UnsplitVendorsPlugin.js +112 -0
- package/lib/performance/UnusedAliasesPlugin.js +253 -0
- package/lib/performance/UnusedDefinesPlugin.js +87 -0
- package/lib/performance/UnusedExternalsPlugin.js +110 -0
- package/lib/performance/UnusedReexportsPlugin.js +159 -0
- package/lib/performance/UnusedRuleWarningPlugin.js +105 -0
- package/lib/performance/getModuleSize.js +22 -0
- package/lib/performance/getSourceModules.js +22 -0
- package/lib/performance/hasOnlyUnusedExports.js +40 -0
- package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +24 -10
- package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +63 -46
- package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +2 -3
- package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +2 -2
- package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +2 -2
- package/lib/prefetch/ResourceHintPlugin.js +295 -79
- package/lib/prefetch/ResourceHintRuntimeModule.js +1 -21
- package/lib/prefetch/StartupAssetHintRuntimeModule.js +10 -133
- package/lib/prefetch/parseResourceHintOptions.js +31 -4
- package/lib/rules/BasicEffectRulePlugin.js +2 -2
- package/lib/rules/BasicMatcherRulePlugin.js +8 -4
- package/lib/rules/GlobMatcherRulePlugin.js +68 -0
- package/lib/rules/ObjectMatcherRulePlugin.js +12 -5
- package/lib/rules/RuleSetCompiler.js +146 -12
- package/lib/rules/UseEffectRulePlugin.js +18 -11
- package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +11 -1
- package/lib/runtime/AsyncModuleRuntimeModule.js +6 -2
- package/lib/runtime/AutoPublicPathRuntimeModule.js +15 -20
- package/lib/runtime/BaseUriRuntimeModule.js +33 -7
- package/lib/runtime/ChunkNameRuntimeModule.js +10 -0
- package/lib/runtime/CompatGetDefaultExportRuntimeModule.js +11 -1
- package/lib/runtime/CompatRuntimeModule.js +5 -3
- package/lib/runtime/ConcatenationWrapRuntimeModule.js +90 -0
- package/lib/runtime/ConstructRequireRuntimeModule.js +52 -0
- package/lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js +8 -6
- package/lib/runtime/CreateScriptRuntimeModule.js +11 -1
- package/lib/runtime/CreateScriptUrlRuntimeModule.js +11 -1
- package/lib/runtime/DefinePropertyGettersRuntimeModule.js +56 -38
- package/lib/runtime/EnsureChunkRuntimeModule.js +18 -2
- package/lib/runtime/GetChunkFilenameRuntimeModule.js +62 -37
- package/lib/runtime/GetFullHashRuntimeModule.js +12 -2
- package/lib/runtime/GetMainFilenameRuntimeModule.js +12 -2
- package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +2 -2
- package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +16 -3
- package/lib/runtime/GlobalRuntimeModule.js +18 -0
- package/lib/runtime/HasOwnPropertyRuntimeModule.js +12 -2
- package/lib/runtime/LoadScriptRuntimeModule.js +2 -2
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +34 -7
- package/lib/runtime/MakeNamespaceObjectRuntimeModule.js +22 -6
- package/lib/runtime/NonceRuntimeModule.js +10 -0
- package/lib/runtime/OnChunksLoadedRuntimeModule.js +5 -3
- package/lib/runtime/PublicPathRuntimeModule.js +12 -2
- package/lib/runtime/RelativeUrlRuntimeModule.js +11 -1
- package/lib/runtime/RuntimeIdRuntimeModule.js +12 -2
- package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +11 -1
- package/lib/runtime/StartupChunkDependenciesPlugin.js +18 -9
- package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +3 -3
- package/lib/runtime/StartupEntrypointRuntimeModule.js +21 -4
- package/lib/runtime/SystemContextRuntimeModule.js +10 -0
- package/lib/runtime/ToBinaryRuntimeModule.js +1 -1
- package/lib/runtime/WorkerRuntimeModule.js +11 -1
- package/lib/runtime/baseUri.js +63 -0
- package/lib/schemes/DataUriPlugin.js +1 -1
- package/lib/schemes/FileUriPlugin.js +1 -1
- package/lib/schemes/HttpUriPlugin.js +46 -20
- package/lib/schemes/VirtualUrlPlugin.js +13 -7
- package/lib/serialization/AggregateErrorSerializer.js +1 -1
- package/lib/serialization/BinaryMiddleware.js +4 -4
- package/lib/serialization/ErrorObjectSerializer.js +1 -1
- package/lib/serialization/FileMiddleware.js +22 -9
- package/lib/serialization/ObjectMiddleware.js +139 -114
- package/lib/serialization/PlainObjectSerializer.js +19 -16
- package/lib/sharing/ConsumeSharedModule.js +30 -21
- package/lib/sharing/ConsumeSharedPlugin.js +18 -10
- package/lib/sharing/ConsumeSharedRuntimeModule.js +6 -9
- package/lib/sharing/ProvideSharedModule.js +25 -16
- package/lib/sharing/ProvideSharedModuleFactory.js +7 -3
- package/lib/sharing/ProvideSharedPlugin.js +8 -4
- package/lib/sharing/SharePlugin.js +17 -5
- package/lib/sharing/ShareRuntimeModule.js +4 -4
- package/lib/sharing/resolveMatchedConfigs.js +9 -6
- package/lib/sharing/utils.js +1 -3
- package/lib/stats/DefaultStatsFactoryPlugin.js +50 -29
- package/lib/stats/DefaultStatsPresetPlugin.js +17 -8
- package/lib/stats/DefaultStatsPrinterPlugin.js +36 -26
- package/lib/stats/StatsFactory.js +25 -26
- package/lib/stats/StatsPrinter.js +16 -12
- package/lib/typescript/TypeScriptPlugin.js +20 -24
- package/lib/url/URLParserPlugin.js +26 -13
- package/lib/util/ArrayQueue.js +3 -3
- package/lib/util/AsyncQueue.js +4 -3
- package/lib/util/Hash.js +5 -1
- package/lib/util/LazySet.js +35 -22
- package/lib/util/LocConverter.js +36 -13
- package/lib/util/SourceProcessor.js +1066 -24
- package/lib/util/StringXor.js +1 -1
- package/lib/util/URLAbsoluteSpecifier.js +3 -1
- package/lib/util/chainedImports.js +9 -5
- package/lib/util/cleverMerge.js +1 -1
- package/lib/util/comparators.js +45 -14
- package/lib/util/concatenate.js +203 -77
- package/lib/util/conventions.js +10 -2
- package/lib/util/createHash.js +2 -2
- package/lib/util/createHooksRegistry.js +8 -10
- package/lib/util/createMappings.js +25 -3
- package/lib/util/dataURL.js +225 -1
- package/lib/util/extractSourceMap.js +4 -3
- package/lib/util/findCaseMismatch.js +139 -0
- package/lib/util/formatLocation.js +1 -2
- package/lib/util/fs.js +22 -5
- package/lib/util/globUtils.js +298 -24
- package/lib/util/hash/BatchedHash.js +5 -1
- package/lib/util/hash/BulkUpdateHash.js +5 -1
- package/lib/util/hash/DebugHash.js +5 -1
- package/lib/util/hash/hash-digest.js +6 -2
- package/lib/util/identifier.js +4 -0
- package/lib/util/implicitTypeLoaderFallback.js +1 -1
- package/lib/util/internalSerializables.js +8 -0
- package/lib/util/lazyModule.js +56 -0
- package/lib/util/makeSerializable.js +7 -3
- package/lib/util/matchAlias.js +25 -0
- package/lib/util/mimeTypes.js +11 -5
- package/lib/util/nonNumericOnlyHash.js +4 -3
- package/lib/util/parseJson.js +5 -3
- package/lib/util/preloadModuleType.js +32 -0
- package/lib/util/registerExternalSerializer.js +7 -5
- package/lib/util/removeBOM.js +82 -1
- package/lib/util/runtime.js +2 -2
- package/lib/util/semver.js +1 -1
- package/lib/util/serialization.js +28 -28
- package/lib/util/source.js +2 -2
- package/lib/util/traverseDestructuringAssignmentProperties.js +6 -2
- package/lib/wasm/EnableWasmLoadingPlugin.js +10 -8
- package/lib/wasm/wasmModuleFilename.js +54 -0
- package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +43 -21
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +45 -21
- package/lib/wasm-async/AsyncWasmModule.js +3 -3
- package/lib/wasm-async/AsyncWebAssemblyGenerator.js +4 -5
- package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +57 -17
- package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +34 -18
- package/lib/wasm-async/AsyncWebAssemblyParser.js +9 -8
- package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +29 -8
- package/lib/wasm-sync/SyncWasmModule.js +2 -2
- package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +18 -13
- package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +4 -5
- package/lib/wasm-sync/WebAssemblyGenerator.js +18 -17
- package/lib/wasm-sync/WebAssemblyInInitialChunkError.js +4 -4
- package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +7 -7
- package/lib/wasm-sync/WebAssemblyModulesPlugin.js +24 -11
- package/lib/wasm-sync/WebAssemblyParser.js +4 -6
- package/lib/wasm-sync/WebAssemblyUtils.js +2 -2
- package/lib/web/FetchCompileAsyncWasmPlugin.js +105 -19
- package/lib/web/FetchCompileWasmPlugin.js +48 -16
- package/lib/web/JsonpChunkLoadingPlugin.js +47 -23
- package/lib/web/JsonpChunkLoadingRuntimeModule.js +50 -20
- package/lib/web/JsonpTemplatePlugin.js +2 -2
- package/lib/webpack.js +22 -11
- package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +60 -26
- package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +30 -32
- package/lib/webworker/WebWorkerTemplatePlugin.js +1 -1
- package/module.d.ts +1 -0
- package/package.json +32 -25
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +667 -34
- package/schemas/plugins/HtmlParserOptions.check.js +1 -1
- package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
- package/schemas/plugins/container/ContainerPlugin.json +10 -0
- package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.json +10 -0
- package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
- package/schemas/plugins/css/CssParserOptions.check.js +1 -1
- package/types.d.ts +3223 -465
- package/lib/runtime/CommonJsWrapRuntimeModule.js +0 -37
package/lib/css/CssParser.js
CHANGED
|
@@ -15,9 +15,6 @@ const CssIcssSymbolDependency = require("../dependencies/CssIcssSymbolDependency
|
|
|
15
15
|
const CssImportDependency = require("../dependencies/CssImportDependency");
|
|
16
16
|
const CssUrlDependency = require("../dependencies/CssUrlDependency");
|
|
17
17
|
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
|
|
18
|
-
const CommentCompilationWarning = require("../errors/CommentCompilationWarning");
|
|
19
|
-
const ModuleDependencyWarning = require("../errors/ModuleDependencyWarning");
|
|
20
|
-
const UnsupportedFeatureWarning = require("../errors/UnsupportedFeatureWarning");
|
|
21
18
|
const WebpackError = require("../errors/WebpackError");
|
|
22
19
|
const ResourceHintPlugin = require("../prefetch/ResourceHintPlugin");
|
|
23
20
|
const LocConverter = require("../util/LocConverter");
|
|
@@ -26,7 +23,9 @@ const {
|
|
|
26
23
|
createMagicCommentContext,
|
|
27
24
|
parseCommentOptionsInRange
|
|
28
25
|
} = require("../util/magicComment");
|
|
26
|
+
const memoize = require("../util/memoize");
|
|
29
27
|
const topologicalSort = require("../util/topologicalSort");
|
|
28
|
+
const { CSS_MODULES_KEYWORDS, CSS_MODULES_KEYWORD_OPTIONS } = require("./data");
|
|
30
29
|
const {
|
|
31
30
|
A,
|
|
32
31
|
NodeType,
|
|
@@ -38,40 +37,83 @@ const {
|
|
|
38
37
|
normalizeUrl,
|
|
39
38
|
rangeEquals,
|
|
40
39
|
rangeEqualsLowerCase,
|
|
40
|
+
skipEscape,
|
|
41
41
|
toLowerCaseIfNeeded,
|
|
42
42
|
unescapeIdentifier
|
|
43
43
|
} = require("./syntax");
|
|
44
44
|
|
|
45
|
+
const getUnsupportedFeatureWarning = memoize(() =>
|
|
46
|
+
require("../errors/UnsupportedFeatureWarning")
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const getModuleDependencyWarning = memoize(() =>
|
|
50
|
+
require("../errors/ModuleDependencyWarning")
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const getCommentCompilationWarning = memoize(() =>
|
|
54
|
+
require("../errors/CommentCompilationWarning")
|
|
55
|
+
);
|
|
56
|
+
|
|
45
57
|
// `SourceProcessor` drives the parse and hands already-built AST nodes to the visitors; positions are read from those nodes' ranges rather than re-scanning the source.
|
|
46
58
|
|
|
47
|
-
/** @
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
/** @
|
|
56
|
-
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
/** @import { BuildInfo, BuildMeta } from "../Module" */
|
|
60
|
+
/**
|
|
61
|
+
* @import CssModule, {
|
|
62
|
+
* CssModuleBuildInfo,
|
|
63
|
+
* CssModuleBuildMeta,
|
|
64
|
+
* Inheritance
|
|
65
|
+
* } from "./CssModule"
|
|
66
|
+
*/
|
|
67
|
+
/** @import { ParserState, PreparsedAst } from "../Parser" */
|
|
68
|
+
/**
|
|
69
|
+
* @import {
|
|
70
|
+
* AtRule,
|
|
71
|
+
* Declaration,
|
|
72
|
+
* FunctionNode,
|
|
73
|
+
* Node as AstNode,
|
|
74
|
+
* QualifiedRule,
|
|
75
|
+
* Rule,
|
|
76
|
+
* SimpleBlock,
|
|
77
|
+
* Token,
|
|
78
|
+
* UrlToken,
|
|
79
|
+
* VisitorMap
|
|
80
|
+
* } from "./syntax"
|
|
81
|
+
*/
|
|
82
|
+
/**
|
|
83
|
+
* @import {
|
|
84
|
+
* CssAutoOrModuleParserOptions
|
|
85
|
+
* } from "../../declarations/WebpackOptions"
|
|
86
|
+
*/
|
|
68
87
|
|
|
69
88
|
/** @typedef {[number, number]} Range */
|
|
70
89
|
/** @typedef {{ line: number, column: number }} Position */
|
|
71
90
|
/** @typedef {{ from: string, items: ({ localName: string, importName: string })[] }} ValueAtRuleImport */
|
|
72
91
|
/** @typedef {{ localName: string, value: string }} ValueAtRuleValue */
|
|
92
|
+
/**
|
|
93
|
+
* What a `@custom-media` name resolves to. `condition` substitutes into any
|
|
94
|
+
* `<media-in-parens>` slot, `type` only at the start of a query, `boolean` is the
|
|
95
|
+
* spec's `true` / `false` (folded into the enclosing query rather than written
|
|
96
|
+
* out — no `<media-in-parens>` is unconditionally true on every engine).
|
|
97
|
+
* @typedef {{ kind: "condition" | "type", text: string } | { kind: "boolean", value: boolean } | { kind: "unsupported" }} CustomMediaValue
|
|
98
|
+
*/
|
|
99
|
+
/** @typedef {CustomMediaValue | { kind: "alias", name: string } | { kind: "or", parts: ({ text: string } | { alias: string })[] }} CustomMediaDefinition */
|
|
100
|
+
/** @typedef {{ name: string, start: number, end: number, invalid: boolean, leading: boolean }} CustomMediaUse */
|
|
101
|
+
/**
|
|
102
|
+
* A `@media` prelude captured as its boolean shape, so a `true` / `false`
|
|
103
|
+
* definition found later can be folded into it. Node ids are recycled per
|
|
104
|
+
* top-level rule, so this holds text and offsets rather than AST nodes.
|
|
105
|
+
* @typedef {{ kind: "text", text: string } | { kind: "ref", text: string, use: CustomMediaUse } | { kind: "group", operand: MediaNode } | { kind: "not", operand: MediaNode } | { kind: "chain", isOr: boolean, terms: MediaNode[] } | { kind: "typed", text: string, rest: MediaNode | null }} MediaNode
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
/** @type {CustomMediaValue} */
|
|
109
|
+
const CUSTOM_MEDIA_UNSUPPORTED = { kind: "unsupported" };
|
|
110
|
+
/** @type {CustomMediaValue} */
|
|
111
|
+
const CUSTOM_MEDIA_TRUE = { kind: "boolean", value: true };
|
|
112
|
+
/** @type {CustomMediaValue} */
|
|
113
|
+
const CUSTOM_MEDIA_FALSE = { kind: "boolean", value: false };
|
|
73
114
|
|
|
74
115
|
const CC_COLON = ":".charCodeAt(0);
|
|
116
|
+
const CC_FULL_STOP = ".".charCodeAt(0);
|
|
75
117
|
const CC_HYPHEN_MINUS = "-".charCodeAt(0);
|
|
76
118
|
const CC_SEMICOLON = ";".charCodeAt(0);
|
|
77
119
|
const CC_TAB = "\t".charCodeAt(0);
|
|
@@ -103,22 +145,23 @@ const VIEW_TRANSITION_PART_PSEUDO =
|
|
|
103
145
|
/^view-transition-(?:group|image-pair|old|new)$/i;
|
|
104
146
|
const IS_MODULES = /\.modules?\.[^.]+$/i;
|
|
105
147
|
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
["eot", "application/vnd.ms-fontobject"]
|
|
113
|
-
]);
|
|
148
|
+
// Which formats get a preload hint is webpack's call; what each one *is* comes
|
|
149
|
+
// from `mime-db`, not a second copy of the mapping.
|
|
150
|
+
const FONT_EXTENSIONS = new Set(["woff2", "woff", "ttf", "otf", "eot"]);
|
|
151
|
+
|
|
152
|
+
// mime-db is heavy — only load it once a font src actually needs a `type`.
|
|
153
|
+
const getMimeTypes = memoize(() => require("../util/mimeTypes"));
|
|
114
154
|
|
|
115
155
|
/**
|
|
116
156
|
* @param {string} request font url (may carry a query/hash)
|
|
117
157
|
* @returns {string | undefined} preload `type` for a known font extension
|
|
118
158
|
*/
|
|
119
159
|
const fontMimeType = (request) => {
|
|
120
|
-
|
|
121
|
-
|
|
160
|
+
// Off the path only: `font?fallback=.woff2` names no font.
|
|
161
|
+
const resourcePath = parseResource(request).path;
|
|
162
|
+
const extension = path.extname(resourcePath).slice(1).toLowerCase();
|
|
163
|
+
if (!FONT_EXTENSIONS.has(extension)) return undefined;
|
|
164
|
+
return getMimeTypes().lookup(resourcePath);
|
|
122
165
|
};
|
|
123
166
|
|
|
124
167
|
// Skip options for a non-CSS-Modules parse: drop the selector prelude (never
|
|
@@ -167,37 +210,18 @@ const ONLY_WHITESPACE = /^\s+$/;
|
|
|
167
210
|
// Relative request prefix (`./` or `../`) — `isSelfReferenceRequest` per `from`.
|
|
168
211
|
const RELATIVE_REQUEST = /^\.{1,2}\//;
|
|
169
212
|
|
|
170
|
-
/**
|
|
171
|
-
* Returns matches.
|
|
172
|
-
* @param {RegExp} regexp a regexp
|
|
173
|
-
* @param {string} str a string
|
|
174
|
-
* @returns {RegExpExecArray[]} matches
|
|
175
|
-
*/
|
|
176
|
-
const matchAll = (regexp, str) => {
|
|
177
|
-
/** @type {RegExpExecArray[]} */
|
|
178
|
-
const result = [];
|
|
179
|
-
|
|
180
|
-
/** @type {null | RegExpExecArray} */
|
|
181
|
-
let match;
|
|
182
|
-
|
|
183
|
-
while ((match = regexp.exec(str)) !== null) {
|
|
184
|
-
result.push(match);
|
|
185
|
-
}
|
|
186
|
-
return result;
|
|
187
|
-
};
|
|
188
|
-
|
|
189
213
|
/**
|
|
190
214
|
* Range-keyed index over a known-properties table: ASCII-case-folded 31-hash
|
|
191
215
|
* of the name bytes → canonical key(s). Lets the Declaration visitor answer
|
|
192
216
|
* "is this a known property" (and get the canonical lowercase name) without
|
|
193
217
|
* slicing the property name out of the source per declaration.
|
|
194
|
-
* @type {WeakMap<Map<string,
|
|
218
|
+
* @type {WeakMap<Map<string, Map<string, number>>, Map<number, string | string[]>>}
|
|
195
219
|
*/
|
|
196
220
|
const KNOWN_PROPERTY_INDEX_CACHE = new WeakMap();
|
|
197
221
|
|
|
198
222
|
/**
|
|
199
223
|
* Gets (or builds) the hash index for a known-properties table.
|
|
200
|
-
* @param {Map<string,
|
|
224
|
+
* @param {Map<string, Map<string, number>>} knownProperties known properties table
|
|
201
225
|
* @returns {Map<number, string | string[]>} hash → canonical name(s)
|
|
202
226
|
*/
|
|
203
227
|
const getKnownPropertyIndex = (knownProperties) => {
|
|
@@ -231,6 +255,12 @@ const knownPropertyForRange = (index, input, start, end) => {
|
|
|
231
255
|
let h = end - start;
|
|
232
256
|
for (let i = start; i < end; i++) {
|
|
233
257
|
let c = input.charCodeAt(i);
|
|
258
|
+
// The table holds no raw-byte spelling, so re-read the unescaped one.
|
|
259
|
+
// Each pass shortens the name, so an escaped `\` cannot recurse forever.
|
|
260
|
+
if (c === CC_REVERSE_SOLIDUS) {
|
|
261
|
+
const name = unescapeIdentifier(input.slice(start, end));
|
|
262
|
+
return knownPropertyForRange(index, name, 0, name.length);
|
|
263
|
+
}
|
|
234
264
|
if (c >= 65 && c <= 90) c |= 0x20;
|
|
235
265
|
h = ((h << 5) - h + c) | 0;
|
|
236
266
|
}
|
|
@@ -245,291 +275,84 @@ const knownPropertyForRange = (index, input, start, end) => {
|
|
|
245
275
|
return undefined;
|
|
246
276
|
};
|
|
247
277
|
|
|
248
|
-
/**
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
"hiragana-iroha": 1,
|
|
288
|
-
katakana: 1,
|
|
289
|
-
/* cspell:disable-next-line */
|
|
290
|
-
"katakana-iroha": 1,
|
|
291
|
-
|
|
292
|
-
disc: 1,
|
|
293
|
-
circle: 1,
|
|
294
|
-
square: 1,
|
|
295
|
-
"disclosure-open": 1,
|
|
296
|
-
"disclosure-closed": 1,
|
|
297
|
-
|
|
298
|
-
"cjk-earthly-branch": 1,
|
|
299
|
-
"cjk-heavenly-stem": 1,
|
|
300
|
-
|
|
301
|
-
"japanese-informal": 1,
|
|
302
|
-
"japanese-formal": 1,
|
|
303
|
-
|
|
304
|
-
"korean-hangul-formal": 1,
|
|
305
|
-
/* cspell:disable-next-line */
|
|
306
|
-
"korean-hanja-informal": 1,
|
|
307
|
-
/* cspell:disable-next-line */
|
|
308
|
-
"korean-hanja-formal": 1,
|
|
309
|
-
|
|
310
|
-
"simp-chinese-informal": 1,
|
|
311
|
-
"simp-chinese-formal": 1,
|
|
312
|
-
"trad-chinese-informal": 1,
|
|
313
|
-
"trad-chinese-formal": 1,
|
|
314
|
-
"cjk-ideographic": 1,
|
|
315
|
-
|
|
316
|
-
"ethiopic-numeric": 1
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
/** @type {Record<string, number>} */
|
|
320
|
-
const GLOBAL_VALUES = {
|
|
321
|
-
// Global values
|
|
322
|
-
initial: Infinity,
|
|
323
|
-
inherit: Infinity,
|
|
324
|
-
unset: Infinity,
|
|
325
|
-
revert: Infinity,
|
|
326
|
-
"revert-layer": Infinity
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
/** @type {Record<string, number>} */
|
|
330
|
-
const GRID_AREA_OR_COLUMN_OR_ROW = {
|
|
331
|
-
auto: Infinity,
|
|
332
|
-
span: Infinity,
|
|
333
|
-
...GLOBAL_VALUES
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
/** @type {Record<string, number>} */
|
|
337
|
-
const GRID_AUTO_COLUMNS_OR_ROW = {
|
|
338
|
-
"min-content": Infinity,
|
|
339
|
-
"max-content": Infinity,
|
|
340
|
-
auto: Infinity,
|
|
341
|
-
...GLOBAL_VALUES
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
/** @type {Record<string, number>} */
|
|
345
|
-
const GRID_AUTO_FLOW = {
|
|
346
|
-
row: 1,
|
|
347
|
-
column: 1,
|
|
348
|
-
dense: 1,
|
|
349
|
-
...GLOBAL_VALUES
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
/** @type {Record<string, number>} */
|
|
353
|
-
const GRID_TEMPLATE_AREAS = {
|
|
354
|
-
// Special
|
|
355
|
-
none: 1,
|
|
356
|
-
...GLOBAL_VALUES
|
|
357
|
-
};
|
|
358
|
-
|
|
359
|
-
/** @type {Record<string, number>} */
|
|
360
|
-
const GRID_TEMPLATE_COLUMNS_OR_ROWS = {
|
|
361
|
-
none: 1,
|
|
362
|
-
subgrid: 1,
|
|
363
|
-
masonry: 1,
|
|
364
|
-
"max-content": Infinity,
|
|
365
|
-
"min-content": Infinity,
|
|
366
|
-
auto: Infinity,
|
|
367
|
-
...GLOBAL_VALUES
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
/** @type {Record<string, number>} */
|
|
371
|
-
const GRID_TEMPLATE = {
|
|
372
|
-
...GRID_TEMPLATE_AREAS,
|
|
373
|
-
...GRID_TEMPLATE_COLUMNS_OR_ROWS
|
|
374
|
-
};
|
|
375
|
-
|
|
376
|
-
/** @type {Record<string, number>} */
|
|
377
|
-
const GRID = {
|
|
378
|
-
"auto-flow": 1,
|
|
379
|
-
dense: 1,
|
|
380
|
-
...GRID_AUTO_COLUMNS_OR_ROW,
|
|
381
|
-
...GRID_AUTO_FLOW,
|
|
382
|
-
...GRID_TEMPLATE_AREAS,
|
|
383
|
-
...GRID_TEMPLATE_COLUMNS_OR_ROWS
|
|
278
|
+
/**
|
|
279
|
+
* Comma-separated index of the counter-name argument in a counter-reading function, or `-1` when the name isn't one. The name is matched over the raw byte range like the other function-name probes; only an escaped name (rare) pays the unescaped slice.
|
|
280
|
+
* @param {string} input source
|
|
281
|
+
* @param {number} start name start offset
|
|
282
|
+
* @param {number} end name end offset
|
|
283
|
+
* @param {string=} escapedName unescaped name, when the raw range carries an escape
|
|
284
|
+
* @returns {number} argument index of the counter name, or `-1`
|
|
285
|
+
*/
|
|
286
|
+
const counterFunctionNameIndex = (input, start, end, escapedName) => {
|
|
287
|
+
// The `target-counter(url, name, style?)` cross-reference forms (Generated Content for Paged Media) name the counter second; print engines read them.
|
|
288
|
+
if (escapedName !== undefined) {
|
|
289
|
+
if (
|
|
290
|
+
equalsLowerCase(escapedName, "counter") ||
|
|
291
|
+
equalsLowerCase(escapedName, "counters")
|
|
292
|
+
) {
|
|
293
|
+
return 0;
|
|
294
|
+
}
|
|
295
|
+
if (
|
|
296
|
+
equalsLowerCase(escapedName, "target-counter") ||
|
|
297
|
+
equalsLowerCase(escapedName, "target-counters")
|
|
298
|
+
) {
|
|
299
|
+
return 1;
|
|
300
|
+
}
|
|
301
|
+
return -1;
|
|
302
|
+
}
|
|
303
|
+
switch (end - start) {
|
|
304
|
+
case 7:
|
|
305
|
+
return rangeEqualsLowerCase(input, start, end, "counter") ? 0 : -1;
|
|
306
|
+
case 8:
|
|
307
|
+
return rangeEqualsLowerCase(input, start, end, "counters") ? 0 : -1;
|
|
308
|
+
case 14:
|
|
309
|
+
return rangeEqualsLowerCase(input, start, end, "target-counter") ? 1 : -1;
|
|
310
|
+
case 15:
|
|
311
|
+
return rangeEqualsLowerCase(input, start, end, "target-counters")
|
|
312
|
+
? 1
|
|
313
|
+
: -1;
|
|
314
|
+
default:
|
|
315
|
+
return -1;
|
|
316
|
+
}
|
|
384
317
|
};
|
|
385
318
|
|
|
386
319
|
/**
|
|
387
|
-
* Gets known
|
|
320
|
+
* Gets the known-properties table for the enabled scoping options: the
|
|
321
|
+
* properties a `css/module` reads a scoped name out of, each with the keywords
|
|
322
|
+
* of its own grammar (see `tooling/generate-css-data.js`).
|
|
388
323
|
* @param {{ animation?: boolean, container?: boolean, customIdents?: boolean, grid?: boolean }=} options options
|
|
389
|
-
* @returns {Map<string,
|
|
324
|
+
* @returns {Map<string, Map<string, number>>} list of known properties
|
|
390
325
|
*/
|
|
391
326
|
const buildKnownProperties = (options = {}) => {
|
|
392
|
-
/** @type {Map<string,
|
|
327
|
+
/** @type {Map<string, Map<string, number>>} */
|
|
393
328
|
const knownProperties = new Map();
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
infinite: 1,
|
|
408
|
-
// animation-play-state
|
|
409
|
-
paused: 1,
|
|
410
|
-
running: 1,
|
|
411
|
-
// animation-timing-function
|
|
412
|
-
ease: 1,
|
|
413
|
-
"ease-in": 1,
|
|
414
|
-
"ease-out": 1,
|
|
415
|
-
"ease-in-out": 1,
|
|
416
|
-
linear: 1,
|
|
417
|
-
"step-end": 1,
|
|
418
|
-
"step-start": 1,
|
|
419
|
-
// Special
|
|
420
|
-
none: Infinity, // No matter how many times you write none, it will never be an animation name
|
|
421
|
-
...GLOBAL_VALUES
|
|
422
|
-
});
|
|
423
|
-
knownProperties.set("animation-name", {
|
|
424
|
-
// Special
|
|
425
|
-
none: Infinity, // No matter how many times you write none, it will never be an animation name
|
|
426
|
-
...GLOBAL_VALUES
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
if (options.container) {
|
|
431
|
-
knownProperties.set("container", {
|
|
432
|
-
// container-type
|
|
433
|
-
normal: 1,
|
|
434
|
-
size: 1,
|
|
435
|
-
"inline-size": 1,
|
|
436
|
-
"scroll-state": 1,
|
|
437
|
-
// Special
|
|
438
|
-
none: Infinity,
|
|
439
|
-
...GLOBAL_VALUES
|
|
440
|
-
});
|
|
441
|
-
knownProperties.set("container-name", {
|
|
442
|
-
// Special
|
|
443
|
-
none: Infinity,
|
|
444
|
-
...GLOBAL_VALUES
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
if (options.customIdents) {
|
|
449
|
-
knownProperties.set("list-style", {
|
|
450
|
-
// list-style-position
|
|
451
|
-
inside: 1,
|
|
452
|
-
outside: 1,
|
|
453
|
-
// list-style-type
|
|
454
|
-
...PREDEFINED_COUNTER_STYLES,
|
|
455
|
-
// Special
|
|
456
|
-
none: Infinity,
|
|
457
|
-
...GLOBAL_VALUES
|
|
458
|
-
});
|
|
459
|
-
knownProperties.set("list-style-type", {
|
|
460
|
-
// list-style-type
|
|
461
|
-
...PREDEFINED_COUNTER_STYLES,
|
|
462
|
-
// Special
|
|
463
|
-
none: Infinity,
|
|
464
|
-
...GLOBAL_VALUES
|
|
465
|
-
});
|
|
466
|
-
knownProperties.set("system", {
|
|
467
|
-
cyclic: 1,
|
|
468
|
-
numeric: 1,
|
|
469
|
-
alphabetic: 1,
|
|
470
|
-
symbolic: 1,
|
|
471
|
-
additive: 1,
|
|
472
|
-
fixed: 1,
|
|
473
|
-
extends: 1,
|
|
474
|
-
...PREDEFINED_COUNTER_STYLES
|
|
475
|
-
});
|
|
476
|
-
knownProperties.set("fallback", {
|
|
477
|
-
...PREDEFINED_COUNTER_STYLES
|
|
478
|
-
});
|
|
479
|
-
knownProperties.set("speak-as", {
|
|
480
|
-
auto: 1,
|
|
481
|
-
bullets: 1,
|
|
482
|
-
numbers: 1,
|
|
483
|
-
words: 1,
|
|
484
|
-
"spell-out": 1,
|
|
485
|
-
...PREDEFINED_COUNTER_STYLES
|
|
486
|
-
});
|
|
487
|
-
knownProperties.set("view-transition-name", {
|
|
488
|
-
none: Infinity,
|
|
489
|
-
auto: Infinity,
|
|
490
|
-
"match-element": Infinity,
|
|
491
|
-
...GLOBAL_VALUES
|
|
492
|
-
});
|
|
493
|
-
knownProperties.set("view-transition-group", {
|
|
494
|
-
normal: Infinity,
|
|
495
|
-
contain: Infinity,
|
|
496
|
-
nearest: Infinity,
|
|
497
|
-
...GLOBAL_VALUES
|
|
498
|
-
});
|
|
499
|
-
knownProperties.set("view-transition-class", {
|
|
500
|
-
none: Infinity,
|
|
501
|
-
...GLOBAL_VALUES
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
if (options.grid) {
|
|
506
|
-
knownProperties.set("grid", GRID);
|
|
507
|
-
knownProperties.set("grid-area", GRID_AREA_OR_COLUMN_OR_ROW);
|
|
508
|
-
knownProperties.set("grid-column", GRID_AREA_OR_COLUMN_OR_ROW);
|
|
509
|
-
knownProperties.set("grid-column-end", GRID_AREA_OR_COLUMN_OR_ROW);
|
|
510
|
-
knownProperties.set("grid-column-start", GRID_AREA_OR_COLUMN_OR_ROW);
|
|
511
|
-
knownProperties.set("grid-row", GRID_AREA_OR_COLUMN_OR_ROW);
|
|
512
|
-
knownProperties.set("grid-row-end", GRID_AREA_OR_COLUMN_OR_ROW);
|
|
513
|
-
knownProperties.set("grid-row-start", GRID_AREA_OR_COLUMN_OR_ROW);
|
|
514
|
-
knownProperties.set("grid-template", GRID_TEMPLATE);
|
|
515
|
-
knownProperties.set("grid-template-areas", GRID_TEMPLATE_AREAS);
|
|
516
|
-
knownProperties.set("grid-template-columns", GRID_TEMPLATE_COLUMNS_OR_ROWS);
|
|
517
|
-
knownProperties.set("grid-template-rows", GRID_TEMPLATE_COLUMNS_OR_ROWS);
|
|
329
|
+
for (const [property, option] of CSS_MODULES_KEYWORD_OPTIONS) {
|
|
330
|
+
if (
|
|
331
|
+
options[
|
|
332
|
+
/** @type {"animation" | "container" | "customIdents" | "grid"} */
|
|
333
|
+
(option)
|
|
334
|
+
]
|
|
335
|
+
) {
|
|
336
|
+
knownProperties.set(
|
|
337
|
+
property,
|
|
338
|
+
/** @type {Map<string, number>} */
|
|
339
|
+
(CSS_MODULES_KEYWORDS.get(property))
|
|
340
|
+
);
|
|
341
|
+
}
|
|
518
342
|
}
|
|
519
|
-
|
|
520
343
|
return knownProperties;
|
|
521
344
|
};
|
|
522
345
|
|
|
523
|
-
/** @type {Map<number, Map<string,
|
|
346
|
+
/** @type {Map<number, Map<string, Map<string, number>>>} */
|
|
524
347
|
const KNOWN_PROPERTIES_CACHE = new Map();
|
|
525
348
|
|
|
526
349
|
/**
|
|
527
350
|
* Memoized {@link buildKnownProperties}: the table depends only on the four
|
|
528
|
-
* boolean options (≤16 combinations) and is read-only, while the same parser is
|
|
351
|
+
* boolean options (≤ 16 combinations) and is read-only, while the same parser is
|
|
529
352
|
* reused across modules — so build each combination once and share it instead
|
|
530
|
-
* of rebuilding the Map
|
|
353
|
+
* of rebuilding the Map per parsed module.
|
|
531
354
|
* @param {{ animation?: boolean, container?: boolean, customIdents?: boolean, grid?: boolean }=} options options
|
|
532
|
-
* @returns {Map<string,
|
|
355
|
+
* @returns {Map<string, Map<string, number>>} known properties table
|
|
533
356
|
*/
|
|
534
357
|
const getKnownProperties = (options = {}) => {
|
|
535
358
|
const key =
|
|
@@ -610,6 +433,60 @@ const rangeHasEscape = (input, start, end) => {
|
|
|
610
433
|
return false;
|
|
611
434
|
};
|
|
612
435
|
|
|
436
|
+
/**
|
|
437
|
+
* Whether a raw ident range names a custom property — `\2d\2d x` is `--x` too,
|
|
438
|
+
* so a name opening with a dash or a backslash pays the unescape.
|
|
439
|
+
* @param {string} input source
|
|
440
|
+
* @param {number} start ident start offset
|
|
441
|
+
* @param {number} end ident end offset (exclusive)
|
|
442
|
+
* @returns {boolean} true when the ident names a custom property
|
|
443
|
+
*/
|
|
444
|
+
const rangeIsDashedIdentifier = (input, start, end) => {
|
|
445
|
+
// `--x` is the shortest spelling; an escaped one is longer still.
|
|
446
|
+
if (end - start < 3) return false;
|
|
447
|
+
const first = input.charCodeAt(start);
|
|
448
|
+
if (first === CC_HYPHEN_MINUS) {
|
|
449
|
+
if (input.charCodeAt(start + 1) === CC_HYPHEN_MINUS) return true;
|
|
450
|
+
if (input.charCodeAt(start + 1) !== CC_REVERSE_SOLIDUS) return false;
|
|
451
|
+
} else if (first !== CC_REVERSE_SOLIDUS) {
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
return isDashedIdentifier(unescapeIdentifier(input.slice(start, end)));
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* The named cell tokens of a `grid-template-areas` string, in source offsets.
|
|
459
|
+
* A whitespace closing a hex escape does not separate; a `.` run names nothing.
|
|
460
|
+
* @param {string} input source
|
|
461
|
+
* @param {number} start content start offset (inside the quote)
|
|
462
|
+
* @param {number} end content end offset (exclusive)
|
|
463
|
+
* @returns {[number, number][]} one `[start, end]` per named cell
|
|
464
|
+
*/
|
|
465
|
+
const gridAreaNames = (input, start, end) => {
|
|
466
|
+
/** @type {[number, number][]} */
|
|
467
|
+
const names = [];
|
|
468
|
+
let i = start;
|
|
469
|
+
while (i < end) {
|
|
470
|
+
while (i < end && isWhitespace(input.charCodeAt(i))) i++;
|
|
471
|
+
if (i >= end) break;
|
|
472
|
+
const nameStart = i;
|
|
473
|
+
let nullCell = true;
|
|
474
|
+
while (i < end) {
|
|
475
|
+
const cc = input.charCodeAt(i);
|
|
476
|
+
if (isWhitespace(cc)) break;
|
|
477
|
+
if (cc === CC_REVERSE_SOLIDUS) {
|
|
478
|
+
i = Math.min(skipEscape(input, i), end);
|
|
479
|
+
nullCell = false;
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
if (cc !== CC_FULL_STOP) nullCell = false;
|
|
483
|
+
i++;
|
|
484
|
+
}
|
|
485
|
+
if (!nullCell) names.push([nameStart, i]);
|
|
486
|
+
}
|
|
487
|
+
return names;
|
|
488
|
+
};
|
|
489
|
+
|
|
613
490
|
/**
|
|
614
491
|
* @param {string} input source
|
|
615
492
|
* @param {number} pos position
|
|
@@ -903,10 +780,14 @@ class CssParser extends Parser {
|
|
|
903
780
|
const { line: el, column: ec } = locConverter.get(end);
|
|
904
781
|
|
|
905
782
|
state.current.addWarning(
|
|
906
|
-
new
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
783
|
+
new (getModuleDependencyWarning())(
|
|
784
|
+
state.module,
|
|
785
|
+
new WebpackError(message),
|
|
786
|
+
{
|
|
787
|
+
start: { line: sl, column: sc },
|
|
788
|
+
end: { line: el, column: ec }
|
|
789
|
+
}
|
|
790
|
+
)
|
|
910
791
|
);
|
|
911
792
|
}
|
|
912
793
|
|
|
@@ -931,6 +812,92 @@ class CssParser extends Parser {
|
|
|
931
812
|
state.module.addError(err);
|
|
932
813
|
}
|
|
933
814
|
|
|
815
|
+
/**
|
|
816
|
+
* Arbitrate cross-kind CSS-Modules export collisions collected during
|
|
817
|
+
* parsing. A class always wins the shared JS export key over the
|
|
818
|
+
* CSS-only kinds (`@keyframes`, `@counter-style`, `@container`, custom
|
|
819
|
+
* property, grid identifier) — matching css-loader / lightning css /
|
|
820
|
+
* postcss-modules; the loser's `EXPORT_MODE` is demoted to `NONE` so
|
|
821
|
+
* the CSS-side rewrite is preserved but the entry no longer contributes
|
|
822
|
+
* to `styles.<name>`. Other pairs (`class` ↔ `id`,
|
|
823
|
+
* `class` ↔ `:export`, `class` ↔ `@value`, kind-vs-kind without a
|
|
824
|
+
* class present, …) surface as a warning so the user resolves the name
|
|
825
|
+
* themselves. Same-kind redeclarations are silent.
|
|
826
|
+
* @param {ParserState} state parser state
|
|
827
|
+
* @param {Map<string, { kind: string, line: number, column: number, entries: number[] }[]>} declaredExports collected declarations grouped by (name, kind)
|
|
828
|
+
* @param {import("../dependencies/CssIcssExportDependency").CssExportEntry[]} cssExportEntries all export entries — losers are demoted in place
|
|
829
|
+
* @returns {void}
|
|
830
|
+
*/
|
|
831
|
+
_resolveAmbiguousExports(state, declaredExports, cssExportEntries) {
|
|
832
|
+
const NONE = CssIcssExportDependency.EXPORT_MODE.NONE;
|
|
833
|
+
for (const [name, decls] of declaredExports) {
|
|
834
|
+
if (decls.length <= 1) continue;
|
|
835
|
+
// Prefer `class` as the winner (matches css-loader / lightning css / postcss-modules); otherwise the first-declared kind wins de facto.
|
|
836
|
+
let winner;
|
|
837
|
+
for (const d of decls) {
|
|
838
|
+
if (d.kind === "class") {
|
|
839
|
+
winner = d;
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
const reference = winner !== undefined ? winner : decls[0];
|
|
844
|
+
for (const loser of decls) {
|
|
845
|
+
if (loser === reference) continue;
|
|
846
|
+
const anchor = cssExportEntries[loser.entries[0]];
|
|
847
|
+
if (
|
|
848
|
+
winner !== undefined &&
|
|
849
|
+
(loser.kind === "custom property" ||
|
|
850
|
+
loser.kind === "@keyframes" ||
|
|
851
|
+
loser.kind === "@counter-style" ||
|
|
852
|
+
loser.kind === "@container" ||
|
|
853
|
+
loser.kind === "grid identifier")
|
|
854
|
+
) {
|
|
855
|
+
for (const idx of loser.entries) {
|
|
856
|
+
cssExportEntries[idx].exportMode = NONE;
|
|
857
|
+
}
|
|
858
|
+
state.current.addWarning(
|
|
859
|
+
new (getModuleDependencyWarning())(
|
|
860
|
+
state.module,
|
|
861
|
+
new WebpackError(
|
|
862
|
+
`CSS module export "${name}" is shadowed by ${winner.kind} at line ${winner.line}:${winner.column}: the ${loser.kind} "${name}" is still scoped in the emitted CSS but is not accessible from the JavaScript export — rename one of them if both are needed`
|
|
863
|
+
),
|
|
864
|
+
{
|
|
865
|
+
start: {
|
|
866
|
+
line: anchor.locStartLine,
|
|
867
|
+
column: anchor.locStartColumn
|
|
868
|
+
},
|
|
869
|
+
end: {
|
|
870
|
+
line: anchor.locEndLine,
|
|
871
|
+
column: anchor.locEndColumn
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
)
|
|
875
|
+
);
|
|
876
|
+
} else {
|
|
877
|
+
// Other collision — warn without changing behavior.
|
|
878
|
+
state.current.addWarning(
|
|
879
|
+
new (getModuleDependencyWarning())(
|
|
880
|
+
state.module,
|
|
881
|
+
new WebpackError(
|
|
882
|
+
`Conflicting CSS module export "${name}": already declared as ${reference.kind} at line ${reference.line}:${reference.column}, redeclared as ${loser.kind}`
|
|
883
|
+
),
|
|
884
|
+
{
|
|
885
|
+
start: {
|
|
886
|
+
line: anchor.locStartLine,
|
|
887
|
+
column: anchor.locStartColumn
|
|
888
|
+
},
|
|
889
|
+
end: {
|
|
890
|
+
line: anchor.locEndLine,
|
|
891
|
+
column: anchor.locEndColumn
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
)
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
934
901
|
/**
|
|
935
902
|
* Parses the provided source and updates the parser state.
|
|
936
903
|
* @param {string | Buffer | PreparsedAst} source the source to parse
|
|
@@ -990,6 +957,43 @@ class CssParser extends Parser {
|
|
|
990
957
|
|
|
991
958
|
const module = state.module;
|
|
992
959
|
|
|
960
|
+
// Every CSS Modules export declaration is tracked here so `_resolveAmbiguousExports` can arbitrate cross-kind collisions in one pass at end-of-parse: a class silently wins over CSS-scoped kinds (`@keyframes`, `@counter-style`, `@container`, custom property, grid identifier) — matching css-loader / lightning css / postcss-modules — while other pairs (`class` ↔ `id`, `class` ↔ `:export`, `class` ↔ `@value`, …) surface as a warning so the user can resolve them.
|
|
961
|
+
/** @typedef {{ kind: string, line: number, column: number, entries: number[] }} DeclarationOfKind */
|
|
962
|
+
/** @type {Map<string, DeclarationOfKind[]>} */
|
|
963
|
+
const declaredExports = new Map();
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* Track a declaration site for later ambiguity resolution. Pointer
|
|
967
|
+
* into `cssExportEntries` is captured now because the entry is
|
|
968
|
+
* pushed immediately after by the calling `addCssExport(…)`.
|
|
969
|
+
* Property-value references (`animation: foo`) are not declarations
|
|
970
|
+
* and skip this hook.
|
|
971
|
+
* @param {string} name export name
|
|
972
|
+
* @param {string} kind human-readable declaration kind
|
|
973
|
+
* @param {number} line start line (1-based) of the declaration
|
|
974
|
+
* @param {number} column start column (0-based) of the declaration
|
|
975
|
+
* @returns {void}
|
|
976
|
+
*/
|
|
977
|
+
const recordDeclaration = (name, kind, line, column) => {
|
|
978
|
+
let decls = declaredExports.get(name);
|
|
979
|
+
if (decls === undefined) {
|
|
980
|
+
decls = [];
|
|
981
|
+
declaredExports.set(name, decls);
|
|
982
|
+
}
|
|
983
|
+
let d;
|
|
984
|
+
for (const existing of decls) {
|
|
985
|
+
if (existing.kind === kind) {
|
|
986
|
+
d = existing;
|
|
987
|
+
break;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
if (d === undefined) {
|
|
991
|
+
d = { kind, line, column, entries: [] };
|
|
992
|
+
decls.push(d);
|
|
993
|
+
}
|
|
994
|
+
d.entries.push(cssExportEntries.length);
|
|
995
|
+
};
|
|
996
|
+
|
|
993
997
|
// All `:export`-style exports are collected into a single
|
|
994
998
|
// `CssIcssExportDependency` per module (emitted at parse end) instead of one
|
|
995
999
|
// `Dependency` per export — far fewer retained objects on CSS-heavy builds.
|
|
@@ -1156,7 +1160,7 @@ class CssParser extends Parser {
|
|
|
1156
1160
|
if (errors) {
|
|
1157
1161
|
for (const e of errors) {
|
|
1158
1162
|
state.module.addWarning(
|
|
1159
|
-
new
|
|
1163
|
+
new (getCommentCompilationWarning())(
|
|
1160
1164
|
`Compilation error while processing magic comment(-s): /*${e.comment.value}*/: ${e.message}`,
|
|
1161
1165
|
rangeLoc(e.comment.range[0], e.comment.range[1])
|
|
1162
1166
|
)
|
|
@@ -1169,7 +1173,7 @@ class CssParser extends Parser {
|
|
|
1169
1173
|
// Loc is computed lazily here — it's only needed for this rare
|
|
1170
1174
|
// warning, not on every checked `url()` / `@import`.
|
|
1171
1175
|
state.module.addWarning(
|
|
1172
|
-
new
|
|
1176
|
+
new (getUnsupportedFeatureWarning())(
|
|
1173
1177
|
`\`webpackIgnore\` expected a boolean, but received: ${options.webpackIgnore}.`,
|
|
1174
1178
|
rangeLoc(warnStart, warnEnd)
|
|
1175
1179
|
)
|
|
@@ -1198,10 +1202,12 @@ class CssParser extends Parser {
|
|
|
1198
1202
|
this.options.customMedia && input.includes("@custom-media");
|
|
1199
1203
|
const mayHaveCustomSelectors =
|
|
1200
1204
|
this.options.customSelectors && input.includes("@custom-selector");
|
|
1201
|
-
/** @type {Map<string,
|
|
1205
|
+
/** @type {Map<string, CustomMediaDefinition> | undefined} */
|
|
1202
1206
|
let customMediaDefs;
|
|
1203
|
-
/** @type {
|
|
1204
|
-
let
|
|
1207
|
+
/** @type {Map<string, CustomMediaValue> | undefined} */
|
|
1208
|
+
let customMediaValues;
|
|
1209
|
+
/** @type {{ queries: MediaNode[], start: number, end: number, uses: CustomMediaUse[] }[] | undefined} */
|
|
1210
|
+
let customMediaQueries;
|
|
1205
1211
|
/** @type {Map<string, string> | undefined} */
|
|
1206
1212
|
let customSelectorDefs;
|
|
1207
1213
|
/** @type {{ name: string, start: number, end: number }[] | undefined} */
|
|
@@ -1525,6 +1531,7 @@ class CssParser extends Parser {
|
|
|
1525
1531
|
} else if (type === 1) {
|
|
1526
1532
|
const { line: sl, column: sc } = locConverter.get(start);
|
|
1527
1533
|
const { line: el, column: ec } = locConverter.get(end);
|
|
1534
|
+
recordDeclaration(name, ":export", sl, sc);
|
|
1528
1535
|
addCssExport(sl, sc, el, ec, name, getReexport(value));
|
|
1529
1536
|
}
|
|
1530
1537
|
};
|
|
@@ -1577,8 +1584,9 @@ class CssParser extends Parser {
|
|
|
1577
1584
|
* Process a `local(...)` / `global(...)` pseudo-function: strip the call (and a leading legacy `:`) via a presentational dep, then emit `local()`'s inner top-level idents as ICSS exports.
|
|
1578
1585
|
* @param {FunctionNode} fn parsed local/global function node
|
|
1579
1586
|
* @param {1 | 2} type 1 = local, 2 = global
|
|
1587
|
+
* @param {string=} declarationKind human-readable export kind to use for conflict tracking when the caller is a declaration site (selector or at-rule prelude). Undefined for property-value references, which are not tracked.
|
|
1580
1588
|
*/
|
|
1581
|
-
const processLocalOrGlobalFunction = (fn, type) => {
|
|
1589
|
+
const processLocalOrGlobalFunction = (fn, type, declarationKind) => {
|
|
1582
1590
|
// Replace `local(` / `global(` (and a leading `:` for the `:local(`/`:global(` selector form) with empty.
|
|
1583
1591
|
const fnStart = A.start(fn);
|
|
1584
1592
|
const isColon = input.charCodeAt(fnStart - 1) === CC_COLON;
|
|
@@ -1596,6 +1604,14 @@ class CssParser extends Parser {
|
|
|
1596
1604
|
const { line: el, column: ec } = locConverter.get(A.end(cv));
|
|
1597
1605
|
const isDashedIdent = isDashedIdentifier(identifier);
|
|
1598
1606
|
if (isDashedIdent) identifier = identifier.slice(2);
|
|
1607
|
+
if (declarationKind !== undefined) {
|
|
1608
|
+
recordDeclaration(
|
|
1609
|
+
identifier,
|
|
1610
|
+
isDashedIdent ? "custom property" : declarationKind,
|
|
1611
|
+
sl,
|
|
1612
|
+
sc
|
|
1613
|
+
);
|
|
1614
|
+
}
|
|
1599
1615
|
addCssExport(
|
|
1600
1616
|
sl,
|
|
1601
1617
|
sc,
|
|
@@ -1623,9 +1639,10 @@ class CssParser extends Parser {
|
|
|
1623
1639
|
* Localize the prelude name of `@keyframes` / `@counter-style` / `@container`: `options.string` takes the first string, `options.identifier` the first ident (a `RegExp` skips matching keywords), `:local()`/`:global()` count as found; top-level `var()`/`style()` dashed idents are always ICSS-processed.
|
|
1624
1640
|
* @param {AtRule} atRule parsed at-rule
|
|
1625
1641
|
* @param {{ string?: boolean, identifier?: boolean | RegExp }} options which prelude value kinds count as the local name
|
|
1642
|
+
* @param {string} kind human-readable export kind for the surrounding at-rule (`"@keyframes"`, `"@counter-style"`, `"@container"`)
|
|
1626
1643
|
* @returns {number} position after handling
|
|
1627
1644
|
*/
|
|
1628
|
-
const processLocalAtRule = (atRule, options) => {
|
|
1645
|
+
const processLocalAtRule = (atRule, options, kind) => {
|
|
1629
1646
|
let found = false;
|
|
1630
1647
|
for (const cv of A.prelude(atRule)) {
|
|
1631
1648
|
const cvType = A.type(cv);
|
|
@@ -1636,6 +1653,7 @@ class CssParser extends Parser {
|
|
|
1636
1653
|
const value = A.unescaped(cv);
|
|
1637
1654
|
const { line: sl, column: sc } = locConverter.get(A.start(cv));
|
|
1638
1655
|
const { line: el, column: ec } = locConverter.get(A.end(cv));
|
|
1656
|
+
recordDeclaration(value, kind, sl, sc);
|
|
1639
1657
|
addCssExport(
|
|
1640
1658
|
sl,
|
|
1641
1659
|
sc,
|
|
@@ -1664,6 +1682,7 @@ class CssParser extends Parser {
|
|
|
1664
1682
|
}
|
|
1665
1683
|
const { line: sl, column: sc } = locConverter.get(A.start(cv));
|
|
1666
1684
|
const { line: el, column: ec } = locConverter.get(A.end(cv));
|
|
1685
|
+
recordDeclaration(identifier, kind, sl, sc);
|
|
1667
1686
|
addCssExport(
|
|
1668
1687
|
sl,
|
|
1669
1688
|
sc,
|
|
@@ -1693,7 +1712,7 @@ class CssParser extends Parser {
|
|
|
1693
1712
|
if (!found && type) {
|
|
1694
1713
|
found = true;
|
|
1695
1714
|
if (type === 1) pure.markLocal();
|
|
1696
|
-
processLocalOrGlobalFunction(fn, type);
|
|
1715
|
+
processLocalOrGlobalFunction(fn, type, kind);
|
|
1697
1716
|
continue;
|
|
1698
1717
|
}
|
|
1699
1718
|
if (
|
|
@@ -1707,15 +1726,29 @@ class CssParser extends Parser {
|
|
|
1707
1726
|
}
|
|
1708
1727
|
return A.end(atRule);
|
|
1709
1728
|
};
|
|
1729
|
+
/**
|
|
1730
|
+
* The custom property's name, without its `--`. An escaped dash makes the
|
|
1731
|
+
* prefix longer than two bytes, so it comes off the unescaped value.
|
|
1732
|
+
* @param {number} identStart start of the `--<name>` ident
|
|
1733
|
+
* @param {number} identEnd end of the ident
|
|
1734
|
+
* @returns {string} the name after `--`
|
|
1735
|
+
*/
|
|
1736
|
+
const dashedIdentName = (identStart, identEnd) =>
|
|
1737
|
+
source.charCodeAt(identStart) === CC_HYPHEN_MINUS &&
|
|
1738
|
+
source.charCodeAt(identStart + 1) === CC_HYPHEN_MINUS
|
|
1739
|
+
? unescapeRange(identStart + 2, identEnd)
|
|
1740
|
+
: unescapeRange(identStart, identEnd).slice(2);
|
|
1741
|
+
|
|
1710
1742
|
/**
|
|
1711
1743
|
* Emit the ICSS export declaring this module exports the given custom property.
|
|
1712
1744
|
* @param {number} identStart start of the `--<name>` ident
|
|
1713
1745
|
* @param {number} identEnd end of the ident (exclusive)
|
|
1714
1746
|
*/
|
|
1715
1747
|
const emitDashedIdentExport = (identStart, identEnd) => {
|
|
1716
|
-
const identifier =
|
|
1748
|
+
const identifier = dashedIdentName(identStart, identEnd);
|
|
1717
1749
|
const { line: sl, column: sc } = locConverter.get(identStart);
|
|
1718
1750
|
const { line: el, column: ec } = locConverter.get(identEnd);
|
|
1751
|
+
recordDeclaration(identifier, "custom property", sl, sc);
|
|
1719
1752
|
addCssExport(
|
|
1720
1753
|
sl,
|
|
1721
1754
|
sc,
|
|
@@ -1745,7 +1778,7 @@ class CssParser extends Parser {
|
|
|
1745
1778
|
sourceEnd,
|
|
1746
1779
|
pathContent
|
|
1747
1780
|
) => {
|
|
1748
|
-
const identifier =
|
|
1781
|
+
const identifier = dashedIdentName(identStart, identEnd);
|
|
1749
1782
|
const { line: sl, column: sc } = locConverter.get(identStart);
|
|
1750
1783
|
const { line: el, column: ec } = locConverter.get(sourceEnd - 1);
|
|
1751
1784
|
const localName = nextIcssImportName();
|
|
@@ -1760,6 +1793,7 @@ class CssParser extends Parser {
|
|
|
1760
1793
|
importDep.setLoc(sl, sc, el, ec);
|
|
1761
1794
|
module.addDependency(importDep);
|
|
1762
1795
|
|
|
1796
|
+
recordDeclaration(identifier, "custom property", sl, sc);
|
|
1763
1797
|
addCssExport(
|
|
1764
1798
|
sl,
|
|
1765
1799
|
sc,
|
|
@@ -1812,16 +1846,7 @@ class CssParser extends Parser {
|
|
|
1812
1846
|
|
|
1813
1847
|
const identStart = A.start(identNode);
|
|
1814
1848
|
const identEnd = A.end(identNode);
|
|
1815
|
-
|
|
1816
|
-
// prefix of length >= 3 (escaped dashes don't match, same as the string
|
|
1817
|
-
// form, since the raw bytes aren't `--`).
|
|
1818
|
-
if (
|
|
1819
|
-
identEnd - identStart < 3 ||
|
|
1820
|
-
input.charCodeAt(identStart) !== CC_HYPHEN_MINUS ||
|
|
1821
|
-
input.charCodeAt(identStart + 1) !== CC_HYPHEN_MINUS
|
|
1822
|
-
) {
|
|
1823
|
-
return;
|
|
1824
|
-
}
|
|
1849
|
+
if (!rangeIsDashedIdentifier(input, identStart, identEnd)) return;
|
|
1825
1850
|
|
|
1826
1851
|
let j = identIdx + 1;
|
|
1827
1852
|
while (j < fv.length && A.type(fv[j]) === NodeType.Whitespace) {
|
|
@@ -1877,18 +1902,25 @@ class CssParser extends Parser {
|
|
|
1877
1902
|
active: false,
|
|
1878
1903
|
/** Should top-level dashed-ident exports be emitted at this nesting level? */
|
|
1879
1904
|
emit: false,
|
|
1880
|
-
/**
|
|
1905
|
+
/** Directly inside a `counter()`-family call whose arguments were already rewritten — suppresses the generic ICSS ident rewrite over the same ranges. */
|
|
1906
|
+
counterArgs: false,
|
|
1907
|
+
/** LIFO save/restore of `active` + `emit` + `counterArgs` across function nesting, bit-packed (bit 0 = active, bit 1 = emit, bit 2 = counterArgs) to avoid a per-function-token object allocation. */
|
|
1881
1908
|
/** @type {number[]} */
|
|
1882
1909
|
stack: [],
|
|
1883
1910
|
/** Push the current scope; call before descending into a `Function` body. */
|
|
1884
1911
|
push() {
|
|
1885
|
-
this.stack.push(
|
|
1912
|
+
this.stack.push(
|
|
1913
|
+
(this.active ? 1 : 0) |
|
|
1914
|
+
(this.emit ? 2 : 0) |
|
|
1915
|
+
(this.counterArgs ? 4 : 0)
|
|
1916
|
+
);
|
|
1886
1917
|
},
|
|
1887
1918
|
/** Pop the saved scope; call when leaving a `Function` body. */
|
|
1888
1919
|
pop() {
|
|
1889
1920
|
const s = /** @type {number} */ (this.stack.pop());
|
|
1890
1921
|
this.active = (s & 1) !== 0;
|
|
1891
1922
|
this.emit = (s & 2) !== 0;
|
|
1923
|
+
this.counterArgs = (s & 4) !== 0;
|
|
1892
1924
|
}
|
|
1893
1925
|
};
|
|
1894
1926
|
// Nearest enclosing declaration / at-rule / qualified-rule, set by each structural enter; the Url / Function / Ident / Comma visitors read it (via `urlActive` / `localGlobalActive` / `icssActive`) to decide value handling from the node hierarchy instead of carrying precomputed flags.
|
|
@@ -1902,10 +1934,12 @@ class CssParser extends Parser {
|
|
|
1902
1934
|
let currentDeclIsKnownProperty = false;
|
|
1903
1935
|
/** Whether the current `composes:` declaration owns the whole value (suppresses value rewrites). */
|
|
1904
1936
|
let currentDeclComposesSkip = false;
|
|
1937
|
+
/** Whether `counter()`-family arguments are scoped in the current declaration's value. */
|
|
1938
|
+
let currentDeclCounterActive = false;
|
|
1905
1939
|
|
|
1906
1940
|
/**
|
|
1907
1941
|
* Per-at-rule scope frames; `exit` reads `hasBlock` to pick the block-cleanup vs `suppressNextRulePrelude` branch.
|
|
1908
|
-
* @type {{ savedAnchor: boolean,
|
|
1942
|
+
* @type {{ savedAnchor: boolean, savedLocalIdentifierCount: number, name: string, hasBlock: boolean, endsWithSemicolon: boolean, fontPreloaded: boolean }[]}
|
|
1909
1943
|
*/
|
|
1910
1944
|
const atRuleStateStack = [];
|
|
1911
1945
|
|
|
@@ -2074,6 +2108,71 @@ class CssParser extends Parser {
|
|
|
2074
2108
|
}
|
|
2075
2109
|
};
|
|
2076
2110
|
|
|
2111
|
+
/**
|
|
2112
|
+
* Emit the ICSS export for one ident argument of a `counter()`-family call. Dashed names are left to the blanket dashed-ident scanner, and reserved names (UA counters, predefined counter styles, CSS-wide keywords) stay global.
|
|
2113
|
+
* @param {AstNode} node the ident node
|
|
2114
|
+
* @param {string} reservedFrom property whose keywords must not be localized here
|
|
2115
|
+
* @returns {void}
|
|
2116
|
+
*/
|
|
2117
|
+
const emitCounterIdent = (node, reservedFrom) => {
|
|
2118
|
+
const name = A.unescaped(node);
|
|
2119
|
+
if (isDashedIdentifier(name)) return;
|
|
2120
|
+
const reserved =
|
|
2121
|
+
/** @type {Map<string, number>} */
|
|
2122
|
+
(CSS_MODULES_KEYWORDS.get(reservedFrom));
|
|
2123
|
+
if (reserved.has(toLowerCaseIfNeeded(name))) return;
|
|
2124
|
+
const start = A.start(node);
|
|
2125
|
+
const end = A.end(node);
|
|
2126
|
+
const { line: sl, column: sc } = locConverter.get(start);
|
|
2127
|
+
const { line: el, column: ec } = locConverter.get(end);
|
|
2128
|
+
addCssExport(
|
|
2129
|
+
sl,
|
|
2130
|
+
sc,
|
|
2131
|
+
el,
|
|
2132
|
+
ec,
|
|
2133
|
+
name,
|
|
2134
|
+
getReexport(name),
|
|
2135
|
+
[start, end],
|
|
2136
|
+
true,
|
|
2137
|
+
CssIcssExportDependency.EXPORT_MODE.ONCE
|
|
2138
|
+
);
|
|
2139
|
+
};
|
|
2140
|
+
|
|
2141
|
+
/**
|
|
2142
|
+
* Scope a `counter()` / `counters()` / `target-counter()` / `target-counters()` call: the counter-name argument localizes like a `counter-reset` value and a trailing `<counter-style>` ident like a `list-style-type` value, so both keep naming the scoped `counter-*` declaration / `@counter-style` rule.
|
|
2143
|
+
* @param {AstNode[]} cvs the call's argument component values
|
|
2144
|
+
* @param {number} nameIndex comma-separated index of the counter-name argument
|
|
2145
|
+
* @returns {void}
|
|
2146
|
+
*/
|
|
2147
|
+
const walkCounterFunction = (cvs, nameIndex) => {
|
|
2148
|
+
let group = 0;
|
|
2149
|
+
let groupNodes = 0;
|
|
2150
|
+
/** Sole ident of the current argument, or undefined when the argument isn't a lone ident. */
|
|
2151
|
+
let lastIdent;
|
|
2152
|
+
for (const cv of cvs) {
|
|
2153
|
+
const type = A.type(cv);
|
|
2154
|
+
if (type === NodeType.Whitespace) continue;
|
|
2155
|
+
if (type === NodeType.Comma) {
|
|
2156
|
+
group++;
|
|
2157
|
+
groupNodes = 0;
|
|
2158
|
+
lastIdent = undefined;
|
|
2159
|
+
continue;
|
|
2160
|
+
}
|
|
2161
|
+
groupNodes++;
|
|
2162
|
+
const loneIdent = groupNodes === 1 && type === NodeType.Ident;
|
|
2163
|
+
if (group === nameIndex) {
|
|
2164
|
+
if (loneIdent) emitCounterIdent(cv, "counter-reset");
|
|
2165
|
+
lastIdent = undefined;
|
|
2166
|
+
} else {
|
|
2167
|
+
lastIdent = loneIdent ? cv : undefined;
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
// The counter style is the last argument when it's a lone ident (`counter(n, style)` / `counters(n, sep, style)`).
|
|
2171
|
+
if (lastIdent !== undefined && group > nameIndex) {
|
|
2172
|
+
emitCounterIdent(lastIdent, "list-style-type");
|
|
2173
|
+
}
|
|
2174
|
+
};
|
|
2175
|
+
|
|
2077
2176
|
/**
|
|
2078
2177
|
* Walk component values as a selector list, emitting ID / attribute deps and recursing into `:not()`/`:is()`/`:local()`/`:global()` wrappers; `localMode` is the sub-tree mode and `topLevel` controls whether commas reset it (only outside parentheses).
|
|
2079
2178
|
* @param {AstNode[]} values component values to walk
|
|
@@ -2182,6 +2281,7 @@ class CssParser extends Parser {
|
|
|
2182
2281
|
const idName = A.unescaped(v);
|
|
2183
2282
|
const { line: idSl, column: idSc } = locConverter.get(A.start(v));
|
|
2184
2283
|
const { line: idEl, column: idEc } = locConverter.get(A.end(v));
|
|
2284
|
+
recordDeclaration(idName, "id", idSl, idSc);
|
|
2185
2285
|
addCssExport(
|
|
2186
2286
|
idSl,
|
|
2187
2287
|
idSc,
|
|
@@ -2224,6 +2324,7 @@ class CssParser extends Parser {
|
|
|
2224
2324
|
// Cursor reads instead of `A.loc` — this is the hottest export site.
|
|
2225
2325
|
const { line: sl, column: sc } = locConverter.get(A.start(next));
|
|
2226
2326
|
const { line: el, column: ec } = locConverter.get(A.end(next));
|
|
2327
|
+
recordDeclaration(name, "class", sl, sc);
|
|
2227
2328
|
addCssExport(
|
|
2228
2329
|
sl,
|
|
2229
2330
|
sc,
|
|
@@ -2267,18 +2368,20 @@ class CssParser extends Parser {
|
|
|
2267
2368
|
};
|
|
2268
2369
|
/**
|
|
2269
2370
|
* Per-qualified-rule scope frames; `{ bailed: true }` for inline-handled `:import` / `:export` pseudo-rules.
|
|
2270
|
-
* @type {({ bailed: true } | { bailed: false, savedAnchor: boolean,
|
|
2371
|
+
* @type {({ bailed: true } | { bailed: false, savedAnchor: boolean, savedLocalIdentifierCount: number, savedPrevComposesFile: string | undefined, savedComposesFiles: Set<string> | null })[]}
|
|
2271
2372
|
*/
|
|
2272
2373
|
const qualifiedRuleStateStack = [];
|
|
2273
2374
|
|
|
2274
2375
|
/**
|
|
2275
|
-
* Whether url() deps are emitted here (from `currentStructural`):
|
|
2376
|
+
* Whether url() deps are emitted here (from `currentStructural`): off in an `@import`
|
|
2377
|
+
* prelude (the import target, unless recovering) and in `@namespace` (an opaque identifier).
|
|
2276
2378
|
* @returns {boolean} true when url() deps should be emitted
|
|
2277
2379
|
*/
|
|
2278
2380
|
const urlActive = () => {
|
|
2279
2381
|
if (!this.options.url || !currentStructural) return false;
|
|
2280
2382
|
if (A.type(currentStructural) === NodeType.AtRule) {
|
|
2281
2383
|
// `currentAtRuleName` is cached on at-rule enter — no per-value slice.
|
|
2384
|
+
if (currentAtRuleName === "@namespace") return false;
|
|
2282
2385
|
return currentAtRuleName !== "@import" || currentUrlRecovery;
|
|
2283
2386
|
}
|
|
2284
2387
|
return true;
|
|
@@ -3007,6 +3110,7 @@ class CssParser extends Parser {
|
|
|
3007
3110
|
{
|
|
3008
3111
|
const { line: sl, column: sc } = locConverter.get(start);
|
|
3009
3112
|
const { line: el, column: ec } = locConverter.get(nameEnd);
|
|
3113
|
+
recordDeclaration(localName, "@value", sl, sc);
|
|
3010
3114
|
addCssExport(
|
|
3011
3115
|
sl,
|
|
3012
3116
|
sc,
|
|
@@ -3048,10 +3152,12 @@ class CssParser extends Parser {
|
|
|
3048
3152
|
|
|
3049
3153
|
icssDefinitions.set(localName, def);
|
|
3050
3154
|
|
|
3155
|
+
recordDeclaration(localName, "@value", sl, sc);
|
|
3051
3156
|
addCssExport(sl, sc, el, ec, localName, getReexport(value));
|
|
3052
3157
|
} else {
|
|
3053
3158
|
icssDefinitions.set(localName, { value });
|
|
3054
3159
|
|
|
3160
|
+
recordDeclaration(localName, "@value", sl, sc);
|
|
3055
3161
|
addCssExport(sl, sc, el, ec, localName, value);
|
|
3056
3162
|
}
|
|
3057
3163
|
}
|
|
@@ -3084,7 +3190,10 @@ class CssParser extends Parser {
|
|
|
3084
3190
|
};
|
|
3085
3191
|
|
|
3086
3192
|
/**
|
|
3087
|
-
* Collect one `@custom-media --name <value>` definition (last-wins) and drop
|
|
3193
|
+
* Collect one `@custom-media --name <value>` definition (last-wins) and drop
|
|
3194
|
+
* the rule. A value naming another custom media is kept as an `alias` — the
|
|
3195
|
+
* name it points at may be defined further down the file, and node ids are
|
|
3196
|
+
* recycled per top-level rule, so nothing AST-shaped can outlive the walk.
|
|
3088
3197
|
* @param {AtRule} at the `@custom-media` at-rule
|
|
3089
3198
|
*/
|
|
3090
3199
|
const collectCustomMedia = (at) => {
|
|
@@ -3105,27 +3214,27 @@ class CssParser extends Parser {
|
|
|
3105
3214
|
if (!isDashedIdentifier(name)) return;
|
|
3106
3215
|
i++;
|
|
3107
3216
|
|
|
3108
|
-
/**
|
|
3109
|
-
* @param {string} text resolved text
|
|
3110
|
-
* @param {"condition" | "type" | "unsupported"} kind value kind
|
|
3111
|
-
*/
|
|
3112
|
-
const store = (text, kind) => {
|
|
3113
|
-
(customMediaDefs || (customMediaDefs = new Map())).set(name, {
|
|
3114
|
-
text,
|
|
3115
|
-
kind
|
|
3116
|
-
});
|
|
3117
|
-
};
|
|
3118
|
-
const extra = { hasExtra: false };
|
|
3119
|
-
|
|
3120
3217
|
// Value span after the name, trimmed.
|
|
3121
3218
|
let vs = i;
|
|
3122
3219
|
let ve = prelude.length;
|
|
3123
3220
|
while (vs < ve && A.type(prelude[vs]) === NodeType.Whitespace) vs++;
|
|
3124
3221
|
while (ve > vs && A.type(prelude[ve - 1]) === NodeType.Whitespace) ve--;
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3222
|
+
(customMediaDefs || (customMediaDefs = new Map())).set(
|
|
3223
|
+
name,
|
|
3224
|
+
classifyCustomMedia(prelude, vs, ve)
|
|
3225
|
+
);
|
|
3226
|
+
};
|
|
3227
|
+
|
|
3228
|
+
/**
|
|
3229
|
+
* Classify one `@custom-media` value against the live AST.
|
|
3230
|
+
* @param {readonly AstNode[]} prelude the defining at-rule's prelude
|
|
3231
|
+
* @param {number} vs first value token
|
|
3232
|
+
* @param {number} ve one past the last value token
|
|
3233
|
+
* @returns {CustomMediaDefinition} what the value is, aliases unresolved
|
|
3234
|
+
*/
|
|
3235
|
+
const classifyCustomMedia = (prelude, vs, ve) => {
|
|
3236
|
+
if (vs >= ve) return CUSTOM_MEDIA_UNSUPPORTED;
|
|
3237
|
+
const extra = { hasExtra: false };
|
|
3129
3238
|
|
|
3130
3239
|
let hasComma = false;
|
|
3131
3240
|
for (let k = vs; k < ve; k++) {
|
|
@@ -3138,46 +3247,52 @@ class CssParser extends Parser {
|
|
|
3138
3247
|
if (!hasComma) {
|
|
3139
3248
|
const first = prelude[vs];
|
|
3140
3249
|
const valueText = input.slice(A.start(first), A.end(prelude[ve - 1]));
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
const nested =
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3250
|
+
// A `(--x)` standing alone is this value spelled as another name.
|
|
3251
|
+
if (ve - vs === 1 && A.type(first) === NodeType.SimpleBlock) {
|
|
3252
|
+
const nested = loneDashedIdentOfBlock(
|
|
3253
|
+
/** @type {SimpleBlock} */ (first),
|
|
3254
|
+
extra
|
|
3255
|
+
);
|
|
3256
|
+
if (nested !== undefined && !extra.hasExtra) {
|
|
3257
|
+
return { kind: "alias", name: nested };
|
|
3258
|
+
}
|
|
3150
3259
|
}
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3260
|
+
// A reference anywhere else in the value has no resolution step of its
|
|
3261
|
+
// own — only a `@media` prelude's uses are scanned — so writing this
|
|
3262
|
+
// value out would emit the reference unresolved.
|
|
3263
|
+
if (hasCustomMediaRef(prelude, vs, ve)) return CUSTOM_MEDIA_UNSUPPORTED;
|
|
3264
|
+
if (A.type(first) === NodeType.SimpleBlock) {
|
|
3265
|
+
return { kind: "condition", text: valueText };
|
|
3154
3266
|
}
|
|
3155
|
-
if (
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
) {
|
|
3159
|
-
|
|
3160
|
-
|
|
3267
|
+
if (A.type(first) !== NodeType.Ident) return CUSTOM_MEDIA_UNSUPPORTED;
|
|
3268
|
+
const s = A.start(first);
|
|
3269
|
+
const e = A.end(first);
|
|
3270
|
+
if (ve - vs === 1) {
|
|
3271
|
+
if (rangeEqualsLowerCase(input, s, e, "true")) {
|
|
3272
|
+
return CUSTOM_MEDIA_TRUE;
|
|
3273
|
+
}
|
|
3274
|
+
if (rangeEqualsLowerCase(input, s, e, "false")) {
|
|
3275
|
+
return CUSTOM_MEDIA_FALSE;
|
|
3276
|
+
}
|
|
3161
3277
|
}
|
|
3162
|
-
if (rangeEqualsLowerCase(input,
|
|
3163
|
-
// `not (…)` is a media condition (wrap so it stays a media-in-parens);
|
|
3278
|
+
if (rangeEqualsLowerCase(input, s, e, "not")) {
|
|
3279
|
+
// `not (…)` is a media condition (wrap so it stays a media-in-parens);
|
|
3280
|
+
// `not <type>` is a media type.
|
|
3164
3281
|
let j = vs + 1;
|
|
3165
3282
|
while (j < ve && A.type(prelude[j]) === NodeType.Whitespace) j++;
|
|
3166
3283
|
if (j < ve && A.type(prelude[j]) === NodeType.SimpleBlock) {
|
|
3167
|
-
|
|
3168
|
-
} else {
|
|
3169
|
-
store(valueText, "type");
|
|
3284
|
+
return { kind: "condition", text: `(${valueText})` };
|
|
3170
3285
|
}
|
|
3171
|
-
return;
|
|
3286
|
+
return { kind: "type", text: valueText };
|
|
3172
3287
|
}
|
|
3173
3288
|
// `screen`, `only screen`, `screen and (…)`, …
|
|
3174
|
-
|
|
3175
|
-
return;
|
|
3289
|
+
return { kind: "type", text: valueText };
|
|
3176
3290
|
}
|
|
3177
3291
|
|
|
3178
|
-
// Comma list → `(seg1 or seg2 …)`; supported only when every segment is a
|
|
3179
|
-
|
|
3180
|
-
|
|
3292
|
+
// Comma list → `(seg1 or seg2 …)`; supported only when every segment is a
|
|
3293
|
+
// media-in-parens (or a name standing for one).
|
|
3294
|
+
/** @type {({ text: string } | { alias: string })[]} */
|
|
3295
|
+
const parts = [];
|
|
3181
3296
|
let ok = true;
|
|
3182
3297
|
/** @type {AstNode[]} */
|
|
3183
3298
|
let seg = [];
|
|
@@ -3192,21 +3307,25 @@ class CssParser extends Parser {
|
|
|
3192
3307
|
}
|
|
3193
3308
|
const f = seg[a];
|
|
3194
3309
|
const text = input.slice(A.start(f), A.end(seg[b - 1]));
|
|
3310
|
+
if (b - a === 1 && A.type(f) === NodeType.SimpleBlock) {
|
|
3311
|
+
const nested = loneDashedIdentOfBlock(
|
|
3312
|
+
/** @type {SimpleBlock} */ (f),
|
|
3313
|
+
extra
|
|
3314
|
+
);
|
|
3315
|
+
if (extra.hasExtra) ok = false;
|
|
3316
|
+
else if (nested === undefined) parts.push({ text });
|
|
3317
|
+
else parts.push({ alias: nested });
|
|
3318
|
+
return;
|
|
3319
|
+
}
|
|
3195
3320
|
if (
|
|
3196
|
-
b - a === 1 &&
|
|
3197
|
-
A.type(f) === NodeType.SimpleBlock &&
|
|
3198
|
-
loneDashedIdentOfBlock(/** @type {SimpleBlock} */ (f), extra) ===
|
|
3199
|
-
undefined
|
|
3200
|
-
) {
|
|
3201
|
-
segments.push(text);
|
|
3202
|
-
} else if (
|
|
3203
3321
|
A.type(f) === NodeType.Ident &&
|
|
3204
|
-
rangeEqualsLowerCase(input, A.start(f), A.end(f), "not")
|
|
3322
|
+
rangeEqualsLowerCase(input, A.start(f), A.end(f), "not") &&
|
|
3323
|
+
!hasCustomMediaRef(seg, a, b)
|
|
3205
3324
|
) {
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
ok = false;
|
|
3325
|
+
parts.push({ text: `(${text})` });
|
|
3326
|
+
return;
|
|
3209
3327
|
}
|
|
3328
|
+
ok = false;
|
|
3210
3329
|
};
|
|
3211
3330
|
for (let k = vs; k < ve; k++) {
|
|
3212
3331
|
if (A.type(prelude[k]) === NodeType.Comma) {
|
|
@@ -3217,54 +3336,386 @@ class CssParser extends Parser {
|
|
|
3217
3336
|
}
|
|
3218
3337
|
}
|
|
3219
3338
|
flush();
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3339
|
+
return ok ? { kind: "or", parts } : CUSTOM_MEDIA_UNSUPPORTED;
|
|
3340
|
+
};
|
|
3341
|
+
|
|
3342
|
+
/**
|
|
3343
|
+
* What a `@custom-media` name resolves to, memoized. An undefined name and a
|
|
3344
|
+
* definition cycle both resolve to unsupported (the use site warns).
|
|
3345
|
+
* @param {string} name the dashed ident
|
|
3346
|
+
* @param {Set<string>} resolving names currently being resolved
|
|
3347
|
+
* @returns {CustomMediaValue} what the name resolves to
|
|
3348
|
+
*/
|
|
3349
|
+
const resolveCustomMediaValue = (name, resolving) => {
|
|
3350
|
+
const cached = customMediaValues && customMediaValues.get(name);
|
|
3351
|
+
if (cached !== undefined) return cached;
|
|
3352
|
+
const def = customMediaDefs && customMediaDefs.get(name);
|
|
3353
|
+
if (def === undefined || resolving.has(name)) {
|
|
3354
|
+
return CUSTOM_MEDIA_UNSUPPORTED;
|
|
3355
|
+
}
|
|
3356
|
+
resolving.add(name);
|
|
3357
|
+
/** @type {CustomMediaValue} */
|
|
3358
|
+
let value;
|
|
3359
|
+
if (def.kind === "alias") {
|
|
3360
|
+
const inner = resolveCustomMediaValue(def.name, resolving);
|
|
3361
|
+
// A media type cannot sit in parens, so a name standing for one is no value.
|
|
3362
|
+
value = inner.kind === "type" ? CUSTOM_MEDIA_UNSUPPORTED : inner;
|
|
3363
|
+
} else if (def.kind === "or") {
|
|
3364
|
+
/** @type {string[]} */
|
|
3365
|
+
const texts = [];
|
|
3366
|
+
let ok = true;
|
|
3367
|
+
let anyTrue = false;
|
|
3368
|
+
for (const part of def.parts) {
|
|
3369
|
+
if (!("alias" in part)) {
|
|
3370
|
+
texts.push(part.text);
|
|
3371
|
+
continue;
|
|
3372
|
+
}
|
|
3373
|
+
const inner = resolveCustomMediaValue(part.alias, resolving);
|
|
3374
|
+
// A media query list is an `or`, so a constant segment drops out of it.
|
|
3375
|
+
if (inner.kind === "boolean") anyTrue = anyTrue || inner.value;
|
|
3376
|
+
else if (inner.kind === "condition") texts.push(inner.text);
|
|
3377
|
+
else ok = false;
|
|
3378
|
+
}
|
|
3379
|
+
value = !ok
|
|
3380
|
+
? CUSTOM_MEDIA_UNSUPPORTED
|
|
3381
|
+
: anyTrue
|
|
3382
|
+
? CUSTOM_MEDIA_TRUE
|
|
3383
|
+
: texts.length === 0
|
|
3384
|
+
? CUSTOM_MEDIA_FALSE
|
|
3385
|
+
: {
|
|
3386
|
+
kind: "condition",
|
|
3387
|
+
text:
|
|
3388
|
+
texts.length === 1 ? texts[0] : `(${texts.join(" or ")})`
|
|
3389
|
+
};
|
|
3225
3390
|
} else {
|
|
3226
|
-
|
|
3391
|
+
value = def;
|
|
3227
3392
|
}
|
|
3393
|
+
resolving.delete(name);
|
|
3394
|
+
(customMediaValues || (customMediaValues = new Map())).set(name, value);
|
|
3395
|
+
return value;
|
|
3228
3396
|
};
|
|
3229
3397
|
|
|
3230
3398
|
/**
|
|
3231
|
-
*
|
|
3232
|
-
*
|
|
3233
|
-
* @param {
|
|
3399
|
+
* Whether a node is the media keyword `word` (media queries are ASCII
|
|
3400
|
+
* case-insensitive).
|
|
3401
|
+
* @param {AstNode} node candidate node
|
|
3402
|
+
* @param {string} word lower-case keyword
|
|
3403
|
+
* @returns {boolean} true on a match
|
|
3234
3404
|
*/
|
|
3235
|
-
const
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3405
|
+
const isMediaKeyword = (node, word) =>
|
|
3406
|
+
A.type(node) === NodeType.Ident &&
|
|
3407
|
+
rangeEqualsLowerCase(input, A.start(node), A.end(node), word);
|
|
3408
|
+
|
|
3409
|
+
/**
|
|
3410
|
+
* First significant index in `tokens[from…to)`.
|
|
3411
|
+
* @param {readonly AstNode[]} tokens token list
|
|
3412
|
+
* @param {number} from first index
|
|
3413
|
+
* @param {number} to one past the last index
|
|
3414
|
+
* @returns {number} the trimmed start
|
|
3415
|
+
*/
|
|
3416
|
+
const mediaTrimStart = (tokens, from, to) => {
|
|
3417
|
+
let a = from;
|
|
3418
|
+
while (a < to && A.type(tokens[a]) === NodeType.Whitespace) a++;
|
|
3419
|
+
return a;
|
|
3420
|
+
};
|
|
3421
|
+
|
|
3422
|
+
/**
|
|
3423
|
+
* One past the last significant index in `tokens[from…to)`.
|
|
3424
|
+
* @param {readonly AstNode[]} tokens token list
|
|
3425
|
+
* @param {number} from first index
|
|
3426
|
+
* @param {number} to one past the last index
|
|
3427
|
+
* @returns {number} the trimmed end
|
|
3428
|
+
*/
|
|
3429
|
+
const mediaTrimEnd = (tokens, from, to) => {
|
|
3430
|
+
let b = to;
|
|
3431
|
+
while (b > from && A.type(tokens[b - 1]) === NodeType.Whitespace) b--;
|
|
3432
|
+
return b;
|
|
3433
|
+
};
|
|
3434
|
+
|
|
3435
|
+
/**
|
|
3436
|
+
* The source text spanned by `tokens[from…to)`.
|
|
3437
|
+
* @param {readonly AstNode[]} tokens token list
|
|
3438
|
+
* @param {number} from first index
|
|
3439
|
+
* @param {number} to one past the last index
|
|
3440
|
+
* @returns {string} the source slice
|
|
3441
|
+
*/
|
|
3442
|
+
const mediaText = (tokens, from, to) =>
|
|
3443
|
+
input.slice(A.start(tokens[from]), A.end(tokens[to - 1]));
|
|
3444
|
+
|
|
3445
|
+
// One flag object for the whole parse: `loneDashedIdentOfBlock` writes it and
|
|
3446
|
+
// every caller reads it back before the next call.
|
|
3447
|
+
const mediaExtra = { hasExtra: false };
|
|
3448
|
+
|
|
3449
|
+
/**
|
|
3450
|
+
* Whether any `(--name)` reference is reachable inside `node`. `childAt` walks
|
|
3451
|
+
* the children without materializing the list.
|
|
3452
|
+
* @param {AstNode} node a block or function node
|
|
3453
|
+
* @returns {boolean} true when a reference is present
|
|
3454
|
+
*/
|
|
3455
|
+
const hasCustomMediaRefIn = (node) => {
|
|
3456
|
+
const count = A.childCount(node);
|
|
3457
|
+
for (let k = 0; k < count; k++) {
|
|
3458
|
+
const child = A.childAt(node, k);
|
|
3459
|
+
const type = A.type(child);
|
|
3460
|
+
if (type !== NodeType.SimpleBlock && type !== NodeType.Function) {
|
|
3243
3461
|
continue;
|
|
3244
3462
|
}
|
|
3245
|
-
if (
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3463
|
+
if (
|
|
3464
|
+
type === NodeType.SimpleBlock &&
|
|
3465
|
+
loneDashedIdentOfBlock(
|
|
3466
|
+
/** @type {SimpleBlock} */ (child),
|
|
3467
|
+
mediaExtra
|
|
3468
|
+
) !== undefined
|
|
3469
|
+
) {
|
|
3470
|
+
return true;
|
|
3471
|
+
}
|
|
3472
|
+
if (hasCustomMediaRefIn(child)) return true;
|
|
3473
|
+
}
|
|
3474
|
+
return false;
|
|
3475
|
+
};
|
|
3476
|
+
|
|
3477
|
+
/**
|
|
3478
|
+
* Whether any `(--name)` reference is reachable in `tokens[from…to)`. Cheap
|
|
3479
|
+
* enough to run over every `@media` prelude so one without a reference builds
|
|
3480
|
+
* no tree at all.
|
|
3481
|
+
* @param {readonly AstNode[]} tokens token list
|
|
3482
|
+
* @param {number} from first index
|
|
3483
|
+
* @param {number} to one past the last index
|
|
3484
|
+
* @returns {boolean} true when a reference is present
|
|
3485
|
+
*/
|
|
3486
|
+
const hasCustomMediaRef = (tokens, from, to) => {
|
|
3487
|
+
for (let i = from; i < to; i++) {
|
|
3488
|
+
const node = tokens[i];
|
|
3489
|
+
const type = A.type(node);
|
|
3490
|
+
if (type !== NodeType.SimpleBlock && type !== NodeType.Function) {
|
|
3491
|
+
continue;
|
|
3492
|
+
}
|
|
3493
|
+
if (
|
|
3494
|
+
type === NodeType.SimpleBlock &&
|
|
3495
|
+
loneDashedIdentOfBlock(
|
|
3496
|
+
/** @type {SimpleBlock} */ (node),
|
|
3497
|
+
mediaExtra
|
|
3498
|
+
) !== undefined
|
|
3499
|
+
) {
|
|
3500
|
+
return true;
|
|
3501
|
+
}
|
|
3502
|
+
if (hasCustomMediaRefIn(node)) return true;
|
|
3503
|
+
}
|
|
3504
|
+
return false;
|
|
3505
|
+
};
|
|
3506
|
+
|
|
3507
|
+
/**
|
|
3508
|
+
* Capture one `<media-in-parens>` — a reference to a custom media name, a
|
|
3509
|
+
* parenthesised sub-condition, or an opaque feature test.
|
|
3510
|
+
* @param {readonly AstNode[]} tokens token list
|
|
3511
|
+
* @param {number} from first index
|
|
3512
|
+
* @param {number} to one past the last index
|
|
3513
|
+
* @param {boolean} leading whether the term starts a top-level query
|
|
3514
|
+
* @param {CustomMediaUse[]} uses the prelude's use list, appended to
|
|
3515
|
+
* @returns {MediaNode} the captured term
|
|
3516
|
+
*/
|
|
3517
|
+
const captureMediaInParens = (tokens, from, to, leading, uses) => {
|
|
3518
|
+
const a = mediaTrimStart(tokens, from, to);
|
|
3519
|
+
const b = mediaTrimEnd(tokens, a, to);
|
|
3520
|
+
if (a >= b) return { kind: "text", text: "" };
|
|
3521
|
+
const text = mediaText(tokens, a, b);
|
|
3522
|
+
if (b - a !== 1 || A.type(tokens[a]) !== NodeType.SimpleBlock) {
|
|
3523
|
+
return { kind: "text", text };
|
|
3524
|
+
}
|
|
3525
|
+
const block = /** @type {SimpleBlock} */ (tokens[a]);
|
|
3526
|
+
const name = loneDashedIdentOfBlock(block, mediaExtra);
|
|
3527
|
+
if (name !== undefined) {
|
|
3528
|
+
const use = {
|
|
3529
|
+
name,
|
|
3530
|
+
start: A.start(block),
|
|
3531
|
+
end: A.end(block),
|
|
3532
|
+
invalid: mediaExtra.hasExtra,
|
|
3533
|
+
leading
|
|
3534
|
+
};
|
|
3535
|
+
uses.push(use);
|
|
3536
|
+
return { kind: "ref", text, use };
|
|
3537
|
+
}
|
|
3538
|
+
const children = A.children(block);
|
|
3539
|
+
const inner = captureMediaCondition(children, 0, children.length, uses);
|
|
3540
|
+
return inner.kind === "text"
|
|
3541
|
+
? { kind: "text", text }
|
|
3542
|
+
: { kind: "group", operand: inner };
|
|
3543
|
+
};
|
|
3544
|
+
|
|
3545
|
+
/**
|
|
3546
|
+
* Capture a `<media-condition>` — `not <in-parens>`, or an `and` / `or` chain
|
|
3547
|
+
* of them (CSS never mixes the two at one level).
|
|
3548
|
+
* @param {readonly AstNode[]} tokens token list
|
|
3549
|
+
* @param {number} from first index
|
|
3550
|
+
* @param {number} to one past the last index
|
|
3551
|
+
* @param {CustomMediaUse[]} uses the prelude's use list, appended to
|
|
3552
|
+
* @returns {MediaNode} the captured condition
|
|
3553
|
+
*/
|
|
3554
|
+
const captureMediaCondition = (tokens, from, to, uses) => {
|
|
3555
|
+
const a = mediaTrimStart(tokens, from, to);
|
|
3556
|
+
const b = mediaTrimEnd(tokens, a, to);
|
|
3557
|
+
if (a >= b) return { kind: "text", text: "" };
|
|
3558
|
+
if (isMediaKeyword(tokens[a], "not")) {
|
|
3559
|
+
return {
|
|
3560
|
+
kind: "not",
|
|
3561
|
+
operand: captureMediaInParens(tokens, a + 1, b, false, uses)
|
|
3562
|
+
};
|
|
3563
|
+
}
|
|
3564
|
+
/** @type {MediaNode[]} */
|
|
3565
|
+
const terms = [];
|
|
3566
|
+
let isOr = false;
|
|
3567
|
+
let start = a;
|
|
3568
|
+
for (let i = a; i <= b; i++) {
|
|
3569
|
+
const atEnd = i === b;
|
|
3570
|
+
if (
|
|
3571
|
+
!atEnd &&
|
|
3572
|
+
!isMediaKeyword(tokens[i], "and") &&
|
|
3573
|
+
!isMediaKeyword(tokens[i], "or")
|
|
3574
|
+
) {
|
|
3575
|
+
continue;
|
|
3576
|
+
}
|
|
3577
|
+
if (!atEnd && isMediaKeyword(tokens[i], "or")) isOr = true;
|
|
3578
|
+
terms.push(captureMediaInParens(tokens, start, i, start === a, uses));
|
|
3579
|
+
start = i + 1;
|
|
3580
|
+
}
|
|
3581
|
+
if (terms.length === 1) return terms[0];
|
|
3582
|
+
return { kind: "chain", isOr, terms };
|
|
3583
|
+
};
|
|
3584
|
+
|
|
3585
|
+
/**
|
|
3586
|
+
* Capture one `<media-query>` — a bare condition, or a media type with an
|
|
3587
|
+
* optional `and` chain after it.
|
|
3588
|
+
* @param {readonly AstNode[]} tokens token list
|
|
3589
|
+
* @param {number} from first index
|
|
3590
|
+
* @param {number} to one past the last index
|
|
3591
|
+
* @param {CustomMediaUse[]} uses the prelude's use list, appended to
|
|
3592
|
+
* @returns {MediaNode} the captured query
|
|
3593
|
+
*/
|
|
3594
|
+
const captureMediaQuery = (tokens, from, to, uses) => {
|
|
3595
|
+
const a = mediaTrimStart(tokens, from, to);
|
|
3596
|
+
const b = mediaTrimEnd(tokens, a, to);
|
|
3597
|
+
if (a >= b) return { kind: "text", text: "" };
|
|
3598
|
+
const rest = mediaTrimStart(tokens, a + 1, b);
|
|
3599
|
+
const startsWithType =
|
|
3600
|
+
A.type(tokens[a]) === NodeType.Ident &&
|
|
3601
|
+
(!isMediaKeyword(tokens[a], "not") ||
|
|
3602
|
+
rest >= b ||
|
|
3603
|
+
A.type(tokens[rest]) !== NodeType.SimpleBlock);
|
|
3604
|
+
if (!startsWithType) return captureMediaCondition(tokens, a, b, uses);
|
|
3605
|
+
// `[not | only]? <type> [and <condition-without-or>]?` — the type itself is
|
|
3606
|
+
// never constant, so only the `and` chain after it can fold.
|
|
3607
|
+
let split = b;
|
|
3608
|
+
for (let i = a; i < b; i++) {
|
|
3609
|
+
if (isMediaKeyword(tokens[i], "and")) {
|
|
3610
|
+
split = i;
|
|
3611
|
+
break;
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
return {
|
|
3615
|
+
kind: "typed",
|
|
3616
|
+
text: mediaText(tokens, a, mediaTrimEnd(tokens, a, split)),
|
|
3617
|
+
rest:
|
|
3618
|
+
split === b ? null : captureMediaCondition(tokens, split + 1, b, uses)
|
|
3619
|
+
};
|
|
3620
|
+
};
|
|
3621
|
+
|
|
3622
|
+
/**
|
|
3623
|
+
* Record one `@media` prelude, the custom-media references inside it, and the
|
|
3624
|
+
* boolean shape needed to fold it once the references resolve.
|
|
3625
|
+
* @param {AtRule} at the `@media` at-rule
|
|
3626
|
+
*/
|
|
3627
|
+
const collectMediaQuery = (at) => {
|
|
3628
|
+
const prelude = A.prelude(at);
|
|
3629
|
+
const start = mediaTrimStart(prelude, 0, prelude.length);
|
|
3630
|
+
const end = mediaTrimEnd(prelude, start, prelude.length);
|
|
3631
|
+
if (start >= end || !hasCustomMediaRef(prelude, start, end)) return;
|
|
3632
|
+
/** @type {CustomMediaUse[]} */
|
|
3633
|
+
const uses = [];
|
|
3634
|
+
/** @type {MediaNode[]} */
|
|
3635
|
+
const queries = [];
|
|
3636
|
+
let queryStart = start;
|
|
3637
|
+
for (let i = start; i <= end; i++) {
|
|
3638
|
+
if (i !== end && A.type(prelude[i]) !== NodeType.Comma) continue;
|
|
3639
|
+
queries.push(captureMediaQuery(prelude, queryStart, i, uses));
|
|
3640
|
+
queryStart = i + 1;
|
|
3641
|
+
}
|
|
3642
|
+
if (uses.length === 0) return;
|
|
3643
|
+
(customMediaQueries || (customMediaQueries = [])).push({
|
|
3644
|
+
queries,
|
|
3645
|
+
start: A.start(prelude[start]),
|
|
3646
|
+
end: A.end(prelude[end - 1]),
|
|
3647
|
+
uses
|
|
3648
|
+
});
|
|
3649
|
+
};
|
|
3650
|
+
|
|
3651
|
+
/**
|
|
3652
|
+
* Fold a captured media node against the resolved definitions. A reference the
|
|
3653
|
+
* resolver could not classify keeps its source text, so it prints as authored.
|
|
3654
|
+
* @param {MediaNode} node the captured node
|
|
3655
|
+
* @param {Set<string>} resolving names currently being resolved
|
|
3656
|
+
* @returns {boolean | string} the constant, or the node's text
|
|
3657
|
+
*/
|
|
3658
|
+
const foldMediaNode = (node, resolving) => {
|
|
3659
|
+
switch (node.kind) {
|
|
3660
|
+
case "text":
|
|
3661
|
+
return node.text;
|
|
3662
|
+
case "ref": {
|
|
3663
|
+
const value = resolveCustomMediaValue(node.use.name, resolving);
|
|
3664
|
+
if (node.use.invalid) return node.text;
|
|
3665
|
+
if (value.kind === "boolean") return value.value;
|
|
3666
|
+
if (value.kind === "condition") return value.text;
|
|
3667
|
+
if (value.kind === "type" && node.use.leading) return value.text;
|
|
3668
|
+
return node.text;
|
|
3669
|
+
}
|
|
3670
|
+
case "group": {
|
|
3671
|
+
const inner = foldMediaNode(node.operand, resolving);
|
|
3672
|
+
return typeof inner === "boolean" ? inner : `(${inner})`;
|
|
3673
|
+
}
|
|
3674
|
+
case "not": {
|
|
3675
|
+
const operand = foldMediaNode(node.operand, resolving);
|
|
3676
|
+
return typeof operand === "boolean" ? !operand : `not ${operand}`;
|
|
3677
|
+
}
|
|
3678
|
+
case "chain": {
|
|
3679
|
+
/** @type {string[]} */
|
|
3680
|
+
const kept = [];
|
|
3681
|
+
for (const term of node.terms) {
|
|
3682
|
+
const folded = foldMediaNode(term, resolving);
|
|
3683
|
+
if (folded === node.isOr) return node.isOr;
|
|
3684
|
+
if (typeof folded !== "boolean") kept.push(folded);
|
|
3260
3685
|
}
|
|
3261
|
-
|
|
3262
|
-
|
|
3686
|
+
if (kept.length === 0) return !node.isOr;
|
|
3687
|
+
if (kept.length === 1) return kept[0];
|
|
3688
|
+
return kept.join(node.isOr ? " or " : " and ");
|
|
3689
|
+
}
|
|
3690
|
+
default: {
|
|
3691
|
+
if (node.rest === null) return node.text;
|
|
3692
|
+
const rest = foldMediaNode(node.rest, resolving);
|
|
3693
|
+
if (rest === false) return false;
|
|
3694
|
+
if (rest === true) return node.text;
|
|
3695
|
+
return `${node.text} and ${rest}`;
|
|
3263
3696
|
}
|
|
3264
|
-
if (topLevel) leading = false;
|
|
3265
3697
|
}
|
|
3266
3698
|
};
|
|
3267
3699
|
|
|
3700
|
+
/**
|
|
3701
|
+
* Fold a whole `@media` prelude. A query that is always false leaves the list;
|
|
3702
|
+
* one that is always true makes the list match everywhere (`all`), and a list
|
|
3703
|
+
* with nothing left matches nowhere (`not all`).
|
|
3704
|
+
* @param {MediaNode[]} queries the prelude's captured queries
|
|
3705
|
+
* @param {Set<string>} resolving names currently being resolved
|
|
3706
|
+
* @returns {string} the folded prelude
|
|
3707
|
+
*/
|
|
3708
|
+
const foldMediaPrelude = (queries, resolving) => {
|
|
3709
|
+
/** @type {string[]} */
|
|
3710
|
+
const kept = [];
|
|
3711
|
+
for (const query of queries) {
|
|
3712
|
+
const folded = foldMediaNode(query, resolving);
|
|
3713
|
+
if (folded === true) return "all";
|
|
3714
|
+
if (folded !== false && folded !== "") kept.push(folded);
|
|
3715
|
+
}
|
|
3716
|
+
return kept.length === 0 ? "not all" : kept.join(", ");
|
|
3717
|
+
};
|
|
3718
|
+
|
|
3268
3719
|
/**
|
|
3269
3720
|
* Collect one `@custom-selector :--name <selector-list>` definition (last-wins) and drop the rule.
|
|
3270
3721
|
* @param {AtRule} at the `@custom-selector` at-rule
|
|
@@ -3328,55 +3779,71 @@ class CssParser extends Parser {
|
|
|
3328
3779
|
};
|
|
3329
3780
|
|
|
3330
3781
|
/**
|
|
3331
|
-
* Rewrite the collected `@custom-media` / `@custom-selector` uses now that all (possibly later-defined) definitions are known; warns on invalid, unknown, or
|
|
3782
|
+
* Rewrite the collected `@custom-media` / `@custom-selector` uses now that all (possibly later-defined) definitions are known; warns on invalid, unknown, or media-type-in-a-non-leading-position custom-media uses.
|
|
3332
3783
|
*/
|
|
3333
3784
|
const resolveCustomMediaAndSelectors = () => {
|
|
3334
|
-
if (
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3785
|
+
if (customMediaQueries) {
|
|
3786
|
+
/** @type {Set<string>} */
|
|
3787
|
+
const resolving = new Set();
|
|
3788
|
+
for (const query of customMediaQueries) {
|
|
3789
|
+
let hasBoolean = false;
|
|
3790
|
+
for (const use of query.uses) {
|
|
3791
|
+
if (use.invalid) {
|
|
3792
|
+
this._emitWarning(
|
|
3793
|
+
state,
|
|
3794
|
+
`Custom media query '${use.name}' must be used in a boolean context`,
|
|
3795
|
+
locConverter,
|
|
3796
|
+
use.start,
|
|
3797
|
+
use.end
|
|
3798
|
+
);
|
|
3799
|
+
continue;
|
|
3800
|
+
}
|
|
3801
|
+
const value = resolveCustomMediaValue(use.name, resolving);
|
|
3802
|
+
if (value.kind === "unsupported") {
|
|
3803
|
+
this._emitWarning(
|
|
3804
|
+
state,
|
|
3805
|
+
customMediaDefs && customMediaDefs.has(use.name)
|
|
3806
|
+
? `Custom media query '${use.name}' has a value that cannot be resolved and was left as written`
|
|
3807
|
+
: `Unknown custom media query '${use.name}'`,
|
|
3808
|
+
locConverter,
|
|
3809
|
+
use.start,
|
|
3810
|
+
use.end
|
|
3811
|
+
);
|
|
3812
|
+
} else if (value.kind === "boolean") {
|
|
3813
|
+
hasBoolean = true;
|
|
3814
|
+
} else if (value.kind === "type" && !use.leading) {
|
|
3815
|
+
this._emitWarning(
|
|
3816
|
+
state,
|
|
3817
|
+
`Custom media query '${use.name}' resolves to a media type and can only be used at the start of a media query`,
|
|
3818
|
+
locConverter,
|
|
3819
|
+
use.start,
|
|
3820
|
+
use.end
|
|
3821
|
+
);
|
|
3822
|
+
}
|
|
3356
3823
|
}
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3824
|
+
// `true` / `false` have no `<media-in-parens>` spelling, so a prelude
|
|
3825
|
+
// holding one is rewritten whole — every other use in it folds with it.
|
|
3826
|
+
if (hasBoolean) {
|
|
3827
|
+
module.addPresentationalDependency(
|
|
3828
|
+
new ConstDependency(foldMediaPrelude(query.queries, resolving), [
|
|
3829
|
+
query.start,
|
|
3830
|
+
query.end
|
|
3831
|
+
])
|
|
3364
3832
|
);
|
|
3365
3833
|
continue;
|
|
3366
3834
|
}
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
use.
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3835
|
+
for (const use of query.uses) {
|
|
3836
|
+
if (use.invalid) continue;
|
|
3837
|
+
const value = resolveCustomMediaValue(use.name, resolving);
|
|
3838
|
+
if (
|
|
3839
|
+
value.kind === "condition" ||
|
|
3840
|
+
(value.kind === "type" && use.leading)
|
|
3841
|
+
) {
|
|
3842
|
+
module.addPresentationalDependency(
|
|
3843
|
+
new ConstDependency(value.text, [use.start, use.end])
|
|
3844
|
+
);
|
|
3845
|
+
}
|
|
3376
3846
|
}
|
|
3377
|
-
module.addPresentationalDependency(
|
|
3378
|
-
new ConstDependency(def.text, [use.start, use.end])
|
|
3379
|
-
);
|
|
3380
3847
|
}
|
|
3381
3848
|
}
|
|
3382
3849
|
if (customSelectorUses) {
|
|
@@ -3400,10 +3867,13 @@ class CssParser extends Parser {
|
|
|
3400
3867
|
/** @type {Record<string, number>} */
|
|
3401
3868
|
let parsedKeywords = Object.create(null);
|
|
3402
3869
|
const isGridProperty = Boolean(declPropertyName.startsWith("grid"));
|
|
3403
|
-
// Only `view-transition-*` legitimately
|
|
3870
|
+
// Only `view-transition-*` and `counter-*` legitimately take a dashed-ident value; other known properties keep the historical plain-ident handling.
|
|
3404
3871
|
const isViewTransitionProperty = Boolean(
|
|
3405
3872
|
declPropertyName.startsWith("view-transition")
|
|
3406
3873
|
);
|
|
3874
|
+
const isCounterProperty = Boolean(
|
|
3875
|
+
declPropertyName.startsWith("counter-")
|
|
3876
|
+
);
|
|
3407
3877
|
const isGridTemplate = isGridProperty
|
|
3408
3878
|
? Boolean(
|
|
3409
3879
|
declPropertyName === "grid" ||
|
|
@@ -3413,7 +3883,7 @@ class CssParser extends Parser {
|
|
|
3413
3883
|
)
|
|
3414
3884
|
: false;
|
|
3415
3885
|
const keywords =
|
|
3416
|
-
/** @type {
|
|
3886
|
+
/** @type {Map<string, number>} */
|
|
3417
3887
|
(knownProperties.get(declPropertyName));
|
|
3418
3888
|
let afterExclamation = false;
|
|
3419
3889
|
/**
|
|
@@ -3430,6 +3900,8 @@ class CssParser extends Parser {
|
|
|
3430
3900
|
isString ? start + 1 : start,
|
|
3431
3901
|
isString ? end - 1 : end
|
|
3432
3902
|
);
|
|
3903
|
+
// Only grid-line names are declaration sites here; property-value references (`animation: foo`) are usages.
|
|
3904
|
+
if (isGridProperty) recordDeclaration(name, "grid identifier", sl, sc);
|
|
3433
3905
|
addCssExport(
|
|
3434
3906
|
sl,
|
|
3435
3907
|
sc,
|
|
@@ -3463,8 +3935,11 @@ class CssParser extends Parser {
|
|
|
3463
3935
|
break;
|
|
3464
3936
|
}
|
|
3465
3937
|
const identifier = A.value(cv);
|
|
3466
|
-
// `view-transition-name: --foo` — a dashed name scopes as a custom property under `dashedIdents`, not as a plain ident export.
|
|
3467
|
-
if (
|
|
3938
|
+
// `view-transition-name: --foo` / `counter-reset: --foo` — a dashed name scopes as a custom property under `dashedIdents`, not as a plain ident export.
|
|
3939
|
+
if (
|
|
3940
|
+
(isViewTransitionProperty || isCounterProperty) &&
|
|
3941
|
+
isDashedIdentifier(identifier)
|
|
3942
|
+
) {
|
|
3468
3943
|
if (this.options.dashedIdents) {
|
|
3469
3944
|
emitDashedIdentExport(A.start(cv), A.end(cv));
|
|
3470
3945
|
}
|
|
@@ -3476,10 +3951,8 @@ class CssParser extends Parser {
|
|
|
3476
3951
|
typeof parsedKeywords[keyword] !== "undefined"
|
|
3477
3952
|
? parsedKeywords[keyword] + 1
|
|
3478
3953
|
: 0;
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
parsedKeywords[keyword] < keywords[keyword]
|
|
3482
|
-
) {
|
|
3954
|
+
const limit = keywords.get(keyword);
|
|
3955
|
+
if (limit !== undefined && parsedKeywords[keyword] < limit) {
|
|
3483
3956
|
break;
|
|
3484
3957
|
}
|
|
3485
3958
|
emit(A.start(cv), A.end(cv));
|
|
@@ -3497,11 +3970,15 @@ class CssParser extends Parser {
|
|
|
3497
3970
|
declPropertyName === "grid-template" ||
|
|
3498
3971
|
declPropertyName === "grid-template-areas"
|
|
3499
3972
|
) {
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3973
|
+
// Raw offsets: a match index into the unescaped text would
|
|
3974
|
+
// slide the replaced range past every escape before it.
|
|
3975
|
+
const names = gridAreaNames(
|
|
3976
|
+
source,
|
|
3977
|
+
A.start(cv) + 1,
|
|
3978
|
+
A.end(cv) - 1
|
|
3979
|
+
);
|
|
3980
|
+
for (const [nameStart, nameEnd] of names) {
|
|
3981
|
+
emit(nameStart, nameEnd, false);
|
|
3505
3982
|
}
|
|
3506
3983
|
}
|
|
3507
3984
|
break;
|
|
@@ -3521,7 +3998,12 @@ class CssParser extends Parser {
|
|
|
3521
3998
|
break;
|
|
3522
3999
|
}
|
|
3523
4000
|
case NodeType.Function:
|
|
3524
|
-
|
|
4001
|
+
// `repeat(…)` line names, and the `counter-reset: reversed(name)` wrapper — but not `local()`/`global()`, whose idents the value visitors own.
|
|
4002
|
+
if (
|
|
4003
|
+
isGridTemplate ||
|
|
4004
|
+
(isCounterProperty &&
|
|
4005
|
+
equalsLowerCase(A.unescapedName(cv), "reversed"))
|
|
4006
|
+
) {
|
|
3525
4007
|
walkExports(A.children(cv));
|
|
3526
4008
|
}
|
|
3527
4009
|
break;
|
|
@@ -3588,13 +4070,10 @@ class CssParser extends Parser {
|
|
|
3588
4070
|
currentUrlRecovery = false;
|
|
3589
4071
|
advanceCommentCursor(A.start(at));
|
|
3590
4072
|
const savedAnchor = currentRule.hasLocalAnchor;
|
|
3591
|
-
|
|
3592
|
-
//
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
? [...savedLocalIdentifiers]
|
|
3596
|
-
: savedLocalIdentifiers;
|
|
3597
|
-
const name = `@${toLowerCaseIfNeeded(A.name(at))}`;
|
|
4073
|
+
// Rollback point: nested walks append to the shared list; the exit
|
|
4074
|
+
// truncates back to this length (no per-rule copy).
|
|
4075
|
+
const savedLocalIdentifierCount = currentRule.localIdentifiers.length;
|
|
4076
|
+
const name = `@${toLowerCaseIfNeeded(A.unescapedName(at))}`;
|
|
3598
4077
|
switch (name) {
|
|
3599
4078
|
case "@namespace": {
|
|
3600
4079
|
this._emitWarning(
|
|
@@ -3638,7 +4117,7 @@ class CssParser extends Parser {
|
|
|
3638
4117
|
break;
|
|
3639
4118
|
}
|
|
3640
4119
|
case "@media": {
|
|
3641
|
-
if (mayHaveCustomMedia)
|
|
4120
|
+
if (mayHaveCustomMedia) collectMediaQuery(at);
|
|
3642
4121
|
break;
|
|
3643
4122
|
}
|
|
3644
4123
|
default: {
|
|
@@ -3650,21 +4129,33 @@ class CssParser extends Parser {
|
|
|
3650
4129
|
this.options.animation &&
|
|
3651
4130
|
OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE.test(name)
|
|
3652
4131
|
) {
|
|
3653
|
-
processLocalAtRule(
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
4132
|
+
processLocalAtRule(
|
|
4133
|
+
at,
|
|
4134
|
+
{
|
|
4135
|
+
string: mode === "local",
|
|
4136
|
+
identifier: mode === "local"
|
|
4137
|
+
},
|
|
4138
|
+
"@keyframes"
|
|
4139
|
+
);
|
|
3657
4140
|
} else if (
|
|
3658
4141
|
this.options.customIdents &&
|
|
3659
4142
|
name === "@counter-style"
|
|
3660
4143
|
) {
|
|
3661
|
-
processLocalAtRule(
|
|
3662
|
-
|
|
3663
|
-
|
|
4144
|
+
processLocalAtRule(
|
|
4145
|
+
at,
|
|
4146
|
+
{
|
|
4147
|
+
identifier: mode === "local"
|
|
4148
|
+
},
|
|
4149
|
+
"@counter-style"
|
|
4150
|
+
);
|
|
3664
4151
|
} else if (this.options.container && name === "@container") {
|
|
3665
|
-
processLocalAtRule(
|
|
3666
|
-
|
|
3667
|
-
|
|
4152
|
+
processLocalAtRule(
|
|
4153
|
+
at,
|
|
4154
|
+
{
|
|
4155
|
+
identifier: mode === "local" ? /^(none|and|or|not)$/ : false
|
|
4156
|
+
},
|
|
4157
|
+
"@container"
|
|
4158
|
+
);
|
|
3668
4159
|
}
|
|
3669
4160
|
}
|
|
3670
4161
|
}
|
|
@@ -3672,7 +4163,7 @@ class CssParser extends Parser {
|
|
|
3672
4163
|
// `@scope (.x) to (.y)` — walk the prelude as a selector list.
|
|
3673
4164
|
if (
|
|
3674
4165
|
isModules &&
|
|
3675
|
-
equalsLowerCase(A.
|
|
4166
|
+
equalsLowerCase(A.unescapedName(at), "scope") &&
|
|
3676
4167
|
A.prelude(at).length > 0
|
|
3677
4168
|
) {
|
|
3678
4169
|
walkSelectorList(
|
|
@@ -3688,6 +4179,7 @@ class CssParser extends Parser {
|
|
|
3688
4179
|
const isProcessedByLocalAtRule = isLocalHandledAtRule(name);
|
|
3689
4180
|
currentStructural = at;
|
|
3690
4181
|
currentAtRuleName = name;
|
|
4182
|
+
currentDeclCounterActive = false;
|
|
3691
4183
|
dashed.active = false;
|
|
3692
4184
|
// `@import` url() is the import target — only walk its prelude for url deps on malformed-import recovery.
|
|
3693
4185
|
if (this.options.url && (name !== "@import" || currentUrlRecovery)) {
|
|
@@ -3728,12 +4220,13 @@ class CssParser extends Parser {
|
|
|
3728
4220
|
);
|
|
3729
4221
|
}
|
|
3730
4222
|
|
|
3731
|
-
// pure.stack push for block-bearing at-rules
|
|
4223
|
+
// pure.stack push for block-bearing at-rules (pure-off builds skip
|
|
4224
|
+
// the frame object — every consumer inside is a no-op then).
|
|
3732
4225
|
const atDecls = A.declarations(at);
|
|
3733
4226
|
const atChildRules = A.childRules(at);
|
|
3734
4227
|
const atHasBlock = Boolean(atDecls || atChildRules);
|
|
3735
4228
|
const atBlockStart = A.blockStart(at);
|
|
3736
|
-
if (atHasBlock && atBlockStart !== -1) {
|
|
4229
|
+
if (pure.enabled && atHasBlock && atBlockStart !== -1) {
|
|
3737
4230
|
const isAtRulePrelude = isPureBodyAtRule(name);
|
|
3738
4231
|
if (isAtRulePrelude) pure.finalizeSelector();
|
|
3739
4232
|
pure.enterBlock({
|
|
@@ -3749,7 +4242,7 @@ class CssParser extends Parser {
|
|
|
3749
4242
|
|
|
3750
4243
|
atRuleStateStack.push({
|
|
3751
4244
|
savedAnchor,
|
|
3752
|
-
|
|
4245
|
+
savedLocalIdentifierCount,
|
|
3753
4246
|
name,
|
|
3754
4247
|
hasBlock: atHasBlock,
|
|
3755
4248
|
endsWithSemicolon: source.charCodeAt(A.end(at)) === CC_SEMICOLON,
|
|
@@ -3772,7 +4265,7 @@ class CssParser extends Parser {
|
|
|
3772
4265
|
suppressNextRulePrelude = true;
|
|
3773
4266
|
}
|
|
3774
4267
|
currentRule.hasLocalAnchor = state.savedAnchor;
|
|
3775
|
-
currentRule.localIdentifiers = state.
|
|
4268
|
+
currentRule.localIdentifiers.length = state.savedLocalIdentifierCount;
|
|
3776
4269
|
if (path.parent === null) finishTopLevelRule(node, true);
|
|
3777
4270
|
}
|
|
3778
4271
|
},
|
|
@@ -3783,11 +4276,16 @@ class CssParser extends Parser {
|
|
|
3783
4276
|
const rule = /** @type {QualifiedRule} */ (node);
|
|
3784
4277
|
const topLevel = path.parent === null;
|
|
3785
4278
|
advanceCommentCursor(A.start(rule));
|
|
4279
|
+
// One prelude materialization per rule, shared by the scans below
|
|
4280
|
+
// (null in plain mode, which never reads the array).
|
|
4281
|
+
const rulePrelude =
|
|
4282
|
+
isModules || mayHaveCustomSelectors ? A.prelude(rule) : null;
|
|
3786
4283
|
// `:--name` custom-selector references (dashed idents never collide with the `:import`/`:export` ICSS preludes below).
|
|
3787
|
-
if (mayHaveCustomSelectors)
|
|
4284
|
+
if (mayHaveCustomSelectors && rulePrelude !== null) {
|
|
4285
|
+
scanCustomSelectorUses(rulePrelude);
|
|
4286
|
+
}
|
|
3788
4287
|
// `:import(…) { … }` / `:export { … }` ICSS pseudo-rules are processed inline at top level; nested ones bail out.
|
|
3789
|
-
if (isModules) {
|
|
3790
|
-
const rulePrelude = A.prelude(rule);
|
|
4288
|
+
if (isModules && rulePrelude !== null) {
|
|
3791
4289
|
const firstIdx = nextNonWhitespace(rulePrelude, 0);
|
|
3792
4290
|
if (
|
|
3793
4291
|
firstIdx + 1 < rulePrelude.length &&
|
|
@@ -3828,14 +4326,12 @@ class CssParser extends Parser {
|
|
|
3828
4326
|
}
|
|
3829
4327
|
}
|
|
3830
4328
|
}
|
|
3831
|
-
// Reset the anchor flag for this rule's body
|
|
4329
|
+
// Reset the anchor flag for this rule's body; nested `composes:` sees
|
|
4330
|
+
// parent + own class names in the shared identifier list, rolled back
|
|
4331
|
+
// by length on exit (no per-rule copy).
|
|
3832
4332
|
const savedAnchor = currentRule.hasLocalAnchor;
|
|
3833
|
-
const
|
|
4333
|
+
const savedLocalIdentifierCount = currentRule.localIdentifiers.length;
|
|
3834
4334
|
currentRule.hasLocalAnchor = false;
|
|
3835
|
-
// Only modules-mode walks mutate `localIdentifiers`; otherwise share the (empty) parent list instead of copying it per rule.
|
|
3836
|
-
currentRule.localIdentifiers = isModules
|
|
3837
|
-
? [...savedLocalIdentifiers]
|
|
3838
|
-
: savedLocalIdentifiers;
|
|
3839
4335
|
// Composes-state reset between rules (saved / restored around this rule); composesFiles is swapped out and re-created lazily only if this rule composes.
|
|
3840
4336
|
const savedPrevComposesFile = currentRule.composesPrevFile;
|
|
3841
4337
|
const savedComposesFiles = currentRule.composesFiles;
|
|
@@ -3844,13 +4340,12 @@ class CssParser extends Parser {
|
|
|
3844
4340
|
qualifiedRuleStateStack.push({
|
|
3845
4341
|
bailed: false,
|
|
3846
4342
|
savedAnchor,
|
|
3847
|
-
|
|
4343
|
+
savedLocalIdentifierCount,
|
|
3848
4344
|
savedPrevComposesFile,
|
|
3849
4345
|
savedComposesFiles
|
|
3850
4346
|
});
|
|
3851
4347
|
// Selectors are only CSS-Modules-relevant when `isModules` holds.
|
|
3852
|
-
|
|
3853
|
-
if (isModules) {
|
|
4348
|
+
if (isModules && rulePrelude !== null) {
|
|
3854
4349
|
walkSelectorList(
|
|
3855
4350
|
rulePrelude,
|
|
3856
4351
|
/** @type {"local" | "global"} */ (
|
|
@@ -3860,22 +4355,24 @@ class CssParser extends Parser {
|
|
|
3860
4355
|
}
|
|
3861
4356
|
// A malformed declaration can leave orphan `url(...)` in the prelude — let the url visitor pick those up.
|
|
3862
4357
|
currentStructural = rule;
|
|
4358
|
+
currentDeclCounterActive = false;
|
|
3863
4359
|
dashed.active = false;
|
|
3864
4360
|
dashed.emit = false;
|
|
3865
|
-
if (this.options.url &&
|
|
3866
|
-
lastTokenEndForComments = A.start(
|
|
4361
|
+
if (this.options.url && A.childCount(rule) > 0) {
|
|
4362
|
+
lastTokenEndForComments = A.start(A.childAt(rule, 0));
|
|
3867
4363
|
}
|
|
3868
4364
|
// Dashed-ident scoping for the deprecated `--foo: { … }` custom-property-set syntax (prelude starts with a dashed-ident).
|
|
3869
4365
|
if (
|
|
3870
4366
|
this.options.dashedIdents &&
|
|
3871
4367
|
isModules &&
|
|
4368
|
+
rulePrelude !== null &&
|
|
3872
4369
|
rulePrelude.length > 0
|
|
3873
4370
|
) {
|
|
3874
4371
|
const first = rulePrelude[nextNonWhitespace(rulePrelude, 0)];
|
|
3875
4372
|
if (
|
|
3876
4373
|
first &&
|
|
3877
4374
|
A.type(first) === NodeType.Ident &&
|
|
3878
|
-
|
|
4375
|
+
rangeIsDashedIdentifier(source, A.start(first), A.end(first))
|
|
3879
4376
|
) {
|
|
3880
4377
|
const effectiveLocalMode = isEffectivelyLocal();
|
|
3881
4378
|
if (effectiveLocalMode) {
|
|
@@ -3885,6 +4382,7 @@ class CssParser extends Parser {
|
|
|
3885
4382
|
}
|
|
3886
4383
|
}
|
|
3887
4384
|
// Pure-mode: report an impure prelude (if leaf-ish) and push the inherited-context frame before walking the body.
|
|
4385
|
+
if (!pure.enabled) return;
|
|
3888
4386
|
const ruleBlockStart = A.blockStart(rule);
|
|
3889
4387
|
pure.enterBlock({
|
|
3890
4388
|
isRulePrelude: true,
|
|
@@ -3903,7 +4401,7 @@ class CssParser extends Parser {
|
|
|
3903
4401
|
if (!state || state.bailed) return;
|
|
3904
4402
|
pure.exitBlock();
|
|
3905
4403
|
currentRule.hasLocalAnchor = state.savedAnchor;
|
|
3906
|
-
currentRule.localIdentifiers = state.
|
|
4404
|
+
currentRule.localIdentifiers.length = state.savedLocalIdentifierCount;
|
|
3907
4405
|
currentRule.composesPrevFile = state.savedPrevComposesFile;
|
|
3908
4406
|
currentRule.composesFiles = state.savedComposesFiles;
|
|
3909
4407
|
if (path.parent === null) finishTopLevelRule(node, false);
|
|
@@ -3928,6 +4426,8 @@ class CssParser extends Parser {
|
|
|
3928
4426
|
lastTokenEndForComments = colonPos + 1;
|
|
3929
4427
|
currentDeclIsKnownProperty = false;
|
|
3930
4428
|
currentDeclComposesSkip = false;
|
|
4429
|
+
currentDeclCounterActive = false;
|
|
4430
|
+
dashed.counterArgs = false;
|
|
3931
4431
|
// Property-name analysis and value exports are CSS-Modules-only; a plain
|
|
3932
4432
|
// stylesheet's declarations need no per-decl name slice / known-property lookup.
|
|
3933
4433
|
if (!isModules) return;
|
|
@@ -3939,13 +4439,23 @@ class CssParser extends Parser {
|
|
|
3939
4439
|
let declName;
|
|
3940
4440
|
/** @type {string | undefined} */
|
|
3941
4441
|
let declPropertyName;
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
)
|
|
3948
|
-
|
|
4442
|
+
let declIsDashed = false;
|
|
4443
|
+
if (
|
|
4444
|
+
source.charCodeAt(nameStart) === CC_HYPHEN_MINUS ||
|
|
4445
|
+
source.charCodeAt(nameStart) === CC_REVERSE_SOLIDUS
|
|
4446
|
+
) {
|
|
4447
|
+
if (rangeIsDashedIdentifier(source, nameStart, nameEnd)) {
|
|
4448
|
+
// Custom property: never vendor-prefixed / known / composes.
|
|
4449
|
+
declIsDashed = true;
|
|
4450
|
+
} else {
|
|
4451
|
+
// Vendor-prefixed, degenerate short, or an escaped name that is
|
|
4452
|
+
// not dashed after all — rare, string path.
|
|
4453
|
+
declName = A.unescapedName(decl);
|
|
4454
|
+
declPropertyName = toLowerCaseIfNeeded(
|
|
4455
|
+
declName.replace(VENDOR_PREFIX, "")
|
|
4456
|
+
);
|
|
4457
|
+
currentDeclIsKnownProperty = knownProperties.has(declPropertyName);
|
|
4458
|
+
}
|
|
3949
4459
|
} else {
|
|
3950
4460
|
declPropertyName = knownPropertyForRange(
|
|
3951
4461
|
knownPropertyIndex,
|
|
@@ -3966,6 +4476,11 @@ class CssParser extends Parser {
|
|
|
3966
4476
|
rangeEqualsLowerCase(source, nameStart, nameEnd, "compose-with"));
|
|
3967
4477
|
if (currentDeclComposesSkip) emitComposesWithAnchor(decl);
|
|
3968
4478
|
const skipForComposes = currentDeclComposesSkip;
|
|
4479
|
+
// `content: counter(name, style)` can name a scoped counter / `@counter-style` from any property, so this isn't driven by the known-property table.
|
|
4480
|
+
currentDeclCounterActive =
|
|
4481
|
+
Boolean(this.options.customIdents) &&
|
|
4482
|
+
effectiveLocalMode &&
|
|
4483
|
+
!skipForComposes;
|
|
3969
4484
|
// Known-property value localization (`animation-name: foo` exports `foo`).
|
|
3970
4485
|
if (effectiveLocalMode && currentDeclIsKnownProperty) {
|
|
3971
4486
|
emitKnownPropertyExports(
|
|
@@ -3979,8 +4494,8 @@ class CssParser extends Parser {
|
|
|
3979
4494
|
effectiveLocalMode &&
|
|
3980
4495
|
!skipForComposes
|
|
3981
4496
|
) {
|
|
3982
|
-
// Only the
|
|
3983
|
-
if (
|
|
4497
|
+
// Only the `--`-prefixed path can carry a dashed ident.
|
|
4498
|
+
if (declIsDashed) {
|
|
3984
4499
|
emitDashedIdentExport(nameStart, nameEnd);
|
|
3985
4500
|
}
|
|
3986
4501
|
dashed.active = true;
|
|
@@ -3996,7 +4511,7 @@ class CssParser extends Parser {
|
|
|
3996
4511
|
declName = source.slice(nameStart, nameEnd);
|
|
3997
4512
|
}
|
|
3998
4513
|
if (
|
|
3999
|
-
!(dashed.active &&
|
|
4514
|
+
!(dashed.active && declIsDashed) &&
|
|
4000
4515
|
icssDefinitions.has(declName)
|
|
4001
4516
|
) {
|
|
4002
4517
|
emitICSSSymbol(declName, nameStart, nameEnd);
|
|
@@ -4122,8 +4637,22 @@ class CssParser extends Parser {
|
|
|
4122
4637
|
emitICSSSymbol(fname, fnNameStart, fnNameEnd);
|
|
4123
4638
|
}
|
|
4124
4639
|
}
|
|
4640
|
+
// `counter()` / `counters()` / `target-counter()` / `target-counters()`: rewrite the counter name and any trailing counter-style ident.
|
|
4641
|
+
let counterNameIndex = -1;
|
|
4642
|
+
if (currentDeclCounterActive && !isLocalFn && !isGlobalFn) {
|
|
4643
|
+
counterNameIndex = counterFunctionNameIndex(
|
|
4644
|
+
input,
|
|
4645
|
+
fnNameStart,
|
|
4646
|
+
fnNameEnd,
|
|
4647
|
+
escapedName
|
|
4648
|
+
);
|
|
4649
|
+
if (counterNameIndex !== -1) {
|
|
4650
|
+
walkCounterFunction(A.children(fn), counterNameIndex);
|
|
4651
|
+
}
|
|
4652
|
+
}
|
|
4125
4653
|
// Dashed-ident scoping: handle this function, then set the child nesting level's state for the walk.
|
|
4126
4654
|
dashed.push();
|
|
4655
|
+
dashed.counterArgs = counterNameIndex !== -1;
|
|
4127
4656
|
if (dashed.active) {
|
|
4128
4657
|
if (isLocalFn || isGlobalFn) {
|
|
4129
4658
|
// `local()` / `global()` dashed args go through the ICSS path above, not here.
|
|
@@ -4171,12 +4700,18 @@ class CssParser extends Parser {
|
|
|
4171
4700
|
// and ICSS context (any non-CSS-Modules stylesheet) a bare ident carries
|
|
4172
4701
|
// no work, and idents are the most common node, so skipping the per-ident
|
|
4173
4702
|
// `value` slice matters. With no `@value`/`:import` definitions the ICSS
|
|
4174
|
-
// probe can never hit, so it doesn't warrant the slice either.
|
|
4703
|
+
// probe can never hit, so it doesn't warrant the slice either. The dashed
|
|
4704
|
+
// probe reads two char codes instead of slicing (escaped dashes don't
|
|
4705
|
+
// match, same as the string form — cf. `processDashedIdentInVarFunction`).
|
|
4175
4706
|
const dashedActive = dashed.active;
|
|
4176
4707
|
const icss = icssActive() && icssDefinitions.size !== 0;
|
|
4177
4708
|
if (!dashedActive && !icss) return;
|
|
4178
|
-
const
|
|
4179
|
-
|
|
4709
|
+
const identStart = A.start(node);
|
|
4710
|
+
const identEnd = A.end(node);
|
|
4711
|
+
if (
|
|
4712
|
+
dashedActive &&
|
|
4713
|
+
rangeIsDashedIdentifier(input, identStart, identEnd)
|
|
4714
|
+
) {
|
|
4180
4715
|
// Dashed idents are scoped here, never `@value` ICSS-rewritten.
|
|
4181
4716
|
if (!dashed.emit) return;
|
|
4182
4717
|
// Resolve the `--foo from "./x.css"` / `--foo from global` import suffix via sibling lookahead over the parent's child span (`path.index` avoids materializing the sibling list per dashed ident).
|
|
@@ -4219,13 +4754,13 @@ class CssParser extends Parser {
|
|
|
4219
4754
|
"global"
|
|
4220
4755
|
)
|
|
4221
4756
|
) {
|
|
4222
|
-
emitDashedIdentFromGlobal(
|
|
4757
|
+
emitDashedIdentFromGlobal(identEnd, A.end(sourceNode));
|
|
4223
4758
|
return;
|
|
4224
4759
|
}
|
|
4225
4760
|
if (sourceNode && A.type(sourceNode) === NodeType.String) {
|
|
4226
4761
|
emitDashedIdentImport(
|
|
4227
|
-
|
|
4228
|
-
|
|
4762
|
+
identStart,
|
|
4763
|
+
identEnd,
|
|
4229
4764
|
A.start(fromIdent),
|
|
4230
4765
|
A.end(sourceNode),
|
|
4231
4766
|
input.slice(A.start(sourceNode) + 1, A.end(sourceNode) - 1)
|
|
@@ -4234,12 +4769,16 @@ class CssParser extends Parser {
|
|
|
4234
4769
|
}
|
|
4235
4770
|
}
|
|
4236
4771
|
}
|
|
4237
|
-
emitDashedIdentExport(
|
|
4772
|
+
emitDashedIdentExport(identStart, identEnd);
|
|
4238
4773
|
return;
|
|
4239
4774
|
}
|
|
4240
4775
|
if (!icss) return;
|
|
4776
|
+
// Already rewritten as a counter / counter-style name — a second dep would overlap the same range.
|
|
4777
|
+
if (dashed.counterArgs) return;
|
|
4778
|
+
// Deferred: only the ICSS probe needs the ident's string value.
|
|
4779
|
+
const identValue = A.value(node);
|
|
4241
4780
|
if (icssDefinitions.has(identValue)) {
|
|
4242
|
-
emitICSSSymbol(identValue,
|
|
4781
|
+
emitICSSSymbol(identValue, identStart, identEnd);
|
|
4243
4782
|
}
|
|
4244
4783
|
}
|
|
4245
4784
|
};
|
|
@@ -4249,19 +4788,22 @@ class CssParser extends Parser {
|
|
|
4249
4788
|
// (per-source) is passed to `process`. One skip set: selector prelude +
|
|
4250
4789
|
// unread value leaves (non-modules only; CSS Modules needs its selectors
|
|
4251
4790
|
// and ICSS-captured values).
|
|
4252
|
-
new SourceProcessor(
|
|
4253
|
-
as: /** @type {"stylesheet" | "block-contents"} */ (this.options.as),
|
|
4254
|
-
// Non-modules parses skip selector preludes, but `@custom-selector` expansion needs them, so keep them when the file may use one.
|
|
4255
|
-
skip: isModules
|
|
4256
|
-
? undefined
|
|
4257
|
-
: mayHaveCustomSelectors
|
|
4258
|
-
? SKIP_NON_MODULES_KEEP_SELECTORS
|
|
4259
|
-
: SKIP_NON_MODULES
|
|
4260
|
-
})
|
|
4791
|
+
new SourceProcessor()
|
|
4261
4792
|
.use(/** @type {VisitorMap} */ (visitors))
|
|
4262
|
-
.process(source, {
|
|
4793
|
+
.process(source, {
|
|
4794
|
+
as: /** @type {"stylesheet" | "block-contents"} */ (this.options.as),
|
|
4795
|
+
// Non-modules parses skip selector preludes, but `@custom-selector` expansion needs them, so keep them when the file may use one.
|
|
4796
|
+
skip: isModules
|
|
4797
|
+
? undefined
|
|
4798
|
+
: mayHaveCustomSelectors
|
|
4799
|
+
? SKIP_NON_MODULES_KEEP_SELECTORS
|
|
4800
|
+
: SKIP_NON_MODULES,
|
|
4801
|
+
locConverter
|
|
4802
|
+
});
|
|
4263
4803
|
|
|
4264
|
-
if (
|
|
4804
|
+
if (customMediaQueries || customSelectorUses) {
|
|
4805
|
+
resolveCustomMediaAndSelectors();
|
|
4806
|
+
}
|
|
4265
4807
|
|
|
4266
4808
|
/** @type {BuildInfo} */
|
|
4267
4809
|
(module.buildInfo).strict = true;
|
|
@@ -4286,6 +4828,9 @@ class CssParser extends Parser {
|
|
|
4286
4828
|
: "redirect-warn";
|
|
4287
4829
|
|
|
4288
4830
|
if (cssExportEntries.length > 0) {
|
|
4831
|
+
if (isModules && declaredExports.size > 0) {
|
|
4832
|
+
this._resolveAmbiguousExports(state, declaredExports, cssExportEntries);
|
|
4833
|
+
}
|
|
4289
4834
|
module.addDependency(new CssIcssExportDependency(cssExportEntries));
|
|
4290
4835
|
}
|
|
4291
4836
|
|