Skip to content

Instantly share code, notes, and snippets.

@zanzamar
Created August 8, 2017 23:56
Show Gist options
  • Save zanzamar/6b8cfd292346fb7237500238c1828a47 to your computer and use it in GitHub Desktop.
Save zanzamar/6b8cfd292346fb7237500238c1828a47 to your computer and use it in GitHub Desktop.
styletron-client-monkey-patch
/* global document */
/**
* Customize our own version of styletron until we get a P/R request imported:
*
* This monkey patches styletron to enable namespacing/wrapping the generated CSS classes from styletron. The generated
* class on the html element stays the same.
*
* ie: `<div class="a" />` has a classname written to the `<style />` of `.WRAP_CLASS a { ... }`
*
* Usage:
* const styletron = Styletron(
* document.getElementsByClassName('_styletron_hydrate_'),
* { selectorPrefix: '.WRAP-CLASS' }
* );
*
* https://github.com/rtsao/styletron/pull/160
*/
import Styletron from 'styletron-client';
import StyletronCore from 'styletron-core';
function initialize(elements, options = {}) {
Styletron.prototype.injectDeclaration = injectDeclaration;
const styletron = new Styletron(elements, options);
styletron.selectorPrefix = options.selectorPrefix;
return styletron;
}
/**
* customized injectDeclaration
*
* Override styletron function
*/
function injectDeclaration(decl) {
const oldCount = this.uniqueCount;
const className = StyletronCore.prototype.injectDeclaration.call(this, decl);
if (oldCount !== this.uniqueCount) {
const rule = declarationToRule(className, decl, this.selectorPrefix);
let sheet;
if (decl.media) {
if (!this.mediaSheets[decl.media]) {
const mediaSheet = document.createElement('style');
mediaSheet.media = decl.media;
this.mediaSheets[decl.media] = mediaSheet;
this.mainSheet.parentNode.appendChild(mediaSheet);
}
sheet = this.mediaSheets[decl.media].sheet;
} else {
sheet = this.mainSheet.sheet;
}
sheet.insertRule(rule, sheet.cssRules.length);
}
return className;
}
/*
* Injection helpers
*
* Override styletron function
*/
function declarationToRule(className, ref, selectorPrefix) {
const prop = ref.prop;
const val = ref.val;
const pseudo = ref.pseudo;
const decl = `${prop}:${val}`;
let selector = `${selectorPrefix ? `${selectorPrefix} ` : ''}.${className}`;
if (pseudo) {
selector += pseudo;
}
return `${selector}{${decl}}`;
}
export default initialize;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment