Skip to content

Commit cfa792b

Browse files
hadlJosefBredereck
andauthored
fix(engine-twig): twig include function syntax not matched by findPartials (#1473)
Closes: #1471 Co-authored-by: Josef Bredreck <[email protected]>
1 parent 3677539 commit cfa792b

File tree

1 file changed

+100
-20
lines changed

1 file changed

+100
-20
lines changed

packages/engine-twig/lib/engine_twig.js

Lines changed: 100 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class TwingLoaderPatternLab {
5151
* @throws TwingErrorLoader When name is not found
5252
*/
5353
getSourceContext(name, from) {
54-
var pattern = this.patterns.get(name);
54+
const pattern = this.patterns.get(name);
5555
return Promise.resolve(
5656
new TwingSource(pattern.extendedTemplate, name, pattern.relPath)
5757
);
@@ -116,23 +116,23 @@ const fileSystemLoader = new TwingLoaderFilesystem();
116116
const patternLabLoader = new TwingLoaderPatternLab();
117117
const chainLoader = new TwingLoaderChain([fileSystemLoader, patternLabLoader]);
118118
const twing = new TwingEnvironment(chainLoader);
119-
var metaPath;
119+
let metaPath;
120+
let patternLabConfig = {};
120121

121-
var engine_twig = {
122+
const engine_twig = {
122123
engine: twing,
123124
engineName: 'twig',
124125
engineFileExtension: '.twig',
125126

126127
// regexes, stored here so they're only compiled once
127128
findPartialsRE:
128-
/{%[-]?\s*(?:extends|include|embed|from|import|use)\s+('[^']+'|"[^"]+").*?%}/g,
129-
findPartialKeyRE: /"((?:\\.|[^"\\])*)"/,
129+
/{[%{]\s*.*?(?:extends|include|embed|from|import|use)\(?\s*['"](.+?)['"][\s\S]*?\)?\s*[%}]}/g,
130130
findListItemsRE:
131131
/({{#( )?)(list(I|i)tems.)(one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty)( )?}}/g, // TODO
132132

133133
// render it
134134
renderPattern: function renderPattern(pattern, data, partials) {
135-
var patternPath = pattern.basePattern
135+
let patternPath = pattern.basePattern
136136
? pattern.basePattern.relPath
137137
: pattern.relPath;
138138
if (patternPath.lastIndexOf(metaPath) === 0) {
@@ -150,8 +150,15 @@ var engine_twig = {
150150

151151
// find and return any {% include 'template-name' %} within pattern
152152
findPartials: function findPartials(pattern) {
153-
var matches = pattern.template.match(this.findPartialsRE);
154-
return matches;
153+
const matches = pattern.template.match(this.findPartialsRE);
154+
const filteredMatches =
155+
matches &&
156+
matches.filter((match) => {
157+
// Filter out programmatically created includes.
158+
// i.e. {% include '@namespace/icons/assets/' ~ name ~ '.svg' %}
159+
return match.indexOf('~') === -1;
160+
});
161+
return filteredMatches;
155162
},
156163

157164
// returns any patterns that match {{> value(foo:"bar") }} or {{>
@@ -161,18 +168,90 @@ var engine_twig = {
161168
// being implemented here.
162169
return [];
163170
},
171+
164172
findListItems: function (pattern) {
165-
var matches = pattern.template.match(this.findListItemsRE);
173+
const matches = pattern.template.match(this.findListItemsRE);
166174
return matches;
167175
},
168176

169177
// given a pattern, and a partial string, tease out the "pattern key" and
170178
// return it.
171179
findPartial: function (partialString) {
172-
var partial = partialString.match(this.findPartialKeyRE)[0];
173-
partial = partial.replace(/"/g, '');
180+
try {
181+
const partial = partialString.replace(this.findPartialsRE, '$1');
182+
183+
// Check if namespaces is not empty.
184+
const [selectedNamespace] = fileSystemLoader
185+
.getNamespaces()
186+
.filter((namespace) => {
187+
// Check to see if this partial contains within the namespace id.
188+
return partial.indexOf(`@${namespace}`) !== -1;
189+
});
190+
191+
let namespaceResolvedPartial = '';
192+
193+
if (selectedNamespace.length > 0) {
194+
// Loop through all namespaces and try to resolve the namespace to a file path.
195+
const namespacePaths = fileSystemLoader.getPaths(selectedNamespace);
196+
197+
for (let index = 0; index < namespacePaths.length; index++) {
198+
const patternPath = path.isAbsolute(namespacePaths[index])
199+
? path.relative(
200+
patternLabConfig.paths.source.root,
201+
namespacePaths[index]
202+
)
203+
: namespacePaths[index];
204+
205+
// Replace the name space with the actual path.
206+
// i.e. @atoms -> source/_patterns/atoms
207+
const tempPartial = path.join(
208+
process.cwd(),
209+
partial.replace(`@${selectedNamespace}`, patternPath)
210+
);
174211

175-
return partial;
212+
try {
213+
// Check to see if the file actually exists.
214+
if (fs.existsSync(tempPartial)) {
215+
// get the path to the top-level folder of this pattern
216+
// ex. /Users/bradfrost/sites/pattern-lab/packages/edition-twig/source/_patterns/atoms
217+
const fullFolderPath = `${
218+
tempPartial.split(namespacePaths[index])[0]
219+
}${namespacePaths[index]}`;
220+
221+
// then tease out the folder name itself (including the # prefix)
222+
// ex. atoms
223+
const folderName = fullFolderPath.substring(
224+
fullFolderPath.lastIndexOf('/') + 1,
225+
fullFolderPath.length
226+
);
227+
228+
// finally, return the Twig path we created from the full file path
229+
// ex. atoms/buttons/button.twig
230+
const fullIncludePath = tempPartial.replace(
231+
tempPartial.split(
232+
`${folderName}${tempPartial.split(folderName)[1]}`
233+
)[0],
234+
''
235+
);
236+
237+
namespaceResolvedPartial = fullIncludePath;
238+
239+
// After it matches one time, set the resolved partial and exit the loop.
240+
break;
241+
}
242+
} catch (err) {
243+
console.error(err);
244+
}
245+
}
246+
}
247+
// Return the path with the namespace resolved OR the regex'd partial.
248+
return namespaceResolvedPartial || partial;
249+
} catch (err) {
250+
console.error(
251+
'Error occurred when trying to find partial name in: ' + partialString
252+
);
253+
return null;
254+
}
176255
},
177256

178257
spawnFile: function (config, fileName) {
@@ -209,31 +288,32 @@ var engine_twig = {
209288
* @param {object} config - the global config object from core
210289
*/
211290
usePatternLabConfig: function (config) {
291+
patternLabConfig = config;
212292
metaPath = path.resolve(config.paths.source.meta);
213293
// Global paths
214294
fileSystemLoader.addPath(config.paths.source.meta);
215295
fileSystemLoader.addPath(config.paths.source.patterns);
216296
// Namespaced paths
217297
if (
218-
config['engines'] &&
219-
config['engines']['twig'] &&
220-
config['engines']['twig']['namespaces']
298+
config.engines &&
299+
config.engines.twig &&
300+
config.engines.twig.namespaces
221301
) {
222-
var namespaces = config['engines']['twig']['namespaces'];
302+
const namespaces = config.engines.twig.namespaces;
223303
Object.keys(namespaces).forEach(function (key, index) {
224304
fileSystemLoader.addPath(namespaces[key], key);
225305
});
226306
}
227307

228308
// add twing extensions
229309
if (
230-
config['engines'] &&
231-
config['engines']['twig'] &&
232-
config['engines']['twig']['loadExtensionsFile']
310+
config.engines &&
311+
config.engines.twig &&
312+
config.engines.twig.loadExtensionsFile
233313
) {
234314
const extensionsFile = path.resolve(
235315
'./',
236-
config['engines']['twig']['loadExtensionsFile']
316+
config.engines.twig.loadExtensionsFile
237317
);
238318
if (fs.pathExistsSync(extensionsFile)) {
239319
try {

0 commit comments

Comments
 (0)