15
15
use Paneon \VueToTwig \Models \Property ;
16
16
use Paneon \VueToTwig \Models \Replacements ;
17
17
use Paneon \VueToTwig \Models \Slot ;
18
+ use Paneon \VueToTwig \Utils \NodeHelper ;
18
19
use Paneon \VueToTwig \Utils \TwigBuilder ;
19
20
use Psr \Log \LoggerInterface ;
20
21
use ReflectionException ;
@@ -52,6 +53,11 @@ class Compiler
52
53
*/
53
54
protected $ builder ;
54
55
56
+ /**
57
+ * @var NodeHelper
58
+ */
59
+ protected $ nodeHelper ;
60
+
55
61
/**
56
62
* @var Property[]
57
63
*/
@@ -88,6 +94,7 @@ class Compiler
88
94
public function __construct (DOMDocument $ document , LoggerInterface $ logger )
89
95
{
90
96
$ this ->builder = new TwigBuilder ();
97
+ $ this ->nodeHelper = new NodeHelper ();
91
98
$ this ->document = $ document ;
92
99
$ this ->logger = $ logger ;
93
100
$ this ->lastCloseIf = [];
@@ -183,14 +190,16 @@ public function convertNode(DOMNode $node, int $level = 0): DOMNode
183
190
} elseif ($ node instanceof DOMDocument) {
184
191
$ this ->logger ->warning ('Document node found. ' );
185
192
} elseif ($ node instanceof DOMElement) {
186
- $ this ->twigRemove ($ node );
193
+ if ($ this ->twigRemove ($ node )) {
194
+ return $ node ;
195
+ }
187
196
$ this ->replaceShowWithIf ($ node );
188
197
$ this ->handleIf ($ node , $ level );
189
198
$ this ->handleFor ($ node );
190
199
$ this ->handleHtml ($ node );
191
200
$ this ->handleText ($ node );
192
201
$ this ->stripEventHandlers ($ node );
193
- $ this ->handleDefaultSlot ($ node );
202
+ $ this ->handleSlots ($ node );
194
203
$ this ->cleanupAttributes ($ node );
195
204
}
196
205
@@ -223,21 +232,13 @@ public function convertNode(DOMNode $node, int $level = 0): DOMNode
223
232
$ this ->convertNode ($ childNode , $ level + 1 );
224
233
}
225
234
226
- // Slots (Default)
235
+ // Slots
227
236
if ($ node ->hasChildNodes ()) {
228
- $ innerHtml = $ this ->innerHtmlOfNode ($ node );
229
- $ innerHtml = $ this ->replacePlaceholders ($ innerHtml );
230
- $ this ->logger ->debug (
231
- 'Add default slot: ' ,
232
- [
233
- 'nodeValue ' => $ node ->nodeValue ,
234
- 'innerHtml ' => $ innerHtml ,
235
- ]
236
- );
237
-
238
- $ slot = $ usedComponent ->addDefaultSlot ($ innerHtml );
239
-
240
- $ this ->addReplaceVariable ($ slot ->getSlotContentVariableString (), $ slot ->getValue ());
237
+ $ this ->handleNamedSlotsInclude ($ node , $ usedComponent );
238
+ // Slots (Default)
239
+ if ($ node ->hasChildNodes () && !$ usedComponent ->hasSlot (Slot::SLOT_DEFAULT_NAME )) {
240
+ $ this ->addSlot (Slot::SLOT_DEFAULT_NAME , $ node , $ usedComponent );
241
+ }
241
242
}
242
243
243
244
// Include Partial
@@ -271,7 +272,7 @@ public function convertNode(DOMNode $node, int $level = 0): DOMNode
271
272
}
272
273
273
274
// Remove original node
274
- $ node -> parentNode -> removeChild ($ node );
275
+ $ this -> nodeHelper -> removeNode ($ node );
275
276
276
277
return $ node ;
277
278
}
@@ -479,7 +480,7 @@ public function handleBinding(string $value, string $name, ?DOMElement $node = n
479
480
480
481
foreach ($ items as $ item ) {
481
482
if (preg_match ($ regexObjectElements , $ item , $ matchElement )) {
482
- $ dynamicValues [] = $ this ->prepareBindingOutput (
483
+ $ dynamicValues [] = $ this ->builder -> prepareBindingOutput (
483
484
$ this ->builder ->refactorCondition ($ matchElement ['condition ' ]) . ' ? \'' . $ matchElement ['class ' ] . ' \'' ,
484
485
$ twigOutput
485
486
);
@@ -493,7 +494,7 @@ public function handleBinding(string $value, string $name, ?DOMElement $node = n
493
494
foreach ($ matches as $ match ) {
494
495
$ templateStringContent = str_replace (
495
496
$ match [0 ],
496
- $ this ->prepareBindingOutput ($ this ->builder ->refactorCondition ($ match [1 ]), $ twigOutput ),
497
+ $ this ->builder -> prepareBindingOutput ($ this ->builder ->refactorCondition ($ match [1 ]), $ twigOutput ),
497
498
$ templateStringContent
498
499
);
499
500
}
@@ -502,25 +503,12 @@ public function handleBinding(string $value, string $name, ?DOMElement $node = n
502
503
} else {
503
504
$ value = $ this ->builder ->refactorCondition ($ value );
504
505
$ this ->logger ->debug (sprintf ('- setAttribute "%s" with value "%s" ' , $ name , $ value ));
505
- $ dynamicValues [] = $ this ->prepareBindingOutput ($ value , $ twigOutput );
506
+ $ dynamicValues [] = $ this ->builder -> prepareBindingOutput ($ value , $ twigOutput );
506
507
}
507
508
508
509
return $ dynamicValues ;
509
510
}
510
511
511
- private function prepareBindingOutput (string $ value , bool $ twigOutput = true ): string
512
- {
513
- $ open = Replacements::getSanitizedConstant ('DOUBLE_CURLY_OPEN ' );
514
- $ close = Replacements::getSanitizedConstant ('DOUBLE_CURLY_CLOSE ' );
515
-
516
- if (!$ twigOutput ) {
517
- $ open = '( ' ;
518
- $ close = ') ' ;
519
- }
520
-
521
- return $ open . ' ' . $ value . ' ' . $ close ;
522
- }
523
-
524
512
/**
525
513
* @throws ReflectionException
526
514
*/
@@ -539,7 +527,7 @@ private function cleanupAttributes(DOMElement $node): void
539
527
/** @var DOMAttr $attribute */
540
528
foreach ($ node ->attributes as $ attribute ) {
541
529
if (
542
- (preg_match ('/^v-([a-z]*)/ ' , $ attribute ->name , $ matches ) === 1 && $ matches [1 ] !== 'bind ' )
530
+ (preg_match ('/^v-([a-z]*)/ ' , $ attribute ->name , $ matches ) === 1 && $ matches [1 ] !== 'bind ' && $ matches [ 1 ] !== ' slot ' )
543
531
|| preg_match ('/^[:]?ref$/ ' , $ attribute ->name ) === 1
544
532
) {
545
533
$ removeAttributes [] = $ attribute ->name ;
@@ -692,25 +680,6 @@ private function handleText(DOMElement $node): void
692
680
$ node ->appendChild (new DOMText ('{{ ' . $ text . '}} ' ));
693
681
}
694
682
695
- protected function addDefaultsToVariable (string $ varName , string $ string ): string
696
- {
697
- if (!in_array ($ varName , array_keys ($ this ->properties ))) {
698
- return $ string ;
699
- }
700
-
701
- $ prop = $ this ->properties [$ varName ];
702
-
703
- if ($ prop ->hasDefault ()) {
704
- $ string = preg_replace (
705
- '/\b( ' . $ varName . ')\b/ ' ,
706
- $ varName . '|default( ' . $ prop ->getDefault () . ') ' ,
707
- $ string
708
- );
709
- }
710
-
711
- return $ string ;
712
- }
713
-
714
683
/**
715
684
* @throws RuntimeException
716
685
*/
@@ -907,28 +876,68 @@ protected function addVariableBlocks(string $string): string
907
876
/**
908
877
* @throws Exception
909
878
*/
910
- protected function handleDefaultSlot (DOMElement $ node ): void
879
+ protected function handleSlots (DOMElement $ node ): void
911
880
{
912
881
if ($ node ->nodeName !== 'slot ' ) {
913
882
return ;
914
883
}
915
884
916
885
$ slotFallback = $ node ->hasChildNodes () ? $ this ->innerHtmlOfNode ($ node ) : null ;
917
886
887
+ $ slotName = Slot::SLOT_PREFIX ;
888
+ $ slotName .= $ node ->getAttribute ('name ' ) ? $ node ->getAttribute ('name ' ) : Slot::SLOT_DEFAULT_NAME ;
889
+
918
890
if ($ slotFallback ) {
919
- $ this ->addVariable ('slot_default_fallback ' , $ slotFallback );
920
- $ variable = $ this ->builder ->createVariableOutput (
921
- Slot::SLOT_PREFIX . Slot::SLOT_DEFAULT_NAME ,
922
- 'slot_default_fallback '
923
- );
891
+ $ this ->addVariable ($ slotName . '_fallback ' , $ slotFallback );
892
+ $ variable = $ this ->builder ->createVariableOutput ($ slotName , $ slotName . '_fallback ' );
924
893
} else {
925
- $ variable = $ this ->builder ->createVariableOutput (Slot:: SLOT_PREFIX . Slot:: SLOT_DEFAULT_NAME );
894
+ $ variable = $ this ->builder ->createVariableOutput ($ slotName );
926
895
}
927
896
928
897
$ variableNode = $ this ->document ->createTextNode ($ variable );
929
898
930
899
$ node ->parentNode ->insertBefore ($ variableNode , $ node );
931
- $ node ->parentNode ->removeChild ($ node );
900
+ $ this ->nodeHelper ->removeNode ($ node );
901
+ }
902
+
903
+ /**
904
+ * @throws Exception
905
+ * @throws ReflectionException
906
+ */
907
+ protected function handleNamedSlotsInclude (DOMNode $ node , Component $ usedComponent ): void
908
+ {
909
+ $ removeNodes = [];
910
+ foreach ($ node ->childNodes as $ childNode ) {
911
+ if ($ childNode instanceof DOMElement && $ childNode ->tagName === 'template ' ) {
912
+ foreach ($ childNode ->attributes as $ attribute ) {
913
+ if ($ attribute instanceof DOMAttr && preg_match ('/v-slot(?::([a-z]+)?)/i ' , $ attribute ->nodeName , $ matches )) {
914
+ $ slotName = $ matches [1 ] ?? Slot::SLOT_DEFAULT_NAME ;
915
+ $ this ->addSlot ($ slotName , $ childNode , $ usedComponent );
916
+ $ removeNodes [] = $ childNode ;
917
+ }
918
+ }
919
+ }
920
+ }
921
+ $ this ->nodeHelper ->removeNodes ($ removeNodes );
922
+ }
923
+
924
+ /**
925
+ * @throws Exception
926
+ * @throws ReflectionException
927
+ */
928
+ protected function addSlot (string $ slotName , DOMNode $ node , Component $ usedComponent ): void
929
+ {
930
+ $ innerHtml = $ this ->replacePlaceholders ($ this ->innerHtmlOfNode ($ node ));
931
+ $ this ->logger ->debug (
932
+ 'Add ' . $ slotName . ' slot: ' ,
933
+ [
934
+ 'nodeValue ' => $ node ->nodeValue ,
935
+ 'innerHtml ' => $ innerHtml ,
936
+ ]
937
+ );
938
+
939
+ $ slot = $ usedComponent ->addSlot ($ slotName , $ innerHtml );
940
+ $ this ->addReplaceVariable ($ slot ->getSlotContentVariableString (), $ slot ->getValue ());
932
941
}
933
942
934
943
protected function insertDefaultValues (): void
@@ -949,7 +958,7 @@ protected function handleRootNodeAttribute(DOMElement $node, ?string $name = nul
949
958
if (!$ name ) {
950
959
return $ node ;
951
960
}
952
- $ string = $ this ->prepareBindingOutput ($ name . '|default( \'\') ' );
961
+ $ string = $ this ->builder -> prepareBindingOutput ($ name . '|default( \'\') ' );
953
962
if ($ node ->hasAttribute ($ name )) {
954
963
$ attribute = $ node ->getAttributeNode ($ name );
955
964
$ attribute ->value .= ' ' . $ string ;
@@ -965,14 +974,18 @@ private function handleCommentNode(DOMComment $node): void
965
974
{
966
975
$ nodeValue = trim ($ node ->nodeValue );
967
976
if (preg_match ('/^(eslint-disable|@?todo)/i ' , $ nodeValue ) === 1 ) {
968
- $ node -> parentNode -> removeChild ($ node );
977
+ $ this -> nodeHelper -> removeNode ($ node );
969
978
}
970
979
}
971
980
972
- private function twigRemove (DOMElement $ node ): void
981
+ private function twigRemove (DOMElement $ node ): bool
973
982
{
974
983
if ($ node ->hasAttribute ('data-twig-remove ' )) {
975
984
$ node ->parentNode ->removeChild ($ node );
985
+
986
+ return true ;
976
987
}
988
+
989
+ return false ;
977
990
}
978
991
}
0 commit comments