Skip to content

Commit

Permalink
fix(engine-twig): twig include function syntax not matched by findPar…
Browse files Browse the repository at this point in the history
…tials

Closes: pattern-lab#1471
  • Loading branch information
hadl committed Jan 15, 2023
1 parent cc1a2bd commit ea8eb70
Showing 1 changed file with 100 additions and 20 deletions.
120 changes: 100 additions & 20 deletions packages/engine-twig/lib/engine_twig.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class TwingLoaderPatternLab {
* @throws TwingErrorLoader When name is not found
*/
getSourceContext(name, from) {
var pattern = this.patterns.get(name);
const pattern = this.patterns.get(name);
return Promise.resolve(
new TwingSource(pattern.extendedTemplate, name, pattern.relPath)
);
Expand Down Expand Up @@ -116,23 +116,23 @@ const fileSystemLoader = new TwingLoaderFilesystem();
const patternLabLoader = new TwingLoaderPatternLab();
const chainLoader = new TwingLoaderChain([fileSystemLoader, patternLabLoader]);
const twing = new TwingEnvironment(chainLoader);
var metaPath;
let metaPath;
let patternLabConfig = {};

var engine_twig = {
const engine_twig = {
engine: twing,
engineName: 'twig',
engineFileExtension: '.twig',

// regexes, stored here so they're only compiled once
findPartialsRE:
/{%[-]?\s*(?:extends|include|embed|from|import|use)\s+('[^']+'|"[^"]+").*?%}/g,
findPartialKeyRE: /"((?:\\.|[^"\\])*)"/,
/{[%{]\s*.*?(?:extends|include|embed|from|import|use)\(?\s*['"](.+?)['"][\s\S]*?\)?\s*[%}]}/g,
findListItemsRE:
/({{#( )?)(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

// render it
renderPattern: function renderPattern(pattern, data, partials) {
var patternPath = pattern.basePattern
let patternPath = pattern.basePattern
? pattern.basePattern.relPath
: pattern.relPath;
if (patternPath.lastIndexOf(metaPath) === 0) {
Expand All @@ -150,8 +150,15 @@ var engine_twig = {

// find and return any {% include 'template-name' %} within pattern
findPartials: function findPartials(pattern) {
var matches = pattern.template.match(this.findPartialsRE);
return matches;
const matches = pattern.template.match(this.findPartialsRE);
const filteredMatches =
matches &&
matches.filter((match) => {
// Filter out programmatically created includes.
// i.e. {% include '@namespace/icons/assets/' ~ name ~ '.svg' %}
return match.indexOf('~') === -1;
});
return filteredMatches;
},

// returns any patterns that match {{> value(foo:"bar") }} or {{>
Expand All @@ -161,18 +168,90 @@ var engine_twig = {
// being implemented here.
return [];
},

findListItems: function (pattern) {
var matches = pattern.template.match(this.findListItemsRE);
const matches = pattern.template.match(this.findListItemsRE);
return matches;
},

// given a pattern, and a partial string, tease out the "pattern key" and
// return it.
findPartial: function (partialString) {
var partial = partialString.match(this.findPartialKeyRE)[0];
partial = partial.replace(/"/g, '');
try {
const partial = partialString.replace(this.findPartialsRE, '$1');

// Check if namespaces is not empty.
const [selectedNamespace] = fileSystemLoader
.getNamespaces()
.filter((namespace) => {
// Check to see if this partial contains within the namespace id.
return partial.indexOf(`@${namespace}`) !== -1;
});

let namespaceResolvedPartial = '';

if (selectedNamespace.length > 0) {
// Loop through all namespaces and try to resolve the namespace to a file path.
const namespacePaths = fileSystemLoader.getPaths(selectedNamespace);

for (let index = 0; index < namespacePaths.length; index++) {
const patternPath = path.isAbsolute(namespacePaths[index])
? path.relative(
patternLabConfig.paths.source.root,
namespacePaths[index]
)
: namespacePaths[index];

// Replace the name space with the actual path.
// i.e. @atoms -> source/_patterns/atoms
const tempPartial = path.join(
process.cwd(),
partial.replace(`@${selectedNamespace}`, patternPath)
);

return partial;
try {
// Check to see if the file actually exists.
if (fs.existsSync(tempPartial)) {
// get the path to the top-level folder of this pattern
// ex. /Users/bradfrost/sites/pattern-lab/packages/edition-twig/source/_patterns/atoms
const fullFolderPath = `${
tempPartial.split(namespacePaths[index])[0]
}${namespacePaths[index]}`;

// then tease out the folder name itself (including the # prefix)
// ex. atoms
const folderName = fullFolderPath.substring(
fullFolderPath.lastIndexOf('/') + 1,
fullFolderPath.length
);

// finally, return the Twig path we created from the full file path
// ex. atoms/buttons/button.twig
const fullIncludePath = tempPartial.replace(
tempPartial.split(
`${folderName}${tempPartial.split(folderName)[1]}`
)[0],
''
);

namespaceResolvedPartial = fullIncludePath;

// After it matches one time, set the resolved partial and exit the loop.
break;
}
} catch (err) {
console.error(err);
}
}
}
// Return the path with the namespace resolved OR the regex'd partial.
return namespaceResolvedPartial || partial;
} catch (err) {
console.error(
'Error occurred when trying to find partial name in: ' + partialString
);
return null;
}
},

spawnFile: function (config, fileName) {
Expand Down Expand Up @@ -209,31 +288,32 @@ var engine_twig = {
* @param {object} config - the global config object from core
*/
usePatternLabConfig: function (config) {
patternLabConfig = config;
metaPath = path.resolve(config.paths.source.meta);
// Global paths
fileSystemLoader.addPath(config.paths.source.meta);
fileSystemLoader.addPath(config.paths.source.patterns);
// Namespaced paths
if (
config['engines'] &&
config['engines']['twig'] &&
config['engines']['twig']['namespaces']
config.engines &&
config.engines.twig &&
config.engines.twig.namespaces
) {
var namespaces = config['engines']['twig']['namespaces'];
const namespaces = config.engines.twig.namespaces;
Object.keys(namespaces).forEach(function (key, index) {
fileSystemLoader.addPath(namespaces[key], key);
});
}

// add twing extensions
if (
config['engines'] &&
config['engines']['twig'] &&
config['engines']['twig']['loadExtensionsFile']
config.engines &&
config.engines.twig &&
config.engines.twig.loadExtensionsFile
) {
const extensionsFile = path.resolve(
'./',
config['engines']['twig']['loadExtensionsFile']
config.engines.twig.loadExtensionsFile
);
if (fs.pathExistsSync(extensionsFile)) {
try {
Expand Down

0 comments on commit ea8eb70

Please sign in to comment.