@@ -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 * (?: e x t e n d s | i n c l u d e | e m b e d ) \s + ( ' [ ^ ' ] + ' | " [ ^ " ] + " ) .* ?( w i t h | % } | \s * % } ) / g,
30+ findPartialKeyRE : / " ( (?: \\ .| [ ^ " \\ ] ) * ) " | ' ( (?: \\ .| [ ^ " \\ ] ) * ) ' / ,
31+ namespaces : [ ] ,
3332
3433 /**
3534 * Accept a Pattern Lab config object from the core and put it in
@@ -57,6 +56,9 @@ const engine_twig_php = {
5756 relativeFrom,
5857 alterTwigEnv,
5958 } ) ;
59+
60+ // Preserve the namespaces (after recursively adding nested folders) from the config so we can use them later to evaluate partials.
61+ this . namespaces = twigRenderer . config . src . namespaces ;
6062 } ,
6163
6264 renderPattern ( pattern , data ) {
@@ -72,8 +74,6 @@ const engine_twig_php = {
7274 const patternPath = path . isAbsolute ( relPath )
7375 ? path . relative ( patternLabConfig . paths . source . root , relPath )
7476 : relPath ;
75- // console.log(patternPath);
76-
7777 let details = '' ;
7878 if ( patternLabConfig . logLevel === 'debug' ) {
7979 details = `<details><pre><code>${ JSON . stringify (
@@ -126,8 +126,29 @@ const engine_twig_php = {
126126 // @todo Add all functions that get called even if disabled to ease implementing engine further
127127 // 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.
128128
129- findPartials ( pattern ) {
130- return null ;
129+ // Find and return any {% extends|include|embed 'template-name' %} within pattern.
130+ // The regex should match the following examples:
131+ // {%
132+ // include '@molecules/teaser-card/teaser-card.twig' with {
133+ // teaser_card: card
134+ // } only
135+ // %}
136+ // OR
137+ // {% include '@molecules/teaser-card/teaser-card.twig' % }
138+ // OR
139+ // {%
140+ // include '@molecules/teaser-card/teaser-card.twig'
141+ // %}
142+ findPartials : function ( pattern ) {
143+ const matches = pattern . template . match ( this . findPartialsRE ) ;
144+ const filteredMatches =
145+ matches &&
146+ matches . filter ( match => {
147+ // Filter out programmatically created includes.
148+ // i.e. {% include '@namespace/icons/assets/' ~ name ~ '.svg' % }
149+ return match . indexOf ( '~' ) === - 1 ;
150+ } ) ;
151+ return filteredMatches ;
131152 } ,
132153
133154 findPartialsWithStyleModifiers ( pattern ) {
@@ -146,8 +167,86 @@ const engine_twig_php = {
146167 return null ;
147168 } ,
148169
149- findPartial ( partialString ) {
150- return null ;
170+ // Given a pattern, and a partial string, tease out the "pattern key" and
171+ // return it.
172+ findPartial : function ( partialString ) {
173+ try {
174+ let partial = partialString . match ( this . findPartialKeyRE ) [ 0 ] ;
175+ partial = partial . replace ( / " / g, '' ) ;
176+ partial = partial . replace ( / ' / g, '' ) ;
177+
178+ // Check if namespaces is not empty.
179+ const selectedNamespace = this . namespaces . filter ( namespace => {
180+ // Check to see if this partial contains within the namespace id.
181+ return partial . indexOf ( `@${ namespace . id } ` ) !== - 1 ;
182+ } ) ;
183+
184+ let namespaceResolvedPartial = '' ;
185+
186+ if ( selectedNamespace . length > 0 ) {
187+ // Loop through all namespaces and try to resolve the namespace to a file path.
188+ for (
189+ let index = 0 ;
190+ index < selectedNamespace [ 0 ] . paths . length ;
191+ index ++
192+ ) {
193+ const patternPath = path . isAbsolute ( selectedNamespace [ 0 ] . paths [ index ] )
194+ ? path . relative (
195+ patternLabConfig . paths . source . root ,
196+ selectedNamespace [ 0 ] . paths [ index ]
197+ )
198+ : selectedNamespace [ 0 ] . paths [ index ] ;
199+
200+ // Replace the name space with the actual path.
201+ // i.e. @atoms -> source/_patterns/00-atoms
202+ const tempPartial = path . join (
203+ process . cwd ( ) ,
204+ partial . replace ( `@${ selectedNamespace [ 0 ] . id } ` , patternPath )
205+ ) ;
206+
207+ try {
208+ // Check to see if the file actually exists.
209+ if ( fs . existsSync ( tempPartial ) ) {
210+ // get the path to the top-level folder of this pattern
211+ // ex. /Users/bradfrost/sites/pattern-lab/packages/edition-twig/source/_patterns/00-atoms
212+ const fullFolderPath = `${
213+ tempPartial . split ( selectedNamespace [ 0 ] . id ) [ 0 ]
214+ } ${ selectedNamespace [ 0 ] . id } `;
215+
216+ // then tease out the folder name itself (including the # prefix)
217+ // ex. 00-atoms
218+ const folderName = fullFolderPath . substring (
219+ fullFolderPath . lastIndexOf ( '/' ) + 1 ,
220+ fullFolderPath . length
221+ ) ;
222+
223+ // finally, return the Twig path we created from the full file path
224+ // ex. 00-atoms/05-buttons/button.twig
225+ const fullIncludePath = tempPartial . replace (
226+ tempPartial . split (
227+ `${ folderName } ${ tempPartial . split ( folderName ) [ 1 ] } `
228+ ) [ 0 ] ,
229+ ''
230+ ) ;
231+
232+ namespaceResolvedPartial = fullIncludePath ;
233+
234+ // After it matches one time, set the resolved partial and exit the loop.
235+ break ;
236+ }
237+ } catch ( err ) {
238+ console . error ( err ) ;
239+ }
240+ }
241+ }
242+ // Return the path with the namespace resolved OR the regex'd partial.
243+ return namespaceResolvedPartial || partial ;
244+ } catch ( err ) {
245+ console . error (
246+ 'Error occured when trying to find partial name in: ' + partialString
247+ ) ;
248+ return null ;
249+ }
151250 } ,
152251
153252 patternMatcher ( pattern , regex ) {
0 commit comments