diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2023-11-05 17:16:09 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2023-11-05 17:16:09 +0800 |
| commit | d1d9f00b1bd660842addf5e6b1d1b64c852a9eea (patch) | |
| tree | 60fb37ae73a1109d95301de5ec9b61b5726a4b61 /node_modules/webpack/lib/rules | |
| parent | 7c85166c4cbdd862fc4252007d2df5befcbc2a58 (diff) | |
added hover prefixer
Diffstat (limited to 'node_modules/webpack/lib/rules')
5 files changed, 717 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/rules/BasicEffectRulePlugin.js b/node_modules/webpack/lib/rules/BasicEffectRulePlugin.js new file mode 100644 index 00000000..7043f3b0 --- /dev/null +++ b/node_modules/webpack/lib/rules/BasicEffectRulePlugin.js @@ -0,0 +1,43 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +/** @typedef {import("./RuleSetCompiler")} RuleSetCompiler */ + +class BasicEffectRulePlugin { + /** + * @param {string} ruleProperty the rule property + * @param {string=} effectType the effect type + */ + constructor(ruleProperty, effectType) { + this.ruleProperty = ruleProperty; + this.effectType = effectType || ruleProperty; + } + + /** + * @param {RuleSetCompiler} ruleSetCompiler the rule set compiler + * @returns {void} + */ + apply(ruleSetCompiler) { + ruleSetCompiler.hooks.rule.tap( + "BasicEffectRulePlugin", + (path, rule, unhandledProperties, result, references) => { + if (unhandledProperties.has(this.ruleProperty)) { + unhandledProperties.delete(this.ruleProperty); + + const value = rule[this.ruleProperty]; + + result.effects.push({ + type: this.effectType, + value + }); + } + } + ); + } +} + +module.exports = BasicEffectRulePlugin; diff --git a/node_modules/webpack/lib/rules/BasicMatcherRulePlugin.js b/node_modules/webpack/lib/rules/BasicMatcherRulePlugin.js new file mode 100644 index 00000000..7bfd13dc --- /dev/null +++ b/node_modules/webpack/lib/rules/BasicMatcherRulePlugin.js @@ -0,0 +1,52 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +/** @typedef {import("./RuleSetCompiler")} RuleSetCompiler */ +/** @typedef {import("./RuleSetCompiler").RuleCondition} RuleCondition */ + +class BasicMatcherRulePlugin { + /** + * @param {string} ruleProperty the rule property + * @param {string=} dataProperty the data property + * @param {boolean=} invert if true, inverts the condition + */ + constructor(ruleProperty, dataProperty, invert) { + this.ruleProperty = ruleProperty; + this.dataProperty = dataProperty || ruleProperty; + this.invert = invert || false; + } + + /** + * @param {RuleSetCompiler} ruleSetCompiler the rule set compiler + * @returns {void} + */ + apply(ruleSetCompiler) { + ruleSetCompiler.hooks.rule.tap( + "BasicMatcherRulePlugin", + (path, rule, unhandledProperties, result) => { + if (unhandledProperties.has(this.ruleProperty)) { + unhandledProperties.delete(this.ruleProperty); + const value = rule[this.ruleProperty]; + const condition = ruleSetCompiler.compileCondition( + `${path}.${this.ruleProperty}`, + value + ); + const fn = condition.fn; + result.conditions.push({ + property: this.dataProperty, + matchWhenEmpty: this.invert + ? !condition.matchWhenEmpty + : condition.matchWhenEmpty, + fn: this.invert ? v => !fn(v) : fn + }); + } + } + ); + } +} + +module.exports = BasicMatcherRulePlugin; diff --git a/node_modules/webpack/lib/rules/ObjectMatcherRulePlugin.js b/node_modules/webpack/lib/rules/ObjectMatcherRulePlugin.js new file mode 100644 index 00000000..613429e8 --- /dev/null +++ b/node_modules/webpack/lib/rules/ObjectMatcherRulePlugin.js @@ -0,0 +1,47 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +/** @typedef {import("./RuleSetCompiler")} RuleSetCompiler */ +/** @typedef {import("./RuleSetCompiler").RuleCondition} RuleCondition */ + +class ObjectMatcherRulePlugin { + constructor(ruleProperty, dataProperty) { + this.ruleProperty = ruleProperty; + this.dataProperty = dataProperty || ruleProperty; + } + + /** + * @param {RuleSetCompiler} ruleSetCompiler the rule set compiler + * @returns {void} + */ + apply(ruleSetCompiler) { + const { ruleProperty, dataProperty } = this; + ruleSetCompiler.hooks.rule.tap( + "ObjectMatcherRulePlugin", + (path, rule, unhandledProperties, result) => { + if (unhandledProperties.has(ruleProperty)) { + unhandledProperties.delete(ruleProperty); + const value = rule[ruleProperty]; + for (const property of Object.keys(value)) { + const nestedDataProperties = property.split("."); + const condition = ruleSetCompiler.compileCondition( + `${path}.${ruleProperty}.${property}`, + value[property] + ); + result.conditions.push({ + property: [dataProperty, ...nestedDataProperties], + matchWhenEmpty: condition.matchWhenEmpty, + fn: condition.fn + }); + } + } + } + ); + } +} + +module.exports = ObjectMatcherRulePlugin; diff --git a/node_modules/webpack/lib/rules/RuleSetCompiler.js b/node_modules/webpack/lib/rules/RuleSetCompiler.js new file mode 100644 index 00000000..7f602764 --- /dev/null +++ b/node_modules/webpack/lib/rules/RuleSetCompiler.js @@ -0,0 +1,379 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +const { SyncHook } = require("tapable"); + +/** + * @typedef {Object} RuleCondition + * @property {string | string[]} property + * @property {boolean} matchWhenEmpty + * @property {function(string): boolean} fn + */ + +/** + * @typedef {Object} Condition + * @property {boolean} matchWhenEmpty + * @property {function(string): boolean} fn + */ + +/** + * @typedef {Object} CompiledRule + * @property {RuleCondition[]} conditions + * @property {(Effect|function(object): Effect[])[]} effects + * @property {CompiledRule[]=} rules + * @property {CompiledRule[]=} oneOf + */ + +/** + * @typedef {Object} Effect + * @property {string} type + * @property {any} value + */ + +/** + * @typedef {Object} RuleSet + * @property {Map<string, any>} references map of references in the rule set (may grow over time) + * @property {function(object): Effect[]} exec execute the rule set + */ + +class RuleSetCompiler { + constructor(plugins) { + this.hooks = Object.freeze({ + /** @type {SyncHook<[string, object, Set<string>, CompiledRule, Map<string, any>]>} */ + rule: new SyncHook([ + "path", + "rule", + "unhandledProperties", + "compiledRule", + "references" + ]) + }); + if (plugins) { + for (const plugin of plugins) { + plugin.apply(this); + } + } + } + + /** + * @param {object[]} ruleSet raw user provided rules + * @returns {RuleSet} compiled RuleSet + */ + compile(ruleSet) { + const refs = new Map(); + const rules = this.compileRules("ruleSet", ruleSet, refs); + + /** + * @param {object} data data passed in + * @param {CompiledRule} rule the compiled rule + * @param {Effect[]} effects an array where effects are pushed to + * @returns {boolean} true, if the rule has matched + */ + const execRule = (data, rule, effects) => { + for (const condition of rule.conditions) { + const p = condition.property; + if (Array.isArray(p)) { + let current = data; + for (const subProperty of p) { + if ( + current && + typeof current === "object" && + Object.prototype.hasOwnProperty.call(current, subProperty) + ) { + current = current[subProperty]; + } else { + current = undefined; + break; + } + } + if (current !== undefined) { + if (!condition.fn(current)) return false; + continue; + } + } else if (p in data) { + const value = data[p]; + if (value !== undefined) { + if (!condition.fn(value)) return false; + continue; + } + } + if (!condition.matchWhenEmpty) { + return false; + } + } + for (const effect of rule.effects) { + if (typeof effect === "function") { + const returnedEffects = effect(data); + for (const effect of returnedEffects) { + effects.push(effect); + } + } else { + effects.push(effect); + } + } + if (rule.rules) { + for (const childRule of rule.rules) { + execRule(data, childRule, effects); + } + } + if (rule.oneOf) { + for (const childRule of rule.oneOf) { + if (execRule(data, childRule, effects)) { + break; + } + } + } + return true; + }; + + return { + references: refs, + exec: data => { + /** @type {Effect[]} */ + const effects = []; + for (const rule of rules) { + execRule(data, rule, effects); + } + return effects; + } + }; + } + + /** + * @param {string} path current path + * @param {object[]} rules the raw rules provided by user + * @param {Map<string, any>} refs references + * @returns {CompiledRule[]} rules + */ + compileRules(path, rules, refs) { + return rules + .filter(Boolean) + .map((rule, i) => this.compileRule(`${path}[${i}]`, rule, refs)); + } + + /** + * @param {string} path current path + * @param {object} rule the raw rule provided by user + * @param {Map<string, any>} refs references + * @returns {CompiledRule} normalized and compiled rule for processing + */ + compileRule(path, rule, refs) { + const unhandledProperties = new Set( + Object.keys(rule).filter(key => rule[key] !== undefined) + ); + + /** @type {CompiledRule} */ + const compiledRule = { + conditions: [], + effects: [], + rules: undefined, + oneOf: undefined + }; + + this.hooks.rule.call(path, rule, unhandledProperties, compiledRule, refs); + + if (unhandledProperties.has("rules")) { + unhandledProperties.delete("rules"); + const rules = rule.rules; + if (!Array.isArray(rules)) + throw this.error(path, rules, "Rule.rules must be an array of rules"); + compiledRule.rules = this.compileRules(`${path}.rules`, rules, refs); + } + + if (unhandledProperties.has("oneOf")) { + unhandledProperties.delete("oneOf"); + const oneOf = rule.oneOf; + if (!Array.isArray(oneOf)) + throw this.error(path, oneOf, "Rule.oneOf must be an array of rules"); + compiledRule.oneOf = this.compileRules(`${path}.oneOf`, oneOf, refs); + } + + if (unhandledProperties.size > 0) { + throw this.error( + path, + rule, + `Properties ${Array.from(unhandledProperties).join(", ")} are unknown` + ); + } + + return compiledRule; + } + + /** + * @param {string} path current path + * @param {any} condition user provided condition value + * @returns {Condition} compiled condition + */ + compileCondition(path, condition) { + if (condition === "") { + return { + matchWhenEmpty: true, + fn: str => str === "" + }; + } + if (!condition) { + throw this.error( + path, + condition, + "Expected condition but got falsy value" + ); + } + if (typeof condition === "string") { + return { + matchWhenEmpty: condition.length === 0, + fn: str => typeof str === "string" && str.startsWith(condition) + }; + } + if (typeof condition === "function") { + try { + return { + matchWhenEmpty: condition(""), + fn: condition + }; + } catch (err) { + throw this.error( + path, + condition, + "Evaluation of condition function threw error" + ); + } + } + if (condition instanceof RegExp) { + return { + matchWhenEmpty: condition.test(""), + fn: v => typeof v === "string" && condition.test(v) + }; + } + if (Array.isArray(condition)) { + const items = condition.map((c, i) => + this.compileCondition(`${path}[${i}]`, c) + ); + return this.combineConditionsOr(items); + } + + if (typeof condition !== "object") { + throw this.error( + path, + condition, + `Unexpected ${typeof condition} when condition was expected` + ); + } + + const conditions = []; + for (const key of Object.keys(condition)) { + const value = condition[key]; + switch (key) { + case "or": + if (value) { + if (!Array.isArray(value)) { + throw this.error( + `${path}.or`, + condition.and, + "Expected array of conditions" + ); + } + conditions.push(this.compileCondition(`${path}.or`, value)); + } + break; + case "and": + if (value) { + if (!Array.isArray(value)) { + throw this.error( + `${path}.and`, + condition.and, + "Expected array of conditions" + ); + } + let i = 0; + for (const item of value) { + conditions.push(this.compileCondition(`${path}.and[${i}]`, item)); + i++; + } + } + break; + case "not": + if (value) { + const matcher = this.compileCondition(`${path}.not`, value); + const fn = matcher.fn; + conditions.push({ + matchWhenEmpty: !matcher.matchWhenEmpty, + fn: v => !fn(v) + }); + } + break; + default: + throw this.error( + `${path}.${key}`, + condition[key], + `Unexpected property ${key} in condition` + ); + } + } + if (conditions.length === 0) { + throw this.error( + path, + condition, + "Expected condition, but got empty thing" + ); + } + return this.combineConditionsAnd(conditions); + } + + /** + * @param {Condition[]} conditions some conditions + * @returns {Condition} merged condition + */ + combineConditionsOr(conditions) { + if (conditions.length === 0) { + return { + matchWhenEmpty: false, + fn: () => false + }; + } else if (conditions.length === 1) { + return conditions[0]; + } else { + return { + matchWhenEmpty: conditions.some(c => c.matchWhenEmpty), + fn: v => conditions.some(c => c.fn(v)) + }; + } + } + + /** + * @param {Condition[]} conditions some conditions + * @returns {Condition} merged condition + */ + combineConditionsAnd(conditions) { + if (conditions.length === 0) { + return { + matchWhenEmpty: false, + fn: () => false + }; + } else if (conditions.length === 1) { + return conditions[0]; + } else { + return { + matchWhenEmpty: conditions.every(c => c.matchWhenEmpty), + fn: v => conditions.every(c => c.fn(v)) + }; + } + } + + /** + * @param {string} path current path + * @param {any} value value at the error location + * @param {string} message message explaining the problem + * @returns {Error} an error object + */ + error(path, value, message) { + return new Error( + `Compiling RuleSet failed: ${message} (at ${path}: ${value})` + ); + } +} + +module.exports = RuleSetCompiler; diff --git a/node_modules/webpack/lib/rules/UseEffectRulePlugin.js b/node_modules/webpack/lib/rules/UseEffectRulePlugin.js new file mode 100644 index 00000000..811d3630 --- /dev/null +++ b/node_modules/webpack/lib/rules/UseEffectRulePlugin.js @@ -0,0 +1,196 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +"use strict"; + +const util = require("util"); + +/** @typedef {import("./RuleSetCompiler")} RuleSetCompiler */ +/** @typedef {import("./RuleSetCompiler").Effect} Effect */ + +class UseEffectRulePlugin { + /** + * @param {RuleSetCompiler} ruleSetCompiler the rule set compiler + * @returns {void} + */ + apply(ruleSetCompiler) { + ruleSetCompiler.hooks.rule.tap( + "UseEffectRulePlugin", + (path, rule, unhandledProperties, result, references) => { + const conflictWith = (property, correctProperty) => { + if (unhandledProperties.has(property)) { + throw ruleSetCompiler.error( + `${path}.${property}`, + rule[property], + `A Rule must not have a '${property}' property when it has a '${correctProperty}' property` + ); + } + }; + + if (unhandledProperties.has("use")) { + unhandledProperties.delete("use"); + unhandledProperties.delete("enforce"); + + conflictWith("loader", "use"); + conflictWith("options", "use"); + + const use = rule.use; + const enforce = rule.enforce; + + const type = enforce ? `use-${enforce}` : "use"; + + /** + * + * @param {string} path options path + * @param {string} defaultIdent default ident when none is provided + * @param {object} item user provided use value + * @returns {Effect|function(any): Effect[]} effect + */ + const useToEffect = (path, defaultIdent, item) => { + if (typeof item === "function") { + return data => useToEffectsWithoutIdent(path, item(data)); + } else { + return useToEffectRaw(path, defaultIdent, item); + } + }; + + /** + * + * @param {string} path options path + * @param {string} defaultIdent default ident when none is provided + * @param {object} item user provided use value + * @returns {Effect} effect + */ + const useToEffectRaw = (path, defaultIdent, item) => { + if (typeof item === "string") { + return { + type, + value: { + loader: item, + options: undefined, + ident: undefined + } + }; + } else { + const loader = item.loader; + const options = item.options; + let ident = item.ident; + if (options && typeof options === "object") { + if (!ident) ident = defaultIdent; + references.set(ident, options); + } + if (typeof options === "string") { + util.deprecate( + () => {}, + `Using a string as loader options is deprecated (${path}.options)`, + "DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING" + )(); + } + return { + type: enforce ? `use-${enforce}` : "use", + value: { + loader, + options, + ident + } + }; + } + }; + + /** + * @param {string} path options path + * @param {any} items user provided use value + * @returns {Effect[]} effects + */ + const useToEffectsWithoutIdent = (path, items) => { + if (Array.isArray(items)) { + return items + .filter(Boolean) + .map((item, idx) => + useToEffectRaw(`${path}[${idx}]`, "[[missing ident]]", item) + ); + } + return [useToEffectRaw(path, "[[missing ident]]", items)]; + }; + + /** + * @param {string} path current path + * @param {any} items user provided use value + * @returns {(Effect|function(any): Effect[])[]} effects + */ + const useToEffects = (path, items) => { + if (Array.isArray(items)) { + return items.filter(Boolean).map((item, idx) => { + const subPath = `${path}[${idx}]`; + return useToEffect(subPath, subPath, item); + }); + } + return [useToEffect(path, path, items)]; + }; + + if (typeof use === "function") { + result.effects.push(data => + useToEffectsWithoutIdent(`${path}.use`, use(data)) + ); + } else { + for (const effect of useToEffects(`${path}.use`, use)) { + result.effects.push(effect); + } + } + } + + if (unhandledProperties.has("loader")) { + unhandledProperties.delete("loader"); + unhandledProperties.delete("options"); + unhandledProperties.delete("enforce"); + + const loader = rule.loader; + const options = rule.options; + const enforce = rule.enforce; + + if (loader.includes("!")) { + throw ruleSetCompiler.error( + `${path}.loader`, + loader, + "Exclamation mark separated loader lists has been removed in favor of the 'use' property with arrays" + ); + } + + if (loader.includes("?")) { + throw ruleSetCompiler.error( + `${path}.loader`, + loader, + "Query arguments on 'loader' has been removed in favor of the 'options' property" + ); + } + + if (typeof options === "string") { + util.deprecate( + () => {}, + `Using a string as loader options is deprecated (${path}.options)`, + "DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING" + )(); + } + + const ident = + options && typeof options === "object" ? path : undefined; + references.set(ident, options); + result.effects.push({ + type: enforce ? `use-${enforce}` : "use", + value: { + loader, + options, + ident + } + }); + } + } + ); + } + + useItemToEffects(path, item) {} +} + +module.exports = UseEffectRulePlugin; |
