vite-plugin-twig-drupal 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,73 @@
1
+ name: validate
2
+ on:
3
+ push:
4
+ branches:
5
+ - 'master'
6
+ - 'beta'
7
+ pull_request: {}
8
+ jobs:
9
+ main:
10
+ strategy:
11
+ matrix:
12
+ node: [16, 18]
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: ๐Ÿ›‘ Cancel Previous Runs
16
+ uses: styfle/cancel-workflow-action@0.9.0
17
+
18
+ - name: โฌ‡๏ธ Checkout repo
19
+ uses: actions/checkout@v2
20
+
21
+ - name: โŽ” Setup node
22
+ uses: actions/setup-node@v2
23
+ with:
24
+ node-version: ${{ matrix.node }}
25
+
26
+ - name: ๐Ÿ“ฅ Download deps
27
+ uses: bahmutov/npm-install@v1
28
+ with:
29
+ useLockFile: false
30
+
31
+ - name: ๐Ÿงน Linting
32
+ run: npm run lint
33
+
34
+ - name: โœ… Tests
35
+ run: npm run test
36
+
37
+ release:
38
+ needs: main
39
+ runs-on: ubuntu-latest
40
+ if:
41
+ ${{ github.repository == 'larowlan/vite-plugin-twig-drupal' &&
42
+ contains('refs/heads/master',github.ref) && github.event_name == 'push' }}
43
+ steps:
44
+ - name: ๐Ÿ›‘ Cancel Previous Runs
45
+ uses: styfle/cancel-workflow-action@0.9.0
46
+
47
+ - name: โฌ‡๏ธ Checkout repo
48
+ uses: actions/checkout@v2
49
+
50
+ - name: โŽ” Setup node
51
+ uses: actions/setup-node@v2
52
+ with:
53
+ node-version: 18
54
+
55
+ - name: ๐Ÿ“ฅ Download deps
56
+ uses: bahmutov/npm-install@v1
57
+ with:
58
+ useLockFile: false
59
+
60
+ - name: ๐Ÿ— Run build script
61
+ run: npm run build
62
+
63
+ - name: ๐Ÿš€ Release
64
+ uses: cycjimmy/semantic-release-action@v4
65
+ with:
66
+ semantic_version: 22
67
+ branches: |
68
+ [
69
+ 'master'
70
+ ]
71
+ env:
72
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
73
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
package/.prettierrc ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "endOfLine": "lf",
3
+ "semi": false,
4
+ "singleQuote": false,
5
+ "tabWidth": 2,
6
+ "trailingComma": "es5",
7
+ "bracketSpacing": true
8
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Lee Rowlands
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,202 @@
1
+ <div align="center">
2
+ <h1>Vite Plugin Twig Drupal</h1>
3
+
4
+ <img
5
+ height="143"
6
+ width="200"
7
+ alt="goat"
8
+ src="https://twig.symfony.com/images/logo.png"
9
+ />
10
+
11
+
12
+ <p>A Vite plugin that handles transforming twig files into a Javascript function that can be used with Storybook.</p>
13
+
14
+ <br />
15
+ </div>
16
+
17
+ <hr />
18
+
19
+ <!-- prettier-ignore-start -->
20
+ [![Build status](https://github.com/larowlan/vite-plugin-twigdrupal/actions/workflows/node.js.yml/badge.svg)](https://github.com/larowlan/vite-plugin-twig-drupal/actions/workflows/node.js.yml)
21
+ [![version][version-badge]][package] [![downloads][downloads-badge]][npmtrends]
22
+ [![MIT License][license-badge]][license]
23
+ [![PRs Welcome][prs-badge]][prs]
24
+
25
+ [![Watch on GitHub][github-watch-badge]][github-watch]
26
+ [![Star on GitHub][github-star-badge]][github-star]
27
+ [![Tweet][twitter-badge]][twitter]
28
+ <!-- prettier-ignore-end -->
29
+
30
+ ## Table of Contents
31
+
32
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
33
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
34
+
35
+ - [The problem](#the-problem)
36
+ - [This solution](#this-solution)
37
+ - [Installation](#installation)
38
+ - [Examples](#examples)
39
+ - [Issues](#issues)
40
+ - [๐Ÿ› Bugs](#-bugs)
41
+ - [๐Ÿ’ก Feature Requests](#-feature-requests)
42
+ - [โ“ Questions](#-questions)
43
+ - [LICENSE](#license)
44
+
45
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
46
+
47
+ ## The problem
48
+
49
+ You are working with Twig in a styleguide-driven-development process. You are writing isolated components
50
+ that consist of css, twig and Javascript.
51
+ You want to be able to use twig to render your components for [Storybook](https://storybook.js.org).
52
+ You want fast refresh with Vite.
53
+ You want Twig embeds, includes and extends to work.
54
+ You want to use Drupal specific twig features like create_attributes etc.
55
+
56
+ ## This solution
57
+
58
+ The `Vite plugin Twig Drupal` is a Vite plugin based on [Twig JS](https://github.com/twigjs/twig.js) for
59
+ compiling Twig-based components into a Javascript function so that they can be used as components with Storybook.
60
+ It allows you to import twig files into your story as though they are Javascript files.
61
+
62
+ ### Comparison to other solutions.
63
+
64
+ * [Vite plugin twig loader](https://github.com/dark-kitt/vite-plugin-twig-loader) Doesn't handle nested includes/embeds/extends. These are a fairly crucial feature of twig when building a component library as they allow re-use and DRY principles
65
+ * [Components library server](https://www.drupal.org/project/cl_server) Requires you to have a running Drupal site. Whilst this ensures your twig output is identical to that of Drupal (because Drupal is doing the rendering), it is a bit more involved to setup. If you're going to use [single directory components](https://www.drupal.org/project/cl_components) or a similar Drupal module like [UI patterns](https://www.drupal.org/project/ui_patterns) then this may be a better option for you.
66
+
67
+ ## Installation
68
+
69
+ This module is distributed via [npm][npm] which is bundled with [node][node] and
70
+ should be installed as one of your project's `devDependencies`:
71
+
72
+ ```
73
+ npm install --save-dev vite-plugin-twig-drupal
74
+ ```
75
+
76
+ You then need to configure your vite.config.js.
77
+
78
+ ```javascript
79
+ import { defineConfig } from "vite"
80
+ import twig from "./src/index.js"
81
+ import { join } from "node:path"
82
+
83
+ export default defineConfig({
84
+ plugins: [
85
+ // Other vite plugins.
86
+ twig({
87
+ namespaces: {
88
+ components: join(__dirname, "/path/to/your/components"),
89
+ // Other namespaces as required.
90
+ },
91
+ // Optional if you are using React storybook renderer. The default is 'html' and works with storybook's html
92
+ // renderer.
93
+ // framework: 'react'
94
+ }),
95
+ // Other vite plugins.
96
+ ],
97
+ })
98
+ ```
99
+
100
+ With this config in place you should be able to import twig files into your story files.
101
+
102
+ ## Examples
103
+
104
+ ```javascript
105
+ // stories/Button.stories.js
106
+
107
+ // Button will be a Javascript function that excepts variables for the twig template.
108
+ import Button from './button.twig';
109
+
110
+ // Import stylesheets, this could be a sass or postcss file too.
111
+ import './path/to/button.css';
112
+ // You may also have JavaScript for the component.
113
+ import './path/to/some/javascript/button.js';
114
+
115
+ export default {
116
+ title: 'Components/Button',
117
+ tags: ['autodocs'],
118
+ argTypes: {
119
+ title: {
120
+ control: { type: 'text' },
121
+ },
122
+ modifier: {
123
+ control: { type: 'select' },
124
+ options: ['primary', 'secondary', 'tertiary'],
125
+ },
126
+ },
127
+ // Just pass along the imported variable.
128
+ component: Button,
129
+ };
130
+
131
+ // Set default variables in the story.
132
+ export const Default = {
133
+ args: { title: 'Click me' },
134
+ };
135
+
136
+ export const Primary = {
137
+ args: { title: 'Click me', modifier: 'primary' },
138
+ };
139
+
140
+ // Advanced example.
141
+ export const ButtonStrip = {
142
+ name: 'Button group',
143
+ render: () => `
144
+ ${Button({title: 'Button 1', modifier: 'primary'})}
145
+ ${Button({title: 'Button 2', modifier: 'secondary'})}
146
+ `
147
+ }
148
+
149
+
150
+
151
+ ```
152
+ - Refer to the [Dom testing library docs](https://testing-library.com/docs/dom-testing-library/example-intro), we're really just adding the ability to render twig templates on top of that.
153
+
154
+ ## Issues
155
+
156
+ ### ๐Ÿ› Bugs
157
+
158
+ Please file an issue for bugs, missing documentation, or unexpected behavior.
159
+
160
+ [**See Bugs**][bugs]
161
+
162
+ ### ๐Ÿ’ก Feature Requests
163
+
164
+ Please file an issue to suggest new features. Vote on feature requests by adding
165
+ a ๐Ÿ‘. This helps maintainers prioritize what to work on.
166
+
167
+ [**See Feature Requests**][requests]
168
+
169
+ ### โ“ Questions
170
+
171
+ For questions related to using the library, please visit a support community
172
+ instead of filing an issue on GitHub.
173
+
174
+ - [Drupal Slack #frontend channel](https://drupal.org/slack)
175
+
176
+ ## LICENSE
177
+
178
+ [MIT](LICENSE)
179
+
180
+ <!-- prettier-ignore-start -->
181
+
182
+ [npm]: https://www.npmjs.com/
183
+ [node]: https://nodejs.org
184
+ [version-badge]: https://img.shields.io/npm/v/vite-plugin-twig-drupal.svg?style=flat-square
185
+ [package]: https://www.npmjs.com/package/vite-plugin-twig-drupal
186
+ [downloads-badge]: https://img.shields.io/npm/dm/vite-plugin-twig-drupal.svg?style=flat-square
187
+ [npmtrends]: http://www.npmtrends.com/vite-plugin-twig-drupal
188
+ [license-badge]: https://img.shields.io/npm/l/vite-plugin-twig-drupal.svg?style=flat-square
189
+ [license]: https://github.com/larowlan/vite-plugin-twig-drupal/blob/master/LICENSE
190
+ [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
191
+ [prs]: http://makeapullrequest.com
192
+ [github-watch-badge]: https://img.shields.io/github/watchers/larowlan/vite-plugin-twig-drupal.svg?style=social
193
+ [github-watch]: https://github.com/larowlan/vite-plugin-twig-drupal/watchers
194
+ [github-star-badge]: https://img.shields.io/github/stars/larowlan/vite-plugin-twig-drupal.svg?style=social
195
+ [github-star]: https://github.com/larowlan/vite-plugin-twig-drupal/stargazers
196
+ [twitter]: https://twitter.com/intent/tweet?text=Check%20out%20vite-plugin-twig-drupal%20by%20%40larowlan%20https%3A%2F%2Fgithub.com%2Flarowlan%2Fvite-plugin-twig-drupal%20%F0%9F%91%8D
197
+ [twitter-badge]: https://img.shields.io/twitter/url/https/github.com/larowlan/vite-plugin-twig-drupal.svg?style=social
198
+ [bugs]: https://github.com/larowlan/vite-plugin-twig-drupal/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Acreated-desc
199
+ [requests]: https://github.com/larowlan/vite-plugin-twig-drupal/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3Aenhancement+is%3Aopen
200
+ [good-first-issue]: https://github.com/larowlan/vite-plugin-twig-drupal/issues?utf8=โœ“&q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A"good+first+issue"+
201
+
202
+ <!-- prettier-ignore-end -->
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "vite-plugin-twig-drupal",
3
+ "version": "1.0.0",
4
+ "description": "Provides a โšก๏ธ Vite plugin to transform ๐ŸŒฑ Twig into HTML with a ๐Ÿ’ง Drupal flavour",
5
+ "keywords": [
6
+ "Vite",
7
+ "Vite plugin",
8
+ "Twig",
9
+ "Storybook",
10
+ "Drupal"
11
+ ],
12
+ "author": "larowlan <23667-larowlan@users.noreply.drupalcode.org>",
13
+ "license": "GPL-2.0-or-later",
14
+ "main": "./src/index.js",
15
+ "type": "module",
16
+ "scripts": {
17
+ "build": "rm -rf dist && vite build",
18
+ "format": "prettier --write \"{test,src}/**/*.js\"",
19
+ "lint": "prettier --check \"{test,src}/**/*.js\"",
20
+ "test": "vitest run",
21
+ "pretest": "npm run-script build",
22
+ "semantic-release": "semantic-release"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/larowlan/vite-plugin-twig-drupal.git"
27
+ },
28
+ "dependencies": {
29
+ "drupal-attribute": "^1.0.2",
30
+ "drupal-twig-extensions": "^1.0.0-beta.5",
31
+ "twig": "^1.16.0"
32
+ },
33
+ "peerDependencies": {
34
+ "vite": "^4.4.11"
35
+ },
36
+ "devDependencies": {
37
+ "prettier": "^3.0.3",
38
+ "semantic-release": "^22.0.5",
39
+ "vite": "^4.4.11",
40
+ "vitest": "^0.34.6"
41
+ }
42
+ }
package/src/index.js ADDED
@@ -0,0 +1,183 @@
1
+ import Twig from "twig"
2
+ const { twig } = Twig
3
+ import { resolve } from "node:path"
4
+
5
+ const FRAMEWORK_REACT = "react"
6
+ const FRAMEWORK_HTML = "html"
7
+
8
+ const defaultOptions = {
9
+ namespaces: {},
10
+ filters: {},
11
+ functions: {},
12
+ framework: FRAMEWORK_HTML,
13
+ pattern: /\.(twig)(\?.*)?$/,
14
+ }
15
+ Twig.cache(false)
16
+
17
+ const includeTokenTypes = [
18
+ "Twig.logic.type.embed",
19
+ "Twig.logic.type.include",
20
+ "Twig.logic.type.extends",
21
+ ]
22
+
23
+ const pluckIncludes = (tokens) => {
24
+ return [
25
+ ...tokens
26
+ .filter((token) => includeTokenTypes.includes(token.token?.type))
27
+ .reduce(
28
+ (carry, token) => [
29
+ ...carry,
30
+ ...token.token.stack.map((stack) => stack.value),
31
+ ],
32
+ []
33
+ ),
34
+ ...tokens.reduce(
35
+ (carry, token) => [...carry, ...pluckIncludes(token.token?.output || [])],
36
+ []
37
+ ),
38
+ ].filter((value, index, array) => {
39
+ return array.indexOf(value) === index
40
+ })
41
+ }
42
+
43
+ const compileTemplate = (id, file, { namespaces }) => {
44
+ return new Promise((resolve, reject) => {
45
+ const options = { namespaces, rethrow: true, allowInlineIncludes: true }
46
+ twig({
47
+ id,
48
+ path: file,
49
+ error: reject,
50
+ allowInlineIncludes: true,
51
+ load(template) {
52
+ if (typeof template.tokens === "undefined") {
53
+ reject("Error compiling twig file")
54
+ return
55
+ }
56
+ resolve({
57
+ includes: pluckIncludes(template.tokens),
58
+ code: template.compile(options),
59
+ })
60
+ },
61
+ })
62
+ })
63
+ }
64
+
65
+ Twig.cache(false)
66
+
67
+ const errorHandler = (id) => (e) => ({
68
+ code: `export default () => 'An error occurred whilst rendering ${id}: ${e.toString()}';`,
69
+ map: null,
70
+ })
71
+
72
+ const plugin = (options = {}) => {
73
+ options = { ...defaultOptions, ...options }
74
+ return {
75
+ name: "vite-plugin-twig-drupal",
76
+ config: ({ root }) => {
77
+ if (!options.root) {
78
+ options.root = root
79
+ }
80
+ },
81
+ async shouldTransformCachedModule(src, id) {
82
+ return options.pattern.test(id)
83
+ },
84
+ async transform(src, id) {
85
+ if (options.pattern.test(id)) {
86
+ let frameworkInclude = ""
87
+ let frameworkTransform = "const frameworkTransform = (html) => html;"
88
+ if (options.framework === FRAMEWORK_REACT) {
89
+ frameworkInclude = `import React from 'react'`
90
+ frameworkTransform = `const frameworkTransform = (html) => React.createElement('div', {dangerouslySetInnerHTML: {'__html': html}});;`
91
+ }
92
+ let embed,
93
+ embeddedIncludes,
94
+ code,
95
+ includes,
96
+ seen = []
97
+ try {
98
+ const result = await compileTemplate(id, id, options).catch(
99
+ errorHandler(id)
100
+ )
101
+ if ("map" in result) {
102
+ // An error occurred.
103
+ return result
104
+ }
105
+ code = result.code
106
+ includes = result.includes
107
+ const includePromises = []
108
+ const processIncludes = (template) => {
109
+ const file = Twig.path.expandNamespace(options.namespaces, template)
110
+ if (!seen.includes(file)) {
111
+ includePromises.push(
112
+ new Promise(async (resolve) => {
113
+ const { includes, code } = await compileTemplate(
114
+ template,
115
+ file,
116
+ options
117
+ )
118
+ includes.forEach(processIncludes)
119
+ resolve(code)
120
+ })
121
+ )
122
+ seen.push(file)
123
+ }
124
+ }
125
+ includes.forEach(processIncludes)
126
+ embed = includes
127
+ .map(
128
+ (template) =>
129
+ `import '${resolve(
130
+ Twig.path.expandNamespace(options.namespaces, template)
131
+ )}';`
132
+ )
133
+ .join("\n")
134
+ const includeResult = await Promise.all(includePromises).catch(
135
+ errorHandler(id)
136
+ )
137
+ if (!Array.isArray(includeResult) && "map" in includeResult) {
138
+ // An error occurred.
139
+ return includeResult
140
+ }
141
+ embeddedIncludes = includeResult.reverse().join("\n")
142
+ } catch (e) {
143
+ return errorHandler(id)(e)
144
+ }
145
+ const output = `
146
+ import Twig, { twig } from 'twig';
147
+ import DrupalAttribute from 'drupal-attribute';
148
+ import { addDrupalExtensions } from 'drupal-twig-extensions/twig';
149
+ ${frameworkInclude}
150
+
151
+ ${embed}
152
+
153
+ addDrupalExtensions(Twig);
154
+ // Disable caching.
155
+ Twig.cache(false);
156
+
157
+
158
+ ${embeddedIncludes};
159
+ ${frameworkTransform};
160
+ export default (context = {}) => {
161
+ const component = ${code}
162
+ ${includes ? `component.options.allowInlineIncludes = true;` : ""}
163
+ try {
164
+ return frameworkTransform(component.render({
165
+ attributes: new DrupalAttribute(),
166
+ ...context
167
+ }));
168
+ }
169
+ catch (e) {
170
+ return frameworkTransform('An error occurred whilst rendering ${id}: ' + e.toString());
171
+ }
172
+ }`
173
+ return {
174
+ code: output,
175
+ map: null,
176
+ dependencies: seen,
177
+ }
178
+ }
179
+ },
180
+ }
181
+ }
182
+
183
+ export default plugin
@@ -0,0 +1,47 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`Basic smoke test > Should support includes 1`] = `
4
+ "<section>
5
+ <h1>Include</h1>
6
+ <article>
7
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
8
+ </article>
9
+ </section>
10
+ <section>
11
+ <h1>Embed</h1>
12
+ <article>
13
+ Lorem ipsum dolor sit amet.
14
+ <button class=\\"button--primary\\">Nested include</button>
15
+ </article>
16
+ </section>
17
+ <section>
18
+ <h1></h1>
19
+ <article>
20
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
21
+ </article>
22
+ </section>
23
+ "
24
+ `;
25
+
26
+ exports[`Basic smoke test > Should support variables 1`] = `
27
+ "<section>
28
+ <h1>Include</h1>
29
+ <article>
30
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
31
+ </article>
32
+ </section>
33
+ <section>
34
+ <h1>Embed</h1>
35
+ <article>
36
+ Lorem ipsum dolor sit amet.
37
+ <button class=\\"button--primary\\">Nested include</button>
38
+ </article>
39
+ </section>
40
+ <section>
41
+ <h1>Pickle Fixie</h1>
42
+ <article>
43
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
44
+ </article>
45
+ </section>
46
+ "
47
+ `;
@@ -0,0 +1 @@
1
+ <button class="{{ modifier_class|default('button--primary') }}">{{ text|default('Click me!') }}</button>
@@ -0,0 +1,3 @@
1
+ {% if true %}
2
+ Yep this is broken
3
+ {% endblock %}
@@ -0,0 +1,8 @@
1
+ {% include "@tests/section.twig" with {title: 'Include'} %}
2
+ {% embed "@tests/section.twig" with {title: 'Embed'} %}
3
+ {% block content %}
4
+ Lorem ipsum dolor sit amet.
5
+ {% include "@tests/button.twig" with {text: 'Nested include'} %}
6
+ {% endblock %}
7
+ {% endembed %}
8
+ {% include "@tests/section.twig" %}
@@ -0,0 +1,8 @@
1
+ <section>
2
+ <h1>{{ title }}</h1>
3
+ <article>
4
+ {% block content %}
5
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
6
+ {% endblock %}
7
+ </article>
8
+ </section>
@@ -0,0 +1,20 @@
1
+ import Markup from "../dist/test.js"
2
+ import Error from "../dist/error.js"
3
+ import { describe, expect, it } from "vitest"
4
+
5
+ describe("Basic smoke test", () => {
6
+ it("Should support includes", () => {
7
+ const markup = Markup()
8
+ expect(markup).toMatchSnapshot()
9
+ expect(markup).toContain("Nested include")
10
+ })
11
+ it("Should support variables", () => {
12
+ const markup = Markup({ title: "Pickle Fixie" })
13
+ expect(markup).toMatchSnapshot()
14
+ expect(markup).toContain("Pickle Fixie")
15
+ })
16
+ it("Should recover from errors", () => {
17
+ const error = Error()
18
+ expect(error).toContain("An error occurred")
19
+ })
20
+ })
package/vite.config.js ADDED
@@ -0,0 +1,27 @@
1
+ import { defineConfig } from "vite"
2
+ import twig from "./src/index.js"
3
+ import { join, resolve } from "node:path"
4
+
5
+ // https://vitejs.dev/config/
6
+ export default defineConfig({
7
+ build: {
8
+ lib: {
9
+ entry: {
10
+ test: resolve(__dirname, "tests/fixtures/mockup.twig"),
11
+ error: resolve(__dirname, "tests/fixtures/error.twig"),
12
+ },
13
+ name: "vite-plugin-twig-drupal",
14
+ fileName: (_, entry) => `${entry}.js`,
15
+ },
16
+ },
17
+ plugins: [
18
+ twig({
19
+ namespaces: {
20
+ tests: join(__dirname, "/tests/fixtures"),
21
+ },
22
+ }),
23
+ ],
24
+ resolve: {
25
+ preserveSymlinks: true,
26
+ },
27
+ })