vite-plugin-twig-drupal 1.0.2 → 1.1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-twig-drupal",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Provides a ⚡️ Vite plugin to transform 🌱 Twig into HTML with a 💧 Drupal flavour",
5
5
  "keywords": [
6
6
  "Vite",
package/src/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import Twig from "twig"
2
+ import { resolve, dirname } from "node:path"
3
+ import { existsSync } from "node:fs"
4
+
2
5
  const { twig } = Twig
3
- import { resolve } from "node:path"
4
6
 
5
7
  const FRAMEWORK_REACT = "react"
6
8
  const FRAMEWORK_HTML = "html"
@@ -9,6 +11,7 @@ const defaultOptions = {
9
11
  namespaces: {},
10
12
  filters: {},
11
13
  functions: {},
14
+ globalContext: {},
12
15
  framework: FRAMEWORK_HTML,
13
16
  pattern: /\.(twig)(\?.*)?$/,
14
17
  }
@@ -21,6 +24,13 @@ const includeTokenTypes = [
21
24
  "Twig.logic.type.import",
22
25
  ]
23
26
 
27
+ const resolveFile = (directory, file) => {
28
+ if (existsSync(resolve(file))) {
29
+ return resolve(file)
30
+ }
31
+ return resolve(directory, file)
32
+ }
33
+
24
34
  const pluckIncludes = (tokens) => {
25
35
  return [
26
36
  ...tokens
@@ -70,7 +80,9 @@ const errorHandler =
70
80
  (e) => {
71
81
  if (isDefault) {
72
82
  return {
73
- code: `export default () => 'An error occurred whilst rendering ${id}: ${e.toString()}';`,
83
+ code: `export default () => 'An error occurred whilst rendering ${id}: ${e.toString()} ${
84
+ e.stack
85
+ }';`,
74
86
  map: null,
75
87
  }
76
88
  }
@@ -102,9 +114,11 @@ const plugin = (options = {}) => {
102
114
  }
103
115
  let embed,
104
116
  embeddedIncludes,
117
+ functions,
105
118
  code,
106
119
  includes,
107
120
  seen = []
121
+
108
122
  try {
109
123
  const result = await compileTemplate(id, id, options).catch(
110
124
  errorHandler(id)
@@ -117,8 +131,11 @@ const plugin = (options = {}) => {
117
131
  includes = result.includes
118
132
  const includePromises = []
119
133
  const processIncludes = (template) => {
120
- const file = Twig.path.expandNamespace(options.namespaces, template)
121
- if (!seen.includes(file)) {
134
+ const file = resolveFile(
135
+ dirname(id),
136
+ Twig.path.expandNamespace(options.namespaces, template)
137
+ )
138
+ if (!seen.includes(template)) {
122
139
  includePromises.push(
123
140
  new Promise(async (resolve, reject) => {
124
141
  const { includes, code } = await compileTemplate(
@@ -132,7 +149,7 @@ const plugin = (options = {}) => {
132
149
  resolve(code)
133
150
  })
134
151
  )
135
- seen.push(file)
152
+ seen.push(template)
136
153
  }
137
154
  }
138
155
  includes.forEach(processIncludes)
@@ -140,11 +157,22 @@ const plugin = (options = {}) => {
140
157
  .filter((template) => template !== "_self")
141
158
  .map(
142
159
  (template) =>
143
- `import '${resolve(
160
+ `import '${resolveFile(
161
+ dirname(id),
144
162
  Twig.path.expandNamespace(options.namespaces, template)
145
163
  )}';`
146
164
  )
147
165
  .join("\n")
166
+
167
+ functions = Object.entries(options.functions)
168
+ .map(([name, value]) => {
169
+ return `
170
+ const ${name} = ${value};
171
+ ${name}(Twig);
172
+ `
173
+ })
174
+ .join("\n")
175
+
148
176
  const includeResult = await Promise.all(includePromises).catch(
149
177
  errorHandler(id)
150
178
  )
@@ -161,10 +189,11 @@ const plugin = (options = {}) => {
161
189
  import DrupalAttribute from 'drupal-attribute';
162
190
  import { addDrupalExtensions } from 'drupal-twig-extensions/twig';
163
191
  ${frameworkInclude}
164
-
192
+
165
193
  ${embed}
166
194
 
167
- addDrupalExtensions(Twig);
195
+ ${functions}
196
+
168
197
  // Disable caching.
169
198
  Twig.cache(false);
170
199
 
@@ -176,7 +205,8 @@ const plugin = (options = {}) => {
176
205
  ${includes ? `component.options.allowInlineIncludes = true;` : ""}
177
206
  try {
178
207
  return frameworkTransform(component.render({
179
- attributes: new DrupalAttribute(),
208
+ attributes: new DrupalAttribute(),
209
+ ...${JSON.stringify(options.globalContext)},
180
210
  ...context
181
211
  }));
182
212
  }
@@ -1,5 +1,35 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
+ exports[`Basic smoke test > Should support global context and functions 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
+ IT WORKS!
16
+ </article>
17
+ </section>
18
+ <section>
19
+ <h1></h1>
20
+ <article>
21
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
22
+ </article>
23
+ </section>
24
+ <section>
25
+ <h1>Relative include</h1>
26
+ <article>
27
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
28
+ </article>
29
+ </section>
30
+ "
31
+ `;
32
+
3
33
  exports[`Basic smoke test > Should support includes 1`] = `
4
34
  "<section>
5
35
  <h1>Include</h1>
@@ -12,7 +42,8 @@ exports[`Basic smoke test > Should support includes 1`] = `
12
42
  <article>
13
43
  Lorem ipsum dolor sit amet.
14
44
  <button class=\\"button--primary\\">Nested include</button>
15
- </article>
45
+ IT WORKS!
46
+ </article>
16
47
  </section>
17
48
  <section>
18
49
  <h1></h1>
@@ -20,6 +51,12 @@ exports[`Basic smoke test > Should support includes 1`] = `
20
51
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
21
52
  </article>
22
53
  </section>
54
+ <section>
55
+ <h1>Relative include</h1>
56
+ <article>
57
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
58
+ </article>
59
+ </section>
23
60
  "
24
61
  `;
25
62
 
@@ -52,7 +89,8 @@ exports[`Basic smoke test > Should support variables 1`] = `
52
89
  <article>
53
90
  Lorem ipsum dolor sit amet.
54
91
  <button class=\\"button--primary\\">Nested include</button>
55
- </article>
92
+ IT WORKS!
93
+ </article>
56
94
  </section>
57
95
  <section>
58
96
  <h1>Pickle Fixie</h1>
@@ -60,5 +98,11 @@ exports[`Basic smoke test > Should support variables 1`] = `
60
98
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
61
99
  </article>
62
100
  </section>
101
+ <section>
102
+ <h1>Relative include</h1>
103
+ <article>
104
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
105
+ </article>
106
+ </section>
63
107
  "
64
108
  `;
@@ -3,6 +3,10 @@
3
3
  {% block content %}
4
4
  Lorem ipsum dolor sit amet.
5
5
  {% include "@tests/button.twig" with {text: 'Nested include'} %}
6
+ {% if active_theme == 'poodles' %}
7
+ {{ testFunction() }}
8
+ {% endif %}
6
9
  {% endblock %}
7
10
  {% endembed %}
8
11
  {% include "@tests/section.twig" %}
12
+ {% include "../fixtures/section.twig" with {title: 'Relative include'} %}
@@ -9,6 +9,7 @@ describe("Basic smoke test", () => {
9
9
  const markup = Markup()
10
10
  expect(markup).toMatchSnapshot()
11
11
  expect(markup).toContain("Nested include")
12
+ expect(markup).toContain("Relative include")
12
13
  })
13
14
  it("Should support variables", () => {
14
15
  const markup = Markup({ title: "Pickle Fixie" })
@@ -28,4 +29,10 @@ describe("Basic smoke test", () => {
28
29
  expect(markup).toContain("Contact")
29
30
  expect(markup).toMatchSnapshot()
30
31
  })
32
+ it("Should support global context and functions", () => {
33
+ const markup = Markup()
34
+ expect(markup).toMatchSnapshot()
35
+ expect(markup).toContain("Nested include")
36
+ expect(markup).toContain("IT WORKS!")
37
+ })
31
38
  })
package/vite.config.js CHANGED
@@ -18,6 +18,13 @@ export default defineConfig({
18
18
  },
19
19
  plugins: [
20
20
  twig({
21
+ globalContext: {
22
+ active_theme: "poodles",
23
+ },
24
+ functions: {
25
+ testFunction: (instance) =>
26
+ instance.extendFunction("testFunction", () => "IT WORKS!"),
27
+ },
21
28
  namespaces: {
22
29
  tests: join(__dirname, "/tests/fixtures"),
23
30
  },