Skip to content
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 'before' insertions (options.insertAt) #253

Merged

Conversation

iancw
Copy link
Contributor

@iancw iancw commented Jun 27, 2017

Allow new styles to be inserted before other <style> or <link> elements that
exist on the page. This allows more precise ordering for complex style overrides
between multiple sources.

What kind of change does this PR introduce?
New feature

Did you add tests for your changes?
Yes

If relevant, did you update the README?
Yes

Summary

This is a new feature adding a third possible value for insertAt: "before". A new option value insertBefore which contains query selector to select the element that the new styles should precede.

Complicated style situations where multiple <style> tags exist and must be inserted in specific order to allow style-overrides to work across sections require more precise placement than just top or bottom. This feature allows more precise selection of exactly where to insert a new <style> section relative to other existing sections.

Does this PR introduce a breaking change?
No

This allows styles to be inserted before other styles or links that
exist on the page. This is necessary to allow ordering style overrides
between multiple sources of styles.
@jsf-clabot
Copy link

jsf-clabot commented Jun 27, 2017

CLA assistant check
All committers have signed the CLA.

@michael-ciniawsky michael-ciniawsky changed the title Add insertAt='before' option feat: support 'before' insertions (options.insertBefore) Jun 27, 2017
@michael-ciniawsky michael-ciniawsky added this to the 0.19.0 milestone Jun 27, 2017
@michael-ciniawsky michael-ciniawsky added this to Feature in Dashboard Jun 27, 2017
lib/addStyles.js Outdated
@@ -170,6 +172,9 @@ function insertStyleElement (options, style) {
stylesInsertedAtTop.push(style);
} else if (options.insertAt === "bottom") {
target.appendChild(style);
} else if (options.insertAt === "before") {
var nextSibling = getElement(options.insertInto + " " + options.insertBefore);
target.insertBefore(style, nextSibling);
} else {
throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error message should include valid option 'before':

Invalid value for parameter 'insertAt'. Must be 'top', 'bottom' or 'before'.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this throw in the browser console or during build time? If the latter

this.emitError("Style Loader\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top' or 'bottom'.\n (https://github.com/webpack-contrib/style-loader#insertat)\n")

else

throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top' or 'bottom'.\n (https://github.com/webpack-contrib/style-loader#insertat)\n")

Copy link
Member

@michael-ciniawsky michael-ciniawsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options.json (Options Schema Validation) needs an update aswell

lib/addStyles.js Outdated
@@ -170,6 +172,9 @@ function insertStyleElement (options, style) {
stylesInsertedAtTop.push(style);
} else if (options.insertAt === "bottom") {
target.appendChild(style);
} else if (options.insertAt === "before") {
var nextSibling = getElement(options.insertInto + " " + options.insertBefore);
target.insertBefore(style, nextSibling);
} else {
throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this throw in the browser console or during build time? If the latter

this.emitError("Style Loader\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top' or 'bottom'.\n (https://github.com/webpack-contrib/style-loader#insertat)\n")

else

throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top' or 'bottom'.\n (https://github.com/webpack-contrib/style-loader#insertat)\n")

README.md Outdated
@@ -139,6 +139,7 @@ Styles are not added on `import/require()`, but instead on call to `use`/`ref`.
|**`transform`** |`{Function}`|`false`|Transform/Conditionally load CSS by passing a transform/condition function|
|**`insertAt`**|`{String}`|`bottom`|Inserts `<style></style>` at the given position|
|**`insertInto`**|`{String}`|`<head>`|Inserts `<style></style>` into the given position|
|**`insertBefore`**|`{String}`|``|A query string specifying an element to insert new `<style>` before, required when `insertAt="before"`|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree with an extra top level option depending on other one. Possible to pass the an {Object} to insertAt instead { type: 'before', $: '#id' } ($ maybe better named selector) [Needs discussion]

Copy link
Contributor Author

@iancw iancw Jun 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I wasn't completely sure the best way to approach this. The logic for insertBefore could also be triggered without requiring anything special in insertAt. In other words, if insertBefore has a non-empty string that behavior pre-empts the normal insertion logic triggered by insertAt.

I steered away from that because it seemed potentially confusing to have insertBefore pre-empt and essentially override the behavior of insertAt.

I'm also fine with making insertAt an object, but that becomes a breaking change. If you think that's best I can go with it, but it seems kind of heavy-handed for a small feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see how it can be done in a backwards-compatible fashion. Pushed an implementation. Another option for the Object interface is { before: '#id'}, which lets us avoid the ambiguous-sounding type key and avoid choosing between $ and selector.

Copy link
Member

@michael-ciniawsky michael-ciniawsky Jun 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah an {Object} isn't optimal in terms of type consistency either, but inter option dependence isn't aswell, the interface you suggested is much better though :)

@michael-ciniawsky michael-ciniawsky changed the title feat: support 'before' insertions (options.insertBefore) feat: support 'before' insertions (options.insertAt) Jun 27, 2017
README.md Outdated
loader: 'style-loader'
options: {
insertAt: {
before: '#style-overrides'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#id || #name (generic)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The options table needs an type update aswell {String} => {String\|Object} (⚠️ \ [escaped])

Copy link
Member

@michael-ciniawsky michael-ciniawsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iancw Thx

@michael-ciniawsky
Copy link
Member

@webpack-contrib/org-maintainers please review :)

@michael-ciniawsky michael-ciniawsky merged commit 67120f8 into webpack-contrib:master Sep 8, 2017
@iancw iancw deleted the insert-before-element branch September 9, 2017 02:03
@michael-ciniawsky michael-ciniawsky removed this from the 0.20.0 milestone Nov 11, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Dashboard
Feature
Development

Successfully merging this pull request may close these issues.

None yet

4 participants