tmplr
tmplr copied to clipboard
Add a way to conditionally render parts of a file
I'm trying to create a vite
template that supports conditionally adding certain plugins/dependencies. It would be nice if files could specify blocks to render based on a given variable:
tmplr.yml
- read: include_vite_sass_dts
prompt: 'Include vite-plugin-sass-dts?'
choices: ['Yes', 'No']
vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import checker from "vite-plugin-checker";
{{ #if tmplr.include_vite_sass_dts }}
import sassDts from "vite-plugin-sass-dts";
{{ #endif }}
export default defineConfig({
base: "/vite-template/",
plugins: [
react(),
checker({
typescript: true,
}),
{{ #if tmplr.include_vite_sass_dts }}
sassDts(),
{{ #endif }}
],
});
this already is possible, though not particularly convenient:
# .tmplr.yml
steps:
- if:
prompt: Include vite-plugin-sass-dts?
choices:
- Yes
- No: ''
steps:
- read: vite_sass_dts_import
eval: 'import sassDts from "vite-plugin-sass-dts"'
- read: vite_sass_dts_plugin
eval: 'sassDts(),'
else:
steps:
- read: vite_sass_dts_import
eval: ''
- read: vite_sass_dts_plugin
eval: ''
- update: vite.config.js
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import checker from "vite-plugin-checker";
{{ tmplr.vite_sass_dts_import }}
export default defineConfig({
base: "/vite-template/",
plugins: [
react(),
checker({
typescript: true,
}),
{{ tmplr.vite_sass_dts_plugin }}
],
});
Though it would be pretty nice to implement conditionals inside template files as well, I have a few reservations about this:
- The current template syntax is pretty specific to avoid clashes with other syntax, this is not.
- The current template mechanism is really intentional: it only changes variables read explicitly. This proposition is not (how to evaluate unread / empty variables?)
- The current template evaluation mechanism is a single pass with extreme speed and simplicity (its a simple regex, basically). This requires a parse tree.
- The current template evaluation mechanism can be safely repeated multiple times (for example, to read more variables). The suggested conditionals need to resolved on the first processing of the template.
Subsequently, I would like to try to come up with a solution that makes the conditional rendering a bit more convenient, but also keep the simplicity of the template engine. I suspect an "if" pipe would do something like that, though it would require further contemplation.
# .tmplr.yml
steps:
- read: include_vite_sass_dts
prompt: Include vite-plugin-sass-dts?
choices:
- Yes
- No: ''
- read: vite_sass_dts_import
eval: 'import sassDts from "vite-plugin-sass-dts";'
- read: vite_sass_dts_plugin
eval: 'sassDts(),'
- update: vite.config.js
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import checker from "vite-plugin-checker";
{{ tmplr.vite_sass_dts_import | if: include_vite_sass_dts }}
export default defineConfig({
base: "/vite-template/",
plugins: [
react(),
checker({
typescript: true,
}),
{{ tmplr.vite_sass_dts_plugin | if: include_vite_sass_dts }}
],
});