Im trying to edit raw 'h' nodes before they get constructed
Hope u get a bit of background how im trying to do that

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>
));
basically im asking for a way to 'deserialize' VNodes in hscript again :((
worth?

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;
};
}
Awesome answer, thanks
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) ]
);
});
Most helpful comment
working decorator implementation: