Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix postcss modules composes imports #2642

Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 192 additions & 2 deletions packages/core/integration-tests/test/css.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,9 @@ describe('css', function() {
assert.equal(typeof output, 'function');

let value = output();
assert(/_index_[0-9a-z]+_1/.test(value));
assert(/_index_[0-9a-z]/.test(value));

let cssClass = value.match(/(_index_[0-9a-z]+_1)/)[1];
let cssClass = value.match(/(_index_[0-9a-z]+)/)[1];

let css = await fs.readFile(
path.join(__dirname, '/dist/index.css'),
Expand All @@ -313,6 +313,196 @@ describe('css', function() {
assert.equal(run1(), run2());
});

it('should support postcss composes imports', async function() {
let b = await bundle(
path.join(__dirname, '/integration/postcss-composes/index.js')
);

await assertBundleTree(b, {
name: 'index.js',
assets: ['index.js', 'composes-1.css', 'composes-2.css', 'mixins.css'],
childBundles: [
{
name: 'index.css',
assets: ['composes-1.css', 'composes-2.css', 'mixins.css'],
childBundles: []
},
{
type: 'map'
}
]
});

let output = await run(b);
assert.equal(typeof output, 'function');

let value = output();
assert.equal(value.composes1, '_composes1_29315 _test_19e21');
assert.equal(value.composes2, '_composes2_b5878 _test_19e21');

let css = await fs.readFile(
path.join(__dirname, '/dist/index.css'),
'utf8'
);
let cssClass1 = value.composes1.match(/(_composes1_[0-9a-z]+)/)[1];
assert(css.includes(`.${cssClass1}`));
let cssClass2 = value.composes2.match(/(_composes2_[0-9a-z]+)/)[1];
assert(css.includes(`.${cssClass2}`));
});

it('should not include css twice for postcss composes imports', async function() {
let b = await bundle(
path.join(__dirname, '/integration/postcss-composes/index.js')
);

await run(b);

let css = await fs.readFile(
path.join(__dirname, '/dist/index.css'),
'utf8'
);
assert.equal(
css.indexOf('height: 100px;'),
css.lastIndexOf('height: 100px;')
);
});

it('should support postcss composes imports for sass', async function() {
let b = await bundle(
path.join(__dirname, '/integration/postcss-composes/index2.js')
);

await assertBundleTree(b, {
name: 'index2.js',
assets: ['index2.js', 'composes-3.css', 'mixins.scss'],
childBundles: [
{
name: 'index2.css',
assets: ['composes-3.css', 'mixins.scss'],
childBundles: []
},
{
type: 'map'
}
]
});

let output = await run(b);
assert.equal(typeof output, 'function');

let value = output();
assert.equal(value.composes3, '_composes3_6834d _test_c0a12');

let css = await fs.readFile(
path.join(__dirname, '/dist/index2.css'),
'utf8'
);
assert(css.includes('height: 200px;'));
});

it('should support postcss composes imports with custom path names', async function() {
let b = await bundle(
path.join(__dirname, '/integration/postcss-composes/index3.js')
);

await assertBundleTree(b, {
name: 'index3.js',
assets: ['index3.js', 'composes-4.css', 'mixins.css'],
childBundles: [
{
name: 'index3.css',
assets: ['composes-4.css', 'mixins.css'],
childBundles: []
},
{
type: 'map'
}
]
});

let output = await run(b);
assert.equal(typeof output, 'function');

let value = output();
assert.equal(value.composes4, '_composes4_7038c _test_19e21');

let css = await fs.readFile(
path.join(__dirname, '/dist/index3.css'),
'utf8'
);
assert(css.includes('height: 100px;'));
});

it('should support deep nested postcss composes imports', async function() {
let b = await bundle(
path.join(__dirname, '/integration/postcss-composes/index4.js')
);

await assertBundleTree(b, {
name: 'index4.js',
assets: [
'index4.js',
'composes-5.css',
'mixins-intermediate.css',
'mixins.css'
],
childBundles: [
{
name: 'index4.css',
assets: ['composes-5.css', 'mixins-intermediate.css', 'mixins.css'],
childBundles: []
},
{
type: 'map'
}
]
});

let output = await run(b);
assert.equal(typeof output, 'function');

let value = output();
assert.equal(
value.composes5,
'_composes5_c6088 _intermediate_6b681 _test_19e21'
);

let css = await fs.readFile(
path.join(__dirname, '/dist/index4.css'),
'utf8'
);
assert(css.includes('height: 100px;'));
assert(css.includes('height: 300px;'));
assert(css.indexOf('_test_19e21') < css.indexOf('_intermediate_6b681'));
});

it('should support postcss composes imports for multiple selectors', async function() {
let b = await bundle(
path.join(__dirname, '/integration/postcss-composes/index5.js')
);

await assertBundleTree(b, {
name: 'index5.js',
assets: ['index5.js', 'composes-6.css', 'mixins.css'],
childBundles: [
{
name: 'index5.css',
assets: ['composes-6.css', 'mixins.css'],
childBundles: []
},
{
type: 'map'
}
]
});

let output = await run(b);
assert.equal(typeof output, 'function');

let value = output();
assert.equal(value.composes6, '_composes6_d20ad _test_19e21 _test-2_19e21');
});

it('should minify CSS in production mode', async function() {
let b = await bundle(
path.join(__dirname, '/integration/cssnano/index.js'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"modules": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.composes1 {
composes: test from './mixins.css';
border: 3px solid orange;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.composes2 {
composes: test from './mixins.css';
border: 3px solid red;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.composes3 {
composes: test from './mixins.scss';
border: 3px solid brown;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.composes4 {
composes: test from '~mixins.css';
border: 3px solid black;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.composes5 {
composes: intermediate from './mixins-intermediate.css';
border: 3px solid yellow;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.composes6 {
composes: test test-2 from './mixins.css';
border: 3px solid orangered;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
var map1 = require('./composes-1.css');
var map2 = require('./composes-2.css');

module.exports = function () {
return Object.assign({}, map1, map2);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var map3 = require('./composes-3.css');

module.exports = function () {
return map3;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var map4 = require('./composes-4.css');

module.exports = function () {
return map4;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var map5 = require('./composes-5.css');

module.exports = function () {
return map5;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var map6 = require('./composes-6.css');

module.exports = function () {
return map6;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.intermediate {
composes: test from './mixins.css';
height: 300px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.test {
height: 100px;
width: 100px;
}

.test-2 {
background: red;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
$test: 200px;

.test {
height: $test;
width: $test;
}
4 changes: 2 additions & 2 deletions packages/core/integration-tests/test/less.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,12 @@ describe('less', function() {

let output = await run(b);
assert.equal(typeof output, 'function');
assert.equal(output(), '_index_ku5n8_1');
assert.equal(output(), '_index_394ba');

let css = await fs.readFile(
path.join(__dirname, '/dist/index.css'),
'utf8'
);
assert(css.includes('._index_ku5n8_1'));
assert(css.includes('._index_394ba'));
});
});
4 changes: 2 additions & 2 deletions packages/core/integration-tests/test/stylus.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,13 @@ describe('stylus', function() {

let output = await run(b);
assert.equal(typeof output, 'function');
assert.equal(output(), '_index_g9mqo_1');
assert.equal(output(), '_index_6768d');

let css = await fs.readFile(
path.join(__dirname, '/dist/index.css'),
'utf8'
);
assert(css.includes('._index_g9mqo_1'));
assert(css.includes('._index_6768d'));
});

it('should support requiring stylus files with glob dependencies', async function() {
Expand Down
1 change: 1 addition & 0 deletions packages/core/parcel-bundler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"command-exists": "^1.2.6",
"commander": "^2.11.0",
"cross-spawn": "^6.0.4",
"css-modules-loader-core": "^1.1.0",
"cssnano": "^4.0.0",
"deasync": "^0.1.14",
"dotenv": "^5.0.0",
Expand Down
27 changes: 17 additions & 10 deletions packages/core/parcel-bundler/src/Asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,7 @@ class Asset {
this.dependencies.set(name, Object.assign({name}, opts));
}

addURLDependency(url, from = this.name, opts) {
if (!url || isURL(url)) {
return url;
}

if (typeof from === 'object') {
opts = from;
from = this.name;
}

resolveDependency(url, from = this.name) {
const parsed = URL.parse(url);
let depName;
let resolved;
Expand All @@ -110,8 +101,24 @@ class Asset {
depName = './' + path.relative(path.dirname(this.name), resolved);
}

return {depName, resolved};
}

addURLDependency(url, from = this.name, opts) {
if (!url || isURL(url)) {
return url;
}

if (typeof from === 'object') {
opts = from;
from = this.name;
}

const {depName, resolved} = this.resolveDependency(url, from);

this.addDependency(depName, Object.assign({dynamic: true, resolved}, opts));

const parsed = URL.parse(url);
parsed.pathname = this.options.parser
.getAsset(resolved, this.options)
.generateBundleName();
Expand Down
Loading