Skip to content

Commit 2588aca

Browse files
jasonenglishmichael-ciniawsky
authored andcommittedAug 27, 2018
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

+124-18
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

+18-1
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)
Please sign in to comment.