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

doubt about editing returned raw VNodes #909

Closed
k1r0s opened this issue Oct 12, 2017 · 5 comments
Closed

doubt about editing returned raw VNodes #909

k1r0s opened this issue Oct 12, 2017 · 5 comments

Comments

@k1r0s
Copy link
Contributor

k1r0s commented Oct 12, 2017

Im trying to edit raw 'h' nodes before they get constructed

Hope u get a bit of background how im trying to do that
image

Im trying to create a @withStyle(cssObj) decorator using a @afterMethod Join Point with kaop-ts to plug a <style> ... content </style> inside some component before it gets evaluated by preact.

Because this occurs in runtime im trying to dynamicly edit component's render() hyperscript result before it become a VNode placing a preact_1.h("style", null, scopedRules))); as the last children.

My question is if there is somehow a way more friendly to edit hyperscript rather than str.replace(regexThatSearchOnHyperScriptBodyFunctionTheLastChildren, "preact_1.h("style", null, scopedRules)))") :\

The resulting implementation will look like this:

import { h, Component } from "preact";
// styles will be replaced with component scoped selectors like angular 2+ does
const styleContent = `
  button {
    color: gray;
  }
  button:hover {
    color: white;
  }
`;

export class MyButton extends Component {

  @withStyle(styleContent)
  render(props) {
    return (
        <button>{props.children}</button>
    )
  } 
}

or

export const MyButton = withStyle(styleContent)(props => (
  <button>{props.children}</button>
));
@k1r0s
Copy link
Contributor Author

k1r0s commented Oct 12, 2017

basically im asking for a way to 'deserialize' VNodes in hscript again :((

@k1r0s
Copy link
Contributor Author

k1r0s commented Oct 12, 2017

worth?
image

@developit
Copy link
Member

Would it be sufficient to instead mutate the resulting VNodes created by an unmodified h()?
I don't have time to write a decorator, but here'd be the wrapper function:

function withStyle(fn) {
  return function() {
    let vnode = fn.apply(this, arguments);
    vnode.children = [ h('style', /*..etc..*/) ].concat(vnode.children)
    return vnode;
  };
}

@k1r0s
Copy link
Contributor Author

k1r0s commented Oct 12, 2017

Awesome answer, thanks

@k1r0s k1r0s closed this as completed Oct 12, 2017
@k1r0s
Copy link
Contributor Author

k1r0s commented Oct 14, 2017

working decorator implementation:

import { h, Component } from "preact";
import { afterMethod } from "kaop-ts";

export const stylesheet = (styleContent: string) =>
afterMethod<Component<any, any>, "render">((meta) => {

  // remove all spaces, eols
  styleContent = styleContent.replace(/(\r\n\s|\n|\r|\s)/gm, "");

  // prefix all selectors to make stylesheet 'scoped'
  styleContent = styleContent.replace(
    /([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/g,
    `${meta.target.constructor.name.toLowerCase()} $1$2`
  )

  // add stylesheet to vnode
  meta.result = h(
    meta.target.constructor.name, null,
    [ meta.result, h("style", { 'scoped': true }, styleContent) ]
  );
});

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

2 participants