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

[Plugin] how to add a rule based on a property declaration #237

Closed
hazem3500 opened this issue Sep 1, 2020 · 3 comments
Closed

[Plugin] how to add a rule based on a property declaration #237

hazem3500 opened this issue Sep 1, 2020 · 3 comments

Comments

@hazem3500
Copy link

I am currently writing a plugin that converts CSS logical properties to directional properties inside a rule with a selector for the direction attribute
Example
from:

padding-inline-start: 50px;

to

padding-inline-start: 50px:
@supports not (padding-inline-start: 50px) {
  [dir=ltr] {
    padding-left: 50px;
  }
  [dir=rtl] {
    padding-right: 50px;
  }
}

My current implementation looks like this (simplified):

import {compile} from 'stylis'

const PROPERTY_CONTEXT = 1;
function stylisPluginLogical(context, content) {
   if (context === PROPERTY_CONTEXT ) {
       const propertyAST = compile(content)[0];
       if (isALogicalProperty(propertyAST.props)) {
           return transforms[propertyAST.props](propertyAST.children);
       }
       return content;
   }
}

const transforms = {
 // ...
 "padding-inline-start": (value) => `
 padding-inline-start: ${value}:
 @supports not (padding-inline-start: ${value}) {
   [dir=ltr] {
     padding-left: ${value};
   }
   [dir=rtl] {
     padding-right: ${value};
   }
 }
 `
}

Repo link

The problem is returning a nested rule with the property declaration doesn't work, so how can I inject this

  @supports not (padding-inline-start: 50px) {
    [dir=ltr] {
      padding-left: 50px;
    }
    [dir=rtl] {
      padding-right: 50px
    }
  }

in another rule outside the rule that has the padding-inline-start: 50px in it?

@Andarist
Copy link
Collaborator

Andarist commented Sep 1, 2020

This is what your plugin should like:

serialize(
  compile(`.user{padding-inline-start: 50px;}`),
  middleware([
    (node, index, children, callback) => {
      if (node.type === "decl") {
        // handle your node, probably insert extra nodes at children[index + 1]
        // node.props holds your property name, so "padding-inline-start" in this case
      }
    },
    stringify,
  ])
);

You might need to create nodes using node appropriately, copy might also come useful.

@hazem3500
Copy link
Author

I've been trying at this for a while, but I am facing some issues.
I wasn't sure how to add a new rule when the current node had the type decl so I tried changing the condition to check for the type rule.
I then would return a string that had the rules that I wanted which worked fine but when I tried passing the plugin to stylisPlugin in emotion@11.x it didn't seem to work.
I am not sure how to approach writing this middleware, is there some sort of guide on how to write one?

Examples

standalone stylis plugin example
plugin passed to emotion
the code of the middleware

@thysultan
Copy link
Owner

Is this still an issue on the stylis side?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants