-
-
Notifications
You must be signed in to change notification settings - Fork 470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support passing a {Function}
(options.insertInto
)
#279
feat: support passing a {Function}
(options.insertInto
)
#279
Conversation
requiredJS = [ | ||
"var el = document.createElement('div');", | ||
"el.id = \"test-shadow\";", | ||
// "var shadow = el.attachShadow({ mode: 'open' })", // sadly shadow dom not working in jsdom |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really want to test with shadow root at first, but jsdom not working with shadow dom. Maybe some day we can use smth like headless-chrome for testing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thx so far, +1 for the feature, but the implementation needs rework and triage
lib/addStyles.js
Outdated
@@ -23,7 +23,11 @@ var isOldIE = memoize(function () { | |||
return window && document && document.all && !window.atob; | |||
}); | |||
|
|||
var getElement = (function (fn) { | |||
var getTargetFunction = function (target) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getTargetFunction
=> getTarget
lib/addStyles.js
Outdated
return document.querySelector(target); | ||
}; | ||
|
||
var getElementCreator = function (fn) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getElementCreator
=> getElement
lib/addStyles.js
Outdated
|
||
var getElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getElement
=> element
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about this. Because in this place we create function nor element and then use it right there https://github.com/webpack-contrib/style-loader/blob/master/lib/addStyles.js#L154
requiredJS = [ | ||
"var el = document.createElement('div');", | ||
"el.id = \"test-shadow\";", | ||
// "var shadow = el.attachShadow({ mode: 'open' })", // sadly shadow dom not working in jsdom |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
index.js
Outdated
"var options = " + JSON.stringify(options), | ||
"options.transform = transform", | ||
"var insertIntoCallable;", | ||
options.insertIntoCallable ? "insertIntoCallable = require(" + loaderUtils.stringifyRequest(this, "!" + path.resolve(options.insertIntoCallable)) + ")" : "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This currently introduces a new options to the loader (options.insertIntoCallable
) ? I would be much in favor to resolve this via type checking of options.insertInto
e.g typeof options.InsertInto === 'function'
instead of adding yet another option to the loader. Passing a {Function}
is a good idea I planned to reduce the options
of style-loader
whenever possible in a similar way for the next major release since most of current options
are kind of style-loader
specific 'weirdness' due to technical debt and legacy support in the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, first time I'm trying to use existing options but loader have validation by schema and this is validation check for string. At second there is should be a path to file. As we can't use function directly we can't check it with typeof operator and have 100% guarantee that given string is path to file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another idea: what if use .toString()
for function and then eval (or inline) it. Not sure how it is safe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, first time I'm trying to use existing options but loader have validation by schema and this is validation check for string.
This can be fixed as the options
validation is able to handle that via oneOf
&& typeof: 'function'
now (the dependency in style-loader
likely needs an update). Simply remove the the check for insertInto
while developing for now and if needed I will help/take over at this point then
As we can't use function directly we can't check it with typeof operator and have 100% guarantee that given string is path to file
webpack.config.js
{
insertInto: require('path/to/custom/targetFn') // {Object}
insertInto () { // {Function}
return document.querySelector('#foo')
}
}
index.js L16+
// handler (within the loader phase)
const insertInto = typeof options.insertInto === 'function' ? ...
...
// pass the result to code block
Another idea: what if use .toString() for function and then eval (or inline) it. Not sure how it is safe
You can certainly try go in that direction since webpack
will parse this code again so a function declaration as {String}
should work (will be/should be 'evaluated' or parsed as {Function}
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be fixed as the options validation is able to handle that via oneOf && typeof: 'function' now
Looks like oneOf
in ajv
not help, need to define new keyword
lib/addStyles.js
Outdated
//} | ||
// path/to/insertInto.js | ||
// module.exports = function () { return document.querySelector("#foo").shadowRoot } | ||
getElement = options.insertIntoCallable != null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var element = typeof options.insertInto === 'function'
? getElement(options.insertInto)
: getElement(getTarget)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another way maybe to pass the options
to getTarget
directly =>
var getTarget = function (target, options) {
return typeof options.insertInto === 'function'
? options.insertInto()
: function (target) { return document.querySelector(target); }
}
Something like that
@michael-ciniawsky I can't reply directly to comment for puppeteer 😄 I really like this idea, but I don't think that this PR a good place for changing test runner :) what do you think? |
@savelichalex This was just a suggestion not a requirement or the like :) |
{Function}
(options.insertInto
)
@@ -14,9 +14,6 @@ | |||
"insertAt": { | |||
"type": ["string", "object"] | |||
}, | |||
"insertInto": { | |||
"type": "string" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we need new keyword in ajv for this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, a newer version of schema-utils
is needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also requires updates to the docs (README) then 😛
index.js
Outdated
@@ -35,6 +35,14 @@ module.exports.pitch = function (request) { | |||
"}" | |||
].join("\n"); | |||
|
|||
var insertInto = "void 0"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why void 0
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this place https://github.com/savelichalex/style-loader/blob/fe58dbe66444852d9133a00d2d1883eb9036ff41/index.js#L55 I need some explicit value. This can be undefined
or null
of course)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, just var insertInto;
please :) . Also please move your code to L21+
index.js
Outdated
if (typeof options.insertInto === "function") { | ||
insertInto = options.insertInto.toString(); | ||
} | ||
if (typeof options.insertInto === "string") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check shouldn't be necessary as there isn't anything to handle within the pitching phase of the loader in case options.insertInto
is a {String}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just want to make this check explicit, if you think that this is excess, I can delete this)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not mandatory (I think it isn't, but didn't test it) please remove it 😛
index.js
Outdated
@@ -35,6 +35,14 @@ module.exports.pitch = function (request) { | |||
"}" | |||
].join("\n"); | |||
|
|||
var insertInto = "void 0"; | |||
if (typeof options.insertInto === "function") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
lib/addStyles.js
Outdated
return function(selector) { | ||
if (typeof memo[selector] === "undefined") { | ||
var styleTarget = fn.call(this, selector); | ||
return function(insertInto) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
insertInto
=> target
lib/addStyles.js
Outdated
var styleTarget = fn.call(this, selector); | ||
return function(insertInto) { | ||
// If passing function in options, then use it for resolve "head" element. | ||
// Usefull for Shadow Root style i.e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usefull
=>Useful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!)
@michael-ciniawsky Sorry for late response
Agree :) |
Would be nice with the shadow dom / iframe targeting to be able to load the styles to multiple targets. Maybe outside of the scope of this PR? Thanks for adding this functionality. |
@cthorner Yeah, I think about it too! But unfortunately I don't know how to do it right. I'm also want to add styles not right after script evaluating. For me nice example of overriding runtime behavior is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- var insertInto = "void 0";
if (typeof options.insertInto === "function") {
- insertInto = options.insertInto.toString();
+ options.insertInto = options.insertInto.toString();
}
- if (typeof options.insertInto === "string") {
- insertInto = '"' + options.insertInto + '"';
- }
"// Prepare cssTransformation",
"var transform;",
options.transform ? "transform = require(" + loaderUtils.stringifyRequest(this, "!" + path.resolve(options.transform)) + ");" : "",
- "var insertInto = " + insertInto + ";" ,
"var options = " + JSON.stringify(options), // using toString() should be working here (?)
"options.transform = transform",
- "options.insertInto = insertInto;",
And then we are g2g I guess :)
index.js
Outdated
@@ -35,6 +35,14 @@ module.exports.pitch = function (request) { | |||
"}" | |||
].join("\n"); | |||
|
|||
var insertInto = "void 0"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, just var insertInto;
please :) . Also please move your code to L21+
index.js
Outdated
if (typeof options.insertInto === "function") { | ||
insertInto = options.insertInto.toString(); | ||
} | ||
if (typeof options.insertInto === "string") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not mandatory (I think it isn't, but didn't test it) please remove it 😛
index.js
Outdated
@@ -44,8 +52,10 @@ module.exports.pitch = function (request) { | |||
"// Prepare cssTransformation", | |||
"var transform;", | |||
options.transform ? "transform = require(" + loaderUtils.stringifyRequest(this, "!" + path.resolve(options.transform)) + ");" : "", | |||
"var options = " + JSON.stringify(options), | |||
"options.transform = transform", | |||
"var insertInto = " + insertInto + ";" , |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is redundant with the reassignment on L57 ? 🙃
@michael-ciniawsky I'll try to explain all this code :) |
@savelichalex Please rebase once you have the time, so I can finally finish this :) |
What kind of change does this PR introduce?
This is new feature, to use function in
insertInto
like options, that add more flexibility to loader. I.e. my case - I want to insert css into shadow root, but this is impossible right now (because::shadow
is deprecated)Did you add tests for your changes?
Yes
If relevant, did you update the README?
Not sure about naming, need review first
Summary
Does this PR introduce a breaking change?
Pass all existed test cases
Other information