From cdf0ba79f0214973ce0efb5d19c75b0993e36582 Mon Sep 17 00:00:00 2001
From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com>
Date: Tue, 14 Sep 2021 20:06:14 +0300
Subject: [PATCH] refactor: code
---
README.md | 142 +++++++++++++++++-
src/index.js | 3 +-
src/runtime/insertStyleElement.js | 3 +-
src/runtime/styleDomAPI.js | 2 +-
.../lazyStyleTag-options.test.js.snap | 63 ++++++++
test/fixtures/lazy-options-use-unuse.js | 8 +
...{lazy-insertOptions.js => lazy-options.js} | 0
test/lazyStyleTag-insertOptions.test.js | 53 -------
test/lazyStyleTag-options.test.js | 73 +++++++++
test/manual/index.html | 2 +-
...uare.lazy.css => custom-square.custom.css} | 4 +-
test/manual/src/custom-square.js | 22 +--
test/manual/webpack.config.js | 27 ++++
13 files changed, 324 insertions(+), 78 deletions(-)
create mode 100644 test/__snapshots__/lazyStyleTag-options.test.js.snap
create mode 100644 test/fixtures/lazy-options-use-unuse.js
rename test/fixtures/{lazy-insertOptions.js => lazy-options.js} (100%)
delete mode 100644 test/lazyStyleTag-insertOptions.test.js
create mode 100644 test/lazyStyleTag-options.test.js
rename test/manual/src/{custom-square.lazy.css => custom-square.custom.css} (50%)
diff --git a/README.md b/README.md
index a35fac12..6003bb59 100644
--- a/README.md
+++ b/README.md
@@ -540,7 +540,7 @@ module.exports = {
Insert styles at top of `head` tag.
-You can pass any parameters to `style.use(anythingHere)` and this value will be passed to `insert` function. These options will be passed to `styleTagTransform` function too.
+You can pass any parameters to `style.use(options)` and this value will be passed to `insert` and `styleTagTransform` functions.
**webpack.config.js**
@@ -554,8 +554,14 @@ module.exports = {
{
loader: "style-loader",
options: {
+ injectType: "lazyStyleTag",
+ // Do not forget that this code will be used in the browser and
+ // not all browsers support latest ECMA features like `let`, `const`, `arrow function expression` and etc,
+ // we recommend use only ECMA 5 features,
+ // but it is depends what browsers you want to support
insert: function insertIntoTarget(element, options) {
- var parent = options.target || document.querySelector("head");
+ var parent = options.target || document.head;
+
parent.appendChild(element);
},
},
@@ -570,14 +576,51 @@ module.exports = {
Insert styles to the provided element or to the `head` tag if target isn't provided. Now you can inject styles into Shadow DOM (or any other element).
-**component.js**
+**custom-square.css**
+
+```css
+div {
+ width: 50px;
+ height: 50px;
+ background-color: red;
+}
+```
+
+**custom-square.js**
```js
-import style from "./file.css";
+import customSquareStyles from "./custom-square.css";
+
+class CustomSquare extends HTMLElement {
+ constructor() {
+ super();
+
+ this.attachShadow({ mode: "open" });
-style.use({
- target: document.querySelector('#myShadowDom').shadowRoot,
-})
+ const divElement = document.createElement("div");
+
+ divElement.textContent = "Text content.";
+
+ this.shadowRoot.appendChild(divElement);
+
+ customSquareStyles.use({ target: this.shadowRoot });
+
+ // You can override injected styles
+ const bgPurple = new CSSStyleSheet();
+ const width = this.getAttribute("w");
+ const height = this.getAttribute("h");
+
+ bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);
+
+ this.shadowRoot.adoptedStyleSheets = [bgPurple];
+
+ // `divElement` will have `100px` width, `100px` height and `red` background color
+ }
+}
+
+customElements.define("custom-square", CustomSquare);
+
+export default CustomSquare;
```
### `styleTagTransform`
@@ -1033,6 +1076,91 @@ module.exports = {
};
```
+#### Custom Elements (Shadow DOM)
+
+You can define custom target for your styles for the `lazyStyleTag` type.
+
+**webpack.config.js**
+
+```js
+module.exports = {
+ module: {
+ rules: [
+ {
+ test: /\.css$/i,
+ use: [
+ {
+ loader: "style-loader",
+ options: {
+ injectType: "lazyStyleTag",
+ // Do not forget that this code will be used in the browser and
+ // not all browsers support latest ECMA features like `let`, `const`, `arrow function expression` and etc,
+ // we recommend use only ECMA 5 features,
+ // but it is depends what browsers you want to support
+ insert: function insertIntoTarget(element, options) {
+ var parent = options.target || document.head;
+
+ parent.appendChild(element);
+ },
+ },
+ },
+ "css-loader",
+ ],
+ },
+ ],
+ },
+};
+```
+
+Insert styles to the provided element or to the `head` tag if target isn't provided.
+
+**custom-square.css**
+
+```css
+div {
+ width: 50px;
+ height: 50px;
+ background-color: red;
+}
+```
+
+**custom-square.js**
+
+```js
+import customSquareStyles from "./custom-square.css";
+
+class CustomSquare extends HTMLElement {
+ constructor() {
+ super();
+
+ this.attachShadow({ mode: "open" });
+
+ const divElement = document.createElement("div");
+
+ divElement.textContent = "Text content.";
+
+ this.shadowRoot.appendChild(divElement);
+
+ customSquareStyles.use({ target: this.shadowRoot });
+
+ // You can override injected styles
+ const bgPurple = new CSSStyleSheet();
+ const width = this.getAttribute("w");
+ const height = this.getAttribute("h");
+
+ bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);
+
+ this.shadowRoot.adoptedStyleSheets = [bgPurple];
+
+ // `divElement` will have `100px` width, `100px` height and `red` background color
+ }
+}
+
+customElements.define("custom-square", CustomSquare);
+
+export default CustomSquare;
+```
+
## Contributing
Please take a moment to read our contributing guidelines if you haven't yet done so.
diff --git a/src/index.js b/src/index.js
index f0db579c..04cbcb53 100644
--- a/src/index.js
+++ b/src/index.js
@@ -126,7 +126,8 @@ options.domAPI = ${getdomAPI(isAuto)};
options.insertStyleElement = insertStyleElement;
exported.use = function(insertOptions) {
- options.insertOptions = insertOptions;
+ options.options = insertOptions || {};
+
if (!(refs++)) {
update = API(content, options);
}
diff --git a/src/runtime/insertStyleElement.js b/src/runtime/insertStyleElement.js
index 5295e18e..abd68176 100644
--- a/src/runtime/insertStyleElement.js
+++ b/src/runtime/insertStyleElement.js
@@ -3,8 +3,7 @@ function insertStyleElement(options) {
const style = document.createElement("style");
options.setAttributes(style, options.attributes);
-
- options.insert(style, options.insertOptions);
+ options.insert(style, options.options);
return style;
}
diff --git a/src/runtime/styleDomAPI.js b/src/runtime/styleDomAPI.js
index a9e2612d..f48b38e3 100644
--- a/src/runtime/styleDomAPI.js
+++ b/src/runtime/styleDomAPI.js
@@ -18,7 +18,7 @@ function apply(style, options, obj) {
// For old IE
/* istanbul ignore if */
- options.styleTagTransform(css, style, options.insertOptions);
+ options.styleTagTransform(css, style, options.options);
}
function removeStyleElement(style) {
diff --git a/test/__snapshots__/lazyStyleTag-options.test.js.snap b/test/__snapshots__/lazyStyleTag-options.test.js.snap
new file mode 100644
index 00000000..c478a710
--- /dev/null
+++ b/test/__snapshots__/lazyStyleTag-options.test.js.snap
@@ -0,0 +1,63 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`lazyStyleTag options should pass "options" to "insert" function and unuse: DOM 1`] = `
+"
+ style-loader test
+
+
+
+ Body
+
+
+
+
+"
+`;
+
+exports[`lazyStyleTag options should pass "options" to "insert" function and unuse: errors 1`] = `Array []`;
+
+exports[`lazyStyleTag options should pass "options" to "insert" function and unuse: warnings 1`] = `Array []`;
+
+exports[`lazyStyleTag options should pass "options" to "insert" function: DOM 1`] = `
+"
+ style-loader test
+
+
+
+ Body
+
+
+
+
+"
+`;
+
+exports[`lazyStyleTag options should pass "options" to "insert" function: errors 1`] = `Array []`;
+
+exports[`lazyStyleTag options should pass "options" to "insert" function: warnings 1`] = `Array []`;
+
+exports[`lazyStyleTag options should pass "options" to "styleTagTransform" function: DOM 1`] = `
+"
+ style-loader test
+
+
+
+ Body
+
+
+
+
+"
+`;
+
+exports[`lazyStyleTag options should pass "options" to "styleTagTransform" function: errors 1`] = `Array []`;
+
+exports[`lazyStyleTag options should pass "options" to "styleTagTransform" function: warnings 1`] = `Array []`;
diff --git a/test/fixtures/lazy-options-use-unuse.js b/test/fixtures/lazy-options-use-unuse.js
new file mode 100644
index 00000000..94cb3c32
--- /dev/null
+++ b/test/fixtures/lazy-options-use-unuse.js
@@ -0,0 +1,8 @@
+import style from './style.css';
+
+style.use({
+ insertInto: document.body,
+ additionalStyles: '.some-element {color: red;}'
+});
+
+style.unuse();
diff --git a/test/fixtures/lazy-insertOptions.js b/test/fixtures/lazy-options.js
similarity index 100%
rename from test/fixtures/lazy-insertOptions.js
rename to test/fixtures/lazy-options.js
diff --git a/test/lazyStyleTag-insertOptions.test.js b/test/lazyStyleTag-insertOptions.test.js
deleted file mode 100644
index 53809d7c..00000000
--- a/test/lazyStyleTag-insertOptions.test.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/* eslint-env browser */
-
-import {
- compile,
- getCompiler,
- getEntryByInjectType,
- getErrors,
- getWarnings,
- runInJsDom,
-} from "./helpers/index";
-
-describe('lazyStyleTag insertOptions', () => {
- it(`should pass "insertOption" to "insert" function`, async () => {
- expect.assertions(3);
-
- const entry = getEntryByInjectType("insertOptions.js", 'lazyStyleTag');
- const compiler = getCompiler(entry, {
- injectType: 'lazyStyleTag',
- insert: (styleTag, options) => {
- options.insertInto.appendChild(styleTag);
- }
- });
- const stats = await compile(compiler);
-
- runInJsDom("main.bundle.js", compiler, stats, (dom) => {
- expect(dom.serialize()).toMatchSnapshot("DOM");
- });
-
- expect(getWarnings(stats)).toMatchSnapshot("warnings");
- expect(getErrors(stats)).toMatchSnapshot("errors");
- });
-
- it(`should pass "insertOption" to "styleTagTransform" function`, async () => {
- expect.assertions(3);
-
- const entry = getEntryByInjectType("insertOptions.js", 'lazyStyleTag');
- const compiler = getCompiler(entry, {
- injectType: 'lazyStyleTag',
- styleTagTransform: (css, styleTag, options) => {
- // eslint-disable-next-line no-param-reassign
- styleTag.innerHTML = `${css}.${options.additionalStyles}\n`;
- }
- });
- const stats = await compile(compiler);
-
- runInJsDom("main.bundle.js", compiler, stats, (dom) => {
- expect(dom.serialize()).toMatchSnapshot("DOM");
- });
-
- expect(getWarnings(stats)).toMatchSnapshot("warnings");
- expect(getErrors(stats)).toMatchSnapshot("errors");
- });
-});
diff --git a/test/lazyStyleTag-options.test.js b/test/lazyStyleTag-options.test.js
new file mode 100644
index 00000000..5571052c
--- /dev/null
+++ b/test/lazyStyleTag-options.test.js
@@ -0,0 +1,73 @@
+/* eslint-env browser */
+
+import {
+ compile,
+ getCompiler,
+ getEntryByInjectType,
+ getErrors,
+ getWarnings,
+ runInJsDom,
+} from "./helpers/index";
+
+describe("lazyStyleTag options", () => {
+ it(`should pass "options" to "insert" function`, async () => {
+ expect.assertions(3);
+
+ const entry = getEntryByInjectType("options.js", "lazyStyleTag");
+ const compiler = getCompiler(entry, {
+ injectType: "lazyStyleTag",
+ insert: (styleTag, options) => {
+ options.insertInto.appendChild(styleTag);
+ },
+ });
+ const stats = await compile(compiler);
+
+ runInJsDom("main.bundle.js", compiler, stats, (dom) => {
+ expect(dom.serialize()).toMatchSnapshot("DOM");
+ });
+
+ expect(getWarnings(stats)).toMatchSnapshot("warnings");
+ expect(getErrors(stats)).toMatchSnapshot("errors");
+ });
+
+ it(`should pass "options" to "insert" function and unuse`, async () => {
+ expect.assertions(3);
+
+ const entry = getEntryByInjectType("options-use-unuse.js", "lazyStyleTag");
+ const compiler = getCompiler(entry, {
+ injectType: "lazyStyleTag",
+ insert: (styleTag, options) => {
+ options.insertInto.appendChild(styleTag);
+ },
+ });
+ const stats = await compile(compiler);
+
+ runInJsDom("main.bundle.js", compiler, stats, (dom) => {
+ expect(dom.serialize()).toMatchSnapshot("DOM");
+ });
+
+ expect(getWarnings(stats)).toMatchSnapshot("warnings");
+ expect(getErrors(stats)).toMatchSnapshot("errors");
+ });
+
+ it(`should pass "options" to "styleTagTransform" function`, async () => {
+ expect.assertions(3);
+
+ const entry = getEntryByInjectType("options.js", "lazyStyleTag");
+ const compiler = getCompiler(entry, {
+ injectType: "lazyStyleTag",
+ styleTagTransform: (css, styleTag, options) => {
+ // eslint-disable-next-line no-param-reassign
+ styleTag.innerHTML = `${css}\n${options.additionalStyles}\n`;
+ },
+ });
+ const stats = await compile(compiler);
+
+ runInJsDom("main.bundle.js", compiler, stats, (dom) => {
+ expect(dom.serialize()).toMatchSnapshot("DOM");
+ });
+
+ expect(getWarnings(stats)).toMatchSnapshot("warnings");
+ expect(getErrors(stats)).toMatchSnapshot("errors");
+ });
+});
diff --git a/test/manual/index.html b/test/manual/index.html
index 89155344..7d218ccf 100644
--- a/test/manual/index.html
+++ b/test/manual/index.html
@@ -93,7 +93,7 @@ Toggle
diff --git a/test/manual/src/custom-square.lazy.css b/test/manual/src/custom-square.custom.css
similarity index 50%
rename from test/manual/src/custom-square.lazy.css
rename to test/manual/src/custom-square.custom.css
index f8677d42..fdd8138a 100644
--- a/test/manual/src/custom-square.lazy.css
+++ b/test/manual/src/custom-square.custom.css
@@ -1,5 +1,5 @@
div {
- width: 100px;
- height: 100px;
+ width: 50px;
+ height: 50px;
background-color: red;
}
diff --git a/test/manual/src/custom-square.js b/test/manual/src/custom-square.js
index a406dc14..d75d8327 100644
--- a/test/manual/src/custom-square.js
+++ b/test/manual/src/custom-square.js
@@ -1,13 +1,13 @@
/* eslint-env browser */
/* eslint-disable */
-// import customSquareStyles from './custom-square.lazy.css';
+import customSquareStyles from "./custom-square.custom.css";
class CustomSquare extends HTMLElement {
// Specify observed attributes so that
// attributeChangedCallback will work
static get observedAttributes() {
- return ["l"];
+ return ["w", "h"];
}
constructor() {
@@ -15,19 +15,19 @@ class CustomSquare extends HTMLElement {
super();
this.attachShadow({ mode: "open" });
- }
- connectedCallback() {
- const div = document.createElement("div");
+ const divElement = document.createElement("div");
+
+ divElement.textContent = "Text content.";
+
+ this.shadowRoot.appendChild(divElement);
- this.shadowRoot.appendChild(div);
+ customSquareStyles.use({ target: this.shadowRoot });
const bgPurple = new CSSStyleSheet();
+ const width = this.getAttribute("w");
+ const height = this.getAttribute("h");
- bgPurple.replace(`div {
- background: purple;
- width: ${this.getAttribute("l")}px;
- height: ${this.getAttribute("l")}px;
-}`);
+ bgPurple.replace(`div { width: ${width}px; height: ${height}px; }`);
this.shadowRoot.adoptedStyleSheets = [bgPurple];
}
diff --git a/test/manual/webpack.config.js b/test/manual/webpack.config.js
index de646fe9..24d0374d 100644
--- a/test/manual/webpack.config.js
+++ b/test/manual/webpack.config.js
@@ -30,6 +30,7 @@ module.exports = {
/\.lazy\.css$/i,
/\.lazy\.module\.css$/i,
/\.link\.css$/i,
+ /\.custom\.css$/i,
],
use: [
{
@@ -88,6 +89,32 @@ module.exports = {
},
],
},
+ {
+ test: /\.custom\.css$/i,
+ use: [
+ {
+ loader: require.resolve("../../dist/cjs.js"),
+ options: {
+ injectType: "lazyStyleTag",
+ esModule: ENABLE_ES_MODULE,
+ insert: function insert(element, options) {
+ // eslint-disable-next-line
+ var parent = options.target || document.head;
+
+ parent.appendChild(element);
+ },
+ },
+ },
+ {
+ loader: "css-loader",
+ options: {
+ sourceMap: ENABLE_SOURCE_MAP,
+ esModule: ENABLE_PREVIOUS_ES_MODULE,
+ },
+ },
+ ],
+ },
+
{
test: /\.lazy\.module\.css$/i,
exclude: [/\.named-export\.lazy\.module\.css$/i],