@markuplint/pug-parser 3.6.1 → 3.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1752 @@
1
+ const { pugParse } = require('../../lib/pug-parser');
2
+
3
+ describe('parser', () => {
4
+ it('basic code', () => {
5
+ const ast = pugParse(`html(lang=en)
6
+ head
7
+ title Title
8
+ body
9
+ // HTML comment
10
+ //- Pug comment
11
+ <!-- HTML raw comment -->
12
+ h1 Title
13
+ p= variable
14
+ p#the-id.the-class1.the-class2
15
+ | lorem
16
+ img(
17
+ src="path/to"
18
+ alt="image"
19
+ )
20
+ img#the-id2(
21
+ src="path/to"
22
+ alt="image"
23
+ ).the-class3
24
+ <div>
25
+ <span>Raw HTML</span>
26
+ </div>
27
+ ul
28
+ each article in articles
29
+ li: a(href=article.href)= article.title
30
+ if bool
31
+ div True
32
+ else if bool2
33
+ div Any
34
+ else
35
+ div False
36
+ case variable
37
+ when "cond"
38
+ - break
39
+ when "cond2"
40
+ p Condition 2
41
+ when "cond3"
42
+ p Condition 3
43
+ default
44
+ p Default
45
+ script.
46
+ console.log(123);
47
+ .
48
+ <script>alert(123)</script>
49
+ :any-filter(arg1 arg2 arg3=123)
50
+ filter contents
51
+ `);
52
+ // console.log(JSON.stringify(ast));
53
+ expect(ast).toStrictEqual({
54
+ type: 'Block',
55
+ nodes: [
56
+ {
57
+ type: 'Tag',
58
+ name: 'html',
59
+ raw: 'html(lang=en)',
60
+ offset: 0,
61
+ endOffset: 13,
62
+ line: 1,
63
+ endLine: 1,
64
+ column: 1,
65
+ endColumn: 14,
66
+ block: {
67
+ type: 'Block',
68
+ nodes: [
69
+ {
70
+ type: 'Tag',
71
+ name: 'head',
72
+ raw: 'head',
73
+ offset: 15,
74
+ endOffset: 19,
75
+ line: 2,
76
+ endLine: 2,
77
+ column: 2,
78
+ endColumn: 6,
79
+ block: {
80
+ type: 'Block',
81
+ nodes: [
82
+ {
83
+ type: 'Tag',
84
+ name: 'title',
85
+ raw: 'title',
86
+ offset: 22,
87
+ endOffset: 27,
88
+ line: 3,
89
+ endLine: 3,
90
+ column: 3,
91
+ endColumn: 8,
92
+ block: {
93
+ type: 'Block',
94
+ nodes: [
95
+ {
96
+ type: 'Text',
97
+ raw: 'Title\n\t',
98
+ offset: 28,
99
+ endOffset: 35,
100
+ line: 3,
101
+ endLine: 4,
102
+ column: 9,
103
+ endColumn: 2,
104
+ },
105
+ ],
106
+ line: 3,
107
+ },
108
+ attrs: [],
109
+ },
110
+ ],
111
+ line: 2,
112
+ },
113
+ attrs: [],
114
+ },
115
+ {
116
+ type: 'Tag',
117
+ name: 'body',
118
+ raw: 'body',
119
+ offset: 35,
120
+ endOffset: 39,
121
+ line: 4,
122
+ endLine: 4,
123
+ column: 2,
124
+ endColumn: 6,
125
+ block: {
126
+ type: 'Block',
127
+ nodes: [
128
+ {
129
+ type: 'Comment',
130
+ val: ' HTML comment',
131
+ buffer: true,
132
+ raw: '// HTML comment',
133
+ offset: 42,
134
+ endOffset: 57,
135
+ line: 5,
136
+ endLine: 5,
137
+ column: 3,
138
+ endColumn: 18,
139
+ },
140
+ {
141
+ type: 'Comment',
142
+ val: ' Pug comment',
143
+ buffer: false,
144
+ raw: '//- Pug comment',
145
+ offset: 60,
146
+ endOffset: 75,
147
+ line: 6,
148
+ endLine: 6,
149
+ column: 3,
150
+ endColumn: 18,
151
+ },
152
+ {
153
+ type: 'Text',
154
+ raw: '<!-- HTML raw comment -->',
155
+ offset: 78,
156
+ endOffset: 103,
157
+ line: 7,
158
+ endLine: 7,
159
+ column: 3,
160
+ endColumn: 28,
161
+ },
162
+ {
163
+ type: 'Tag',
164
+ name: 'h1',
165
+ raw: 'h1',
166
+ offset: 106,
167
+ endOffset: 108,
168
+ line: 8,
169
+ endLine: 8,
170
+ column: 3,
171
+ endColumn: 5,
172
+ block: {
173
+ type: 'Block',
174
+ nodes: [
175
+ {
176
+ type: 'Text',
177
+ raw: 'Title',
178
+ offset: 109,
179
+ endOffset: 114,
180
+ line: 8,
181
+ endLine: 8,
182
+ column: 6,
183
+ endColumn: 11,
184
+ },
185
+ ],
186
+ line: 8,
187
+ },
188
+ attrs: [],
189
+ },
190
+ {
191
+ type: 'Tag',
192
+ name: 'p',
193
+ raw: 'p',
194
+ offset: 117,
195
+ endOffset: 118,
196
+ line: 9,
197
+ endLine: 9,
198
+ column: 3,
199
+ endColumn: 4,
200
+ block: {
201
+ type: 'Block',
202
+ nodes: [
203
+ {
204
+ type: 'Code',
205
+ raw: '= variable',
206
+ val: 'variable',
207
+ buffer: true,
208
+ mustEscape: true,
209
+ isInline: true,
210
+ offset: 118,
211
+ endOffset: 128,
212
+ line: 9,
213
+ endLine: 9,
214
+ column: 4,
215
+ endColumn: 14,
216
+ },
217
+ ],
218
+ line: 9,
219
+ },
220
+ attrs: [],
221
+ },
222
+ {
223
+ type: 'Tag',
224
+ name: 'p',
225
+ raw: 'p#the-id.the-class1.the-class2',
226
+ offset: 131,
227
+ endOffset: 161,
228
+ line: 10,
229
+ endLine: 10,
230
+ column: 3,
231
+ endColumn: 33,
232
+ block: {
233
+ type: 'Block',
234
+ nodes: [
235
+ {
236
+ type: 'Text',
237
+ raw: 'lorem\n\t\t',
238
+ offset: 167,
239
+ endOffset: 175,
240
+ line: 11,
241
+ endLine: 12,
242
+ column: 6,
243
+ endColumn: 3,
244
+ },
245
+ ],
246
+ line: 10,
247
+ },
248
+ attrs: [
249
+ {
250
+ name: 'id',
251
+ val: "'the-id'",
252
+ mustEscape: false,
253
+ offset: 132,
254
+ endOffset: 139,
255
+ line: 10,
256
+ endLine: 10,
257
+ column: 4,
258
+ endColumn: 11,
259
+ raw: '#the-id',
260
+ },
261
+ {
262
+ name: 'class',
263
+ val: "'the-class1'",
264
+ mustEscape: false,
265
+ offset: 139,
266
+ endOffset: 150,
267
+ line: 10,
268
+ endLine: 10,
269
+ column: 11,
270
+ endColumn: 22,
271
+ raw: '.the-class1',
272
+ },
273
+ {
274
+ name: 'class',
275
+ val: "'the-class2'",
276
+ mustEscape: false,
277
+ offset: 150,
278
+ endOffset: 161,
279
+ line: 10,
280
+ endLine: 10,
281
+ column: 22,
282
+ endColumn: 33,
283
+ raw: '.the-class2',
284
+ },
285
+ ],
286
+ },
287
+ {
288
+ type: 'Tag',
289
+ name: 'img',
290
+ raw: 'img(\n\t\t\tsrc="path/to"\n\t\t\talt="image"\n\t\t)',
291
+ offset: 175,
292
+ endOffset: 215,
293
+ line: 12,
294
+ endLine: 15,
295
+ column: 3,
296
+ endColumn: 4,
297
+ block: { type: 'Block', nodes: [], line: 12 },
298
+ attrs: [
299
+ {
300
+ name: 'src',
301
+ val: '"path/to"',
302
+ mustEscape: true,
303
+ offset: 183,
304
+ endOffset: 196,
305
+ line: 13,
306
+ endLine: 13,
307
+ column: 4,
308
+ endColumn: 17,
309
+ raw: 'src="path/to"',
310
+ },
311
+ {
312
+ name: 'alt',
313
+ val: '"image"',
314
+ mustEscape: true,
315
+ offset: 200,
316
+ endOffset: 211,
317
+ line: 14,
318
+ endLine: 14,
319
+ column: 4,
320
+ endColumn: 15,
321
+ raw: 'alt="image"',
322
+ },
323
+ ],
324
+ },
325
+ {
326
+ type: 'Tag',
327
+ name: 'img',
328
+ raw: 'img#the-id2(\n\t\t\tsrc="path/to"\n\t\t\talt="image"\n\t\t).the-class3',
329
+ offset: 218,
330
+ endOffset: 277,
331
+ line: 16,
332
+ endLine: 19,
333
+ column: 3,
334
+ endColumn: 15,
335
+ block: { type: 'Block', nodes: [], line: 16 },
336
+ attrs: [
337
+ {
338
+ name: 'id',
339
+ val: "'the-id2'",
340
+ mustEscape: false,
341
+ offset: 221,
342
+ endOffset: 229,
343
+ line: 16,
344
+ endLine: 16,
345
+ column: 6,
346
+ endColumn: 14,
347
+ raw: '#the-id2',
348
+ },
349
+ {
350
+ name: 'src',
351
+ val: '"path/to"',
352
+ mustEscape: true,
353
+ offset: 234,
354
+ endOffset: 247,
355
+ line: 17,
356
+ endLine: 17,
357
+ column: 4,
358
+ endColumn: 17,
359
+ raw: 'src="path/to"',
360
+ },
361
+ {
362
+ name: 'alt',
363
+ val: '"image"',
364
+ mustEscape: true,
365
+ offset: 251,
366
+ endOffset: 262,
367
+ line: 18,
368
+ endLine: 18,
369
+ column: 4,
370
+ endColumn: 15,
371
+ raw: 'alt="image"',
372
+ },
373
+ {
374
+ name: 'class',
375
+ val: "'the-class3'",
376
+ mustEscape: false,
377
+ offset: 266,
378
+ endOffset: 277,
379
+ line: 19,
380
+ endLine: 19,
381
+ column: 4,
382
+ endColumn: 15,
383
+ raw: '.the-class3',
384
+ },
385
+ ],
386
+ },
387
+ {
388
+ type: 'Text',
389
+ raw: '<div>\n\t\t\t<span>Raw HTML</span>\n\t\t</div>',
390
+ offset: 280,
391
+ endOffset: 319,
392
+ line: 20,
393
+ endLine: 22,
394
+ column: 3,
395
+ endColumn: 9,
396
+ },
397
+ {
398
+ type: 'Tag',
399
+ name: 'ul',
400
+ raw: 'ul',
401
+ offset: 322,
402
+ endOffset: 324,
403
+ line: 23,
404
+ endLine: 23,
405
+ column: 3,
406
+ endColumn: 5,
407
+ block: {
408
+ type: 'Block',
409
+ nodes: [
410
+ {
411
+ type: 'Each',
412
+ val: 'article',
413
+ obj: 'articles',
414
+ key: null,
415
+ raw: 'each article in articles',
416
+ offset: 328,
417
+ endOffset: 352,
418
+ line: 24,
419
+ endLine: 24,
420
+ column: 4,
421
+ endColumn: 28,
422
+ block: {
423
+ type: 'Block',
424
+ nodes: [
425
+ {
426
+ type: 'Tag',
427
+ name: 'li',
428
+ raw: 'li',
429
+ offset: 357,
430
+ endOffset: 359,
431
+ line: 25,
432
+ endLine: 25,
433
+ column: 5,
434
+ endColumn: 7,
435
+ block: {
436
+ type: 'Block',
437
+ nodes: [
438
+ {
439
+ type: 'Tag',
440
+ name: 'a',
441
+ raw: 'a(href=article.href)',
442
+ offset: 361,
443
+ endOffset: 381,
444
+ line: 25,
445
+ endLine: 25,
446
+ column: 9,
447
+ endColumn: 29,
448
+ block: {
449
+ type: 'Block',
450
+ nodes: [
451
+ {
452
+ type: 'Code',
453
+ raw: '= article.title',
454
+ val: 'article.title',
455
+ buffer: true,
456
+ mustEscape: true,
457
+ isInline: true,
458
+ offset: 381,
459
+ endOffset: 396,
460
+ line: 25,
461
+ endLine: 25,
462
+ column: 29,
463
+ endColumn: 44,
464
+ },
465
+ ],
466
+ line: 25,
467
+ },
468
+ attrs: [
469
+ {
470
+ name: 'href',
471
+ val: 'article.href',
472
+ mustEscape: true,
473
+ offset: 363,
474
+ endOffset: 380,
475
+ line: 25,
476
+ endLine: 25,
477
+ column: 11,
478
+ endColumn: 28,
479
+ raw: 'href=article.href',
480
+ },
481
+ ],
482
+ },
483
+ ],
484
+ line: 25,
485
+ },
486
+ attrs: [],
487
+ },
488
+ ],
489
+ line: 25,
490
+ },
491
+ },
492
+ ],
493
+ line: 23,
494
+ },
495
+ attrs: [],
496
+ },
497
+ {
498
+ type: 'Conditional',
499
+ raw: 'if bool',
500
+ test: 'bool',
501
+ offset: 399,
502
+ endOffset: 406,
503
+ line: 26,
504
+ endLine: 26,
505
+ column: 3,
506
+ endColumn: 10,
507
+ block: {
508
+ type: 'Block',
509
+ nodes: [
510
+ {
511
+ type: 'Tag',
512
+ name: 'div',
513
+ raw: 'div',
514
+ offset: 410,
515
+ endOffset: 413,
516
+ line: 27,
517
+ endLine: 27,
518
+ column: 4,
519
+ endColumn: 7,
520
+ block: {
521
+ type: 'Block',
522
+ nodes: [
523
+ {
524
+ type: 'Text',
525
+ raw: 'True\n\t\t',
526
+ offset: 414,
527
+ endOffset: 421,
528
+ line: 27,
529
+ endLine: 28,
530
+ column: 8,
531
+ endColumn: 3,
532
+ },
533
+ ],
534
+ line: 27,
535
+ },
536
+ attrs: [],
537
+ },
538
+ ],
539
+ line: 27,
540
+ },
541
+ },
542
+ {
543
+ type: 'Conditional',
544
+ raw: 'else if bool2',
545
+ test: 'bool2',
546
+ offset: 421,
547
+ endOffset: 434,
548
+ line: 28,
549
+ endLine: 28,
550
+ column: 3,
551
+ endColumn: 16,
552
+ block: {
553
+ type: 'Block',
554
+ nodes: [
555
+ {
556
+ type: 'Tag',
557
+ name: 'div',
558
+ raw: 'div',
559
+ offset: 438,
560
+ endOffset: 441,
561
+ line: 29,
562
+ endLine: 29,
563
+ column: 4,
564
+ endColumn: 7,
565
+ block: {
566
+ type: 'Block',
567
+ nodes: [
568
+ {
569
+ type: 'Text',
570
+ raw: 'Any\n\t\t',
571
+ offset: 442,
572
+ endOffset: 448,
573
+ line: 29,
574
+ endLine: 30,
575
+ column: 8,
576
+ endColumn: 3,
577
+ },
578
+ ],
579
+ line: 29,
580
+ },
581
+ attrs: [],
582
+ },
583
+ ],
584
+ line: 29,
585
+ },
586
+ },
587
+ {
588
+ type: 'Conditional',
589
+ raw: 'else',
590
+ test: 'bool2',
591
+ offset: 448,
592
+ endOffset: 452,
593
+ line: 30,
594
+ endLine: 30,
595
+ column: 3,
596
+ endColumn: 7,
597
+ block: {
598
+ type: 'Block',
599
+ nodes: [
600
+ {
601
+ type: 'Tag',
602
+ name: 'div',
603
+ raw: 'div',
604
+ offset: 456,
605
+ endOffset: 459,
606
+ line: 31,
607
+ endLine: 31,
608
+ column: 4,
609
+ endColumn: 7,
610
+ block: {
611
+ type: 'Block',
612
+ nodes: [
613
+ {
614
+ type: 'Text',
615
+ raw: 'False\n\t\t',
616
+ offset: 460,
617
+ endOffset: 468,
618
+ line: 31,
619
+ endLine: 32,
620
+ column: 8,
621
+ endColumn: 3,
622
+ },
623
+ ],
624
+ line: 31,
625
+ },
626
+ attrs: [],
627
+ },
628
+ ],
629
+ line: 31,
630
+ },
631
+ },
632
+ {
633
+ type: 'Case',
634
+ expr: 'variable',
635
+ raw: 'case variable',
636
+ offset: 468,
637
+ endOffset: 481,
638
+ line: 32,
639
+ endLine: 32,
640
+ column: 3,
641
+ endColumn: 16,
642
+ block: {
643
+ type: 'Block',
644
+ nodes: [
645
+ {
646
+ type: 'When',
647
+ expr: '"cond"',
648
+ raw: 'when "cond"',
649
+ offset: 485,
650
+ endOffset: 496,
651
+ line: 33,
652
+ endLine: 33,
653
+ column: 4,
654
+ endColumn: 15,
655
+ block: {
656
+ type: 'Block',
657
+ nodes: [
658
+ {
659
+ type: 'Code',
660
+ raw: '- break',
661
+ val: 'break',
662
+ buffer: false,
663
+ mustEscape: false,
664
+ isInline: false,
665
+ offset: 501,
666
+ endOffset: 508,
667
+ line: 34,
668
+ endLine: 34,
669
+ column: 5,
670
+ endColumn: 12,
671
+ },
672
+ ],
673
+ line: 34,
674
+ },
675
+ },
676
+ {
677
+ type: 'When',
678
+ expr: '"cond2"',
679
+ raw: 'when "cond2"',
680
+ offset: 512,
681
+ endOffset: 524,
682
+ line: 35,
683
+ endLine: 35,
684
+ column: 4,
685
+ endColumn: 16,
686
+ block: {
687
+ type: 'Block',
688
+ nodes: [
689
+ {
690
+ type: 'Tag',
691
+ name: 'p',
692
+ raw: 'p',
693
+ offset: 529,
694
+ endOffset: 530,
695
+ line: 36,
696
+ endLine: 36,
697
+ column: 5,
698
+ endColumn: 6,
699
+ block: {
700
+ type: 'Block',
701
+ nodes: [
702
+ {
703
+ type: 'Text',
704
+ raw: 'Condition 2\n\t\t\t',
705
+ offset: 531,
706
+ endOffset: 546,
707
+ line: 36,
708
+ endLine: 37,
709
+ column: 7,
710
+ endColumn: 4,
711
+ },
712
+ ],
713
+ line: 36,
714
+ },
715
+ attrs: [],
716
+ },
717
+ ],
718
+ line: 36,
719
+ },
720
+ },
721
+ {
722
+ type: 'When',
723
+ expr: '"cond3"',
724
+ raw: 'when "cond3"',
725
+ offset: 546,
726
+ endOffset: 558,
727
+ line: 37,
728
+ endLine: 37,
729
+ column: 4,
730
+ endColumn: 16,
731
+ block: {
732
+ type: 'Block',
733
+ nodes: [
734
+ {
735
+ type: 'Tag',
736
+ name: 'p',
737
+ raw: 'p',
738
+ offset: 563,
739
+ endOffset: 564,
740
+ line: 38,
741
+ endLine: 38,
742
+ column: 5,
743
+ endColumn: 6,
744
+ block: {
745
+ type: 'Block',
746
+ nodes: [
747
+ {
748
+ type: 'Text',
749
+ raw: 'Condition 3\n\t\t\t',
750
+ offset: 565,
751
+ endOffset: 580,
752
+ line: 38,
753
+ endLine: 39,
754
+ column: 7,
755
+ endColumn: 4,
756
+ },
757
+ ],
758
+ line: 38,
759
+ },
760
+ attrs: [],
761
+ },
762
+ ],
763
+ line: 38,
764
+ },
765
+ },
766
+ {
767
+ type: 'When',
768
+ expr: 'default',
769
+ raw: 'default',
770
+ offset: 580,
771
+ endOffset: 587,
772
+ line: 39,
773
+ endLine: 39,
774
+ column: 4,
775
+ endColumn: 11,
776
+ block: {
777
+ type: 'Block',
778
+ nodes: [
779
+ {
780
+ type: 'Tag',
781
+ name: 'p',
782
+ raw: 'p',
783
+ offset: 592,
784
+ endOffset: 593,
785
+ line: 40,
786
+ endLine: 40,
787
+ column: 5,
788
+ endColumn: 6,
789
+ block: {
790
+ type: 'Block',
791
+ nodes: [
792
+ {
793
+ type: 'Text',
794
+ raw: 'Default\n\t\t',
795
+ offset: 594,
796
+ endOffset: 604,
797
+ line: 40,
798
+ endLine: 41,
799
+ column: 7,
800
+ endColumn: 3,
801
+ },
802
+ ],
803
+ line: 40,
804
+ },
805
+ attrs: [],
806
+ },
807
+ ],
808
+ line: 40,
809
+ },
810
+ },
811
+ ],
812
+ line: 33,
813
+ },
814
+ },
815
+ {
816
+ type: 'Tag',
817
+ name: 'script',
818
+ raw: 'script',
819
+ offset: 604,
820
+ endOffset: 610,
821
+ line: 41,
822
+ endLine: 41,
823
+ column: 3,
824
+ endColumn: 9,
825
+ block: {
826
+ type: 'Block',
827
+ nodes: [
828
+ {
829
+ type: 'Text',
830
+ raw: 'console.log(123);',
831
+ offset: 615,
832
+ endOffset: 632,
833
+ line: 42,
834
+ endLine: 42,
835
+ column: 4,
836
+ endColumn: 21,
837
+ },
838
+ ],
839
+ line: 41,
840
+ },
841
+ attrs: [],
842
+ },
843
+ {
844
+ type: 'Text',
845
+ raw: '<script>alert(123)</script>',
846
+ offset: 640,
847
+ endOffset: 667,
848
+ line: 44,
849
+ endLine: 44,
850
+ column: 4,
851
+ endColumn: 31,
852
+ },
853
+ {
854
+ type: 'Filter',
855
+ name: 'any-filter',
856
+ raw: ':any-filter(arg1 arg2 arg3=123)',
857
+ offset: 670,
858
+ endOffset: 701,
859
+ line: 45,
860
+ endLine: 45,
861
+ column: 3,
862
+ endColumn: 34,
863
+ block: {
864
+ type: 'Block',
865
+ nodes: [
866
+ {
867
+ type: 'Text',
868
+ raw: 'filter contents',
869
+ offset: 705,
870
+ endOffset: 720,
871
+ line: 46,
872
+ endLine: 46,
873
+ column: 4,
874
+ endColumn: 19,
875
+ },
876
+ ],
877
+ line: 45,
878
+ },
879
+ attrs: [
880
+ {
881
+ name: 'arg1',
882
+ val: true,
883
+ mustEscape: true,
884
+ offset: 682,
885
+ endOffset: 686,
886
+ line: 45,
887
+ endLine: 45,
888
+ column: 15,
889
+ endColumn: 19,
890
+ raw: 'arg1',
891
+ },
892
+ {
893
+ name: 'arg2',
894
+ val: true,
895
+ mustEscape: true,
896
+ offset: 687,
897
+ endOffset: 691,
898
+ line: 45,
899
+ endLine: 45,
900
+ column: 20,
901
+ endColumn: 24,
902
+ raw: 'arg2',
903
+ },
904
+ {
905
+ name: 'arg3',
906
+ val: '123',
907
+ mustEscape: true,
908
+ offset: 692,
909
+ endOffset: 700,
910
+ line: 45,
911
+ endLine: 45,
912
+ column: 25,
913
+ endColumn: 33,
914
+ raw: 'arg3=123',
915
+ },
916
+ ],
917
+ },
918
+ ],
919
+ line: 4,
920
+ },
921
+ attrs: [],
922
+ },
923
+ ],
924
+ line: 1,
925
+ },
926
+ attrs: [
927
+ {
928
+ name: 'lang',
929
+ val: 'en',
930
+ mustEscape: true,
931
+ offset: 5,
932
+ endOffset: 12,
933
+ line: 1,
934
+ endLine: 1,
935
+ column: 6,
936
+ endColumn: 13,
937
+ raw: 'lang=en',
938
+ },
939
+ ],
940
+ },
941
+ ],
942
+ line: 0,
943
+ });
944
+ });
945
+
946
+ /**
947
+ * @see https://pugjs.org/language/mixins.html
948
+ */
949
+ it('use mixin', () => {
950
+ const ast = pugParse(`//- Declaration
951
+ mixin list
952
+ ul
953
+ li foo
954
+ li bar
955
+ li baz
956
+ //- Use
957
+ +list
958
+ +list
959
+
960
+ mixin article(title)
961
+ .article
962
+ .article-wrapper
963
+ h1= title
964
+ if block
965
+ block
966
+ else
967
+ p No content provided
968
+
969
+ +article('Hello world')
970
+
971
+ +article('Hello world')
972
+ p This is my
973
+ p Amazing article
974
+
975
+ mixin link(href, name)
976
+ //- attributes == {class: "btn"}
977
+ a(class!=attributes.class href=href)= name
978
+
979
+ +link('/foo', 'foo')(class="btn")
980
+ `);
981
+ // console.log(JSON.stringify(ast));
982
+ expect(ast).toStrictEqual({
983
+ type: 'Block',
984
+ nodes: [
985
+ {
986
+ type: 'Comment',
987
+ val: ' Declaration',
988
+ buffer: false,
989
+ raw: '//- Declaration',
990
+ offset: 0,
991
+ endOffset: 15,
992
+ line: 1,
993
+ endLine: 1,
994
+ column: 1,
995
+ endColumn: 16,
996
+ },
997
+ {
998
+ type: 'Mixin',
999
+ name: 'list',
1000
+ args: null,
1001
+ call: false,
1002
+ raw: 'mixin list',
1003
+ offset: 16,
1004
+ endOffset: 26,
1005
+ line: 2,
1006
+ endLine: 2,
1007
+ column: 1,
1008
+ endColumn: 11,
1009
+ block: {
1010
+ type: 'Block',
1011
+ nodes: [
1012
+ {
1013
+ type: 'Tag',
1014
+ name: 'ul',
1015
+ raw: 'ul',
1016
+ offset: 28,
1017
+ endOffset: 30,
1018
+ line: 3,
1019
+ endLine: 3,
1020
+ column: 2,
1021
+ endColumn: 4,
1022
+ block: {
1023
+ type: 'Block',
1024
+ nodes: [
1025
+ {
1026
+ type: 'Tag',
1027
+ name: 'li',
1028
+ raw: 'li',
1029
+ offset: 33,
1030
+ endOffset: 35,
1031
+ line: 4,
1032
+ endLine: 4,
1033
+ column: 3,
1034
+ endColumn: 5,
1035
+ block: {
1036
+ type: 'Block',
1037
+ nodes: [
1038
+ {
1039
+ type: 'Text',
1040
+ raw: 'foo',
1041
+ offset: 36,
1042
+ endOffset: 39,
1043
+ line: 4,
1044
+ endLine: 4,
1045
+ column: 6,
1046
+ endColumn: 9,
1047
+ },
1048
+ ],
1049
+ line: 4,
1050
+ },
1051
+ attrs: [],
1052
+ },
1053
+ {
1054
+ type: 'Tag',
1055
+ name: 'li',
1056
+ raw: 'li',
1057
+ offset: 42,
1058
+ endOffset: 44,
1059
+ line: 5,
1060
+ endLine: 5,
1061
+ column: 3,
1062
+ endColumn: 5,
1063
+ block: {
1064
+ type: 'Block',
1065
+ nodes: [
1066
+ {
1067
+ type: 'Text',
1068
+ raw: 'bar',
1069
+ offset: 45,
1070
+ endOffset: 48,
1071
+ line: 5,
1072
+ endLine: 5,
1073
+ column: 6,
1074
+ endColumn: 9,
1075
+ },
1076
+ ],
1077
+ line: 5,
1078
+ },
1079
+ attrs: [],
1080
+ },
1081
+ {
1082
+ type: 'Tag',
1083
+ name: 'li',
1084
+ raw: 'li',
1085
+ offset: 51,
1086
+ endOffset: 53,
1087
+ line: 6,
1088
+ endLine: 6,
1089
+ column: 3,
1090
+ endColumn: 5,
1091
+ block: {
1092
+ type: 'Block',
1093
+ nodes: [
1094
+ {
1095
+ type: 'Text',
1096
+ raw: 'baz\n',
1097
+ offset: 54,
1098
+ endOffset: 58,
1099
+ line: 6,
1100
+ endLine: 7,
1101
+ column: 6,
1102
+ endColumn: 1,
1103
+ },
1104
+ ],
1105
+ line: 6,
1106
+ },
1107
+ attrs: [],
1108
+ },
1109
+ ],
1110
+ line: 3,
1111
+ },
1112
+ attrs: [],
1113
+ },
1114
+ ],
1115
+ line: 3,
1116
+ },
1117
+ attrs: [],
1118
+ },
1119
+ {
1120
+ type: 'Comment',
1121
+ val: ' Use',
1122
+ buffer: false,
1123
+ raw: '',
1124
+ offset: 58,
1125
+ endOffset: 58,
1126
+ line: 7,
1127
+ endLine: 7,
1128
+ column: 1,
1129
+ endColumn: 1,
1130
+ },
1131
+ {
1132
+ type: 'Mixin',
1133
+ name: 'list',
1134
+ args: null,
1135
+ call: true,
1136
+ raw: '+list',
1137
+ offset: 66,
1138
+ endOffset: 71,
1139
+ line: 8,
1140
+ endLine: 8,
1141
+ column: 1,
1142
+ endColumn: 6,
1143
+ block: null,
1144
+ attrs: [],
1145
+ },
1146
+ {
1147
+ type: 'Mixin',
1148
+ name: 'list',
1149
+ args: null,
1150
+ call: true,
1151
+ raw: '+list',
1152
+ offset: 72,
1153
+ endOffset: 77,
1154
+ line: 9,
1155
+ endLine: 9,
1156
+ column: 1,
1157
+ endColumn: 6,
1158
+ block: null,
1159
+ attrs: [],
1160
+ },
1161
+ {
1162
+ type: 'Mixin',
1163
+ name: 'article',
1164
+ args: 'title',
1165
+ call: false,
1166
+ raw: 'mixin article(title)',
1167
+ offset: 79,
1168
+ endOffset: 99,
1169
+ line: 11,
1170
+ endLine: 11,
1171
+ column: 1,
1172
+ endColumn: 21,
1173
+ block: {
1174
+ type: 'Block',
1175
+ nodes: [
1176
+ {
1177
+ type: 'Tag',
1178
+ name: 'div',
1179
+ raw: '.article',
1180
+ offset: 101,
1181
+ endOffset: 109,
1182
+ line: 12,
1183
+ endLine: 12,
1184
+ column: 2,
1185
+ endColumn: 10,
1186
+ block: {
1187
+ type: 'Block',
1188
+ nodes: [
1189
+ {
1190
+ type: 'Tag',
1191
+ name: 'div',
1192
+ raw: '.article-wrapper',
1193
+ offset: 112,
1194
+ endOffset: 128,
1195
+ line: 13,
1196
+ endLine: 13,
1197
+ column: 3,
1198
+ endColumn: 19,
1199
+ block: {
1200
+ type: 'Block',
1201
+ nodes: [
1202
+ {
1203
+ type: 'Tag',
1204
+ name: 'h1',
1205
+ raw: 'h1',
1206
+ offset: 132,
1207
+ endOffset: 134,
1208
+ line: 14,
1209
+ endLine: 14,
1210
+ column: 4,
1211
+ endColumn: 6,
1212
+ block: {
1213
+ type: 'Block',
1214
+ nodes: [
1215
+ {
1216
+ type: 'Code',
1217
+ raw: '= title',
1218
+ val: 'title',
1219
+ buffer: true,
1220
+ mustEscape: true,
1221
+ isInline: true,
1222
+ offset: 134,
1223
+ endOffset: 141,
1224
+ line: 14,
1225
+ endLine: 14,
1226
+ column: 6,
1227
+ endColumn: 13,
1228
+ },
1229
+ ],
1230
+ line: 14,
1231
+ },
1232
+ attrs: [],
1233
+ },
1234
+ {
1235
+ type: 'Conditional',
1236
+ raw: 'if block',
1237
+ test: 'block',
1238
+ offset: 145,
1239
+ endOffset: 153,
1240
+ line: 15,
1241
+ endLine: 15,
1242
+ column: 4,
1243
+ endColumn: 12,
1244
+ block: {
1245
+ type: 'Block',
1246
+ nodes: [
1247
+ {
1248
+ type: 'MixinBlock',
1249
+ raw: 'block',
1250
+ offset: 158,
1251
+ endOffset: 163,
1252
+ line: 16,
1253
+ endLine: 16,
1254
+ column: 5,
1255
+ endColumn: 10,
1256
+ },
1257
+ ],
1258
+ line: 16,
1259
+ },
1260
+ },
1261
+ {
1262
+ type: 'Conditional',
1263
+ raw: 'else',
1264
+ test: 'block',
1265
+ offset: 167,
1266
+ endOffset: 171,
1267
+ line: 17,
1268
+ endLine: 17,
1269
+ column: 4,
1270
+ endColumn: 8,
1271
+ block: {
1272
+ type: 'Block',
1273
+ nodes: [
1274
+ {
1275
+ type: 'Tag',
1276
+ name: 'p',
1277
+ raw: 'p',
1278
+ offset: 176,
1279
+ endOffset: 177,
1280
+ line: 18,
1281
+ endLine: 18,
1282
+ column: 5,
1283
+ endColumn: 6,
1284
+ block: {
1285
+ type: 'Block',
1286
+ nodes: [
1287
+ {
1288
+ type: 'Text',
1289
+ raw: 'No content provided\n\n',
1290
+ offset: 178,
1291
+ endOffset: 199,
1292
+ line: 18,
1293
+ endLine: 20,
1294
+ column: 7,
1295
+ endColumn: 1,
1296
+ },
1297
+ ],
1298
+ line: 18,
1299
+ },
1300
+ attrs: [],
1301
+ },
1302
+ ],
1303
+ line: 18,
1304
+ },
1305
+ },
1306
+ ],
1307
+ line: 13,
1308
+ },
1309
+ attrs: [
1310
+ {
1311
+ name: 'class',
1312
+ val: "'article-wrapper'",
1313
+ mustEscape: false,
1314
+ offset: 112,
1315
+ endOffset: 128,
1316
+ line: 13,
1317
+ endLine: 13,
1318
+ column: 3,
1319
+ endColumn: 19,
1320
+ raw: '.article-wrapper',
1321
+ },
1322
+ ],
1323
+ },
1324
+ ],
1325
+ line: 12,
1326
+ },
1327
+ attrs: [
1328
+ {
1329
+ name: 'class',
1330
+ val: "'article'",
1331
+ mustEscape: false,
1332
+ offset: 101,
1333
+ endOffset: 109,
1334
+ line: 12,
1335
+ endLine: 12,
1336
+ column: 2,
1337
+ endColumn: 10,
1338
+ raw: '.article',
1339
+ },
1340
+ ],
1341
+ },
1342
+ ],
1343
+ line: 12,
1344
+ },
1345
+ attrs: [],
1346
+ },
1347
+ {
1348
+ type: 'Mixin',
1349
+ name: 'article',
1350
+ args: "'Hello world'",
1351
+ call: true,
1352
+ raw: "+article('Hello world')",
1353
+ offset: 199,
1354
+ endOffset: 222,
1355
+ line: 20,
1356
+ endLine: 20,
1357
+ column: 1,
1358
+ endColumn: 24,
1359
+ block: null,
1360
+ attrs: [],
1361
+ },
1362
+ {
1363
+ type: 'Mixin',
1364
+ name: 'article',
1365
+ args: "'Hello world'",
1366
+ call: true,
1367
+ raw: "+article('Hello world')",
1368
+ offset: 224,
1369
+ endOffset: 247,
1370
+ line: 22,
1371
+ endLine: 22,
1372
+ column: 1,
1373
+ endColumn: 24,
1374
+ block: {
1375
+ type: 'Block',
1376
+ nodes: [
1377
+ {
1378
+ type: 'Tag',
1379
+ name: 'p',
1380
+ raw: 'p',
1381
+ offset: 249,
1382
+ endOffset: 250,
1383
+ line: 23,
1384
+ endLine: 23,
1385
+ column: 2,
1386
+ endColumn: 3,
1387
+ block: {
1388
+ type: 'Block',
1389
+ nodes: [
1390
+ {
1391
+ type: 'Text',
1392
+ raw: 'This is my',
1393
+ offset: 251,
1394
+ endOffset: 261,
1395
+ line: 23,
1396
+ endLine: 23,
1397
+ column: 4,
1398
+ endColumn: 14,
1399
+ },
1400
+ ],
1401
+ line: 23,
1402
+ },
1403
+ attrs: [],
1404
+ },
1405
+ {
1406
+ type: 'Tag',
1407
+ name: 'p',
1408
+ raw: 'p',
1409
+ offset: 263,
1410
+ endOffset: 264,
1411
+ line: 24,
1412
+ endLine: 24,
1413
+ column: 2,
1414
+ endColumn: 3,
1415
+ block: {
1416
+ type: 'Block',
1417
+ nodes: [
1418
+ {
1419
+ type: 'Text',
1420
+ raw: 'Amazing article\n\n',
1421
+ offset: 265,
1422
+ endOffset: 282,
1423
+ line: 24,
1424
+ endLine: 26,
1425
+ column: 4,
1426
+ endColumn: 1,
1427
+ },
1428
+ ],
1429
+ line: 24,
1430
+ },
1431
+ attrs: [],
1432
+ },
1433
+ ],
1434
+ line: 22,
1435
+ },
1436
+ attrs: [],
1437
+ },
1438
+ {
1439
+ type: 'Mixin',
1440
+ name: 'link',
1441
+ args: 'href, name',
1442
+ call: false,
1443
+ raw: 'mixin link(href, name)',
1444
+ offset: 282,
1445
+ endOffset: 304,
1446
+ line: 26,
1447
+ endLine: 26,
1448
+ column: 1,
1449
+ endColumn: 23,
1450
+ block: {
1451
+ type: 'Block',
1452
+ nodes: [
1453
+ {
1454
+ type: 'Comment',
1455
+ val: ' attributes == {class: "btn"}',
1456
+ buffer: false,
1457
+ raw: '//- attributes == {class: "btn"}',
1458
+ offset: 306,
1459
+ endOffset: 338,
1460
+ line: 27,
1461
+ endLine: 27,
1462
+ column: 2,
1463
+ endColumn: 34,
1464
+ },
1465
+ {
1466
+ type: 'Tag',
1467
+ name: 'a',
1468
+ raw: 'a(class!=attributes.class href=href)',
1469
+ offset: 340,
1470
+ endOffset: 376,
1471
+ line: 28,
1472
+ endLine: 28,
1473
+ column: 2,
1474
+ endColumn: 38,
1475
+ block: {
1476
+ type: 'Block',
1477
+ nodes: [
1478
+ {
1479
+ type: 'Code',
1480
+ raw: '= name',
1481
+ val: 'name',
1482
+ buffer: true,
1483
+ mustEscape: true,
1484
+ isInline: true,
1485
+ offset: 376,
1486
+ endOffset: 382,
1487
+ line: 28,
1488
+ endLine: 28,
1489
+ column: 38,
1490
+ endColumn: 44,
1491
+ },
1492
+ ],
1493
+ line: 28,
1494
+ },
1495
+ attrs: [
1496
+ {
1497
+ name: 'class',
1498
+ val: 'attributes.class',
1499
+ mustEscape: false,
1500
+ offset: 342,
1501
+ endOffset: 365,
1502
+ line: 28,
1503
+ endLine: 28,
1504
+ column: 4,
1505
+ endColumn: 27,
1506
+ raw: 'class!=attributes.class',
1507
+ },
1508
+ {
1509
+ name: 'href',
1510
+ val: 'href',
1511
+ mustEscape: true,
1512
+ offset: 366,
1513
+ endOffset: 375,
1514
+ line: 28,
1515
+ endLine: 28,
1516
+ column: 28,
1517
+ endColumn: 37,
1518
+ raw: 'href=href',
1519
+ },
1520
+ ],
1521
+ },
1522
+ ],
1523
+ line: 27,
1524
+ },
1525
+ attrs: [],
1526
+ },
1527
+ {
1528
+ type: 'Mixin',
1529
+ name: 'link',
1530
+ args: "'/foo', 'foo'",
1531
+ call: true,
1532
+ raw: "+link('/foo', 'foo')",
1533
+ offset: 384,
1534
+ endOffset: 404,
1535
+ line: 30,
1536
+ endLine: 30,
1537
+ column: 1,
1538
+ endColumn: 21,
1539
+ block: null,
1540
+ attrs: [],
1541
+ },
1542
+ ],
1543
+ line: 0,
1544
+ });
1545
+ });
1546
+
1547
+ it('use mixin', () => {
1548
+ const ast = pugParse(`div
1549
+ <span>
1550
+ <img src="path/to">
1551
+ </span>
1552
+ `);
1553
+ // console.log(JSON.stringify(ast));
1554
+ expect(ast).toStrictEqual({
1555
+ type: 'Block',
1556
+ nodes: [
1557
+ {
1558
+ type: 'Tag',
1559
+ name: 'div',
1560
+ raw: 'div',
1561
+ offset: 0,
1562
+ endOffset: 3,
1563
+ line: 1,
1564
+ endLine: 1,
1565
+ column: 1,
1566
+ endColumn: 4,
1567
+ block: {
1568
+ type: 'Block',
1569
+ nodes: [
1570
+ {
1571
+ type: 'Text',
1572
+ raw: '<span>\n\t\t<img src="path/to">\n\t</span>\n',
1573
+ offset: 5,
1574
+ endOffset: 43,
1575
+ line: 2,
1576
+ endLine: 5,
1577
+ column: 2,
1578
+ endColumn: 1,
1579
+ },
1580
+ ],
1581
+ line: 1,
1582
+ },
1583
+ attrs: [],
1584
+ },
1585
+ ],
1586
+ line: 0,
1587
+ });
1588
+ });
1589
+
1590
+ it('tag interpolation (Issue #58)', () => {
1591
+ const ast = pugParse(`p
1592
+ | lorem #[span ipsum]`);
1593
+ expect(ast).toStrictEqual({
1594
+ type: 'Block',
1595
+ nodes: [
1596
+ {
1597
+ type: 'Tag',
1598
+ name: 'p',
1599
+ raw: 'p',
1600
+ offset: 0,
1601
+ endOffset: 1,
1602
+ line: 1,
1603
+ endLine: 1,
1604
+ column: 1,
1605
+ endColumn: 2,
1606
+ block: {
1607
+ type: 'Block',
1608
+ nodes: [
1609
+ {
1610
+ type: 'Text',
1611
+ raw: 'lorem ',
1612
+ offset: 5,
1613
+ endOffset: 11,
1614
+ line: 2,
1615
+ endLine: 2,
1616
+ column: 4,
1617
+ endColumn: 10,
1618
+ },
1619
+ {
1620
+ type: 'Tag',
1621
+ name: 'span',
1622
+ raw: 'span',
1623
+ offset: 13,
1624
+ endOffset: 17,
1625
+ line: 2,
1626
+ endLine: 2,
1627
+ column: 12,
1628
+ endColumn: 16,
1629
+ block: {
1630
+ type: 'Block',
1631
+ nodes: [
1632
+ {
1633
+ type: 'Text',
1634
+ raw: 'ipsum',
1635
+ offset: 18,
1636
+ endOffset: 23,
1637
+ line: 2,
1638
+ endLine: 2,
1639
+ column: 17,
1640
+ endColumn: 22,
1641
+ },
1642
+ ],
1643
+ line: 2,
1644
+ },
1645
+ attrs: [],
1646
+ },
1647
+ // A cause of issue #58
1648
+ {
1649
+ type: 'Text',
1650
+ raw: '',
1651
+ offset: 24,
1652
+ endOffset: 24,
1653
+ line: 2,
1654
+ endLine: 2,
1655
+ column: 23,
1656
+ endColumn: 23,
1657
+ },
1658
+ ],
1659
+ line: 1,
1660
+ },
1661
+ attrs: [],
1662
+ },
1663
+ ],
1664
+ line: 0,
1665
+ });
1666
+ });
1667
+
1668
+ it('block-in-tag', () => {
1669
+ const ast = pugParse(`div.
1670
+ #text
1671
+ <img tag>
1672
+ <span>
1673
+ #text2
1674
+ </span>`);
1675
+ // console.log(JSON.stringify(ast));
1676
+ expect(ast).toStrictEqual({
1677
+ type: 'Block',
1678
+ nodes: [
1679
+ {
1680
+ type: 'Tag',
1681
+ name: 'div',
1682
+ raw: 'div',
1683
+ offset: 0,
1684
+ endOffset: 3,
1685
+ line: 1,
1686
+ endLine: 1,
1687
+ column: 1,
1688
+ endColumn: 4,
1689
+ block: {
1690
+ type: 'Block',
1691
+ nodes: [
1692
+ {
1693
+ type: 'Text',
1694
+ raw: '\n\t#text\n\t<img tag>\n\t<span>\n\t\t#text2\n\t</span>',
1695
+ offset: 4,
1696
+ endOffset: 48,
1697
+ line: 1,
1698
+ endLine: 6,
1699
+ column: 5,
1700
+ endColumn: 9,
1701
+ },
1702
+ ],
1703
+ line: 1,
1704
+ },
1705
+ attrs: [],
1706
+ },
1707
+ ],
1708
+ line: 0,
1709
+ });
1710
+ });
1711
+
1712
+ it('block-in-tag', () => {
1713
+ const ast = pugParse(`div.
1714
+ <input invalid-attr/>
1715
+ <input invalid-attr/>`);
1716
+ // console.log(JSON.stringify(ast));
1717
+ expect(ast).toStrictEqual({
1718
+ type: 'Block',
1719
+ nodes: [
1720
+ {
1721
+ type: 'Tag',
1722
+ name: 'div',
1723
+ raw: 'div',
1724
+ offset: 0,
1725
+ endOffset: 3,
1726
+ line: 1,
1727
+ endLine: 1,
1728
+ column: 1,
1729
+ endColumn: 4,
1730
+ block: {
1731
+ type: 'Block',
1732
+ nodes: [
1733
+ {
1734
+ type: 'Text',
1735
+ raw: '\n\t<input invalid-attr/>\n\t<input invalid-attr/>',
1736
+ offset: 4,
1737
+ endOffset: 50,
1738
+ line: 1,
1739
+ endLine: 3,
1740
+ column: 5,
1741
+ endColumn: 23,
1742
+ },
1743
+ ],
1744
+ line: 1,
1745
+ },
1746
+ attrs: [],
1747
+ },
1748
+ ],
1749
+ line: 0,
1750
+ });
1751
+ });
1752
+ });