diff --git a/.changeset/gorgeous-steaks-report.md b/.changeset/gorgeous-steaks-report.md new file mode 100644 index 0000000000..2df79ac6f6 --- /dev/null +++ b/.changeset/gorgeous-steaks-report.md @@ -0,0 +1,6 @@ +--- +'@emotion/cache': minor +'@emotion/sheet': minor +--- + +Accept new `prepend` option to allow for adding style tags at the beginning of the specified DOM container. diff --git a/packages/cache/README.md b/packages/cache/README.md index 0b94e1ffe2..be76d90ecb 100644 --- a/packages/cache/README.md +++ b/packages/cache/README.md @@ -56,3 +56,9 @@ The prefix before class names. It will also be set as the value of the `data-emo `HTMLElement` A DOM node that emotion will insert all of its style tags into. This is useful for inserting styles into iframes. + +### `prepend` + +`boolean` + +A string representing whether to prepend rather than append style tags into the specified container DOM node. diff --git a/packages/cache/src/index.js b/packages/cache/src/index.js index a8caad7a1b..f93998e60b 100644 --- a/packages/cache/src/index.js +++ b/packages/cache/src/index.js @@ -19,7 +19,8 @@ export type Options = { prefix?: PrefixOption, key?: string, container?: HTMLElement, - speedy?: boolean + speedy?: boolean, + prepend?: boolean } let rootServerStylisCache = {} @@ -240,7 +241,8 @@ let createCache = (options?: Options): EmotionCache => { key, container, nonce: options.nonce, - speedy: options.speedy + speedy: options.speedy, + prepend: options.prepend }), nonce: options.nonce, inserted, diff --git a/packages/cache/types/index.d.ts b/packages/cache/types/index.d.ts index a9a9ca8fd5..ef317ac573 100644 --- a/packages/cache/types/index.d.ts +++ b/packages/cache/types/index.d.ts @@ -12,6 +12,7 @@ export interface Options { key?: string container?: HTMLElement speedy?: boolean + prepend?: boolean } export default function createCache(options?: Options): EmotionCache diff --git a/packages/sheet/__tests__/__snapshots__/index.js.snap b/packages/sheet/__tests__/__snapshots__/index.js.snap index 322157e694..0a281a3b4f 100644 --- a/packages/sheet/__tests__/__snapshots__/index.js.snap +++ b/packages/sheet/__tests__/__snapshots__/index.js.snap @@ -1,5 +1,28 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`StyleSheet should accept prepend option 1`] = ` + +
+ + + + ++ +`; + exports[`StyleSheet should insert a rule into the DOM when not in speedy 1`] = `
diff --git a/packages/sheet/__tests__/index.js b/packages/sheet/__tests__/index.js index 35ada5c952..1caf083f1a 100644 --- a/packages/sheet/__tests__/index.js +++ b/packages/sheet/__tests__/index.js @@ -3,6 +3,7 @@ import { safeQuerySelector } from 'test-utils' import { StyleSheet } from '@emotion/sheet' const rule = 'html { color: hotpink; }' +const rule2 = '* { box-sizing: border-box; }' let defaultOptions = { key: '', @@ -110,4 +111,19 @@ describe('StyleSheet', () => { expect(sheet.tags[0].sheet.cssRules[0]).toBeInstanceOf(window.CSSImportRule) sheet.flush() }) + + it('should accept prepend option', () => { + const head = safeQuerySelector('head') + const otherStyle = document.createElement('style') + otherStyle.setAttribute('id', 'other') + head.appendChild(otherStyle) + + const sheet = new StyleSheet({ ...defaultOptions, prepend: true }) + sheet.insert(rule) + sheet.insert(rule2) + expect(document.documentElement).toMatchSnapshot() + + sheet.flush() + head.removeChild(otherStyle) + }) }) diff --git a/packages/sheet/src/index.js b/packages/sheet/src/index.js index c7e5f41ef3..ff4b93add1 100644 --- a/packages/sheet/src/index.js +++ b/packages/sheet/src/index.js @@ -43,7 +43,8 @@ export type Options = { nonce?: string, key: string, container: HTMLElement, - speedy?: boolean + speedy?: boolean, + prepend?: boolean } function createStyleElement(options: { @@ -66,6 +67,7 @@ export class StyleSheet { container: HTMLElement key: string nonce: string | void + prepend: boolean | void before: Element | null constructor(options: Options) { this.isSpeedy = @@ -78,6 +80,7 @@ export class StyleSheet { // key is the value of the data-emotion attribute, it's used to identify different sheets this.key = options.key this.container = options.container + this.prepend = options.prepend this.before = null } insert(rule: string) { @@ -88,7 +91,7 @@ export class StyleSheet { let tag = createStyleElement(this) let before if (this.tags.length === 0) { - before = this.before + before = this.prepend ? this.container.firstChild : this.before } else { before = this.tags[this.tags.length - 1].nextSibling } diff --git a/packages/sheet/types/index.d.ts b/packages/sheet/types/index.d.ts index bda5d570e0..3eac35b53f 100644 --- a/packages/sheet/types/index.d.ts +++ b/packages/sheet/types/index.d.ts @@ -6,6 +6,7 @@ export interface Options { key: string container: HTMLElement speedy?: boolean + prepend?: boolean } export class StyleSheet {