Skip to content

Commit 2588aca

Browse files
jasonenglishmichael-ciniawsky
authored andcommitted
feat(useable): add insertInto support (options.insertInto) (#341)
1 parent 4217bd1 commit 2588aca

File tree

2 files changed

+142
-19
lines changed

2 files changed

+142
-19
lines changed

test/useable.test.js

Lines changed: 124 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,136 @@ var loaderUtils = require('loader-utils');
88
var useable = require("../useable");
99

1010
describe("useable tests", function () {
11-
var sandbox = sinon.sandbox.create();
12-
var getOptions;
11+
describe('hmr', function () {
12+
var sandbox = sinon.sandbox.create();
13+
var getOptions;
1314

14-
beforeEach(() => {
15-
// Mock loaderUtils to override options
16-
getOptions = sandbox.stub(loaderUtils, 'getOptions');
17-
});
15+
beforeEach(() => {
16+
// Mock loaderUtils to override options
17+
getOptions = sandbox.stub(loaderUtils, 'getOptions');
18+
});
1819

19-
afterEach(() => {
20-
sandbox.restore();
21-
});
20+
afterEach(() => {
21+
sandbox.restore();
22+
});
2223

23-
it("should output HMR code by default", function () {
24-
assert.equal(/(module\.hot)/g.test(useable.pitch()), true);
25-
});
24+
it("should output HMR code by default", function () {
25+
assert.equal(/(module\.hot)/g.test(useable.pitch()), true);
26+
});
2627

27-
it("should NOT output HMR code when options.hmr is false", function () {
28-
getOptions.returns({hmr: false});
29-
assert.equal(/(module\.hot)/g.test(useable.pitch()), false);
28+
it("should NOT output HMR code when options.hmr is false", function () {
29+
getOptions.returns({hmr: false});
30+
assert.equal(/(module\.hot)/g.test(useable.pitch()), false);
31+
});
32+
33+
it("should output HMR code when options.hmr is true", function () {
34+
getOptions.returns({hmr: true});
35+
assert.equal(/(module\.hot)/g.test(useable.pitch()), true);
36+
});
3037
});
3138

32-
it("should output HMR code when options.hmr is true", function () {
33-
getOptions.returns({hmr: true});
34-
assert.equal(/(module\.hot)/g.test(useable.pitch()), true);
39+
describe('insert into', function () {
40+
var path = require("path");
41+
42+
var utils = require("./utils"),
43+
runCompilerTest = utils.runCompilerTest;
44+
45+
var fs;
46+
47+
var requiredCss = ".required { color: blue }",
48+
requiredCssTwo = ".requiredTwo { color: cyan }",
49+
localScopedCss = ":local(.className) { background: red; }",
50+
localComposingCss = `
51+
:local(.composingClass) {
52+
composes: className from './localScoped.css';
53+
color: blue;
54+
}
55+
`,
56+
requiredStyle = `<style type="text/css">${requiredCss}</style>`,
57+
existingStyle = `<style id="existing-style">.existing { color: yellow }</style>`,
58+
checkValue = '<div class="check">check</div>',
59+
rootDir = path.resolve(__dirname + "/../") + "/",
60+
jsdomHtml = [
61+
"<html>",
62+
"<head id='head'>",
63+
existingStyle,
64+
"</head>",
65+
"<body>",
66+
"<div class='target'>",
67+
checkValue,
68+
"</div>",
69+
"<iframe class='iframeTarget'/>",
70+
"</body>",
71+
"</html>"
72+
].join("\n"),
73+
requiredJS = [
74+
"var el = document.createElement('div');",
75+
"el.id = \"test-shadow\";",
76+
"document.body.appendChild(el)",
77+
"var css = require('./style.css');",
78+
"css.use();",
79+
].join("\n");
80+
81+
var styleLoaderOptions = {};
82+
var cssRule = {};
83+
84+
var defaultCssRule = {
85+
test: /\.css?$/,
86+
use: [
87+
{
88+
loader: "style-loader/useable",
89+
options: styleLoaderOptions
90+
},
91+
"css-loader"
92+
]
93+
};
94+
95+
var webpackConfig = {
96+
entry: "./main.js",
97+
output: {
98+
filename: "bundle.js"
99+
},
100+
module: {
101+
rules: [cssRule]
102+
}
103+
};
104+
105+
var setupWebpackConfig = function() {
106+
fs = utils.setup(webpackConfig, jsdomHtml);
107+
108+
// Create a tiny file system. rootDir is used because loaders are referring to absolute paths.
109+
fs.mkdirpSync(rootDir);
110+
fs.writeFileSync(rootDir + "main.js", requiredJS);
111+
fs.writeFileSync(rootDir + "style.css", requiredCss);
112+
fs.writeFileSync(rootDir + "styleTwo.css", requiredCssTwo);
113+
fs.writeFileSync(rootDir + "localScoped.css", localScopedCss);
114+
fs.writeFileSync(rootDir + "localComposing.css", localComposingCss);
115+
};
116+
117+
beforeEach(function() {
118+
// Reset all style-loader options
119+
for (var member in styleLoaderOptions) {
120+
delete styleLoaderOptions[member];
121+
}
122+
123+
for (var member in defaultCssRule) {
124+
cssRule[member] = defaultCssRule[member];
125+
}
126+
127+
setupWebpackConfig();
128+
}); // before each
129+
130+
it("insert into iframe", function(done) {
131+
let selector = "iframe.iframeTarget";
132+
styleLoaderOptions.insertInto = selector;
133+
134+
let expected = requiredStyle;
135+
136+
runCompilerTest(expected, done, function() {
137+
return this.document.querySelector(selector).contentDocument.head.innerHTML;
138+
}, selector);
139+
}); // it insert into
140+
35141
});
36142

37143
});

useable.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@ module.exports.pitch = function (request) {
1818

1919
options.hmr = typeof options.hmr === 'undefined' ? true : options.hmr;
2020

21+
// The variable is needed, because the function should be inlined.
22+
// If is just stored it in options, JSON.stringify will quote
23+
// the function and it would be just a string at runtime
24+
var insertInto;
25+
26+
if (typeof options.insertInto === "function") {
27+
insertInto = options.insertInto.toString();
28+
}
29+
30+
// We need to check if it a string, or variable will be "undefined"
31+
// and the loader crashes
32+
if (typeof options.insertInto === "string") {
33+
insertInto = '"' + options.insertInto + '"';
34+
}
35+
2136
var hmr = [
2237
// Hot Module Replacement
2338
"if(module.hot) {",
@@ -48,14 +63,16 @@ module.exports.pitch = function (request) {
4863
"var refs = 0;",
4964
"var dispose;",
5065
"var content = require(" + loaderUtils.stringifyRequest(this, "!!" + request) + ");",
66+
"var options = " + JSON.stringify(options) + ";",
67+
"options.insertInto = " + insertInto + ";",
5168
"",
5269
"if(typeof content === 'string') content = [[module.id, content, '']];",
5370
// Export CSS Modules
5471
"if(content.locals) exports.locals = content.locals;",
5572
"",
5673
"exports.use = exports.ref = function() {",
5774
" if(!(refs++)) {",
58-
" dispose = require(" + loaderUtils.stringifyRequest(this, "!" + path.join(__dirname, "lib", "addStyles.js")) + ")(content, " + JSON.stringify(options) + ");",
75+
" dispose = require(" + loaderUtils.stringifyRequest(this, "!" + path.join(__dirname, "lib", "addStyles.js")) + ")(content, options);",
5976
" }",
6077
"",
6178
" return exports;",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy