1
+ import SlotTemplateElseBlock from './SlotTemplateElseBlock' ;
2
+ import Component from '../Component' ;
3
+ import AbstractBlock from './shared/AbstractBlock' ;
4
+ import Expression from './shared/Expression' ;
5
+ import TemplateScope from './shared/TemplateScope' ;
6
+ import Node from './shared/Node' ;
7
+ import compiler_errors from '../compiler_errors' ;
8
+ import get_const_tags from './shared/get_const_tags' ;
9
+ import { TemplateNode } from '../../interfaces' ;
10
+ import ConstTag from './ConstTag' ;
11
+ import { regex_only_whitespaces } from '../../utils/patterns' ;
12
+ import SlotTemplate from './SlotTemplate' ;
13
+ import { INode } from './interfaces' ;
14
+
15
+
16
+ export default class SlotTemplateIfBlock extends AbstractBlock {
17
+ type : 'SlotTemplateIfBlock' ;
18
+ expression : Expression ;
19
+ else : SlotTemplateElseBlock ;
20
+ scope : TemplateScope ;
21
+ const_tags : ConstTag [ ] ;
22
+ slot_names = new Set < string > ( ) ;
23
+
24
+ constructor (
25
+ component : Component ,
26
+ parent : Node ,
27
+ scope : TemplateScope ,
28
+ info : TemplateNode
29
+ ) {
30
+ super ( component , parent , scope , info ) ;
31
+ this . scope = scope . child ( ) ;
32
+
33
+ const children = [ ] ;
34
+ for ( const child of info . children ) {
35
+ if ( child . type === 'SlotTemplate' || child . type === 'ConstTag' ) {
36
+ children . push ( child ) ;
37
+ } else if ( child . type === 'Comment' ) {
38
+ // ignore
39
+ } else if ( child . type === 'Text' && regex_only_whitespaces . test ( child . data ) ) {
40
+ // ignore
41
+ } else if ( child . type === 'IfBlock' ) {
42
+ children . push ( {
43
+ ...child ,
44
+ type : 'SlotTemplateIfBlock'
45
+ } ) ;
46
+ } else {
47
+ this . component . error ( child , compiler_errors . invalid_mix_element_and_conditional_slot ) ;
48
+ }
49
+ }
50
+
51
+ this . expression = new Expression ( component , this , this . scope , info . expression ) ;
52
+ ( [ this . const_tags , this . children ] = get_const_tags ( children , component , this , this ) ) ;
53
+
54
+ this . else = info . else
55
+ ? new SlotTemplateElseBlock ( component , this , scope , { ...info . else , type : 'SlotTemplateElseBlock' } )
56
+ : null ;
57
+ }
58
+
59
+ validate_duplicate_slot_name ( component_name : string ) : Map < string , SlotTemplate > {
60
+ const if_slot_names = validate_get_slot_names ( this . children , this . component , component_name ) ;
61
+ if ( ! this . else ) {
62
+ return if_slot_names ;
63
+ }
64
+
65
+ const else_slot_names = validate_get_slot_names ( this . else . children , this . component , component_name ) ;
66
+ return new Map ( [ ...if_slot_names , ...else_slot_names ] ) ;
67
+ }
68
+ }
69
+
70
+ export function validate_get_slot_names ( children : Array < INode > , component : Component , component_name : string ) {
71
+ const slot_names = new Map < string , SlotTemplate > ( ) ;
72
+ function add_slot_name ( slot_name : string , child : SlotTemplate ) {
73
+ if ( slot_names . has ( slot_name ) ) {
74
+ component . error ( child , compiler_errors . duplicate_slot_name_in_component ( slot_name , component_name ) ) ;
75
+ }
76
+ slot_names . set ( slot_name , child ) ;
77
+ }
78
+
79
+ for ( const child of children ) {
80
+ if ( child . type === 'SlotTemplateIfBlock' ) {
81
+ const child_slot_names = child . validate_duplicate_slot_name ( component_name ) ;
82
+ for ( const [ slot_name , child ] of child_slot_names ) {
83
+ add_slot_name ( slot_name , child ) ;
84
+ }
85
+ } else if ( child . type === 'SlotTemplate' ) {
86
+ add_slot_name ( child . slot_template_name , child ) ;
87
+ }
88
+ }
89
+ return slot_names ;
90
+ }
0 commit comments