Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: webpack-contrib/css-loader
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.2.1
Choose a base ref
...
head repository: webpack-contrib/css-loader
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v3.3.0
Choose a head ref
  • 5 commits
  • 27 files changed
  • 2 contributors

Commits on Dec 3, 2019

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e662b61 View commit details

Commits on Dec 5, 2019

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    80e9662 View commit details

Commits on Dec 6, 2019

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6769783 View commit details

Commits on Dec 9, 2019

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6177af5 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    889807a View commit details
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,19 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [3.3.0](https://github.com/webpack-contrib/css-loader/compare/v3.2.1...v3.3.0) (2019-12-09)


### Features

* support `pure` css modules ([#1008](https://github.com/webpack-contrib/css-loader/issues/1008)) ([6177af5](https://github.com/webpack-contrib/css-loader/commit/6177af5596566fead13a8f66d5abcb4dc2b744db))


### Bug Fixes

* do not crash when an assert return `null` or `undefined` ([#1006](https://github.com/webpack-contrib/css-loader/issues/1006)) ([6769783](https://github.com/webpack-contrib/css-loader/commit/67697833725e1cff12a14663390bbe4c65ea36d2))
* reduce count of `require` ([#1004](https://github.com/webpack-contrib/css-loader/issues/1004)) ([80e9662](https://github.com/webpack-contrib/css-loader/commit/80e966280f2477c5c0e4553d3be3a04511fea381))

### [3.2.1](https://github.com/webpack-contrib/css-loader/compare/v3.2.0...v3.2.1) (2019-12-02)


1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -317,6 +317,7 @@ module.exports = {

Using `local` value requires you to specify `:global` classes.
Using `global` value requires you to specify `:local` classes.
Using `pure` value requires selectors must contain at least one local class or id.

You can find more information [here](https://github.com/css-modules/css-modules).

2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "css-loader",
"version": "3.2.1",
"version": "3.3.0",
"description": "css loader module for webpack",
"license": "MIT",
"repository": "webpack-contrib/css-loader",
97 changes: 44 additions & 53 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -13,13 +13,11 @@ import { importParser, icssParser, urlParser } from './plugins';
import {
normalizeSourceMap,
getModulesPlugins,
getImportPrefix,
getFilter,
getApiCode,
getImportCode,
getModuleCode,
getExportCode,
prepareCode,
} from './utils';
import Warning from './Warning';
import CssSyntaxError from './CssSyntaxError';
@@ -55,31 +53,21 @@ export default function loader(content, map, meta) {
plugins.push(...getModulesPlugins(options, this));
}

// Run other loader (`postcss-loader`, `sass-loader` and etc) for importing CSS
const importPrefix = getImportPrefix(this, options.importLoaders);
const exportType = options.onlyLocals ? 'locals' : 'full';

plugins.push(
icssParser({
loaderContext: this,
importPrefix,
localsConvention: options.localsConvention,
})
);
plugins.push(icssParser());

if (options.import !== false) {
if (options.import !== false && exportType === 'full') {
plugins.push(
importParser({
loaderContext: this,
importPrefix,
filter: getFilter(options.import, this.resourcePath),
})
);
}

if (options.url !== false) {
if (options.url !== false && exportType === 'full') {
plugins.push(
urlParser({
loaderContext: this,
filter: getFilter(options.url, this.resourcePath, (value) =>
isUrlRequest(value)
),
@@ -92,54 +80,57 @@ export default function loader(content, map, meta) {
from: this.remainingRequest.split('!').pop(),
to: this.currentRequest.split('!').pop(),
map: options.sourceMap
? {
prev: map,
inline: false,
annotation: false,
}
: null,
? { prev: map, inline: false, annotation: false }
: false,
})
.then((result) => {
result
.warnings()
.forEach((warning) => this.emitWarning(new Warning(warning)));

if (!result.messages) {
// eslint-disable-next-line no-param-reassign
result.messages = [];
const imports = [];
const exports = [];
const replacers = [];

for (const message of result.messages) {
// eslint-disable-next-line default-case
switch (message.type) {
case 'import':
imports.push(message.value);
break;
case 'export':
exports.push(message.value);
break;
case 'replacer':
replacers.push(message.value);
break;
}
}

const { onlyLocals } = options;

const importItems = result.messages
.filter((message) => (message.type === 'import' ? message : false))
.reduce((accumulator, currentValue) => {
accumulator.push(currentValue.import);

return accumulator;
}, []);
const exportItems = result.messages
.filter((message) => (message.type === 'export' ? message : false))
.reduce((accumulator, currentValue) => {
accumulator.push(currentValue.export);

return accumulator;
}, []);

const importCode = getImportCode(importItems, onlyLocals);
const moduleCode = getModuleCode(result, sourceMap, onlyLocals);
const exportCode = getExportCode(exportItems, onlyLocals);
const apiCode = getApiCode(this, sourceMap, onlyLocals);
// Run other loader (`postcss-loader`, `sass-loader` and etc) for importing CSS
const apiCode = exportType === 'full' ? getApiCode(this, sourceMap) : '';
const importCode =
imports.length > 0
? getImportCode(this, imports, {
importLoaders: options.importLoaders,
exportType,
})
: '';
const moduleCode =
exportType === 'full'
? getModuleCode(this, result, replacers, sourceMap)
: '';
const exportCode =
exports.length > 0
? getExportCode(this, exports, replacers, {
localsConvention: options.localsConvention,
exportType,
})
: '';

return callback(
null,
prepareCode(
{ apiCode, importCode, moduleCode, exportCode },
result.messages,
this,
importPrefix,
onlyLocals
)
[apiCode, importCode, moduleCode, exportCode].join('')
);
})
.catch((error) => {
4 changes: 2 additions & 2 deletions src/options.json
Original file line number Diff line number Diff line change
@@ -30,14 +30,14 @@
"type": "boolean"
},
{
"enum": ["local", "global"]
"enum": ["local", "global", "pure"]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"mode": {
"enum": ["local", "global"]
"enum": ["local", "global", "pure"]
},
"localIdentName": {
"type": "string"
73 changes: 28 additions & 45 deletions src/plugins/postcss-icss-parser.js
Original file line number Diff line number Diff line change
@@ -1,76 +1,59 @@
import postcss from 'postcss';
import { extractICSS, replaceValueSymbols, replaceSymbols } from 'icss-utils';
import loaderUtils from 'loader-utils';

import { getExportItemCode, getImportItemCode } from '../utils';

const pluginName = 'postcss-icss-parser';

function hasImportMessage(messages, url) {
return messages.find(
(message) =>
message.pluginName === pluginName &&
message.type === 'import' &&
message.item.url === url &&
message.item.media === ''
);
}

export default postcss.plugin(
pluginName,
(options = {}) =>
() =>
function process(css, result) {
const importReplacements = Object.create(null);
const { icssImports, icssExports } = extractICSS(css);

let index = 0;
Object.keys(icssImports).forEach((url, importIndex) => {
const tokens = Object.keys(icssImports[url]);

if (tokens.length === 0) {
return;
}

const importName = `___CSS_LOADER_ICSS_IMPORT_${importIndex}___`;

result.messages.push({
pluginName,
type: 'import',
value: { type: 'icss-import', name: importName, url },
});

for (const importUrl of Object.keys(icssImports)) {
const url = loaderUtils.parseString(importUrl);
tokens.forEach((token, replacementIndex) => {
const name = `___CSS_LOADER_ICSS_IMPORT_${importIndex}_REPLACEMENT_${replacementIndex}___`;
const localName = icssImports[url][token];

for (const token of Object.keys(icssImports[importUrl])) {
index += 1;
importReplacements[token] = `___CSS_LOADER_IMPORT___${index}___`;
importReplacements[token] = name;

result.messages.push({
pluginName,
type: 'icss-import',
item: { url, export: icssImports[importUrl][token], index },
type: 'replacer',
value: { type: 'icss-import', name, importName, localName },
});
});
});

if (!hasImportMessage(result.messages, url)) {
const media = '';
const { loaderContext, importPrefix } = options;

result.messages.push({
pluginName,
type: 'import',
import: getImportItemCode(
{ url, media },
loaderContext,
importPrefix
),
item: { url, media },
});
}
}
if (Object.keys(importReplacements).length > 0) {
replaceSymbols(css, importReplacements);
}

replaceSymbols(css, importReplacements);

for (const exportName of Object.keys(icssExports)) {
const name = exportName;
Object.keys(icssExports).forEach((name) => {
const value = replaceValueSymbols(
icssExports[name],
importReplacements
);

result.messages.push({
pluginName,
export: getExportItemCode(name, value, options.localsConvention),
type: 'export',
item: { name, value },
value: { name, value },
});
}
});
}
);
50 changes: 29 additions & 21 deletions src/plugins/postcss-import-parser.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import postcss from 'postcss';
import valueParser from 'postcss-value-parser';

import { uniqWith, getImportItemCode } from '../utils';

const pluginName = 'postcss-import-parser';

function getArg(nodes) {
@@ -46,7 +44,7 @@ function parseImport(params) {
}

function walkAtRules(css, result, filter) {
const items = [];
const items = new Map();

css.walkAtRules(/^import$/i, (atRule) => {
// Convert only top-level @import
@@ -79,33 +77,43 @@ function walkAtRules(css, result, filter) {
atRule.remove();

const { url, media } = parsed;
const value = items.get(url);

items.push({ url, media });
if (!value) {
items.set(url, new Set([media]));
} else {
value.add(media);
}
});

return items;
}

export default postcss.plugin(
pluginName,
(options = {}) =>
(options) =>
function process(css, result) {
const traversed = walkAtRules(css, result, options.filter);
const paths = uniqWith(
traversed,
(value, other) => value.url === other.url && value.media === other.media
);

paths.forEach((item) => {
result.messages.push({
pluginName,
type: 'import',
import: getImportItemCode(
item,
options.loaderContext,
options.importPrefix
),
const items = walkAtRules(css, result, options.filter);

[...items]
.reduce((accumulator, currentValue) => {
const [url, medias] = currentValue;

medias.forEach((media) => {
accumulator.push({ url, media });
});

return accumulator;
}, [])
.forEach((item, index) => {
const { url, media } = item;
const name = `___CSS_LOADER_AT_RULE_IMPORT_${index}___`;

result.messages.push({
pluginName,
type: 'import',
value: { type: '@import', name, url, media },
});
});
});
}
);
Loading