From b5d93b6abd5616f68efda3bba290eee28a205d4c Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Thu, 30 Jul 2015 21:13:12 +1000 Subject: [PATCH 1/8] got a reasonable test case to start thinking about this --- test/test-cases/media-queries/breakpoints.css | 3 +++ test/test-cases/media-queries/expected.css | 21 ++++++++++++++++ test/test-cases/media-queries/expected.json | 3 +++ test/test-cases/media-queries/source.css | 25 +++++++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 test/test-cases/media-queries/breakpoints.css create mode 100644 test/test-cases/media-queries/expected.css create mode 100644 test/test-cases/media-queries/expected.json create mode 100644 test/test-cases/media-queries/source.css diff --git a/test/test-cases/media-queries/breakpoints.css b/test/test-cases/media-queries/breakpoints.css new file mode 100644 index 0000000..a3f23cf --- /dev/null +++ b/test/test-cases/media-queries/breakpoints.css @@ -0,0 +1,3 @@ +@custom-media --small (max-width: 30em); +@custom-media --medium (max-width: 60em); +@custom-media --large (max-width: 90em); diff --git a/test/test-cases/media-queries/expected.css b/test/test-cases/media-queries/expected.css new file mode 100644 index 0000000..191f331 --- /dev/null +++ b/test/test-cases/media-queries/expected.css @@ -0,0 +1,21 @@ +._media-queries_source__red { + color: red; +} + +@media (max-width: 30em) { + ._media-queries_source__red { + color: maroon; + } +} + +@media (max-width: 60em) { + ._media-queries_source__red { + color: darkmagenta; + } +} + +@media (max-width: 90em) { + ._media-queries_source__red { + color: fuchsia; + } +} diff --git a/test/test-cases/media-queries/expected.json b/test/test-cases/media-queries/expected.json new file mode 100644 index 0000000..7e71621 --- /dev/null +++ b/test/test-cases/media-queries/expected.json @@ -0,0 +1,3 @@ +{ + "red": "_media-queries_source__red" +} diff --git a/test/test-cases/media-queries/source.css b/test/test-cases/media-queries/source.css new file mode 100644 index 0000000..e4a1283 --- /dev/null +++ b/test/test-cases/media-queries/source.css @@ -0,0 +1,25 @@ +@custom-media --small from "./breakpoints.css"; +@custom-media --medium from "./breakpoints.css"; +@custom-media --large from "./breakpoints.css"; + +.red { + color: red; +} + +@media (--small) { + .red { + color: maroon; + } +} + +@media (--medium) { + .red { + color: darkmagenta; + } +} + +@media (--large) { + .red { + color: fuchsia; + } +} From 0bf11a965ca80e1e07852eea8a4af68f414aba43 Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Tue, 4 Aug 2015 16:44:01 +1000 Subject: [PATCH 2/8] wip --- test/cssi/media-queries/breakpoints.css | 9 ++++++ test/cssi/media-queries/expected.css | 25 ++++++++++++++++ test/cssi/media-queries/expected.json | 5 ++++ test/cssi/media-queries/source.css | 37 ++++++++++++++++++++++++ test/test-cases/media-queries/source.css | 2 +- 5 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 test/cssi/media-queries/breakpoints.css create mode 100644 test/cssi/media-queries/expected.css create mode 100644 test/cssi/media-queries/expected.json create mode 100644 test/cssi/media-queries/source.css diff --git a/test/cssi/media-queries/breakpoints.css b/test/cssi/media-queries/breakpoints.css new file mode 100644 index 0000000..b76ae77 --- /dev/null +++ b/test/cssi/media-queries/breakpoints.css @@ -0,0 +1,9 @@ +:exports { + --small: --x__breakpoints__small; + --medium: --x__breakpoints__medium; + --large: --x__breakpoints__large; +} + +@custom-media --x__breakpoints__small (max-width: 30em); +@custom-media --x__breakpoints__medium (max-width: 60em); +@custom-media --x__breakpoints__large (max-width: 90em); diff --git a/test/cssi/media-queries/expected.css b/test/cssi/media-queries/expected.css new file mode 100644 index 0000000..38f3e03 --- /dev/null +++ b/test/cssi/media-queries/expected.css @@ -0,0 +1,25 @@ +@custom-media --x__source__small (max-width: 30em); +@custom-media --x__source__medium (max-width: 60em); +@custom-media --x__source__large (max-width: 90em); + +._media-queries_source__red { + color: red; +} + +@media (max-width: 30em) { + ._media-queries_source__red { + color: maroon; + } +} + +@media (max-width: 60em) { + ._media-queries_source__red { + color: darkmagenta; + } +} + +@media (max-width: 90em) { + ._media-queries_source__red { + color: fuchsia; + } +} diff --git a/test/cssi/media-queries/expected.json b/test/cssi/media-queries/expected.json new file mode 100644 index 0000000..2d455f0 --- /dev/null +++ b/test/cssi/media-queries/expected.json @@ -0,0 +1,5 @@ +{ + "--small": "--x__source__small", + "--medium": "--x__source__medium", + "--large": "--x__source__large" +} diff --git a/test/cssi/media-queries/source.css b/test/cssi/media-queries/source.css new file mode 100644 index 0000000..cc66b21 --- /dev/null +++ b/test/cssi/media-queries/source.css @@ -0,0 +1,37 @@ +:imports("./breakpoints.css") { + --i__breakpoints__small: --small; + --i__breakpoints__medium: --medium; + --i__breakpoints__large: --large; +} + +:exports { + --small: --x__source__small; + --medium: --x__source__medium; + --large: --x__source__large; +} + +@custom-media --x__source__small --i__breakpoints__small; +@custom-media --x__source__medium --i__breakpoints__medium; +@custom-media --x__source__large --i__breakpoints__large; + +.red { + color: red; +} + +@media (--x__source__small) { + .red { + color: maroon; + } +} + +@media (--x__source__medium) { + .red { + color: darkmagenta; + } +} + +@media (--x__source__large) { + .red { + color: fuchsia; + } +} diff --git a/test/test-cases/media-queries/source.css b/test/test-cases/media-queries/source.css index e4a1283..d354d27 100644 --- a/test/test-cases/media-queries/source.css +++ b/test/test-cases/media-queries/source.css @@ -1,6 +1,6 @@ @custom-media --small from "./breakpoints.css"; @custom-media --medium from "./breakpoints.css"; -@custom-media --large from "./breakpoints.css"; +@custom-media --large (min-width: 90em); .red { color: red; From abe7bf99fefdcb51f02de5a4fc0d06ac57768cbc Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Mon, 10 Aug 2015 18:59:17 +1000 Subject: [PATCH 3/8] actually got the expectations in line with the plugins --- test/cssi/media-queries/breakpoints.css | 12 ++++---- test/cssi/media-queries/expected.css | 20 ++++++------- test/cssi/media-queries/source.css | 37 +++++++++++++------------ 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/test/cssi/media-queries/breakpoints.css b/test/cssi/media-queries/breakpoints.css index b76ae77..6fc05ff 100644 --- a/test/cssi/media-queries/breakpoints.css +++ b/test/cssi/media-queries/breakpoints.css @@ -1,9 +1,9 @@ :exports { - --small: --x__breakpoints__small; - --medium: --x__breakpoints__medium; - --large: --x__breakpoints__large; + --small: "(max-width: 30em)"; + --medium: "(max-width: 60em)"; + --large: "(max-width: 90em)"; } -@custom-media --x__breakpoints__small (max-width: 30em); -@custom-media --x__breakpoints__medium (max-width: 60em); -@custom-media --x__breakpoints__large (max-width: 90em); +@custom-media --small (max-width: 30em); +@custom-media --medium (max-width: 60em); +@custom-media --large (max-width: 90em); diff --git a/test/cssi/media-queries/expected.css b/test/cssi/media-queries/expected.css index 38f3e03..1889bf5 100644 --- a/test/cssi/media-queries/expected.css +++ b/test/cssi/media-queries/expected.css @@ -1,25 +1,25 @@ -@custom-media --x__source__small (max-width: 30em); -@custom-media --x__source__medium (max-width: 60em); -@custom-media --x__source__large (max-width: 90em); +@custom-media --small (max-width: 30em); +@custom-media --medium (max-width: 60em); +@custom-media --large (max-width: 90em); -._media-queries_source__red { +.exported-red { color: red; } -@media (max-width: 30em) { - ._media-queries_source__red { +@media (--small) { + .exported-red { color: maroon; } } -@media (max-width: 60em) { - ._media-queries_source__red { +@media (--medium) { + .exported-red { color: darkmagenta; } } -@media (max-width: 90em) { - ._media-queries_source__red { +@media (--large) { + .exported-red { color: fuchsia; } } diff --git a/test/cssi/media-queries/source.css b/test/cssi/media-queries/source.css index cc66b21..222ce70 100644 --- a/test/cssi/media-queries/source.css +++ b/test/cssi/media-queries/source.css @@ -1,37 +1,38 @@ -:imports("./breakpoints.css") { - --i__breakpoints__small: --small; - --i__breakpoints__medium: --medium; - --i__breakpoints__large: --large; +:import("./breakpoints.css") { + i__breakpoints__small: --small; + i__breakpoints__medium: --medium; + i__breakpoints__large: --large; } -:exports { - --small: --x__source__small; - --medium: --x__source__medium; - --large: --x__source__large; +:export { + --small: i__breakpoints__small; + --medium: i__breakpoints__medium; + --large: i__breakpoints__large; + red: exported-red; } -@custom-media --x__source__small --i__breakpoints__small; -@custom-media --x__source__medium --i__breakpoints__medium; -@custom-media --x__source__large --i__breakpoints__large; +@custom-media --small i__breakpoints__small; +@custom-media --medium i__breakpoints__medium; +@custom-media --large i__breakpoints__large; -.red { +.exported-red { color: red; } -@media (--x__source__small) { - .red { +@media (--small) { + .exported-red { color: maroon; } } -@media (--x__source__medium) { - .red { +@media (--medium) { + .exported-red { color: darkmagenta; } } -@media (--x__source__large) { - .red { +@media (--large) { + .exported-red { color: fuchsia; } } From 464b5d8b8c9afd2eecd8adc6c85529941ffca160 Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Tue, 11 Aug 2015 09:35:49 +1000 Subject: [PATCH 4/8] ICSS test case passing! --- src/parser.js | 18 +++++++++++++----- test/cssi/media-queries/breakpoints.css | 2 +- test/cssi/media-queries/expected.css | 3 +++ test/cssi/media-queries/expected.json | 7 ++++--- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/parser.js b/src/parser.js index 536e9cd..aa1559c 100644 --- a/src/parser.js +++ b/src/parser.js @@ -26,10 +26,18 @@ export default class Parser { } linkImportedSymbols( css ) { - css.eachDecl( decl => { - Object.keys(this.translations).forEach( translation => { - decl.value = decl.value.replace(translation, this.translations[translation]) - } ) + css.eachInside( node => { + if ( node.type === "decl" ) { + this.replaceOccurrences( node, "value" ) + } else if ( node.type === "atrule" && node.name === "custom-media" ) { + this.replaceOccurrences( node, "params" ) + } + }) + } + + replaceOccurrences( node, prop ) { + Object.keys(this.translations).forEach(translation => { + node[prop] = node[prop].replace(translation, this.translations[translation]) }) } @@ -57,7 +65,7 @@ export default class Parser { return this.pathFetcher( file, relativeTo, depTrace ).then( exports => { importNode.each( decl => { if ( decl.type == 'decl' ) { - this.translations[decl.prop] = exports[decl.value] + this.translations[decl.prop] = exports[decl.value].replace(/^['"]|['"]$/g,'') } } ) importNode.removeSelf() diff --git a/test/cssi/media-queries/breakpoints.css b/test/cssi/media-queries/breakpoints.css index 6fc05ff..d18fcf8 100644 --- a/test/cssi/media-queries/breakpoints.css +++ b/test/cssi/media-queries/breakpoints.css @@ -1,4 +1,4 @@ -:exports { +:export { --small: "(max-width: 30em)"; --medium: "(max-width: 60em)"; --large: "(max-width: 90em)"; diff --git a/test/cssi/media-queries/expected.css b/test/cssi/media-queries/expected.css index 1889bf5..943c6a9 100644 --- a/test/cssi/media-queries/expected.css +++ b/test/cssi/media-queries/expected.css @@ -1,6 +1,9 @@ @custom-media --small (max-width: 30em); @custom-media --medium (max-width: 60em); @custom-media --large (max-width: 90em); +@custom-media --small (max-width: 30em); +@custom-media --medium (max-width: 60em); +@custom-media --large (max-width: 90em); .exported-red { color: red; diff --git a/test/cssi/media-queries/expected.json b/test/cssi/media-queries/expected.json index 2d455f0..77e6a8e 100644 --- a/test/cssi/media-queries/expected.json +++ b/test/cssi/media-queries/expected.json @@ -1,5 +1,6 @@ { - "--small": "--x__source__small", - "--medium": "--x__source__medium", - "--large": "--x__source__large" + "--small": "(max-width: 30em)", + "--medium": "(max-width: 60em)", + "--large": "(max-width: 90em)", + "red": "exported-red" } From d65b0800895b9e06c503b38f36197a847fa1b326 Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Tue, 11 Aug 2015 12:20:06 +1000 Subject: [PATCH 5/8] media queries test passing! --- src/index.js | 1 - src/parser.js | 9 +++++++-- test/test-cases/media-queries/breakpoints.css | 1 - test/test-cases/media-queries/expected.css | 20 ++++++++++++------- test/test-cases/media-queries/expected.json | 5 ++++- test/test-cases/media-queries/source.css | 2 +- 6 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/index.js b/src/index.js index f5994ef..d3533d8 100644 --- a/src/index.js +++ b/src/index.js @@ -21,7 +21,6 @@ export default class Core { } } - // These three plugins are aliased under this package for simplicity. Core.localByDefault = localByDefault Core.extractImports = extractImports diff --git a/src/parser.js b/src/parser.js index aa1559c..56a3a25 100644 --- a/src/parser.js +++ b/src/parser.js @@ -53,7 +53,7 @@ export default class Parser { Object.keys(this.translations).forEach( translation => { decl.value = decl.value.replace(translation, this.translations[translation]) } ) - this.exportTokens[decl.prop] = decl.value + this.exportTokens[decl.prop] = decl.value.replace(/^['"]|['"]$/g, '') } } ) exportNode.removeSelf() @@ -65,7 +65,12 @@ export default class Parser { return this.pathFetcher( file, relativeTo, depTrace ).then( exports => { importNode.each( decl => { if ( decl.type == 'decl' ) { - this.translations[decl.prop] = exports[decl.value].replace(/^['"]|['"]$/g,'') + let translation = exports[decl.value] + if ( translation ) { + this.translations[decl.prop] = translation.replace(/^['"]|['"]$/g, '') + } else { + console.warn( `Missing ${decl.value} for ${decl.prop}` ) + } } } ) importNode.removeSelf() diff --git a/test/test-cases/media-queries/breakpoints.css b/test/test-cases/media-queries/breakpoints.css index a3f23cf..158d1f2 100644 --- a/test/test-cases/media-queries/breakpoints.css +++ b/test/test-cases/media-queries/breakpoints.css @@ -1,3 +1,2 @@ @custom-media --small (max-width: 30em); @custom-media --medium (max-width: 60em); -@custom-media --large (max-width: 90em); diff --git a/test/test-cases/media-queries/expected.css b/test/test-cases/media-queries/expected.css index 191f331..fc612cd 100644 --- a/test/test-cases/media-queries/expected.css +++ b/test/test-cases/media-queries/expected.css @@ -1,21 +1,27 @@ -._media-queries_source__red { +@custom-media --small (max-width: 30em); +@custom-media --medium (max-width: 60em); +@custom-media --small (max-width: 30em); +@custom-media --medium (max-width: 60em); +@custom-media --large (max-width: 90em); + +._media_queries_source__red { color: red; } -@media (max-width: 30em) { - ._media-queries_source__red { +@media (--small) { + ._media_queries_source__red { color: maroon; } } -@media (max-width: 60em) { - ._media-queries_source__red { +@media (--medium) { + ._media_queries_source__red { color: darkmagenta; } } -@media (max-width: 90em) { - ._media-queries_source__red { +@media (--large) { + ._media_queries_source__red { color: fuchsia; } } diff --git a/test/test-cases/media-queries/expected.json b/test/test-cases/media-queries/expected.json index 7e71621..8f5c598 100644 --- a/test/test-cases/media-queries/expected.json +++ b/test/test-cases/media-queries/expected.json @@ -1,3 +1,6 @@ { - "red": "_media-queries_source__red" + "red": "_media_queries_source__red", + "--small": "(max-width: 30em)", + "--medium": "(max-width: 60em)", + "--large": "(max-width: 90em)" } diff --git a/test/test-cases/media-queries/source.css b/test/test-cases/media-queries/source.css index d354d27..5c1058e 100644 --- a/test/test-cases/media-queries/source.css +++ b/test/test-cases/media-queries/source.css @@ -1,6 +1,6 @@ @custom-media --small from "./breakpoints.css"; @custom-media --medium from "./breakpoints.css"; -@custom-media --large (min-width: 90em); +@custom-media --large (max-width: 90em); .red { color: red; From 40d5c2a5dbcf7d4d9681dfaa02a0be0bbdb89f33 Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Tue, 11 Aug 2015 14:11:32 +1000 Subject: [PATCH 6/8] added postcss-custom-media as a postlinker plugin and custom media queries disappear! --- package.json | 1 + src/file-system-loader.js | 4 ++-- src/index.js | 15 +++++++++++---- test/test-cases.js | 2 +- test/test-cases/media-queries/expected.css | 11 +++-------- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index ecec1f9..9a7d06f 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "postcss": "^4.1.11", + "postcss-custom-media": "^4.1.0", "postcss-modules-extract-imports": "^0.0.5", "postcss-modules-local-by-default": "^0.0.9", "postcss-modules-scope": "^0.0.8" diff --git a/src/file-system-loader.js b/src/file-system-loader.js index 2a3f47d..4beb2f1 100644 --- a/src/file-system-loader.js +++ b/src/file-system-loader.js @@ -20,11 +20,11 @@ const traceKeySorter = ( a, b ) => { }; export default class FileSystemLoader { - constructor( root, plugins ) { + constructor( root, plugins, postLinkers ) { this.root = root this.sources = {} this.importNr = 0 - this.core = new Core(plugins) + this.core = new Core( plugins, postLinkers ) this.tokensByFile = {}; } diff --git a/src/index.js b/src/index.js index d3533d8..1e7fa56 100644 --- a/src/index.js +++ b/src/index.js @@ -2,18 +2,23 @@ import postcss from 'postcss' import localByDefault from 'postcss-modules-local-by-default' import extractImports from 'postcss-modules-extract-imports' import scope from 'postcss-modules-scope' +import customMedia from 'postcss-custom-media' import Parser from './parser' export default class Core { - constructor( plugins ) { + constructor( plugins, postLinkers ) { this.plugins = plugins || Core.defaultPlugins + this.postLinkers = postLinkers || Core.defaultPostLinkers } load( sourceString, sourcePath, trace, pathFetcher ) { - let parser = new Parser( pathFetcher, trace ) + let parser = new Parser( pathFetcher, trace ), + pluginChain = this.plugins + .concat( [parser.plugin] ) + .concat( this.postLinkers ); - return postcss( this.plugins.concat( [parser.plugin] ) ) + return postcss( pluginChain ) .process( sourceString, { from: "/" + sourcePath } ) .then( result => { return { injectableSource: result.css, exportTokens: parser.exportTokens } @@ -21,8 +26,10 @@ export default class Core { } } -// These three plugins are aliased under this package for simplicity. +// These four plugins are aliased under this package for simplicity. Core.localByDefault = localByDefault Core.extractImports = extractImports Core.scope = scope +Core.customMedia = customMedia Core.defaultPlugins = [localByDefault, extractImports, scope] +Core.defaultPostLinkers = [customMedia] diff --git a/test/test-cases.js b/test/test-cases.js index c6adcff..f38d9d8 100644 --- a/test/test-cases.js +++ b/test/test-cases.js @@ -21,7 +21,7 @@ Object.keys( pipelines ).forEach( dirname => { if ( fs.existsSync( path.join( testDir, testCase, "source.css" ) ) ) { it( "should " + testCase.replace( /-/g, " " ), done => { let expected = normalize( fs.readFileSync( path.join( testDir, testCase, "expected.css" ), "utf-8" ) ) - let loader = new FileSystemLoader( testDir, pipelines[dirname] ) + let loader = new FileSystemLoader( testDir, pipelines[dirname], pipelines[dirname] ) let expectedTokens = JSON.parse( fs.readFileSync( path.join( testDir, testCase, "expected.json" ), "utf-8" ) ) loader.fetch( `${testCase}/source.css`, "/" ).then( tokens => { assert.equal( loader.finalSource, expected ) diff --git a/test/test-cases/media-queries/expected.css b/test/test-cases/media-queries/expected.css index fc612cd..795fd15 100644 --- a/test/test-cases/media-queries/expected.css +++ b/test/test-cases/media-queries/expected.css @@ -1,26 +1,21 @@ -@custom-media --small (max-width: 30em); -@custom-media --medium (max-width: 60em); -@custom-media --small (max-width: 30em); -@custom-media --medium (max-width: 60em); -@custom-media --large (max-width: 90em); ._media_queries_source__red { color: red; } -@media (--small) { +@media (max-width: 30em) { ._media_queries_source__red { color: maroon; } } -@media (--medium) { +@media (max-width: 60em) { ._media_queries_source__red { color: darkmagenta; } } -@media (--large) { +@media (max-width: 90em) { ._media_queries_source__red { color: fuchsia; } From 31c7c65f2126747c320af08523b8215649a89f7e Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Sat, 15 Aug 2015 13:20:25 +1000 Subject: [PATCH 7/8] using the beta versions of the updated loaders --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9a7d06f..60483f0 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,9 @@ "dependencies": { "postcss": "^4.1.11", "postcss-custom-media": "^4.1.0", - "postcss-modules-extract-imports": "^0.0.5", + "postcss-modules-extract-imports": "^1.0.0-beta1", "postcss-modules-local-by-default": "^0.0.9", - "postcss-modules-scope": "^0.0.8" + "postcss-modules-scope": "^1.0.0-beta1" }, "devDependencies": { "babel": "^5.5.4", From 38847183ce971a46276ddf9089b1021469da15ac Mon Sep 17 00:00:00 2001 From: Glen Maddern Date: Sat, 15 Aug 2015 13:27:46 +1000 Subject: [PATCH 8/8] bump to 1.0 beta --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 60483f0..f537c28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-modules-loader-core", - "version": "0.0.12", + "version": "1.0.0-beta1", "description": "A loader-agnostic CSS Modules implementation, based on PostCSS", "main": "lib/index.js", "directories": {