From a112c8bdb4c9ef14802e991636ade1d2ebd9d814 Mon Sep 17 00:00:00 2001 From: Jason Quense Date: Mon, 18 Feb 2019 08:51:11 -0500 Subject: [PATCH 1/3] WIP --- index.js | 43 +++++++++++++++++++++++++++++---- package.json | 1 + test.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ yarn.lock | 35 +++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index c6f963f..4d7cfc2 100644 --- a/index.js +++ b/index.js @@ -6,6 +6,21 @@ const valueParser = require('postcss-value-parser'); const isSpacing = node => node.type === 'combinator' && node.value === ' '; +function getImportLocalAliases(icssImports) { + const localAliases = new Map(); + Object.keys(icssImports).forEach((key) => { + Object.keys(icssImports[key]).forEach((prop) => { + localAliases.set(prop, icssImports[key][prop]) + }) + }) + return localAliases; +} + +function maybeLocalizeValue(value, localAliasMap) { + if (localAliasMap.has(value)) return value +} + + function normalizeNodeArray(nodes) { const array = []; @@ -191,7 +206,11 @@ function localizeNode(rule, mode, options) { } case 'id': case 'class': { - if (!context.global) { + const isGlobalImportedValue = !context.inside && context.localAliasMap.has(node.name) + + // console.log('HERE', node) + if (!context.global && !isGlobalImportedValue) { + const innerNode = node.clone(); innerNode.spaces = { before: '', after: '' }; @@ -231,8 +250,12 @@ function localizeDeclNode(node, context) { switch (node.type) { case 'word': if (context.localizeNextItem) { - node.value = ':local(' + node.value + ')'; - context.localizeNextItem = false; + console.log('HERE', context, node.value) + if (!context.localAliasMap.has(node.value)) { + + node.value = ':local(' + node.value + ')'; + context.localizeNextItem = false; + } } break; @@ -360,6 +383,7 @@ function localizeAnimationShorthandDeclValues(decl, context) { options: context.options, global: context.global, localizeNextItem: shouldParseAnimationName && !context.global, + localAliasMap: context.localAliasMap, }; return localizeDeclNode(node, subContext); }); @@ -374,6 +398,7 @@ function localizeDeclValues(localize, decl, context) { options: context.options, global: context.global, localizeNextItem: localize && !context.global, + localAliasMap: context.localAliasMap, }; nodes[index] = localizeDeclNode(node, subContext); }); @@ -423,6 +448,9 @@ module.exports = postcss.plugin('postcss-modules-local-by-default', function( const globalMode = options && options.mode === 'global'; return function(css) { + const { icssImports } = extractICSS(css, false); + const localAliasMap = getImportLocalAliases(icssImports) + css.walkAtRules(function(atrule) { if (/keyframes$/i.test(atrule.name)) { const globalMatch = /^\s*:global\s*\((.+)\)\s*$/.exec(atrule.params); @@ -440,10 +468,13 @@ module.exports = postcss.plugin('postcss-modules-local-by-default', function( atrule.params = localMatch[0]; globalKeyframes = false; } else if (!globalMode) { - atrule.params = ':local(' + atrule.params + ')'; + // console.log('HERE', context) + if (!localAliasMap.has(atrule.params)) + atrule.params = ':local(' + atrule.params + ')'; } atrule.walkDecls(function(decl) { localizeDecl(decl, { + localAliasMap, options: options, global: globalKeyframes, }); @@ -452,6 +483,7 @@ module.exports = postcss.plugin('postcss-modules-local-by-default', function( atrule.nodes.forEach(function(decl) { if (decl.type === 'decl') { localizeDecl(decl, { + localAliasMap, options: options, global: globalMode, }); @@ -478,7 +510,8 @@ module.exports = postcss.plugin('postcss-modules-local-by-default', function( return; } - const context = localizeNode(rule, options.mode); + const context = localizeNode(rule, options.mode, + localAliasMap); context.options = options; diff --git a/package.json b/package.json index a1f0f2a..77c54cc 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "trailingComma": "es5" }, "dependencies": { + "icss-utils": "^4.0.0", "postcss": "^7.0.6", "postcss-selector-parser": "^6.0.0", "postcss-value-parser": "^3.3.1" diff --git a/test.js b/test.js index c71bea6..563476e 100644 --- a/test.js +++ b/test.js @@ -532,6 +532,74 @@ const tests = [ input: ':root { --title-align: center; --sr-only: { position: absolute; } }', expected: ':root { --title-align: center; --sr-only: { position: absolute; } }', }, + /** + * Imported aliases + */ + { + should: 'not localize imported alias', + input: ` + :import(foo) { a_value: some-value; } + + .foo > .a_value { } + `, + expected: ` + :import(foo) { a_value: some-value; } + + :local(.foo) > .a_value { } + ` + }, + { + should: 'not localize nested imported alias', + input: ` + :import(foo) { a_value: some-value; } + + .foo > .a_value > .bar { } + `, + expected: ` + :import(foo) { a_value: some-value; } + + :local(.foo) > .a_value > :local(.bar) { } + ` + }, + { + should: 'not localize open ended imported alias', + input: ` + :import(foo) { a_value: some-value; } + + :local .foo .a_value .bar { } + `, + expected: ` + :import(foo) { a_value: some-value; } + + :local(.foo) .a_value :local(.bar) { } + ` + }, + { + should: 'ignore imported in explicit local', + input: ` + :import(foo) { a_value: some-value; } + + :local(.a_value) { } + `, + expected: ` + :import(foo) { a_value: some-value; } + + :local(.a_value) { } + ` + }, + { + should: 'maintain explicit local', + input: ` + :import(foo) { a_value: some-value; } + + :local(.a_value, .foo) .a_value { } + `, + expected: ` + :import(foo) { a_value: some-value; } + + :local(.a_value) :local(.foo) .a_value { } + ` + } ]; function process(css, options) { diff --git a/yarn.lock b/yarn.lock index 62bce72..99860aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -324,6 +324,15 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -1221,6 +1230,13 @@ iconv-lite@^0.4.24, iconv-lite@^0.4.4: dependencies: safer-buffer ">= 2.1.2 < 3" +icss-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.0.0.tgz#d52cf4bcdcfa1c45c2dbefb4ffdf6b00ef608098" + integrity sha512-bA/xGiwWM17qjllIs9X/y0EjsB7e0AV08F3OL8UPsoNkNRibIuu8f1eKTnQ8QO1DteKKTxTUAn+IEWUToIwGOA== + dependencies: + postcss "^7.0.5" + ignore-walk@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" @@ -2098,6 +2114,15 @@ postcss-value-parser@^3.3.1: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== +postcss@^7.0.5: + version "7.0.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" + integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + postcss@^7.0.6: version "7.0.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" @@ -2644,6 +2669,16 @@ supports-color@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== +<<<<<<< HEAD +======= + dependencies: + has-flag "^3.0.0" + +table@^5.0.2: + version "5.1.1" + resolved "https://registry.yarnpkg.com/table/-/table-5.1.1.tgz#92030192f1b7b51b6eeab23ed416862e47b70837" + integrity sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw== +>>>>>>> WIP dependencies: has-flag "^3.0.0" From f95be60683c931065242e414d6540ee9fa3ba189 Mon Sep 17 00:00:00 2001 From: Jason Quense Date: Thu, 7 Mar 2019 08:51:05 -0500 Subject: [PATCH 2/3] feat: don't localize imported values in selectors --- index.js | 34 +++++++++++++++++----------------- test.js | 50 +++++++++++++++++++++++++++++++++----------------- yarn.lock | 30 +----------------------------- 3 files changed, 51 insertions(+), 63 deletions(-) diff --git a/index.js b/index.js index 4d7cfc2..22fd961 100644 --- a/index.js +++ b/index.js @@ -3,24 +3,24 @@ const postcss = require('postcss'); const selectorParser = require('postcss-selector-parser'); const valueParser = require('postcss-value-parser'); +const { extractICSS } = require('icss-utils'); const isSpacing = node => node.type === 'combinator' && node.value === ' '; function getImportLocalAliases(icssImports) { const localAliases = new Map(); - Object.keys(icssImports).forEach((key) => { - Object.keys(icssImports[key]).forEach((prop) => { - localAliases.set(prop, icssImports[key][prop]) - }) - }) + Object.keys(icssImports).forEach(key => { + Object.keys(icssImports[key]).forEach(prop => { + localAliases.set(prop, icssImports[key][prop]); + }); + }); return localAliases; } function maybeLocalizeValue(value, localAliasMap) { - if (localAliasMap.has(value)) return value + if (localAliasMap.has(value)) return value; } - function normalizeNodeArray(nodes) { const array = []; @@ -40,7 +40,7 @@ function normalizeNodeArray(nodes) { return array; } -function localizeNode(rule, mode, options) { +function localizeNode(rule, mode, localAliasMap) { const isScopePseudo = node => node.value === ':local' || node.value === ':global'; @@ -206,11 +206,14 @@ function localizeNode(rule, mode, options) { } case 'id': case 'class': { - const isGlobalImportedValue = !context.inside && context.localAliasMap.has(node.name) + if (context.global) { + break; + } - // console.log('HERE', node) - if (!context.global && !isGlobalImportedValue) { + const isImportedValue = localAliasMap.has(node.value); + const isImportedWithExplicitScope = isImportedValue && context.explicit; + if (!isImportedValue || isImportedWithExplicitScope) { const innerNode = node.clone(); innerNode.spaces = { before: '', after: '' }; @@ -250,9 +253,7 @@ function localizeDeclNode(node, context) { switch (node.type) { case 'word': if (context.localizeNextItem) { - console.log('HERE', context, node.value) if (!context.localAliasMap.has(node.value)) { - node.value = ':local(' + node.value + ')'; context.localizeNextItem = false; } @@ -449,7 +450,7 @@ module.exports = postcss.plugin('postcss-modules-local-by-default', function( return function(css) { const { icssImports } = extractICSS(css, false); - const localAliasMap = getImportLocalAliases(icssImports) + const localAliasMap = getImportLocalAliases(icssImports); css.walkAtRules(function(atrule) { if (/keyframes$/i.test(atrule.name)) { @@ -468,7 +469,6 @@ module.exports = postcss.plugin('postcss-modules-local-by-default', function( atrule.params = localMatch[0]; globalKeyframes = false; } else if (!globalMode) { - // console.log('HERE', context) if (!localAliasMap.has(atrule.params)) atrule.params = ':local(' + atrule.params + ')'; } @@ -510,10 +510,10 @@ module.exports = postcss.plugin('postcss-modules-local-by-default', function( return; } - const context = localizeNode(rule, options.mode, - localAliasMap); + const context = localizeNode(rule, options.mode, localAliasMap); context.options = options; + context.localAliasMap = localAliasMap; if (pureMode && context.hasPureGlobals) { throw rule.error( diff --git a/test.js b/test.js index 563476e..bdcb9ce 100644 --- a/test.js +++ b/test.js @@ -529,8 +529,10 @@ const tests = [ }, { should: 'not ignore custom property set', - input: ':root { --title-align: center; --sr-only: { position: absolute; } }', - expected: ':root { --title-align: center; --sr-only: { position: absolute; } }', + input: + ':root { --title-align: center; --sr-only: { position: absolute; } }', + expected: + ':root { --title-align: center; --sr-only: { position: absolute; } }', }, /** * Imported aliases @@ -546,7 +548,7 @@ const tests = [ :import(foo) { a_value: some-value; } :local(.foo) > .a_value { } - ` + `, }, { should: 'not localize nested imported alias', @@ -559,47 +561,61 @@ const tests = [ :import(foo) { a_value: some-value; } :local(.foo) > .a_value > :local(.bar) { } - ` + `, }, + { - should: 'not localize open ended imported alias', + should: 'ignore imported in explicit local', input: ` :import(foo) { a_value: some-value; } - :local .foo .a_value .bar { } + :local(.a_value) { } `, expected: ` :import(foo) { a_value: some-value; } - :local(.foo) .a_value :local(.bar) { } - ` + :local(.a_value) { } + `, }, { - should: 'ignore imported in explicit local', + should: 'escape local context with explict global', input: ` :import(foo) { a_value: some-value; } - :local(.a_value) { } + :local .foo :global(.a_value) .bar { } `, expected: ` :import(foo) { a_value: some-value; } - :local(.a_value) { } - ` + :local(.foo) .a_value :local(.bar) { } + `, }, { - should: 'maintain explicit local', + should: 'respect explicit local', input: ` :import(foo) { a_value: some-value; } - :local(.a_value, .foo) .a_value { } + .a_value :local .a_value .foo :global .a_value { } `, expected: ` :import(foo) { a_value: some-value; } - :local(.a_value) :local(.foo) .a_value { } - ` - } + .a_value :local(.a_value) :local(.foo) .a_value { } + `, + }, + { + should: 'not localize imported animation-name', + input: ` + :import(file) { a_value: some-value; } + + .foo { animation-name: a_value; } + `, + expected: ` + :import(file) { a_value: some-value; } + + :local(.foo) { animation-name: a_value; } + `, + }, ]; function process(css, options) { diff --git a/yarn.lock b/yarn.lock index 99860aa..90d5743 100644 --- a/yarn.lock +++ b/yarn.lock @@ -324,15 +324,6 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -2114,16 +2105,7 @@ postcss-value-parser@^3.3.1: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss@^7.0.5: - version "7.0.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" - integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - -postcss@^7.0.6: +postcss@^7.0.5, postcss@^7.0.6: version "7.0.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg== @@ -2669,16 +2651,6 @@ supports-color@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== -<<<<<<< HEAD -======= - dependencies: - has-flag "^3.0.0" - -table@^5.0.2: - version "5.1.1" - resolved "https://registry.yarnpkg.com/table/-/table-5.1.1.tgz#92030192f1b7b51b6eeab23ed416862e47b70837" - integrity sha512-NUjapYb/qd4PeFW03HnAuOJ7OMcBkJlqeClWxeNlQ0lXGSb52oZXGzkO0/I0ARegQ2eUT1g2VDJH0eUxDRcHmw== ->>>>>>> WIP dependencies: has-flag "^3.0.0" From d1c211126d04934e1efc4769a2b32cc454a245aa Mon Sep 17 00:00:00 2001 From: Jason Quense Date: Thu, 7 Mar 2019 09:11:52 -0500 Subject: [PATCH 3/3] check for params --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 22fd961..2acedea 100644 --- a/index.js +++ b/index.js @@ -469,7 +469,7 @@ module.exports = postcss.plugin('postcss-modules-local-by-default', function( atrule.params = localMatch[0]; globalKeyframes = false; } else if (!globalMode) { - if (!localAliasMap.has(atrule.params)) + if (atrule.params && !localAliasMap.has(atrule.params)) atrule.params = ':local(' + atrule.params + ')'; } atrule.walkDecls(function(decl) {