From 7ef5ed1709a5368972de2cf0b7a260f133ca42e4 Mon Sep 17 00:00:00 2001 From: biodiscus Date: Mon, 4 Nov 2024 12:28:14 +0100 Subject: [PATCH] feat: add `tempura` preprocessor --- CHANGELOG.md | 8 + README.md | 135 +- examples/tempura/README.md | 13 + examples/tempura/package-lock.json | 6979 +++++++++++++++++ examples/tempura/package.json | 25 + examples/tempura/src/images/favicon.png | Bin 0 -> 550 bytes examples/tempura/src/js/main.js | 1 + examples/tempura/src/scss/styles.scss | 28 + examples/tempura/src/views/pages/home.hbs | 44 + examples/tempura/src/views/pages/homeData.js | 8 + .../tempura/src/views/partials/footer.hbs | 1 + .../tempura/src/views/partials/header.hbs | 1 + .../tempura/src/views/partials/person.hbs | 1 + examples/tempura/webpack.config.js | 81 + package-lock.json | 315 +- package.json | 3 +- src/Loader/Preprocessor.js | 5 +- .../Preprocessors/Tempura/helpers/include.js | 35 + src/Loader/Preprocessors/Tempura/index.js | 138 + .../js-tmpl-tmpr-compile/expected/app.js | 1 + .../expected/img/fig.c6809878.png | Bin 0 -> 1635 bytes .../expected/img/kiwi.da3e3cc9.png | Bin 0 -> 1697 bytes .../expected/img/pear.6b9b072a.png | Bin 0 -> 1759 bytes .../js-tmpl-tmpr-compile/expected/index.html | 13 + .../js-tmpl-tmpr-compile/src/app.js | 10 + .../js-tmpl-tmpr-compile/src/index.hbs | 14 + .../src/partials/content.hbs | 18 + .../src/partials/star.hbs | 2 + .../js-tmpl-tmpr-compile/webpack.config.js | 49 + .../expected/css/style.5a52a33d.css | 13 + .../expected/img/apple.02a7c382.png | Bin 0 -> 1779 bytes .../tempura-default/expected/index.html | 49 + .../expected/js/main.7693a3d5.js | 1 + .../tempura-default/src/views/pages/home.hbs | 49 + .../tempura-default/src/views/pages/main.js | 1 + .../tempura-default/src/views/pages/style.css | 13 + .../src/views/partials/footer.hbs | 1 + .../src/views/partials/header.hbs | 4 + .../tempura-default/webpack.config.js | 64 + .../expected/css/styles.f2a99c01.css | 28 + .../expected/img/favicon.c0ab17be.png | Bin 0 -> 550 bytes .../tempura-render/expected/index.html | 45 + .../expected/js/main.3f2e1834.js | 8 + .../tempura-render/src/images/favicon.png | Bin 0 -> 550 bytes .../tempura-render/src/js/main.js | 1 + .../tempura-render/src/scss/styles.scss | 28 + .../tempura-render/src/views/pages/home.hbs | 44 + .../src/views/partials/footer.hbs | 1 + .../src/views/partials/header.hbs | 1 + .../src/views/partials/person.hbs | 1 + .../tempura-render/webpack.config.js | 65 + test/preprocessor.test.js | 9 + types.d.ts | 1 + 53 files changed, 8207 insertions(+), 148 deletions(-) create mode 100644 examples/tempura/README.md create mode 100644 examples/tempura/package-lock.json create mode 100644 examples/tempura/package.json create mode 100644 examples/tempura/src/images/favicon.png create mode 100644 examples/tempura/src/js/main.js create mode 100644 examples/tempura/src/scss/styles.scss create mode 100644 examples/tempura/src/views/pages/home.hbs create mode 100644 examples/tempura/src/views/pages/homeData.js create mode 100644 examples/tempura/src/views/partials/footer.hbs create mode 100644 examples/tempura/src/views/partials/header.hbs create mode 100644 examples/tempura/src/views/partials/person.hbs create mode 100644 examples/tempura/webpack.config.js create mode 100644 src/Loader/Preprocessors/Tempura/helpers/include.js create mode 100644 src/Loader/Preprocessors/Tempura/index.js create mode 100644 test/cases/_preprocessor/js-tmpl-tmpr-compile/expected/app.js create mode 100644 test/cases/_preprocessor/js-tmpl-tmpr-compile/expected/img/fig.c6809878.png create mode 100644 test/cases/_preprocessor/js-tmpl-tmpr-compile/expected/img/kiwi.da3e3cc9.png create mode 100644 test/cases/_preprocessor/js-tmpl-tmpr-compile/expected/img/pear.6b9b072a.png create mode 100644 test/cases/_preprocessor/js-tmpl-tmpr-compile/expected/index.html create mode 100644 test/cases/_preprocessor/js-tmpl-tmpr-compile/src/app.js create mode 100644 test/cases/_preprocessor/js-tmpl-tmpr-compile/src/index.hbs create mode 100644 test/cases/_preprocessor/js-tmpl-tmpr-compile/src/partials/content.hbs create mode 100644 test/cases/_preprocessor/js-tmpl-tmpr-compile/src/partials/star.hbs create mode 100644 test/cases/_preprocessor/js-tmpl-tmpr-compile/webpack.config.js create mode 100644 test/cases/_preprocessor/tempura-default/expected/css/style.5a52a33d.css create mode 100644 test/cases/_preprocessor/tempura-default/expected/img/apple.02a7c382.png create mode 100644 test/cases/_preprocessor/tempura-default/expected/index.html create mode 100644 test/cases/_preprocessor/tempura-default/expected/js/main.7693a3d5.js create mode 100644 test/cases/_preprocessor/tempura-default/src/views/pages/home.hbs create mode 100644 test/cases/_preprocessor/tempura-default/src/views/pages/main.js create mode 100644 test/cases/_preprocessor/tempura-default/src/views/pages/style.css create mode 100644 test/cases/_preprocessor/tempura-default/src/views/partials/footer.hbs create mode 100644 test/cases/_preprocessor/tempura-default/src/views/partials/header.hbs create mode 100644 test/cases/_preprocessor/tempura-default/webpack.config.js create mode 100644 test/cases/_preprocessor/tempura-render/expected/css/styles.f2a99c01.css create mode 100644 test/cases/_preprocessor/tempura-render/expected/img/favicon.c0ab17be.png create mode 100644 test/cases/_preprocessor/tempura-render/expected/index.html create mode 100644 test/cases/_preprocessor/tempura-render/expected/js/main.3f2e1834.js create mode 100644 test/cases/_preprocessor/tempura-render/src/images/favicon.png create mode 100644 test/cases/_preprocessor/tempura-render/src/js/main.js create mode 100644 test/cases/_preprocessor/tempura-render/src/scss/styles.scss create mode 100644 test/cases/_preprocessor/tempura-render/src/views/pages/home.hbs create mode 100644 test/cases/_preprocessor/tempura-render/src/views/partials/footer.hbs create mode 100644 test/cases/_preprocessor/tempura-render/src/views/partials/header.hbs create mode 100644 test/cases/_preprocessor/tempura-render/src/views/partials/person.hbs create mode 100644 test/cases/_preprocessor/tempura-render/webpack.config.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 81322d36..8f4deb43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Change log +## 4.3.0 (2024-11-04) + +- feat: add preprocessor for [Tempura](https://github.com/lukeed/tempura) template engine. + Supports the static render and template function. +- test: add test for the `tempura` preprocessor +- docs: add documentation for Tempura +- chore: add usage example + ## 4.2.0 (2024-11-03) - feat: add support for Webpack `>= 5.96` to correct inline images into CSS and HTML diff --git a/README.md b/README.md index 70d18072..52b9657c 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,8 @@ Advanced alternative to [html-webpack-plugin](https://github.com/jantimon/html-w - An [entry point](#option-entry) is any HTML template. **Start from HTML**, not from JS. - **Find** and automatic processing of templates in the [entry directory](#option-entry-path). - **Renders** the [template engines](#template-engine) "out of the box": - [Eta](#using-template-eta), [EJS](#using-template-ejs), [Handlebars](#using-template-handlebars), [Nunjucks](#using-template-nunjucks), [Pug](#using-template-pug), [TwigJS](#using-template-twig), [LiquidJS](#using-template-liquidjs). + [Eta](#using-template-eta), [EJS](#using-template-ejs), [Handlebars](#using-template-handlebars), [Nunjucks](#using-template-nunjucks), [Pug](#using-template-pug), [Tempura](#using-template-tempura), [TwigJS](#using-template-twig), [LiquidJS](#using-template-liquidjs). + It is very easy to add support for any template engine. - **Source files** of [`script`](#option-js) and [`style`](#option-css) can be specified directly in HTML: - ``\ No longer need to define source style files in Webpack entry or import styles in JavaScript. @@ -495,6 +496,7 @@ See [boilerplate](https://github.com/webdiscus/webpack-html-scss-boilerplate) - [eta](#loader-option-preprocessor-options-eta) - [ejs](#loader-option-preprocessor-options-ejs) - [handlebars](#loader-option-preprocessor-options-handlebars) + - [tempura](#loader-option-preprocessor-options-tempura) - [nunjucks](#loader-option-preprocessor-options-nunjucks) - [pug](#loader-option-preprocessor-options-pug) - [twig](#loader-option-preprocessor-options-twig) @@ -508,6 +510,7 @@ See [boilerplate](https://github.com/webdiscus/webpack-html-scss-boilerplate) - [Mustache](#using-template-mustache) - [Nunjucks](#using-template-nunjucks) - [Pug](#using-template-pug) + - [Tempura](#using-template-tempura) - [TwigJS](#using-template-twig) 1. [Using template in JavaScript](#template-in-js) 1. [Setup Live Reload](#setup-live-reload) @@ -3657,6 +3660,60 @@ For the complete list of Handlebars `compile` options see [here](https://handleb #### [↑ back to contents](#contents) + + + +#### Options for `preprocessor: 'tempura'` + +[Tempura](https://github.com/lukeed/tempura) is a light and fast template engine with Handlebars-like syntax. + +The preprocessor has built-in `include` helper, to load a partial file. + +```js +{ + preprocessor: 'tempura', + preprocessorOptions: { + // defaults process.cwd(), root path for includes with an absolute path (e.g., /file.html) + root: path.join(__dirname, 'src/views/'), // defaults process.cwd() + // defaults [], an array of paths to use when resolving includes with relative paths + views: [ + 'src/views/includes', // relative path + path.join(__dirname, 'src/views/partials'), // absolute path + ], + blocks: { + // define here custom helpers + bar: ({ value }) => `${value}`, + }, + }, +}, +``` + +For all available options, see the [Tempura API options](https://github.com/lukeed/tempura/blob/master/docs/api.md#options-2). + +**Using build-in `include` helper.** + +The `src` attribute contains a path to the partial file. + +The path relative to current working directory (defaults webpack config directory): + +```hbs +{{#include src='src/views/partials/header.hbs' }} +``` + +The path relative to directory defined in `root` option, e.g. `root: 'src/view'`: +```hbs +{{#include src='partials/header.hbs' }} +``` + +The path relative to one of directories defined in `views` option, e.g. `views: ['src/views/partials']`: +```hbs +{{#include src='header.hbs' }} +``` + +--- + +#### [↑ back to contents](#contents) + #### Options for `preprocessor: 'nunjucks'` @@ -3917,6 +3974,7 @@ Using the [preprocessor](#loader-option-preprocessor), you can compile any templ - [Mustache](https://github.com/janl/mustache.js) - [Nunjucks](https://mozilla.github.io/nunjucks/) - [Pug](https://pugjs.org) +- [Tempura](https://github.com/lukeed/tempura) - [TwigJS](https://github.com/twigjs/twig.js) + + + +
+ + \ No newline at end of file diff --git a/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/app.js b/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/app.js new file mode 100644 index 00000000..bc9600e9 --- /dev/null +++ b/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/app.js @@ -0,0 +1,10 @@ +import tmpl from './partials/content.hbs?lang=en'; + +const locals = { + name: 'World', + people: ['Alexa ', 'Cortana ', 'Siri '], +}; + +document.getElementById('main').innerHTML = tmpl(locals); + +console.log('>> app'); diff --git a/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/index.hbs b/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/index.hbs new file mode 100644 index 00000000..4f706993 --- /dev/null +++ b/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/index.hbs @@ -0,0 +1,14 @@ +{{! expected props to receive }} +{{#expect title }} + + + + + {{ title }} + + + + +
+ + diff --git a/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/partials/content.hbs b/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/partials/content.hbs new file mode 100644 index 00000000..62d1a3ac --- /dev/null +++ b/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/partials/content.hbs @@ -0,0 +1,18 @@ +{{! expected props to receive }} +{{#expect title, name, lang, people }} + +

Hello {{ name }}!

+
Global data: title = "{{ title }}"
+
Query param: lang = "{{ lang }}"
+ +
    + {{#each people as item}} +
  • {{item}}
  • + {{/each}} +
+ +

{{#bar name='Alice' }}

+ + +{{!-- TODO: add supports for include helper in template function --}} +{{!#include src='src/partials/star.hbs' }} diff --git a/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/partials/star.hbs b/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/partials/star.hbs new file mode 100644 index 00000000..4b15fc8c --- /dev/null +++ b/test/cases/_preprocessor/js-tmpl-tmpr-compile/src/partials/star.hbs @@ -0,0 +1,2 @@ +
++ Included partial ++
+ \ No newline at end of file diff --git a/test/cases/_preprocessor/js-tmpl-tmpr-compile/webpack.config.js b/test/cases/_preprocessor/js-tmpl-tmpr-compile/webpack.config.js new file mode 100644 index 00000000..a8508a0e --- /dev/null +++ b/test/cases/_preprocessor/js-tmpl-tmpr-compile/webpack.config.js @@ -0,0 +1,49 @@ +const path = require('path'); +const HtmlBundlerPlugin = require('@test/html-bundler-webpack-plugin'); + +module.exports = { + mode: 'production', + + output: { + path: path.join(__dirname, 'dist/'), + }, + + resolve: { + alias: { + '@images': path.join(__dirname, '../../../fixtures/images'), + }, + }, + + plugins: [ + new HtmlBundlerPlugin({ + entry: { + index: './src/index.hbs', + }, + preprocessor: 'tempura', + preprocessorOptions: { + blocks: { + // test custom helper in template function + bar({ name }) { + return `${name}`; + }, + }, + }, + data: { + // pass global data in all templates + title: 'My Title', + }, + }), + ], + + module: { + rules: [ + { + test: /\.(ico|png|jp?g|svg)$/, + type: 'asset/resource', + generator: { + filename: 'img/[name].[hash:8][ext][query]', + }, + }, + ], + }, +}; diff --git a/test/cases/_preprocessor/tempura-default/expected/css/style.5a52a33d.css b/test/cases/_preprocessor/tempura-default/expected/css/style.5a52a33d.css new file mode 100644 index 00000000..d7b437e0 --- /dev/null +++ b/test/cases/_preprocessor/tempura-default/expected/css/style.5a52a33d.css @@ -0,0 +1,13 @@ +h1 { + color: orangered; +} + +footer { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 40px; + color: #fff; + background-color: #9fa9af; +} diff --git a/test/cases/_preprocessor/tempura-default/expected/img/apple.02a7c382.png b/test/cases/_preprocessor/tempura-default/expected/img/apple.02a7c382.png new file mode 100644 index 0000000000000000000000000000000000000000..c3b5ce07f66020372ad9fffeff0bdb9111cf21cf GIT binary patch literal 1779 zcmV004pr0{{R3_H{EN0001KP)t-s*4Eb7 z*Vpv)^!4@i_xJbO+S=yk=JxjX^78W4)z$3m?BL+w+9>~<>ln$WQr zd70F6ds2)6;~=3cz?Gthpc%ww1cTgMkI!%%pAq5?K+9i~j}e+11Ra1V4Ohiu)~5|0 z)&LQ?tjSmCYIOicWr9~|#Ew(ml8C!4FdW15`*G z5LrPGSnt%NANl2lj=N2PdFNoc*dJ-S4?2O0?UJ^`Fz_4|pcBSZx8#w4Zrd!%Q!N81giFl=h+ifFP0`&zK!G@*?zjk6lYpiM54!R5 zujv6XoZ8nx>T{cRJ`C|7zmALGzI`J9*FSJ5ycba#$@0X27`yE&A%6d$f%^|q>Nqro zULTGF?1*5}%O|WCQ{GF`xYvi{Jh|JL(p8k{ddwn>vCyCp8lAa7p|5b$DJ{$*#$weK&Fz(}f`mZAF^x@di zOcW|}>~%c_oBosP^x^37pt3hU-#hr;{8z=W!-tcOsA*3}-1J{X*zUvea}x5l@PCea z_}=_i5w`kJW7-)UYE9X^?mK$9Hvc_?-{wP|d9k(ksEneyy^*d7Q=9*)7`FIOZ|MW= zvixY<=W7!6E!(vDuOd|YPzO+C1X+X-InGC|NpAOFMHr#UBREWb{*$5^!noO376I(> z-!q2c?L7mFtPl42PXZcY_C~l&iu?RmW%<_h;oN{j{U^m@h-yBZ9dMxkD#Em$<=Im_ z(0@{IKAaNJQf#Aq;J*UI5p8+;6f+R(;GM*}NOkQq|4G$+I2j=03(d=^e(gj5JqcfY zI2oXo@NvU+_u8R;=s&5N52pgO4kib5wx{aDf9k&{AoF1+eK-Z6@Sofpzmz^4=|3s^ zRKK|%px~1q|H5O4NBgf7ofNR}pClAM#3TJT3n2GjwV`7e+=nd7qx?5HV9kG0+=nQ# z4Gle)lC=R}{U^nI2zq=I0@nOj5gzpTrUPvHPfGVN+9ZHV|Bcbzoe5CozcB(b6QI(6 zUj*3Zzpnrs?!V)0ANyxsG513|aU-!T_F9&J+sw`K$pDA?FJr&YI_H=b_mGGa(amxR z$ZE0+xtGzn}M1$5!$|3!#df6Jh($0lcHqeiVj95-%Y|BVG=W^1Y|v&%DE( zL3w;Hl<*L}mdl#Ml&Y-K z4{&9`j#D2UN^VqHRs&+t02~*=PZa6_vaW7sX#rw5CH~Ah1TY>D_^#pH0zJUx^aIq@ zCxE6MOn=h6Pv0Lw`U&7;SvaoU5WsVp;xL=>#SyjS`b8(8b(Qm@FyAb!yzEq+Vmzw` zcu%1f5WBRhzBpg0#>vUX`^EV>bjHgIHGaqIy8wHgJ()>#ZX7*r0HSQw zSG0?>XYGIpgO!CV#?Y}-tNSHKwbR+b@lat{{T)J Vs6AcRANBwM002ovPDHLkV1iIdiy8m` literal 0 HcmV?d00001 diff --git a/test/cases/_preprocessor/tempura-default/expected/index.html b/test/cases/_preprocessor/tempura-default/expected/index.html new file mode 100644 index 00000000..c85462ad --- /dev/null +++ b/test/cases/_preprocessor/tempura-default/expected/index.html @@ -0,0 +1,49 @@ + + + + + Home + + + + + + + + + + +

Header: My header

+ + + + + + + + + +

You have 3 tasks remaining!

+ + +

You've got this 💪🏼

+ + +
    + +
  • Feed the doggo
  • + +
  • Buy groceries
  • + +
  • Exercise, ok
  • + +
+ + + + apple + + +
footer
+ + \ No newline at end of file diff --git a/test/cases/_preprocessor/tempura-default/expected/js/main.7693a3d5.js b/test/cases/_preprocessor/tempura-default/expected/js/main.7693a3d5.js new file mode 100644 index 00000000..2e9cefcb --- /dev/null +++ b/test/cases/_preprocessor/tempura-default/expected/js/main.7693a3d5.js @@ -0,0 +1 @@ +console.log(">> main.js"); \ No newline at end of file diff --git a/test/cases/_preprocessor/tempura-default/src/views/pages/home.hbs b/test/cases/_preprocessor/tempura-default/src/views/pages/home.hbs new file mode 100644 index 00000000..71af7ab8 --- /dev/null +++ b/test/cases/_preprocessor/tempura-default/src/views/pages/home.hbs @@ -0,0 +1,49 @@ + + + + + {{ title }} + + {{! relative path to CSS source file }} + + {{! relative path to JS source file }} + + + + {{! partial path relative to `views` HtmlBundlerPlugin preprocessorOptions }} + {{#include src='header.hbs' }} + + {{! expected props to receive }} + {{#expect title, items }} + + {{! inline variables }} + {{#var count = items.length }} + {{#var suffix = count === 1 ? 'task' : 'tasks' }} + + {{#if count == 0}} +

You're done! 🎉

+ {{#else}} +

You have {{{ count }}} {{{ suffix }}} remaining!

+ + {{#if count == 1}} +

Almost there!

+ {{#elif count > 10}} +

... you must be fried 😔

+ {{#else}} +

You've got this 💪🏼

+ {{/if}} + +
    + {{#each items as todo}} +
  • {{ todo.text }}
  • + {{/each}} +
+ {{/if}} + + {{! webpack alias as path to image source file }} + apple + + {{! partial path relative to `root` HtmlBundlerPlugin preprocessorOptions }} + {{#include src='partials/footer.hbs' }} + + diff --git a/test/cases/_preprocessor/tempura-default/src/views/pages/main.js b/test/cases/_preprocessor/tempura-default/src/views/pages/main.js new file mode 100644 index 00000000..0833b011 --- /dev/null +++ b/test/cases/_preprocessor/tempura-default/src/views/pages/main.js @@ -0,0 +1 @@ +console.log('>> main.js'); diff --git a/test/cases/_preprocessor/tempura-default/src/views/pages/style.css b/test/cases/_preprocessor/tempura-default/src/views/pages/style.css new file mode 100644 index 00000000..d7b437e0 --- /dev/null +++ b/test/cases/_preprocessor/tempura-default/src/views/pages/style.css @@ -0,0 +1,13 @@ +h1 { + color: orangered; +} + +footer { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 40px; + color: #fff; + background-color: #9fa9af; +} diff --git a/test/cases/_preprocessor/tempura-default/src/views/partials/footer.hbs b/test/cases/_preprocessor/tempura-default/src/views/partials/footer.hbs new file mode 100644 index 00000000..b1e16c26 --- /dev/null +++ b/test/cases/_preprocessor/tempura-default/src/views/partials/footer.hbs @@ -0,0 +1 @@ +
footer
diff --git a/test/cases/_preprocessor/tempura-default/src/views/partials/header.hbs b/test/cases/_preprocessor/tempura-default/src/views/partials/header.hbs new file mode 100644 index 00000000..5fd00c14 --- /dev/null +++ b/test/cases/_preprocessor/tempura-default/src/views/partials/header.hbs @@ -0,0 +1,4 @@ +{{! expected props to receive }} +{{#expect header }} + +

Header: {{ header }}

diff --git a/test/cases/_preprocessor/tempura-default/webpack.config.js b/test/cases/_preprocessor/tempura-default/webpack.config.js new file mode 100644 index 00000000..c9c627c3 --- /dev/null +++ b/test/cases/_preprocessor/tempura-default/webpack.config.js @@ -0,0 +1,64 @@ +const path = require('path'); +const HtmlBundlerPlugin = require('@test/html-bundler-webpack-plugin'); + +module.exports = { + mode: 'production', + + output: { + path: path.join(__dirname, 'dist/'), + }, + + resolve: { + alias: { + '@images': path.join(__dirname, '../../../fixtures/images'), + }, + }, + + plugins: [ + new HtmlBundlerPlugin({ + entry: { + index: { + import: './src/views/pages/home.hbs', + data: { + title: 'Home', + header: 'My header', + items: [ + { id: 1, text: 'Feed the doggo' }, + { id: 2, text: 'Buy groceries' }, + { id: 3, text: 'Exercise, ok' }, + ], + }, + }, + }, + preprocessor: 'tempura', + preprocessorOptions: { + // root path for all included partials + root: path.join(__dirname, 'src/views/'), + // find included partials in the paths + views: [path.join(__dirname, 'src/views/partials/')], + }, + js: { + filename: 'js/[name].[contenthash:8].js', // JS output filename + }, + css: { + filename: 'css/[name].[contenthash:8].css', // CSS output filename + }, + }), + ], + + module: { + rules: [ + { + test: /\.css$/, + use: ['css-loader'], + }, + { + test: /\.(png|svg|jpe?g|webp)$/i, + type: 'asset/resource', + generator: { + filename: 'img/[name].[hash:8][ext]', + }, + }, + ], + }, +}; diff --git a/test/cases/_preprocessor/tempura-render/expected/css/styles.f2a99c01.css b/test/cases/_preprocessor/tempura-render/expected/css/styles.f2a99c01.css new file mode 100644 index 00000000..8ef7a599 --- /dev/null +++ b/test/cases/_preprocessor/tempura-render/expected/css/styles.f2a99c01.css @@ -0,0 +1,28 @@ +body { + font-family: "OpenSans", sans-serif; + margin: 0; +} + +h1 { + color: #f0772b; +} + +.header { + padding: 20px 0; + text-align: center; + color: #351704; + background-color: #ffddaa; +} + +.footer { + padding: 10px 0; + text-align: center; + color: white; + background-color: #f0772b; +} + +.container { + display: flex; + flex-direction: column; + align-items: center; +} \ No newline at end of file diff --git a/test/cases/_preprocessor/tempura-render/expected/img/favicon.c0ab17be.png b/test/cases/_preprocessor/tempura-render/expected/img/favicon.c0ab17be.png new file mode 100644 index 0000000000000000000000000000000000000000..3f679280c902cce52214a78f59ad0fff389e9028 GIT binary patch literal 550 zcmV+>0@?kEP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv0004%NklVT3AR)ZdbZk%tEMPyb>FXbI;5;55^hJ{Ey^g zCJSp>`qj7k9*d8B^9ATrBFWUmaNw}1%TJdaPWG*PQBI!k6(p(Wie)1Xj}GE*1b%=Q z#m)jU2otX^q=84_um}A-Nr+Zo6wL9#FBdbLn>F>Z$cN%C!Mw5N)6e2899k_Pi}SxxoSBI3wq_Kh$D%Y>gOaR7^mVlQ2LCKAycn5A z6lEm%Ja4Ao@C!OkH2$rwfCz%XF%7lIPmM!Wi4K#aL*TgovO=GxRf-x)QLlK^S=-g6 zGHU8WMPUx~Y4I>HO}KNp&dH5*8}^_m(^OS=6iU}zZZ~7+g&^OA1Y>7jJp oqpI6)opGlqg}mF}d>%qx0S(0QN=ErU-~a#s07*qoM6N<$g3v4TS^xk5 literal 0 HcmV?d00001 diff --git a/test/cases/_preprocessor/tempura-render/expected/index.html b/test/cases/_preprocessor/tempura-render/expected/index.html new file mode 100644 index 00000000..9696a426 --- /dev/null +++ b/test/cases/_preprocessor/tempura-render/expected/index.html @@ -0,0 +1,45 @@ + + + + + + + Tempura + + + + + + + +
Header
+ +
+

Tempura

+ + + + + + + + + Custom helper! 🎉 + + +

3 persons:

+ +
    + +
  • Nils is 20 years old.
  • + +
  • Robert is 10 years old.
  • + +
  • Margaret is 40 years old.
  • + +
+
+ + + + \ No newline at end of file diff --git a/test/cases/_preprocessor/tempura-render/expected/js/main.3f2e1834.js b/test/cases/_preprocessor/tempura-render/expected/js/main.3f2e1834.js new file mode 100644 index 00000000..8ce58df5 --- /dev/null +++ b/test/cases/_preprocessor/tempura-render/expected/js/main.3f2e1834.js @@ -0,0 +1,8 @@ +/******/ (() => { // webpackBootstrap +/*!************************!*\ + !*** ./src/js/main.js ***! + \************************/ +console.log('>> main'); + +/******/ })() +; \ No newline at end of file diff --git a/test/cases/_preprocessor/tempura-render/src/images/favicon.png b/test/cases/_preprocessor/tempura-render/src/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..3f679280c902cce52214a78f59ad0fff389e9028 GIT binary patch literal 550 zcmV+>0@?kEP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv0004%NklVT3AR)ZdbZk%tEMPyb>FXbI;5;55^hJ{Ey^g zCJSp>`qj7k9*d8B^9ATrBFWUmaNw}1%TJdaPWG*PQBI!k6(p(Wie)1Xj}GE*1b%=Q z#m)jU2otX^q=84_um}A-Nr+Zo6wL9#FBdbLn>F>Z$cN%C!Mw5N)6e2899k_Pi}SxxoSBI3wq_Kh$D%Y>gOaR7^mVlQ2LCKAycn5A z6lEm%Ja4Ao@C!OkH2$rwfCz%XF%7lIPmM!Wi4K#aL*TgovO=GxRf-x)QLlK^S=-g6 zGHU8WMPUx~Y4I>HO}KNp&dH5*8}^_m(^OS=6iU}zZZ~7+g&^OA1Y>7jJp oqpI6)opGlqg}mF}d>%qx0S(0QN=ErU-~a#s07*qoM6N<$g3v4TS^xk5 literal 0 HcmV?d00001 diff --git a/test/cases/_preprocessor/tempura-render/src/js/main.js b/test/cases/_preprocessor/tempura-render/src/js/main.js new file mode 100644 index 00000000..89ae7c12 --- /dev/null +++ b/test/cases/_preprocessor/tempura-render/src/js/main.js @@ -0,0 +1 @@ +console.log('>> main'); diff --git a/test/cases/_preprocessor/tempura-render/src/scss/styles.scss b/test/cases/_preprocessor/tempura-render/src/scss/styles.scss new file mode 100644 index 00000000..7d1463e7 --- /dev/null +++ b/test/cases/_preprocessor/tempura-render/src/scss/styles.scss @@ -0,0 +1,28 @@ +body { + font-family: 'OpenSans', sans-serif; + margin: 0; +} + +h1 { + color: #f0772b; +} + +.header { + padding: 20px 0; + text-align: center; + color: #351704; + background-color: #ffddaa; +} + +.footer { + padding: 10px 0; + text-align: center; + color: white; + background-color: #f0772b; +} + +.container { + display: flex; + flex-direction: column; + align-items: center; +} diff --git a/test/cases/_preprocessor/tempura-render/src/views/pages/home.hbs b/test/cases/_preprocessor/tempura-render/src/views/pages/home.hbs new file mode 100644 index 00000000..ccaff4ac --- /dev/null +++ b/test/cases/_preprocessor/tempura-render/src/views/pages/home.hbs @@ -0,0 +1,44 @@ +{{! expected props to receive }} +{{#expect title, header, persons }} + + + + + + {{ title }} + {{! reference to source image }} + + {{! references to source style and script }} + + + + + {{#include src='header.hbs' }} + +
+

Tempura

+ + {{! inline variables }} + {{#var count = persons.length }} + + {{#if count <= 1}} + {{#var str_person = 'person' }} + {{#else}} + {{#var str_person = 'persons' }} + {{/if}} + + {{#bar value="Custom helper! 🎉"}} + + {{! using of the arraySize helper }} +

{{ count }} {{ str_person }}:

+ +
    + {{#each persons as person}} +
  • {{person.name}} is {{person.age}} years old.
  • + {{/each}} +
+
+ + {{#include src='footer.hbs' }} + + diff --git a/test/cases/_preprocessor/tempura-render/src/views/partials/footer.hbs b/test/cases/_preprocessor/tempura-render/src/views/partials/footer.hbs new file mode 100644 index 00000000..5191aac4 --- /dev/null +++ b/test/cases/_preprocessor/tempura-render/src/views/partials/footer.hbs @@ -0,0 +1 @@ + diff --git a/test/cases/_preprocessor/tempura-render/src/views/partials/header.hbs b/test/cases/_preprocessor/tempura-render/src/views/partials/header.hbs new file mode 100644 index 00000000..2a5bd76b --- /dev/null +++ b/test/cases/_preprocessor/tempura-render/src/views/partials/header.hbs @@ -0,0 +1 @@ +
Header
diff --git a/test/cases/_preprocessor/tempura-render/src/views/partials/person.hbs b/test/cases/_preprocessor/tempura-render/src/views/partials/person.hbs new file mode 100644 index 00000000..a931a97f --- /dev/null +++ b/test/cases/_preprocessor/tempura-render/src/views/partials/person.hbs @@ -0,0 +1 @@ +
  • {{person.name}} is {{person.age}} years old.
  • diff --git a/test/cases/_preprocessor/tempura-render/webpack.config.js b/test/cases/_preprocessor/tempura-render/webpack.config.js new file mode 100644 index 00000000..68adbdc7 --- /dev/null +++ b/test/cases/_preprocessor/tempura-render/webpack.config.js @@ -0,0 +1,65 @@ +const path = require('path'); +const HtmlBundlerPlugin = require('@test/html-bundler-webpack-plugin'); + +module.exports = { + mode: 'development', + + output: { + path: path.resolve(__dirname, 'dist'), + clean: true, + }, + + plugins: [ + new HtmlBundlerPlugin({ + entry: { + // define templates here + index: { + import: 'src/views/pages/home.hbs', // => dist/index.html + // pass data to template as an object + data: { + title: 'Tempura', + persons: [ + { name: 'Nils', age: 20 }, + { name: 'Robert', age: 10 }, + { name: 'Margaret', age: 40 }, + ], + }, + }, + }, + // specify the `tempura` template engine + preprocessor: 'tempura', + // define tempura options + preprocessorOptions: { + views: ['src/views/partials'], + blocks: { + // define custom helpers + bar: ({ value }) => `${value}`, + }, + }, + js: { + // output filename of compiled JavaScript + filename: 'js/[name].[contenthash:8].js', + }, + css: { + // output filename of extracted CSS + filename: 'css/[name].[contenthash:8].css', + }, + }), + ], + + module: { + rules: [ + { + test: /\.(scss)$/, + use: ['css-loader', 'sass-loader'], + }, + { + test: /\.(png|svg|jpe?g|webp)$/i, + type: 'asset/resource', + generator: { + filename: 'img/[name].[hash:8][ext]', + }, + }, + ], + }, +}; diff --git a/test/preprocessor.test.js b/test/preprocessor.test.js index cd94d3f0..4423a8e5 100644 --- a/test/preprocessor.test.js +++ b/test/preprocessor.test.js @@ -64,6 +64,11 @@ describe('other preprocessors', () => { //test('jsx', () => compareFiles('_preprocessor/preprocessor-jsx')); }); +describe('tempura', () => { + test('default', () => compareFiles('_preprocessor/tempura-default')); + test('render', () => compareFiles('_preprocessor/tempura-render')); +}); + describe('special use cases', () => { test('preprocessor function', () => compareFiles('_preprocessor/preprocessor-function')); test('preprocessor null', () => compareFiles('_preprocessor/preprocessor-return-null')); @@ -95,4 +100,8 @@ describe('usage template in js on client side', () => { // Twig test('twig: compile to fn', () => compareFiles('_preprocessor/js-tmpl-twig-compile')); + + // Tempura + // TODO: locally passes the test, but on GitHub fail because the generated JS code contains other char for minimized function name + //test('tempura: compile to fn', () => compareFiles('_preprocessor/js-tmpl-tmpr-compile')); }); diff --git a/types.d.ts b/types.d.ts index f5e390c2..6298e8d7 100644 --- a/types.d.ts +++ b/types.d.ts @@ -268,6 +268,7 @@ type Preprocessor = | 'handlebars' | 'nunjucks' | 'pug' + | 'tempura' | 'twig' | ((content: string, loaderContext: BundlerPluginLoaderContext) => string | Promise | undefined);