nanohtml icon indicating copy to clipboard operation
nanohtml copied to clipboard

thoughts on extensible custom tags

Open SilentCicero opened this issue 8 years ago • 7 comments

So this may not be in the philosophy of bel, but how/should/can I easily create an extensible module for bel/yoyo (the module I use) that allows for custom tags/props that just render functions.

Here is what I'm thinking:

const Button = function (opts) {
    return bel`<button>my ${opts.name} button</button>`
}

const Col = function (_yield, opts) {
   return bel`<div class="column">${_yield}</div>`
}

const customtagsuse = bel`<div><Button name="Nick" /></div>`

// which is actually just

const customtagsuse = bel`<div>${Button({name: "Nick"})}</div>`

// or

const customtagsuse2 = bel`<div><Col> some cols </Col></div>`

// which is actually

const customtagsuse2 = bel`<div>${Col(" some cols ")}</div>`

Kinda reactish, but all it's doing is regexing the string, and replacing it with the element.

I'm thinking of providing a layer to bel.

so something like:

var extensible = require("bel-custom")
var bel = extensible(require("bel))
bel.customElements = {"Button": Button}; // sort of thing

Any thoughts on design patterns, approaches, potential pitfalls, potential benefits @shama?

SilentCicero avatar Apr 19 '16 17:04 SilentCicero

I've been tinkering with an approach to this at https://github.com/chromakode/diablo. Currently storing an internal mapping of custom components, though this can be a bit cumbersome because the mapping is a shared global. Would be interesting to think about alternatives!

chromakode avatar Apr 19 '16 19:04 chromakode

What about a transform? Something that detects bel or yo-yo template strings and pre-parses the template literal and detects if a HTML tag matches a variable on the current scope. Then transforms to a common API call, ie: ${Col({ _yield: " some cols ", name: "Nick" })}?

https://github.com/shama/yo-yoify/blob/master/index.js gets part way there.

shama avatar Apr 19 '16 20:04 shama

That's a great idea! I think you could just do it by default for uppercase tag names and not have to consider the scope at all.

chromakode avatar Apr 19 '16 20:04 chromakode

@chromakode consider making your module even more modular lol. Let me know how it goes. I really want this feature. It would really make me yoyo harder =D

Oh I see like a webpack loader of some kind. Okay, yes thats cool. I could definitely do that. Thanks!

But what about intercepting the actual yo or bel elements and doing it there, does that seem unfeasible or very difficult to accomplish on that level?

I keep feeling like I would need to go down to the node/morphom/hyperex level in order to build it that way.

SilentCicero avatar Apr 19 '16 20:04 SilentCicero

@SilentCicero webpack can run browserify transforms too.

But what about intercepting the actual yo or bel elements and doing it there, does that seem unfeasible or very difficult to accomplish on that level?

When parsing the template literal, it doesn't know about the variables on the same scope of the literal, only the expressions passed in with ${}. So it would require registering each component as the above examples are doing and informing the parser about that registry, which can get pretty messy.

shama avatar Apr 19 '16 21:04 shama

Ah, yes, good point. I think it would require a lot of modification. I'll avoid that for now.

But I do think a yoyo-loader is a possibility (transformer/extractify style loader).

Did you manage to take a look at/do some thinking on a yoyo-hot-loader module @shama? I think this as well seems very difficult to accomplish. I really dont get webpacks hot module system, and there is not enough documentation. The fact that the React people figured it out to me boggles the mind.

In any case, hot module reloading for yoyo/bel would be amazing. Just cray.

SilentCicero avatar Apr 20 '16 01:04 SilentCicero

Hey guys, was thinking about this today and had a similar idea... what about using proper custom elements from the web components spec?

EDIT: Probably no matter what you do, the issue of passing in attributes other than strings will be annoying, ie. <MyElement codes=${ [ 'foo', 'bar' ] }></MyElement>

EDIT2: Threw together an example using choo

timwis avatar Jun 17 '16 03:06 timwis