pugjs / pug

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

Question: How can I extend the include filter to include other templates? #2461

Open Jeff-Tian opened 8 years ago

Jeff-Tian commented 8 years ago

I saw the grammer include:markdown xxx.md to include markdown files, it's very sexy!

I have a lot of existing ejs template files, and I want to include some to my pug template. How can I write a little code to make include:ejs xxx.ejs work?

Thanks!

ForbesLindesay commented 8 years ago

It will "work" out of the box. Unfortunately though, the EJS won't have access to any runtime variables, so it's not actually very useful with templating languages like EJS.

The way this currently works is that the "filter" which is an npm module with the name "jstransformer-" translates the source language (markdown, EJS, etc.) into HTML at compile time. It's important that this happens at compile time because it's much better for performance, but it makes it difficult to handle more advanced use cases.

There are two things that people generally want that I would call "runtime filters":

  1. Compile a string of text that is not known at compile time. e.g. compile a string of markdown read from a database. This can be easily solved by just directly calling the markdown rendering function, so it's not something I'm hugely interested in, but we should keep this use case in mind.
  2. Take the source code, which is known at compile time, and compile it to some kind of JavaScript expression which uses runtime variables to get it's output. EJS compiles to JavaScript, and then that JavaScript returns HTML, for example.

I think the steps to allow filters to return JavaScript rather than HTML working would be:

  1. Decide on the syntax for runtime fitlers. e.g. do we have another special character, instead of : do we define say ? (which we don't currently use) to mean "runtime" and then support ?:filter-name to mean "runtime filter"
  2. Add support for this syntax in pug-lexer (mostly just replicate the filter method for runtime-filter)
  3. Add support for the new token type to pug-parser (mostly just replicate parseFilter and parseIncludeFilter for runtime-filter)
  4. Update pug-filters to add support for runtime-filter. It should call the transformer's (currently undocumented) compileClient method and generate a pug AST token of type Code instead of Text (see https://github.com/pugjs/pug-ast-spec/blob/master/parser.md#code)

All of this could be done via a plugin, but it's a fair bit of work.