vite-plugin-twig-drupal 1.2.1 → 1.4.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.
@@ -2,7 +2,7 @@ name: validate
2
2
  on:
3
3
  push:
4
4
  branches:
5
- - 'master'
5
+ - 'main'
6
6
  - 'beta'
7
7
  pull_request: {}
8
8
  jobs:
@@ -43,7 +43,7 @@ jobs:
43
43
  runs-on: ubuntu-latest
44
44
  if:
45
45
  ${{ github.repository == 'larowlan/vite-plugin-twig-drupal' &&
46
- contains('refs/heads/master',github.ref) && github.event_name == 'push' }}
46
+ contains('refs/heads/main',github.ref) && github.event_name == 'push' }}
47
47
  steps:
48
48
  - name: 🛑 Cancel Previous Runs
49
49
  uses: styfle/cancel-workflow-action@0.9.0
@@ -70,7 +70,7 @@ jobs:
70
70
  semantic_version: 22
71
71
  branches: |
72
72
  [
73
- 'master'
73
+ 'main'
74
74
  ]
75
75
  env:
76
76
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
package/README.md CHANGED
@@ -36,6 +36,7 @@
36
36
  - [This solution](#this-solution)
37
37
  - [Installation](#installation)
38
38
  - [Examples](#examples)
39
+ - [Usage with React](#usage-with-react)
39
40
  - [Issues](#issues)
40
41
  - [🐛 Bugs](#-bugs)
41
42
  - [💡 Feature Requests](#-feature-requests)
@@ -95,6 +96,8 @@ export default defineConfig({
95
96
  // You can add custom functions - each is a function that is passed the active Twig instance and should call
96
97
  // e.g. extendFunction to register a function
97
98
  reverse: (twigInstance) => twigInstance.extendFunction("reverse", () => (text) => text.split(' ').reverse().join(' ')),
99
+ // e.g. extendFilter to register a filter
100
+ clean_unique_id: (twigInstance) => twigInstance.extendFilter("clean_unique_id", () => (text) => text.split(' ').reverse().join(' ')),
98
101
  },
99
102
  globalContext: {
100
103
  // Global variables that should be present in all templates.
@@ -155,8 +158,35 @@ export const ButtonStrip = {
155
158
  ${Button({title: 'Button 2', modifier: 'secondary'})}
156
159
  `
157
160
  }
161
+ ```
162
+
163
+ ## Usage with React
164
+
165
+ When adding `framework: 'react'` to vite.config.js twig files will output React JSX functions
166
+ that can be used inside a React Storybook instance.
167
+
168
+ This way Twig components can be rendered alongside React components.
158
169
 
170
+ However, you will need to revert to a straight TwigJS function import so you can nest Twig components
171
+ inside other Twig components. In these instances append `?twig` to your component import. This will return a JavaScript function instead of a React component.
172
+ When nesting
173
+ Twig components inside React components this is not needed. Nesting React components inside Twig components
174
+ does not work currently.
175
+
176
+ ```javascript
177
+ import Button from './button.twig';
178
+ import OtherComponent from ../other-component.twig?twig
159
179
 
180
+ export default {
181
+ title: 'Components/Button',
182
+ tags: ['autodocs'],
183
+ args: {
184
+ // Render by calling the component as a function.
185
+ // You can pass any variables down as an object.
186
+ otherComponent: OtherComponent(),
187
+ },
188
+ component: Button,
189
+ };
160
190
 
161
191
  ```
162
192
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-twig-drupal",
3
- "version": "1.2.1",
3
+ "version": "1.4.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
@@ -25,8 +25,16 @@ const includeTokenTypes = [
25
25
  ]
26
26
 
27
27
  const resolveFile = (directory, file) => {
28
- if (existsSync(resolve(file))) {
29
- return resolve(file)
28
+ const filesToTry = [file, `${file}.twig`, `${file}.html.twig`]
29
+ for (const ix in filesToTry) {
30
+ const path = resolve(filesToTry[ix])
31
+ if (existsSync(path)) {
32
+ return path
33
+ }
34
+ const withDir = resolve(directory, filesToTry[ix])
35
+ if (existsSync(withDir)) {
36
+ return withDir
37
+ }
30
38
  }
31
39
  return resolve(directory, file)
32
40
  }
@@ -51,6 +59,16 @@ const pluckIncludes = (tokens) => {
51
59
  })
52
60
  }
53
61
 
62
+ const resolveNamespaceOrComponent = (namespaces, template) => {
63
+ let resolveTemplate = template
64
+ // Support for SDC.
65
+ if (template.includes(":")) {
66
+ const [namespace, component] = template.split(":")
67
+ resolveTemplate = `@${namespace}/${component}/${component}`
68
+ }
69
+ return Twig.path.expandNamespace(namespaces, resolveTemplate)
70
+ }
71
+
54
72
  const compileTemplate = (id, file, { namespaces }) => {
55
73
  return new Promise((resolve, reject) => {
56
74
  const options = { namespaces, rethrow: true, allowInlineIncludes: true }
@@ -108,10 +126,19 @@ const plugin = (options = {}) => {
108
126
  if (options.pattern.test(id)) {
109
127
  let frameworkInclude = ""
110
128
  let frameworkTransform = "const frameworkTransform = (html) => html;"
111
- if (options.framework === FRAMEWORK_REACT) {
129
+
130
+ let asTwigJs = id.match(/\?twig$/)
131
+
132
+ if (options.framework === FRAMEWORK_REACT && !asTwigJs) {
112
133
  frameworkInclude = `import React from 'react'`
113
134
  frameworkTransform = `const frameworkTransform = (html) => React.createElement('div', {dangerouslySetInnerHTML: {'__html': html}});;`
114
135
  }
136
+
137
+ if (asTwigJs) {
138
+ // Tidy up file path by remove ?twig
139
+ id = id.slice(0, -5)
140
+ }
141
+
115
142
  let embed,
116
143
  embeddedIncludes,
117
144
  functions,
@@ -133,7 +160,7 @@ const plugin = (options = {}) => {
133
160
  const processIncludes = (template) => {
134
161
  const file = resolveFile(
135
162
  dirname(id),
136
- Twig.path.expandNamespace(options.namespaces, template)
163
+ resolveNamespaceOrComponent(options.namespaces, template)
137
164
  )
138
165
  if (!seen.includes(template)) {
139
166
  includePromises.push(
@@ -159,7 +186,7 @@ const plugin = (options = {}) => {
159
186
  (template) =>
160
187
  `import '${resolveFile(
161
188
  dirname(id),
162
- Twig.path.expandNamespace(options.namespaces, template)
189
+ resolveNamespaceOrComponent(options.namespaces, template)
163
190
  )}';`
164
191
  )
165
192
  .join("\n")
@@ -32,6 +32,9 @@ exports[`Basic smoke test > Should support global context and functions 1`] = `
32
32
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
33
33
  </article>
34
34
  </section>
35
+ <h2>SDC</h2>
36
+ <p>Card</p>
37
+ <button>SDC</button>
35
38
  "
36
39
  `;
37
40
 
@@ -62,6 +65,9 @@ exports[`Basic smoke test > Should support includes 1`] = `
62
65
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
63
66
  </article>
64
67
  </section>
68
+ <h2>SDC</h2>
69
+ <p>Card</p>
70
+ <button>SDC</button>
65
71
  "
66
72
  `;
67
73
 
@@ -109,5 +115,8 @@ exports[`Basic smoke test > Should support variables 1`] = `
109
115
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. At dignissimos fugiat inventore laborum maiores molestiae neque quia quo unde veniam?
110
116
  </article>
111
117
  </section>
118
+ <h2>SDC</h2>
119
+ <p>Card</p>
120
+ <button>SDC</button>
112
121
  "
113
122
  `;
@@ -0,0 +1 @@
1
+ <button>{{title}}</button>
@@ -0,0 +1,2 @@
1
+ <h2>{{title}}</h2>
2
+ <p>{{teaser}}</p>
@@ -10,3 +10,12 @@
10
10
  {% endembed %}
11
11
  {% include "@tests/section.twig" %}
12
12
  {% include "../fixtures/section.twig" with {title: 'Relative include'} %}
13
+ {% embed 'jabba:card' with {
14
+ title: 'SDC',
15
+ teaser: 'Card',
16
+ } %}
17
+ {% endembed %}
18
+ {% embed 'jabba:button' with {
19
+ title: 'SDC',
20
+ } %}
21
+ {% endembed %}
package/vite.config.js CHANGED
@@ -31,6 +31,7 @@ export default defineConfig({
31
31
  },
32
32
  namespaces: {
33
33
  tests: join(__dirname, "/tests/fixtures"),
34
+ jabba: join(__dirname, "/tests/fixtures/jabba"),
34
35
  },
35
36
  }),
36
37
  ],