There's a few things missing pre-v0.6.4 of the stylis compiler that your fork will not handle that could be nice to have.
/* this should get wrapped in the namespace */
color: red;
h1 {
font-size:1px;
}
full prefix support in @root and @keyframes blocks.
support opting out of name-spacing keyframes and animations.
I've done away with the regex solution i was using, and added supports for stylis("[data-id=namespace]") namespaces.
@thysultan what do you think about :host support instead?
@rauchg So these will be the same& { ... } === :host { ... } ?
yep so
<div>
<style jsx>{`
:host {
color: red
}
`}</style>
</div>
:host would impact the div.
Alternatively, we could make the div also targetable simply with div { }, but I'm not sure if that's elegant
cc @giuseppeg
sure i can add that, :host will be an alias for &.
@rauchg correct :host should resolve to the shadow root aka the div in the example.
One thing to keep in mind is that styles applied from the outside should win over :host's but I guess that this behavior is hard to shim.
Nice to have then it would be to get :host-context(selector) support e.g.:
<body>
<div>
<style jsx>{`
:host-context(body) {
color: red
}
`}</style>
</div>
</body>
yields
body div[data-jsx="abc"] { color: red }
But probably it is better to tackle this later and maybe also consider the ._aB1bC-ext thing that I suggested in the original issue.
@rauchg @giuseppeg pushed a patch for all the host variations
:host - > ${namespace} {...}
:host(.fancy), -> ${namspace}.fancy {...}
:host-context(body) -> body ${namespace} {...}
@thysultan cool in order for * {} to work you need to append the namespace though otherwise ${namespace}* {} won't work. In general I think that suffixing is better than prefixing.
@giuseppeg * {} will generate ${namespace} * {} with a space.
@thysultan oh I see, sorry I was thinking in terms of styled-jsx :)
@rauchg instead of this
<style jsx>{`
:host {
color: red
}
`}</style>
can this work
<style jsx>`
:host {
color: red
}
`</style>
or better yet a plugin that treats everything in the <style jsx><style> block as a text node/string literal, removing the need for \`or{}`
<style jsx>
:host {
color: red
}
</style>
The latter is invalid JSX unfortunately. It'll think of { … } as an expression
We picked the most optimal syntax considering how JSX works today I think :D
@thysultan what happens here
https://github.com/zeit/styled-jsx/blob/master/lib/style-transform.js#L197
if the selector is something like:
[title="a,b"] {
color: red
}
@rauchg it will break, i fixed this in 0.7.1 commit
@thysultan do you think that it would be trivial to switch to your version of the compiler and write a middleware to add scoping the styled-jsx way (with data-jsx to each selector)? If so would you be interested in helping out?
Sure, the middleware will look something like this
function middleware (ctx, str, line, col, prefix) {
if (ctx === 1.5) {
// avoids name-spacing :global() functions
if (str.indexOf(prefix) === 0) {
return str.replace(prefix, '') + prefix;
}
}
}
This will change h1, h2 { to h1[prefix], h2[prefix] {
The 1.5 context is to be executed at every selector(post-processed) in a selector declaration.
@giuseppeg On the repl site https://stylis.js.org/ You can try the following in the console.
stylis.use(middleware (ctx, str, line, col, prefix) {
if (ctx === 1.5) {
if (str.indexOf(prefix+' ') === 0) {
var pos = (str = str.substring(prefix.length).replace('&', '').trim()).indexOf(' ');
return pos !== -1 ? str.substring(0, pos) + prefix + str.substring(pos) : str + prefix;
}
}
});
and input something into the editor and it should namespace the styled-jsx way.
@thysultan the selector below should be .logo[data-jsx="foo"] a[data-jsx="foo"]

i.e. the prefix should be added to every part of the selector (except for globals). Do you think that it is doable with the current version of stylis + middleware?
@giuseppeg Yes doable, what should .logo:hover a { compile to?
cool .logo[data-jsx="foo"]:hover a[data-jsx="foo"]
Then this should work as expected.
function middleware (ctx, str, line, col, prefix) {
if (ctx === 1.5) {
// avoid :global()
if (str.indexOf(prefix+' ') === 0) {
// strips stylis added namespace
str = str.substring(prefix.length).trim();
// flag if single selector
var pos = str.indexOf(' ');
// multiple selectors, i.e h1 h2
if (pos !== -1) {
var parts = str.split(' ');
// add namespace to all parts
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
pos = part.indexOf(':');
// if has pseudo selector
parts[i] = pos !== -1 ? part.substring(0, pos) + prefix + part.substring(pos) : part + prefix;
}
return parts.join(' ');
}
// single selector
else {
return str + prefix;
}
}
}
}
@thysultan @rauchg I started to work on this tonight https://github.com/zeit/styled-jsx/pull/125 keep in mind that it is very wip
fixed by #134