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

Callable block-mixin #1608

Closed
maxim-grishaev opened this issue Jul 28, 2014 · 8 comments
Closed

Callable block-mixin #1608

maxim-grishaev opened this issue Jul 28, 2014 · 8 comments
Labels

Comments

@maxim-grishaev
Copy link

It'd be great to use custom mixins as "callable block" like iterators:

- var dbg = {a:1, b:2, c:3}
mixin eachDbg()
    ul
        each val, name in dbg
            +block(name, val, name + val)
foo
    +eachDbg
        mixin (name, val ,id)
            tab: a(href="##{id}")= name
    //
    +eachDbg
        mixin (name, val, id)
            h2= name
            pane(id=id)= val

I hope this example explains my idea well

@maxim-grishaev
Copy link
Author

I see only one little conventional problem here: block and mixins has defferent nature now. block is "supposed to be" just inserted, not called.

@ForbesLindesay
Copy link
Member

Yes, we need to think about the syntax/wording here. I've been wanting to change how blocks work slightly for a while now. I'd like them to be a function that returns a string, so that you could do something like:

mixin escape()
  != block().replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
+escape()
  .foo

becomes

&lt;div class=&quot;foo&quot;&gt;&lt;div&gt;

We could continue to have something like the following to maintain backwards compatibility:

mixin container()
  .foo
    block
+container()
  .bar

becomes

<div class="foo"><div class="bar"></div></div>

We could actually then do your example as simply:

- var dbg = {a:1, b:2, c:3}
mixin eachDbg()
    ul
        each val, name in dbg
            block(name, val, name + val)
foo
    +eachDbg
        - var name = arguments[0];
        - var val = arguments[1];
        - var id = arguments[2];
        tab: a(href="##{id}")= name
    //
    +eachDbg
        - var name = arguments[0];
        - var val = arguments[1];
        - var id = arguments[2];
        h2= name
        pane(id=id)= val

Admittedly, that is a little bit crude. One solution would be to just support some ES6 style destructing (this is actually valid today, but the compiler will fail):

- let [name, val, id] = arguments;

Or perhaps as a keyword:

arguments(name, val, id)

so that your example becomes:

- var dbg = {a:1, b:2, c:3}
mixin eachDbg()
    ul
        each val, name in dbg
            block(name, val, name + val)
foo
    +eachDbg
        arguments(name, val ,id)
        tab: a(href="##{id}")= name
    //
    +eachDbg
        arguments(name, val, id)
        h2= name
        pane(id=id)= val

The final use case that isn't really supported still is having multiple blocks for a mixin, but you could do something like the following (again, not very pretty):

mixin ab()
  .a
    block('a')
  .b
    block('b')
+ab()
  case arguments[0]
    when 'a'
      | contents of a
    when 'b'
      | contents of b

@ForbesLindesay
Copy link
Member

P.S. I don't think that inconsistency really applies because blocks are actually called at the moment rather than "inserted" we just don't support arguments

@jeromew
Copy link
Contributor

jeromew commented Jul 31, 2014

note that op's request can maybe also be solved without blocks, with the lesser known 'dynamic mixins' feature. Here is an example :

mixin ul(list, itemizer)
  ul
    each val, name in list
      +#{'item_as_' + itemizer}(name, val, val+name)

mixin item_as_tab(name, val, id)
  tab: a(href="##{id}")= name

mixin item_as_pane(name, val, id)
  h2= name
  pane(id=id)= val

- var dbg = {a:1, b:2, c:3}
+ul(dbg, 'tab')
+ul(dbg, 'pane')

@maxim-grishaev
Copy link
Author

@jeromew Yes, it can be solved like that, but there is a few problems here: I need define mixin separate from it's call, I need to give some name for it and I MUST type it correctly or I will have an error and that is against all the ideology of templates.

@jeromew
Copy link
Contributor

jeromew commented Jul 31, 2014

yep sorry ; I just saw that @ForbesLindesay had already added the dynamic mixin solution in #1606.

dynamic mixins are resolved at rendering time (they are "dynamic" after all) so they won't protect you from typos. They are useful for me in some cases in order to avoid long switch/cases or when the choice of a mixin depends on a - safe - data coming from a db.

@Artazor
Copy link

Artazor commented Aug 13, 2014

I'm working towards this feature

pugjs/with#3 - here is description of what's done
https://github.com/Artazor/jade - my fork of jade (extended conservatively with mentioned features)

Waiting for @ForbesLindesay to take a look on the changes
Any comments from community appreciated

@ForbesLindesay
Copy link
Member

Mixins are being overhauled as part of 2.0.0 so hopefully this will be resolved by that.

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

No branches or pull requests

4 participants