@lexho111/plainblog 0.6.0 → 0.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.
- package/Blog.js +1 -6
- package/blog_test_empty.db +0 -0
- package/blog_test_load.db +0 -0
- package/coverage/clover.xml +638 -630
- package/coverage/coverage-final.json +14 -14
- package/coverage/lcov-report/index.html +36 -36
- package/coverage/lcov-report/package/Article.js.html +20 -20
- package/coverage/lcov-report/package/Blog.js.html +378 -339
- package/coverage/lcov-report/package/Formatter.js.html +2 -2
- package/coverage/lcov-report/package/build-scripts.js.html +1 -1
- package/coverage/lcov-report/package/build-styles.js.html +1 -1
- package/coverage/lcov-report/package/index.html +19 -19
- package/coverage/lcov-report/package/model/APIModel.js.html +8 -8
- package/coverage/lcov-report/package/model/DataModel.js.html +34 -16
- package/coverage/lcov-report/package/model/DatabaseModel.js.html +14 -11
- package/coverage/lcov-report/package/model/FileAdapter.js.html +26 -23
- package/coverage/lcov-report/package/model/FileModel.js.html +20 -17
- package/coverage/lcov-report/package/model/SequelizeAdapter.js.html +36 -36
- package/coverage/lcov-report/package/model/SqliteAdapter.js.html +11 -11
- package/coverage/lcov-report/package/model/datastructures/ArrayList.js.html +2 -2
- package/coverage/lcov-report/package/model/datastructures/ArrayListHashMap.js.html +1 -1
- package/coverage/lcov-report/package/model/datastructures/BinarySearchTree.js.html +71 -68
- package/coverage/lcov-report/package/model/datastructures/BinarySearchTreeHashMap.js.html +28 -19
- package/coverage/lcov-report/package/model/datastructures/FileList.js.html +1 -1
- package/coverage/lcov-report/package/model/datastructures/index.html +21 -21
- package/coverage/lcov-report/package/model/index.html +26 -26
- package/coverage/lcov-report/package/utilities.js.html +19 -19
- package/coverage/lcov.info +1193 -1178
- package/model/DataModel.js +1 -1
- package/model/DatabaseModel.js +1 -1
- package/model/FileAdapter.js +1 -1
- package/model/FileModel.js +1 -1
- package/model/datastructures/BinarySearchTree.js +1 -1
- package/model/datastructures/BinarySearchTreeHashMap.js +1 -1
- package/package.json +2 -4
- package/public/scripts.min.js +2 -2
|
@@ -23,30 +23,30 @@
|
|
|
23
23
|
<div class='clearfix'>
|
|
24
24
|
|
|
25
25
|
<div class='fl pad1y space-right2'>
|
|
26
|
-
<span class="strong">
|
|
26
|
+
<span class="strong">74.1% </span>
|
|
27
27
|
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>
|
|
28
|
+
<span class='fraction'>289/390</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
<div class='fl pad1y space-right2'>
|
|
33
|
-
<span class="strong">
|
|
33
|
+
<span class="strong">58.56% </span>
|
|
34
34
|
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>
|
|
35
|
+
<span class='fraction'>106/181</span>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
<div class='fl pad1y space-right2'>
|
|
40
|
-
<span class="strong">
|
|
40
|
+
<span class="strong">88% </span>
|
|
41
41
|
<span class="quiet">Functions</span>
|
|
42
|
-
<span class='fraction'>
|
|
42
|
+
<span class='fraction'>44/50</span>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
<div class='fl pad1y space-right2'>
|
|
47
|
-
<span class="strong">
|
|
47
|
+
<span class="strong">74.86% </span>
|
|
48
48
|
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>
|
|
49
|
+
<span class='fraction'>277/370</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -913,7 +913,20 @@
|
|
|
913
913
|
<a name='L848'></a><a href='#L848'>848</a>
|
|
914
914
|
<a name='L849'></a><a href='#L849'>849</a>
|
|
915
915
|
<a name='L850'></a><a href='#L850'>850</a>
|
|
916
|
-
<a name='L851'></a><a href='#L851'>851</a
|
|
916
|
+
<a name='L851'></a><a href='#L851'>851</a>
|
|
917
|
+
<a name='L852'></a><a href='#L852'>852</a>
|
|
918
|
+
<a name='L853'></a><a href='#L853'>853</a>
|
|
919
|
+
<a name='L854'></a><a href='#L854'>854</a>
|
|
920
|
+
<a name='L855'></a><a href='#L855'>855</a>
|
|
921
|
+
<a name='L856'></a><a href='#L856'>856</a>
|
|
922
|
+
<a name='L857'></a><a href='#L857'>857</a>
|
|
923
|
+
<a name='L858'></a><a href='#L858'>858</a>
|
|
924
|
+
<a name='L859'></a><a href='#L859'>859</a>
|
|
925
|
+
<a name='L860'></a><a href='#L860'>860</a>
|
|
926
|
+
<a name='L861'></a><a href='#L861'>861</a>
|
|
927
|
+
<a name='L862'></a><a href='#L862'>862</a>
|
|
928
|
+
<a name='L863'></a><a href='#L863'>863</a>
|
|
929
|
+
<a name='L864'></a><a href='#L864'>864</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
|
917
930
|
<span class="cline-any cline-neutral"> </span>
|
|
918
931
|
<span class="cline-any cline-neutral"> </span>
|
|
919
932
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -938,11 +951,12 @@
|
|
|
938
951
|
<span class="cline-any cline-neutral"> </span>
|
|
939
952
|
<span class="cline-any cline-neutral"> </span>
|
|
940
953
|
<span class="cline-any cline-neutral"> </span>
|
|
941
|
-
<span class="cline-any cline-
|
|
954
|
+
<span class="cline-any cline-neutral"> </span>
|
|
955
|
+
<span class="cline-any cline-yes">5x</span>
|
|
942
956
|
<span class="cline-any cline-neutral"> </span>
|
|
943
957
|
<span class="cline-any cline-neutral"> </span>
|
|
944
958
|
<span class="cline-any cline-neutral"> </span>
|
|
945
|
-
<span class="cline-any cline-yes">
|
|
959
|
+
<span class="cline-any cline-yes">31x</span>
|
|
946
960
|
<span class="cline-any cline-neutral"> </span>
|
|
947
961
|
<span class="cline-any cline-neutral"> </span>
|
|
948
962
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -950,26 +964,26 @@
|
|
|
950
964
|
<span class="cline-any cline-neutral"> </span>
|
|
951
965
|
<span class="cline-any cline-neutral"> </span>
|
|
952
966
|
<span class="cline-any cline-neutral"> </span>
|
|
953
|
-
<span class="cline-any cline-yes">
|
|
967
|
+
<span class="cline-any cline-yes">31x</span>
|
|
954
968
|
<span class="cline-any cline-neutral"> </span>
|
|
955
969
|
<span class="cline-any cline-neutral"> </span>
|
|
956
970
|
<span class="cline-any cline-neutral"> </span>
|
|
957
971
|
<span class="cline-any cline-neutral"> </span>
|
|
958
972
|
<span class="cline-any cline-neutral"> </span>
|
|
959
973
|
<span class="cline-any cline-neutral"> </span>
|
|
960
|
-
<span class="cline-any cline-yes">
|
|
961
|
-
<span class="cline-any cline-yes">
|
|
962
|
-
<span class="cline-any cline-yes">
|
|
963
|
-
<span class="cline-any cline-yes">
|
|
964
|
-
<span class="cline-any cline-yes">
|
|
974
|
+
<span class="cline-any cline-yes">31x</span>
|
|
975
|
+
<span class="cline-any cline-yes">31x</span>
|
|
976
|
+
<span class="cline-any cline-yes">31x</span>
|
|
977
|
+
<span class="cline-any cline-yes">31x</span>
|
|
978
|
+
<span class="cline-any cline-yes">31x</span>
|
|
965
979
|
<span class="cline-any cline-neutral"> </span>
|
|
966
|
-
<span class="cline-any cline-yes">
|
|
980
|
+
<span class="cline-any cline-yes">31x</span>
|
|
967
981
|
<span class="cline-any cline-neutral"> </span>
|
|
968
|
-
<span class="cline-any cline-yes">
|
|
969
|
-
<span class="cline-any cline-yes">
|
|
982
|
+
<span class="cline-any cline-yes">31x</span>
|
|
983
|
+
<span class="cline-any cline-yes">31x</span>
|
|
970
984
|
<span class="cline-any cline-neutral"> </span>
|
|
971
|
-
<span class="cline-any cline-yes">
|
|
972
|
-
<span class="cline-any cline-yes">
|
|
985
|
+
<span class="cline-any cline-yes">31x</span>
|
|
986
|
+
<span class="cline-any cline-yes">31x</span>
|
|
973
987
|
<span class="cline-any cline-neutral"> </span>
|
|
974
988
|
<span class="cline-any cline-neutral"> </span>
|
|
975
989
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -998,20 +1012,20 @@
|
|
|
998
1012
|
<span class="cline-any cline-neutral"> </span>
|
|
999
1013
|
<span class="cline-any cline-neutral"> </span>
|
|
1000
1014
|
<span class="cline-any cline-neutral"> </span>
|
|
1001
|
-
<span class="cline-any cline-yes">
|
|
1002
|
-
<span class="cline-any cline-yes">
|
|
1003
|
-
<span class="cline-any cline-yes">
|
|
1015
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1016
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1017
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1004
1018
|
<span class="cline-any cline-neutral"> </span>
|
|
1005
|
-
<span class="cline-any cline-yes">
|
|
1006
|
-
<span class="cline-any cline-yes">
|
|
1007
|
-
<span class="cline-any cline-yes">
|
|
1008
|
-
<span class="cline-any cline-yes">
|
|
1009
|
-
<span class="cline-any cline-yes">
|
|
1010
|
-
<span class="cline-any cline-yes">
|
|
1011
|
-
<span class="cline-any cline-yes">
|
|
1012
|
-
<span class="cline-any cline-yes">
|
|
1013
|
-
<span class="cline-any cline-yes">
|
|
1014
|
-
<span class="cline-any cline-yes">
|
|
1019
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1020
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1021
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1022
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1023
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1024
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1025
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1026
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1027
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1028
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1015
1029
|
<span class="cline-any cline-neutral"> </span>
|
|
1016
1030
|
<span class="cline-any cline-neutral"> </span>
|
|
1017
1031
|
<span class="cline-any cline-yes">6x</span>
|
|
@@ -1026,20 +1040,20 @@
|
|
|
1026
1040
|
<span class="cline-any cline-neutral"> </span>
|
|
1027
1041
|
<span class="cline-any cline-neutral"> </span>
|
|
1028
1042
|
<span class="cline-any cline-neutral"> </span>
|
|
1029
|
-
<span class="cline-any cline-yes">
|
|
1030
|
-
<span class="cline-any cline-yes">
|
|
1043
|
+
<span class="cline-any cline-yes">5x</span>
|
|
1044
|
+
<span class="cline-any cline-yes">5x</span>
|
|
1031
1045
|
<span class="cline-any cline-neutral"> </span>
|
|
1032
1046
|
<span class="cline-any cline-neutral"> </span>
|
|
1033
1047
|
<span class="cline-any cline-neutral"> </span>
|
|
1034
|
-
<span class="cline-any cline-yes">
|
|
1048
|
+
<span class="cline-any cline-yes">5x</span>
|
|
1035
1049
|
<span class="cline-any cline-neutral"> </span>
|
|
1036
1050
|
<span class="cline-any cline-neutral"> </span>
|
|
1037
1051
|
<span class="cline-any cline-neutral"> </span>
|
|
1038
|
-
<span class="cline-any cline-yes">
|
|
1052
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1039
1053
|
<span class="cline-any cline-neutral"> </span>
|
|
1040
1054
|
<span class="cline-any cline-neutral"> </span>
|
|
1041
1055
|
<span class="cline-any cline-neutral"> </span>
|
|
1042
|
-
<span class="cline-any cline-yes">
|
|
1056
|
+
<span class="cline-any cline-yes">3x</span>
|
|
1043
1057
|
<span class="cline-any cline-neutral"> </span>
|
|
1044
1058
|
<span class="cline-any cline-neutral"> </span>
|
|
1045
1059
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1047,13 +1061,13 @@
|
|
|
1047
1061
|
<span class="cline-any cline-neutral"> </span>
|
|
1048
1062
|
<span class="cline-any cline-neutral"> </span>
|
|
1049
1063
|
<span class="cline-any cline-neutral"> </span>
|
|
1050
|
-
<span class="cline-any cline-yes">
|
|
1051
|
-
<span class="cline-any cline-yes">
|
|
1052
|
-
<span class="cline-any cline-yes">
|
|
1053
|
-
<span class="cline-any cline-yes">
|
|
1064
|
+
<span class="cline-any cline-yes">4x</span>
|
|
1065
|
+
<span class="cline-any cline-yes">4x</span>
|
|
1066
|
+
<span class="cline-any cline-yes">4x</span>
|
|
1067
|
+
<span class="cline-any cline-yes">4x</span>
|
|
1054
1068
|
<span class="cline-any cline-neutral"> </span>
|
|
1055
1069
|
<span class="cline-any cline-neutral"> </span>
|
|
1056
|
-
<span class="cline-any cline-yes">
|
|
1070
|
+
<span class="cline-any cline-yes">4x</span>
|
|
1057
1071
|
<span class="cline-any cline-neutral"> </span>
|
|
1058
1072
|
<span class="cline-any cline-neutral"> </span>
|
|
1059
1073
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1061,8 +1075,8 @@
|
|
|
1061
1075
|
<span class="cline-any cline-neutral"> </span>
|
|
1062
1076
|
<span class="cline-any cline-neutral"> </span>
|
|
1063
1077
|
<span class="cline-any cline-neutral"> </span>
|
|
1064
|
-
<span class="cline-any cline-
|
|
1065
|
-
<span class="cline-any cline-
|
|
1078
|
+
<span class="cline-any cline-yes">1x</span>
|
|
1079
|
+
<span class="cline-any cline-yes">1x</span>
|
|
1066
1080
|
<span class="cline-any cline-neutral"> </span>
|
|
1067
1081
|
<span class="cline-any cline-neutral"> </span>
|
|
1068
1082
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1076,7 +1090,7 @@
|
|
|
1076
1090
|
<span class="cline-any cline-neutral"> </span>
|
|
1077
1091
|
<span class="cline-any cline-neutral"> </span>
|
|
1078
1092
|
<span class="cline-any cline-neutral"> </span>
|
|
1079
|
-
<span class="cline-any cline-yes">
|
|
1093
|
+
<span class="cline-any cline-yes">164663x</span>
|
|
1080
1094
|
<span class="cline-any cline-neutral"> </span>
|
|
1081
1095
|
<span class="cline-any cline-neutral"> </span>
|
|
1082
1096
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1134,60 +1148,60 @@
|
|
|
1134
1148
|
<span class="cline-any cline-neutral"> </span>
|
|
1135
1149
|
<span class="cline-any cline-neutral"> </span>
|
|
1136
1150
|
<span class="cline-any cline-neutral"> </span>
|
|
1137
|
-
<span class="cline-any cline-yes">
|
|
1138
|
-
<span class="cline-any cline-yes">
|
|
1151
|
+
<span class="cline-any cline-yes">31x</span>
|
|
1152
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1139
1153
|
<span class="cline-any cline-neutral"> </span>
|
|
1140
1154
|
<span class="cline-any cline-neutral"> </span>
|
|
1141
1155
|
<span class="cline-any cline-neutral"> </span>
|
|
1142
|
-
<span class="cline-any cline-yes">
|
|
1156
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1143
1157
|
<span class="cline-any cline-neutral"> </span>
|
|
1144
|
-
<span class="cline-any cline-yes">
|
|
1158
|
+
<span class="cline-any cline-yes">9x</span>
|
|
1145
1159
|
<span class="cline-any cline-neutral"> </span>
|
|
1146
|
-
<span class="cline-any cline-yes">
|
|
1160
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1147
1161
|
<span class="cline-any cline-neutral"> </span>
|
|
1148
1162
|
<span class="cline-any cline-neutral"> </span>
|
|
1149
1163
|
<span class="cline-any cline-neutral"> </span>
|
|
1150
1164
|
<span class="cline-any cline-neutral"> </span>
|
|
1151
1165
|
<span class="cline-any cline-neutral"> </span>
|
|
1152
|
-
<span class="cline-any cline-yes">
|
|
1153
|
-
<span class="cline-any cline-yes">
|
|
1154
|
-
<span class="cline-any cline-yes">
|
|
1155
|
-
<span class="cline-any cline-yes">
|
|
1166
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1167
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1168
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1169
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1156
1170
|
<span class="cline-any cline-neutral"> </span>
|
|
1157
1171
|
<span class="cline-any cline-neutral"> </span>
|
|
1158
1172
|
<span class="cline-any cline-neutral"> </span>
|
|
1159
1173
|
<span class="cline-any cline-neutral"> </span>
|
|
1160
1174
|
<span class="cline-any cline-neutral"> </span>
|
|
1161
|
-
<span class="cline-any cline-yes">
|
|
1162
|
-
<span class="cline-any cline-yes">
|
|
1175
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1176
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1163
1177
|
<span class="cline-any cline-neutral"> </span>
|
|
1164
|
-
<span class="cline-any cline-yes">
|
|
1178
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1165
1179
|
<span class="cline-any cline-neutral"> </span>
|
|
1166
1180
|
<span class="cline-any cline-neutral"> </span>
|
|
1167
1181
|
<span class="cline-any cline-neutral"> </span>
|
|
1168
|
-
<span class="cline-any cline-yes">
|
|
1182
|
+
<span class="cline-any cline-yes">18x</span>
|
|
1169
1183
|
<span class="cline-any cline-neutral"> </span>
|
|
1170
1184
|
<span class="cline-any cline-neutral"> </span>
|
|
1171
|
-
<span class="cline-any cline-yes">
|
|
1185
|
+
<span class="cline-any cline-yes">18x</span>
|
|
1172
1186
|
<span class="cline-any cline-neutral"> </span>
|
|
1173
|
-
<span class="cline-any cline-yes">
|
|
1187
|
+
<span class="cline-any cline-yes">4x</span>
|
|
1174
1188
|
<span class="cline-any cline-neutral"> </span>
|
|
1175
1189
|
<span class="cline-any cline-neutral"> </span>
|
|
1176
1190
|
<span class="cline-any cline-neutral"> </span>
|
|
1177
|
-
<span class="cline-any cline-yes">
|
|
1191
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1178
1192
|
<span class="cline-any cline-neutral"> </span>
|
|
1179
1193
|
<span class="cline-any cline-neutral"> </span>
|
|
1180
1194
|
<span class="cline-any cline-no"> </span>
|
|
1181
1195
|
<span class="cline-any cline-neutral"> </span>
|
|
1182
1196
|
<span class="cline-any cline-neutral"> </span>
|
|
1183
1197
|
<span class="cline-any cline-neutral"> </span>
|
|
1184
|
-
<span class="cline-any cline-yes">
|
|
1185
|
-
<span class="cline-any cline-yes">
|
|
1198
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1199
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1186
1200
|
<span class="cline-any cline-neutral"> </span>
|
|
1187
1201
|
<span class="cline-any cline-neutral"> </span>
|
|
1188
1202
|
<span class="cline-any cline-neutral"> </span>
|
|
1189
1203
|
<span class="cline-any cline-neutral"> </span>
|
|
1190
|
-
<span class="cline-any cline-yes">
|
|
1204
|
+
<span class="cline-any cline-yes">22x</span>
|
|
1191
1205
|
<span class="cline-any cline-yes">4x</span>
|
|
1192
1206
|
<span class="cline-any cline-yes">4x</span>
|
|
1193
1207
|
<span class="cline-any cline-yes">4x</span>
|
|
@@ -1205,40 +1219,40 @@
|
|
|
1205
1219
|
<span class="cline-any cline-neutral"> </span>
|
|
1206
1220
|
<span class="cline-any cline-neutral"> </span>
|
|
1207
1221
|
<span class="cline-any cline-neutral"> </span>
|
|
1208
|
-
<span class="cline-any cline-yes">
|
|
1209
|
-
<span class="cline-any cline-yes">
|
|
1210
|
-
<span class="cline-any cline-yes">
|
|
1211
|
-
<span class="cline-any cline-yes">
|
|
1222
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1223
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1224
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1225
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1212
1226
|
<span class="cline-any cline-neutral"> </span>
|
|
1213
|
-
<span class="cline-any cline-yes">
|
|
1214
|
-
<span class="cline-any cline-yes">
|
|
1215
|
-
<span class="cline-any cline-yes">
|
|
1227
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1228
|
+
<span class="cline-any cline-yes">2x</span>
|
|
1229
|
+
<span class="cline-any cline-yes">2x</span>
|
|
1216
1230
|
<span class="cline-any cline-neutral"> </span>
|
|
1217
|
-
<span class="cline-any cline-yes">
|
|
1218
|
-
<span class="cline-any cline-yes">
|
|
1219
|
-
<span class="cline-any cline-yes">
|
|
1220
|
-
<span class="cline-any cline-yes">
|
|
1221
|
-
<span class="cline-any cline-yes">
|
|
1231
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1232
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1233
|
+
<span class="cline-any cline-yes">19x</span>
|
|
1234
|
+
<span class="cline-any cline-yes">19x</span>
|
|
1235
|
+
<span class="cline-any cline-yes">19x</span>
|
|
1222
1236
|
<span class="cline-any cline-neutral"> </span>
|
|
1223
1237
|
<span class="cline-any cline-neutral"> </span>
|
|
1224
|
-
<span class="cline-any cline-yes">
|
|
1225
|
-
<span class="cline-any cline-yes">
|
|
1226
|
-
<span class="cline-any cline-yes">
|
|
1227
|
-
<span class="cline-any cline-yes">
|
|
1238
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1239
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1240
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1241
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1228
1242
|
<span class="cline-any cline-neutral"> </span>
|
|
1229
1243
|
<span class="cline-any cline-neutral"> </span>
|
|
1230
1244
|
<span class="cline-any cline-neutral"> </span>
|
|
1231
1245
|
<span class="cline-any cline-neutral"> </span>
|
|
1232
|
-
<span class="cline-any cline-yes">
|
|
1246
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1233
1247
|
<span class="cline-any cline-neutral"> </span>
|
|
1234
1248
|
<span class="cline-any cline-neutral"> </span>
|
|
1235
|
-
<span class="cline-any cline-yes">
|
|
1249
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1236
1250
|
<span class="cline-any cline-neutral"> </span>
|
|
1237
1251
|
<span class="cline-any cline-neutral"> </span>
|
|
1238
1252
|
<span class="cline-any cline-neutral"> </span>
|
|
1239
1253
|
<span class="cline-any cline-neutral"> </span>
|
|
1240
|
-
<span class="cline-any cline-yes">
|
|
1241
|
-
<span class="cline-any cline-yes">
|
|
1254
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1255
|
+
<span class="cline-any cline-yes">4x</span>
|
|
1242
1256
|
<span class="cline-any cline-neutral"> </span>
|
|
1243
1257
|
<span class="cline-any cline-neutral"> </span>
|
|
1244
1258
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1246,7 +1260,7 @@
|
|
|
1246
1260
|
<span class="cline-any cline-neutral"> </span>
|
|
1247
1261
|
<span class="cline-any cline-neutral"> </span>
|
|
1248
1262
|
<span class="cline-any cline-neutral"> </span>
|
|
1249
|
-
<span class="cline-any cline-yes">
|
|
1263
|
+
<span class="cline-any cline-yes">4x</span>
|
|
1250
1264
|
<span class="cline-any cline-neutral"> </span>
|
|
1251
1265
|
<span class="cline-any cline-neutral"> </span>
|
|
1252
1266
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1255,17 +1269,17 @@
|
|
|
1255
1269
|
<span class="cline-any cline-neutral"> </span>
|
|
1256
1270
|
<span class="cline-any cline-neutral"> </span>
|
|
1257
1271
|
<span class="cline-any cline-neutral"> </span>
|
|
1258
|
-
<span class="cline-any cline-yes">
|
|
1272
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1259
1273
|
<span class="cline-any cline-no"> </span>
|
|
1260
|
-
<span class="cline-any cline-yes">
|
|
1261
|
-
<span class="cline-any cline-yes">
|
|
1262
|
-
<span class="cline-any cline-yes">
|
|
1263
|
-
<span class="cline-any cline-yes">
|
|
1264
|
-
<span class="cline-any cline-yes">
|
|
1265
|
-
<span class="cline-any cline-yes">
|
|
1274
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1275
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1276
|
+
<span class="cline-any cline-yes">10x</span>
|
|
1277
|
+
<span class="cline-any cline-yes">13x</span>
|
|
1278
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1279
|
+
<span class="cline-any cline-yes">23x</span>
|
|
1266
1280
|
<span class="cline-any cline-neutral"> </span>
|
|
1267
1281
|
<span class="cline-any cline-neutral"> </span>
|
|
1268
|
-
<span class="cline-any cline-yes">
|
|
1282
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1269
1283
|
<span class="cline-any cline-neutral"> </span>
|
|
1270
1284
|
<span class="cline-any cline-neutral"> </span>
|
|
1271
1285
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1309,14 +1323,14 @@
|
|
|
1309
1323
|
<span class="cline-any cline-neutral"> </span>
|
|
1310
1324
|
<span class="cline-any cline-neutral"> </span>
|
|
1311
1325
|
<span class="cline-any cline-neutral"> </span>
|
|
1312
|
-
<span class="cline-any cline-yes">
|
|
1326
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1313
1327
|
<span class="cline-any cline-neutral"> </span>
|
|
1314
|
-
<span class="cline-any cline-yes">
|
|
1328
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1315
1329
|
<span class="cline-any cline-neutral"> </span>
|
|
1316
1330
|
<span class="cline-any cline-neutral"> </span>
|
|
1331
|
+
<span class="cline-any cline-yes">11x</span>
|
|
1332
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1317
1333
|
<span class="cline-any cline-yes">8x</span>
|
|
1318
|
-
<span class="cline-any cline-yes">5x</span>
|
|
1319
|
-
<span class="cline-any cline-yes">5x</span>
|
|
1320
1334
|
<span class="cline-any cline-neutral"> </span>
|
|
1321
1335
|
<span class="cline-any cline-neutral"> </span>
|
|
1322
1336
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1426,28 +1440,28 @@
|
|
|
1426
1440
|
<span class="cline-any cline-neutral"> </span>
|
|
1427
1441
|
<span class="cline-any cline-neutral"> </span>
|
|
1428
1442
|
<span class="cline-any cline-neutral"> </span>
|
|
1429
|
-
<span class="cline-any cline-yes">
|
|
1443
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1430
1444
|
<span class="cline-any cline-neutral"> </span>
|
|
1431
|
-
<span class="cline-any cline-yes">
|
|
1432
|
-
<span class="cline-any cline-yes">
|
|
1433
|
-
<span class="cline-any cline-yes">
|
|
1434
|
-
<span class="cline-any cline-yes">
|
|
1445
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1446
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1447
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1448
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1435
1449
|
<span class="cline-any cline-neutral"> </span>
|
|
1436
|
-
<span class="cline-any cline-yes">
|
|
1437
|
-
<span class="cline-any cline-yes">
|
|
1438
|
-
<span class="cline-any cline-yes">
|
|
1450
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1451
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1452
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1439
1453
|
<span class="cline-any cline-neutral"> </span>
|
|
1440
1454
|
<span class="cline-any cline-neutral"> </span>
|
|
1441
1455
|
<span class="cline-any cline-neutral"> </span>
|
|
1442
1456
|
<span class="cline-any cline-neutral"> </span>
|
|
1443
1457
|
<span class="cline-any cline-neutral"> </span>
|
|
1444
|
-
<span class="cline-any cline-yes">
|
|
1445
|
-
<span class="cline-any cline-yes">
|
|
1458
|
+
<span class="cline-any cline-yes">11x</span>
|
|
1459
|
+
<span class="cline-any cline-yes">11x</span>
|
|
1446
1460
|
<span class="cline-any cline-neutral"> </span>
|
|
1447
|
-
<span class="cline-any cline-yes">
|
|
1448
|
-
<span class="cline-any cline-yes">
|
|
1449
|
-
<span class="cline-any cline-yes">
|
|
1450
|
-
<span class="cline-any cline-yes">
|
|
1461
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1462
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1463
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1464
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1451
1465
|
<span class="cline-any cline-neutral"> </span>
|
|
1452
1466
|
<span class="cline-any cline-neutral"> </span>
|
|
1453
1467
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1458,56 +1472,69 @@
|
|
|
1458
1472
|
<span class="cline-any cline-neutral"> </span>
|
|
1459
1473
|
<span class="cline-any cline-neutral"> </span>
|
|
1460
1474
|
<span class="cline-any cline-neutral"> </span>
|
|
1461
|
-
<span class="cline-any cline-yes">
|
|
1462
|
-
<span class="cline-any cline-yes">
|
|
1463
|
-
<span class="cline-any cline-yes">
|
|
1475
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1476
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1477
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1464
1478
|
<span class="cline-any cline-neutral"> </span>
|
|
1465
1479
|
<span class="cline-any cline-neutral"> </span>
|
|
1466
1480
|
<span class="cline-any cline-neutral"> </span>
|
|
1467
|
-
<span class="cline-any cline-yes">
|
|
1481
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1468
1482
|
<span class="cline-any cline-neutral"> </span>
|
|
1469
|
-
<span class="cline-any cline-yes">
|
|
1470
|
-
<span class="cline-any cline-yes">
|
|
1471
|
-
<span class="cline-any cline-yes">
|
|
1472
|
-
<span class="cline-any cline-yes">
|
|
1473
|
-
<span class="cline-any cline-yes">
|
|
1474
|
-
<span class="cline-any cline-yes">
|
|
1483
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1484
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1485
|
+
<span class="cline-any cline-yes">24x</span>
|
|
1486
|
+
<span class="cline-any cline-yes">24x</span>
|
|
1487
|
+
<span class="cline-any cline-yes">311088x</span>
|
|
1488
|
+
<span class="cline-any cline-yes">155532x</span>
|
|
1489
|
+
<span class="cline-any cline-yes">155532x</span>
|
|
1490
|
+
<span class="cline-any cline-yes">155532x</span>
|
|
1475
1491
|
<span class="cline-any cline-neutral"> </span>
|
|
1476
1492
|
<span class="cline-any cline-neutral"> </span>
|
|
1477
1493
|
<span class="cline-any cline-neutral"> </span>
|
|
1478
1494
|
<span class="cline-any cline-neutral"> </span>
|
|
1479
1495
|
<span class="cline-any cline-neutral"> </span>
|
|
1480
|
-
<span class="cline-any cline-yes">
|
|
1481
|
-
<span class="cline-any cline-yes">
|
|
1482
|
-
<span class="cline-any cline-yes">
|
|
1496
|
+
<span class="cline-any cline-yes">155532x</span>
|
|
1497
|
+
<span class="cline-any cline-yes">155532x</span>
|
|
1498
|
+
<span class="cline-any cline-yes">155532x</span>
|
|
1483
1499
|
<span class="cline-any cline-neutral"> </span>
|
|
1484
|
-
<span class="cline-any cline-yes">
|
|
1500
|
+
<span class="cline-any cline-yes">24x</span>
|
|
1485
1501
|
<span class="cline-any cline-neutral"> </span>
|
|
1502
|
+
<span class="cline-any cline-yes">1x</span>
|
|
1503
|
+
<span class="cline-any cline-yes">9118x</span>
|
|
1486
1504
|
<span class="cline-any cline-neutral"> </span>
|
|
1487
1505
|
<span class="cline-any cline-neutral"> </span>
|
|
1488
1506
|
<span class="cline-any cline-neutral"> </span>
|
|
1489
|
-
<span class="cline-any cline-yes">1x</span>
|
|
1490
|
-
<span class="cline-any cline-yes">1x</span>
|
|
1491
|
-
<span class="cline-any cline-yes">1x</span>
|
|
1492
1507
|
<span class="cline-any cline-neutral"> </span>
|
|
1493
1508
|
<span class="cline-any cline-neutral"> </span>
|
|
1509
|
+
<span class="cline-any cline-yes">9118x</span>
|
|
1494
1510
|
<span class="cline-any cline-neutral"> </span>
|
|
1495
1511
|
<span class="cline-any cline-neutral"> </span>
|
|
1496
1512
|
<span class="cline-any cline-neutral"> </span>
|
|
1497
1513
|
<span class="cline-any cline-neutral"> </span>
|
|
1498
|
-
<span class="cline-any cline-yes">5x</span>
|
|
1499
|
-
<span class="cline-any cline-yes">5x</span>
|
|
1500
1514
|
<span class="cline-any cline-neutral"> </span>
|
|
1501
|
-
<span class="cline-any cline-
|
|
1502
|
-
<span class="cline-any cline-yes">
|
|
1515
|
+
<span class="cline-any cline-neutral"> </span>
|
|
1516
|
+
<span class="cline-any cline-yes">2x</span>
|
|
1503
1517
|
<span class="cline-any cline-yes">2x</span>
|
|
1504
1518
|
<span class="cline-any cline-yes">2x</span>
|
|
1505
1519
|
<span class="cline-any cline-neutral"> </span>
|
|
1506
1520
|
<span class="cline-any cline-neutral"> </span>
|
|
1507
|
-
<span class="cline-any cline-yes">2x</span>
|
|
1508
1521
|
<span class="cline-any cline-neutral"> </span>
|
|
1509
1522
|
<span class="cline-any cline-neutral"> </span>
|
|
1510
|
-
<span class="cline-any cline-
|
|
1523
|
+
<span class="cline-any cline-neutral"> </span>
|
|
1524
|
+
<span class="cline-any cline-neutral"> </span>
|
|
1525
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1526
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1527
|
+
<span class="cline-any cline-neutral"> </span>
|
|
1528
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1529
|
+
<span class="cline-any cline-yes">6x</span>
|
|
1530
|
+
<span class="cline-any cline-yes">5x</span>
|
|
1531
|
+
<span class="cline-any cline-yes">5x</span>
|
|
1532
|
+
<span class="cline-any cline-neutral"> </span>
|
|
1533
|
+
<span class="cline-any cline-neutral"> </span>
|
|
1534
|
+
<span class="cline-any cline-yes">5x</span>
|
|
1535
|
+
<span class="cline-any cline-neutral"> </span>
|
|
1536
|
+
<span class="cline-any cline-neutral"> </span>
|
|
1537
|
+
<span class="cline-any cline-yes">6x</span>
|
|
1511
1538
|
<span class="cline-any cline-no"> </span>
|
|
1512
1539
|
<span class="cline-any cline-no"> </span>
|
|
1513
1540
|
<span class="cline-any cline-no"> </span>
|
|
@@ -1515,7 +1542,7 @@
|
|
|
1515
1542
|
<span class="cline-any cline-no"> </span>
|
|
1516
1543
|
<span class="cline-any cline-neutral"> </span>
|
|
1517
1544
|
<span class="cline-any cline-neutral"> </span>
|
|
1518
|
-
<span class="cline-any cline-yes">
|
|
1545
|
+
<span class="cline-any cline-yes">6x</span>
|
|
1519
1546
|
<span class="cline-any cline-neutral"> </span>
|
|
1520
1547
|
<span class="cline-any cline-yes">1x</span>
|
|
1521
1548
|
<span class="cline-any cline-yes">1x</span>
|
|
@@ -1596,8 +1623,8 @@
|
|
|
1596
1623
|
<span class="cline-any cline-neutral"> </span>
|
|
1597
1624
|
<span class="cline-any cline-neutral"> </span>
|
|
1598
1625
|
<span class="cline-any cline-neutral"> </span>
|
|
1599
|
-
<span class="cline-any cline-yes">
|
|
1600
|
-
<span class="cline-any cline-yes">
|
|
1626
|
+
<span class="cline-any cline-yes">2x</span>
|
|
1627
|
+
<span class="cline-any cline-yes">2x</span>
|
|
1601
1628
|
<span class="cline-any cline-neutral"> </span>
|
|
1602
1629
|
<span class="cline-any cline-neutral"> </span>
|
|
1603
1630
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1642,22 +1669,22 @@
|
|
|
1642
1669
|
<span class="cline-any cline-neutral"> </span>
|
|
1643
1670
|
<span class="cline-any cline-neutral"> </span>
|
|
1644
1671
|
<span class="cline-any cline-neutral"> </span>
|
|
1645
|
-
<span class="cline-any cline-yes">
|
|
1672
|
+
<span class="cline-any cline-yes">9x</span>
|
|
1646
1673
|
<span class="cline-any cline-neutral"> </span>
|
|
1647
1674
|
<span class="cline-any cline-neutral"> </span>
|
|
1648
1675
|
<span class="cline-any cline-neutral"> </span>
|
|
1649
1676
|
<span class="cline-any cline-neutral"> </span>
|
|
1650
|
-
<span class="cline-any cline-yes">
|
|
1651
|
-
<span class="cline-any cline-yes">
|
|
1677
|
+
<span class="cline-any cline-yes">9x</span>
|
|
1678
|
+
<span class="cline-any cline-yes">9x</span>
|
|
1652
1679
|
<span class="cline-any cline-neutral"> </span>
|
|
1653
|
-
<span class="cline-any cline-yes">
|
|
1680
|
+
<span class="cline-any cline-yes">8x</span>
|
|
1654
1681
|
<span class="cline-any cline-neutral"> </span>
|
|
1655
1682
|
<span class="cline-any cline-neutral"> </span>
|
|
1656
1683
|
<span class="cline-any cline-neutral"> </span>
|
|
1657
1684
|
<span class="cline-any cline-neutral"> </span>
|
|
1658
1685
|
<span class="cline-any cline-neutral"> </span>
|
|
1659
1686
|
<span class="cline-any cline-neutral"> </span>
|
|
1660
|
-
<span class="cline-any cline-yes">
|
|
1687
|
+
<span class="cline-any cline-yes">9x</span>
|
|
1661
1688
|
<span class="cline-any cline-neutral"> </span>
|
|
1662
1689
|
<span class="cline-any cline-yes">2x</span>
|
|
1663
1690
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1707,47 +1734,47 @@
|
|
|
1707
1734
|
<span class="cline-any cline-neutral"> </span>
|
|
1708
1735
|
<span class="cline-any cline-neutral"> </span>
|
|
1709
1736
|
<span class="cline-any cline-neutral"> </span>
|
|
1710
|
-
<span class="cline-any cline-yes">
|
|
1711
|
-
<span class="cline-any cline-yes">
|
|
1737
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1738
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1712
1739
|
<span class="cline-any cline-neutral"> </span>
|
|
1713
|
-
<span class="cline-any cline-yes">
|
|
1740
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1714
1741
|
<span class="cline-any cline-neutral"> </span>
|
|
1715
1742
|
<span class="cline-any cline-neutral"> </span>
|
|
1716
|
-
<span class="cline-any cline-yes">
|
|
1717
|
-
<span class="cline-any cline-yes">
|
|
1743
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1744
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1718
1745
|
<span class="cline-any cline-neutral"> </span>
|
|
1719
|
-
<span class="cline-any cline-yes">
|
|
1720
|
-
<span class="cline-any cline-yes">
|
|
1721
|
-
<span class="cline-any cline-yes">
|
|
1746
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1747
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1748
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1722
1749
|
<span class="cline-any cline-neutral"> </span>
|
|
1723
1750
|
<span class="cline-any cline-neutral"> </span>
|
|
1724
1751
|
<span class="cline-any cline-neutral"> </span>
|
|
1725
|
-
<span class="cline-any cline-yes">
|
|
1752
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1726
1753
|
<span class="cline-any cline-neutral"> </span>
|
|
1727
1754
|
<span class="cline-any cline-neutral"> </span>
|
|
1728
1755
|
<span class="cline-any cline-neutral"> </span>
|
|
1729
1756
|
<span class="cline-any cline-neutral"> </span>
|
|
1730
|
-
<span class="cline-any cline-yes">
|
|
1757
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1731
1758
|
<span class="cline-any cline-neutral"> </span>
|
|
1732
1759
|
<span class="cline-any cline-neutral"> </span>
|
|
1733
1760
|
<span class="cline-any cline-neutral"> </span>
|
|
1734
1761
|
<span class="cline-any cline-neutral"> </span>
|
|
1735
1762
|
<span class="cline-any cline-neutral"> </span>
|
|
1736
|
-
<span class="cline-any cline-yes">
|
|
1737
|
-
<span class="cline-any cline-yes">
|
|
1738
|
-
<span class="cline-any cline-yes">
|
|
1739
|
-
<span class="cline-any cline-yes">
|
|
1763
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1764
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1765
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1766
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1740
1767
|
<span class="cline-any cline-neutral"> </span>
|
|
1741
1768
|
<span class="cline-any cline-neutral"> </span>
|
|
1742
1769
|
<span class="cline-any cline-neutral"> </span>
|
|
1743
|
-
<span class="cline-any cline-yes">
|
|
1744
|
-
<span class="cline-any cline-yes">
|
|
1770
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1771
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1745
1772
|
<span class="cline-any cline-neutral"> </span>
|
|
1746
1773
|
<span class="cline-any cline-neutral"> </span>
|
|
1747
1774
|
<span class="cline-any cline-neutral"> </span>
|
|
1748
1775
|
<span class="cline-any cline-neutral"> </span>
|
|
1749
1776
|
<span class="cline-any cline-neutral"> </span>
|
|
1750
|
-
<span class="cline-any cline-yes">
|
|
1777
|
+
<span class="cline-any cline-yes">25x</span>
|
|
1751
1778
|
<span class="cline-any cline-no"> </span>
|
|
1752
1779
|
<span class="cline-any cline-no"> </span>
|
|
1753
1780
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -1762,7 +1789,6 @@
|
|
|
1762
1789
|
<span class="cline-any cline-neutral"> </span>
|
|
1763
1790
|
<span class="cline-any cline-neutral"> </span>
|
|
1764
1791
|
<span class="cline-any cline-neutral"> </span>
|
|
1765
|
-
<span class="cline-any cline-neutral"> </span>
|
|
1766
1792
|
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import http from "http";
|
|
1767
1793
|
import crypto from "node:crypto";
|
|
1768
1794
|
import fs from "fs";
|
|
@@ -1771,7 +1797,7 @@ import process from "node:process";
|
|
|
1771
1797
|
import path from "path";
|
|
1772
1798
|
import { fileURLToPath } from "url";
|
|
1773
1799
|
import pkg from "./package.json" with { type: "json" };
|
|
1774
|
-
import createDebug from "
|
|
1800
|
+
import { debuglog as createDebug } from "node:util";
|
|
1775
1801
|
import Article from "./Article.js";
|
|
1776
1802
|
import DatabaseModel from "./model/DatabaseModel.js";
|
|
1777
1803
|
import { fetchData, postData } from "./model/APIModel.js";
|
|
@@ -1867,9 +1893,9 @@ export default class Blog {
|
|
|
1867
1893
|
this.#title = title;
|
|
1868
1894
|
}
|
|
1869
1895
|
|
|
1870
|
-
|
|
1871
|
-
<span class="
|
|
1872
|
-
}
|
|
1896
|
+
setPassword(password) {
|
|
1897
|
+
<span class="fstat-no" title="function not covered" ></span> this.#password = password;
|
|
1898
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
1873
1899
|
|
|
1874
1900
|
/**
|
|
1875
1901
|
* Appends CSS rules to the \<style\>-tag.
|
|
@@ -1897,9 +1923,9 @@ export default class Blog {
|
|
|
1897
1923
|
* @param {*} adapter a database adapter like PostgresAdapter or SqliteAdapter
|
|
1898
1924
|
*/
|
|
1899
1925
|
setDatabaseAdapter(adapter) {
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1926
|
+
if (!this.#databaseModel) {
|
|
1927
|
+
<span class="missing-if-branch" title="else path not taken" >E</span> if (this.database.type === "file") {
|
|
1928
|
+
<span class="missing-if-branch" title="else path not taken" >E</span> const adapter = new FileAdapter(this.database);
|
|
1903
1929
|
this.#databaseModel = new DatabaseModel(adapter);
|
|
1904
1930
|
}
|
|
1905
1931
|
}
|
|
@@ -1910,9 +1936,9 @@ export default class Blog {
|
|
|
1910
1936
|
* Appends CSS rules to the \<style\>-tag.
|
|
1911
1937
|
* @param {string} style - A string containing CSS rules.
|
|
1912
1938
|
*/
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1939
|
+
set style(style) {
|
|
1940
|
+
this.#styles += style;
|
|
1941
|
+
this.compilestyle = true;
|
|
1916
1942
|
}
|
|
1917
1943
|
|
|
1918
1944
|
/**
|
|
@@ -1953,10 +1979,10 @@ export default class Blog {
|
|
|
1953
1979
|
Location: "/",
|
|
1954
1980
|
});
|
|
1955
1981
|
res.end();
|
|
1956
|
-
} else
|
|
1957
|
-
<span class="
|
|
1982
|
+
} else {
|
|
1983
|
+
res.w<span class="missing-if-branch" title="else path not taken" >E</span>riteHead(401, { "Content-Type": "text/html" });
|
|
1958
1984
|
<span class="cstat-no" title="statement not covered" > res.end(`${header("My Blog")}</span>
|
|
1959
|
-
<body>
|
|
1985
|
+
<body><span class="cstat-no" title="statement not covered" ></span>
|
|
1960
1986
|
<h1>Unauthorized</h1><div class="box"><p>Please enter the password.<form method="POST">
|
|
1961
1987
|
<input type="password" name="password" placeholder="Password" />
|
|
1962
1988
|
<button style="margin: 2px;">Login</button></form></div>
|
|
@@ -1965,22 +1991,22 @@ export default class Blog {
|
|
|
1965
1991
|
}
|
|
1966
1992
|
|
|
1967
1993
|
#handleLogout(req, res) {
|
|
1968
|
-
|
|
1969
|
-
<span class="cstat-no" title="statement not covered" > if (req.headers.cookie)
|
|
1970
|
-
|
|
1971
|
-
req.headers.
|
|
1994
|
+
debug("handle logout");
|
|
1995
|
+
<span class="cstat-no" title="statement not covered" > if (req.headers.cookie) </span>{
|
|
1996
|
+
<span class="cstat-no" title="statement not covered" > const params = new URLSearchParams(</span>
|
|
1997
|
+
req.headers.c<span class="cstat-no" title="statement not covered" >ookie.replace(/; /g, "&"),</span>
|
|
1972
1998
|
);
|
|
1973
|
-
const sessionId =
|
|
1974
|
-
|
|
1999
|
+
const sessionId = params.get("session");
|
|
2000
|
+
if (this.sessions.<span class="cstat-no" title="statement not covered" >has(sessionId)) {</span>
|
|
1975
2001
|
<span class="cstat-no" title="statement not covered" > this.sessions.delete(sessionId);</span>
|
|
1976
|
-
}
|
|
2002
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
1977
2003
|
}
|
|
1978
|
-
|
|
1979
|
-
"Set-Cookie": "session=; HttpOnly; Path=/; Max-Age=0"
|
|
2004
|
+
res.writeHead(303, {
|
|
2005
|
+
<span class="cstat-no" title="statement not covered" > "Set-Cookie": "session=; HttpOnly; Path=/; Max-Age=0",</span>
|
|
1980
2006
|
Location: "/",
|
|
1981
2007
|
});
|
|
1982
|
-
|
|
1983
|
-
}
|
|
2008
|
+
res.end();
|
|
2009
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
1984
2010
|
|
|
1985
2011
|
/** initializes database */
|
|
1986
2012
|
async init() {
|
|
@@ -2018,17 +2044,17 @@ export default class Blog {
|
|
|
2018
2044
|
const match = publicCSS.match(
|
|
2019
2045
|
/\/\* source-hash: ([a-f0-9]{64}) \*\//,
|
|
2020
2046
|
);
|
|
2021
|
-
|
|
2022
|
-
})
|
|
2047
|
+
if (match) publicHash = match[1];
|
|
2048
|
+
})<span class="missing-if-branch" title="else path not taken" >E</span>
|
|
2023
2049
|
.catch((err) => console.error(err)), // public/styles.min.css doesn't exist, will be created.
|
|
2024
2050
|
fs.promises
|
|
2025
2051
|
.readFile(srcStylePath, "utf8")
|
|
2026
2052
|
.then((content) => {
|
|
2027
2053
|
srcStyles = content;
|
|
2028
2054
|
})
|
|
2029
|
-
.catch(
|
|
2030
|
-
<span class="
|
|
2031
|
-
})
|
|
2055
|
+
.catch((err) => {
|
|
2056
|
+
if (e<span class="fstat-no" title="function not covered" >rr</span>.code !== "ENOENT") console.error(err);
|
|
2057
|
+
})<span class="cstat-no" title="statement not covered" >, // ignore if src/styles.c<span class="cstat-no" title="statement not covered" >ss doesn't exist</span></span>
|
|
2032
2058
|
]);
|
|
2033
2059
|
|
|
2034
2060
|
const combinedStyles = this.#styles + srcStyles;
|
|
@@ -2049,8 +2075,8 @@ export default class Blog {
|
|
|
2049
2075
|
finalStyles + `\n/* source-hash: ${srcHash} */`,
|
|
2050
2076
|
);
|
|
2051
2077
|
} catch (err) {
|
|
2052
|
-
|
|
2053
|
-
}
|
|
2078
|
+
console.error("Failed to write styles to public folder:", err);
|
|
2079
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2054
2080
|
}
|
|
2055
2081
|
}
|
|
2056
2082
|
|
|
@@ -2066,8 +2092,8 @@ export default class Blog {
|
|
|
2066
2092
|
} else {
|
|
2067
2093
|
console.log(`database: ${this.database.type}`);
|
|
2068
2094
|
if (!this.#databaseModel) {
|
|
2069
|
-
|
|
2070
|
-
|
|
2095
|
+
if (this.database.type === "file") {
|
|
2096
|
+
<span class="missing-if-branch" title="else path not taken" >E</span> const adapter = new FileAdapter(this.database);
|
|
2071
2097
|
this.#databaseModel = new DatabaseModel(adapter);
|
|
2072
2098
|
}
|
|
2073
2099
|
}
|
|
@@ -2105,9 +2131,9 @@ export default class Blog {
|
|
|
2105
2131
|
),
|
|
2106
2132
|
);
|
|
2107
2133
|
}
|
|
2108
|
-
|
|
2109
|
-
<span class="
|
|
2110
|
-
|
|
2134
|
+
if (this.reloadStylesOnGET)
|
|
2135
|
+
<span class="missing-if-branch" title="if path not taken" >I</span> console.log("reload scripts and styles on GET-Request");
|
|
2136
|
+
le<span class="cstat-no" title="statement not covered" >t title = "";</span>
|
|
2111
2137
|
if (this.#title != null && this.#title.length > 0)
|
|
2112
2138
|
title = this.#title; // use blog title if set
|
|
2113
2139
|
else title = dbTitle; // use title from the database
|
|
@@ -2132,8 +2158,8 @@ export default class Blog {
|
|
|
2132
2158
|
const title = params.get("title");
|
|
2133
2159
|
const content = params.get("content");
|
|
2134
2160
|
|
|
2135
|
-
|
|
2136
|
-
|
|
2161
|
+
if (title && content) {
|
|
2162
|
+
<span class="missing-if-branch" title="else path not taken" >E</span> const newArticleData = { title, content };
|
|
2137
2163
|
try {
|
|
2138
2164
|
// Save the new article to the database via the ApiServer
|
|
2139
2165
|
const promises = [];
|
|
@@ -2148,8 +2174,8 @@ export default class Blog {
|
|
|
2148
2174
|
this.#articles.remove(1); // "Sample Entry #1"
|
|
2149
2175
|
this.#articles.remove(2); // "Sample Entry #2"
|
|
2150
2176
|
} catch (error) {
|
|
2151
|
-
|
|
2152
|
-
}
|
|
2177
|
+
console.error("Failed to post new article to API:", error);
|
|
2178
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2153
2179
|
}
|
|
2154
2180
|
|
|
2155
2181
|
res.writeHead(303, { Location: "/" });
|
|
@@ -2158,8 +2184,8 @@ export default class Blog {
|
|
|
2158
2184
|
}
|
|
2159
2185
|
|
|
2160
2186
|
/** start a http server with default port 8080 */
|
|
2161
|
-
async startServer(port =
|
|
2162
|
-
await this.init()
|
|
2187
|
+
async startServer(port = 8080) {
|
|
2188
|
+
await this.init();<span class="branch-0 cbranch-no" title="branch not covered" ></span>
|
|
2163
2189
|
|
|
2164
2190
|
const server = http.createServer(async (req, res) => {
|
|
2165
2191
|
//debug("query %s", req.url);
|
|
@@ -2171,82 +2197,82 @@ export default class Blog {
|
|
|
2171
2197
|
|
|
2172
2198
|
// Web Page Routes
|
|
2173
2199
|
if (req.url === "/login") {
|
|
2174
|
-
|
|
2175
|
-
<span class="
|
|
2200
|
+
if (req.method === "GET") {
|
|
2201
|
+
<span class="missing-if-branch" title="if path not taken" >I</span> res.writeHead(200, { "Content-Type": "text/html" });
|
|
2176
2202
|
<span class="cstat-no" title="statement not covered" > res.end(`${header("My Blog")}</span>
|
|
2177
|
-
<body>
|
|
2203
|
+
<body><span class="cstat-no" title="statement not covered" ></span>
|
|
2178
2204
|
<h1>Login</h1><div class="box"><form method="POST">
|
|
2179
2205
|
<input type="password" name="password" placeholder="Password" />
|
|
2180
2206
|
<button style="margin: 2px;">Login</button></form></div>
|
|
2181
2207
|
</body></html>`);
|
|
2182
|
-
|
|
2183
|
-
}
|
|
2184
|
-
await this.#handleLogin(req, res);
|
|
2208
|
+
return;
|
|
2209
|
+
} <span class="cstat-no" title="statement not covered" >else if </span>(req.method === "POST") {
|
|
2210
|
+
await<span class="missing-if-branch" title="else path not taken" >E</span> this.#handleLogin(req, res);
|
|
2185
2211
|
return;
|
|
2186
2212
|
}
|
|
2187
2213
|
}
|
|
2188
2214
|
|
|
2189
|
-
|
|
2190
|
-
<span class="
|
|
2215
|
+
if (req.url === "/logout") {
|
|
2216
|
+
<span class="missing-if-branch" title="if path not taken" >I</span> this.#handleLogout(req, res);
|
|
2191
2217
|
<span class="cstat-no" title="statement not covered" > return;</span>
|
|
2192
|
-
}
|
|
2218
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2193
2219
|
// POST new article
|
|
2194
|
-
|
|
2195
|
-
<span class="
|
|
2220
|
+
if (req.method === "POST" && req.url === "/") {
|
|
2221
|
+
<span class="missing-if-branch" title="if path not taken" >I</span> if (!this.#isAuthenticated(<span class="branch-1 cbranch-no" title="branch not covered" >req)) {</span>
|
|
2196
2222
|
<span class="cstat-no" title="statement not covered" > res.writeHead(403, { "Content-Type": "text/plain" });</span>
|
|
2197
2223
|
<span class="cstat-no" title="statement not covered" > res.end("Forbidden");</span>
|
|
2198
2224
|
<span class="cstat-no" title="statement not covered" > return;</span>
|
|
2199
|
-
}
|
|
2200
|
-
|
|
2201
|
-
// GET artciles
|
|
2225
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2226
|
+
await this.postArticle(req, res);
|
|
2227
|
+
<span class="cstat-no" title="statement not covered" > // GET artciles</span>
|
|
2202
2228
|
} else if (req.method === "GET" && req.url === "/") {
|
|
2203
2229
|
// load articles
|
|
2204
2230
|
|
|
2205
2231
|
// reload styles and scripts on (every) request
|
|
2206
|
-
|
|
2207
|
-
<span class="
|
|
2232
|
+
if (this.reloadStylesOnGET) {
|
|
2233
|
+
<span class="missing-if-branch" title="if path not taken" >I</span> if (this.#stylesheetPath != null && this.compilestyle) {
|
|
2208
2234
|
<span class="cstat-no" title="statement not covered" > await this.#processStylesheets(this.#stylesheetPath);</span>
|
|
2209
|
-
}
|
|
2210
|
-
const __filename =
|
|
2211
|
-
const __dirname = <span class="cstat-no" title="statement not covered" >
|
|
2212
|
-
const
|
|
2213
|
-
<span class="cstat-no" title="statement not covered" >
|
|
2214
|
-
}
|
|
2235
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2236
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
2237
|
+
const __dirname = p<span class="cstat-no" title="statement not covered" >ath.dirname(__filename);</span>
|
|
2238
|
+
const srcScriptPat<span class="cstat-no" title="statement not covered" >h = path.join(__dirname, </span>"src", "fetchData.js");
|
|
2239
|
+
await this.#processScr<span class="cstat-no" title="statement not covered" >ipts(srcScriptPath);</span>
|
|
2240
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2215
2241
|
|
|
2216
2242
|
let loggedin = false;
|
|
2217
2243
|
if (!this.#isAuthenticated(req)) {
|
|
2218
2244
|
// login
|
|
2219
2245
|
loggedin = false;
|
|
2220
|
-
} else
|
|
2221
|
-
//
|
|
2222
|
-
|
|
2223
|
-
}
|
|
2246
|
+
} else {
|
|
2247
|
+
// lo<span class="missing-if-branch" title="else path not taken" >E</span>gout
|
|
2248
|
+
loggedin = true;
|
|
2249
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2224
2250
|
|
|
2225
2251
|
try {
|
|
2226
2252
|
const html = await this.toHTML(loggedin); // render this blog to HTML
|
|
2227
2253
|
res.writeHead(200, { "Content-Type": "text/html; charset=UTF-8" });
|
|
2228
2254
|
res.end(html);
|
|
2229
2255
|
} catch (err) {
|
|
2230
|
-
|
|
2231
|
-
<span class="cstat-no" title="statement not covered" > res.writeHead(500, { "Content-Type": "text/plain" })
|
|
2256
|
+
console.error(err);
|
|
2257
|
+
<span class="cstat-no" title="statement not covered" > res.writeHead(500, {</span> "Content-Type": "text/plain" });
|
|
2232
2258
|
<span class="cstat-no" title="statement not covered" > res.end("Internal Server Error");</span>
|
|
2233
|
-
}
|
|
2234
|
-
} else
|
|
2235
|
-
//
|
|
2236
|
-
|
|
2237
|
-
|
|
2259
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2260
|
+
} else {
|
|
2261
|
+
// Tr<span class="missing-if-branch" title="else path not taken" >E</span>y to serve static files from public folder
|
|
2262
|
+
try {
|
|
2263
|
+
<span class="cstat-no" title="statement not covered" > const publicDir = path.join(process.cwd(), "public");</span>
|
|
2238
2264
|
const parsedUrl = <span class="cstat-no" title="statement not covered" >new URL(</span>
|
|
2239
|
-
req.url
|
|
2265
|
+
req.url,<span class="cstat-no" title="statement not covered" ></span>
|
|
2240
2266
|
`http://${req.headers.host || "localhost"}`,
|
|
2241
2267
|
);
|
|
2242
|
-
const filePath =
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
<span class="cstat-no" title="statement not covered" >
|
|
2247
|
-
|
|
2248
|
-
const
|
|
2249
|
-
".html": "text/
|
|
2268
|
+
const filePath = path.join(publicDir, parsedUrl.pathname);
|
|
2269
|
+
<span class="cstat-no" title="statement not covered" ></span>
|
|
2270
|
+
if (filePath.startsWith(publicDir)) {
|
|
2271
|
+
<span class="cstat-no" title="statement not covered" > const stats = await fs.promises.stat(filePath);</span>
|
|
2272
|
+
if (stats.isFi<span class="cstat-no" title="statement not covered" >le()) {</span>
|
|
2273
|
+
<span class="cstat-no" title="statement not covered" > const ext = path.extname(filePath).toLowerCase();</span>
|
|
2274
|
+
const mimeTy<span class="cstat-no" title="statement not covered" >pes = {</span>
|
|
2275
|
+
".html": "text/h<span class="cstat-no" title="statement not covered" >tml",</span>
|
|
2250
2276
|
".js": "text/javascript",
|
|
2251
2277
|
".css": "text/css",
|
|
2252
2278
|
".json": "application/json",
|
|
@@ -2256,31 +2282,31 @@ export default class Blog {
|
|
|
2256
2282
|
".svg": "image/svg+xml",
|
|
2257
2283
|
".ico": "image/x-icon",
|
|
2258
2284
|
};
|
|
2259
|
-
const contentType =
|
|
2260
|
-
<span class="cstat-no" title="statement not covered" >
|
|
2285
|
+
const contentType = mimeTypes[ext] || "application/octet-stream";
|
|
2286
|
+
res.writeHead(200, {<span class="cstat-no" title="statement not covered" > "Content-Type": contentType });</span>
|
|
2261
2287
|
<span class="cstat-no" title="statement not covered" > fs.createReadStream(filePath).pipe(res);</span>
|
|
2262
2288
|
<span class="cstat-no" title="statement not covered" > return;</span>
|
|
2263
|
-
}
|
|
2289
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2264
2290
|
}
|
|
2265
2291
|
} catch (err) {
|
|
2266
2292
|
// ENOENT (file not found) is expected, leading to a 404.
|
|
2267
2293
|
// Only log other, unexpected errors.
|
|
2268
|
-
|
|
2294
|
+
if (err.code !== "ENOENT") {
|
|
2269
2295
|
<span class="cstat-no" title="statement not covered" > console.error(err);</span>
|
|
2270
|
-
}
|
|
2296
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2271
2297
|
}
|
|
2272
2298
|
|
|
2273
2299
|
// Error 404
|
|
2274
|
-
|
|
2300
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2275
2301
|
<span class="cstat-no" title="statement not covered" > res.end(JSON.stringify({ message: "Not Found" }));</span>
|
|
2276
|
-
}
|
|
2302
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2277
2303
|
});
|
|
2278
2304
|
|
|
2279
2305
|
this.#server = server;
|
|
2280
2306
|
|
|
2281
2307
|
return new Promise((resolve, reject) => {
|
|
2282
|
-
const errorHandler =
|
|
2283
|
-
this.#server.once("
|
|
2308
|
+
const errorHandler = (err) => reject(err);
|
|
2309
|
+
this.#server.once("er<span class="fstat-no" title="function not covered" >ro</span>r", err<span class="cstat-no" title="statement not covered" >orHandler);</span>
|
|
2284
2310
|
this.#server.listen(port, "0.0.0.0", () => {
|
|
2285
2311
|
// <-- for docker 0.0.0.0, localhost 127.0.0.1
|
|
2286
2312
|
this.#server.removeListener("error", errorHandler);
|
|
@@ -2295,8 +2321,8 @@ export default class Blog {
|
|
|
2295
2321
|
if (this.#server) {
|
|
2296
2322
|
// if server is running
|
|
2297
2323
|
this.#server.close((err) => {
|
|
2298
|
-
|
|
2299
|
-
console.log("Server closed.")
|
|
2324
|
+
if (err && err.code !== "ERR_SERVER_NOT_RUNNING") return reject(err);
|
|
2325
|
+
<span class="missing-if-branch" title="if path not taken" >I</span>console.log<span class="branch-1 cbranch-no" title="branch not covered" >("Server closed.");<span class="cstat-no" title="statement not covered" ></span></span>
|
|
2300
2326
|
resolve();
|
|
2301
2327
|
});
|
|
2302
2328
|
} else {
|
|
@@ -2311,42 +2337,55 @@ export default class Blog {
|
|
|
2311
2337
|
debug("applyBlogData");
|
|
2312
2338
|
if (this.#articles.storage.clear) {
|
|
2313
2339
|
this.#articles.storage.clear();
|
|
2314
|
-
} else
|
|
2315
|
-
//
|
|
2340
|
+
} else {
|
|
2341
|
+
//thi<span class="missing-if-branch" title="else path not taken" >E</span>s.#articles.setDataModel(this.#makeDataModel()); // Fallback if clear() isn't implemented
|
|
2316
2342
|
}
|
|
2317
2343
|
this.#title = data.title;
|
|
2318
2344
|
// Assuming data contains a title and an array of articles with title and content
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
const
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
articleData.
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2345
|
+
if (this.#articles && data.articles && Array.isArray(data.articles)) {
|
|
2346
|
+
<span class="missing-if-branch" title="else path not taken" >E</span> if (this.#articles.getStorageName().includes("BinarySearchTree")) {
|
|
2347
|
+
debug("using special insert method for BST");
|
|
2348
|
+
const insertBalanced = (start, end) => {
|
|
2349
|
+
if (start > end) return;
|
|
2350
|
+
const mid = Math.floor((start + end) / 2);
|
|
2351
|
+
const articleData = data.articles[mid];
|
|
2352
|
+
const article = new Article(
|
|
2353
|
+
articleData.id,
|
|
2354
|
+
articleData.title,
|
|
2355
|
+
articleData.content,
|
|
2356
|
+
articleData.createdAt,
|
|
2357
|
+
);
|
|
2358
|
+
this.addArticle(article);
|
|
2359
|
+
insertBalanced(start, mid - 1);
|
|
2360
|
+
insertBalanced(mid + 1, end);
|
|
2361
|
+
};
|
|
2362
|
+
insertBalanced(0, data.articles.length - 1);
|
|
2363
|
+
} else {
|
|
2364
|
+
for (const articleData of data.articles) {
|
|
2365
|
+
const article = new Article(
|
|
2366
|
+
articleData.id,
|
|
2367
|
+
articleData.title,
|
|
2368
|
+
articleData.content,
|
|
2369
|
+
articleData.createdAt,
|
|
2370
|
+
);
|
|
2371
|
+
this.addArticle(article);
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2335
2374
|
}
|
|
2336
2375
|
}
|
|
2337
2376
|
|
|
2338
2377
|
async #loadFromAPI() {
|
|
2339
2378
|
const data = await fetchData(this.#apiUrl);
|
|
2340
|
-
|
|
2341
|
-
|
|
2379
|
+
if (data) {
|
|
2380
|
+
<span class="missing-if-branch" title="else path not taken" >E</span> this.#applyBlogData(data);
|
|
2342
2381
|
}
|
|
2343
2382
|
}
|
|
2344
2383
|
|
|
2345
2384
|
// controller
|
|
2346
2385
|
/** everything that happens in /api */
|
|
2347
2386
|
async #jsonAPI(req, res) {
|
|
2348
|
-
const url = new URL(req.url, `http://${req.headers.host ||
|
|
2349
|
-
const pathname = url.pathname
|
|
2387
|
+
const url = new URL(req.url, `http://${req.headers.host || "localhost"}`);
|
|
2388
|
+
const pathname = url.pathname;<span class="branch-1 cbranch-no" title="branch not covered" ></span>
|
|
2350
2389
|
|
|
2351
2390
|
if (req.method === "GET") {
|
|
2352
2391
|
if (pathname === "/api" || pathname === "/api/") {
|
|
@@ -2357,19 +2396,19 @@ export default class Blog {
|
|
|
2357
2396
|
res.end(JSON.stringify(data));
|
|
2358
2397
|
}
|
|
2359
2398
|
// Search
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
<span class="cstat-no" title="statement not covered" >
|
|
2363
|
-
|
|
2364
|
-
<span class="cstat-no" title="statement not covered" >
|
|
2399
|
+
if (url.searchParams.has("q")) {
|
|
2400
|
+
<span class="missing-if-branch" title="if path not taken" >I</span> const query = url.searchParams.get("q");
|
|
2401
|
+
res.writeHead(<span class="cstat-no" title="statement not covered" >200, { "Content-Type": "ap</span>plication/json" });
|
|
2402
|
+
<span class="cstat-no" title="statement not covered" > const results = this.#articles.search(query);</span>
|
|
2403
|
+
res.end(JSON.str<span class="cstat-no" title="statement not covered" >ingify({ articles: results })</span>);
|
|
2365
2404
|
<span class="cstat-no" title="statement not covered" > return;</span>
|
|
2366
|
-
}
|
|
2405
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2367
2406
|
// GET all blog data
|
|
2368
2407
|
if (pathname === "/api/articles") {
|
|
2369
2408
|
// Use 'offset' param as startId (filter) to get items starting at ID
|
|
2370
2409
|
const pLimit = parseInt(url.searchParams.get("limit"));
|
|
2371
|
-
const limit = !isNaN(pLimit) ?
|
|
2372
|
-
|
|
2410
|
+
const limit = !isNaN(pLimit) ? pLimit : null;
|
|
2411
|
+
<span class="branch-0 cbranch-no" title="branch not covered" ></span>
|
|
2373
2412
|
const start = url.searchParams.get("startdate");
|
|
2374
2413
|
const end = url.searchParams.get("enddate");
|
|
2375
2414
|
//const parsedStart = parseDateParam(qStartdate);
|
|
@@ -2407,41 +2446,41 @@ export default class Blog {
|
|
|
2407
2446
|
// extern
|
|
2408
2447
|
res.writeHead(201, { "Content-Type": "application/json" });
|
|
2409
2448
|
res.end(JSON.stringify(newArticle));
|
|
2410
|
-
} else
|
|
2411
|
-
|
|
2449
|
+
} else if (req.method === "DELETE" && pathname === "/api/articles") {
|
|
2450
|
+
if (!<span class="cstat-no" title="statement not covered" ><span class="missing-if-branch" title="else path not taken" >E</span>this.#isAuthenticated(req)) {</span>
|
|
2412
2451
|
<span class="cstat-no" title="statement not covered" > res.writeHead(403, { "Content-Type": "application/json" });</span>
|
|
2413
2452
|
<span class="cstat-no" title="statement not covered" > res.end(JSON.stringify({ error: "Forbidden" }));</span>
|
|
2414
2453
|
<span class="cstat-no" title="statement not covered" > return;</span>
|
|
2415
|
-
}
|
|
2416
|
-
const id =
|
|
2417
|
-
<span class="cstat-no" title="statement not covered"
|
|
2454
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2455
|
+
const id = url.searchParams.get("id");
|
|
2456
|
+
if (id) {<span class="cstat-no" title="statement not covered" ></span>
|
|
2418
2457
|
<span class="cstat-no" title="statement not covered" > this.#articles.remove(parseInt(id));</span>
|
|
2419
2458
|
<span class="cstat-no" title="statement not covered" > if (this.#databaseModel) {</span>
|
|
2420
2459
|
<span class="cstat-no" title="statement not covered" > await this.#databaseModel.remove(parseInt(id));</span>
|
|
2421
|
-
}
|
|
2422
|
-
|
|
2460
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2461
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2423
2462
|
<span class="cstat-no" title="statement not covered" > res.end(JSON.stringify({ status: "deleted", id }));</span>
|
|
2424
|
-
}
|
|
2425
|
-
} else
|
|
2426
|
-
|
|
2463
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2464
|
+
} else if (req.method === "PUT" && pathname === "/api/articles") {
|
|
2465
|
+
if (!<span class="cstat-no" title="statement not covered" >this.#isAuthenticated(req)) {</span>
|
|
2427
2466
|
<span class="cstat-no" title="statement not covered" > res.writeHead(403, { "Content-Type": "application/json" });</span>
|
|
2428
2467
|
<span class="cstat-no" title="statement not covered" > res.end(JSON.stringify({ error: "Forbidden" }));</span>
|
|
2429
2468
|
<span class="cstat-no" title="statement not covered" > return;</span>
|
|
2430
|
-
}
|
|
2431
|
-
const id =
|
|
2432
|
-
const body
|
|
2433
|
-
let data = <span class="cstat-no" title="statement not covered" >""
|
|
2434
|
-
|
|
2435
|
-
<span class="cstat-no" title="statement not covered" > req.on("end", <span class="fstat-no" title="function not covered" >
|
|
2436
|
-
})
|
|
2437
|
-
const { title, content } =
|
|
2438
|
-
<span class="cstat-no" title="statement not covered" >
|
|
2469
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2470
|
+
const id = url.searchParams.get("id");
|
|
2471
|
+
const body <span class="cstat-no" title="statement not covered" >= await new Promise((resolv</span>e) => {
|
|
2472
|
+
let data = <span class="cstat-no" title="statement not covered" >"";<span class="fstat-no" title="function not covered" ></span></span>
|
|
2473
|
+
req.on("dat<span class="cstat-no" title="statement not covered" >a",</span> (chunk) => (data += chunk));
|
|
2474
|
+
<span class="cstat-no" title="statement not covered" > req.on("end", (<span class="fstat-no" title="function not covered" >) </span>=> resolve<span class="cstat-no" title="statement not covered" >(data));</span></span>
|
|
2475
|
+
})<span class="cstat-no" title="statement not covered" >;<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" ></span></span></span>
|
|
2476
|
+
const { title, content } = JSON.parse(body);
|
|
2477
|
+
this.#articles.update(parse<span class="cstat-no" title="statement not covered" >Int(id), title, c</span>ontent);
|
|
2439
2478
|
<span class="cstat-no" title="statement not covered" > if (this.#databaseModel) {</span>
|
|
2440
2479
|
<span class="cstat-no" title="statement not covered" > await this.#databaseModel.update(parseInt(id), { title, content });</span>
|
|
2441
|
-
}
|
|
2442
|
-
|
|
2480
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2481
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2443
2482
|
<span class="cstat-no" title="statement not covered" > res.end(JSON.stringify({ status: "updated", id }));</span>
|
|
2444
|
-
}
|
|
2483
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2445
2484
|
}
|
|
2446
2485
|
|
|
2447
2486
|
/** set external API */
|
|
@@ -2473,8 +2512,8 @@ export default class Blog {
|
|
|
2473
2512
|
login: "",
|
|
2474
2513
|
};
|
|
2475
2514
|
|
|
2476
|
-
|
|
2477
|
-
else data.
|
|
2515
|
+
if (loggedin) data.login = `<a href="/logout">logout</a>`;
|
|
2516
|
+
<span class="missing-if-branch" title="if path not taken" >I</span>else data.logi<span class="cstat-no" title="statement not covered" >n = `<a href="/login">login</a>`;</span>
|
|
2478
2517
|
|
|
2479
2518
|
//debug("typeof data: %o", typeof data);
|
|
2480
2519
|
//debug("typeof data.articles: %o", typeof data.articles);
|
|
@@ -2483,9 +2522,9 @@ export default class Blog {
|
|
|
2483
2522
|
debug("first article: ");
|
|
2484
2523
|
debug("%d %s %s", article.id, article.title, article.getContentVeryShort());
|
|
2485
2524
|
const html = formatHTML(data);
|
|
2486
|
-
|
|
2487
|
-
<span class="
|
|
2488
|
-
}
|
|
2525
|
+
if (validate(html)) return html;
|
|
2526
|
+
<span class="missing-if-branch" title="else path not taken" >E</span>throw new Error("Error. Invalid HTML!");
|
|
2527
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2489
2528
|
|
|
2490
2529
|
/**
|
|
2491
2530
|
* read files, compare checksums, compile and write to public/styles.min.css
|
|
@@ -2512,8 +2551,8 @@ export default class Blog {
|
|
|
2512
2551
|
const fileData = await Promise.all(
|
|
2513
2552
|
styleFiles.sort().map(async (f) => {
|
|
2514
2553
|
const content = await fs.promises.readFile(f, "utf-8");
|
|
2515
|
-
|
|
2516
|
-
return { path: f,
|
|
2554
|
+
if (content == "") throw new Error("Invalid Filepath or empty file!");
|
|
2555
|
+
<span class="missing-if-branch" title="if path not taken" >I</span>return { path: f, c<span class="cstat-no" title="statement not covered" >ontent };</span>
|
|
2517
2556
|
}),
|
|
2518
2557
|
);
|
|
2519
2558
|
|
|
@@ -2545,9 +2584,9 @@ export default class Blog {
|
|
|
2545
2584
|
path.join(publicDir, "styles.min.css"),
|
|
2546
2585
|
this.compiledStyles + `\n/* source-hash: ${currentHash} */`,
|
|
2547
2586
|
);
|
|
2548
|
-
} else
|
|
2549
|
-
<span class="
|
|
2550
|
-
}
|
|
2587
|
+
} else {
|
|
2588
|
+
conso<span class="missing-if-branch" title="else path not taken" >E</span>le.log("styles are up-to-date");
|
|
2589
|
+
}<span class="cstat-no" title="statement not covered" ></span>
|
|
2551
2590
|
}
|
|
2552
2591
|
}
|
|
2553
2592
|
|
|
@@ -2557,18 +2596,18 @@ export default class Blog {
|
|
|
2557
2596
|
*/
|
|
2558
2597
|
async #processScripts(files) {
|
|
2559
2598
|
// Normalize input to array
|
|
2560
|
-
const fileList = Array.isArray(files) ?
|
|
2561
|
-
const scriptFiles = fileList.filter(
|
|
2599
|
+
const fileList = Array.isArray(files) ? files : [files];
|
|
2600
|
+
const scriptFiles = fileList.filter(<span class="branch-0 cbranch-no" title="branch not covered" ></span>
|
|
2562
2601
|
(f) =>
|
|
2563
2602
|
typeof f === "string" && f.endsWith(".js") && !f.endsWith(".min.js"),
|
|
2564
2603
|
);
|
|
2565
2604
|
|
|
2566
|
-
|
|
2567
|
-
|
|
2605
|
+
if (scriptFiles.length > 0) {
|
|
2606
|
+
<span class="missing-if-branch" title="else path not taken" >E</span> const fileData = await Promise.all(
|
|
2568
2607
|
scriptFiles.map(async (f) => {
|
|
2569
2608
|
const content = await fs.promises.readFile(f, "utf-8");
|
|
2570
|
-
|
|
2571
|
-
return { path: f,
|
|
2609
|
+
if (content == "") throw new Error("Invalid Filepath or empty file!");
|
|
2610
|
+
<span class="missing-if-branch" title="if path not taken" >I</span>return { path: f, c<span class="cstat-no" title="statement not covered" >ontent };</span>
|
|
2572
2611
|
}),
|
|
2573
2612
|
);
|
|
2574
2613
|
|
|
@@ -2583,30 +2622,30 @@ export default class Blog {
|
|
|
2583
2622
|
)
|
|
2584
2623
|
.digest("hex");
|
|
2585
2624
|
|
|
2586
|
-
|
|
2587
|
-
|
|
2625
|
+
if (!this.#scriptsHash) {
|
|
2626
|
+
<span class="missing-if-branch" title="else path not taken" >E</span> try {
|
|
2588
2627
|
const publicDir = path.join(process.cwd(), "public");
|
|
2589
2628
|
const existing = await fs.promises.readFile(
|
|
2590
2629
|
path.join(publicDir, "scripts.min.js"),
|
|
2591
2630
|
"utf-8",
|
|
2592
2631
|
);
|
|
2593
2632
|
const match = existing.match(/\/\* source-hash: ([a-f0-9]{64}) \*\//);
|
|
2594
|
-
|
|
2595
|
-
} catch (err) {
|
|
2633
|
+
if (match) this.#scriptsHash = match[1];
|
|
2634
|
+
} <span class="missing-if-branch" title="else path not taken" >E</span>catch (err) {
|
|
2596
2635
|
// ignore
|
|
2597
2636
|
}
|
|
2598
2637
|
}
|
|
2599
2638
|
|
|
2600
|
-
|
|
2601
|
-
<span class="
|
|
2639
|
+
if (currentHash !== this.#scriptsHash) {
|
|
2640
|
+
<span class="missing-if-branch" title="if path not taken" >I</span> console.log("Script assets have changed. Recompiling...");
|
|
2602
2641
|
<span class="cstat-no" title="statement not covered" > this.#scriptsHash = currentHash;</span>
|
|
2603
|
-
|
|
2604
|
-
const compiledScripts =
|
|
2605
|
-
|
|
2606
|
-
const publicDir =
|
|
2607
|
-
|
|
2642
|
+
<span class="cstat-no" title="statement not covered" ></span>
|
|
2643
|
+
const compiledScripts = await compileScripts(fileData);
|
|
2644
|
+
<span class="cstat-no" title="statement not covered" ></span>
|
|
2645
|
+
const publicDir = path.join(process.cwd(), "public");
|
|
2646
|
+
await fs.promises.<span class="cstat-no" title="statement not covered" >mkdir(publicDir, { recursive: true </span>});
|
|
2608
2647
|
<span class="cstat-no" title="statement not covered" > await fs.promises.writeFile(</span>
|
|
2609
|
-
path.join(publicDir, "scripts.min.js")
|
|
2648
|
+
<span class="cstat-no" title="statement not covered" > path.join(publicDir, "scripts.min.js"),</span>
|
|
2610
2649
|
compiledScripts + `\n/* source-hash: ${currentHash} */`,
|
|
2611
2650
|
);
|
|
2612
2651
|
}
|
|
@@ -2620,7 +2659,7 @@ export default class Blog {
|
|
|
2620
2659
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
2621
2660
|
Code coverage generated by
|
|
2622
2661
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
2623
|
-
at 2026-01-
|
|
2662
|
+
at 2026-01-18T09:48:57.520Z
|
|
2624
2663
|
</div>
|
|
2625
2664
|
<script src="../prettify.js"></script>
|
|
2626
2665
|
<script>
|