| 1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-397
-398
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-409
-410
-411
-412
-413
-414
-415
-416
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-441
-442
-443
-444
-445
-446
-447
-448
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-489
-490
-491
-492
-493
-494
-495
-496
-497
-498
-499
-500
-501
-502
-503
-504
-505
-506
-507
-508
-509
-510
-511
-512
-513
-514
-515
-516
-517
-518
-519
-520
-521
-522
-523
-524
-525
-526
-527
-528
-529
-530
-531
-532
-533
-534
-535
-536
-537
-538
-539
-540
-541
-542
-543
-544
-545
-546
-547
-548
-549
-550
-551
-552
-553
-554
-555
-556
-557
-558
-559
-560
-561
-562
-563
-564
-565
-566
-567
-568
-569
-570
-571
-572
-573
-574
-575
-576
-577
-578
-579
-580
-581
-582
-583
-584
-585
-586
-587
-588
-589
-590
-591
-592
-593
-594
-595
-596
-597
-598
-599
-600
-601
-602
-603
-604
-605
-606
-607
-608
-609
-610
-611
-612
-613
-614
-615
-616
-617
-618
-619
-620
-621
-622
-623
-624
-625
-626
-627
-628
-629
-630
-631
-632
-633
-634
-635
-636
-637
-638
-639
-640
-641
-642
-643
-644
-645
-646
-647
-648
-649
-650
-651
-652
-653
-654
-655
-656
-657
-658
-659
-660
-661
-662
-663
-664
-665
-666
-667
-668
-669
-670
-671
-672
-673
-674
-675
-676
-677
-678
-679
-680
-681
-682
-683
-684
-685
-686
-687
-688
-689
-690
-691
-692
-693
-694
-695
-696
-697
-698
-699
-700
-701
-702
-703
-704
-705
-706
-707
-708
-709
-710
-711
-712
-713
-714
-715
-716
-717
-718
-719
-720
-721
-722
-723
-724
-725
-726
-727
-728
-729
-730
-731
-732
-733
-734
-735
-736
-737
-738
-739
-740
-741
-742
-743
-744
-745
-746
-747
-748
-749
-750
-751
-752
-753
-754
-755
-756
-757
-758
-759
-760
-761
-762
-763
-764
-765
-766
-767
-768
-769
-770
-771
-772
-773
-774
-775
-776
-777
-778
-779
-780
-781
-782
-783
-784
-785
-786
-787
-788
-789
-790
-791
-792
-793
-794
-795
-796
-797
-798
-799
-800
-801
-802
-803
-804
-805
-806
-807
-808
-809
-810
-811
-812
-813
-814
-815
-816
-817
-818
-819
-820
-821
-822
-823
-824
-825
-826
-827
-828
-829
-830
-831
-832
-833
-834
-835
-836
-837
-838
-839
-840
-841
-842
-843
-844
-845
-846
-847
-848
-849
-850
-851
-852
-853
-854
-855
-856
-857
-858
-859
-860
-861
-862
-863
-864
-865
-866
-867
-868
-869
-870
-871
-872
-873
-874
-875
-876
-877
-878
-879
-880
-881
-882
-883
-884
-885
-886
-887
-888
-889
-890
-891
-892
-893
-894
-895
-896
-897
-898
-899
-900
-901
-902
-903
-904
-905
-906
-907
-908
-909
-910
-911
-912
-913
-914
-915
-916
-917
-918
-919
-920
-921
-922
-923
-924
-925
-926
-927
-928
-929
-930
-931
-932
-933
-934
-935
-936
-937
-938
-939
-940
-941
-942
-943
-944
-945
-946
-947
-948
-949
-950
-951
-952
-953
-954
-955
-956
-957
-958
-959
-960
-961
-962
-963
-964
-965
-966
-967
-968
-969
-970
-971
-972
-973
-974
-975
-976
-977
-978
-979
-980
-981
-982
-983
-984
-985
-986
-987
-988
-989
-990
-991
-992
-993
-994
-995
-996
-997
-998
-999
-1000
-1001
-1002
-1003
-1004
-1005
-1006
-1007
-1008
-1009
-1010
-1011
-1012
-1013
-1014
-1015
-1016
-1017
-1018
-1019
-1020
-1021
-1022
-1023
-1024
-1025
-1026
-1027
-1028
-1029
-1030
-1031
-1032
-1033
-1034
-1035
-1036
-1037
-1038
-1039
-1040
-1041
-1042
-1043
-1044
-1045
-1046
-1047
-1048
-1049
-1050
-1051
-1052
-1053
-1054
-1055
-1056
-1057
-1058
-1059
-1060
-1061
-1062
-1063
-1064
-1065
-1066
-1067
-1068
-1069
-1070
-1071
-1072
-1073
-1074
-1075
-1076
-1077
-1078
-1079
-1080
-1081
-1082
-1083
-1084
-1085
-1086
-1087
-1088
-1089
-1090
-1091
-1092
-1093
-1094
-1095
-1096
-1097
-1098
-1099
-1100
-1101
-1102
-1103
-1104
-1105
-1106
-1107
-1108
-1109
-1110
-1111
-1112
-1113
-1114
-1115
-1116
-1117 | 2ร
-
-
-
-
-
-
-
-
-
-2ร
-
-
-1ร
-180ร
-180ร
-
-
-
-100ร
-100ร
-
-180ร
-180ร
-
-
-
-2ร
-28ร
-32ร
-32ร
-32ร
-32ร
-
-
-
-
-2ร
-2ร
-
-
-
-2ร
-52ร
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2ร
-2ร
-2ร
-2ร
-2ร
-
-
-2ร
-2ร
-
-2ร
-2ร
-2ร
-2ร
-
-
-
-
-
-
-
-1ร
-38ร
-
-
-
-
-38ร
-26ร
-12ร
-
-26ร
-
-
-
-
-
-1ร
-22ร
-
-12ร
-12ร
-6ร
-6ร
-
-6ร
-6ร
-
-6ร
-4ร
-
-6ร
-
-2ร
-2ร
-
-
-
-
-1ร
-50ร
-50ร
-18ร
-18ร
-
-
-
-
-1ร
-90ร
-90ร
-
-
-
-1ร
-14ร
-14ร
-2ร
-2ร
-2ร
-
-12ร
-12ร
-
-
-
-
-
-
-
-
-1ร
-26ร
-92ร
-
-
-
-22ร
-22ร
-
-6ร
-6ร
-
-64ร
-40ร
-40ร
-12ร
-
-28ร
-
-
-
-8ร
-8ร
-
-2ร
-2ร
-4ร
-
-2ร
-2ร
-2ร
-
-16ร
-2ร
-
-16ร
-2ร
-2ร
-
-
-16ร
-16ร
-16ร
-
-
-24ร
-2ร
-
-22ร
-
-64ร
-
-
-
-
-
-
-
-
-1ร
-26ร
-
-
-
-
-
-
-
-
-
-
-
-26ร
-26ร
-
-22ร
-14ร
-14ร
-14ร
-
-
-
-
-10ร
-6ร
-
-
-6ร
-4ร
-
-
-
-
-20ร
-16ร
-
-
-16ร
-14ร
-
-
-
-
-
-
-
-1ร
-30ร
-30ร
-48ร
-34ร
-34ร
-
-
-
-
-
-1ร
-24ร
-50ร
-
-
-
-20ร
-20ร
-20ร
-20ร
-20ร
-
-2ร
-2ร
-
-28ร
-18ร
-2ร
-2ร
-
-16ร
-
-
-
-4ร
-4ร
-
-2ร
-2ร
-2ร
-
-2ร
-2ร
-
-10ร
-2ร
-
-10ร
-2ร
-2ร
-
-
-8ร
-8ร
-
-
-10ร
-2ร
-
-8ร
-
-
-
-
-
-
-
-28ร
-
-
-
-
-
-
-
-
-
-1ร
-92ร
-
-
-
-
-
-
-32ร
-32ร
-26ร
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1ร
-174ร
-
-
-
-
-
-250ร
-250ร
-
-92ร
-92ร
-92ร
-
-60ร
-58ร
-16ร
-42ร
-
-
-
-22ร
-
-20ร
-20ร
-20ร
-
-
-60ร
-
-98ร
-4ร
-
-98ร
-
-
-
-
-
-
-
-2ร
-
-
-
-
-2ร
-
-
-
-
-
-2ร
-2ร
-2ร
-2ร
-
-
-
-
-2ร
-
-
-
-
-
-
-2ร
-
-
-2ร
-2ร
-
-
-
-
-
-
-1ร
-4ร
-
-
-
-1ร
-36ร
-
-
-
-
-
-
-
-56ร
-56ร
-
-
-
-40ร
-
-
-36ร
-
-
-
-1ร
-127ร
-
-
-
-
-1ร
-102ร
-
-
-
-
-
-
-
-1ร
-100ร
-100ร
-100ร
-100ร
-100ร
-100ร
-
-47ร
-
-
-
-
-
-
-47ร
-
-100ร
-
-
-
-1ร
-1ร
-1ร
-
-99ร
-99ร
-53ร
-
-46ร
-
-
-100ร
-
-
-
-1ร
-2ร
-2ร
-2ร
-2ร
-2ร
-2ร
-
-
-
-1ร
-68ร
-
-
-
-
-1ร
-46ร
-
-
-
-
-
-
-
-
-72ร
-
-8ร
-8ร
-6ร
-
-8ร
-8ร
-
-26ร
-
-
-16ร
-16ร
-16ร
-26ร
-26ร
-10ร
-
-16ร
-
-
-16ร
-16ร
-14ร
-
-16ร
-16ร
-14ร
-
-16ร
-16ร
-
-
-10ร
-10ร
-10ร
-10ร
-10ร
-10ร
-10ร
-10ร
-
-
-
-
-
-2ร
-2ร
-
-
-2ร
-
-
-8ร
-8ร
-
-10ร
-
-
-
-10ร
-
-
-
-
-
-10ร
-8ร
-
-10ร
-
-26ร
-
-
-38ร
-
-
-
-
-
-38ร
-38ร
-
-
-46ร
-
-
-
-1ร
-26ร
-
-
-
-1ร
-32ร
-32ร
-
-32ร
-60ร
-60ร
-28ร
-
-32ร
-
-
-
-
-
-1ร
-60ร
-
-
-
-1ร
-100ร
-14ร
-
-
-
-
-1ร
-10ร
-10ร
-2ร
-2ร
-
-
-
-
-1ร
-106ร
-106ร
-
-26ร
-26ร
-
-26ร
-26ร
-
-30ร
-30ร
-
-24ร
-24ร
-
-106ร
-
-
-
-
-1ร
-16ร
-16ร
-12ร
-12ร
-12ร
-12ร
-12ร
-12ร
-12ร
-
-
-
-
-1ร
-88ร
-
-
-
-
-
-
-
-2ร
-
-2ร
-109ร
-
-58ร
-
-
-
-
-
-
-
-
-
-2ร
-
-1ร
-1ร
-
-50ร
-
-
-
-
-
-41ร
-
-
-
-
-
-
-
-
-2ร
-
-1ร
-
-
-1ร
-1ร
-59ร
-
-
-
-
-2ร
-12ร
-
-
-
-
-
-
-2ร
-2ร
-1ร
-1ร
-135ร
-135ร
-
-
-
-
-
-2ร
-
-63ร
-
-
-16ร
-
-
-
-
-24ร
-
-
-
-
-2ร
-124ร
-
-
-2ร
-
-102ร
-
-
-
-
-
-
-289ร
-289ร
-161ร
-
-102ร
-
-61ร
-
-
-
-2ร
-
-57ร
-79ร
-79ร
-
-41ร
-41ร
-
-38ร
-38ร
-
-
-57ร
-
-
-57ร
-79ร
-
-57ร
-
-
-
-2ร
-1ร
-1ร
-1ร
-13ร
-13ร
-
-
-
-
-2ร
-
-6ร
-6ร
-
-6ร
-
-2ร
-
-5ร
-5ร
-
-5ร
-
-
-2ร
-
-
-2ร
-
-
-2ร
-
-
-2ร
-
-
-
-2ร
-2ร
-2ร
-2ร
-
-119ร
-
-
-
-
-
-85ร
-
-119ร
-
-
-34ร
-
-
-
-
-
-
-
-
-
-1ร
-82ร
-82ร
-82ร
-41ร
-41ร
-
-82ร
-82ร
-82ร
-82ร
-82ร
-
-
-
-
-
-1ร
-88ร
-88ร
-88ร
-
-
-20ร
-20ร
-
-
-42ร
-42ร
-
-
-
-42ร
-
-
-26ร
-26ร
-26ร
-
-88ร
-
-
-
-
-64ร
-
-88ร
-
-
-
-
-
-1ร
-68ร
-
-
-
-
-
-
-60ร
-60ร
-60ร
-6ร
-6ร
-
-60ร
-
-68ร
-68ร
-
-
-
-1ร
-32ร
-
-
-
-
-
-
-46ร
-46ร
-46ร
-
-
-
-
-
-
-32ร
-32ร
-
-
-
-1ร
-180ร
-198ร
-
-
-
-
-
-1ร
-100ร
-100ร
-100ร
-
-100ร
-68ร
-68ร
-68ร
-
-32ร
-
-100ร
-
-
-
-
-
-
-
-1ร
-32ร
-
-1ร
-34ร
-34ร
-
-
-34ร
-
-
-1ร
-58ร
-36ร
-36ร
-4ร
-
-36ร
-
-58ร
-
-
-32ร
-
-14ร
-14ร
-14ร
-10ร
-10ร
-10ร
-14ร
-10ร
-2ร
-2ร
-
-
-
-
-2ร
-
-8ร
-8ร
-
-
-14ร
-14ร
-
-
-14ร
-
-
-44ร
-44ร
-26ร
-26ร
-26ร
-
-44ร
-44ร
-
-
-
-
-1ร
-38ร
-38ร
-38ร
-38ร
-8ร
-8ร
-
-38ร
-16ร
-16ร
-
-38ร
-
-
-
-
-
-2ร
-
-
-
-
-2ร
- | var hyperHTML = (function (globalDocument) {'use strict';
-
- /*! (c) 2017 Andrea Giammarchi @WebReflection, (ISC) */
-
- // ---------------------------------------------
- // hyperHTML Public API
- // ---------------------------------------------
-
- // The document must be swap-able at runtime.
- // Needed by both basicHTML and nativeHTML
- hyperHTML.document = globalDocument;
-
- // hyperHTML.bind(el) โก๏ธ
- function hyperHTML(template) {
- var hyper = hypers.get(this);
- if (
- !hyper ||
- hyper.template !== (FF ? unique(template) : template)
- ) {
- hyper = upgrade.apply(this, arguments);
- hypers.set(this, hyper);
- }
- update.apply(hyper.updates, arguments);
- return this;
- }
-
- // hyperHTML.adopt(el) ๐ฃ
- hyperHTML.adopt = function adopt(node) {
- return function () {
- notAdopting = false;
- hyperHTML.apply(node, arguments);
- notAdopting = true;
- return node;
- };
- };
-
- // hyperHTML.escape('<html>') => '<text>'
- hyperHTML.escape = function escape(html) {
- return html.replace(reEscape, fnEscape);
- };
-
- // hyperHTML.wire(obj, 'type:ID') โฐ
- hyperHTML.wire = function wire(obj, type) {
- return arguments.length < 1 ?
- wireContent('html') :
- (obj == null ?
- wireContent(type || 'html') :
- wireWeakly(obj, type || 'html')
- );
- };
-
- // - - - - - - - - - - - - - - - - - - - - - - -
-
- // ---------------------------------------------
- // Constants
- // ---------------------------------------------
-
- // Node.CONSTANTS
- // without assuming Node is globally available
- // since this project is used on the backend too
- var ELEMENT_NODE = 1;
- var ATTRIBUTE_NODE = 2;
- var TEXT_NODE = 3;
- var COMMENT_NODE = 8;
- var DOCUMENT_FRAGMENT_NODE = 11;
-
- // SVG related
- var OWNER_SVG_ELEMENT = 'ownerSVGElement';
- var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
-
- var SHOULD_USE_ATTRIBUTE = /^style$/i;
- var EXPANDO = '_hyper_html: ';
- var UID = EXPANDO + ((Math.random() * new Date) | 0) + ';';
- var UIDC = '<!--' + UID + '-->';
-
- // ---------------------------------------------
- // DOM Manipulation
- // ---------------------------------------------
-
- // return -1 if no differences are found
- // the index where differences starts otherwise
- function indexOfDifferences(a, b) {
- var
- i = 0,
- aLength = a.length,
- bLength = b.length
- ;
- while (i < aLength) {
- if (i < bLength && a[i] === b[i]) i++;
- else return i;
- }
- return i === bLength ? -1 : i;
- }
-
- // accordingly with the content type
- // it replace the content of a node
- // with the give child
- function populateNode(parent, child) {
- switch (child.nodeType) {
- case ELEMENT_NODE:
- var childNodes = parent.childNodes;
- if (childNodes[0] === child) {
- removeNodeList(childNodes, 1);
- break;
- }
- resetAndPopulate(parent, child);
- break;
- case DOCUMENT_FRAGMENT_NODE:
- if (indexOfDifferences(parent.childNodes, child.childNodes) !== -1) {
- resetAndPopulate(parent, child);
- }
- break;
- case TEXT_NODE:
- parent.textContent = child.textContent;
- break;
- }
- }
-
- // remove a list of nodes from startIndex to list.length
- function removeNodeList(list, startIndex) {
- var length = list.length, child;
- while (startIndex < length--) {
- child = list[length];
- child.parentNode.removeChild(child);
- }
- }
-
- // erase a node content and populate it
- function resetAndPopulate(parent, child) {
- parent.textContent = '';
- parent.appendChild(child);
- }
-
- // append childNodes to a node from a specific index
- function updateViaArray(node, childNodes, i) {
- var fragment = emptyFragment(node);
- if (i !== 0) {
- removeNodeList(node.childNodes, i);
- appendNodes(fragment, childNodes.slice(i));
- node.appendChild(fragment);
- } else {
- appendNodes(fragment, childNodes);
- resetAndPopulate(node, fragment);
- }
- }
-
- // ---------------------------------------------
- // hyperHTML Operations
- // ---------------------------------------------
-
- // `<div>${'any'}</div>`
- function setAnyContent(node) {
- return function any(value) {
- switch (typeof value) {
- case 'string':
- case 'number':
- case 'boolean':
- node.innerHTML = value;
- break;
- case 'function':
- any(value(node, node.children, 0));
- break;
- default:
- if (isArray(value)) {
- var i, length = value.length;
- if (length === 1) {
- any(value[0]);
- } else {
- switch (length === 0 ? '' : typeof value[0]) {
- case 'string':
- case 'number':
- case 'boolean':
- any(value.join(''));
- break;
- case 'function':
- var children = slice.call(node.children);
- for (i = 0, length = value.length; i < length; i++) {
- value[i] = value[i](node, children, i);
- }
- removeNodeList(children, i);
- any(value.concat.apply([], value));
- break;
- case 'object':
- if (isArray(value[0])) {
- value = value.concat.apply([], value);
- }
- if (isPromise_ish(value[0])) {
- Promise.all(value).then(any);
- break;
- }
- default:
- i = indexOfDifferences(node.childNodes, value);
- if (i !== -1) updateViaArray(node, value, i);
- break;
- }
- }
- } else if (isPromise_ish(value)) {
- value.then(any);
- } else {
- populateNode(node, value);
- }
- break;
- }
- };
- }
-
- // `<div class="${'attr'}"></div>`
- // `<div onclick="${function () {... }}"></div>`
- // `<div onclick="${{handleEvent(){ ... }}}"></div>`
- // `<div contenteditable="${true}"></div>`
- function setAttribute(attribute, removeAttributes) {
- var
- name = attribute.name,
- node = attribute.ownerElement,
- isEvent = /^on/.test(name),
- isSpecial = name in node && !(
- // always use set attribute with SVGs
- OWNER_SVG_ELEMENT in node ||
- SHOULD_USE_ATTRIBUTE.test(name)
- ),
- type = isEvent ? name.slice(2) : '',
- oldValue
- ;
- if (isSpecial || isEvent) removeAttributes.push(node, name);
- return isEvent ?
- function eventAttr(newValue) {
- if (oldValue !== newValue) {
- if (oldValue) node.removeEventListener(type, oldValue, false);
- oldValue = newValue;
- if (newValue) node.addEventListener(type, newValue, false);
- }
- } :
- (isSpecial ?
- function specialAttr(newValue) {
- if (oldValue !== newValue) {
- oldValue = newValue;
- // WebKit moves the cursor if input.value
- // is set again, even if same value
- if (node[name] !== newValue) {
- node[name] = newValue;
- }
- }
- } :
- function normalAttr(newValue) {
- if (oldValue !== newValue) {
- oldValue = newValue;
- // WebKit moves the cursor if input.value
- // is set again, even if same value
- if (attribute.value !== newValue) {
- attribute.value = newValue;
- }
- }
- }
- );
- }
-
- // `<div> ${'text'} </div>`
- function setTextContent(node) {
- var oldValue;
- return function text(newValue) {
- if (oldValue !== newValue) {
- oldValue = newValue;
- node.textContent = newValue;
- }
- };
- }
-
- // `<li>a</li>${'virtual'}<li>c</li>`
- function setVirtualContent(node, childNodes) {
- return function anyVirtual(value) {
- switch (typeof value) {
- case 'string':
- case 'number':
- case 'boolean':
- removeNodeList(childNodes, 0);
- var fragment = createFragment(node, value);
- childNodes = slice.call(fragment.childNodes);
- node.parentNode.insertBefore(fragment, node);
- break;
- case 'function':
- anyVirtual(value(node.parentNode, childNodes, 0));
- break;
- default:
- if (isArray(value)) {
- if (value.length === 0) {
- removeNodeList(childNodes, 0);
- childNodes = [];
- } else {
- switch (typeof value[0]) {
- case 'string':
- case 'number':
- case 'boolean':
- anyVirtual(value.join(''));
- break;
- case 'function':
- var parentNode = node.parentNode;
- for (var i = 0, length = value.length; i < length; i++) {
- value[i] = value[i](parentNode, childNodes, i);
- }
- anyVirtual(value.concat.apply([], value));
- break;
- case 'object':
- if (isArray(value[0])) {
- value = value.concat.apply([], value);
- }
- if (isPromise_ish(value[0])) {
- Promise.all(value).then(anyVirtual);
- break;
- }
- default:
- updateVirtualNodes(node, childNodes, value);
- break;
- }
- }
- } else if (isPromise_ish(value)) {
- value.then(anyVirtual);
- } else {
- updateVirtualNodes(
- node,
- childNodes,
- value.nodeType === DOCUMENT_FRAGMENT_NODE ?
- slice.call(value.childNodes) :
- [value]
- );
- }
- break;
- }
- };
- }
-
- // ---------------------------------------------
- // DOM Traversing
- // ---------------------------------------------
-
- // look for attributes that contains the comment text
- function attributesSeeker(node, paths) {
- for (var
- attribute,
- value = IE ? UID : UIDC,
- attributes = node.attributes,
- i = 0, length = attributes.length;
- i < length; i++
- ) {
- attribute = attributes[i];
- if (attribute.value === value) {
- paths.push(
- Path(
- 'attr',
- // with IE the order doesn't really matter
- // as long as the right attribute is addressed
- IE ?
- node.attributes[IEAttributes.shift()] :
- attribute
- )
- );
- }
- }
- }
-
- // walk the fragment tree in search of comments
- function commentsSeeker(node, paths) {
- for (var
- child, text,
- childNodes = node.childNodes,
- length = childNodes.length,
- i = 0; i < length; i++
- ) {
- child = childNodes[i];
- switch (child.nodeType) {
- case ELEMENT_NODE:
- attributesSeeker(child, paths);
- commentsSeeker(child, paths);
- break;
- case COMMENT_NODE:
- if (child.textContent === UID) {
- if (length === 1) {
- paths.push(Path('any', node));
- } else if (
- (i < 1 || childNodes[i - 1].nodeType === ELEMENT_NODE) &&
- (i + 1 === length || childNodes[i + 1].nodeType === ELEMENT_NODE)
- ) {
- paths.push(Path('virtual', child));
- } else {
- text = createText(child, '');
- child.parentNode.replaceChild(text, child);
- paths.push(Path('text', text));
- }
- }
- break;
- case TEXT_NODE:
- if (SHOULD_USE_ATTRIBUTE.test(node.nodeName) && child.textContent === UIDC) {
- paths.push(Path('text', node));
- }
- break;
- }
- }
- }
-
- // ---------------------------------------------
- // Features detection / ugly UA sniffs
- // ---------------------------------------------
- var featureFragment = createDocumentFragment(globalDocument);
-
- // Firefox < 55 has non standard template literals.
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1108941
- // TODO: is there any better way to feature detect this ?
- var FF = typeof navigator === 'object' &&
- /Firefox\/(\d+)/.test(navigator.userAgent) &&
- parseFloat(RegExp.$1) < 55;
-
- // If attributes order is shuffled, threat the browser differently
- // Usually this is a well known IE only limitation but some older FF does the same.
- var IE = (function () {
- var p = globalDocument.createElement('p');
- p.innerHTML = '<i data-i="" class=""></i>';
- return /class/i.test(p.firstChild.attributes[0].name);
- }());
-
-
- // beside IE, old WebKit browsers don't have `children` in DocumentFragment
- var WK = !('children' in featureFragment);
-
- // ---------------------------------------------
- // Helpers
- // ---------------------------------------------
-
- // used to convert childNodes to Array
- var slice = [].slice;
-
- // used to sanitize html
- var reEscape = /[&<>'"]/g;
- var oEscape = {
- '&': '&',
- '<': '<',
- '>': '>',
- "'": ''',
- '"': '"'
- };
- function fnEscape(m) {
- return oEscape[m];
- }
-
- // return a single node or an Array or nodes
- function createContent(node) {
- for (var
- child,
- content = [],
- childNodes = node.childNodes,
- i = 0,
- length = childNodes.length;
- i < length; i++
- ) {
- child = childNodes[i];
- if (
- child.nodeType === ELEMENT_NODE ||
- trim.call(child.textContent).length !== 0
- ) {
- content.push(child);
- }
- }
- return content.length === 1 ? content[0] : content;
- }
-
- // just a minifier friendly indirection
- function createDocumentFragment(document) {
- return document.createDocumentFragment();
- }
-
- // given a node, inject some html and return
- // the resulting template document fragment
- function createFragment(node, html) {
- return (
- OWNER_SVG_ELEMENT in node ?
- createSVGFragment :
- createHTMLFragment
- )(node, html);
- }
-
- // create fragment for HTML
- function createHTMLFragment(node, html) {
- var fragment;
- var document = node.ownerDocument;
- var container = document.createElement('template');
- var hasContent = 'content' in container;
- var needsTableWrap = false;
- if (!hasContent) {
- // DO NOT MOVE THE FOLLOWING LINE ELSEWHERE
- fragment = createDocumentFragment(document);
- // (a jsdom + nodejs tests coverage gotcha)
-
- // el.innerHTML = '<td></td>'; is not possible
- // if the content is a partial internal table content
- // it needs to be wrapped around once injected.
- // HTMLTemplateElement does not suffer this issue.
- needsTableWrap = /^[^\S]*?<(t(?:head|body|foot|r|d|h))/i.test(html);
- }
- if (needsTableWrap) {
- // secure the RegExp.$1 result ASAP to avoid issues
- // in case a non-browser DOM library uses RegExp internally
- // when HTML content is injected (basicHTML / jsdom / others...)
- var selector = RegExp.$1;
- container.innerHTML = '<table>' + html + '</table>';
- appendNodes(fragment, slice.call(container.querySelectorAll(selector)));
- } else {
- container.innerHTML = html;
- if (hasContent) {
- fragment = container.content;
- } else {
- appendNodes(fragment, slice.call(container.childNodes));
- }
- }
- return fragment;
- }
-
- // create a fragment for SVG
- function createSVGFragment(node, html) {
- var document = node.ownerDocument;
- var fragment = createDocumentFragment(document);
- var container = document.createElementNS(SVG_NAMESPACE, 'svg');
- container.innerHTML = html;
- appendNodes(fragment, slice.call(container.childNodes));
- return fragment;
- }
-
- // given a node, it does what is says
- function createText(node, text) {
- return node.ownerDocument.createTextNode(text);
- }
-
- // given an info, tries to find out the best option
- // to replace or update the content
- function discoverNode(parentNode, virtual, info, childNodes) {
- for (var
- target = parentNode,
- document = parentNode.ownerDocument,
- path = info.path,
- virtualNode = getNode(virtual, path),
- i = 0,
- length = path.length;
- i < length; i++
- ) {
- switch (path[i++]) {
- case 'attributes':
- var name = virtualNode.name;
- if (!parentNode.hasAttribute(name)) {
- parentNode.setAttribute(name, '');
- }
- target = parentNode.attributes[name];
- break;
- case 'childNodes':
- switch (info.type) {
- // TODO: supports multiple text per element ?
- case 'text':
- var before = getTextContent(virtualNode, 'previous');
- var after = getTextContent(virtualNode, 'next');
- do {
- target = parentNode.firstChild;
- if (target && target.nodeType === TEXT_NODE) {
- parentNode.removeChild(target);
- } else {
- break;
- }
- } while (target);
- var fragment = createDocumentFragment(document);
- if (before.length) {
- fragment.appendChild(createText(parentNode, before));
- }
- target = fragment.appendChild(createText(parentNode, ''));
- if (after.length) {
- fragment.appendChild(createText(parentNode, after));
- }
- parentNode.insertBefore(fragment, parentNode.firstChild);
- break;
- // TODO: supports multiple virtual content per element ?
- case 'virtual':
- var children = getChildren(parentNode);
- var virtualChildren = getChildren(virtualNode.parentNode);
- target = previousElementSibling(virtualNode);
- var before = target ? (path.indexOf.call(virtualChildren, target) + 1) : -1;
- target = nextElementSibling(virtualNode);
- var after = target ? path.indexOf.call(virtualChildren, target) : -1;
- target = document.createComment(UID);
- switch (true) {
- // `${'virtual'}` is actually resolved as `${'any'}`
- // case before < 0 && after < 0: before = 0;
-
- // `</a>${'virtual'}`
- case after < 0:
- after = children.length;
- break;
- // `${'virtual'}<b>`
- case before < 0:
- before = 0;
- // `</a>${'virtual'}<b>`
- default:
- after = -(virtualChildren.length - after);
- break;
- }
- childNodes.push.apply(
- childNodes,
- slice.call(children, before, after)
- );
- parentNode.insertBefore(
- target,
- childNodes.length ?
- nextElementSibling(childNodes[childNodes.length - 1]) :
- slice.call(children, after)[0]
- );
- if (childNodes.length === 0) {
- removePreviousText(parentNode, target);
- }
- break;
- }
- break;
- default:
- // if the node is not there, create it
- target = getChildren(parentNode)[path[i]] ||
- parentNode.appendChild(
- parentNode.ownerDocument.createElement(
- getNode(virtual, path.slice(0, i + 1)).nodeName
- )
- );
- parentNode = target;
- break;
- }
- }
- return target;
- }
-
- // create an empty fragment from a generic node
- function emptyFragment(node) {
- return createDocumentFragment(node.ownerDocument);
- }
-
- // given a node, returns text content before it or after it
- function getTextContent(node, direction) {
- var content = [];
- var method = direction === 'next' ?
- content.push : content.unshift;
- do {
- node = node[direction + 'Sibling'];
- if (node && node.nodeType === TEXT_NODE) {
- method.call(content, node.textContent);
- } else {
- return content.join('');
- }
- } while (true);
- }
-
- // quick and dirty Promise check
- function isPromise_ish(value) {
- return value != null && 'then' in value;
- }
-
- // remove a list of [node, attribute]
- function removeAttributeList(list) {
- for (var i = 0, length = list.length; i < length; i++) {
- list[i++].removeAttribute(list[i]);
- }
- }
-
- // remove all text nodes from a virtual space
- function removePreviousText(parentNode, node) {
- var previousSibling = node.previousSibling;
- if (previousSibling && previousSibling.nodeType === TEXT_NODE) {
- parentNode.removeChild(previousSibling);
- removePreviousText(parentNode, node);
- }
- }
-
- // specify the content to update
- function setContent(type, target, removeAttributes, childNodes) {
- var update;
- switch (type) {
- case 'any':
- update = setAnyContent(target);
- break;
- case 'attr':
- update = setAttribute(target, removeAttributes);
- break;
- case 'text':
- update = setTextContent(target);
- break;
- case 'virtual':
- update = setVirtualContent(target, childNodes);
- break;
- }
- return update;
- }
-
- // update partially or fully the list of virtual nodes
- // it modifies in place the childNodes list if necessary
- function updateVirtualNodes(node, childNodes, value) {
- var i = indexOfDifferences(childNodes, value);
- if (i !== -1) {
- var fragment = emptyFragment(node);
- removeNodeList(childNodes, i);
- childNodes.splice(i);
- value = value.slice(i);
- appendNodes(fragment, value);
- node.parentNode.insertBefore(fragment, node);
- childNodes.push.apply(childNodes, value);
- }
- }
-
- // used for common path creation.
- function Path(type, node) {
- return {type: type, path: createPath(node)};
- }
-
- // ---------------------------------------------
- // Hybrid Shims
- // ---------------------------------------------
-
- // WeakMap with partial EXPANDO fallback
- var $WeakMap = typeof WeakMap === typeof $WeakMap ?
- function () {
- return {
- get: function (obj) { return obj[EXPANDO]; },
- set: function (obj, value) {
- Object.defineProperty(obj, EXPANDO, {
- configurable: true,
- value: value
- });
- }
- };
- } :
- WeakMap;
-
- // Map with partial double Array fallback
- var $Map = typeof Map === typeof $Map ?
- function () {
- var k = [], v = [];
- return {
- get: function (obj) {
- return v[k.indexOf(obj)];
- },
- // being used with unique template literals
- // there is never a case when a value is overwritten
- // no need to check upfront for the indexOf
- set: function (obj, value) {
- v[k.push(obj) - 1] = value;
- }
- };
- } :
- Map;
-
- // TODO: which browser needs these partial polyfills here?
-
- // BB7 and webOS need this
- var isArray = Array.isArray ||
- (function () {
- var toString = {}.toString;
- // I once had an engine returning [array Array]
- // and I've got scared since!
- var s = toString.call([]);
- return function (a) {
- return toString.call(a) === s;
- };
- }());
-
- // older WebKit need this
- var trim = EXPANDO.trim ||
- function () { return this.replace(/^\s+|\s+$/g, ''); };
-
- // ---------------------------------------------
- // Shared variables
- // ---------------------------------------------
-
- // normalize Firefox issue with template literals
- var templateObjects, unique;
- if (FF) {
- templateObjects = Object.create(null);
- unique = function (template) {
- var key = template.join(UID);
- return templateObjects[key] ||
- (templateObjects[key] = template);
- };
- }
-
- // use native .append(...childNodes) where available
- var appendNodes = 'append' in featureFragment ?
- function (node, childNodes) {
- node.append.apply(node, childNodes);
- } :
- function appendNodes(node, childNodes) {
- for (var
- i = 0,
- length = childNodes.length;
- i < length; i++
- ) {
- node.appendChild(childNodes[i]);
- }
- };
-
- // traps function bind once (useful in destructuring)
- var bind = hyperHTML.bind;
- hyperHTML.bind = function () { return bind.apply(hyperHTML, arguments); };
-
- // returns children or retrieve them in IE/Edge
- var getChildren = WK ?
- function (node) {
- for (var
- child,
- children = [],
- childNodes = node.childNodes,
- j = 0, i = 0, length = childNodes.length;
- i < length; i++
- ) {
- child = childNodes[i];
- if (child.nodeType === ELEMENT_NODE)
- children[j++] = child;
- }
- return children;
- } :
- function (node) { return node.children; };
-
- // return the correct node walking through a path
- // fixes IE/Edge issues with attributes and children (fixes old WebKit too)
- var getNode = IE || WK ?
- function (parentNode, path) {
- for (var name, i = 0, length = path.length; i < length; i++) {
- name = path[i++];
- switch (name) {
- case 'children':
- parentNode = getChildren(parentNode)[path[i]];
- break;
- default:
- parentNode = parentNode[name][path[i]];
- break;
- }
- }
- return parentNode;
- } :
- function (parentNode, path) {
- for (var i = 0, length = path.length; i < length; i++) {
- parentNode = parentNode[path[i++]][path[i]];
- }
- return parentNode;
- };
-
- // fixes IE problems with comments
- if (IE) {
- var IEAttributes;
- var no = new RegExp('([^\\S][a-z]+[a-z0-9_-]*=)([\'"])' + UIDC + '\\2', 'g');
- var comments = function ($0, $1, $2) {
- IEAttributes.push($1.slice(1, -1));
- return $1 + $2 + UID + $2;
- };
- }
-
- // IE/Edge gotcha with comment nodes
- var nextElementSibling = IE ?
- function (node) {
- node = node.nextSibling;
- return node && node.nodeType === ELEMENT_NODE ? node : undefined;
- } :
- function (node) { return node.nextElementSibling; };
-
- var previousElementSibling = IE ?
- function (node) {
- node = node.previousSibling;
- return node && node.nodeType === ELEMENT_NODE ? node : undefined;
- } :
- function (node) { return node.previousElementSibling; };
-
- // [element] = {template, updates};
- var hypers = new $WeakMap;
-
- // [element] = {template, updates};
- var wires = new $WeakMap;
-
- // [template] = {fragment, paths};
- var templates = new $Map;
-
- // internal signal to switch adoption
- var notAdopting = true;
-
- // IE 11 has problems with cloning templates too
- // it "forgets" empty childNodes
- var cloneNode = (function () {
- featureFragment.appendChild(createText(featureFragment, 'g'));
- featureFragment.appendChild(createText(featureFragment, ''));
- return featureFragment.cloneNode(true).childNodes.length === 1 ?
- function (node) {
- for (var
- clone = node.cloneNode(),
- childNodes = node.childNodes || [],
- i = 0, length = childNodes.length;
- i < length; i++
- ) {
- clone.appendChild(cloneNode(childNodes[i]));
- }
- return clone;
- } :
- function (fragment) {
- return fragment.cloneNode(true);
- };
- }());
-
- // ---------------------------------------------
- // Template related utilities
- // ---------------------------------------------
-
- // given a unique template object
- // create, parse, and store retrieved info
- function createTemplate(template) {
- var paths = [];
- var html = template.join(UIDC);
- if (IE) {
- IEAttributes = [];
- html = html.replace(no, comments);
- }
- var fragment = createFragment(this, html);
- var info = {fragment: fragment, paths: paths};
- commentsSeeker(fragment, paths);
- templates.set(template, info);
- return info;
- }
-
- // given a generic node, returns a path capable
- // of retrieving such path back again.
- // TODO: worth passing the index when available ?
- function createPath(node) {
- var path = [];
- var parentNode;
- switch(node.nodeType) {
- case ELEMENT_NODE:
- case DOCUMENT_FRAGMENT_NODE:
- parentNode = node;
- break;
- case TEXT_NODE:
- case COMMENT_NODE:
- parentNode = node.parentNode;
- path.unshift(
- 'childNodes',
- path.indexOf.call(parentNode.childNodes, node)
- );
- break;
- case ATTRIBUTE_NODE:
- default: // jsdom here does not provide a nodeType 2 ...
- parentNode = node.ownerElement;
- path.unshift('attributes', node.name);
- break;
- }
- for (
- node = parentNode;
- parentNode = parentNode.parentNode;
- node = parentNode
- ) {
- path.unshift('children', path.indexOf.call(getChildren(parentNode), node));
- }
- return path;
- }
-
- // given a root node and a list of paths
- // creates an array of updates to invoke
- // whenever the next interpolation happens
- function createUpdates(fragment, paths) {
- for (var
- info, target,
- updates = [],
- removeAttributes = [],
- i = 0, length = paths.length;
- i < length; i++
- ) {
- info = paths[i];
- target = getNode(fragment, info.path);
- if (target.nodeType === DOCUMENT_FRAGMENT_NODE) {
- removeNodeList(target.childNodes, 0);
- target = this;
- }
- updates[i] = setContent(info.type, target, removeAttributes, []);
- }
- removeAttributeList(removeAttributes);
- return updates;
- }
-
- // like createUpdates but for nodes with already a content
- function discoverUpdates(fragment, paths) {
- for (var
- info, childNodes,
- updates = [],
- removeAttributes = [],
- i = 0, length = paths.length;
- i < length; i++
- ) {
- childNodes = [];
- info = paths[i];
- updates[i] = setContent(
- info.type,
- discoverNode(this, fragment, info, childNodes),
- removeAttributes,
- childNodes
- );
- }
- removeAttributeList(removeAttributes);
- return updates;
- }
-
- // invokes each update function passing interpolated value
- function update() {
- for (var i = 1, length = arguments.length; i < length; i++) {
- this[i - 1](arguments[i]);
- }
- }
-
- // create a template, if unknown
- // upgrade a node to use such template for future updates
- function upgrade(template) {
- if (FF) template = unique(template);
- var updates;
- var info = templates.get(template) ||
- createTemplate.call(this, template);
- if (notAdopting) {
- var fragment = cloneNode(info.fragment);
- updates = createUpdates.call(this, fragment, info.paths);
- resetAndPopulate(this, fragment);
- } else {
- updates = discoverUpdates.call(this, info.fragment, info.paths);
- }
- return {template: template, updates: updates};
- }
-
- // ---------------------------------------------
- // Wires
- // ---------------------------------------------
-
- // create a new wire for generic DOM content
- function wireContent(type) {
- var adopter, content, container, fragment, render, setup, template;
-
- function before(document) {
- fragment = createDocumentFragment(document);
- container = type === 'svg' ?
- document.createElementNS(SVG_NAMESPACE, 'svg') :
- fragment;
- render = hyperHTML.bind(container);
- }
-
- function after() {
- if (setup) {
- setup = false;
- if (type === 'svg') {
- appendNodes(fragment, slice.call(container.childNodes));
- }
- content = createContent(fragment);
- }
- return content;
- }
-
- return type === 'adopt' ?
- function adopt(statics) {
- var args = arguments;
- if (FF) statics = unique(statics);
- if (template !== statics) {
- setup = true;
- template = statics;
- adopter = function (parentNode, children, i) {
- if (setup) {
- if (i < children.length) {
- container = children[i];
- fragment = {
- ownerDocument: container.ownerDocument,
- childNodes: [container],
- children: [container]
- };
- render = hyperHTML.adopt(fragment);
- } else {
- if (OWNER_SVG_ELEMENT in parentNode) type = 'svg';
- before(parentNode.ownerDocument);
- }
- }
- render.apply(null, args);
- return after();
- };
- }
- return adopter;
- } :
- function update(statics) {
- if (FF) statics = unique(statics);
- if (template !== statics) {
- setup = true;
- template = statics;
- before(hyperHTML.document);
- }
- render.apply(null, arguments);
- return after();
- };
- }
-
- // setup a weak reference if needed and return a wire by ID
- function wireWeakly(obj, type) {
- var wire = wires.get(obj);
- var i = type.indexOf(':');
- var id = type;
- if (-1 < i) {
- id = type.slice(i + 1);
- type = type.slice(0, i) || 'html';
- }
- if (!wire) {
- wire = {};
- wires.set(obj, wire);
- }
- return wire[id] || (wire[id] = wireContent(type));
- }
-
- // ---------------------------------------------
- // โก๏ธ ๏ธ๏ธThe End โฐ
- // ---------------------------------------------
- return hyperHTML;
-
-}(document));
-
-// umd.KISS
-try { module.exports = hyperHTML; } catch(o_O) {}
- |
-