pugjs / pug

Pug – robust, elegant, feature rich template engine for Node.js
https://pugjs.org
21.54k stars 1.96k forks source link

pseudo "dynamic" includes in static context #3386

Open noraj opened 1 year ago

noraj commented 1 year ago

Discussion

I wanted to make a remark about #2030 but I wasn't able to since the conversation was locked to avoid "me too" comments.

I understand it's impossible or difficult to implement truly dynamic includes because of pre-compilation.

So truly dynamic includes will never be implemented in pug.

Solution suggesting using a syntax that pass all possibles values as arguments is nearly useless, it would end up just being a short syntax for a switch case.

But pug is not used only on dynamic environment like websites but is also often used on staticgen (static website generator).

A staticgen take all sort of languages and templates, and build / compile all that into static assets. So in the case of pug being used in staticgen there is no issue with dynamic inputs since anyway everything is compiled one time.

So could there be an alternative pug compiler autorizing pseudo-dynamic includes for static contexts? Of course dynamic environment like express would still continue to use the classic pug compiler where dynamic includes are not authorized due to their dynamic nature. But staticgens for exemple could call the pug_static compiler where pseudo-dynamic includes are authorized since they can be resolved at compilation time.

Note: In my case I have a several projects using pug with a self-made staticgen from sratch using gulp tasks for building and so I use gulp-pug. I have other projects using Hexo staticgen where is use hexo-render-pug. Just for me having pseudo-dynamic I could avoid thousands of copy-paste per project in a dozen of project. But there is not only Hexo staticgen that use pug but also Eleventy, Cogear.js, Mimogear, Platframe; Starter Project, ADM-dev-kit, INTUITION.DEV, blogdown, Entu, 20ful, statik-site, etc. that use pug in static contect where everything is compiled.

Example

For example I have a page page where I list dozens of categories and I have this kind of block for each category:

                h3.title.is-3#title-tools-a-a A A
                article
                    include content/tools/a_a.pug
                    script(src='js/tablefilter/tools/a_a.js')

                h3.title.is-3#title-tools-b-b B B
                article
                    include content/tools/b_b.pug
                    script(src='js/tablefilter/tools/b_b.js')

[...]

So I wanted to create a mixin like that

mixin category(name)
    - name_hyphen = name.toLowerCase().replace(/\s/g, '-')
    - name_underscore = name_hyphen.replace('-', '_')

    h3.title.is-3(id="#title-tools-#{name_hyphen}")= name
    article
        include content/tools/#{name_underscore}.pug
        script(src='js/tablefilter/tools/#{name_underscore}.js')

So my page could just end being:

include mixins/category.pug

each category in data.categories
            +category(category)

Instead of copy/pasting dozens of times the same block. I have many other examples like this one with hundreds of copy paste.

Now because includes are not dynamic I would have to write something like that and just deport the copy pasting in the mixin which make the use of a mixin half useless (it is still a bit useful as I just have to copy paste the include and not the whole block).

mixin category(name)
    - name_hyphen = name.toLowerCase().replace(/\s/g, '-')
    - name_underscore = name_hyphen.replace('-', '_')

    h3.title.is-3(id="#title-tools-#{name_hyphen}")= name
    article
        case name
            when 'A A'
                include content/tools/a_a.pug
            when 'B B'
                include content/tools/b_b.pug
            when 'C C'
                include content/tools/c_c.pug
            [...]
        script(src='js/tablefilter/tools/#{name_underscore}.js')