Skip to content

Commit

Permalink
feat: added attributes option
Browse files Browse the repository at this point in the history
  • Loading branch information
cap-Bernardito authored Oct 15, 2020
1 parent a5f17c4 commit e8a2d5a
Show file tree
Hide file tree
Showing 17 changed files with 970 additions and 755 deletions.
39 changes: 37 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ module.exports = {
| **[`chunkFilename`](#chunkFilename)** | `{String\|Function}` | `based on filename` | This option determines the name of non-entry chunk files |
| **[`ignoreOrder`](#ignoreOrder)** | `{Boolean}` | `false` | Remove Order Warnings |
| **[`insert`](#insert)** | `{String\|Function}` | `var head = document.getElementsByTagName("head")[0];head.appendChild(linkTag);` | Inserts `<link>` at the given position |
| **[`attributes`](#attributes)** | `{Object}` | `{}` | Adds custom attributes to tag |

#### `filename`

Expand Down Expand Up @@ -113,7 +114,7 @@ See [examples](#remove-order-warnings) below for details.
#### `insert`

Type: `String|Function`
Default: `var head = document.getElementsByTagName("head")[0];head.appendChild(linkTag);`
Default: `var head = document.getElementsByTagName("head")[0]; head.appendChild(linkTag);`

By default, the `extract-css-chunks-plugin` appends styles (`<link>` elements) to `document.head` of the current `window`.

Expand Down Expand Up @@ -151,7 +152,7 @@ Allows to override default behavior and insert styles at any position.
```js
new MiniCssExtractPlugin({
insert: function (linkTag) {
const reference = document.querySelector('#some-element');
var reference = document.querySelector('#some-element');
if (reference) {
reference.parentNode.insertBefore(linkTag, reference);
}
Expand All @@ -161,6 +162,40 @@ new MiniCssExtractPlugin({

A new `<link>` element will be inserted before the element with id `some-element`.

#### `attributes`

Type: `Object`
Default: `{}`

If defined, the `mini-css-extract-plugin` will attach given attributes with their values on <link> element.

**webpack.config.js**

```js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
plugins: [
new MiniCssExtractPlugin({
attributes: {
id: 'target',
'data-target': 'example',
},
}),
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
```

Note: It's only applied to dynamically loaded css chunks, if you want to modify link attributes inside html file, please using [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin)

### Loader Options

| Name | Type | Default | Description |
Expand Down
1,536 changes: 783 additions & 753 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/CssLoadingRuntimeModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ module.exports = class CssLoadingRuntimeModule extends RuntimeModule {
'fullhref, resolve, reject',
[
'var linkTag = document.createElement("link");',
this.runtimeOptions.attributes,
'linkTag.rel = "stylesheet";',
'linkTag.type = "text/css";',
'linkTag.onload = resolve;',
Expand Down
14 changes: 14 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class MiniCssExtractPlugin {
'head.appendChild(linkTag);',
]);

const attributes =
typeof options.attributes === 'object' ? options.attributes : {};

this.options = Object.assign(
{
filename: DEFAULT_FILENAME,
Expand All @@ -61,6 +64,16 @@ class MiniCssExtractPlugin {
insert,
};

this.runtimeOptions.attributes = Template.asString(
Object.entries(attributes).map((entry) => {
const [key, value] = entry;

return `linkTag.setAttribute(${JSON.stringify(key)}, ${JSON.stringify(
value
)});`;
})
);

if (!this.options.chunkFilename) {
const { filename } = this.options;

Expand Down Expand Up @@ -383,6 +396,7 @@ class MiniCssExtractPlugin {
]),
'}',
'var linkTag = document.createElement("link");',
this.runtimeOptions.attributes,
'linkTag.rel = "stylesheet";',
'linkTag.type = "text/css";',
'linkTag.onload = resolve;',
Expand Down
4 changes: 4 additions & 0 deletions src/plugin-options.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
"instanceof": "Function"
}
]
},
"attributes": {
"description": "Adds custom attributes to tag (https://github.com/webpack-contrib/mini-css-extract-plugin#attributes).",
"type": "object"
}
}
}
37 changes: 37 additions & 0 deletions test/__snapshots__/attributes-option.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`attributes option should work with attributes option: DOM 1`] = `
"<!DOCTYPE html><html><head>
<title>style-loader test</title>
<style id=\\"existing-style\\">.existing { color: yellow }</style>
<link id=\\"target\\" data-target=\\"example\\" rel=\\"stylesheet\\" type=\\"text/css\\" href=\\"simple.css\\"><script charset=\\"utf-8\\" src=\\"simple.bundle.js\\"></script></head>
<body>
<h1>Body</h1>
<div class=\\"target\\"></div>
<iframe class=\\"iframeTarget\\"></iframe>
</body></html>"
`;
exports[`attributes option should work with attributes option: errors 1`] = `Array []`;
exports[`attributes option should work with attributes option: warnings 1`] = `Array []`;
exports[`attributes option should work without attributes option: DOM 1`] = `
"<!DOCTYPE html><html><head>
<title>style-loader test</title>
<style id=\\"existing-style\\">.existing { color: yellow }</style>
<link rel=\\"stylesheet\\" type=\\"text/css\\" href=\\"simple.css\\"><script charset=\\"utf-8\\" src=\\"simple.bundle.js\\"></script></head>
<body>
<h1>Body</h1>
<div class=\\"target\\"></div>
<iframe class=\\"iframeTarget\\"></iframe>
</body></html>"
`;
exports[`attributes option should work without attributes option: errors 1`] = `Array []`;
exports[`attributes option should work without attributes option: warnings 1`] = `Array []`;
7 changes: 7 additions & 0 deletions test/__snapshots__/validate-plugin-options.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`validate options should throw an error on the "attributes" option with "true" value 1`] = `
"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema.
- options.attributes should be an object:
object {}
-> Adds custom attributes to tag (https://github.com/webpack-contrib/mini-css-extract-plugin#attributes)."
`;

exports[`validate options should throw an error on the "chunkFilename" option with "true" value 1`] = `
"Invalid options object. Mini CSS Extract Plugin has been initialized using an options object that does not match the API schema.
- options.chunkFilename should be one of these:
Expand Down
74 changes: 74 additions & 0 deletions test/attributes-option.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* eslint-env browser */
import path from 'path';

import MiniCssExtractPlugin from '../src/cjs';

import {
compile,
getCompiler,
getErrors,
getWarnings,
runInJsDom,
} from './helpers/index';

describe('attributes option', () => {
it(`should work without attributes option`, async () => {
const compiler = getCompiler(
'attributes.js',
{},
{
output: {
publicPath: '',
path: path.resolve(__dirname, '../outputs'),
filename: '[name].bundle.js',
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
}
);
const stats = await compile(compiler);

runInJsDom('main.bundle.js', compiler, stats, (dom) => {
// console.log(dom.serialize())
expect(dom.serialize()).toMatchSnapshot('DOM');
});

expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});

it(`should work with attributes option`, async () => {
const compiler = getCompiler(
'attributes.js',
{},
{
output: {
publicPath: '',
path: path.resolve(__dirname, '../outputs'),
filename: '[name].bundle.js',
},
plugins: [
new MiniCssExtractPlugin({
attributes: {
id: 'target',
'data-target': 'example',
},
filename: '[name].css',
}),
],
}
);
const stats = await compile(compiler);

runInJsDom('main.bundle.js', compiler, stats, (dom) => {
// console.log(dom.serialize())
expect(dom.serialize()).toMatchSnapshot('DOM');
});

expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
});
1 change: 1 addition & 0 deletions test/cases/hmr/expected/webpack-5/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3292,6 +3292,7 @@ module.exports = function (x) {
/******/ (() => {
/******/ var createStylesheet = (fullhref, resolve, reject) => {
/******/ var linkTag = document.createElement("link");
/******/
/******/ linkTag.rel = "stylesheet";
/******/ linkTag.type = "text/css";
/******/ linkTag.onload = resolve;
Expand Down
1 change: 1 addition & 0 deletions test/cases/insert-function/expected/webpack-4/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
/******/ if(dataHref === href || dataHref === fullhref) return resolve();
/******/ }
/******/ var linkTag = document.createElement("link");
/******/
/******/ linkTag.rel = "stylesheet";
/******/ linkTag.type = "text/css";
/******/ linkTag.onload = resolve;
Expand Down
1 change: 1 addition & 0 deletions test/cases/insert-function/expected/webpack-5/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
/******/ (() => {
/******/ var createStylesheet = (fullhref, resolve, reject) => {
/******/ var linkTag = document.createElement("link");
/******/
/******/ linkTag.rel = "stylesheet";
/******/ linkTag.type = "text/css";
/******/ linkTag.onload = resolve;
Expand Down
1 change: 1 addition & 0 deletions test/cases/insert-string/expected/webpack-4/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
/******/ if(dataHref === href || dataHref === fullhref) return resolve();
/******/ }
/******/ var linkTag = document.createElement("link");
/******/
/******/ linkTag.rel = "stylesheet";
/******/ linkTag.type = "text/css";
/******/ linkTag.onload = resolve;
Expand Down
1 change: 1 addition & 0 deletions test/cases/insert-string/expected/webpack-5/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
/******/ (() => {
/******/ var createStylesheet = (fullhref, resolve, reject) => {
/******/ var linkTag = document.createElement("link");
/******/
/******/ linkTag.rel = "stylesheet";
/******/ linkTag.type = "text/css";
/******/ linkTag.onload = resolve;
Expand Down
1 change: 1 addition & 0 deletions test/cases/insert-undefined/expected/webpack-4/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
/******/ if(dataHref === href || dataHref === fullhref) return resolve();
/******/ }
/******/ var linkTag = document.createElement("link");
/******/
/******/ linkTag.rel = "stylesheet";
/******/ linkTag.type = "text/css";
/******/ linkTag.onload = resolve;
Expand Down
1 change: 1 addition & 0 deletions test/cases/insert-undefined/expected/webpack-5/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
/******/ (() => {
/******/ var createStylesheet = (fullhref, resolve, reject) => {
/******/ var linkTag = document.createElement("link");
/******/
/******/ linkTag.rel = "stylesheet";
/******/ linkTag.type = "text/css";
/******/ linkTag.onload = resolve;
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* eslint-disable-next-line no-unused-expressions */
import(/* webpackChunkName: "simple" */ './simple.css');
4 changes: 4 additions & 0 deletions test/validate-plugin-options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ describe('validate options', () => {
success: ['#existing-style', function insert() {}],
failure: [1, true, {}],
},
attributes: {
success: [{}, { id: 'id' }],
failure: [true],
},
unknown: {
success: [],
// TODO failed in next release
Expand Down

0 comments on commit e8a2d5a

Please sign in to comment.