Skip to content

Commit 1ade945

Browse files
author
ZackHawkinsMC
committed
fix(engine_twig_php): Twig incremental rebuilds
Fixes issue where edits to twig files included in parent do not appear until the parent file is updated. Closes issue #1015
1 parent da4f187 commit 1ade945

1 file changed

Lines changed: 82 additions & 9 deletions

File tree

packages/engine-twig-php/lib/engine_twig_php.js

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ const engine_twig_php = {
2626
engineName: 'twig-php',
2727
engineFileExtension: '.twig',
2828
expandPartials: false,
29-
30-
// @todo Evaluate RegExs
31-
// findPartialsRE: /{%\s*(?:extends|include|embed)\s+('[^']+'|"[^"]+").*?%}/g,
32-
// findPartialKeyRE: /"((?:\\.|[^"\\])*)"/,
29+
findPartialsRE: /{%\s*(?:extends|include|embed)\s+('[^']+'|"[^"]+").*?(with|%}|\s*%})/g,
30+
findPartialKeyRE: /"((?:\\.|[^"\\])*)"|'((?:\\.|[^"\\])*)'/,
31+
namespaces: [],
3332

3433
/**
3534
* Accept a Pattern Lab config object from the core and put it in
@@ -47,6 +46,10 @@ const engine_twig_php = {
4746

4847
const { namespaces, alterTwigEnv, relativeFrom } = config.engines.twig;
4948

49+
// Preserve the namespaces from the config so we can use them later to
50+
// evaluate partials.
51+
this.namespaces = namespaces;
52+
5053
// Schema on config object being passed in:
5154
// https://github.com/basaltinc/twig-renderer/blob/master/config.schema.json
5255
twigRenderer = new TwigRenderer({
@@ -64,7 +67,6 @@ const engine_twig_php = {
6467
const patternPath = path.isAbsolute(pattern.relPath)
6568
? path.relative(patternLabConfig.paths.source.root, pattern.relPath)
6669
: pattern.relPath;
67-
// console.log(patternPath);
6870

6971
let details = '';
7072
if (patternLabConfig.logLevel === 'debug') {
@@ -118,8 +120,22 @@ const engine_twig_php = {
118120
// @todo Add all functions that get called even if disabled to ease implementing engine further
119121
// Currently all of them return `null` as I'm not totally sure there absence will be ok. Additionally, future improvements may be implemented in this functions.
120122

121-
findPartials(pattern) {
122-
return null;
123+
// Find and return any {% extends|include|embed 'template-name' %} within pattern.
124+
// The regex should match the following examples:
125+
// {%
126+
// include '@molecules/teaser-card/teaser-card.twig' with {
127+
// teaser_card: card
128+
// } only
129+
// %}
130+
// OR
131+
// {% include '@molecules/teaser-card/teaser-card.twig' %}
132+
// OR
133+
// {%
134+
// include '@molecules/teaser-card/teaser-card.twig'
135+
// %}
136+
findPartials: function(pattern) {
137+
const matches = pattern.template.match(this.findPartialsRE);
138+
return matches;
123139
},
124140

125141
findPartialsWithStyleModifiers(pattern) {
@@ -138,8 +154,65 @@ const engine_twig_php = {
138154
return null;
139155
},
140156

141-
findPartial(partialString) {
142-
return null;
157+
// Given a pattern, and a partial string, tease out the "pattern key" and
158+
// return it.
159+
findPartial: function(partialString) {
160+
try {
161+
let partial = partialString.match(this.findPartialKeyRE)[0];
162+
partial = partial.replace(/"/g, '');
163+
partial = partial.replace(/'/g, '');
164+
165+
// Check if namespaces is not empty.
166+
const selectedNamespace = this.namespaces.filter(namespace => {
167+
// Check to see if this partial contains within the namespace id.
168+
return partial.indexOf(`@${namespace.id}`) !== -1;
169+
});
170+
171+
let namespaceResolvedPartial = '';
172+
173+
if (selectedNamespace.length > 0) {
174+
// Loop through all namespaces and try to resolve the namespace to a file path.
175+
for (
176+
let index = 0;
177+
index < selectedNamespace[0].paths.length;
178+
index++
179+
) {
180+
const path = selectedNamespace[0].paths[index];
181+
// Replace the name space with the actual path.
182+
// i.e. @atoms -> source/_patterns/00-atoms
183+
const tempPartial = partial.replace(
184+
`@${selectedNamespace[0].id}`,
185+
path
186+
);
187+
188+
try {
189+
// Check to see if the file exists.
190+
if (fs.existsSync(tempPartial)) {
191+
// If it does, find the last directory in the namespace path.
192+
// i.e. source/_patterns/00-atoms -> 00-atoms.
193+
const lastDirectory = path.split('/').reverse()[0];
194+
// Replace the namespace in the path with the directory name.
195+
// i.e. @atoms/04-images/04-avatar.twig -> 00-atoms/04-images/04-avatar.twig
196+
namespaceResolvedPartial = partial.replace(
197+
`@${selectedNamespace[0].id}`,
198+
lastDirectory
199+
);
200+
// After it matches one time, set the resolved partial and exit the loop.
201+
break;
202+
}
203+
} catch (err) {
204+
console.error(err);
205+
}
206+
}
207+
}
208+
// Return the path with the namespace resolved OR the regex'd partial.
209+
return namespaceResolvedPartial || partial;
210+
} catch (err) {
211+
console.error(
212+
'Error occured when trying to find partial name in: ' + partialString
213+
);
214+
return null;
215+
}
143216
},
144217

145218
patternMatcher(pattern, regex) {

0 commit comments

Comments
 (0)