diff options
author | 2020-11-16 00:10:28 +0100 | |
---|---|---|
committer | 2020-11-16 00:10:28 +0100 | |
commit | e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d (patch) | |
tree | 55713f725f77b44ebfec86e4eec3ce33e71458ca /node_modules/postcss-modules-local-by-default/index.js | |
download | website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.gz website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.bz2 website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.zip |
api, login, auth
Diffstat (limited to 'node_modules/postcss-modules-local-by-default/index.js')
-rw-r--r-- | node_modules/postcss-modules-local-by-default/index.js | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/node_modules/postcss-modules-local-by-default/index.js b/node_modules/postcss-modules-local-by-default/index.js new file mode 100644 index 0000000..09be822 --- /dev/null +++ b/node_modules/postcss-modules-local-by-default/index.js @@ -0,0 +1,364 @@ +var postcss = require('postcss'); +var Tokenizer = require('css-selector-tokenizer'); + +function normalizeNodeArray(nodes) { + var array = []; + nodes.forEach(function(x) { + if(Array.isArray(x)) { + normalizeNodeArray(x).forEach(function(item) { + array.push(item); + }); + } else if(x) { + array.push(x); + } + }); + if(array.length > 0 && array[array.length - 1].type === 'spacing') { + array.pop(); + } + return array; +} + +function localizeNode(node, context) { + if(context.ignoreNextSpacing && node.type !== 'spacing') { + throw new Error('Missing whitespace after :' + context.ignoreNextSpacing); + } + if(context.enforceNoSpacing && node.type === 'spacing') { + throw new Error('Missing whitespace before :' + context.enforceNoSpacing); + } + + var newNodes; + switch(node.type) { + case 'selectors': + var resultingGlobal; + context.hasPureGlobals = false; + newNodes = node.nodes.map(function(n) { + var nContext = { + global: context.global, + lastWasSpacing: true, + hasLocals: false, + explicit: false + }; + n = localizeNode(n, nContext); + if(typeof resultingGlobal === 'undefined') { + resultingGlobal = nContext.global; + } else if(resultingGlobal !== nContext.global) { + throw new Error('Inconsistent rule global/local result in rule "' + + Tokenizer.stringify(node) + '" (multiple selectors must result in the same mode for the rule)'); + } + if(!nContext.hasLocals) { + context.hasPureGlobals = true; + } + return n; + }); + context.global = resultingGlobal; + node = Object.create(node); + node.nodes = normalizeNodeArray(newNodes); + break; + + case 'selector': + newNodes = node.nodes.map(function(n) { + return localizeNode(n, context); + }); + node = Object.create(node); + node.nodes = normalizeNodeArray(newNodes); + break; + + case 'spacing': + if(context.ignoreNextSpacing) { + context.ignoreNextSpacing = false; + context.lastWasSpacing = false; + context.enforceNoSpacing = false; + return null; + } + context.lastWasSpacing = true; + return node; + + case 'pseudo-class': + if(node.name === 'local' || node.name === 'global') { + if(context.inside) { + throw new Error('A :' + node.name + ' is not allowed inside of a :' + context.inside + '(...)'); + } + context.ignoreNextSpacing = context.lastWasSpacing ? node.name : false; + context.enforceNoSpacing = context.lastWasSpacing ? false : node.name; + context.global = (node.name === 'global'); + context.explicit = true; + return null; + } + break; + + case 'nested-pseudo-class': + var subContext; + if(node.name === 'local' || node.name === 'global') { + if(context.inside) { + throw new Error('A :' + node.name + '(...) is not allowed inside of a :' + context.inside + '(...)'); + } + subContext = { + global: (node.name === 'global'), + inside: node.name, + hasLocals: false, + explicit: true + }; + node = node.nodes.map(function(n) { + return localizeNode(n, subContext); + }); + // don't leak spacing + node[0].before = undefined; + node[node.length - 1].after = undefined; + } else { + subContext = { + global: context.global, + inside: context.inside, + lastWasSpacing: true, + hasLocals: false, + explicit: context.explicit + }; + newNodes = node.nodes.map(function(n) { + return localizeNode(n, subContext); + }); + node = Object.create(node); + node.nodes = normalizeNodeArray(newNodes); + } + if(subContext.hasLocals) { + context.hasLocals = true; + } + break; + + case 'id': + case 'class': + if(!context.global) { + node = { + type: 'nested-pseudo-class', + name: 'local', + nodes: [node] + }; + context.hasLocals = true; + } + break; + } + + // reset context + context.lastWasSpacing = false; + context.ignoreNextSpacing = false; + context.enforceNoSpacing = false; + return node; +} + +function localizeDeclNode(node, context) { + var newNode; + switch(node.type) { + case 'item': + if(context.localizeNextItem) { + newNode = Object.create(node); + newNode.name = ':local(' + newNode.name + ')'; + context.localizeNextItem = false; + return newNode; + } + break; + + case 'nested-item': + var newNodes = node.nodes.map(function(n) { + return localizeDeclValue(n, context); + }); + node = Object.create(node); + node.nodes = newNodes; + break; + + case 'url': + if(context.options && context.options.rewriteUrl) { + newNode = Object.create(node); + newNode.url = context.options.rewriteUrl(context.global, node.url); + return newNode; + } + break; + } + return node; +} + +function localizeDeclValue(valueNode, context) { + var newValueNode = Object.create(valueNode); + newValueNode.nodes = valueNode.nodes.map(function(node) { + return localizeDeclNode(node, context); + }); + return newValueNode; +} + +function localizeAnimationShorthandDeclValueNodes(nodes, context) { + var validIdent = validIdent = /^-?[_a-z][_a-z0-9-]*$/i; + + /* + The spec defines some keywords that you can use to describe properties such as the timing + function. These are still valid animation names, so as long as there is a property that accepts + a keyword, it is given priority. Only when all the properties that can take a keyword are + exhausted can the animation name be set to the keyword. I.e. + + animation: infinite infinite; + + The animation will repeat an infinite number of times from the first argument, and will have an + animation name of infinite from the second. + */ + var animationKeywords = { + '$alternate': 1, + '$alternate-reverse': 1, + '$backwards': 1, + '$both': 1, + '$ease': 1, + '$ease-in': 1, + '$ease-in-out': 1, + '$ease-out': 1, + '$forwards': 1, + '$infinite': 1, + '$linear': 1, + '$none': Infinity, // No matter how many times you write none, it will never be an animation name + '$normal': 1, + '$paused': 1, + '$reverse': 1, + '$running': 1, + '$step-end': 1, + '$step-start': 1, + '$initial': Infinity, + '$inherit': Infinity, + '$unset': Infinity, + }; + + var didParseAnimationName = false; + var parsedAnimationKeywords = {}; + return nodes.map(function(valueNode) { + var value = valueNode.type === 'item' + ? valueNode.name.toLowerCase() + : null; + + var shouldParseAnimationName = false; + + if (!didParseAnimationName && value && validIdent.test(value)) { + if ('$' + value in animationKeywords) { + parsedAnimationKeywords['$' + value] = ('$' + value in parsedAnimationKeywords) + ? (parsedAnimationKeywords['$' + value] + 1) + : 0; + + shouldParseAnimationName = (parsedAnimationKeywords['$' + value] >= animationKeywords['$' + value]); + } else { + shouldParseAnimationName = true; + } + } + + var subContext = { + options: context.options, + global: context.global, + localizeNextItem: shouldParseAnimationName && !context.global + }; + return localizeDeclNode(valueNode, subContext); + }); +} + +function localizeAnimationShorthandDeclValues(valuesNode, decl, context) { + var newValuesNode = Object.create(valuesNode); + newValuesNode.nodes = valuesNode.nodes.map(function(valueNode, index) { + var newValueNode = Object.create(valueNode); + newValueNode.nodes = localizeAnimationShorthandDeclValueNodes(valueNode.nodes, context); + return newValueNode; + }); + decl.value = Tokenizer.stringifyValues(newValuesNode); +} + +function localizeDeclValues(localize, valuesNode, decl, context) { + var newValuesNode = Object.create(valuesNode); + newValuesNode.nodes = valuesNode.nodes.map(function(valueNode) { + var subContext = { + options: context.options, + global: context.global, + localizeNextItem: localize && !context.global + }; + return localizeDeclValue(valueNode, subContext); + }); + decl.value = Tokenizer.stringifyValues(newValuesNode); +} + +function localizeDecl(decl, context) { + var valuesNode = Tokenizer.parseValues(decl.value); + + var isAnimation = /animation?$/.test(decl.prop); + if (isAnimation) return localizeAnimationShorthandDeclValues(valuesNode, decl, context); + + var isAnimationName = /animation(-name)?$/.test(decl.prop); + if (isAnimationName) return localizeDeclValues(true, valuesNode, decl, context); + + return localizeDeclValues(false, valuesNode, decl, context); +} + +module.exports = postcss.plugin('postcss-modules-local-by-default', function (options) { + if (typeof options !== 'object') { + options = {}; // If options is undefined or not an object the plugin fails + } + if(options && options.mode) { + if(options.mode !== 'global' && options.mode !== 'local' && options.mode !== 'pure') { + throw new Error('options.mode must be either "global", "local" or "pure" (default "local")'); + } + } + var pureMode = options && options.mode === 'pure'; + var globalMode = options && options.mode === 'global'; + return function(css) { + css.walkAtRules(function(atrule) { + if(/keyframes$/.test(atrule.name)) { + var globalMatch = /^\s*:global\s*\((.+)\)\s*$/.exec(atrule.params); + var localMatch = /^\s*:local\s*\((.+)\)\s*$/.exec(atrule.params); + var globalKeyframes = globalMode; + if(globalMatch) { + if(pureMode) { + throw atrule.error('@keyframes :global(...) is not allowed in pure mode'); + } + atrule.params = globalMatch[1]; + globalKeyframes = true; + } else if(localMatch) { + atrule.params = localMatch[0]; + globalKeyframes = false; + } else if(!globalMode) { + atrule.params = ':local(' + atrule.params + ')'; + } + atrule.walkDecls(function(decl) { + localizeDecl(decl, { + options: options, + global: globalKeyframes + }); + }); + } else if(atrule.nodes) { + atrule.nodes.forEach(function(decl) { + if(decl.type === 'decl') { + localizeDecl(decl, { + options: options, + global: globalMode + }); + } + }); + } + }); + css.walkRules(function(rule) { + if(rule.parent.type === 'atrule' && /keyframes$/.test(rule.parent.name)) { + // ignore keyframe rules + return; + } + var selector = Tokenizer.parse(rule.selector); + var context = { + options: options, + global: globalMode, + hasPureGlobals: false + }; + var newSelector; + try { + newSelector = localizeNode(selector, context); + } catch(e) { + throw rule.error(e.message); + } + if(pureMode && context.hasPureGlobals) { + throw rule.error('Selector "' + Tokenizer.stringify(selector) + '" is not pure ' + + '(pure selectors must contain at least one local class or id)'); + } + // Less-syntax mixins parse as rules with no nodes + if (rule.nodes) { + rule.nodes.forEach(function(decl) { + localizeDecl(decl, context); + }); + } + rule.selector = Tokenizer.stringify(newSelector); + }); + }; +}); |