@igo2/geo 1.14.2 → 1.14.3

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.
Files changed (871) hide show
  1. package/esm2020/igo2-geo.mjs +4 -4
  2. package/esm2020/lib/catalog/catalog-browser/catalog-browser-group.component.mjs +300 -300
  3. package/esm2020/lib/catalog/catalog-browser/catalog-browser-layer.component.mjs +305 -305
  4. package/esm2020/lib/catalog/catalog-browser/catalog-browser.component.mjs +246 -246
  5. package/esm2020/lib/catalog/catalog-browser/catalog-browser.module.mjs +79 -79
  6. package/esm2020/lib/catalog/catalog-library/add-catalog-dialog.component.mjs +208 -208
  7. package/esm2020/lib/catalog/catalog-library/catalog-library-item.component.mjs +78 -78
  8. package/esm2020/lib/catalog/catalog-library/catalog-library.component.mjs +216 -216
  9. package/esm2020/lib/catalog/catalog-library/catalog-library.module.mjs +94 -94
  10. package/esm2020/lib/catalog/catalog.module.mjs +52 -52
  11. package/esm2020/lib/catalog/index.mjs +4 -4
  12. package/esm2020/lib/catalog/shared/catalog.abstract.mjs +94 -94
  13. package/esm2020/lib/catalog/shared/catalog.enum.mjs +15 -15
  14. package/esm2020/lib/catalog/shared/catalog.interface.mjs +1 -1
  15. package/esm2020/lib/catalog/shared/catalog.service.mjs +605 -605
  16. package/esm2020/lib/catalog/shared/index.mjs +4 -4
  17. package/esm2020/lib/datasource/datasource.module.mjs +21 -21
  18. package/esm2020/lib/datasource/index.mjs +2 -2
  19. package/esm2020/lib/datasource/shared/capabilities.service.mjs +430 -430
  20. package/esm2020/lib/datasource/shared/datasource.service.mjs +235 -235
  21. package/esm2020/lib/datasource/shared/datasources/any-datasource.interface.mjs +1 -1
  22. package/esm2020/lib/datasource/shared/datasources/any-datasource.mjs +1 -1
  23. package/esm2020/lib/datasource/shared/datasources/arcgisrest-datasource.interface.mjs +1 -1
  24. package/esm2020/lib/datasource/shared/datasources/arcgisrest-datasource.mjs +144 -144
  25. package/esm2020/lib/datasource/shared/datasources/carto-datasource.interface.mjs +1 -1
  26. package/esm2020/lib/datasource/shared/datasources/carto-datasource.mjs +108 -108
  27. package/esm2020/lib/datasource/shared/datasources/cluster-datasource.interface.mjs +1 -1
  28. package/esm2020/lib/datasource/shared/datasources/cluster-datasource.mjs +14 -14
  29. package/esm2020/lib/datasource/shared/datasources/data.service.mjs +2 -2
  30. package/esm2020/lib/datasource/shared/datasources/datasource.interface.mjs +1 -1
  31. package/esm2020/lib/datasource/shared/datasources/datasource.mjs +28 -28
  32. package/esm2020/lib/datasource/shared/datasources/feature-datasource.interface.mjs +1 -1
  33. package/esm2020/lib/datasource/shared/datasources/feature-datasource.mjs +42 -42
  34. package/esm2020/lib/datasource/shared/datasources/imagearcgisrest-datasource.interface.mjs +1 -1
  35. package/esm2020/lib/datasource/shared/datasources/imagearcgisrest-datasource.mjs +56 -56
  36. package/esm2020/lib/datasource/shared/datasources/index.mjs +35 -35
  37. package/esm2020/lib/datasource/shared/datasources/mvt-datasource.interface.mjs +1 -1
  38. package/esm2020/lib/datasource/shared/datasources/mvt-datasource.mjs +27 -27
  39. package/esm2020/lib/datasource/shared/datasources/osm-datasource.interface.mjs +1 -1
  40. package/esm2020/lib/datasource/shared/datasources/osm-datasource.mjs +11 -11
  41. package/esm2020/lib/datasource/shared/datasources/tilearcgisrest-datasource.interface.mjs +1 -1
  42. package/esm2020/lib/datasource/shared/datasources/tilearcgisrest-datasource.mjs +48 -48
  43. package/esm2020/lib/datasource/shared/datasources/tiledebug-datasource.interface.mjs +1 -1
  44. package/esm2020/lib/datasource/shared/datasources/tiledebug-datasource.mjs +14 -14
  45. package/esm2020/lib/datasource/shared/datasources/websocket-datasource.interface.mjs +1 -1
  46. package/esm2020/lib/datasource/shared/datasources/websocket-datasource.mjs +53 -53
  47. package/esm2020/lib/datasource/shared/datasources/wfs-datasource.interface.mjs +1 -1
  48. package/esm2020/lib/datasource/shared/datasources/wfs-datasource.mjs +71 -71
  49. package/esm2020/lib/datasource/shared/datasources/wfs.service.mjs +151 -151
  50. package/esm2020/lib/datasource/shared/datasources/wms-datasource.interface.mjs +1 -1
  51. package/esm2020/lib/datasource/shared/datasources/wms-datasource.mjs +205 -205
  52. package/esm2020/lib/datasource/shared/datasources/wms-wfs.utils.mjs +206 -206
  53. package/esm2020/lib/datasource/shared/datasources/wmts-datasource.interface.mjs +1 -1
  54. package/esm2020/lib/datasource/shared/datasources/wmts-datasource.mjs +15 -15
  55. package/esm2020/lib/datasource/shared/datasources/xyz-datasource.interface.mjs +1 -1
  56. package/esm2020/lib/datasource/shared/datasources/xyz-datasource.mjs +8 -8
  57. package/esm2020/lib/datasource/shared/index.mjs +4 -4
  58. package/esm2020/lib/datasource/shared/options/index.mjs +4 -4
  59. package/esm2020/lib/datasource/shared/options/options-api.interface.mjs +1 -1
  60. package/esm2020/lib/datasource/shared/options/options-api.providers.mjs +14 -14
  61. package/esm2020/lib/datasource/shared/options/options-api.service.mjs +80 -80
  62. package/esm2020/lib/datasource/shared/options/options.service.mjs +2 -2
  63. package/esm2020/lib/datasource/utils/esri-style-generator.mjs +356 -356
  64. package/esm2020/lib/datasource/utils/index.mjs +2 -2
  65. package/esm2020/lib/datasource/utils/tilegrid.mjs +19 -19
  66. package/esm2020/lib/directions/directions-buttons/directions-buttons.component.mjs +223 -223
  67. package/esm2020/lib/directions/directions-buttons/index.mjs +1 -1
  68. package/esm2020/lib/directions/directions-inputs/directions-inputs.component.mjs +289 -289
  69. package/esm2020/lib/directions/directions-inputs/index.mjs +1 -1
  70. package/esm2020/lib/directions/directions-results/directions-results.component.mjs +195 -195
  71. package/esm2020/lib/directions/directions-results/index.mjs +1 -1
  72. package/esm2020/lib/directions/directions-sources/directions-source.interface.mjs +1 -1
  73. package/esm2020/lib/directions/directions-sources/directions-source.mjs +2 -2
  74. package/esm2020/lib/directions/directions-sources/directions-source.provider.mjs +15 -15
  75. package/esm2020/lib/directions/directions-sources/index.mjs +4 -4
  76. package/esm2020/lib/directions/directions-sources/osrm-directions-source.mjs +98 -98
  77. package/esm2020/lib/directions/directions.component.mjs +310 -310
  78. package/esm2020/lib/directions/directions.module.mjs +101 -101
  79. package/esm2020/lib/directions/index.mjs +6 -6
  80. package/esm2020/lib/directions/shared/directions-source.service.mjs +16 -16
  81. package/esm2020/lib/directions/shared/directions.enum.mjs +27 -27
  82. package/esm2020/lib/directions/shared/directions.interface.mjs +1 -1
  83. package/esm2020/lib/directions/shared/directions.service.mjs +28 -28
  84. package/esm2020/lib/directions/shared/directions.utils.mjs +508 -508
  85. package/esm2020/lib/directions/shared/index.mjs +5 -5
  86. package/esm2020/lib/directions/shared/store.mjs +23 -23
  87. package/esm2020/lib/download/download-button/download-button.component.mjs +60 -60
  88. package/esm2020/lib/download/download-button/index.mjs +1 -1
  89. package/esm2020/lib/download/download.module.mjs +41 -41
  90. package/esm2020/lib/download/index.mjs +2 -2
  91. package/esm2020/lib/download/shared/download.interface.mjs +1 -1
  92. package/esm2020/lib/download/shared/download.service.mjs +64 -64
  93. package/esm2020/lib/download/shared/index.mjs +2 -2
  94. package/esm2020/lib/draw/draw/draw-layer-popup.component.mjs +54 -54
  95. package/esm2020/lib/draw/draw/draw-popup.component.mjs +590 -590
  96. package/esm2020/lib/draw/draw/draw-shorcuts.component.mjs +47 -47
  97. package/esm2020/lib/draw/draw/draw.component.mjs +1298 -1298
  98. package/esm2020/lib/draw/draw/draw.module.mjs +112 -112
  99. package/esm2020/lib/draw/drawingTool.module.mjs +19 -19
  100. package/esm2020/lib/draw/index.mjs +2 -2
  101. package/esm2020/lib/draw/shared/draw-icon.service.mjs +26 -26
  102. package/esm2020/lib/draw/shared/draw-style.service.mjs +189 -189
  103. package/esm2020/lib/draw/shared/draw.enum.mjs +36 -36
  104. package/esm2020/lib/draw/shared/draw.interface.mjs +1 -1
  105. package/esm2020/lib/draw/shared/draw.utils.mjs +121 -121
  106. package/esm2020/lib/draw/shared/index.mjs +5 -5
  107. package/esm2020/lib/feature/feature-details/feature-details.component.mjs +404 -404
  108. package/esm2020/lib/feature/feature-details/feature-details.directive.mjs +53 -53
  109. package/esm2020/lib/feature/feature-details/feature-details.module.mjs +47 -47
  110. package/esm2020/lib/feature/feature-form/feature-form.component.mjs +111 -111
  111. package/esm2020/lib/feature/feature-form/feature-form.module.mjs +33 -33
  112. package/esm2020/lib/feature/feature.module.mjs +27 -27
  113. package/esm2020/lib/feature/index.mjs +3 -3
  114. package/esm2020/lib/feature/shared/feature.enums.mjs +8 -8
  115. package/esm2020/lib/feature/shared/feature.interfaces.mjs +1 -1
  116. package/esm2020/lib/feature/shared/feature.utils.mjs +346 -346
  117. package/esm2020/lib/feature/shared/index.mjs +6 -6
  118. package/esm2020/lib/feature/shared/store.mjs +123 -123
  119. package/esm2020/lib/feature/shared/strategies/in-map-extent.mjs +112 -112
  120. package/esm2020/lib/feature/shared/strategies/in-map-resolution.mjs +93 -93
  121. package/esm2020/lib/feature/shared/strategies/index.mjs +5 -5
  122. package/esm2020/lib/feature/shared/strategies/loading-layer.mjs +103 -103
  123. package/esm2020/lib/feature/shared/strategies/loading.mjs +132 -132
  124. package/esm2020/lib/feature/shared/strategies/selection.mjs +369 -369
  125. package/esm2020/lib/feature/shared/strategies.utils.mjs +36 -36
  126. package/esm2020/lib/filter/filter.module.mjs +288 -288
  127. package/esm2020/lib/filter/index.mjs +15 -15
  128. package/esm2020/lib/filter/ogc-filter-button/index.mjs +1 -1
  129. package/esm2020/lib/filter/ogc-filter-button/ogc-filter-button.component.mjs +139 -139
  130. package/esm2020/lib/filter/ogc-filter-form/index.mjs +1 -1
  131. package/esm2020/lib/filter/ogc-filter-form/ogc-filter-form.component.mjs +644 -644
  132. package/esm2020/lib/filter/ogc-filter-selection/index.mjs +1 -1
  133. package/esm2020/lib/filter/ogc-filter-selection/ogc-filter-selection.component.mjs +1301 -1301
  134. package/esm2020/lib/filter/ogc-filter-time/index.mjs +2 -2
  135. package/esm2020/lib/filter/ogc-filter-time/ogc-filter-time-slider.component.mjs +176 -176
  136. package/esm2020/lib/filter/ogc-filter-time/ogc-filter-time.component.mjs +897 -897
  137. package/esm2020/lib/filter/ogc-filterable-form/index.mjs +1 -1
  138. package/esm2020/lib/filter/ogc-filterable-form/ogc-filterable-form.component.mjs +58 -58
  139. package/esm2020/lib/filter/ogc-filterable-item/index.mjs +1 -1
  140. package/esm2020/lib/filter/ogc-filterable-item/ogc-filterable-item.component.mjs +306 -306
  141. package/esm2020/lib/filter/ogc-filterable-list/index.mjs +2 -2
  142. package/esm2020/lib/filter/ogc-filterable-list/ogc-filterable-list-binding.directive.mjs +30 -30
  143. package/esm2020/lib/filter/ogc-filterable-list/ogc-filterable-list.component.mjs +43 -43
  144. package/esm2020/lib/filter/shared/filterable-datasource.pipe.mjs +54 -54
  145. package/esm2020/lib/filter/shared/index.mjs +11 -11
  146. package/esm2020/lib/filter/shared/ogc-filter-time.service.mjs +71 -71
  147. package/esm2020/lib/filter/shared/ogc-filter.enum.mjs +29 -29
  148. package/esm2020/lib/filter/shared/ogc-filter.interface.mjs +1 -1
  149. package/esm2020/lib/filter/shared/ogc-filter.mjs +691 -691
  150. package/esm2020/lib/filter/shared/ogc-filter.service.mjs +45 -45
  151. package/esm2020/lib/filter/shared/spatial-filter.enum.mjs +22 -22
  152. package/esm2020/lib/filter/shared/spatial-filter.interface.mjs +1 -1
  153. package/esm2020/lib/filter/shared/spatial-filter.service.mjs +268 -268
  154. package/esm2020/lib/filter/shared/time-filter.enum.mjs +12 -12
  155. package/esm2020/lib/filter/shared/time-filter.interface.mjs +1 -1
  156. package/esm2020/lib/filter/shared/time-filter.service.mjs +106 -106
  157. package/esm2020/lib/filter/spatial-filter/spatial-filter-item/index.mjs +1 -1
  158. package/esm2020/lib/filter/spatial-filter/spatial-filter-item/spatial-filter-item.component.mjs +1088 -1088
  159. package/esm2020/lib/filter/spatial-filter/spatial-filter-list/index.mjs +1 -1
  160. package/esm2020/lib/filter/spatial-filter/spatial-filter-list/spatial-filter-list.component.mjs +207 -207
  161. package/esm2020/lib/filter/spatial-filter/spatial-filter-type/index.mjs +1 -1
  162. package/esm2020/lib/filter/spatial-filter/spatial-filter-type/spatial-filter-type.component.mjs +143 -143
  163. package/esm2020/lib/filter/time-filter-button/index.mjs +1 -1
  164. package/esm2020/lib/filter/time-filter-button/time-filter-button.component.mjs +77 -77
  165. package/esm2020/lib/filter/time-filter-form/index.mjs +1 -1
  166. package/esm2020/lib/filter/time-filter-form/time-filter-form.component.mjs +733 -733
  167. package/esm2020/lib/filter/time-filter-item/index.mjs +1 -1
  168. package/esm2020/lib/filter/time-filter-item/time-filter-item.component.mjs +118 -118
  169. package/esm2020/lib/filter/time-filter-list/index.mjs +2 -2
  170. package/esm2020/lib/filter/time-filter-list/time-filter-list-binding.directive.mjs +30 -30
  171. package/esm2020/lib/filter/time-filter-list/time-filter-list.component.mjs +38 -38
  172. package/esm2020/lib/geo.module.mjs +101 -101
  173. package/esm2020/lib/geometry/geometry-form-field/geometry-form-field-input.component.mjs +520 -520
  174. package/esm2020/lib/geometry/geometry-form-field/geometry-form-field.component.mjs +188 -188
  175. package/esm2020/lib/geometry/geometry-form-field/geometry-form-field.module.mjs +63 -63
  176. package/esm2020/lib/geometry/geometry.module.mjs +26 -26
  177. package/esm2020/lib/geometry/index.mjs +3 -3
  178. package/esm2020/lib/geometry/shared/controls/draw.mjs +313 -313
  179. package/esm2020/lib/geometry/shared/controls/index.mjs +3 -3
  180. package/esm2020/lib/geometry/shared/controls/modify.mjs +520 -520
  181. package/esm2020/lib/geometry/shared/controls/slice.mjs +176 -176
  182. package/esm2020/lib/geometry/shared/geometry.errors.mjs +25 -25
  183. package/esm2020/lib/geometry/shared/geometry.interfaces.mjs +1 -1
  184. package/esm2020/lib/geometry/shared/geometry.utils.mjs +121 -121
  185. package/esm2020/lib/geometry/shared/index.mjs +4 -4
  186. package/esm2020/lib/import-export/export-button/export-button.component.mjs +63 -63
  187. package/esm2020/lib/import-export/export-button/index.mjs +1 -1
  188. package/esm2020/lib/import-export/import-export/import-export.component.mjs +1219 -1219
  189. package/esm2020/lib/import-export/import-export/index.mjs +1 -1
  190. package/esm2020/lib/import-export/import-export.module.mjs +95 -95
  191. package/esm2020/lib/import-export/index.mjs +4 -4
  192. package/esm2020/lib/import-export/shared/drop-geo-file.directive.mjs +134 -134
  193. package/esm2020/lib/import-export/shared/export.errors.mjs +14 -14
  194. package/esm2020/lib/import-export/shared/export.interface.mjs +1 -1
  195. package/esm2020/lib/import-export/shared/export.service.mjs +194 -194
  196. package/esm2020/lib/import-export/shared/export.type.mjs +3 -3
  197. package/esm2020/lib/import-export/shared/export.utils.mjs +54 -54
  198. package/esm2020/lib/import-export/shared/import.errors.mjs +38 -38
  199. package/esm2020/lib/import-export/shared/import.interface.mjs +1 -1
  200. package/esm2020/lib/import-export/shared/import.service.mjs +214 -214
  201. package/esm2020/lib/import-export/shared/import.utils.mjs +234 -234
  202. package/esm2020/lib/import-export/shared/index.mjs +10 -10
  203. package/esm2020/lib/import-export/style-list/index.mjs +4 -4
  204. package/esm2020/lib/import-export/style-list/style-list.interface.mjs +1 -1
  205. package/esm2020/lib/import-export/style-list/style-list.module.mjs +22 -22
  206. package/esm2020/lib/import-export/style-list/style-list.provider.mjs +20 -20
  207. package/esm2020/lib/import-export/style-list/style-list.service.mjs +50 -50
  208. package/esm2020/lib/layer/index.mjs +10 -10
  209. package/esm2020/lib/layer/layer-item/index.mjs +1 -1
  210. package/esm2020/lib/layer/layer-item/layer-item.component.mjs +299 -299
  211. package/esm2020/lib/layer/layer-legend/index.mjs +1 -1
  212. package/esm2020/lib/layer/layer-legend/layer-legend.component.mjs +387 -387
  213. package/esm2020/lib/layer/layer-legend-item/index.mjs +1 -1
  214. package/esm2020/lib/layer/layer-legend-item/layer-legend-item.component.mjs +83 -83
  215. package/esm2020/lib/layer/layer-legend-list/index.mjs +2 -2
  216. package/esm2020/lib/layer/layer-legend-list/layer-legend-list-binding.directive.mjs +47 -47
  217. package/esm2020/lib/layer/layer-legend-list/layer-legend-list.component.mjs +194 -194
  218. package/esm2020/lib/layer/layer-list/index.mjs +3 -3
  219. package/esm2020/lib/layer/layer-list/layer-list-binding.directive.mjs +58 -58
  220. package/esm2020/lib/layer/layer-list/layer-list.component.mjs +1008 -1008
  221. package/esm2020/lib/layer/layer-list/layer-list.enum.mjs +18 -18
  222. package/esm2020/lib/layer/layer-list-tool/index.mjs +4 -4
  223. package/esm2020/lib/layer/layer-list-tool/layer-list-tool.component.mjs +164 -164
  224. package/esm2020/lib/layer/layer-list-tool/layer-list-tool.enum.mjs +6 -6
  225. package/esm2020/lib/layer/layer-list-tool/layer-list-tool.interface.mjs +1 -1
  226. package/esm2020/lib/layer/layer-list-tool/layer-list-tool.service.mjs +21 -21
  227. package/esm2020/lib/layer/layer.module.mjs +184 -184
  228. package/esm2020/lib/layer/shared/clusterParam.mjs +1 -1
  229. package/esm2020/lib/layer/shared/index.mjs +6 -6
  230. package/esm2020/lib/layer/shared/layer.enums.mjs +1 -1
  231. package/esm2020/lib/layer/shared/layer.service.mjs +185 -185
  232. package/esm2020/lib/layer/shared/layers/any-layer.interface.mjs +1 -1
  233. package/esm2020/lib/layer/shared/layers/any-layer.mjs +1 -1
  234. package/esm2020/lib/layer/shared/layers/image-layer.interface.mjs +1 -1
  235. package/esm2020/lib/layer/shared/layers/image-layer.mjs +67 -67
  236. package/esm2020/lib/layer/shared/layers/index.mjs +12 -12
  237. package/esm2020/lib/layer/shared/layers/layer.interface.mjs +17 -17
  238. package/esm2020/lib/layer/shared/layers/layer.mjs +163 -163
  239. package/esm2020/lib/layer/shared/layers/tile-layer.interface.mjs +1 -1
  240. package/esm2020/lib/layer/shared/layers/tile-layer.mjs +46 -46
  241. package/esm2020/lib/layer/shared/layers/vector-layer.interface.mjs +1 -1
  242. package/esm2020/lib/layer/shared/layers/vector-layer.mjs +377 -377
  243. package/esm2020/lib/layer/shared/layers/vectortile-layer.interface.mjs +1 -1
  244. package/esm2020/lib/layer/shared/layers/vectortile-layer.mjs +103 -103
  245. package/esm2020/lib/layer/shared/style.service.mjs +355 -355
  246. package/esm2020/lib/layer/shared/vector-style.interface.mjs +1 -1
  247. package/esm2020/lib/layer/style-modal/index.mjs +1 -1
  248. package/esm2020/lib/layer/style-modal/style-modal.component.mjs +287 -287
  249. package/esm2020/lib/layer/track-feature-button/index.mjs +1 -1
  250. package/esm2020/lib/layer/track-feature-button/track-feature-button.component.mjs +58 -58
  251. package/esm2020/lib/layer/utils/image-watcher.mjs +61 -61
  252. package/esm2020/lib/layer/utils/index.mjs +5 -5
  253. package/esm2020/lib/layer/utils/layer.utils.mjs +9 -9
  254. package/esm2020/lib/layer/utils/outputLegend.mjs +26 -26
  255. package/esm2020/lib/layer/utils/tile-watcher.mjs +49 -49
  256. package/esm2020/lib/layer/utils/vector-watcher.mjs +47 -47
  257. package/esm2020/lib/map/baselayers-switcher/baselayers-switcher.animation.mjs +19 -19
  258. package/esm2020/lib/map/baselayers-switcher/baselayers-switcher.component.mjs +96 -96
  259. package/esm2020/lib/map/baselayers-switcher/index.mjs +2 -2
  260. package/esm2020/lib/map/baselayers-switcher/mini-basemap.component.mjs +141 -142
  261. package/esm2020/lib/map/geolocate-button/geolocate-button.component.mjs +78 -78
  262. package/esm2020/lib/map/geolocate-button/index.mjs +1 -1
  263. package/esm2020/lib/map/home-extent-button/home-extent-button.component.mjs +62 -62
  264. package/esm2020/lib/map/home-extent-button/index.mjs +1 -1
  265. package/esm2020/lib/map/index.mjs +13 -13
  266. package/esm2020/lib/map/info-section/index.mjs +1 -1
  267. package/esm2020/lib/map/info-section/info-section.component.mjs +29 -29
  268. package/esm2020/lib/map/map-browser/index.mjs +1 -1
  269. package/esm2020/lib/map/map-browser/map-browser.component.mjs +65 -65
  270. package/esm2020/lib/map/map-center/index.mjs +1 -1
  271. package/esm2020/lib/map/map-center/map-center.component.mjs +49 -49
  272. package/esm2020/lib/map/map.module.mjs +126 -126
  273. package/esm2020/lib/map/menu-button/index.mjs +1 -1
  274. package/esm2020/lib/map/menu-button/menu-button.component.mjs +61 -61
  275. package/esm2020/lib/map/offline-button/index.mjs +1 -1
  276. package/esm2020/lib/map/offline-button/offline-button.component.mjs +75 -75
  277. package/esm2020/lib/map/rotation-button/index.mjs +1 -1
  278. package/esm2020/lib/map/rotation-button/rotation-button.component.mjs +69 -69
  279. package/esm2020/lib/map/shared/controllers/controller.mjs +41 -41
  280. package/esm2020/lib/map/shared/controllers/geolocation.mjs +307 -307
  281. package/esm2020/lib/map/shared/controllers/index.mjs +3 -3
  282. package/esm2020/lib/map/shared/controllers/view.mjs +350 -350
  283. package/esm2020/lib/map/shared/hover-feature.directive.mjs +502 -502
  284. package/esm2020/lib/map/shared/index.mjs +13 -13
  285. package/esm2020/lib/map/shared/linkedLayers.utils.mjs +237 -237
  286. package/esm2020/lib/map/shared/map-pointer-position.directive.mjs +106 -106
  287. package/esm2020/lib/map/shared/map.enums.mjs +5 -5
  288. package/esm2020/lib/map/shared/map.interface.mjs +1 -1
  289. package/esm2020/lib/map/shared/map.mjs +406 -406
  290. package/esm2020/lib/map/shared/map.service.mjs +28 -28
  291. package/esm2020/lib/map/shared/map.utils.mjs +462 -462
  292. package/esm2020/lib/map/shared/mapOffline.directive.mjs +162 -162
  293. package/esm2020/lib/map/shared/projection.interfaces.mjs +1 -1
  294. package/esm2020/lib/map/shared/projection.service.mjs +64 -64
  295. package/esm2020/lib/map/shared/projection.utils.mjs +63 -63
  296. package/esm2020/lib/map/swipe-control/index.mjs +1 -1
  297. package/esm2020/lib/map/swipe-control/swipe-control.component.mjs +192 -192
  298. package/esm2020/lib/map/utils/layer-watcher.mjs +78 -78
  299. package/esm2020/lib/map/wake-lock-button/index.mjs +1 -1
  300. package/esm2020/lib/map/wake-lock-button/wake-lock-button.component.mjs +113 -113
  301. package/esm2020/lib/map/zoom-button/index.mjs +1 -1
  302. package/esm2020/lib/map/zoom-button/zoom-button.component.mjs +39 -39
  303. package/esm2020/lib/measure/index.mjs +3 -3
  304. package/esm2020/lib/measure/measure.module.mjs +19 -19
  305. package/esm2020/lib/measure/measurer/measure-format.pipe.mjs +36 -36
  306. package/esm2020/lib/measure/measurer/measurer-dialog.component.mjs +179 -179
  307. package/esm2020/lib/measure/measurer/measurer-item.component.mjs +139 -139
  308. package/esm2020/lib/measure/measurer/measurer.component.mjs +1041 -1041
  309. package/esm2020/lib/measure/measurer/measurer.module.mjs +93 -93
  310. package/esm2020/lib/measure/shared/index.mjs +3 -3
  311. package/esm2020/lib/measure/shared/measure.enum.mjs +36 -36
  312. package/esm2020/lib/measure/shared/measure.interfaces.mjs +1 -1
  313. package/esm2020/lib/measure/shared/measure.utils.mjs +488 -488
  314. package/esm2020/lib/metadata/index.mjs +2 -2
  315. package/esm2020/lib/metadata/metadata-button/index.mjs +1 -1
  316. package/esm2020/lib/metadata/metadata-button/metadata-button.component.mjs +133 -133
  317. package/esm2020/lib/metadata/metadata.module.mjs +54 -54
  318. package/esm2020/lib/metadata/shared/index.mjs +2 -2
  319. package/esm2020/lib/metadata/shared/metadata.interface.mjs +1 -1
  320. package/esm2020/lib/metadata/shared/metadata.service.mjs +18 -18
  321. package/esm2020/lib/offline/geoDB/configFileToGeoDB.service.mjs +104 -104
  322. package/esm2020/lib/offline/geoDB/geoDB.enums.mjs +5 -5
  323. package/esm2020/lib/offline/geoDB/geoDB.interface.mjs +1 -1
  324. package/esm2020/lib/offline/geoDB/geoDB.service.mjs +166 -166
  325. package/esm2020/lib/offline/geoDB/index.mjs +4 -4
  326. package/esm2020/lib/offline/index.mjs +2 -2
  327. package/esm2020/lib/offline/shared/geo-network.service.mjs +65 -65
  328. package/esm2020/lib/offline/shared/index.mjs +1 -1
  329. package/esm2020/lib/overlay/index.mjs +1 -1
  330. package/esm2020/lib/overlay/overlay.module.mjs +22 -22
  331. package/esm2020/lib/overlay/shared/index.mjs +6 -6
  332. package/esm2020/lib/overlay/shared/overlay-marker-style.utils.mjs +68 -68
  333. package/esm2020/lib/overlay/shared/overlay.directive.mjs +32 -32
  334. package/esm2020/lib/overlay/shared/overlay.enum.mjs +7 -7
  335. package/esm2020/lib/overlay/shared/overlay.mjs +129 -129
  336. package/esm2020/lib/overlay/shared/overlay.service.mjs +26 -26
  337. package/esm2020/lib/overlay/shared/overlay.utils.mjs +102 -102
  338. package/esm2020/lib/print/index.mjs +3 -3
  339. package/esm2020/lib/print/print/print.component.mjs +125 -125
  340. package/esm2020/lib/print/print-form/index.mjs +1 -1
  341. package/esm2020/lib/print/print-form/print-form.component.mjs +427 -427
  342. package/esm2020/lib/print/print.module.mjs +64 -64
  343. package/esm2020/lib/print/shared/geopdf.mjs +57 -57
  344. package/esm2020/lib/print/shared/index.mjs +4 -4
  345. package/esm2020/lib/print/shared/print.interface.mjs +1 -1
  346. package/esm2020/lib/print/shared/print.service.mjs +933 -933
  347. package/esm2020/lib/print/shared/print.type.mjs +29 -29
  348. package/esm2020/lib/query/index.mjs +1 -1
  349. package/esm2020/lib/query/query.module.mjs +28 -28
  350. package/esm2020/lib/query/shared/index.mjs +6 -6
  351. package/esm2020/lib/query/shared/query-search-source.mjs +34 -34
  352. package/esm2020/lib/query/shared/query-search-source.providers.mjs +21 -21
  353. package/esm2020/lib/query/shared/query.directive.mjs +260 -260
  354. package/esm2020/lib/query/shared/query.enums.mjs +29 -29
  355. package/esm2020/lib/query/shared/query.interfaces.mjs +1 -1
  356. package/esm2020/lib/query/shared/query.service.mjs +732 -732
  357. package/esm2020/lib/query/shared/query.utils.mjs +36 -36
  358. package/esm2020/lib/search/index.mjs +11 -11
  359. package/esm2020/lib/search/search-bar/search-bar.component.mjs +511 -511
  360. package/esm2020/lib/search/search-bar/search-bar.module.mjs +74 -74
  361. package/esm2020/lib/search/search-bar/search-url-param.directive.mjs +34 -34
  362. package/esm2020/lib/search/search-results/save-feature-dialog.component.mjs +117 -117
  363. package/esm2020/lib/search/search-results/search-results-add-button.component.mjs +370 -370
  364. package/esm2020/lib/search/search-results/search-results-item.component.mjs +123 -123
  365. package/esm2020/lib/search/search-results/search-results.component.mjs +339 -339
  366. package/esm2020/lib/search/search-results/search-results.module.mjs +103 -103
  367. package/esm2020/lib/search/search-selector/search-selector.component.mjs +122 -122
  368. package/esm2020/lib/search/search-selector/search-selector.module.mjs +55 -55
  369. package/esm2020/lib/search/search-settings/search-settings.component.mjs +441 -441
  370. package/esm2020/lib/search/search-settings/search-settings.module.mjs +59 -59
  371. package/esm2020/lib/search/search.module.mjs +66 -66
  372. package/esm2020/lib/search/shared/index.mjs +8 -8
  373. package/esm2020/lib/search/shared/search-pointer-summary.directive.mjs +321 -321
  374. package/esm2020/lib/search/shared/search-source-service.providers.mjs +19 -19
  375. package/esm2020/lib/search/shared/search-source.service.mjs +46 -46
  376. package/esm2020/lib/search/shared/search.enums.mjs +3 -3
  377. package/esm2020/lib/search/shared/search.interfaces.mjs +1 -1
  378. package/esm2020/lib/search/shared/search.service.mjs +120 -120
  379. package/esm2020/lib/search/shared/search.utils.mjs +90 -90
  380. package/esm2020/lib/search/shared/sources/coordinates.interfaces.mjs +1 -1
  381. package/esm2020/lib/search/shared/sources/coordinates.mjs +152 -152
  382. package/esm2020/lib/search/shared/sources/coordinates.providers.mjs +39 -39
  383. package/esm2020/lib/search/shared/sources/icherche.interfaces.mjs +1 -1
  384. package/esm2020/lib/search/shared/sources/icherche.mjs +766 -766
  385. package/esm2020/lib/search/shared/sources/icherche.providers.mjs +65 -65
  386. package/esm2020/lib/search/shared/sources/ilayer.interfaces.mjs +1 -1
  387. package/esm2020/lib/search/shared/sources/ilayer.mjs +319 -319
  388. package/esm2020/lib/search/shared/sources/ilayer.providers.mjs +39 -39
  389. package/esm2020/lib/search/shared/sources/index.mjs +17 -17
  390. package/esm2020/lib/search/shared/sources/nominatim.interfaces.mjs +1 -1
  391. package/esm2020/lib/search/shared/sources/nominatim.mjs +251 -251
  392. package/esm2020/lib/search/shared/sources/nominatim.providers.mjs +22 -22
  393. package/esm2020/lib/search/shared/sources/source.interfaces.mjs +1 -1
  394. package/esm2020/lib/search/shared/sources/source.mjs +178 -178
  395. package/esm2020/lib/search/shared/sources/storedqueries.interfaces.mjs +1 -1
  396. package/esm2020/lib/search/shared/sources/storedqueries.mjs +424 -424
  397. package/esm2020/lib/search/shared/sources/storedqueries.providers.mjs +40 -40
  398. package/esm2020/lib/toast/index.mjs +1 -1
  399. package/esm2020/lib/toast/toast.component.mjs +112 -112
  400. package/esm2020/lib/toast/toast.module.mjs +44 -44
  401. package/esm2020/lib/utils/commonVectorStyle.interface.mjs +1 -1
  402. package/esm2020/lib/utils/commonVectorStyle.mjs +74 -74
  403. package/esm2020/lib/utils/googleLinks.mjs +12 -12
  404. package/esm2020/lib/utils/id-generator.mjs +109 -109
  405. package/esm2020/lib/utils/index.mjs +5 -5
  406. package/esm2020/lib/utils/osmLinks.mjs +9 -9
  407. package/esm2020/lib/wkt/index.mjs +1 -1
  408. package/esm2020/lib/wkt/shared/index.mjs +1 -1
  409. package/esm2020/lib/wkt/shared/wkt.service.mjs +224 -224
  410. package/esm2020/lib/wkt/wkt.module.mjs +21 -21
  411. package/esm2020/lib/workspace/confirmation-popup/confirmation-popup.component.mjs +47 -47
  412. package/esm2020/lib/workspace/confirmation-popup/confirmation-popup.module.mjs +35 -35
  413. package/esm2020/lib/workspace/confirmation-popup/index.mjs +2 -2
  414. package/esm2020/lib/workspace/index.mjs +7 -7
  415. package/esm2020/lib/workspace/shared/edition-workspace.mjs +279 -279
  416. package/esm2020/lib/workspace/shared/edition-workspace.service.mjs +656 -656
  417. package/esm2020/lib/workspace/shared/feature-workspace.mjs +34 -34
  418. package/esm2020/lib/workspace/shared/feature-workspace.service.mjs +149 -149
  419. package/esm2020/lib/workspace/shared/index.mjs +7 -7
  420. package/esm2020/lib/workspace/shared/wfs-workspace.mjs +34 -34
  421. package/esm2020/lib/workspace/shared/wfs-workspace.service.mjs +149 -149
  422. package/esm2020/lib/workspace/shared/wms-workspace.service.mjs +259 -259
  423. package/esm2020/lib/workspace/shared/workspace.utils.mjs +23 -23
  424. package/esm2020/lib/workspace/widgets/index.mjs +3 -3
  425. package/esm2020/lib/workspace/widgets/ogc-filter/ogc-filter.component.mjs +46 -46
  426. package/esm2020/lib/workspace/widgets/ogc-filter/ogc-filter.module.mjs +35 -35
  427. package/esm2020/lib/workspace/widgets/widgets.mjs +14 -14
  428. package/esm2020/lib/workspace/workspace-selector/workspace-selector.directive.mjs +132 -132
  429. package/esm2020/lib/workspace/workspace-selector/workspace-selector.module.mjs +27 -27
  430. package/esm2020/lib/workspace/workspace-updator/workspace-updator.directive.mjs +112 -112
  431. package/esm2020/lib/workspace/workspace-updator/workspace-updator.module.mjs +27 -27
  432. package/esm2020/lib/workspace/workspace.module.mjs +61 -61
  433. package/esm2020/public_api.mjs +54 -54
  434. package/fesm2015/igo2-geo.mjs +44986 -44986
  435. package/fesm2015/igo2-geo.mjs.map +1 -1
  436. package/fesm2020/igo2-geo.mjs +43029 -43030
  437. package/fesm2020/igo2-geo.mjs.map +1 -1
  438. package/index.d.ts +5 -5
  439. package/lib/catalog/catalog-browser/catalog-browser-group.component.d.ts +126 -126
  440. package/lib/catalog/catalog-browser/catalog-browser-layer.component.d.ts +80 -80
  441. package/lib/catalog/catalog-browser/catalog-browser.component.d.ts +105 -105
  442. package/lib/catalog/catalog-browser/catalog-browser.module.d.ts +22 -22
  443. package/lib/catalog/catalog-library/add-catalog-dialog.component.d.ts +45 -45
  444. package/lib/catalog/catalog-library/catalog-library-item.component.d.ts +25 -25
  445. package/lib/catalog/catalog-library/catalog-library.component.d.ts +65 -65
  446. package/lib/catalog/catalog-library/catalog-library.module.d.ts +26 -26
  447. package/lib/catalog/catalog.module.d.ts +14 -14
  448. package/lib/catalog/index.d.ts +4 -4
  449. package/lib/catalog/shared/catalog.abstract.d.ts +50 -50
  450. package/lib/catalog/shared/catalog.enum.d.ts +14 -14
  451. package/lib/catalog/shared/catalog.interface.d.ts +66 -66
  452. package/lib/catalog/shared/catalog.service.d.ts +36 -36
  453. package/lib/catalog/shared/index.d.ts +4 -4
  454. package/lib/datasource/datasource.module.d.ts +8 -8
  455. package/lib/datasource/index.d.ts +2 -2
  456. package/lib/datasource/shared/capabilities.service.d.ts +37 -37
  457. package/lib/datasource/shared/datasource.service.d.ts +37 -37
  458. package/lib/datasource/shared/datasources/any-datasource.d.ts +16 -16
  459. package/lib/datasource/shared/datasources/any-datasource.interface.d.ts +15 -15
  460. package/lib/datasource/shared/datasources/arcgisrest-datasource.d.ts +14 -14
  461. package/lib/datasource/shared/datasources/arcgisrest-datasource.interface.d.ts +14 -14
  462. package/lib/datasource/shared/datasources/carto-datasource.d.ts +15 -15
  463. package/lib/datasource/shared/datasources/carto-datasource.interface.d.ts +13 -13
  464. package/lib/datasource/shared/datasources/cluster-datasource.d.ts +10 -10
  465. package/lib/datasource/shared/datasources/cluster-datasource.interface.d.ts +11 -11
  466. package/lib/datasource/shared/datasources/data.service.d.ts +3 -3
  467. package/lib/datasource/shared/datasources/datasource.d.ts +20 -20
  468. package/lib/datasource/shared/datasources/datasource.interface.d.ts +100 -100
  469. package/lib/datasource/shared/datasources/feature-datasource.d.ts +12 -12
  470. package/lib/datasource/shared/datasources/feature-datasource.interface.d.ts +18 -18
  471. package/lib/datasource/shared/datasources/imagearcgisrest-datasource.d.ts +15 -15
  472. package/lib/datasource/shared/datasources/imagearcgisrest-datasource.interface.d.ts +15 -15
  473. package/lib/datasource/shared/datasources/index.d.ts +35 -35
  474. package/lib/datasource/shared/datasources/mvt-datasource.d.ts +10 -10
  475. package/lib/datasource/shared/datasources/mvt-datasource.interface.d.ts +13 -13
  476. package/lib/datasource/shared/datasources/osm-datasource.d.ts +9 -9
  477. package/lib/datasource/shared/datasources/osm-datasource.interface.d.ts +7 -7
  478. package/lib/datasource/shared/datasources/tilearcgisrest-datasource.d.ts +15 -15
  479. package/lib/datasource/shared/datasources/tilearcgisrest-datasource.interface.d.ts +14 -14
  480. package/lib/datasource/shared/datasources/tiledebug-datasource.d.ts +9 -9
  481. package/lib/datasource/shared/datasources/tiledebug-datasource.interface.d.ts +9 -9
  482. package/lib/datasource/shared/datasources/websocket-datasource.d.ts +15 -15
  483. package/lib/datasource/shared/datasources/websocket-datasource.interface.d.ts +7 -7
  484. package/lib/datasource/shared/datasources/wfs-datasource.d.ts +20 -20
  485. package/lib/datasource/shared/datasources/wfs-datasource.interface.d.ts +20 -20
  486. package/lib/datasource/shared/datasources/wfs.service.d.ts +17 -17
  487. package/lib/datasource/shared/datasources/wms-datasource.d.ts +31 -31
  488. package/lib/datasource/shared/datasources/wms-datasource.interface.d.ts +32 -32
  489. package/lib/datasource/shared/datasources/wms-wfs.utils.d.ts +41 -41
  490. package/lib/datasource/shared/datasources/wmts-datasource.d.ts +10 -10
  491. package/lib/datasource/shared/datasources/wmts-datasource.interface.d.ts +13 -13
  492. package/lib/datasource/shared/datasources/xyz-datasource.d.ts +9 -9
  493. package/lib/datasource/shared/datasources/xyz-datasource.interface.d.ts +11 -11
  494. package/lib/datasource/shared/index.d.ts +4 -4
  495. package/lib/datasource/shared/options/index.d.ts +4 -4
  496. package/lib/datasource/shared/options/options-api.interface.d.ts +4 -4
  497. package/lib/datasource/shared/options/options-api.providers.d.ts +10 -10
  498. package/lib/datasource/shared/options/options-api.service.d.ts +16 -16
  499. package/lib/datasource/shared/options/options.service.d.ts +6 -6
  500. package/lib/datasource/utils/esri-style-generator.d.ts +21 -21
  501. package/lib/datasource/utils/index.d.ts +2 -2
  502. package/lib/datasource/utils/tilegrid.d.ts +2 -2
  503. package/lib/directions/directions-buttons/directions-buttons.component.d.ts +30 -30
  504. package/lib/directions/directions-buttons/index.d.ts +1 -1
  505. package/lib/directions/directions-inputs/directions-inputs.component.d.ts +45 -45
  506. package/lib/directions/directions-inputs/index.d.ts +1 -1
  507. package/lib/directions/directions-results/directions-results.component.d.ts +30 -30
  508. package/lib/directions/directions-results/index.d.ts +1 -1
  509. package/lib/directions/directions-sources/directions-source.d.ts +7 -7
  510. package/lib/directions/directions-sources/directions-source.interface.d.ts +11 -11
  511. package/lib/directions/directions-sources/directions-source.provider.d.ts +11 -11
  512. package/lib/directions/directions-sources/index.d.ts +4 -4
  513. package/lib/directions/directions-sources/osrm-directions-source.d.ts +23 -23
  514. package/lib/directions/directions.component.d.ts +56 -56
  515. package/lib/directions/directions.module.d.ts +26 -26
  516. package/lib/directions/index.d.ts +6 -6
  517. package/lib/directions/shared/directions-source.service.d.ts +11 -11
  518. package/lib/directions/shared/directions.enum.d.ts +22 -22
  519. package/lib/directions/shared/directions.interface.d.ts +126 -126
  520. package/lib/directions/shared/directions.service.d.ts +13 -13
  521. package/lib/directions/shared/directions.utils.d.ts +42 -42
  522. package/lib/directions/shared/index.d.ts +5 -5
  523. package/lib/directions/shared/store.d.ts +18 -18
  524. package/lib/download/download-button/download-button.component.d.ts +18 -18
  525. package/lib/download/download-button/index.d.ts +1 -1
  526. package/lib/download/download.module.d.ts +14 -14
  527. package/lib/download/index.d.ts +2 -2
  528. package/lib/download/shared/download.interface.d.ts +10 -10
  529. package/lib/download/shared/download.service.d.ts +11 -11
  530. package/lib/download/shared/index.d.ts +2 -2
  531. package/lib/draw/draw/draw-layer-popup.component.d.ts +14 -14
  532. package/lib/draw/draw/draw-popup.component.d.ts +63 -63
  533. package/lib/draw/draw/draw-shorcuts.component.d.ts +5 -5
  534. package/lib/draw/draw/draw.component.d.ts +239 -239
  535. package/lib/draw/draw/draw.module.d.ts +34 -34
  536. package/lib/draw/drawingTool.module.d.ts +7 -7
  537. package/lib/draw/index.d.ts +2 -2
  538. package/lib/draw/shared/draw-icon.service.d.ts +12 -12
  539. package/lib/draw/shared/draw-style.service.d.ts +36 -36
  540. package/lib/draw/shared/draw.enum.d.ts +32 -32
  541. package/lib/draw/shared/draw.interface.d.ts +40 -40
  542. package/lib/draw/shared/draw.utils.d.ts +35 -35
  543. package/lib/draw/shared/index.d.ts +5 -5
  544. package/lib/feature/feature-details/feature-details.component.d.ts +60 -60
  545. package/lib/feature/feature-details/feature-details.directive.d.ts +19 -19
  546. package/lib/feature/feature-details/feature-details.module.d.ts +15 -15
  547. package/lib/feature/feature-form/feature-form.component.d.ts +50 -50
  548. package/lib/feature/feature-form/feature-form.module.d.ts +12 -12
  549. package/lib/feature/feature.module.d.ts +9 -9
  550. package/lib/feature/index.d.ts +3 -3
  551. package/lib/feature/shared/feature.enums.d.ts +7 -7
  552. package/lib/feature/shared/feature.interfaces.d.ts +74 -74
  553. package/lib/feature/shared/feature.utils.d.ts +104 -104
  554. package/lib/feature/shared/index.d.ts +6 -6
  555. package/lib/feature/shared/store.d.ts +71 -71
  556. package/lib/feature/shared/strategies/in-map-extent.d.ts +52 -52
  557. package/lib/feature/shared/strategies/in-map-resolution.d.ts +52 -52
  558. package/lib/feature/shared/strategies/index.d.ts +5 -5
  559. package/lib/feature/shared/strategies/loading-layer.d.ts +59 -59
  560. package/lib/feature/shared/strategies/loading.d.ts +75 -75
  561. package/lib/feature/shared/strategies/selection.d.ts +176 -176
  562. package/lib/feature/shared/strategies.utils.d.ts +17 -17
  563. package/lib/filter/filter.module.d.ts +53 -53
  564. package/lib/filter/index.d.ts +15 -15
  565. package/lib/filter/ogc-filter-button/index.d.ts +1 -1
  566. package/lib/filter/ogc-filter-button/ogc-filter-button.component.d.ts +20 -20
  567. package/lib/filter/ogc-filter-form/index.d.ts +1 -1
  568. package/lib/filter/ogc-filter-form/ogc-filter-form.component.d.ts +65 -65
  569. package/lib/filter/ogc-filter-selection/index.d.ts +1 -1
  570. package/lib/filter/ogc-filter-selection/ogc-filter-selection.component.d.ts +93 -93
  571. package/lib/filter/ogc-filter-time/index.d.ts +2 -2
  572. package/lib/filter/ogc-filter-time/ogc-filter-time-slider.component.d.ts +39 -39
  573. package/lib/filter/ogc-filter-time/ogc-filter-time.component.d.ts +86 -86
  574. package/lib/filter/ogc-filterable-form/index.d.ts +1 -1
  575. package/lib/filter/ogc-filterable-form/ogc-filterable-form.component.d.ts +15 -15
  576. package/lib/filter/ogc-filterable-item/index.d.ts +1 -1
  577. package/lib/filter/ogc-filterable-item/ogc-filterable-item.component.d.ts +41 -41
  578. package/lib/filter/ogc-filterable-list/index.d.ts +2 -2
  579. package/lib/filter/ogc-filterable-list/ogc-filterable-list-binding.directive.d.ts +14 -14
  580. package/lib/filter/ogc-filterable-list/ogc-filterable-list.component.d.ts +10 -10
  581. package/lib/filter/shared/filterable-datasource.pipe.d.ts +10 -10
  582. package/lib/filter/shared/index.d.ts +11 -11
  583. package/lib/filter/shared/ogc-filter-time.service.d.ts +19 -19
  584. package/lib/filter/shared/ogc-filter.d.ts +29 -29
  585. package/lib/filter/shared/ogc-filter.enum.d.ts +27 -27
  586. package/lib/filter/shared/ogc-filter.interface.d.ts +200 -200
  587. package/lib/filter/shared/ogc-filter.service.d.ts +11 -11
  588. package/lib/filter/shared/spatial-filter.enum.d.ts +19 -19
  589. package/lib/filter/shared/spatial-filter.interface.d.ts +10 -10
  590. package/lib/filter/shared/spatial-filter.service.d.ts +37 -37
  591. package/lib/filter/shared/time-filter.enum.d.ts +10 -10
  592. package/lib/filter/shared/time-filter.interface.d.ts +29 -29
  593. package/lib/filter/shared/time-filter.service.d.ts +11 -11
  594. package/lib/filter/spatial-filter/spatial-filter-item/index.d.ts +1 -1
  595. package/lib/filter/spatial-filter/spatial-filter-item/spatial-filter-item.component.d.ts +166 -166
  596. package/lib/filter/spatial-filter/spatial-filter-list/index.d.ts +1 -1
  597. package/lib/filter/spatial-filter/spatial-filter-list/spatial-filter-list.component.d.ts +58 -58
  598. package/lib/filter/spatial-filter/spatial-filter-type/index.d.ts +1 -1
  599. package/lib/filter/spatial-filter/spatial-filter-type/spatial-filter-type.component.d.ts +45 -45
  600. package/lib/filter/time-filter-button/index.d.ts +1 -1
  601. package/lib/filter/time-filter-button/time-filter-button.component.d.ts +20 -20
  602. package/lib/filter/time-filter-form/index.d.ts +1 -1
  603. package/lib/filter/time-filter-form/time-filter-form.component.d.ts +77 -77
  604. package/lib/filter/time-filter-item/index.d.ts +1 -1
  605. package/lib/filter/time-filter-item/time-filter-item.component.d.ts +28 -28
  606. package/lib/filter/time-filter-list/index.d.ts +2 -2
  607. package/lib/filter/time-filter-list/time-filter-list-binding.directive.d.ts +14 -14
  608. package/lib/filter/time-filter-list/time-filter-list.component.d.ts +12 -12
  609. package/lib/geo.module.d.ts +28 -28
  610. package/lib/geometry/geometry-form-field/geometry-form-field-input.component.d.ts +206 -206
  611. package/lib/geometry/geometry-form-field/geometry-form-field.component.d.ts +88 -88
  612. package/lib/geometry/geometry-form-field/geometry-form-field.module.d.ts +19 -19
  613. package/lib/geometry/geometry.module.d.ts +8 -8
  614. package/lib/geometry/index.d.ts +3 -3
  615. package/lib/geometry/shared/controls/draw.d.ts +150 -150
  616. package/lib/geometry/shared/controls/index.d.ts +3 -3
  617. package/lib/geometry/shared/controls/modify.d.ts +228 -228
  618. package/lib/geometry/shared/controls/slice.d.ts +99 -99
  619. package/lib/geometry/shared/geometry.errors.d.ts +11 -11
  620. package/lib/geometry/shared/geometry.interfaces.d.ts +13 -13
  621. package/lib/geometry/shared/geometry.utils.d.ts +45 -45
  622. package/lib/geometry/shared/index.d.ts +4 -4
  623. package/lib/import-export/export-button/export-button.component.d.ts +16 -16
  624. package/lib/import-export/export-button/index.d.ts +1 -1
  625. package/lib/import-export/import-export/import-export.component.d.ts +104 -104
  626. package/lib/import-export/import-export/index.d.ts +1 -1
  627. package/lib/import-export/import-export.module.d.ts +26 -26
  628. package/lib/import-export/index.d.ts +4 -4
  629. package/lib/import-export/shared/drop-geo-file.directive.d.ts +36 -36
  630. package/lib/import-export/shared/export.errors.d.ts +8 -8
  631. package/lib/import-export/shared/export.interface.d.ts +11 -11
  632. package/lib/import-export/shared/export.service.d.ts +30 -30
  633. package/lib/import-export/shared/export.type.d.ts +16 -16
  634. package/lib/import-export/shared/export.utils.d.ts +19 -19
  635. package/lib/import-export/shared/import.errors.d.ts +20 -20
  636. package/lib/import-export/shared/import.interface.d.ts +8 -8
  637. package/lib/import-export/shared/import.service.d.ts +31 -31
  638. package/lib/import-export/shared/import.utils.d.ts +18 -18
  639. package/lib/import-export/shared/index.d.ts +10 -10
  640. package/lib/import-export/style-list/index.d.ts +4 -4
  641. package/lib/import-export/style-list/style-list.interface.d.ts +6 -6
  642. package/lib/import-export/style-list/style-list.module.d.ts +8 -8
  643. package/lib/import-export/style-list/style-list.provider.d.ts +15 -15
  644. package/lib/import-export/style-list/style-list.service.d.ts +18 -18
  645. package/lib/layer/index.d.ts +10 -10
  646. package/lib/layer/layer-item/index.d.ts +1 -1
  647. package/lib/layer/layer-item/layer-item.component.d.ts +62 -62
  648. package/lib/layer/layer-legend/index.d.ts +1 -1
  649. package/lib/layer/layer-legend/layer-legend.component.d.ts +90 -90
  650. package/lib/layer/layer-legend-item/index.d.ts +1 -1
  651. package/lib/layer/layer-legend-item/layer-legend-item.component.d.ts +22 -22
  652. package/lib/layer/layer-legend-list/index.d.ts +2 -2
  653. package/lib/layer/layer-legend-list/layer-legend-list-binding.directive.d.ts +16 -16
  654. package/lib/layer/layer-legend-list/layer-legend-list.component.d.ts +31 -31
  655. package/lib/layer/layer-list/index.d.ts +3 -3
  656. package/lib/layer/layer-list/layer-list-binding.directive.d.ts +19 -19
  657. package/lib/layer/layer-list/layer-list.component.d.ts +127 -127
  658. package/lib/layer/layer-list/layer-list.enum.d.ts +15 -15
  659. package/lib/layer/layer-list-tool/index.d.ts +4 -4
  660. package/lib/layer/layer-list-tool/layer-list-tool.component.d.ts +32 -32
  661. package/lib/layer/layer-list-tool/layer-list-tool.enum.d.ts +5 -5
  662. package/lib/layer/layer-list-tool/layer-list-tool.interface.d.ts +8 -8
  663. package/lib/layer/layer-list-tool/layer-list-tool.service.d.ts +14 -14
  664. package/lib/layer/layer.module.d.ts +36 -36
  665. package/lib/layer/shared/clusterParam.d.ts +13 -13
  666. package/lib/layer/shared/index.d.ts +6 -6
  667. package/lib/layer/shared/layer.enums.d.ts +1 -1
  668. package/lib/layer/shared/layer.service.d.ts +30 -30
  669. package/lib/layer/shared/layers/any-layer.d.ts +6 -6
  670. package/lib/layer/shared/layers/any-layer.interface.d.ts +6 -6
  671. package/lib/layer/shared/layers/image-layer.d.ts +22 -22
  672. package/lib/layer/shared/layers/image-layer.interface.d.ts +19 -19
  673. package/lib/layer/shared/layers/index.d.ts +12 -12
  674. package/lib/layer/shared/layers/layer.d.ts +62 -62
  675. package/lib/layer/shared/layers/layer.interface.d.ts +109 -107
  676. package/lib/layer/shared/layers/tile-layer.d.ts +31 -31
  677. package/lib/layer/shared/layers/tile-layer.interface.d.ts +20 -20
  678. package/lib/layer/shared/layers/vector-layer.d.ts +78 -78
  679. package/lib/layer/shared/layers/vector-layer.interface.d.ts +41 -41
  680. package/lib/layer/shared/layers/vectortile-layer.d.ts +28 -28
  681. package/lib/layer/shared/layers/vectortile-layer.interface.d.ts +18 -18
  682. package/lib/layer/shared/style.service.d.ts +57 -57
  683. package/lib/layer/shared/vector-style.interface.d.ts +38 -38
  684. package/lib/layer/style-modal/index.d.ts +1 -1
  685. package/lib/layer/style-modal/style-modal.component.d.ts +42 -42
  686. package/lib/layer/track-feature-button/index.d.ts +1 -1
  687. package/lib/layer/track-feature-button/track-feature-button.component.d.ts +15 -15
  688. package/lib/layer/utils/image-watcher.d.ts +17 -17
  689. package/lib/layer/utils/index.d.ts +5 -5
  690. package/lib/layer/utils/layer.utils.d.ts +2 -2
  691. package/lib/layer/utils/outputLegend.d.ts +7 -7
  692. package/lib/layer/utils/tile-watcher.d.ts +14 -14
  693. package/lib/layer/utils/vector-watcher.d.ts +13 -13
  694. package/lib/map/baselayers-switcher/baselayers-switcher.animation.d.ts +2 -2
  695. package/lib/map/baselayers-switcher/baselayers-switcher.component.d.ts +21 -21
  696. package/lib/map/baselayers-switcher/index.d.ts +2 -2
  697. package/lib/map/baselayers-switcher/mini-basemap.component.d.ts +29 -29
  698. package/lib/map/geolocate-button/geolocate-button.component.d.ts +22 -22
  699. package/lib/map/geolocate-button/index.d.ts +1 -1
  700. package/lib/map/home-extent-button/home-extent-button.component.d.ts +20 -20
  701. package/lib/map/home-extent-button/index.d.ts +1 -1
  702. package/lib/map/index.d.ts +13 -13
  703. package/lib/map/info-section/index.d.ts +1 -1
  704. package/lib/map/info-section/info-section.component.d.ts +7 -7
  705. package/lib/map/map-browser/index.d.ts +1 -1
  706. package/lib/map/map-browser/map-browser.component.d.ts +25 -25
  707. package/lib/map/map-center/index.d.ts +1 -1
  708. package/lib/map/map-center/map-center.component.d.ts +31 -31
  709. package/lib/map/map.module.d.ts +28 -28
  710. package/lib/map/menu-button/index.d.ts +1 -1
  711. package/lib/map/menu-button/menu-button.component.d.ts +17 -17
  712. package/lib/map/offline-button/index.d.ts +1 -1
  713. package/lib/map/offline-button/offline-button.component.d.ts +23 -23
  714. package/lib/map/rotation-button/index.d.ts +1 -1
  715. package/lib/map/rotation-button/rotation-button.component.d.ts +17 -17
  716. package/lib/map/shared/controllers/controller.d.ts +29 -29
  717. package/lib/map/shared/controllers/geolocation.d.ts +112 -112
  718. package/lib/map/shared/controllers/index.d.ts +3 -3
  719. package/lib/map/shared/controllers/view.d.ts +200 -200
  720. package/lib/map/shared/hover-feature.directive.d.ts +132 -132
  721. package/lib/map/shared/index.d.ts +13 -13
  722. package/lib/map/shared/linkedLayers.utils.d.ts +17 -17
  723. package/lib/map/shared/map-pointer-position.directive.d.ts +71 -71
  724. package/lib/map/shared/map.d.ts +135 -135
  725. package/lib/map/shared/map.enums.d.ts +4 -4
  726. package/lib/map/shared/map.interface.d.ts +57 -57
  727. package/lib/map/shared/map.service.d.ts +19 -19
  728. package/lib/map/shared/map.utils.d.ts +90 -90
  729. package/lib/map/shared/mapOffline.directive.d.ts +21 -21
  730. package/lib/map/shared/projection.interfaces.d.ts +29 -29
  731. package/lib/map/shared/projection.service.d.ts +19 -19
  732. package/lib/map/shared/projection.utils.d.ts +19 -19
  733. package/lib/map/swipe-control/index.d.ts +1 -1
  734. package/lib/map/swipe-control/swipe-control.component.d.ts +97 -97
  735. package/lib/map/utils/layer-watcher.d.ts +20 -20
  736. package/lib/map/wake-lock-button/index.d.ts +1 -1
  737. package/lib/map/wake-lock-button/wake-lock-button.component.d.ts +30 -30
  738. package/lib/map/zoom-button/index.d.ts +1 -1
  739. package/lib/map/zoom-button/zoom-button.component.d.ts +12 -12
  740. package/lib/measure/index.d.ts +3 -3
  741. package/lib/measure/measure.module.d.ts +7 -7
  742. package/lib/measure/measurer/measure-format.pipe.d.ts +15 -15
  743. package/lib/measure/measurer/measurer-dialog.component.d.ts +14 -14
  744. package/lib/measure/measurer/measurer-item.component.d.ts +66 -66
  745. package/lib/measure/measurer/measurer.component.d.ts +405 -405
  746. package/lib/measure/measurer/measurer.module.d.ts +25 -25
  747. package/lib/measure/shared/index.d.ts +3 -3
  748. package/lib/measure/shared/measure.enum.d.ts +33 -33
  749. package/lib/measure/shared/measure.interfaces.d.ts +21 -21
  750. package/lib/measure/shared/measure.utils.d.ts +180 -180
  751. package/lib/metadata/index.d.ts +2 -2
  752. package/lib/metadata/metadata-button/index.d.ts +1 -1
  753. package/lib/metadata/metadata-button/metadata-button.component.d.ts +26 -26
  754. package/lib/metadata/metadata.module.d.ts +15 -15
  755. package/lib/metadata/shared/index.d.ts +2 -2
  756. package/lib/metadata/shared/metadata.interface.d.ts +13 -13
  757. package/lib/metadata/shared/metadata.service.d.ts +8 -8
  758. package/lib/offline/geoDB/configFileToGeoDB.service.d.ts +14 -14
  759. package/lib/offline/geoDB/geoDB.enums.d.ts +4 -4
  760. package/lib/offline/geoDB/geoDB.interface.d.ts +19 -19
  761. package/lib/offline/geoDB/geoDB.service.d.ts +37 -37
  762. package/lib/offline/geoDB/index.d.ts +4 -4
  763. package/lib/offline/index.d.ts +2 -2
  764. package/lib/offline/shared/geo-network.service.d.ts +28 -28
  765. package/lib/offline/shared/index.d.ts +1 -1
  766. package/lib/overlay/index.d.ts +1 -1
  767. package/lib/overlay/overlay.module.d.ts +9 -9
  768. package/lib/overlay/shared/index.d.ts +6 -6
  769. package/lib/overlay/shared/overlay-marker-style.utils.d.ts +11 -11
  770. package/lib/overlay/shared/overlay.d.ts +81 -81
  771. package/lib/overlay/shared/overlay.directive.d.ts +18 -18
  772. package/lib/overlay/shared/overlay.enum.d.ts +6 -6
  773. package/lib/overlay/shared/overlay.service.d.ts +14 -14
  774. package/lib/overlay/shared/overlay.utils.d.ts +17 -17
  775. package/lib/print/index.d.ts +3 -3
  776. package/lib/print/print/print.component.d.ts +35 -35
  777. package/lib/print/print-form/index.d.ts +1 -1
  778. package/lib/print/print-form/print-form.component.d.ts +97 -97
  779. package/lib/print/print.module.d.ts +19 -19
  780. package/lib/print/shared/geopdf.d.ts +1 -1
  781. package/lib/print/shared/index.d.ts +4 -4
  782. package/lib/print/shared/print.interface.d.ts +22 -22
  783. package/lib/print/shared/print.service.d.ts +168 -168
  784. package/lib/print/shared/print.type.d.ts +45 -45
  785. package/lib/query/index.d.ts +1 -1
  786. package/lib/query/query.module.d.ts +11 -11
  787. package/lib/query/shared/index.d.ts +6 -6
  788. package/lib/query/shared/query-search-source.d.ts +17 -17
  789. package/lib/query/shared/query-search-source.providers.d.ts +17 -17
  790. package/lib/query/shared/query.directive.d.ts +105 -105
  791. package/lib/query/shared/query.enums.d.ts +26 -26
  792. package/lib/query/shared/query.interfaces.d.ts +35 -35
  793. package/lib/query/shared/query.service.d.ts +56 -56
  794. package/lib/query/shared/query.utils.d.ts +27 -27
  795. package/lib/search/index.d.ts +11 -11
  796. package/lib/search/search-bar/search-bar.component.d.ts +230 -230
  797. package/lib/search/search-bar/search-bar.module.d.ts +23 -23
  798. package/lib/search/search-bar/search-url-param.directive.d.ts +13 -13
  799. package/lib/search/search-results/save-feature-dialog.component.d.ts +32 -32
  800. package/lib/search/search-results/search-results-add-button.component.d.ts +76 -76
  801. package/lib/search/search-results/search-results-item.component.d.ts +47 -47
  802. package/lib/search/search-results/search-results.component.d.ts +161 -161
  803. package/lib/search/search-results/search-results.module.d.ts +28 -28
  804. package/lib/search/search-selector/search-selector.component.d.ts +58 -58
  805. package/lib/search/search-selector/search-selector.module.d.ts +19 -19
  806. package/lib/search/search-settings/search-settings.component.d.ts +102 -102
  807. package/lib/search/search-settings/search-settings.module.d.ts +20 -20
  808. package/lib/search/search.module.d.ts +14 -14
  809. package/lib/search/shared/index.d.ts +8 -8
  810. package/lib/search/shared/search-pointer-summary.directive.d.ts +133 -133
  811. package/lib/search/shared/search-source-service.providers.d.ts +15 -15
  812. package/lib/search/shared/search-source.service.d.ts +32 -32
  813. package/lib/search/shared/search.enums.d.ts +1 -1
  814. package/lib/search/shared/search.interfaces.d.ts +29 -29
  815. package/lib/search/shared/search.service.d.ts +53 -53
  816. package/lib/search/shared/search.utils.d.ts +39 -39
  817. package/lib/search/shared/sources/coordinates.d.ts +40 -40
  818. package/lib/search/shared/sources/coordinates.interfaces.d.ts +12 -12
  819. package/lib/search/shared/sources/coordinates.providers.d.ts +31 -31
  820. package/lib/search/shared/sources/icherche.d.ts +96 -96
  821. package/lib/search/shared/sources/icherche.interfaces.d.ts +30 -30
  822. package/lib/search/shared/sources/icherche.providers.d.ts +46 -46
  823. package/lib/search/shared/sources/ilayer.d.ts +55 -55
  824. package/lib/search/shared/sources/ilayer.interfaces.d.ts +47 -47
  825. package/lib/search/shared/sources/ilayer.providers.d.ts +31 -31
  826. package/lib/search/shared/sources/index.d.ts +17 -17
  827. package/lib/search/shared/sources/nominatim.d.ts +45 -45
  828. package/lib/search/shared/sources/nominatim.interfaces.d.ts +10 -10
  829. package/lib/search/shared/sources/nominatim.providers.d.ts +18 -18
  830. package/lib/search/shared/sources/source.d.ts +108 -108
  831. package/lib/search/shared/sources/source.interfaces.d.ts +47 -47
  832. package/lib/search/shared/sources/storedqueries.d.ts +73 -73
  833. package/lib/search/shared/sources/storedqueries.interfaces.d.ts +42 -42
  834. package/lib/search/shared/sources/storedqueries.providers.d.ts +32 -32
  835. package/lib/toast/index.d.ts +1 -1
  836. package/lib/toast/toast.component.d.ts +33 -33
  837. package/lib/toast/toast.module.d.ts +14 -14
  838. package/lib/utils/commonVectorStyle.d.ts +14 -14
  839. package/lib/utils/commonVectorStyle.interface.d.ts +16 -16
  840. package/lib/utils/googleLinks.d.ts +5 -5
  841. package/lib/utils/id-generator.d.ts +54 -54
  842. package/lib/utils/index.d.ts +5 -5
  843. package/lib/utils/osmLinks.d.ts +4 -4
  844. package/lib/wkt/index.d.ts +1 -1
  845. package/lib/wkt/shared/index.d.ts +1 -1
  846. package/lib/wkt/shared/wkt.service.d.ts +19 -19
  847. package/lib/wkt/wkt.module.d.ts +8 -8
  848. package/lib/workspace/confirmation-popup/confirmation-popup.component.d.ts +23 -23
  849. package/lib/workspace/confirmation-popup/confirmation-popup.module.d.ts +14 -14
  850. package/lib/workspace/confirmation-popup/index.d.ts +2 -2
  851. package/lib/workspace/index.d.ts +7 -7
  852. package/lib/workspace/shared/edition-workspace.d.ts +82 -82
  853. package/lib/workspace/shared/edition-workspace.service.d.ts +52 -52
  854. package/lib/workspace/shared/feature-workspace.d.ts +18 -18
  855. package/lib/workspace/shared/feature-workspace.service.d.ts +19 -19
  856. package/lib/workspace/shared/index.d.ts +7 -7
  857. package/lib/workspace/shared/wfs-workspace.d.ts +18 -18
  858. package/lib/workspace/shared/wfs-workspace.service.d.ts +19 -19
  859. package/lib/workspace/shared/wms-workspace.service.d.ts +22 -22
  860. package/lib/workspace/shared/workspace.utils.d.ts +10 -10
  861. package/lib/workspace/widgets/index.d.ts +3 -3
  862. package/lib/workspace/widgets/ogc-filter/ogc-filter.component.d.ts +29 -29
  863. package/lib/workspace/widgets/ogc-filter/ogc-filter.module.d.ts +14 -14
  864. package/lib/workspace/widgets/widgets.d.ts +9 -9
  865. package/lib/workspace/workspace-selector/workspace-selector.directive.d.ts +32 -32
  866. package/lib/workspace/workspace-selector/workspace-selector.module.d.ts +11 -11
  867. package/lib/workspace/workspace-updator/workspace-updator.directive.d.ts +26 -26
  868. package/lib/workspace/workspace-updator/workspace-updator.module.d.ts +11 -11
  869. package/lib/workspace/workspace.module.d.ts +14 -14
  870. package/package.json +4 -4
  871. package/public_api.d.ts +51 -51
@@ -1,934 +1,934 @@
1
- import { Injectable } from '@angular/core';
2
- import { Observable, Subject, forkJoin } from 'rxjs';
3
- import { map as rxMap } from 'rxjs/operators';
4
- import { saveAs } from 'file-saver';
5
- import jsPDF from 'jspdf';
6
- import html2canvas from 'html2canvas';
7
- import { default as JSZip } from 'jszip';
8
- import { SubjectStatus } from '@igo2/utils';
9
- import { SecureImagePipe } from '@igo2/common';
10
- import { formatScale } from '../../map/shared/map.utils';
11
- import { getLayersLegends } from '../../layer/utils/outputLegend';
12
- import GeoPdfPlugin from './geopdf';
13
- import * as i0 from "@angular/core";
14
- import * as i1 from "@angular/common/http";
15
- import * as i2 from "@igo2/core";
16
- export class PrintService {
17
- constructor(http, messageService, activityService, languageService, configService) {
18
- this.http = http;
19
- this.messageService = messageService;
20
- this.activityService = activityService;
21
- this.languageService = languageService;
22
- this.configService = configService;
23
- this.TEXTPDFFONT = {
24
- titleFont: 'Times',
25
- titleFontStyle: 'bold',
26
- subtitleFont: 'Times',
27
- subtitleFontStyle: 'bold',
28
- commentFont: 'courier',
29
- commentFontStyle: 'normal',
30
- commentFontSize: 16
31
- };
32
- }
33
- print(map, options) {
34
- const status$ = new Subject();
35
- const paperFormat = options.paperFormat;
36
- const resolution = +options.resolution; // Default is 96
37
- const orientation = options.orientation;
38
- const legendPostion = options.legendPosition;
39
- this.activityId = this.activityService.register();
40
- GeoPdfPlugin(jsPDF.API);
41
- const doc = new jsPDF({
42
- orientation,
43
- format: paperFormat.toLowerCase(),
44
- unit: 'mm' // default
45
- });
46
- const dimensions = [
47
- doc.internal.pageSize.width,
48
- doc.internal.pageSize.height
49
- ];
50
- const margins = [10, 10, 10, 10];
51
- const width = dimensions[0] - margins[3] - margins[1];
52
- const height = dimensions[1] - margins[0] - margins[2];
53
- const size = [width, height];
54
- let titleSizes;
55
- let subtitleSizes;
56
- // PDF title
57
- if (options.title !== undefined) {
58
- const fontSizeInPt = Math.round(2 * (height + 145) * 0.05) / 2; //calculate the fontSize title from the page height.
59
- titleSizes = this.getTextPdfObjectSizeAndMarg(options.title, margins, this.TEXTPDFFONT.titleFont, fontSizeInPt, this.TEXTPDFFONT.titleFontStyle, doc);
60
- this.addTextInPdfDoc(doc, options.title, this.TEXTPDFFONT.titleFont, this.TEXTPDFFONT.titleFontStyle, titleSizes.fontSize, titleSizes.marginLeft + margins[3], margins[0]);
61
- margins[0] = titleSizes.height + margins[0]; // cumulative margin top for next elem to place in pdf doc
62
- }
63
- // PDF subtitle
64
- if (options.subtitle !== undefined) {
65
- subtitleSizes = this.getTextPdfObjectSizeAndMarg(options.subtitle, margins, this.TEXTPDFFONT.subtitleFont, titleSizes.fontSize * 0.7, // 70% size of title
66
- this.TEXTPDFFONT.subtitleFontStyle, doc);
67
- this.addTextInPdfDoc(doc, options.subtitle, this.TEXTPDFFONT.subtitleFont, this.TEXTPDFFONT.subtitleFontStyle, subtitleSizes.fontSize, subtitleSizes.marginLeft + margins[3], margins[0]);
68
- margins[0] += 5; // cumulative marg top for next elem to place in pdf doc. 5 is a fix it could be adjust
69
- }
70
- if (options.showProjection === true || options.showScale === true) {
71
- this.addProjScale(doc, map, resolution, options.showProjection, options.showScale);
72
- }
73
- if (options.comment !== '') {
74
- this.addComment(doc, options.comment);
75
- }
76
- this.addMap(doc, map, resolution, size, margins).subscribe(async (status) => {
77
- if (status === SubjectStatus.Done) {
78
- await this.addScale(doc, map, margins);
79
- await this.handleMeasureLayer(doc, map, margins);
80
- const width = this.imgSizeAdded[0];
81
- const height = this.imgSizeAdded[1];
82
- const res = 1;
83
- this.addGeoRef(doc, map, width, height, res, margins);
84
- if (options.legendPosition !== 'none') {
85
- if (['topleft', 'topright', 'bottomleft', 'bottomright'].indexOf(options.legendPosition) > -1) {
86
- await this.addLegendSamePage(doc, map, margins, resolution, options.legendPosition);
87
- }
88
- else if (options.legendPosition === 'newpage') {
89
- await this.addLegend(doc, map, margins, resolution);
90
- }
91
- }
92
- else {
93
- await this.saveDoc(doc);
94
- }
95
- }
96
- if (status === SubjectStatus.Done || status === SubjectStatus.Error) {
97
- this.activityService.unregister(this.activityId);
98
- status$.next(SubjectStatus.Done);
99
- }
100
- });
101
- return status$;
102
- }
103
- // ref GeoMoose https://github.com/geomoose/gm3/tree/main/src/gm3/components/print
104
- addGeoRef(doc, map, width, height, resolution, margins) {
105
- const unit = 'mm';
106
- const docHeight = doc.internal.pageSize.getHeight();
107
- // x,y = margin left-bottom corner for img in pdf doc
108
- const x = margins[3];
109
- const y = docHeight - margins[0] - height;
110
- let pdf_extents = [x, y, x + width, y + height];
111
- for (let i = 0; i < pdf_extents.length; i++) {
112
- pdf_extents[i] = this.pdf_units2points(pdf_extents[i], unit);
113
- }
114
- const mapExtent = map.viewController.getExtent('EPSG:3857');
115
- doc.setGeoArea(pdf_extents, mapExtent);
116
- }
117
- /**
118
- * Add measure overlay on the map on the document when the measure layer is present
119
- * @param doc - Pdf document where measure tooltip will be added
120
- * @param map - Map of the app
121
- * @param margins - Page margins
122
- */
123
- async handleMeasureLayer(doc, map, margins) {
124
- if (map.layers.find(layer => layer.visible && layer.id.startsWith('igo-measures-'))) {
125
- let canvasOverlayHTMLMeasures;
126
- const mapOverlayMeasuresHTML = map.ol.getOverlayContainer();
127
- await html2canvas(mapOverlayMeasuresHTML, {
128
- scale: 1,
129
- backgroundColor: null
130
- }).then(e => {
131
- canvasOverlayHTMLMeasures = e;
132
- });
133
- this.addCanvas(doc, canvasOverlayHTMLMeasures, margins); // this adds measure overlays
134
- }
135
- }
136
- /**
137
- * Get html code for all layers legend
138
- * @param map IgoMap
139
- * @param width The width that the legend need to be
140
- * @return Html code for the legend
141
- */
142
- getLayersLegendHtml(map, width, resolution) {
143
- return new Observable((observer) => {
144
- let html = '';
145
- const legends = getLayersLegends(map.layers, {
146
- resolution: map.viewController.getResolution(),
147
- extent: map.viewController.getExtent(),
148
- projection: map.viewController.getOlProjection().getCode(),
149
- // scale: map.viewController.getScale(resolution),
150
- size: map.ol.getSize()
151
- });
152
- if (legends.filter(l => l.display === true).length === 0) {
153
- observer.next(html);
154
- observer.complete();
155
- return;
156
- }
157
- // Define important style to be sure that all container is convert
158
- // to image not just visible part
159
- html += '<style media="screen" type="text/css">';
160
- html += '.html2canvas-container { width: ' + width + 'mm !important; height: 2000px !important; }';
161
- html += 'table.tableLegend {table-layout: auto;}';
162
- html += 'div.styleLegend {padding-top: 5px; padding-right:5px;padding-left:5px;padding-bottom:5px;}';
163
- html += '</style>';
164
- // The font size will also be lowered afterwards (globally along the legend size)
165
- // this allows having a good relative font size here and to keep ajusting the legend size
166
- // while keeping good relative font size
167
- html += '<font size="3" face="Times" >';
168
- html += '<div class="styleLegend">';
169
- html += '<table class="tableLegend" >';
170
- // For each legend, define an html table cell
171
- const images$ = legends.filter(l => l.display).map((legend) => this.getDataImage(legend.url).pipe(rxMap((dataImage) => {
172
- let htmlImg = '<tr><td>' + legend.title.toUpperCase() + '</td></tr>';
173
- htmlImg += '<tr><td><img src="' + dataImage + '"></td></tr>';
174
- return htmlImg;
175
- })));
176
- forkJoin(images$).subscribe((dataImages) => {
177
- html = dataImages.reduce((acc, current) => (acc += current), html);
178
- html += '</table>';
179
- html += '</div>';
180
- observer.next(html);
181
- observer.complete();
182
- });
183
- });
184
- }
185
- getDataImage(url) {
186
- const secureIMG = new SecureImagePipe(this.http, this.configService);
187
- return secureIMG.transform(url);
188
- }
189
- /**
190
- * Get all the legend in a single image
191
- * * @param format - Image format. default value to "png"
192
- * @return The image of the legend
193
- */
194
- async getLayersLegendImage(map, format = 'png', doZipFile, resolution) {
195
- const status$ = new Subject();
196
- // Get html code for the legend
197
- const width = 200; // milimeters unit, originally define for document pdf
198
- let html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
199
- format = format.toLowerCase();
200
- // If no legend show No LEGEND in an image
201
- if (html.length === 0) {
202
- html = '<font size="12" face="Courier New" >';
203
- html += '<div align="center"><b>NO LEGEND</b></div>';
204
- }
205
- // Create div to contain html code for legend
206
- const div = window.document.createElement('div');
207
- div.style.position = 'absolute';
208
- div.style.top = '0';
209
- // Add html code to convert in the new window
210
- window.document.body.appendChild(div);
211
- div.innerHTML = html;
212
- await this.timeout(1);
213
- const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
214
- console.log(e);
215
- });
216
- if (canvas) {
217
- let status = SubjectStatus.Done;
218
- try {
219
- if (!doZipFile) {
220
- // Save the canvas as file
221
- this.saveCanvasImageAsFile(canvas, 'legendImage', format);
222
- }
223
- else {
224
- // Add the canvas to zip
225
- this.generateCanvaFileToZip(canvas, 'legendImage' + '.' + format);
226
- }
227
- div.parentNode.removeChild(div); // remove temp div (IE)
228
- }
229
- catch (err) {
230
- status = SubjectStatus.Error;
231
- }
232
- status$.next(status);
233
- }
234
- return status$;
235
- }
236
- getTextPdfObjectSizeAndMarg(text, margins, font, fontSizeInPt, fontStyle, doc) {
237
- const pdfResolution = 96;
238
- const docWidth = doc.internal.pageSize.getWidth();
239
- const pageWidth = docWidth - margins[1] - margins[3];
240
- // important to set it first, the textDimension change when font change!
241
- doc.setFont(font, fontStyle);
242
- doc.setFontSize(fontSizeInPt);
243
- let textDimensions = doc.getTextDimensions(text);
244
- let textMarginLeft;
245
- if (textDimensions.w > pageWidth) {
246
- // if the text is to long, reduce fontSize 70% and the overflow with be cut in print...
247
- textMarginLeft = 0;
248
- fontSizeInPt = fontSizeInPt * 0.7;
249
- doc.setFontSize(fontSizeInPt);
250
- textDimensions = doc.getTextDimensions(text);
251
- }
252
- else {
253
- textMarginLeft = (pageWidth - textDimensions.w) / 2;
254
- }
255
- return {
256
- 'fontSize': fontSizeInPt,
257
- 'marginLeft': textMarginLeft,
258
- 'height': textDimensions.h
259
- };
260
- }
261
- /**
262
- * Add comment to the document
263
- * * @param doc - pdf document
264
- * * @param comment - Comment to add in the document
265
- */
266
- addComment(doc, comment) {
267
- const commentMarginLeft = 20; //margin left and bottom is fix
268
- const commentMarginBottom = 5;
269
- const marginTop = doc.internal.pageSize.height - commentMarginBottom;
270
- this.addTextInPdfDoc(doc, comment, this.TEXTPDFFONT.commentFont, this.TEXTPDFFONT.commentFontStyle, this.TEXTPDFFONT.commentFontSize, commentMarginLeft, marginTop);
271
- }
272
- addTextInPdfDoc(doc, textToAdd, textFont, textFontStyle, textFontSize, textMarginLeft, textMarginTop) {
273
- doc.setFont(textFont, textFontStyle);
274
- doc.setFontSize(textFontSize);
275
- doc.text(textToAdd, textMarginLeft, textMarginTop);
276
- }
277
- /**
278
- * Add projection and/or scale to the document
279
- * @param doc - pdf document
280
- * @param map - Map of the app
281
- * @param dpi - DPI resolution of the document
282
- * @param projection - Bool to indicate if projection need to be added
283
- * @param scale - Bool to indicate if scale need to be added
284
- */
285
- addProjScale(doc, map, dpi, projection, scale) {
286
- const translate = this.languageService.translate;
287
- const projScaleSize = 16;
288
- const projScaleMarginLeft = 20;
289
- const marginBottom = 15;
290
- const heightPixels = doc.internal.pageSize.height - marginBottom;
291
- let textProjScale = '';
292
- if (projection === true) {
293
- const projText = translate.instant('igo.geo.printForm.projection');
294
- textProjScale += projText + ': ' + map.projection;
295
- }
296
- if (scale === true) {
297
- if (projection === true) {
298
- textProjScale += ' ';
299
- }
300
- const scaleText = translate.instant('igo.geo.printForm.scale');
301
- const mapScale = map.viewController.getScale(dpi);
302
- textProjScale += scaleText + ': ~ 1 / ' + formatScale(mapScale);
303
- }
304
- doc.setFont('courier');
305
- doc.setFontSize(projScaleSize);
306
- doc.text(textProjScale, projScaleMarginLeft, heightPixels);
307
- }
308
- /**
309
- * Add the legend to the document
310
- * @param doc - Pdf document where legend will be added
311
- * @param map - Map of the app
312
- * @param margins - Page margins
313
- */
314
- async addLegend(doc, map, margins, resolution) {
315
- // Get html code for the legend
316
- const width = doc.internal.pageSize.width;
317
- const html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
318
- // If no legend, save the map directly
319
- if (html === '') {
320
- await this.saveDoc(doc);
321
- return true;
322
- }
323
- // Create div to contain html code for legend
324
- const div = window.document.createElement('div');
325
- div.style.position = 'absolute';
326
- div.style.top = '0';
327
- // Add html code to convert in the new window
328
- window.document.body.appendChild(div);
329
- div.innerHTML = html;
330
- await this.timeout(1);
331
- const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
332
- console.log(e);
333
- });
334
- if (canvas) {
335
- const pourcentageReduction = 0.85;
336
- const imageSize = [pourcentageReduction * (25.4 * canvas.width) / resolution, pourcentageReduction
337
- * (25.4 * canvas.height) / resolution];
338
- let imgData;
339
- doc.addPage();
340
- imgData = canvas.toDataURL('image/png');
341
- doc.addImage(imgData, 'PNG', 10, 10, imageSize[0], imageSize[1]);
342
- div.parentNode.removeChild(div); // remove temp div (IE style)
343
- }
344
- await this.saveDoc(doc);
345
- }
346
- /**
347
- * Add the legend to the document
348
- * @param doc - Pdf document where legend will be added
349
- * @param map - Map of the app
350
- * @param margins - Page margins
351
- */
352
- async addLegendSamePage(doc, map, margins, resolution, legendPosition) {
353
- // Get html code for the legend
354
- const width = doc.internal.pageSize.width;
355
- const html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
356
- // If no legend, save the map directly
357
- if (html === '') {
358
- await this.saveDoc(doc);
359
- return true;
360
- }
361
- // Create div to contain html code for legend
362
- const div = window.document.createElement('div');
363
- div.style.position = 'absolute';
364
- div.style.top = '0';
365
- // Add html code to convert in the new window
366
- window.document.body.appendChild(div);
367
- div.innerHTML = html;
368
- await this.timeout(1);
369
- const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
370
- console.log(e);
371
- });
372
- let marginsLegend;
373
- if (canvas) {
374
- const pourcentageReduction = 0.85;
375
- const imageSize = [pourcentageReduction * (25.4 * canvas.width) / resolution,
376
- pourcentageReduction * (25.4 * canvas.height) / resolution];
377
- // Move the legend to the correct position on the page
378
- if (legendPosition === 'bottomright') {
379
- marginsLegend = [doc.internal.pageSize.height - margins[2] - imageSize[1], margins[1],
380
- margins[2], doc.internal.pageSize.width - margins[1] - imageSize[0]];
381
- }
382
- else if (legendPosition === 'topright') {
383
- marginsLegend = [margins[0], margins[1], doc.internal.pageSize.height - margins[0] - imageSize[1],
384
- doc.internal.pageSize.width - margins[1] - imageSize[0]];
385
- }
386
- else if (legendPosition === 'bottomleft') {
387
- // When the legend is in the bottom left, raise the legend slightly upward so that attributions are visible
388
- marginsLegend = [doc.internal.pageSize.height - margins[2] - imageSize[1] - 15,
389
- doc.internal.pageSize.width - margins[3] - imageSize[0], margins[2] + 15, margins[3]];
390
- }
391
- else if (legendPosition === 'topleft') {
392
- marginsLegend = [margins[0], doc.internal.pageSize.width - margins[3] - imageSize[0],
393
- doc.internal.pageSize.height - margins[0] - imageSize[1], margins[3]];
394
- }
395
- this.addCanvas(doc, canvas, marginsLegend); // this adds the legend
396
- div.parentNode.removeChild(div); // remove temp div (IE style)
397
- await this.saveDoc(doc);
398
- }
399
- }
400
- /**
401
- * Add scale and attributions on the map on the document
402
- * @param doc - Pdf document where legend will be added
403
- * @param map - Map of the app
404
- * @param margins - Page margins
405
- */
406
- async addScale(doc, map, margins) {
407
- const mapSize = map.ol.getSize();
408
- const extent = map.ol.getView().calculateExtent(mapSize);
409
- // Get the scale and attribution
410
- // we use cloneNode to modify the nodes to print without modifying it on the page, using deep:true to get children
411
- let canvasOverlayHTML;
412
- const mapOverlayHTML = map.ol.getOverlayContainerStopEvent();
413
- // Remove the UI buttons from the nodes
414
- const OverlayHTMLButtons = mapOverlayHTML.getElementsByTagName('button');
415
- const OverlayHTMLButtonsarr = Array.from(OverlayHTMLButtons);
416
- for (const OverlayHTMLButton of OverlayHTMLButtonsarr) {
417
- OverlayHTMLButton.setAttribute('data-html2canvas-ignore', 'true');
418
- }
419
- // Change the styles of hyperlink in the printed version
420
- // Transform the Overlay into a canvas
421
- // scale is necessary to make it in google chrome
422
- // background as null because otherwise it is white and cover the map
423
- // allowtaint is to allow rendering images in the attributions
424
- // useCORS: true pour permettre de renderer les images (ne marche pas en local)
425
- const canvas = await html2canvas(mapOverlayHTML, {
426
- scale: 1,
427
- backgroundColor: null,
428
- allowTaint: true,
429
- useCORS: true,
430
- }).then(e => {
431
- canvasOverlayHTML = e;
432
- });
433
- this.addCanvas(doc, canvasOverlayHTML, margins); // this adds scales and attributions
434
- }
435
- defineNbFileToProcess(nbFileToProcess) {
436
- this.nbFileToProcess = nbFileToProcess;
437
- }
438
- timeout(ms) {
439
- return new Promise((resolve) => setTimeout(resolve, ms));
440
- }
441
- addCanvas(doc, canvas, margins) {
442
- let image;
443
- if (canvas) {
444
- image = canvas.toDataURL('image/png');
445
- }
446
- if (image !== undefined) {
447
- if (image.length < 20) { // img is corrupt todo: fix addScale in mobile make a corrupt img
448
- console.log('Warning: An image cannot be print in pdf file');
449
- return;
450
- }
451
- const imageSize = this.getImageSizeToFitPdf(doc, canvas, margins);
452
- doc.addImage(image, 'PNG', margins[3], margins[0], imageSize[0], imageSize[1]);
453
- doc.rect(margins[3], margins[0], imageSize[0], imageSize[1]);
454
- this.imgSizeAdded = imageSize; // keep img size for georef later
455
- }
456
- }
457
- // TODO fix printing with image resolution
458
- addMap(doc, map, resolution, size, margins) {
459
- const status$ = new Subject();
460
- const mapSize = map.ol.getSize();
461
- const extent = map.ol.getView().calculateExtent(mapSize);
462
- const widthPixels = Math.round((size[0] * resolution) / 25.4);
463
- const heightPixels = Math.round((size[1] * resolution) / 25.4);
464
- let timeout;
465
- map.ol.once('rendercomplete', (event) => {
466
- const canvases = event.target.getViewport().getElementsByTagName('canvas');
467
- const mapStatus$$ = map.status$.subscribe((mapStatus) => {
468
- clearTimeout(timeout);
469
- if (mapStatus !== SubjectStatus.Done) {
470
- return;
471
- }
472
- mapStatus$$.unsubscribe();
473
- let status = SubjectStatus.Done;
474
- try {
475
- for (const canvas of canvases) {
476
- if (canvas.width !== 0) {
477
- this.addCanvas(doc, canvas, margins);
478
- }
479
- }
480
- }
481
- catch (err) {
482
- status = SubjectStatus.Error;
483
- this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
484
- }
485
- this.renderMap(map, mapSize, extent);
486
- status$.next(status);
487
- });
488
- // If no loading as started after 200ms, then probably no loading
489
- // is required.
490
- timeout = window.setTimeout(() => {
491
- mapStatus$$.unsubscribe();
492
- let status = SubjectStatus.Done;
493
- try {
494
- for (const canvas of canvases) {
495
- if (canvas.width !== 0) {
496
- this.addCanvas(doc, canvas, margins);
497
- }
498
- }
499
- }
500
- catch (err) {
501
- status = SubjectStatus.Error;
502
- this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
503
- }
504
- this.renderMap(map, mapSize, extent);
505
- status$.next(status);
506
- }, 200);
507
- });
508
- this.renderMap(map, [widthPixels, heightPixels], extent);
509
- return status$;
510
- }
511
- /**
512
- * Download an image of the map with addition of informations
513
- * @param map - Map of the app
514
- * @param format - Image format. default value to "png"
515
- * @param projection - Indicate if projection need to be add. Default to false
516
- * @param scale - Indicate if scale need to be add. Default to false
517
- * @param legend - Indicate if the legend of layers need to be download. Default to false
518
- * @param title - Title to add for the map - Default to blank
519
- * @param subtitle - Subtitle to add for the map - Default to blank
520
- * @param comment - Comment to add for the map - Default to blank
521
- * @param doZipFile - Indicate if we do a zip with the file
522
- * @return Image file of the map with extension format given as parameter
523
- */
524
- downloadMapImage(map, resolution, format = 'png', projection = false, scale = false, title = '', subtitle = '', comment = '', doZipFile = true, legendPosition) {
525
- const status$ = new Subject();
526
- // const resolution = map.ol.getView().getResolution();
527
- this.activityId = this.activityService.register();
528
- const translate = this.languageService.translate;
529
- map.ol.once('rendercomplete', async (event) => {
530
- format = format.toLowerCase();
531
- const oldCanvas = event.target
532
- .getViewport()
533
- .getElementsByTagName('canvas')[0];
534
- const newCanvas = document.createElement('canvas');
535
- const newContext = newCanvas.getContext('2d');
536
- // Postion in height to set the canvas in new canvas
537
- let positionHCanvas = 0;
538
- // Get height/width of map canvas
539
- const width = oldCanvas.width;
540
- let height = oldCanvas.height;
541
- // Set Font to calculate comment width
542
- newContext.font = '20px Calibri';
543
- const commentWidth = newContext.measureText(comment).width;
544
- // Add height for title if defined
545
- height = title !== '' ? height + 30 : height;
546
- // Add height for title if defined
547
- height = subtitle !== '' ? height + 30 : height;
548
- // Add height for projection or scale (same line) if defined
549
- height = projection !== false || scale !== false ? height + 30 : height;
550
- const positionHProjScale = height - 10;
551
- // Define number of line depending of the comment length
552
- const commentNbLine = Math.ceil(commentWidth / width);
553
- // Add height for multiline comment if defined
554
- height = comment !== '' ? height + commentNbLine * 30 : height;
555
- let positionHComment = height - commentNbLine * 20 + 5;
556
- // Set the new canvas with the new calculated size
557
- newCanvas.width = width;
558
- newCanvas.height = height;
559
- if (['bmp', 'gif', 'jpeg', 'png', 'tiff'].indexOf(format) > -1) {
560
- // Patch Jpeg default black background to white
561
- if (format === 'jpeg') {
562
- newContext.fillStyle = '#ffffff';
563
- newContext.fillRect(0, 0, width, height);
564
- newContext.fillStyle = '#000000';
565
- }
566
- else if (title !== '' || subtitle !== '' || comment !== '' ||
567
- projection !== false || scale !== false) {
568
- newContext.fillStyle = '#ffffff';
569
- newContext.fillRect(0, 0, width, height);
570
- newContext.fillStyle = '#000000';
571
- }
572
- }
573
- // If a title need to be added to canvas
574
- if (title !== '') {
575
- // Set font for title
576
- // Adjust according to title length
577
- newContext.font = '26px Calibri';
578
- positionHCanvas = 30;
579
- newContext.textAlign = 'center';
580
- newContext.fillText(title, width / 2, 20, width * 0.9);
581
- }
582
- if (subtitle !== '') {
583
- // Set font for subtitle
584
- // Adjust according to title length
585
- newContext.font = '26px Calibri';
586
- positionHCanvas = 60;
587
- newContext.textAlign = 'center';
588
- newContext.fillText(subtitle, width / 2, 50, width * 0.9);
589
- }
590
- // Set font for next section
591
- newContext.font = '20px Calibri';
592
- // If projection or/end scale need to be added to canvas
593
- if ((projection !== false) || (scale !== false)) {
594
- let projectionScaleText = '';
595
- if (projection !== false) {
596
- const projText = translate.instant('igo.geo.printForm.projection');
597
- projectionScaleText = projText + ': ' + map.projection + ' ';
598
- }
599
- if (scale !== false) {
600
- const scaleText = translate.instant('igo.geo.printForm.scale');
601
- const mapScale = map.viewController.getScale(resolution);
602
- projectionScaleText += scaleText + ': ~ 1 / ' + formatScale(mapScale);
603
- }
604
- newContext.textAlign = 'center';
605
- newContext.fillText(projectionScaleText, width / 2, positionHProjScale, width * 0.9);
606
- }
607
- // If a comment need to be added to canvas
608
- if (comment !== '') {
609
- newContext.textAlign = 'center';
610
- // If only one line, no need to multiline the comment
611
- if (commentNbLine === 1) {
612
- newContext.fillText(comment, width / 2, positionHComment);
613
- }
614
- else {
615
- // Separate the setenses to be approx. the same length
616
- const nbCommentChar = comment.length;
617
- const CommentLengthToCut = Math.floor(nbCommentChar / commentNbLine);
618
- let commentCurrentLine = '';
619
- let positionFirstCutChar = 0;
620
- let positionLastBlank;
621
- // Loop for the number of line calculated
622
- for (let i = 0; i < commentNbLine; i++) {
623
- // For all line except last
624
- if (commentNbLine - 1 > i) {
625
- // Get comment current line to find the right place tu cut comment
626
- commentCurrentLine = comment.substr(positionFirstCutChar, CommentLengthToCut);
627
- // Cut the setence at blank
628
- positionLastBlank = commentCurrentLine.lastIndexOf(' ');
629
- newContext.fillText(commentCurrentLine.substr(0, positionLastBlank), width / 2, positionHComment);
630
- positionFirstCutChar += positionLastBlank;
631
- // Go to next line for insertion
632
- positionHComment += 20;
633
- }
634
- else {
635
- // Don't cut last part
636
- newContext.fillText(comment.substr(positionFirstCutChar), width / 2, positionHComment);
637
- }
638
- }
639
- }
640
- }
641
- // Add map to new canvas
642
- newContext.drawImage(oldCanvas, 0, positionHCanvas);
643
- // Check the legendPosition
644
- if (legendPosition !== 'none') {
645
- if (['topleft', 'topright', 'bottomleft', 'bottomright'].indexOf(legendPosition) > -1) {
646
- await this.addLegendToImage(newCanvas, map, resolution, legendPosition, format);
647
- }
648
- }
649
- let status = SubjectStatus.Done;
650
- let fileNameWithExt = 'map.' + format;
651
- if (format.toLowerCase() === 'tiff') {
652
- fileNameWithExt = 'map' + map.projection.replace(':', '_') + '.' + format;
653
- }
654
- try {
655
- // Save the canvas as file
656
- if (!doZipFile) {
657
- this.saveCanvasImageAsFile(newCanvas, fileNameWithExt, format);
658
- }
659
- else if (format.toLowerCase() === 'tiff') {
660
- // Add the canvas to zip
661
- this.generateCanvaFileToZip(newCanvas, fileNameWithExt);
662
- }
663
- else {
664
- // Add the canvas to zip
665
- this.generateCanvaFileToZip(newCanvas, fileNameWithExt);
666
- }
667
- }
668
- catch (err) {
669
- status = SubjectStatus.Error;
670
- }
671
- status$.next(status);
672
- if (format.toLowerCase() === 'tiff') {
673
- const tfwFileNameWithExt = fileNameWithExt.substring(0, fileNameWithExt.toLowerCase().indexOf('.tiff')) + '.tfw';
674
- const tiwContent = this.getWorldFileInformation(map);
675
- const blob = new Blob([tiwContent], {
676
- type: 'text/plain;charset=utf-8'
677
- });
678
- if (!doZipFile) {
679
- // saveAs automaticly replace ':' for '_'
680
- saveAs(blob, tfwFileNameWithExt);
681
- this.saveFileProcessing();
682
- }
683
- else {
684
- // Add the canvas to zip
685
- this.addFileToZip(tfwFileNameWithExt, blob);
686
- }
687
- }
688
- });
689
- map.ol.renderSync();
690
- return status$;
691
- }
692
- /**
693
- * Create and Add Legend to the map canvas
694
- * @param canvas Canvas of the map
695
- * @param map Map of the app
696
- * @param resolution Resolution of map
697
- * @param legendPosition Legend position
698
- * @param format Image format
699
- */
700
- async addLegendToImage(canvas, map, resolution, legendPosition, format) {
701
- const fileNameWithExt = 'map.' + format;
702
- const context = canvas.getContext('2d');
703
- // Get html code for the legend
704
- const html = await this.getLayersLegendHtml(map, canvas.width, resolution).toPromise();
705
- // If no legend, save the map directly
706
- if (html === '') {
707
- await this.saveCanvasImageAsFile(canvas, fileNameWithExt, format);
708
- return true;
709
- }
710
- // Create div to contain html code for legend
711
- const div = window.document.createElement('div');
712
- div.style.position = 'absolute';
713
- div.style.top = '0';
714
- // Add html code to convert in the new window
715
- window.document.body.appendChild(div);
716
- div.innerHTML = html;
717
- await this.timeout(1);
718
- const canvasLegend = await html2canvas(div, { useCORS: true }).catch((e) => {
719
- console.log(e);
720
- });
721
- if (canvasLegend) {
722
- const canvasHeight = canvas.height;
723
- const canvasWidth = canvas.width;
724
- const legendHeight = canvasLegend.height;
725
- const legendWidth = canvasLegend.width;
726
- // Move the legend to the correct position on the page
727
- const offset = canvasHeight * 0.01;
728
- let legendX;
729
- let legendY;
730
- if (legendPosition === 'bottomright') {
731
- legendX = canvasWidth - legendWidth - offset;
732
- legendY = canvasHeight - legendHeight - offset;
733
- }
734
- else if (legendPosition === 'topright') {
735
- legendX = canvasWidth - legendWidth - offset;
736
- legendY = offset;
737
- }
738
- else if (legendPosition === 'bottomleft') {
739
- legendX = offset;
740
- legendY = canvasHeight - legendHeight - offset;
741
- }
742
- else if (legendPosition === 'topleft') {
743
- legendX = offset;
744
- legendY = offset;
745
- }
746
- context.drawImage(canvasLegend, legendX, legendY, legendWidth, legendHeight);
747
- context.strokeRect(legendX, legendY, legendWidth, legendHeight);
748
- div.parentNode.removeChild(div); // remove temp div (IE style)
749
- return true;
750
- }
751
- }
752
- renderMap(map, size, extent) {
753
- map.ol.updateSize();
754
- map.ol.renderSync();
755
- }
756
- /**
757
- * Save document
758
- * @param doc - Document to save
759
- */
760
- async saveDoc(doc) {
761
- await doc.save('map_georef.pdf', { returnPromise: true });
762
- }
763
- /**
764
- * Calculate the best Image size to fit in pdf
765
- * @param doc - Pdf Document
766
- * @param canvas - Canvas of image
767
- * @param margins - Page margins
768
- */
769
- getImageSizeToFitPdf(doc, canvas, margins) {
770
- // Define variable to calculate best size to fit in one page
771
- const pageHeight = doc.internal.pageSize.getHeight() - (margins[0] + margins[2]);
772
- const pageWidth = doc.internal.pageSize.getWidth() - (margins[1] + margins[3]);
773
- const canHeight = this.pdf_units2points(canvas.height, 'mm');
774
- const canWidth = this.pdf_units2points(canvas.width, 'mm');
775
- const heightRatio = canHeight / pageHeight;
776
- const widthRatio = canWidth / pageWidth;
777
- const maxRatio = heightRatio > widthRatio ? heightRatio : widthRatio;
778
- const imgHeigh = maxRatio > 1 ? canHeight / maxRatio : canHeight;
779
- const imgWidth = maxRatio > 1 ? canWidth / maxRatio : canWidth;
780
- return [imgWidth, imgHeigh];
781
- }
782
- /**
783
- * Get a world file information for tiff
784
- * @param map - Map of the app
785
- */
786
- getWorldFileInformation(map) {
787
- const currentResolution = map.viewController.getResolution();
788
- const currentExtent = map.viewController.getExtent(); // Return [minx, miny, maxx, maxy]
789
- return [
790
- currentResolution,
791
- 0,
792
- 0,
793
- -currentResolution,
794
- currentExtent[0] + currentResolution / 0.5,
795
- currentExtent[3] - currentResolution / 0.5
796
- ].join('\n');
797
- }
798
- /**
799
- * Save canvas image as file
800
- * @param canvas - Canvas to save
801
- * @param name - Name of the file
802
- * @param format - file format
803
- */
804
- saveCanvasImageAsFile(canvas, nameWithExt, format) {
805
- const blobFormat = 'image/' + format;
806
- const that = this;
807
- try {
808
- canvas.toDataURL(); // Just to make the catch trigger wihtout toBlob Error throw not catched
809
- // If navigator is Internet Explorer
810
- if (navigator.msSaveBlob) {
811
- navigator.msSaveBlob(canvas.msToBlob(), nameWithExt);
812
- this.saveFileProcessing();
813
- }
814
- else {
815
- canvas.toBlob((blob) => {
816
- // download image
817
- saveAs(blob, nameWithExt);
818
- that.saveFileProcessing();
819
- }, blobFormat);
820
- }
821
- }
822
- catch (err) {
823
- this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
824
- }
825
- }
826
- /**
827
- * Add file to a zip
828
- * @param canvas - File to add to the zip
829
- * @param name -Name of the fileoverview
830
- */
831
- generateCanvaFileToZip(canvas, name) {
832
- const blobFormat = 'image/' + 'jpeg';
833
- const that = this;
834
- if (!this.hasOwnProperty('zipFile') ||
835
- typeof this.zipFile === 'undefined') {
836
- this.zipFile = new JSZip();
837
- }
838
- try {
839
- canvas.toDataURL(); // Just to make the catch trigger wihtout toBlob Error throw not catched
840
- if (navigator.msSaveBlob) {
841
- this.addFileToZip(name, canvas.msToBlob());
842
- }
843
- else {
844
- canvas.toBlob((blob) => {
845
- that.addFileToZip(name, blob);
846
- }, blobFormat);
847
- }
848
- }
849
- catch (err) {
850
- this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
851
- }
852
- }
853
- /**
854
- * Add file to zip, if all file are zipped, download
855
- * @param name - Name of the files
856
- * @param blob - Contain of file
857
- */
858
- addFileToZip(name, blob) {
859
- // add file to zip
860
- this.zipFile.file(name, blob);
861
- this.nbFileToProcess--;
862
- // If all files are proccessed
863
- if (this.nbFileToProcess === 0) {
864
- // Download zip file
865
- this.getZipFile();
866
- // Stop loading
867
- this.activityService.unregister(this.activityId);
868
- }
869
- }
870
- saveFileProcessing() {
871
- this.nbFileToProcess--;
872
- // If all files are proccessed
873
- if (this.nbFileToProcess === 0) {
874
- // Stop loading
875
- this.activityService.unregister(this.activityId);
876
- }
877
- }
878
- /**
879
- * Get the zipped file
880
- * @return Retun a zip file
881
- */
882
- getZipFile() {
883
- const that = this;
884
- this.zipFile.generateAsync({ type: 'blob' }).then((blob) => {
885
- // 1) generate the zip file
886
- saveAs(blob, 'map.zip');
887
- delete that.zipFile;
888
- });
889
- }
890
- pdf_units2points(n, unit) {
891
- let k = 1;
892
- // this code is borrowed from jsPDF
893
- // as it does not expose a public API
894
- // for converting units to points.
895
- switch (unit) {
896
- case 'pt':
897
- k = 1;
898
- break;
899
- case 'mm':
900
- k = 72 / 25.4;
901
- break;
902
- case 'cm':
903
- k = 72 / 2.54;
904
- break;
905
- case 'in':
906
- k = 72;
907
- break;
908
- case 'px':
909
- k = 96 / 72;
910
- break;
911
- case 'pc':
912
- k = 12;
913
- break;
914
- case 'em':
915
- k = 12;
916
- break;
917
- case 'ex':
918
- k = 6;
919
- break;
920
- default:
921
- throw new Error('Invalid unit: ' + unit);
922
- }
923
- return n * k;
924
- }
925
- }
926
- PrintService.ɵfac = function PrintService_Factory(t) { return new (t || PrintService)(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(i2.MessageService), i0.ɵɵinject(i2.ActivityService), i0.ɵɵinject(i2.LanguageService), i0.ɵɵinject(i2.ConfigService)); };
927
- PrintService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PrintService, factory: PrintService.ɵfac, providedIn: 'root' });
928
- (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PrintService, [{
929
- type: Injectable,
930
- args: [{
931
- providedIn: 'root'
932
- }]
933
- }], function () { return [{ type: i1.HttpClient }, { type: i2.MessageService }, { type: i2.ActivityService }, { type: i2.LanguageService }, { type: i2.ConfigService }]; }, null); })();
1
+ import { Injectable } from '@angular/core';
2
+ import { Observable, Subject, forkJoin } from 'rxjs';
3
+ import { map as rxMap } from 'rxjs/operators';
4
+ import { saveAs } from 'file-saver';
5
+ import jsPDF from 'jspdf';
6
+ import html2canvas from 'html2canvas';
7
+ import { default as JSZip } from 'jszip';
8
+ import { SubjectStatus } from '@igo2/utils';
9
+ import { SecureImagePipe } from '@igo2/common';
10
+ import { formatScale } from '../../map/shared/map.utils';
11
+ import { getLayersLegends } from '../../layer/utils/outputLegend';
12
+ import GeoPdfPlugin from './geopdf';
13
+ import * as i0 from "@angular/core";
14
+ import * as i1 from "@angular/common/http";
15
+ import * as i2 from "@igo2/core";
16
+ export class PrintService {
17
+ constructor(http, messageService, activityService, languageService, configService) {
18
+ this.http = http;
19
+ this.messageService = messageService;
20
+ this.activityService = activityService;
21
+ this.languageService = languageService;
22
+ this.configService = configService;
23
+ this.TEXTPDFFONT = {
24
+ titleFont: 'Times',
25
+ titleFontStyle: 'bold',
26
+ subtitleFont: 'Times',
27
+ subtitleFontStyle: 'bold',
28
+ commentFont: 'courier',
29
+ commentFontStyle: 'normal',
30
+ commentFontSize: 16
31
+ };
32
+ }
33
+ print(map, options) {
34
+ const status$ = new Subject();
35
+ const paperFormat = options.paperFormat;
36
+ const resolution = +options.resolution; // Default is 96
37
+ const orientation = options.orientation;
38
+ const legendPostion = options.legendPosition;
39
+ this.activityId = this.activityService.register();
40
+ GeoPdfPlugin(jsPDF.API);
41
+ const doc = new jsPDF({
42
+ orientation,
43
+ format: paperFormat.toLowerCase(),
44
+ unit: 'mm' // default
45
+ });
46
+ const dimensions = [
47
+ doc.internal.pageSize.width,
48
+ doc.internal.pageSize.height
49
+ ];
50
+ const margins = [10, 10, 10, 10];
51
+ const width = dimensions[0] - margins[3] - margins[1];
52
+ const height = dimensions[1] - margins[0] - margins[2];
53
+ const size = [width, height];
54
+ let titleSizes;
55
+ let subtitleSizes;
56
+ // PDF title
57
+ if (options.title !== undefined) {
58
+ const fontSizeInPt = Math.round(2 * (height + 145) * 0.05) / 2; //calculate the fontSize title from the page height.
59
+ titleSizes = this.getTextPdfObjectSizeAndMarg(options.title, margins, this.TEXTPDFFONT.titleFont, fontSizeInPt, this.TEXTPDFFONT.titleFontStyle, doc);
60
+ this.addTextInPdfDoc(doc, options.title, this.TEXTPDFFONT.titleFont, this.TEXTPDFFONT.titleFontStyle, titleSizes.fontSize, titleSizes.marginLeft + margins[3], margins[0]);
61
+ margins[0] = titleSizes.height + margins[0]; // cumulative margin top for next elem to place in pdf doc
62
+ }
63
+ // PDF subtitle
64
+ if (options.subtitle !== undefined) {
65
+ subtitleSizes = this.getTextPdfObjectSizeAndMarg(options.subtitle, margins, this.TEXTPDFFONT.subtitleFont, titleSizes.fontSize * 0.7, // 70% size of title
66
+ this.TEXTPDFFONT.subtitleFontStyle, doc);
67
+ this.addTextInPdfDoc(doc, options.subtitle, this.TEXTPDFFONT.subtitleFont, this.TEXTPDFFONT.subtitleFontStyle, subtitleSizes.fontSize, subtitleSizes.marginLeft + margins[3], margins[0]);
68
+ margins[0] += 5; // cumulative marg top for next elem to place in pdf doc. 5 is a fix it could be adjust
69
+ }
70
+ if (options.showProjection === true || options.showScale === true) {
71
+ this.addProjScale(doc, map, resolution, options.showProjection, options.showScale);
72
+ }
73
+ if (options.comment !== '') {
74
+ this.addComment(doc, options.comment);
75
+ }
76
+ this.addMap(doc, map, resolution, size, margins).subscribe(async (status) => {
77
+ if (status === SubjectStatus.Done) {
78
+ await this.addScale(doc, map, margins);
79
+ await this.handleMeasureLayer(doc, map, margins);
80
+ const width = this.imgSizeAdded[0];
81
+ const height = this.imgSizeAdded[1];
82
+ const res = 1;
83
+ this.addGeoRef(doc, map, width, height, res, margins);
84
+ if (options.legendPosition !== 'none') {
85
+ if (['topleft', 'topright', 'bottomleft', 'bottomright'].indexOf(options.legendPosition) > -1) {
86
+ await this.addLegendSamePage(doc, map, margins, resolution, options.legendPosition);
87
+ }
88
+ else if (options.legendPosition === 'newpage') {
89
+ await this.addLegend(doc, map, margins, resolution);
90
+ }
91
+ }
92
+ else {
93
+ await this.saveDoc(doc);
94
+ }
95
+ }
96
+ if (status === SubjectStatus.Done || status === SubjectStatus.Error) {
97
+ this.activityService.unregister(this.activityId);
98
+ status$.next(SubjectStatus.Done);
99
+ }
100
+ });
101
+ return status$;
102
+ }
103
+ // ref GeoMoose https://github.com/geomoose/gm3/tree/main/src/gm3/components/print
104
+ addGeoRef(doc, map, width, height, resolution, margins) {
105
+ const unit = 'mm';
106
+ const docHeight = doc.internal.pageSize.getHeight();
107
+ // x,y = margin left-bottom corner for img in pdf doc
108
+ const x = margins[3];
109
+ const y = docHeight - margins[0] - height;
110
+ let pdf_extents = [x, y, x + width, y + height];
111
+ for (let i = 0; i < pdf_extents.length; i++) {
112
+ pdf_extents[i] = this.pdf_units2points(pdf_extents[i], unit);
113
+ }
114
+ const mapExtent = map.viewController.getExtent('EPSG:3857');
115
+ doc.setGeoArea(pdf_extents, mapExtent);
116
+ }
117
+ /**
118
+ * Add measure overlay on the map on the document when the measure layer is present
119
+ * @param doc - Pdf document where measure tooltip will be added
120
+ * @param map - Map of the app
121
+ * @param margins - Page margins
122
+ */
123
+ async handleMeasureLayer(doc, map, margins) {
124
+ if (map.layers.find(layer => layer.visible && layer.id.startsWith('igo-measures-'))) {
125
+ let canvasOverlayHTMLMeasures;
126
+ const mapOverlayMeasuresHTML = map.ol.getOverlayContainer();
127
+ await html2canvas(mapOverlayMeasuresHTML, {
128
+ scale: 1,
129
+ backgroundColor: null
130
+ }).then(e => {
131
+ canvasOverlayHTMLMeasures = e;
132
+ });
133
+ this.addCanvas(doc, canvasOverlayHTMLMeasures, margins); // this adds measure overlays
134
+ }
135
+ }
136
+ /**
137
+ * Get html code for all layers legend
138
+ * @param map IgoMap
139
+ * @param width The width that the legend need to be
140
+ * @return Html code for the legend
141
+ */
142
+ getLayersLegendHtml(map, width, resolution) {
143
+ return new Observable((observer) => {
144
+ let html = '';
145
+ const legends = getLayersLegends(map.layers, {
146
+ resolution: map.viewController.getResolution(),
147
+ extent: map.viewController.getExtent(),
148
+ projection: map.viewController.getOlProjection().getCode(),
149
+ // scale: map.viewController.getScale(resolution),
150
+ size: map.ol.getSize()
151
+ });
152
+ if (legends.filter(l => l.display === true).length === 0) {
153
+ observer.next(html);
154
+ observer.complete();
155
+ return;
156
+ }
157
+ // Define important style to be sure that all container is convert
158
+ // to image not just visible part
159
+ html += '<style media="screen" type="text/css">';
160
+ html += '.html2canvas-container { width: ' + width + 'mm !important; height: 2000px !important; }';
161
+ html += 'table.tableLegend {table-layout: auto;}';
162
+ html += 'div.styleLegend {padding-top: 5px; padding-right:5px;padding-left:5px;padding-bottom:5px;}';
163
+ html += '</style>';
164
+ // The font size will also be lowered afterwards (globally along the legend size)
165
+ // this allows having a good relative font size here and to keep ajusting the legend size
166
+ // while keeping good relative font size
167
+ html += '<font size="3" face="Times" >';
168
+ html += '<div class="styleLegend">';
169
+ html += '<table class="tableLegend" >';
170
+ // For each legend, define an html table cell
171
+ const images$ = legends.filter(l => l.display).map((legend) => this.getDataImage(legend.url).pipe(rxMap((dataImage) => {
172
+ let htmlImg = '<tr><td>' + legend.title.toUpperCase() + '</td></tr>';
173
+ htmlImg += '<tr><td><img src="' + dataImage + '"></td></tr>';
174
+ return htmlImg;
175
+ })));
176
+ forkJoin(images$).subscribe((dataImages) => {
177
+ html = dataImages.reduce((acc, current) => (acc += current), html);
178
+ html += '</table>';
179
+ html += '</div>';
180
+ observer.next(html);
181
+ observer.complete();
182
+ });
183
+ });
184
+ }
185
+ getDataImage(url) {
186
+ const secureIMG = new SecureImagePipe(this.http, this.configService);
187
+ return secureIMG.transform(url);
188
+ }
189
+ /**
190
+ * Get all the legend in a single image
191
+ * * @param format - Image format. default value to "png"
192
+ * @return The image of the legend
193
+ */
194
+ async getLayersLegendImage(map, format = 'png', doZipFile, resolution) {
195
+ const status$ = new Subject();
196
+ // Get html code for the legend
197
+ const width = 200; // milimeters unit, originally define for document pdf
198
+ let html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
199
+ format = format.toLowerCase();
200
+ // If no legend show No LEGEND in an image
201
+ if (html.length === 0) {
202
+ html = '<font size="12" face="Courier New" >';
203
+ html += '<div align="center"><b>NO LEGEND</b></div>';
204
+ }
205
+ // Create div to contain html code for legend
206
+ const div = window.document.createElement('div');
207
+ div.style.position = 'absolute';
208
+ div.style.top = '0';
209
+ // Add html code to convert in the new window
210
+ window.document.body.appendChild(div);
211
+ div.innerHTML = html;
212
+ await this.timeout(1);
213
+ const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
214
+ console.log(e);
215
+ });
216
+ if (canvas) {
217
+ let status = SubjectStatus.Done;
218
+ try {
219
+ if (!doZipFile) {
220
+ // Save the canvas as file
221
+ this.saveCanvasImageAsFile(canvas, 'legendImage', format);
222
+ }
223
+ else {
224
+ // Add the canvas to zip
225
+ this.generateCanvaFileToZip(canvas, 'legendImage' + '.' + format);
226
+ }
227
+ div.parentNode.removeChild(div); // remove temp div (IE)
228
+ }
229
+ catch (err) {
230
+ status = SubjectStatus.Error;
231
+ }
232
+ status$.next(status);
233
+ }
234
+ return status$;
235
+ }
236
+ getTextPdfObjectSizeAndMarg(text, margins, font, fontSizeInPt, fontStyle, doc) {
237
+ const pdfResolution = 96;
238
+ const docWidth = doc.internal.pageSize.getWidth();
239
+ const pageWidth = docWidth - margins[1] - margins[3];
240
+ // important to set it first, the textDimension change when font change!
241
+ doc.setFont(font, fontStyle);
242
+ doc.setFontSize(fontSizeInPt);
243
+ let textDimensions = doc.getTextDimensions(text);
244
+ let textMarginLeft;
245
+ if (textDimensions.w > pageWidth) {
246
+ // if the text is to long, reduce fontSize 70% and the overflow with be cut in print...
247
+ textMarginLeft = 0;
248
+ fontSizeInPt = fontSizeInPt * 0.7;
249
+ doc.setFontSize(fontSizeInPt);
250
+ textDimensions = doc.getTextDimensions(text);
251
+ }
252
+ else {
253
+ textMarginLeft = (pageWidth - textDimensions.w) / 2;
254
+ }
255
+ return {
256
+ 'fontSize': fontSizeInPt,
257
+ 'marginLeft': textMarginLeft,
258
+ 'height': textDimensions.h
259
+ };
260
+ }
261
+ /**
262
+ * Add comment to the document
263
+ * * @param doc - pdf document
264
+ * * @param comment - Comment to add in the document
265
+ */
266
+ addComment(doc, comment) {
267
+ const commentMarginLeft = 20; //margin left and bottom is fix
268
+ const commentMarginBottom = 5;
269
+ const marginTop = doc.internal.pageSize.height - commentMarginBottom;
270
+ this.addTextInPdfDoc(doc, comment, this.TEXTPDFFONT.commentFont, this.TEXTPDFFONT.commentFontStyle, this.TEXTPDFFONT.commentFontSize, commentMarginLeft, marginTop);
271
+ }
272
+ addTextInPdfDoc(doc, textToAdd, textFont, textFontStyle, textFontSize, textMarginLeft, textMarginTop) {
273
+ doc.setFont(textFont, textFontStyle);
274
+ doc.setFontSize(textFontSize);
275
+ doc.text(textToAdd, textMarginLeft, textMarginTop);
276
+ }
277
+ /**
278
+ * Add projection and/or scale to the document
279
+ * @param doc - pdf document
280
+ * @param map - Map of the app
281
+ * @param dpi - DPI resolution of the document
282
+ * @param projection - Bool to indicate if projection need to be added
283
+ * @param scale - Bool to indicate if scale need to be added
284
+ */
285
+ addProjScale(doc, map, dpi, projection, scale) {
286
+ const translate = this.languageService.translate;
287
+ const projScaleSize = 16;
288
+ const projScaleMarginLeft = 20;
289
+ const marginBottom = 15;
290
+ const heightPixels = doc.internal.pageSize.height - marginBottom;
291
+ let textProjScale = '';
292
+ if (projection === true) {
293
+ const projText = translate.instant('igo.geo.printForm.projection');
294
+ textProjScale += projText + ': ' + map.projection;
295
+ }
296
+ if (scale === true) {
297
+ if (projection === true) {
298
+ textProjScale += ' ';
299
+ }
300
+ const scaleText = translate.instant('igo.geo.printForm.scale');
301
+ const mapScale = map.viewController.getScale(dpi);
302
+ textProjScale += scaleText + ': ~ 1 / ' + formatScale(mapScale);
303
+ }
304
+ doc.setFont('courier');
305
+ doc.setFontSize(projScaleSize);
306
+ doc.text(textProjScale, projScaleMarginLeft, heightPixels);
307
+ }
308
+ /**
309
+ * Add the legend to the document
310
+ * @param doc - Pdf document where legend will be added
311
+ * @param map - Map of the app
312
+ * @param margins - Page margins
313
+ */
314
+ async addLegend(doc, map, margins, resolution) {
315
+ // Get html code for the legend
316
+ const width = doc.internal.pageSize.width;
317
+ const html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
318
+ // If no legend, save the map directly
319
+ if (html === '') {
320
+ await this.saveDoc(doc);
321
+ return true;
322
+ }
323
+ // Create div to contain html code for legend
324
+ const div = window.document.createElement('div');
325
+ div.style.position = 'absolute';
326
+ div.style.top = '0';
327
+ // Add html code to convert in the new window
328
+ window.document.body.appendChild(div);
329
+ div.innerHTML = html;
330
+ await this.timeout(1);
331
+ const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
332
+ console.log(e);
333
+ });
334
+ if (canvas) {
335
+ const pourcentageReduction = 0.85;
336
+ const imageSize = [pourcentageReduction * (25.4 * canvas.width) / resolution, pourcentageReduction
337
+ * (25.4 * canvas.height) / resolution];
338
+ let imgData;
339
+ doc.addPage();
340
+ imgData = canvas.toDataURL('image/png');
341
+ doc.addImage(imgData, 'PNG', 10, 10, imageSize[0], imageSize[1]);
342
+ div.parentNode.removeChild(div); // remove temp div (IE style)
343
+ }
344
+ await this.saveDoc(doc);
345
+ }
346
+ /**
347
+ * Add the legend to the document
348
+ * @param doc - Pdf document where legend will be added
349
+ * @param map - Map of the app
350
+ * @param margins - Page margins
351
+ */
352
+ async addLegendSamePage(doc, map, margins, resolution, legendPosition) {
353
+ // Get html code for the legend
354
+ const width = doc.internal.pageSize.width;
355
+ const html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
356
+ // If no legend, save the map directly
357
+ if (html === '') {
358
+ await this.saveDoc(doc);
359
+ return true;
360
+ }
361
+ // Create div to contain html code for legend
362
+ const div = window.document.createElement('div');
363
+ div.style.position = 'absolute';
364
+ div.style.top = '0';
365
+ // Add html code to convert in the new window
366
+ window.document.body.appendChild(div);
367
+ div.innerHTML = html;
368
+ await this.timeout(1);
369
+ const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
370
+ console.log(e);
371
+ });
372
+ let marginsLegend;
373
+ if (canvas) {
374
+ const pourcentageReduction = 0.85;
375
+ const imageSize = [pourcentageReduction * (25.4 * canvas.width) / resolution,
376
+ pourcentageReduction * (25.4 * canvas.height) / resolution];
377
+ // Move the legend to the correct position on the page
378
+ if (legendPosition === 'bottomright') {
379
+ marginsLegend = [doc.internal.pageSize.height - margins[2] - imageSize[1], margins[1],
380
+ margins[2], doc.internal.pageSize.width - margins[1] - imageSize[0]];
381
+ }
382
+ else if (legendPosition === 'topright') {
383
+ marginsLegend = [margins[0], margins[1], doc.internal.pageSize.height - margins[0] - imageSize[1],
384
+ doc.internal.pageSize.width - margins[1] - imageSize[0]];
385
+ }
386
+ else if (legendPosition === 'bottomleft') {
387
+ // When the legend is in the bottom left, raise the legend slightly upward so that attributions are visible
388
+ marginsLegend = [doc.internal.pageSize.height - margins[2] - imageSize[1] - 15,
389
+ doc.internal.pageSize.width - margins[3] - imageSize[0], margins[2] + 15, margins[3]];
390
+ }
391
+ else if (legendPosition === 'topleft') {
392
+ marginsLegend = [margins[0], doc.internal.pageSize.width - margins[3] - imageSize[0],
393
+ doc.internal.pageSize.height - margins[0] - imageSize[1], margins[3]];
394
+ }
395
+ this.addCanvas(doc, canvas, marginsLegend); // this adds the legend
396
+ div.parentNode.removeChild(div); // remove temp div (IE style)
397
+ await this.saveDoc(doc);
398
+ }
399
+ }
400
+ /**
401
+ * Add scale and attributions on the map on the document
402
+ * @param doc - Pdf document where legend will be added
403
+ * @param map - Map of the app
404
+ * @param margins - Page margins
405
+ */
406
+ async addScale(doc, map, margins) {
407
+ const mapSize = map.ol.getSize();
408
+ const extent = map.ol.getView().calculateExtent(mapSize);
409
+ // Get the scale and attribution
410
+ // we use cloneNode to modify the nodes to print without modifying it on the page, using deep:true to get children
411
+ let canvasOverlayHTML;
412
+ const mapOverlayHTML = map.ol.getOverlayContainerStopEvent();
413
+ // Remove the UI buttons from the nodes
414
+ const OverlayHTMLButtons = mapOverlayHTML.getElementsByTagName('button');
415
+ const OverlayHTMLButtonsarr = Array.from(OverlayHTMLButtons);
416
+ for (const OverlayHTMLButton of OverlayHTMLButtonsarr) {
417
+ OverlayHTMLButton.setAttribute('data-html2canvas-ignore', 'true');
418
+ }
419
+ // Change the styles of hyperlink in the printed version
420
+ // Transform the Overlay into a canvas
421
+ // scale is necessary to make it in google chrome
422
+ // background as null because otherwise it is white and cover the map
423
+ // allowtaint is to allow rendering images in the attributions
424
+ // useCORS: true pour permettre de renderer les images (ne marche pas en local)
425
+ const canvas = await html2canvas(mapOverlayHTML, {
426
+ scale: 1,
427
+ backgroundColor: null,
428
+ allowTaint: true,
429
+ useCORS: true,
430
+ }).then(e => {
431
+ canvasOverlayHTML = e;
432
+ });
433
+ this.addCanvas(doc, canvasOverlayHTML, margins); // this adds scales and attributions
434
+ }
435
+ defineNbFileToProcess(nbFileToProcess) {
436
+ this.nbFileToProcess = nbFileToProcess;
437
+ }
438
+ timeout(ms) {
439
+ return new Promise((resolve) => setTimeout(resolve, ms));
440
+ }
441
+ addCanvas(doc, canvas, margins) {
442
+ let image;
443
+ if (canvas) {
444
+ image = canvas.toDataURL('image/png');
445
+ }
446
+ if (image !== undefined) {
447
+ if (image.length < 20) { // img is corrupt todo: fix addScale in mobile make a corrupt img
448
+ console.log('Warning: An image cannot be print in pdf file');
449
+ return;
450
+ }
451
+ const imageSize = this.getImageSizeToFitPdf(doc, canvas, margins);
452
+ doc.addImage(image, 'PNG', margins[3], margins[0], imageSize[0], imageSize[1]);
453
+ doc.rect(margins[3], margins[0], imageSize[0], imageSize[1]);
454
+ this.imgSizeAdded = imageSize; // keep img size for georef later
455
+ }
456
+ }
457
+ // TODO fix printing with image resolution
458
+ addMap(doc, map, resolution, size, margins) {
459
+ const status$ = new Subject();
460
+ const mapSize = map.ol.getSize();
461
+ const extent = map.ol.getView().calculateExtent(mapSize);
462
+ const widthPixels = Math.round((size[0] * resolution) / 25.4);
463
+ const heightPixels = Math.round((size[1] * resolution) / 25.4);
464
+ let timeout;
465
+ map.ol.once('rendercomplete', (event) => {
466
+ const canvases = event.target.getViewport().getElementsByTagName('canvas');
467
+ const mapStatus$$ = map.status$.subscribe((mapStatus) => {
468
+ clearTimeout(timeout);
469
+ if (mapStatus !== SubjectStatus.Done) {
470
+ return;
471
+ }
472
+ mapStatus$$.unsubscribe();
473
+ let status = SubjectStatus.Done;
474
+ try {
475
+ for (const canvas of canvases) {
476
+ if (canvas.width !== 0) {
477
+ this.addCanvas(doc, canvas, margins);
478
+ }
479
+ }
480
+ }
481
+ catch (err) {
482
+ status = SubjectStatus.Error;
483
+ this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
484
+ }
485
+ this.renderMap(map, mapSize, extent);
486
+ status$.next(status);
487
+ });
488
+ // If no loading as started after 200ms, then probably no loading
489
+ // is required.
490
+ timeout = window.setTimeout(() => {
491
+ mapStatus$$.unsubscribe();
492
+ let status = SubjectStatus.Done;
493
+ try {
494
+ for (const canvas of canvases) {
495
+ if (canvas.width !== 0) {
496
+ this.addCanvas(doc, canvas, margins);
497
+ }
498
+ }
499
+ }
500
+ catch (err) {
501
+ status = SubjectStatus.Error;
502
+ this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
503
+ }
504
+ this.renderMap(map, mapSize, extent);
505
+ status$.next(status);
506
+ }, 200);
507
+ });
508
+ this.renderMap(map, [widthPixels, heightPixels], extent);
509
+ return status$;
510
+ }
511
+ /**
512
+ * Download an image of the map with addition of informations
513
+ * @param map - Map of the app
514
+ * @param format - Image format. default value to "png"
515
+ * @param projection - Indicate if projection need to be add. Default to false
516
+ * @param scale - Indicate if scale need to be add. Default to false
517
+ * @param legend - Indicate if the legend of layers need to be download. Default to false
518
+ * @param title - Title to add for the map - Default to blank
519
+ * @param subtitle - Subtitle to add for the map - Default to blank
520
+ * @param comment - Comment to add for the map - Default to blank
521
+ * @param doZipFile - Indicate if we do a zip with the file
522
+ * @return Image file of the map with extension format given as parameter
523
+ */
524
+ downloadMapImage(map, resolution, format = 'png', projection = false, scale = false, title = '', subtitle = '', comment = '', doZipFile = true, legendPosition) {
525
+ const status$ = new Subject();
526
+ // const resolution = map.ol.getView().getResolution();
527
+ this.activityId = this.activityService.register();
528
+ const translate = this.languageService.translate;
529
+ map.ol.once('rendercomplete', async (event) => {
530
+ format = format.toLowerCase();
531
+ const oldCanvas = event.target
532
+ .getViewport()
533
+ .getElementsByTagName('canvas')[0];
534
+ const newCanvas = document.createElement('canvas');
535
+ const newContext = newCanvas.getContext('2d');
536
+ // Postion in height to set the canvas in new canvas
537
+ let positionHCanvas = 0;
538
+ // Get height/width of map canvas
539
+ const width = oldCanvas.width;
540
+ let height = oldCanvas.height;
541
+ // Set Font to calculate comment width
542
+ newContext.font = '20px Calibri';
543
+ const commentWidth = newContext.measureText(comment).width;
544
+ // Add height for title if defined
545
+ height = title !== '' ? height + 30 : height;
546
+ // Add height for title if defined
547
+ height = subtitle !== '' ? height + 30 : height;
548
+ // Add height for projection or scale (same line) if defined
549
+ height = projection !== false || scale !== false ? height + 30 : height;
550
+ const positionHProjScale = height - 10;
551
+ // Define number of line depending of the comment length
552
+ const commentNbLine = Math.ceil(commentWidth / width);
553
+ // Add height for multiline comment if defined
554
+ height = comment !== '' ? height + commentNbLine * 30 : height;
555
+ let positionHComment = height - commentNbLine * 20 + 5;
556
+ // Set the new canvas with the new calculated size
557
+ newCanvas.width = width;
558
+ newCanvas.height = height;
559
+ if (['bmp', 'gif', 'jpeg', 'png', 'tiff'].indexOf(format) > -1) {
560
+ // Patch Jpeg default black background to white
561
+ if (format === 'jpeg') {
562
+ newContext.fillStyle = '#ffffff';
563
+ newContext.fillRect(0, 0, width, height);
564
+ newContext.fillStyle = '#000000';
565
+ }
566
+ else if (title !== '' || subtitle !== '' || comment !== '' ||
567
+ projection !== false || scale !== false) {
568
+ newContext.fillStyle = '#ffffff';
569
+ newContext.fillRect(0, 0, width, height);
570
+ newContext.fillStyle = '#000000';
571
+ }
572
+ }
573
+ // If a title need to be added to canvas
574
+ if (title !== '') {
575
+ // Set font for title
576
+ // Adjust according to title length
577
+ newContext.font = '26px Calibri';
578
+ positionHCanvas = 30;
579
+ newContext.textAlign = 'center';
580
+ newContext.fillText(title, width / 2, 20, width * 0.9);
581
+ }
582
+ if (subtitle !== '') {
583
+ // Set font for subtitle
584
+ // Adjust according to title length
585
+ newContext.font = '26px Calibri';
586
+ positionHCanvas = 60;
587
+ newContext.textAlign = 'center';
588
+ newContext.fillText(subtitle, width / 2, 50, width * 0.9);
589
+ }
590
+ // Set font for next section
591
+ newContext.font = '20px Calibri';
592
+ // If projection or/end scale need to be added to canvas
593
+ if ((projection !== false) || (scale !== false)) {
594
+ let projectionScaleText = '';
595
+ if (projection !== false) {
596
+ const projText = translate.instant('igo.geo.printForm.projection');
597
+ projectionScaleText = projText + ': ' + map.projection + ' ';
598
+ }
599
+ if (scale !== false) {
600
+ const scaleText = translate.instant('igo.geo.printForm.scale');
601
+ const mapScale = map.viewController.getScale(resolution);
602
+ projectionScaleText += scaleText + ': ~ 1 / ' + formatScale(mapScale);
603
+ }
604
+ newContext.textAlign = 'center';
605
+ newContext.fillText(projectionScaleText, width / 2, positionHProjScale, width * 0.9);
606
+ }
607
+ // If a comment need to be added to canvas
608
+ if (comment !== '') {
609
+ newContext.textAlign = 'center';
610
+ // If only one line, no need to multiline the comment
611
+ if (commentNbLine === 1) {
612
+ newContext.fillText(comment, width / 2, positionHComment);
613
+ }
614
+ else {
615
+ // Separate the setenses to be approx. the same length
616
+ const nbCommentChar = comment.length;
617
+ const CommentLengthToCut = Math.floor(nbCommentChar / commentNbLine);
618
+ let commentCurrentLine = '';
619
+ let positionFirstCutChar = 0;
620
+ let positionLastBlank;
621
+ // Loop for the number of line calculated
622
+ for (let i = 0; i < commentNbLine; i++) {
623
+ // For all line except last
624
+ if (commentNbLine - 1 > i) {
625
+ // Get comment current line to find the right place tu cut comment
626
+ commentCurrentLine = comment.substr(positionFirstCutChar, CommentLengthToCut);
627
+ // Cut the setence at blank
628
+ positionLastBlank = commentCurrentLine.lastIndexOf(' ');
629
+ newContext.fillText(commentCurrentLine.substr(0, positionLastBlank), width / 2, positionHComment);
630
+ positionFirstCutChar += positionLastBlank;
631
+ // Go to next line for insertion
632
+ positionHComment += 20;
633
+ }
634
+ else {
635
+ // Don't cut last part
636
+ newContext.fillText(comment.substr(positionFirstCutChar), width / 2, positionHComment);
637
+ }
638
+ }
639
+ }
640
+ }
641
+ // Add map to new canvas
642
+ newContext.drawImage(oldCanvas, 0, positionHCanvas);
643
+ // Check the legendPosition
644
+ if (legendPosition !== 'none') {
645
+ if (['topleft', 'topright', 'bottomleft', 'bottomright'].indexOf(legendPosition) > -1) {
646
+ await this.addLegendToImage(newCanvas, map, resolution, legendPosition, format);
647
+ }
648
+ }
649
+ let status = SubjectStatus.Done;
650
+ let fileNameWithExt = 'map.' + format;
651
+ if (format.toLowerCase() === 'tiff') {
652
+ fileNameWithExt = 'map' + map.projection.replace(':', '_') + '.' + format;
653
+ }
654
+ try {
655
+ // Save the canvas as file
656
+ if (!doZipFile) {
657
+ this.saveCanvasImageAsFile(newCanvas, fileNameWithExt, format);
658
+ }
659
+ else if (format.toLowerCase() === 'tiff') {
660
+ // Add the canvas to zip
661
+ this.generateCanvaFileToZip(newCanvas, fileNameWithExt);
662
+ }
663
+ else {
664
+ // Add the canvas to zip
665
+ this.generateCanvaFileToZip(newCanvas, fileNameWithExt);
666
+ }
667
+ }
668
+ catch (err) {
669
+ status = SubjectStatus.Error;
670
+ }
671
+ status$.next(status);
672
+ if (format.toLowerCase() === 'tiff') {
673
+ const tfwFileNameWithExt = fileNameWithExt.substring(0, fileNameWithExt.toLowerCase().indexOf('.tiff')) + '.tfw';
674
+ const tiwContent = this.getWorldFileInformation(map);
675
+ const blob = new Blob([tiwContent], {
676
+ type: 'text/plain;charset=utf-8'
677
+ });
678
+ if (!doZipFile) {
679
+ // saveAs automaticly replace ':' for '_'
680
+ saveAs(blob, tfwFileNameWithExt);
681
+ this.saveFileProcessing();
682
+ }
683
+ else {
684
+ // Add the canvas to zip
685
+ this.addFileToZip(tfwFileNameWithExt, blob);
686
+ }
687
+ }
688
+ });
689
+ map.ol.renderSync();
690
+ return status$;
691
+ }
692
+ /**
693
+ * Create and Add Legend to the map canvas
694
+ * @param canvas Canvas of the map
695
+ * @param map Map of the app
696
+ * @param resolution Resolution of map
697
+ * @param legendPosition Legend position
698
+ * @param format Image format
699
+ */
700
+ async addLegendToImage(canvas, map, resolution, legendPosition, format) {
701
+ const fileNameWithExt = 'map.' + format;
702
+ const context = canvas.getContext('2d');
703
+ // Get html code for the legend
704
+ const html = await this.getLayersLegendHtml(map, canvas.width, resolution).toPromise();
705
+ // If no legend, save the map directly
706
+ if (html === '') {
707
+ await this.saveCanvasImageAsFile(canvas, fileNameWithExt, format);
708
+ return true;
709
+ }
710
+ // Create div to contain html code for legend
711
+ const div = window.document.createElement('div');
712
+ div.style.position = 'absolute';
713
+ div.style.top = '0';
714
+ // Add html code to convert in the new window
715
+ window.document.body.appendChild(div);
716
+ div.innerHTML = html;
717
+ await this.timeout(1);
718
+ const canvasLegend = await html2canvas(div, { useCORS: true }).catch((e) => {
719
+ console.log(e);
720
+ });
721
+ if (canvasLegend) {
722
+ const canvasHeight = canvas.height;
723
+ const canvasWidth = canvas.width;
724
+ const legendHeight = canvasLegend.height;
725
+ const legendWidth = canvasLegend.width;
726
+ // Move the legend to the correct position on the page
727
+ const offset = canvasHeight * 0.01;
728
+ let legendX;
729
+ let legendY;
730
+ if (legendPosition === 'bottomright') {
731
+ legendX = canvasWidth - legendWidth - offset;
732
+ legendY = canvasHeight - legendHeight - offset;
733
+ }
734
+ else if (legendPosition === 'topright') {
735
+ legendX = canvasWidth - legendWidth - offset;
736
+ legendY = offset;
737
+ }
738
+ else if (legendPosition === 'bottomleft') {
739
+ legendX = offset;
740
+ legendY = canvasHeight - legendHeight - offset;
741
+ }
742
+ else if (legendPosition === 'topleft') {
743
+ legendX = offset;
744
+ legendY = offset;
745
+ }
746
+ context.drawImage(canvasLegend, legendX, legendY, legendWidth, legendHeight);
747
+ context.strokeRect(legendX, legendY, legendWidth, legendHeight);
748
+ div.parentNode.removeChild(div); // remove temp div (IE style)
749
+ return true;
750
+ }
751
+ }
752
+ renderMap(map, size, extent) {
753
+ map.ol.updateSize();
754
+ map.ol.renderSync();
755
+ }
756
+ /**
757
+ * Save document
758
+ * @param doc - Document to save
759
+ */
760
+ async saveDoc(doc) {
761
+ await doc.save('map_georef.pdf', { returnPromise: true });
762
+ }
763
+ /**
764
+ * Calculate the best Image size to fit in pdf
765
+ * @param doc - Pdf Document
766
+ * @param canvas - Canvas of image
767
+ * @param margins - Page margins
768
+ */
769
+ getImageSizeToFitPdf(doc, canvas, margins) {
770
+ // Define variable to calculate best size to fit in one page
771
+ const pageHeight = doc.internal.pageSize.getHeight() - (margins[0] + margins[2]);
772
+ const pageWidth = doc.internal.pageSize.getWidth() - (margins[1] + margins[3]);
773
+ const canHeight = this.pdf_units2points(canvas.height, 'mm');
774
+ const canWidth = this.pdf_units2points(canvas.width, 'mm');
775
+ const heightRatio = canHeight / pageHeight;
776
+ const widthRatio = canWidth / pageWidth;
777
+ const maxRatio = heightRatio > widthRatio ? heightRatio : widthRatio;
778
+ const imgHeigh = maxRatio > 1 ? canHeight / maxRatio : canHeight;
779
+ const imgWidth = maxRatio > 1 ? canWidth / maxRatio : canWidth;
780
+ return [imgWidth, imgHeigh];
781
+ }
782
+ /**
783
+ * Get a world file information for tiff
784
+ * @param map - Map of the app
785
+ */
786
+ getWorldFileInformation(map) {
787
+ const currentResolution = map.viewController.getResolution();
788
+ const currentExtent = map.viewController.getExtent(); // Return [minx, miny, maxx, maxy]
789
+ return [
790
+ currentResolution,
791
+ 0,
792
+ 0,
793
+ -currentResolution,
794
+ currentExtent[0] + currentResolution / 0.5,
795
+ currentExtent[3] - currentResolution / 0.5
796
+ ].join('\n');
797
+ }
798
+ /**
799
+ * Save canvas image as file
800
+ * @param canvas - Canvas to save
801
+ * @param name - Name of the file
802
+ * @param format - file format
803
+ */
804
+ saveCanvasImageAsFile(canvas, nameWithExt, format) {
805
+ const blobFormat = 'image/' + format;
806
+ const that = this;
807
+ try {
808
+ canvas.toDataURL(); // Just to make the catch trigger wihtout toBlob Error throw not catched
809
+ // If navigator is Internet Explorer
810
+ if (navigator.msSaveBlob) {
811
+ navigator.msSaveBlob(canvas.msToBlob(), nameWithExt);
812
+ this.saveFileProcessing();
813
+ }
814
+ else {
815
+ canvas.toBlob((blob) => {
816
+ // download image
817
+ saveAs(blob, nameWithExt);
818
+ that.saveFileProcessing();
819
+ }, blobFormat);
820
+ }
821
+ }
822
+ catch (err) {
823
+ this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
824
+ }
825
+ }
826
+ /**
827
+ * Add file to a zip
828
+ * @param canvas - File to add to the zip
829
+ * @param name -Name of the fileoverview
830
+ */
831
+ generateCanvaFileToZip(canvas, name) {
832
+ const blobFormat = 'image/' + 'jpeg';
833
+ const that = this;
834
+ if (!this.hasOwnProperty('zipFile') ||
835
+ typeof this.zipFile === 'undefined') {
836
+ this.zipFile = new JSZip();
837
+ }
838
+ try {
839
+ canvas.toDataURL(); // Just to make the catch trigger wihtout toBlob Error throw not catched
840
+ if (navigator.msSaveBlob) {
841
+ this.addFileToZip(name, canvas.msToBlob());
842
+ }
843
+ else {
844
+ canvas.toBlob((blob) => {
845
+ that.addFileToZip(name, blob);
846
+ }, blobFormat);
847
+ }
848
+ }
849
+ catch (err) {
850
+ this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
851
+ }
852
+ }
853
+ /**
854
+ * Add file to zip, if all file are zipped, download
855
+ * @param name - Name of the files
856
+ * @param blob - Contain of file
857
+ */
858
+ addFileToZip(name, blob) {
859
+ // add file to zip
860
+ this.zipFile.file(name, blob);
861
+ this.nbFileToProcess--;
862
+ // If all files are proccessed
863
+ if (this.nbFileToProcess === 0) {
864
+ // Download zip file
865
+ this.getZipFile();
866
+ // Stop loading
867
+ this.activityService.unregister(this.activityId);
868
+ }
869
+ }
870
+ saveFileProcessing() {
871
+ this.nbFileToProcess--;
872
+ // If all files are proccessed
873
+ if (this.nbFileToProcess === 0) {
874
+ // Stop loading
875
+ this.activityService.unregister(this.activityId);
876
+ }
877
+ }
878
+ /**
879
+ * Get the zipped file
880
+ * @return Retun a zip file
881
+ */
882
+ getZipFile() {
883
+ const that = this;
884
+ this.zipFile.generateAsync({ type: 'blob' }).then((blob) => {
885
+ // 1) generate the zip file
886
+ saveAs(blob, 'map.zip');
887
+ delete that.zipFile;
888
+ });
889
+ }
890
+ pdf_units2points(n, unit) {
891
+ let k = 1;
892
+ // this code is borrowed from jsPDF
893
+ // as it does not expose a public API
894
+ // for converting units to points.
895
+ switch (unit) {
896
+ case 'pt':
897
+ k = 1;
898
+ break;
899
+ case 'mm':
900
+ k = 72 / 25.4;
901
+ break;
902
+ case 'cm':
903
+ k = 72 / 2.54;
904
+ break;
905
+ case 'in':
906
+ k = 72;
907
+ break;
908
+ case 'px':
909
+ k = 96 / 72;
910
+ break;
911
+ case 'pc':
912
+ k = 12;
913
+ break;
914
+ case 'em':
915
+ k = 12;
916
+ break;
917
+ case 'ex':
918
+ k = 6;
919
+ break;
920
+ default:
921
+ throw new Error('Invalid unit: ' + unit);
922
+ }
923
+ return n * k;
924
+ }
925
+ }
926
+ PrintService.ɵfac = function PrintService_Factory(t) { return new (t || PrintService)(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(i2.MessageService), i0.ɵɵinject(i2.ActivityService), i0.ɵɵinject(i2.LanguageService), i0.ɵɵinject(i2.ConfigService)); };
927
+ PrintService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PrintService, factory: PrintService.ɵfac, providedIn: 'root' });
928
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PrintService, [{
929
+ type: Injectable,
930
+ args: [{
931
+ providedIn: 'root'
932
+ }]
933
+ }], function () { return [{ type: i1.HttpClient }, { type: i2.MessageService }, { type: i2.ActivityService }, { type: i2.LanguageService }, { type: i2.ConfigService }]; }, null); })();
934
934
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbnQuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2dlby9zcmMvbGliL3ByaW50L3NoYXJlZC9wcmludC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFHM0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3JELE9BQU8sRUFBRSxHQUFHLElBQUksS0FBSyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFOUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNwQyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDMUIsT0FBTyxXQUFXLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxPQUFPLElBQUksS0FBSyxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBRXpDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDNUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUkvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFekQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFHbEUsT0FBTyxZQUFZLE1BQU0sVUFBVSxDQUFDOzs7O0FBV3BDLE1BQU0sT0FBTyxZQUFZO0lBZ0J2QixZQUNVLElBQWdCLEVBQ2hCLGNBQThCLEVBQzlCLGVBQWdDLEVBQ2hDLGVBQWdDLEVBQ2hDLGFBQTRCO1FBSjVCLFNBQUksR0FBSixJQUFJLENBQVk7UUFDaEIsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQzlCLG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtRQUNoQyxvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUFDaEMsa0JBQWEsR0FBYixhQUFhLENBQWU7UUFm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QyxHQUFHLENBQUMsQ0FBQztnQkFDTixNQUFNO1lBQ1YsS0FBSyxJQUFJO2dCQUNMLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO2dCQUNkLE1BQU07WUFDVixLQUFLLElBQUk7Z0JBQ0wsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7Z0JBQ2QsTUFBTTtZQUNWLEtBQUssSUFBSTtnQkFDTCxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNQLE1BQU07WUFDVixLQUFLLElBQUk7Z0JBQ0wsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7Z0JBQ1osTUFBTTtZQUNWLEtBQUssSUFBSTtnQkFDTCxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNQLE1BQU07WUFDVixLQUFLLElBQUk7Z0JBQ0wsQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDUCxNQUFNO1lBQ1YsS0FBSyxJQUFJO2dCQUNMLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ04sTUFBTTtZQUNWO2dCQUNJLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLENBQUM7U0FDaEQ7UUFFRCxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDZixDQUFDOzt3RUF0cENVLFlBQVk7a0VBQVosWUFBWSxXQUFaLFlBQVksbUJBRlgsTUFBTTt1RkFFUCxZQUFZO2NBSHhCLFVBQVU7ZUFBQztnQkFDVixVQUFVLEVBQUUsTUFBTTthQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5cbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QsIGZvcmtKb2luIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAgYXMgcnhNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IHNhdmVBcyB9IGZyb20gJ2ZpbGUtc2F2ZXInO1xuaW1wb3J0IGpzUERGIGZyb20gJ2pzcGRmJztcbmltcG9ydCBodG1sMmNhbnZhcyBmcm9tICdodG1sMmNhbnZhcyc7XG5pbXBvcnQgeyBkZWZhdWx0IGFzIEpTWmlwIH0gZnJvbSAnanN6aXAnO1xuXG5pbXBvcnQgeyBTdWJqZWN0U3RhdHVzIH0gZnJvbSAnQGlnbzIvdXRpbHMnO1xuaW1wb3J0IHsgU2VjdXJlSW1hZ2VQaXBlIH0gZnJvbSAnQGlnbzIvY29tbW9uJztcbmltcG9ydCB7IE1lc3NhZ2VTZXJ2aWNlLCBBY3Rpdml0eVNlcnZpY2UsIExhbmd1YWdlU2VydmljZSwgQ29uZmlnU2VydmljZSB9IGZyb20gJ0BpZ28yL2NvcmUnO1xuXG5pbXBvcnQgeyBJZ29NYXAgfSBmcm9tICcuLi8uLi9tYXAvc2hhcmVkL21hcCc7XG5pbXBvcnQgeyBmb3JtYXRTY2FsZSB9IGZyb20gJy4uLy4uL21hcC9zaGFyZWQvbWFwLnV0aWxzJztcbmltcG9ydCB7IExlZ2VuZE1hcFZpZXdPcHRpb25zIH0gZnJvbSAnLi4vLi4vbGF5ZXIvc2hhcmVkL2xheWVycy9sYXllci5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgZ2V0TGF5ZXJzTGVnZW5kcyB9IGZyb20gJy4uLy4uL2xheWVyL3V0aWxzL291dHB1dExlZ2VuZCc7XG5cbmltcG9ydCB7IFByaW50T3B0aW9ucywgVGV4dFBkZlNpemVBbmRNYXJnaW4gfSBmcm9tICcuL3ByaW50LmludGVyZmFjZSc7XG5pbXBvcnQgR2VvUGRmUGx1Z2luIGZyb20gJy4vZ2VvcGRmJztcblxuZGVjbGFyZSBnbG9iYWwge1xuICBpbnRlcmZhY2UgTmF2aWdhdG9yIHtcbiAgICBtc1NhdmVCbG9iPzogKGJsb2I6IGFueSwgZGVmYXVsdE5hbWU/OiBzdHJpbmcpID0+IGJvb2xlYW5cbiAgfVxufVxuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBQcmludFNlcnZpY2Uge1xuICB6aXBGaWxlOiBKU1ppcDtcbiAgbmJGaWxlVG9Qcm9jZXNzOiBudW1iZXI7XG4gIGFjdGl2aXR5SWQ6IHN0cmluZztcbiAgaW1nU2l6ZUFkZGVkOiBBcnJheTxudW1iZXI+O1xuXG4gIFRFWFRQREZGT05UID0ge1xuICAgIHRpdGxlRm9udDogJ1RpbWVzJyxcbiAgICB0aXRsZUZvbnRTdHlsZTogJ2JvbGQnLFxuICAgIHN1YnRpdGxlRm9udDogJ1RpbWVzJyxcbiAgICBzdWJ0aXRsZUZvbnRTdHlsZTogJ2JvbGQnLFxuICAgIGNvbW1lbnRGb250OiAnY291cmllcicsXG4gICAgY29tbWVudEZvbnRTdHlsZTogJ25vcm1hbCcsXG4gICAgY29tbWVudEZvbnRTaXplOiAxNlxuICB9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcbiAgICBwcml2YXRlIG1lc3NhZ2VTZXJ2aWNlOiBNZXNzYWdlU2VydmljZSxcbiAgICBwcml2YXRlIGFjdGl2aXR5U2VydmljZTogQWN0aXZpdHlTZXJ2aWNlLFxuICAgIHByaXZhdGUgbGFuZ3VhZ2VTZXJ2aWNlOiBMYW5ndWFnZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBjb25maWdTZXJ2aWNlOiBDb25maWdTZXJ2aWNlXG4gICkge31cblxuICBwcmludChtYXA6IElnb01hcCwgb3B0aW9uczogUHJpbnRPcHRpb25zKTogU3ViamVjdDxhbnk+IHtcbiAgICBjb25zdCBzdGF0dXMkID0gbmV3IFN1YmplY3QoKTtcbiAgICBjb25zdCBwYXBlckZvcm1hdDogc3RyaW5nID0gb3B0aW9ucy5wYXBlckZvcm1hdDtcbiAgICBjb25zdCByZXNvbHV0aW9uID0gK29wdGlvbnMucmVzb2x1dGlvbjsgLy8gRGVmYXVsdCBpcyA5NlxuICAgIGNvbnN0IG9yaWVudGF0aW9uID0gb3B0aW9ucy5vcmllbnRhdGlvbjtcbiAgICBjb25zdCBsZWdlbmRQb3N0aW9uID0gb3B0aW9ucy5sZWdlbmRQb3NpdGlvbjtcbiAgICB0aGlzLmFjdGl2aXR5SWQgPSB0aGlzLmFjdGl2aXR5U2VydmljZS5yZWdpc3RlcigpO1xuXG4gICAgR2VvUGRmUGx1Z2luKGpzUERGLkFQSSk7XG5cbiAgICBjb25zdCBkb2MgPSBuZXcganNQREYoe1xuICAgICAgb3JpZW50YXRpb24sXG4gICAgICBmb3JtYXQ6IHBhcGVyRm9ybWF0LnRvTG93ZXJDYXNlKCksXG4gICAgICB1bml0OiAnbW0nIC8vIGRlZmF1bHRcbiAgICB9KTtcblxuICAgIGNvbnN0IGRpbWVuc2lvbnMgPSBbXG4gICAgICBkb2MuaW50ZXJuYWwucGFnZVNpemUud2lkdGgsXG4gICAgICBkb2MuaW50ZXJuYWwucGFnZVNpemUuaGVpZ2h0XG4gICAgXTtcblxuICAgIGNvbnN0IG1hcmdpbnMgPSBbMTAsIDEwLCAxMCwgMTBdO1xuICAgIGNvbnN0IHdpZHRoID0gZGltZW5zaW9uc1swXSAtIG1hcmdpbnNbM10gLSBtYXJnaW5zWzFdO1xuICAgIGNvbnN0IGhlaWdodCA9IGRpbWVuc2lvbnNbMV0gLSBtYXJnaW5zWzBdIC0gbWFyZ2luc1syXTtcbiAgICBjb25zdCBzaXplID0gW3dpZHRoLCBoZWlnaHRdO1xuICAgIGxldCB0aXRsZVNpemVzOiBUZXh0UGRmU2l6ZUFuZE1hcmdpbjtcbiAgICBsZXQgc3VidGl0bGVTaXplczogVGV4dFBkZlNpemVBbmRNYXJnaW47XG5cbiAgICAvLyBQREYgdGl0bGVcbiAgICBpZiAob3B0aW9ucy50aXRsZSAhPT0gdW5kZWZpbmVkICkge1xuICAgICAgY29uc3QgZm9udFNpemVJblB0ID0gTWF0aC5yb3VuZCgyICogKGhlaWdodCArIDE0NSkgKiAwLjA1KSAvIDI7IC8vY2FsY3VsYXRlIHRoZSBmb250U2l6ZSB0aXRsZSBmcm9tIHRoZSBwYWdlIGhlaWdodC5cbiAgICAgIHRpdGxlU2l6ZXMgPSB0aGlzLmdldFRleHRQZGZPYmplY3RTaXplQW5kTWFyZyhvcHRpb25zLnRpdGxlLFxuICAgICAgICBtYXJnaW5zLFxuICAgICAgICB0aGlzLlRFWFRQREZGT05ULnRpdGxlRm9udCxcbiAgICAgICAgZm9udFNpemVJblB0LFxuICAgICAgICB0aGlzLlRFWFRQREZGT05ULnRpdGxlRm9udFN0eWxlLFxuICAgICAgICBkb2MpO1xuXG4gICAgICB0aGlzLmFkZFRleHRJblBkZkRvYyhkb2MsXG4gICAgICAgIG9wdGlvbnMudGl0bGUsXG4gICAgICAgIHRoaXMuVEVYVFBERkZPTlQudGl0bGVGb250LFxuICAgICAgICB0aGlzLlRFWFRQREZGT05ULnRpdGxlRm9udFN0eWxlLFxuICAgICAgICB0aXRsZVNpemVzLmZvbnRTaXplLFxuICAgICAgICB0aXRsZVNpemVzLm1hcmdpbkxlZnQgKyBtYXJnaW5zWzNdLFxuICAgICAgICBtYXJnaW5zWzBdKTtcblxuICAgICAgbWFyZ2luc1swXSA9IHRpdGxlU2l6ZXMuaGVpZ2h0ICsgbWFyZ2luc1swXTsgLy8gY3VtdWxhdGl2ZSBtYXJnaW4gdG9wIGZvciBuZXh0IGVsZW0gdG8gcGxhY2UgaW4gcGRmIGRvY1xuXG4gICAgfVxuXG4gICAgLy8gUERGIHN1YnRpdGxlXG4gICAgaWYgKG9wdGlvbnMuc3VidGl0bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgc3VidGl0bGVTaXplcyA9IHRoaXMuZ2V0VGV4dFBkZk9iamVjdFNpemVBbmRNYXJnKG9wdGlvbnMuc3VidGl0bGUsXG4gICAgICAgIG1hcmdpbnMsXG4gICAgICAgIHRoaXMuVEVYVFBERkZPTlQuc3VidGl0bGVGb250LFxuICAgICAgICB0aXRsZVNpemVzLmZvbnRTaXplICogMC43LCAvLyA3MCUgc2l6ZSBvZiB0aXRsZVxuICAgICAgICB0aGlzLlRFWFRQREZGT05ULnN1YnRpdGxlRm9udFN0eWxlLFxuICAgICAgICBkb2MpO1xuXG4gICAgICAgdGhpcy5hZGRUZXh0SW5QZGZEb2MoZG9jLFxuICAgICAgICBvcHRpb25zLnN1YnRpdGxlLFxuICAgICAgICB0aGlzLlRFWFRQREZGT05ULnN1YnRpdGxlRm9udCxcbiAgICAgICAgdGhpcy5URVhUUERGRk9OVC5zdWJ0aXRsZUZvbnRTdHlsZSxcbiAgICAgICAgc3VidGl0bGVTaXplcy5mb250U2l6ZSxcbiAgICAgICAgc3VidGl0bGVTaXplcy5tYXJnaW5MZWZ0ICsgbWFyZ2luc1szXSxcbiAgICAgICAgbWFyZ2luc1swXVxuICAgICAgKTtcblxuICAgICAgbWFyZ2luc1swXSArPSA1OyAvLyBjdW11bGF0aXZlIG1hcmcgdG9wIGZvciBuZXh0IGVsZW0gdG8gcGxhY2UgaW4gcGRmIGRvYy4gNSBpcyBhIGZpeCBpdCBjb3VsZCBiZSBhZGp1c3RcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5zaG93UHJvamVjdGlvbiA9PT0gdHJ1ZSB8fCBvcHRpb25zLnNob3dTY2FsZSA9PT0gdHJ1ZSkge1xuICAgICAgdGhpcy5hZGRQcm9qU2NhbGUoXG4gICAgICAgIGRvYyxcbiAgICAgICAgbWFwLFxuICAgICAgICByZXNvbHV0aW9uLFxuICAgICAgICBvcHRpb25zLnNob3dQcm9qZWN0aW9uLFxuICAgICAgICBvcHRpb25zLnNob3dTY2FsZVxuICAgICAgICApO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5jb21tZW50ICE9PSAnJykge1xuICAgICAgdGhpcy5hZGRDb21tZW50KGRvYywgb3B0aW9ucy5jb21tZW50KTtcbiAgICB9XG5cbiAgICB0aGlzLmFkZE1hcChkb2MsIG1hcCwgcmVzb2x1dGlvbiwgc2l6ZSwgbWFyZ2lucykuc3Vic2NyaWJlKFxuICAgICAgYXN5bmMgKHN0YXR1czogU3ViamVjdFN0YXR1cykgPT4ge1xuICAgICAgICBpZiAoc3RhdHVzID09PSBTdWJqZWN0U3RhdHVzLkRvbmUpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmFkZFNjYWxlKGRvYywgbWFwLCBtYXJnaW5zKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZU1lYXN1cmVMYXllcihkb2MsIG1hcCwgbWFyZ2lucyk7XG5cbiAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuaW1nU2l6ZUFkZGVkWzBdO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaW1nU2l6ZUFkZGVkWzFdO1xuICAgICAgICAgIGNvbnN0IHJlcyA9IDE7XG4gICAgICAgICAgdGhpcy5hZGRHZW9SZWYoZG9jLCBtYXAsIHdpZHRoLCBoZWlnaHQsIHJlcywgbWFyZ2lucyk7XG5cbiAgICAgICAgICBpZiAob3B0aW9ucy5sZWdlbmRQb3NpdGlvbiAhPT0gJ25vbmUnKSB7XG4gICAgICAgICAgICBpZiAoWyd0b3BsZWZ0JywgJ3RvcHJpZ2h0JywgJ2JvdHRvbWxlZnQnLCAnYm90dG9tcmlnaHQnXS5pbmRleE9mKG9wdGlvbnMubGVnZW5kUG9zaXRpb24pID4gLTEgKSB7XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMuYWRkTGVnZW5kU2FtZVBhZ2UoZG9jLCBtYXAsIG1hcmdpbnMsIHJlc29sdXRpb24sIG9wdGlvbnMubGVnZW5kUG9zaXRpb24pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmxlZ2VuZFBvc2l0aW9uID09PSAnbmV3cGFnZScpIHtcbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy5hZGRMZWdlbmQoZG9jLCBtYXAsIG1hcmdpbnMsIHJlc29sdXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNhdmVEb2MoZG9jKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RhdHVzID09PSBTdWJqZWN0U3RhdHVzLkRvbmUgfHwgc3RhdHVzID09PSBTdWJqZWN0U3RhdHVzLkVycm9yKSB7XG4gICAgICAgICAgdGhpcy5hY3Rpdml0eVNlcnZpY2UudW5yZWdpc3Rlcih0aGlzLmFjdGl2aXR5SWQpO1xuICAgICAgICAgIHN0YXR1cyQubmV4dChTdWJqZWN0U3RhdHVzLkRvbmUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgKTtcblxuICAgIHJldHVybiBzdGF0dXMkO1xuICB9XG4gIC8vIHJlZiBHZW9Nb29zZSBodHRwczovL2dpdGh1Yi5jb20vZ2VvbW9vc2UvZ20zL3RyZWUvbWFpbi9zcmMvZ20zL2NvbXBvbmVudHMvcHJpbnRcbiAgYWRkR2VvUmVmKGRvYywgbWFwLCB3aWR0aCwgaGVpZ2h0LCByZXNvbHV0aW9uLCBtYXJnaW5zKSB7XG4gICAgY29uc3QgdW5pdCA9ICdtbSc7XG4gICAgY29uc3QgZG9jSGVpZ2h0ID0gZG9jLmludGVybmFsLnBhZ2VTaXplLmdldEhlaWdodCgpO1xuXG4gICAgLy8geCx5ID0gbWFyZ2luIGxlZnQtYm90dG9tIGNvcm5lciBmb3IgaW1nIGluIHBkZiBkb2NcbiAgICBjb25zdCB4ID0gbWFyZ2luc1szXTtcbiAgICBjb25zdCB5ID0gZG9jSGVpZ2h0IC0gbWFyZ2luc1swXSAtIGhlaWdodDtcblxuICAgIGxldCBwZGZfZXh0ZW50cyA9IFt4LCB5LCB4ICsgd2lkdGgsIHkgKyBoZWlnaHRdO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBwZGZfZXh0ZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgcGRmX2V4dGVudHNbaV0gPSB0aGlzLnBkZl91bml0czJwb2ludHMocGRmX2V4dGVudHNbaV0sIHVuaXQpO1xuICAgIH1cblxuICAgIGNvbnN0IG1hcEV4dGVudCA9IG1hcC52aWV3Q29udHJvbGxlci5nZXRFeHRlbnQoJ0VQU0c6Mzg1NycpO1xuICAgIGRvYy5zZXRHZW9BcmVhKHBkZl9leHRlbnRzLCBtYXBFeHRlbnQpO1xuXG4gIH1cblxuICAvKipcbiAgICogQWRkIG1lYXN1cmUgb3ZlcmxheSBvbiB0aGUgbWFwIG9uIHRoZSBkb2N1bWVudCB3aGVuIHRoZSBtZWFzdXJlIGxheWVyIGlzIHByZXNlbnRcbiAgICogQHBhcmFtICBkb2MgLSBQZGYgZG9jdW1lbnQgd2hlcmUgbWVhc3VyZSB0b29sdGlwIHdpbGwgYmUgYWRkZWRcbiAgICogQHBhcmFtICBtYXAgLSBNYXAgb2YgdGhlIGFwcFxuICAgKiBAcGFyYW0gIG1hcmdpbnMgLSBQYWdlIG1hcmdpbnNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlTWVhc3VyZUxheWVyKFxuICAgIGRvYzoganNQREYsXG4gICAgbWFwOiBJZ29NYXAsXG4gICAgbWFyZ2luczogQXJyYXk8bnVtYmVyPlxuICApIHtcbiAgICBpZiAobWFwLmxheWVycy5maW5kKGxheWVyID0+IGxheWVyLnZpc2libGUgJiYgbGF5ZXIuaWQuc3RhcnRzV2l0aCgnaWdvLW1lYXN1cmVzLScpKSkge1xuICAgICAgbGV0IGNhbnZhc092ZXJsYXlIVE1MTWVhc3VyZXM7XG4gICAgICBjb25zdCBtYXBPdmVybGF5TWVhc3VyZXNIVE1MID0gbWFwLm9sLmdldE92ZXJsYXlDb250YWluZXIoKTtcbiAgICAgIGF3YWl0IGh0bWwyY2FudmFzKG1hcE92ZXJsYXlNZWFzdXJlc0hUTUwsIHtcbiAgICAgICAgc2NhbGU6IDEsXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogbnVsbFxuICAgICAgfSkudGhlbihlID0+IHtcbiAgICAgICAgY2FudmFzT3ZlcmxheUhUTUxNZWFzdXJlcyA9IGU7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuYWRkQ2FudmFzKGRvYywgY2FudmFzT3ZlcmxheUhUTUxNZWFzdXJlcywgbWFyZ2lucyk7IC8vIHRoaXMgYWRkcyBtZWFzdXJlIG92ZXJsYXlzXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBodG1sIGNvZGUgZm9yIGFsbCBsYXllcnMgbGVnZW5kXG4gICAqIEBwYXJhbSAgbWFwIElnb01hcFxuICAgKiBAcGFyYW0gIHdpZHRoIFRoZSB3aWR0aCB0aGF0IHRoZSBsZWdlbmQgbmVlZCB0byBiZVxuICAgKiBAcmV0dXJuIEh0bWwgY29kZSBmb3IgdGhlIGxlZ2VuZFxuICAgKi9cbiAgZ2V0TGF5ZXJzTGVnZW5kSHRtbChcbiAgICBtYXA6IElnb01hcCxcbiAgICB3aWR0aDogbnVtYmVyLFxuICAgIHJlc29sdXRpb246IG51bWJlclxuICApOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXIpID0+IHtcbiAgICAgIGxldCBodG1sID0gJyc7XG4gICAgICBjb25zdCBsZWdlbmRzID0gZ2V0TGF5ZXJzTGVnZW5kcyhcbiAgICAgICAgbWFwLmxheWVycyxcbiAgICAgICAge1xuICAgICAgICAgIHJlc29sdXRpb246IG1hcC52aWV3Q29udHJvbGxlci5nZXRSZXNvbHV0aW9uKCksXG4gICAgICAgICAgZXh0ZW50OiBtYXAudmlld0NvbnRyb2xsZXIuZ2V0RXh0ZW50KCksXG4gICAgICAgICAgcHJvamVjdGlvbjogbWFwLnZpZXdDb250cm9sbGVyLmdldE9sUHJvamVjdGlvbigpLmdldENvZGUoKSxcbiAgICAgICAgICAvLyBzY2FsZTogbWFwLnZpZXdDb250cm9sbGVyLmdldFNjYWxlKHJlc29sdXRpb24pLFxuICAgICAgICAgIHNpemU6IG1hcC5vbC5nZXRTaXplKClcbiAgICAgICAgfSBhcyBMZWdlbmRNYXBWaWV3T3B0aW9uc1xuICAgICAgKTtcbiAgICAgIGlmIChsZWdlbmRzLmZpbHRlcihsID0+IGwuZGlzcGxheSA9PT0gdHJ1ZSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIG9ic2VydmVyLm5leHQoaHRtbCk7XG4gICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIC8vIERlZmluZSBpbXBvcnRhbnQgc3R5bGUgdG8gYmUgc3VyZSB0aGF0IGFsbCBjb250YWluZXIgaXMgY29udmVydFxuICAgICAgLy8gdG8gaW1hZ2Ugbm90IGp1c3QgdmlzaWJsZSBwYXJ0XG4gICAgICBodG1sICs9ICc8c3R5bGUgbWVkaWE9XCJzY3JlZW5cIiB0eXBlPVwidGV4dC9jc3NcIj4nO1xuICAgICAgaHRtbCArPSAnLmh0bWwyY2FudmFzLWNvbnRhaW5lciB7IHdpZHRoOiAnICsgd2lkdGggKyAnbW0gIWltcG9ydGFudDsgaGVpZ2h0OiAyMDAwcHggIWltcG9ydGFudDsgfSc7XG4gICAgICBodG1sICs9ICd0YWJsZS50YWJsZUxlZ2VuZCB7dGFibGUtbGF5b3V0OiBhdXRvO30nO1xuICAgICAgaHRtbCArPSAnZGl2LnN0eWxlTGVnZW5kIHtwYWRkaW5nLXRvcDogNXB4OyBwYWRkaW5nLXJpZ2h0OjVweDtwYWRkaW5nLWxlZnQ6NXB4O3BhZGRpbmctYm90dG9tOjVweDt9JztcbiAgICAgIGh0bWwgKz0gJzwvc3R5bGU+JztcbiAgICAgIC8vIFRoZSBmb250IHNpemUgd2lsbCBhbHNvIGJlIGxvd2VyZWQgYWZ0ZXJ3YXJkcyAoZ2xvYmFsbHkgYWxvbmcgdGhlIGxlZ2VuZCBzaXplKVxuICAgICAgLy8gdGhpcyBhbGxvd3MgaGF2aW5nIGEgZ29vZCByZWxhdGl2ZSBmb250IHNpemUgaGVyZSBhbmQgdG8ga2VlcCBhanVzdGluZyB0aGUgbGVnZW5kIHNpemVcbiAgICAgIC8vIHdoaWxlIGtlZXBpbmcgZ29vZCByZWxhdGl2ZSBmb250IHNpemVcbiAgICAgIGh0bWwgKz0gJzxmb250IHNpemU9XCIzXCIgZmFjZT1cIlRpbWVzXCIgPic7XG4gICAgICBodG1sICs9ICc8ZGl2IGNsYXNzPVwic3R5bGVMZWdlbmRcIj4nO1xuICAgICAgaHRtbCArPSAnPHRhYmxlIGNsYXNzPVwidGFibGVMZWdlbmRcIiA+JztcblxuICAgICAgLy8gRm9yIGVhY2ggbGVnZW5kLCBkZWZpbmUgYW4gaHRtbCB0YWJsZSBjZWxsXG4gICAgICBjb25zdCBpbWFnZXMkID0gbGVnZW5kcy5maWx0ZXIobCA9PiBsLmRpc3BsYXkpLm1hcCgobGVnZW5kKSA9PlxuICAgICAgICB0aGlzLmdldERhdGFJbWFnZShsZWdlbmQudXJsKS5waXBlKFxuICAgICAgICAgIHJ4TWFwKChkYXRhSW1hZ2UpID0+IHtcbiAgICAgICAgICAgIGxldCBodG1sSW1nID0gJzx0cj48dGQ+JyArIGxlZ2VuZC50aXRsZS50b1VwcGVyQ2FzZSgpICsgJzwvdGQ+PC90cj4nO1xuICAgICAgICAgICAgaHRtbEltZyArPSAnPHRyPjx0ZD48aW1nIHNyYz1cIicgKyBkYXRhSW1hZ2UgKyAnXCI+PC90ZD48L3RyPic7XG4gICAgICAgICAgICByZXR1cm4gaHRtbEltZztcbiAgICAgICAgICB9KVxuICAgICAgICApXG4gICAgICApO1xuICAgICAgZm9ya0pvaW4oaW1hZ2VzJCkuc3Vic2NyaWJlKChkYXRhSW1hZ2VzKSA9PiB7XG4gICAgICAgIGh0bWwgPSBkYXRhSW1hZ2VzLnJlZHVjZSgoYWNjLCBjdXJyZW50KSA9PiAoYWNjICs9IGN1cnJlbnQpLCBodG1sKTtcbiAgICAgICAgaHRtbCArPSAnPC90YWJsZT4nO1xuICAgICAgICBodG1sICs9ICc8L2Rpdj4nO1xuICAgICAgICBvYnNlcnZlci5uZXh0KGh0bWwpO1xuICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXREYXRhSW1hZ2UodXJsOiBzdHJpbmcpOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuICAgIGNvbnN0IHNlY3VyZUlNRyA9IG5ldyBTZWN1cmVJbWFnZVBpcGUodGhpcy5odHRwLCB0aGlzLmNvbmZpZ1NlcnZpY2UpO1xuICAgIHJldHVybiBzZWN1cmVJTUcudHJhbnNmb3JtKHVybCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCB0aGUgbGVnZW5kIGluIGEgc2luZ2xlIGltYWdlXG4gICAqICogQHBhcmFtICBmb3JtYXQgLSBJbWFnZSBmb3JtYXQuIGRlZmF1bHQgdmFsdWUgdG8gXCJwbmdcIlxuICAgKiBAcmV0dXJuIFRoZSBpbWFnZSBvZiB0aGUgbGVnZW5kXG4gICAqL1xuICBhc3luYyBnZXRMYXllcnNMZWdlbmRJbWFnZShcbiAgICBtYXAsXG4gICAgZm9ybWF0OiBzdHJpbmcgPSAncG5nJyxcbiAgICBkb1ppcEZpbGU6IGJvb2xlYW4sXG4gICAgcmVzb2x1dGlvbjogbnVtYmVyXG4gICkge1xuICAgIGNvbnN0IHN0YXR1cyQgPSBuZXcgU3ViamVjdCgpO1xuICAgIC8vIEdldCBodG1sIGNvZGUgZm9yIHRoZSBsZWdlbmRcbiAgICBjb25zdCB3aWR0aCA9IDIwMDsgLy8gbWlsaW1ldGVycyB1bml0LCBvcmlnaW5hbGx5IGRlZmluZSBmb3IgZG9jdW1lbnQgcGRmXG4gICAgbGV0IGh0bWwgPSBhd2FpdCB0aGlzLmdldExheWVyc0xlZ2VuZEh0bWwoXG4gICAgICBtYXAsXG4gICAgICB3aWR0aCxcbiAgICAgIHJlc29sdXRpb25cbiAgICApLnRvUHJvbWlzZSgpO1xuICAgIGZvcm1hdCA9IGZvcm1hdC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgLy8gSWYgbm8gbGVnZW5kIHNob3cgTm8gTEVHRU5EIGluIGFuIGltYWdlXG4gICAgaWYgKGh0bWwubGVuZ3RoID09PSAwKSB7XG4gICAgICBodG1sID0gJzxmb250IHNpemU9XCIxMlwiIGZhY2U9XCJDb3VyaWVyIE5ld1wiID4nO1xuICAgICAgaHRtbCArPSAnPGRpdiBhbGlnbj1cImNlbnRlclwiPjxiPk5PIExFR0VORDwvYj48L2Rpdj4nO1xuICAgIH1cbiAgICAvLyBDcmVhdGUgZGl2IHRvIGNvbnRhaW4gaHRtbCBjb2RlIGZvciBsZWdlbmRcbiAgICBjb25zdCBkaXYgPSB3aW5kb3cuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZGl2LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBkaXYuc3R5bGUudG9wID0gJzAnO1xuXG4gICAgLy8gQWRkIGh0bWwgY29kZSB0byBjb252ZXJ0IGluIHRoZSBuZXcgd2luZG93XG4gICAgd2luZG93LmRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZGl2KTtcbiAgICBkaXYuaW5uZXJIVE1MID0gaHRtbDtcblxuICAgIGF3YWl0IHRoaXMudGltZW91dCgxKTtcbiAgICBjb25zdCBjYW52YXMgPSBhd2FpdCBodG1sMmNhbnZhcyhkaXYsIHsgdXNlQ09SUzogdHJ1ZSB9KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgfSk7XG5cbiAgICBpZiAoY2FudmFzKSB7XG4gICAgICBsZXQgc3RhdHVzID0gU3ViamVjdFN0YXR1cy5Eb25lO1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKCFkb1ppcEZpbGUpIHtcbiAgICAgICAgICAvLyBTYXZlIHRoZSBjYW52YXMgYXMgZmlsZVxuICAgICAgICAgIHRoaXMuc2F2ZUNhbnZhc0ltYWdlQXNGaWxlKGNhbnZhcywgJ2xlZ2VuZEltYWdlJywgZm9ybWF0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBBZGQgdGhlIGNhbnZhcyB0byB6aXBcbiAgICAgICAgICB0aGlzLmdlbmVyYXRlQ2FudmFGaWxlVG9aaXAoY2FudmFzLCAnbGVnZW5kSW1hZ2UnICsgJy4nICsgZm9ybWF0KTtcbiAgICAgICAgfVxuICAgICAgICBkaXYucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkaXYpOyAvLyByZW1vdmUgdGVtcCBkaXYgKElFKVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHN0YXR1cyA9IFN1YmplY3RTdGF0dXMuRXJyb3I7XG4gICAgICB9XG4gICAgICBzdGF0dXMkLm5leHQoc3RhdHVzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3RhdHVzJDtcbiAgfVxuXG5cbiAgZ2V0VGV4dFBkZk9iamVjdFNpemVBbmRNYXJnKHRleHQ6IHN0cmluZywgbWFyZ2lucywgZm9udDpzdHJpbmcsIGZvbnRTaXplSW5QdDogbnVtYmVyLCBmb250U3R5bGU6c3RyaW5nLCBkb2M6IGpzUERGKVxuICA6IFRleHRQZGZTaXplQW5kTWFyZ2luIHtcbiAgICBjb25zdCBwZGZSZXNvbHV0aW9uID0gOTY7XG4gICAgY29uc3QgZG9jV2lkdGggPSBkb2MuaW50ZXJuYWwucGFnZVNpemUuZ2V0V2lkdGgoKTtcbiAgICBjb25zdCBwYWdlV2lkdGggPSBkb2NXaWR0aCAtIG1hcmdpbnNbMV0gLSBtYXJnaW5zWzNdO1xuXG4gICAgLy8gaW1wb3J0YW50IHRvIHNldCBpdCBmaXJzdCwgdGhlIHRleHREaW1lbnNpb24gY2hhbmdlIHdoZW4gZm9udCBjaGFuZ2UhXG4gICAgZG9jLnNldEZvbnQoZm9udCwgZm9udFN0eWxlKTtcbiAgICBkb2Muc2V0Rm9udFNpemUoZm9udFNpemVJblB0KTtcblxuICAgIGxldCB0ZXh0RGltZW5zaW9ucyA9IGRvYy5nZXRUZXh0RGltZW5zaW9ucyh0ZXh0KTtcbiAgICBsZXQgdGV4dE1hcmdpbkxlZnQ6IG51bWJlcjtcblxuICAgIGlmICh0ZXh0RGltZW5zaW9ucy53ID4gcGFnZVdpZHRoKSB7XG4gICAgICAvLyBpZiB0aGUgdGV4dCBpcyB0byBsb25nLCByZWR1Y2UgZm9udFNpemUgNzAlIGFuZCB0aGUgb3ZlcmZsb3cgd2l0aCBiZSBjdXQgaW4gcHJpbnQuLi5cbiAgICAgIHRleHRNYXJnaW5MZWZ0ID0gMDtcbiAgICAgIGZvbnRTaXplSW5QdCA9IGZvbnRTaXplSW5QdCAqIDAuNztcbiAgICAgIGRvYy5zZXRGb250U2l6ZShmb250U2l6ZUluUHQpO1xuICAgICAgdGV4dERpbWVuc2lvbnMgPSBkb2MuZ2V0VGV4dERpbWVuc2lvbnModGV4dCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgdGV4dE1hcmdpbkxlZnQgPSAocGFnZVdpZHRoIC0gdGV4dERpbWVuc2lvbnMudyApIC8gMiA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICdmb250U2l6ZSc6IGZvbnRTaXplSW5QdCxcbiAgICAgICdtYXJnaW5MZWZ0JzogdGV4dE1hcmdpbkxlZnQsXG4gICAgICAnaGVpZ2h0JzogdGV4dERpbWVuc2lvbnMuaFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQWRkIGNvbW1lbnQgdG8gdGhlIGRvY3VtZW50XG4gICAqICogQHBhcmFtICBkb2MgLSBwZGYgZG9jdW1lbnRcbiAgICogKiBAcGFyYW0gIGNvbW1lbnQgLSBDb21tZW50IHRvIGFkZCBpbiB0aGUgZG9jdW1lbnRcbiAgICovXG4gIHByaXZhdGUgYWRkQ29tbWVudChkb2M6IGpzUERGLCBjb21tZW50OiBzdHJpbmcpIHtcbiAgICBjb25zdCBjb21tZW50TWFyZ2luTGVmdCA9IDIwOyAvL21hcmdpbiBsZWZ0IGFuZCBib3R0b20gaXMgZml4XG4gICAgY29uc3QgY29tbWVudE1hcmdpbkJvdHRvbSA9IDU7XG4gICAgY29uc3QgbWFyZ2luVG9wID0gZG9jLmludGVybmFsLnBhZ2VTaXplLmhlaWdodCAtIGNvbW1lbnRNYXJnaW5Cb3R0b207XG4gICAgdGhpcy4gYWRkVGV4dEluUGRmRG9jKGRvYyxjb21tZW50LFxuICAgICAgdGhpcy5URVhUUERGRk9OVC5jb21tZW50Rm9udCxcbiAgICAgIHRoaXMuVEVYVFBERkZPTlQuY29tbWVudEZvbnRTdHlsZSxcbiAgICAgIHRoaXMuVEVYVFBERkZPTlQuY29tbWVudEZvbnRTaXplLFxuICAgICAgY29tbWVudE1hcmdpbkxlZnQsXG4gICAgICBtYXJnaW5Ub3BcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRUZXh0SW5QZGZEb2MoZG9jOiBqc1BERixcbiAgICB0ZXh0VG9BZGQ6IHN0cmluZyxcbiAgICB0ZXh0Rm9udDogc3RyaW5nLFxuICAgIHRleHRGb250U3R5bGU6IHN0cmluZyxcbiAgICB0ZXh0Rm9udFNpemU6IG51bWJlcixcbiAgICB0ZXh0TWFyZ2luTGVmdDogbnVtYmVyLFxuICAgIHRleHRNYXJnaW5Ub3A6IG51bWJlcilcbiAgICB7XG4gICAgICBkb2Muc2V0Rm9udCh0ZXh0Rm9udCwgdGV4dEZvbnRTdHlsZSk7XG4gICAgICBkb2Muc2V0Rm9udFNpemUodGV4dEZvbnRTaXplKTtcbiAgICAgIGRvYy50ZXh0KHRleHRUb0FkZCwgdGV4dE1hcmdpbkxlZnQsIHRleHRNYXJnaW5Ub3ApO1xuICAgIH1cblxuICAvKipcbiAgICogQWRkIHByb2plY3Rpb24gYW5kL29yIHNjYWxlIHRvIHRoZSBkb2N1bWVudFxuICAgKiBAcGFyYW0gIGRvYyAtIHBkZiBkb2N1bWVudFxuICAgKiBAcGFyYW0gIG1hcCAtIE1hcCBvZiB0aGUgYXBwXG4gICAqIEBwYXJhbSAgZHBpIC0gRFBJIHJlc29sdXRpb24gb2YgdGhlIGRvY3VtZW50XG4gICAqIEBwYXJhbSAgcHJvamVjdGlvbiAtIEJvb2wgdG8gaW5kaWNhdGUgaWYgcHJvamVjdGlvbiBuZWVkIHRvIGJlIGFkZGVkXG4gICAqIEBwYXJhbSAgc2NhbGUgLSBCb29sIHRvIGluZGljYXRlIGlmIHNjYWxlIG5lZWQgdG8gYmUgYWRkZWRcbiAgICovXG4gIHByaXZhdGUgYWRkUHJvalNjYWxlKFxuICAgIGRvYzoganNQREYsXG4gICAgbWFwOiBJZ29NYXAsXG4gICAgZHBpOiBudW1iZXIsXG4gICAgcHJvamVjdGlvbjogYm9vbGVhbixcbiAgICBzY2FsZTogYm9vbGVhblxuICApIHtcbiAgICBjb25zdCB0cmFuc2xhdGUgPSB0aGlzLmxhbmd1YWdlU2VydmljZS50cmFuc2xhdGU7XG4gICAgY29uc3QgcHJvalNjYWxlU2l6ZSA9IDE2O1xuICAgIGNvbnN0IHByb2pTY2FsZU1hcmdpbkxlZnQgPSAyMDtcbiAgICBjb25zdCBtYXJnaW5Cb3R0b20gPSAxNTtcbiAgICBjb25zdCBoZWlnaHRQaXhlbHMgPSBkb2MuaW50ZXJuYWwucGFnZVNpemUuaGVpZ2h0IC0gbWFyZ2luQm90dG9tO1xuXG4gICAgbGV0IHRleHRQcm9qU2NhbGU6IHN0cmluZyA9ICcnO1xuICAgIGlmIChwcm9qZWN0aW9uID09PSB0cnVlKSB7XG4gICAgICBjb25zdCBwcm9qVGV4dCA9IHRyYW5zbGF0ZS5pbnN0YW50KCdpZ28uZ2VvLnByaW50Rm9ybS5wcm9qZWN0aW9uJyk7XG4gICAgICB0ZXh0UHJvalNjYWxlICs9IHByb2pUZXh0ICsgJzogJyArIG1hcC5wcm9qZWN0aW9uO1xuICAgIH1cbiAgICBpZiAoc2NhbGUgPT09IHRydWUpIHtcbiAgICAgIGlmIChwcm9qZWN0aW9uID09PSB0cnVlKSB7XG4gICAgICAgIHRleHRQcm9qU2NhbGUgKz0gJyAgICc7XG4gICAgICB9XG4gICAgICBjb25zdCBzY2FsZVRleHQgPSB0cmFuc2xhdGUuaW5zdGFudCgnaWdvLmdlby5wcmludEZvcm0uc2NhbGUnKTtcbiAgICAgIGNvbnN0IG1hcFNjYWxlID0gbWFwLnZpZXdDb250cm9sbGVyLmdldFNjYWxlKGRwaSk7XG4gICAgICB0ZXh0UHJvalNjYWxlICs9IHNjYWxlVGV4dCArICc6IH4gMSAvICcgKyBmb3JtYXRTY2FsZShtYXBTY2FsZSk7XG4gICAgfVxuICAgIGRvYy5zZXRGb250KCdjb3VyaWVyJyk7XG4gICAgZG9jLnNldEZvbnRTaXplKHByb2pTY2FsZVNpemUpO1xuICAgIGRvYy50ZXh0KHRleHRQcm9qU2NhbGUsIHByb2pTY2FsZU1hcmdpbkxlZnQsIGhlaWdodFBpeGVscyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIHRoZSBsZWdlbmQgdG8gdGhlIGRvY3VtZW50XG4gICAqIEBwYXJhbSAgZG9jIC0gUGRmIGRvY3VtZW50IHdoZXJlIGxlZ2VuZCB3aWxsIGJlIGFkZGVkXG4gICAqIEBwYXJhbSAgbWFwIC0gTWFwIG9mIHRoZSBhcHBcbiAgICogQHBhcmFtICBtYXJnaW5zIC0gUGFnZSBtYXJnaW5zXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGFkZExlZ2VuZChcbiAgICBkb2M6IGpzUERGLFxuICAgIG1hcDogSWdvTWFwLFxuICAgIG1hcmdpbnM6IEFycmF5PG51bWJlcj4sXG4gICAgcmVzb2x1dGlvbjogbnVtYmVyXG4gICkge1xuICAgIC8vIEdldCBodG1sIGNvZGUgZm9yIHRoZSBsZWdlbmRcbiAgICBjb25zdCB3aWR0aCA9IGRvYy5pbnRlcm5hbC5wYWdlU2l6ZS53aWR0aDtcbiAgICBjb25zdCBodG1sID0gYXdhaXQgdGhpcy5nZXRMYXllcnNMZWdlbmRIdG1sKFxuICAgICAgbWFwLFxuICAgICAgd2lkdGgsXG4gICAgICByZXNvbHV0aW9uXG4gICAgKS50b1Byb21pc2UoKTtcbiAgICAvLyBJZiBubyBsZWdlbmQsIHNhdmUgdGhlIG1hcCBkaXJlY3RseVxuICAgIGlmIChodG1sID09PSAnJykge1xuICAgICAgYXdhaXQgdGhpcy5zYXZlRG9jKGRvYyk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgLy8gQ3JlYXRlIGRpdiB0byBjb250YWluIGh0bWwgY29kZSBmb3IgbGVnZW5kXG4gICAgY29uc3QgZGl2ID0gd2luZG93LmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGRpdi5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgZGl2LnN0eWxlLnRvcCA9ICcwJztcblxuICAgIC8vIEFkZCBodG1sIGNvZGUgdG8gY29udmVydCBpbiB0aGUgbmV3IHdpbmRvd1xuICAgIHdpbmRvdy5kb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdik7XG4gICAgZGl2LmlubmVySFRNTCA9IGh0bWw7XG5cbiAgICBhd2FpdCB0aGlzLnRpbWVvdXQoMSk7XG4gICAgY29uc3QgY2FudmFzID0gYXdhaXQgaHRtbDJjYW52YXMoZGl2LCB7IHVzZUNPUlM6IHRydWUgfSkuY2F0Y2goKGUpID0+IHtcbiAgICAgIGNvbnNvbGUubG9nKGUpO1xuICAgIH0pO1xuXG4gICAgaWYgKGNhbnZhcykge1xuICAgICAgY29uc3QgcG91cmNlbnRhZ2VSZWR1Y3Rpb24gPSAwLjg1O1xuICAgICAgY29uc3QgaW1hZ2VTaXplID0gW3BvdXJjZW50YWdlUmVkdWN0aW9uICogKDI1LjQgKiBjYW52YXMud2lkdGgpIC8gcmVzb2x1dGlvbiwgcG91cmNlbnRhZ2VSZWR1Y3Rpb25cbiAgICAgICAgKiAoMjUuNCAqIGNhbnZhcy5oZWlnaHQpIC8gcmVzb2x1dGlvbl07XG4gICAgICBsZXQgaW1nRGF0YTtcbiAgICAgIGRvYy5hZGRQYWdlKCk7XG4gICAgICBpbWdEYXRhID0gY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvcG5nJyk7XG4gICAgICBkb2MuYWRkSW1hZ2UoaW1nRGF0YSwgJ1BORycsIDEwLCAxMCwgaW1hZ2VTaXplWzBdLCBpbWFnZVNpemVbMV0pO1xuICAgICAgZGl2LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZGl2KTsgLy8gcmVtb3ZlIHRlbXAgZGl2IChJRSBzdHlsZSlcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnNhdmVEb2MoZG9jKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCB0aGUgbGVnZW5kIHRvIHRoZSBkb2N1bWVudFxuICAgKiBAcGFyYW0gIGRvYyAtIFBkZiBkb2N1bWVudCB3aGVyZSBsZWdlbmQgd2lsbCBiZSBhZGRlZFxuICAgKiBAcGFyYW0gIG1hcCAtIE1hcCBvZiB0aGUgYXBwXG4gICAqIEBwYXJhbSAgbWFyZ2lucyAtIFBhZ2UgbWFyZ2luc1xuICAgKi9cbiAgICAgcHJpdmF0ZSBhc3luYyBhZGRMZWdlbmRTYW1lUGFnZShcbiAgICAgIGRvYzoganNQREYsXG4gICAgICBtYXA6IElnb01hcCxcbiAgICAgIG1hcmdpbnM6IEFycmF5PG51bWJlcj4sXG4gICAgICByZXNvbHV0aW9uOiBudW1iZXIsXG4gICAgICBsZWdlbmRQb3NpdGlvbjogc3RyaW5nXG4gICAgKSB7XG4gICAgICAvLyBHZXQgaHRtbCBjb2RlIGZvciB0aGUgbGVnZW5kXG4gICAgICBjb25zdCB3aWR0aCA9IGRvYy5pbnRlcm5hbC5wYWdlU2l6ZS53aWR0aDtcbiAgICAgIGNvbnN0IGh0bWwgPSBhd2FpdCB0aGlzLmdldExheWVyc0xlZ2VuZEh0bWwoXG4gICAgICAgIG1hcCxcbiAgICAgICAgd2lkdGgsXG4gICAgICAgIHJlc29sdXRpb25cbiAgICAgICkudG9Qcm9taXNlKCk7XG4gICAgICAvLyBJZiBubyBsZWdlbmQsIHNhdmUgdGhlIG1hcCBkaXJlY3RseVxuICAgICAgaWYgKGh0bWwgPT09ICcnKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2F2ZURvYyhkb2MpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIC8vIENyZWF0ZSBkaXYgdG8gY29udGFpbiBodG1sIGNvZGUgZm9yIGxlZ2VuZFxuICAgICAgY29uc3QgZGl2ID0gd2luZG93LmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgZGl2LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgIGRpdi5zdHlsZS50b3AgPSAnMCc7XG4gICAgICAvLyBBZGQgaHRtbCBjb2RlIHRvIGNvbnZlcnQgaW4gdGhlIG5ldyB3aW5kb3dcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdik7XG4gICAgICBkaXYuaW5uZXJIVE1MID0gaHRtbDtcbiAgICAgIGF3YWl0IHRoaXMudGltZW91dCgxKTtcbiAgICAgIGNvbnN0IGNhbnZhcyA9IGF3YWl0IGh0bWwyY2FudmFzKGRpdiwgeyB1c2VDT1JTOiB0cnVlIH0pLmNhdGNoKChlKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKGUpO1xuICAgICAgfSk7XG4gICAgICBsZXQgbWFyZ2luc0xlZ2VuZDtcbiAgICAgIGlmIChjYW52YXMpIHtcbiAgICAgICAgY29uc3QgcG91cmNlbnRhZ2VSZWR1Y3Rpb24gPSAwLjg1O1xuICAgICAgICBjb25zdCBpbWFnZVNpemUgPSBbcG91cmNlbnRhZ2VSZWR1Y3Rpb24gKiAoMjUuNCAqIGNhbnZhcy53aWR0aCkgLyByZXNvbHV0aW9uLFxuICAgICAgICAgICBwb3VyY2VudGFnZVJlZHVjdGlvbiAqICgyNS40ICogY2FudmFzLmhlaWdodCkgLyByZXNvbHV0aW9uXTtcbiAgICAgICAgLy8gTW92ZSB0aGUgbGVnZW5kIHRvIHRoZSBjb3JyZWN0IHBvc2l0aW9uIG9uIHRoZSBwYWdlXG4gICAgICAgIGlmICggbGVnZW5kUG9zaXRpb24gPT09ICdib3R0b21yaWdodCcpIHtcbiAgICAgICAgICBtYXJnaW5zTGVnZW5kID0gW2RvYy5pbnRlcm5hbC5wYWdlU2l6ZS5oZWlnaHQgLSBtYXJnaW5zWzJdIC0gaW1hZ2VTaXplWzFdLCBtYXJnaW5zWzFdLFxuICAgICAgICAgICBtYXJnaW5zWzJdLCBkb2MuaW50ZXJuYWwucGFnZVNpemUud2lkdGggLSBtYXJnaW5zWzFdIC0gaW1hZ2VTaXplWzBdXTtcbiAgICAgICAgfSBlbHNlIGlmIChsZWdlbmRQb3NpdGlvbiA9PT0gJ3RvcHJpZ2h0Jykge1xuICAgICAgICAgIG1hcmdpbnNMZWdlbmQgPSBbbWFyZ2luc1swXSwgbWFyZ2luc1sxXSwgZG9jLmludGVybmFsLnBhZ2VTaXplLmhlaWdodCAtIG1hcmdpbnNbMF0gLSBpbWFnZVNpemVbMV0sXG4gICAgICAgICAgZG9jLmludGVybmFsLnBhZ2VTaXplLndpZHRoIC0gbWFyZ2luc1sxXSAtIGltYWdlU2l6ZVswXSBdO1xuICAgICAgICB9IGVsc2UgaWYgKGxlZ2VuZFBvc2l0aW9uID09PSAnYm90dG9tbGVmdCcpIHtcbiAgICAgICAgICAvLyBXaGVuIHRoZSBsZWdlbmQgaXMgaW4gdGhlIGJvdHRvbSBsZWZ0LCByYWlzZSB0aGUgbGVnZW5kIHNsaWdodGx5IHVwd2FyZCBzbyB0aGF0IGF0dHJpYnV0aW9ucyBhcmUgdmlzaWJsZVxuICAgICAgICAgIG1hcmdpbnNMZWdlbmQgPSBbZG9jLmludGVybmFsLnBhZ2VTaXplLmhlaWdodCAtIG1hcmdpbnNbMl0gLSBpbWFnZVNpemVbMV0gLSAxNSxcbiAgICAgICAgICBkb2MuaW50ZXJuYWwucGFnZVNpemUud2lkdGggLSBtYXJnaW5zWzNdIC0gaW1hZ2VTaXplWzBdLCBtYXJnaW5zWzJdICsgMTUsIG1hcmdpbnNbM10gXTtcbiAgICAgICAgfSBlbHNlIGlmIChsZWdlbmRQb3NpdGlvbiA9PT0gJ3RvcGxlZnQnKSB7XG4gICAgICAgICAgbWFyZ2luc0xlZ2VuZCA9IFttYXJnaW5zWzBdLCBkb2MuaW50ZXJuYWwucGFnZVNpemUud2lkdGggLSBtYXJnaW5zWzNdIC0gaW1hZ2VTaXplWzBdLFxuICAgICAgICAgICBkb2MuaW50ZXJuYWwucGFnZVNpemUuaGVpZ2h0IC0gbWFyZ2luc1swXSAtIGltYWdlU2l6ZVsxXSwgbWFyZ2luc1szXSBdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWRkQ2FudmFzKGRvYywgY2FudmFzLCBtYXJnaW5zTGVnZW5kKTsgLy8gdGhpcyBhZGRzIHRoZSBsZWdlbmRcbiAgICAgICAgZGl2LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZGl2KTsgLy8gcmVtb3ZlIHRlbXAgZGl2IChJRSBzdHlsZSlcbiAgICAgICAgYXdhaXQgdGhpcy5zYXZlRG9jKGRvYyk7XG4gICAgICB9XG4gICAgfVxuXG4gIC8qKlxuICAgKiBBZGQgc2NhbGUgYW5kIGF0dHJpYnV0aW9ucyBvbiB0aGUgbWFwIG9uIHRoZSBkb2N1bWVudFxuICAgKiBAcGFyYW0gIGRvYyAtIFBkZiBkb2N1bWVudCB3aGVyZSBsZWdlbmQgd2lsbCBiZSBhZGRlZFxuICAgKiBAcGFyYW0gIG1hcCAtIE1hcCBvZiB0aGUgYXBwXG4gICAqIEBwYXJhbSAgbWFyZ2lucyAtIFBhZ2UgbWFyZ2luc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBhZGRTY2FsZShcbiAgICBkb2M6IGpzUERGLFxuICAgIG1hcDogSWdvTWFwLFxuICAgIG1hcmdpbnM6IEFycmF5PG51bWJlcj5cbiAgICApIHtcbiAgICAgIGNvbnN0IG1hcFNpemUgPSBtYXAub2wuZ2V0U2l6ZSgpO1xuICAgICAgY29uc3QgZXh0ZW50ID0gbWFwLm9sLmdldFZpZXcoKS5jYWxjdWxhdGVFeHRlbnQobWFwU2l6ZSk7XG4gICAgICAvLyBHZXQgdGhlIHNjYWxlIGFuZCBhdHRyaWJ1dGlvblxuICAgICAgLy8gd2UgdXNlIGNsb25lTm9kZSB0byBtb2RpZnkgdGhlIG5vZGVzIHRvIHByaW50IHdpdGhvdXQgbW9kaWZ5aW5nIGl0IG9uIHRoZSBwYWdlLCB1c2luZyBkZWVwOnRydWUgdG8gZ2V0IGNoaWxkcmVuXG4gICAgICBsZXQgY2FudmFzT3ZlcmxheUhUTUw7XG4gICAgICBjb25zdCBtYXBPdmVybGF5SFRNTCA9IG1hcC5vbC5nZXRPdmVybGF5Q29udGFpbmVyU3RvcEV2ZW50KCk7XG4gICAgICAvLyBSZW1vdmUgdGhlIFVJIGJ1dHRvbnMgZnJvbSB0aGUgbm9kZXNcbiAgICAgIGNvbnN0IE92ZXJsYXlIVE1MQnV0dG9ucyA9IG1hcE92ZXJsYXlIVE1MLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdidXR0b24nKTtcbiAgICAgIGNvbnN0IE92ZXJsYXlIVE1MQnV0dG9uc2FyciA9IEFycmF5LmZyb20oT3ZlcmxheUhUTUxCdXR0b25zKTtcbiAgICAgIGZvciAoY29uc3QgT3ZlcmxheUhUTUxCdXR0b24gb2YgT3ZlcmxheUhUTUxCdXR0b25zYXJyKSB7XG4gICAgICAgIE92ZXJsYXlIVE1MQnV0dG9uLnNldEF0dHJpYnV0ZSgnZGF0YS1odG1sMmNhbnZhcy1pZ25vcmUnLCAndHJ1ZScpO1xuICAgICAgfVxuICAgICAgLy8gQ2hhbmdlIHRoZSBzdHlsZXMgb2YgaHlwZXJsaW5rIGluIHRoZSBwcmludGVkIHZlcnNpb25cbiAgICAgIC8vIFRyYW5zZm9ybSB0aGUgT3ZlcmxheSBpbnRvIGEgY2FudmFzXG4gICAgICAvLyBzY2FsZSBpcyBuZWNlc3NhcnkgdG8gbWFrZSBpdCBpbiBnb29nbGUgY2hyb21lXG4gICAgICAvLyBiYWNrZ3JvdW5kIGFzIG51bGwgYmVjYXVzZSBvdGhlcndpc2UgaXQgaXMgd2hpdGUgYW5kIGNvdmVyIHRoZSBtYXBcbiAgICAgIC8vIGFsbG93dGFpbnQgaXMgdG8gYWxsb3cgcmVuZGVyaW5nIGltYWdlcyBpbiB0aGUgYXR0cmlidXRpb25zXG4gICAgICAvLyB1c2VDT1JTOiB0cnVlIHBvdXIgcGVybWV0dHJlIGRlIHJlbmRlcmVyIGxlcyBpbWFnZXMgKG5lIG1hcmNoZSBwYXMgZW4gbG9jYWwpXG4gICAgICBjb25zdCBjYW52YXMgPSBhd2FpdCBodG1sMmNhbnZhcyhtYXBPdmVybGF5SFRNTCwge1xuICAgICAgICBzY2FsZTogMSxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiBudWxsLFxuICAgICAgICBhbGxvd1RhaW50OiB0cnVlLFxuICAgICAgICB1c2VDT1JTOiB0cnVlLFxuICAgICAgfSkudGhlbiggZSA9PiB7XG4gICAgICAgIGNhbnZhc092ZXJsYXlIVE1MID0gZTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5hZGRDYW52YXMoZG9jLCBjYW52YXNPdmVybGF5SFRNTCwgbWFyZ2lucyk7IC8vIHRoaXMgYWRkcyBzY2FsZXMgYW5kIGF0dHJpYnV0aW9uc1xuIH1cblxuICBkZWZpbmVOYkZpbGVUb1Byb2Nlc3MobmJGaWxlVG9Qcm9jZXNzKSB7XG4gICAgdGhpcy5uYkZpbGVUb1Byb2Nlc3MgPSBuYkZpbGVUb1Byb2Nlc3M7XG4gIH1cblxuICBwcml2YXRlIHRpbWVvdXQobXMpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkQ2FudmFzKFxuICAgIGRvYzoganNQREYsXG4gICAgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCxcbiAgICBtYXJnaW5zOiBBcnJheTxudW1iZXI+XG4gICkge1xuICAgIGxldCBpbWFnZTtcbiAgICBpZiAoY2FudmFzKSB7XG4gICAgICBpbWFnZSA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xuICAgIH1cblxuICAgIGlmIChpbWFnZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoaW1hZ2UubGVuZ3RoIDwgMjAgKSB7IC8vICBpbWcgaXMgY29ycnVwdCAgICB0b2RvOiBmaXggYWRkU2NhbGUgaW4gbW9iaWxlIG1ha2UgYSBjb3JydXB0IGltZ1xuICAgICAgICBjb25zb2xlLmxvZygnV2FybmluZzogQW4gaW1hZ2UgY2Fubm90IGJlIHByaW50IGluIHBkZiBmaWxlJyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGltYWdlU2l6ZSA9IHRoaXMuZ2V0SW1hZ2VTaXplVG9GaXRQZGYoZG9jLCBjYW52YXMsIG1hcmdpbnMpO1xuICAgICAgZG9jLmFkZEltYWdlKFxuICAgICAgICBpbWFnZSxcbiAgICAgICAgJ1BORycsXG4gICAgICAgIG1hcmdpbnNbM10sXG4gICAgICAgIG1hcmdpbnNbMF0sXG4gICAgICAgIGltYWdlU2l6ZVswXSxcbiAgICAgICAgaW1hZ2VTaXplWzFdXG4gICAgICApO1xuICAgICAgZG9jLnJlY3QobWFyZ2luc1szXSwgbWFyZ2luc1swXSwgaW1hZ2VTaXplWzBdLCBpbWFnZVNpemVbMV0pO1xuICAgICAgdGhpcy5pbWdTaXplQWRkZWQgPSBpbWFnZVNpemU7IC8vIGtlZXAgaW1nIHNpemUgZm9yIGdlb3JlZiBsYXRlclxuICAgIH1cbiAgfVxuXG4gIC8vIFRPRE8gZml4IHByaW50aW5nIHdpdGggaW1hZ2UgcmVzb2x1dGlvblxuICBwcml2YXRlIGFkZE1hcChcbiAgICBkb2M6IGpzUERGLFxuICAgIG1hcDogSWdvTWFwLFxuICAgIHJlc29sdXRpb246IG51bWJlcixcbiAgICBzaXplOiBBcnJheTxudW1iZXI+LFxuICAgIG1hcmdpbnM6IEFycmF5PG51bWJlcj5cbiAgKSB7XG4gICAgY29uc3Qgc3RhdHVzJCA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgICBjb25zdCBtYXBTaXplID0gbWFwLm9sLmdldFNpemUoKTtcbiAgICBjb25zdCBleHRlbnQgPSBtYXAub2wuZ2V0VmlldygpLmNhbGN1bGF0ZUV4dGVudChtYXBTaXplKTtcblxuICAgIGNvbnN0IHdpZHRoUGl4ZWxzID0gTWF0aC5yb3VuZCgoc2l6ZVswXSAqIHJlc29sdXRpb24pIC8gMjUuNCk7XG4gICAgY29uc3QgaGVpZ2h0UGl4ZWxzID0gTWF0aC5yb3VuZCgoc2l6ZVsxXSAqIHJlc29sdXRpb24pIC8gMjUuNCk7XG5cbiAgICBsZXQgdGltZW91dDtcblxuICAgIG1hcC5vbC5vbmNlKCdyZW5kZXJjb21wbGV0ZScsIChldmVudDogYW55KSA9PiB7XG4gICAgICBjb25zdCBjYW52YXNlcyA9IGV2ZW50LnRhcmdldC5nZXRWaWV3cG9ydCgpLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdjYW52YXMnKTtcbiAgICAgIGNvbnN0IG1hcFN0YXR1cyQkID0gbWFwLnN0YXR1cyQuc3Vic2NyaWJlKChtYXBTdGF0dXM6IFN1YmplY3RTdGF0dXMpID0+IHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIGlmIChtYXBTdGF0dXMgIT09IFN1YmplY3RTdGF0dXMuRG9uZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIG1hcFN0YXR1cyQkLnVuc3Vic2NyaWJlKCk7XG5cbiAgICAgICAgbGV0IHN0YXR1cyA9IFN1YmplY3RTdGF0dXMuRG9uZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmb3IgKGNvbnN0IGNhbnZhcyBvZiBjYW52YXNlcykge1xuICAgICAgICAgICAgaWYgKGNhbnZhcy53aWR0aCAhPT0gMCkge1xuICAgICAgICAgICAgICB0aGlzLmFkZENhbnZhcyhkb2MsIGNhbnZhcywgbWFyZ2lucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBzdGF0dXMgPSBTdWJqZWN0U3RhdHVzLkVycm9yO1xuICAgICAgICAgIHRoaXMubWVzc2FnZVNlcnZpY2UuZXJyb3IoXG4gICAgICAgICAgICB0aGlzLmxhbmd1YWdlU2VydmljZS50cmFuc2xhdGUuaW5zdGFudChcbiAgICAgICAgICAgICAgJ2lnby5nZW8ucHJpbnRGb3JtLmNvcnNFcnJvck1lc3NhZ2VCb2R5J1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHRoaXMubGFuZ3VhZ2VTZXJ2aWNlLnRyYW5zbGF0ZS5pbnN0YW50KFxuICAgICAgICAgICAgICAnaWdvLmdlby5wcmludEZvcm0uY29yc0Vycm9yTWVzc2FnZUhlYWRlcidcbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVuZGVyTWFwKG1hcCwgbWFwU2l6ZSwgZXh0ZW50KTtcbiAgICAgICAgc3RhdHVzJC5uZXh0KHN0YXR1cyk7XG4gICAgICB9KTtcblxuICAgICAgLy8gSWYgbm8gbG9hZGluZyBhcyBzdGFydGVkIGFmdGVyIDIwMG1zLCB0aGVuIHByb2JhYmx5IG5vIGxvYWRpbmdcbiAgICAgIC8vIGlzIHJlcXVpcmVkLlxuICAgICAgdGltZW91dCA9IHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgbWFwU3RhdHVzJCQudW5zdWJzY3JpYmUoKTtcblxuICAgICAgICBsZXQgc3RhdHVzID0gU3ViamVjdFN0YXR1cy5Eb25lO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGZvciAoY29uc3QgY2FudmFzIG9mIGNhbnZhc2VzKSB7XG4gICAgICAgICAgICBpZiAoY2FudmFzLndpZHRoICE9PSAwKSB7XG4gICAgICAgICAgICAgIHRoaXMuYWRkQ2FudmFzKGRvYywgY2FudmFzLCBtYXJnaW5zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIHN0YXR1cyA9IFN1YmplY3RTdGF0dXMuRXJyb3I7XG4gICAgICAgICAgdGhpcy5tZXNzYWdlU2VydmljZS5lcnJvcihcbiAgICAgICAgICAgIHRoaXMubGFuZ3VhZ2VTZXJ2aWNlLnRyYW5zbGF0ZS5pbnN0YW50KFxuICAgICAgICAgICAgICAnaWdvLmdlby5wcmludEZvcm0uY29yc0Vycm9yTWVzc2FnZUJvZHknXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgdGhpcy5sYW5ndWFnZVNlcnZpY2UudHJhbnNsYXRlLmluc3RhbnQoXG4gICAgICAgICAgICAgICdpZ28uZ2VvLnByaW50Rm9ybS5jb3JzRXJyb3JNZXNzYWdlSGVhZGVyJ1xuICAgICAgICAgICAgKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW5kZXJNYXAobWFwLCBtYXBTaXplLCBleHRlbnQpO1xuICAgICAgICBzdGF0dXMkLm5leHQoc3RhdHVzKTtcbiAgICAgIH0sIDIwMCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLnJlbmRlck1hcChtYXAsIFt3aWR0aFBpeGVscywgaGVpZ2h0UGl4ZWxzXSwgZXh0ZW50KTtcblxuICAgIHJldHVybiBzdGF0dXMkO1xuICB9XG5cbiAgLyoqXG4gICAqIERvd25sb2FkIGFuIGltYWdlIG9mIHRoZSBtYXAgd2l0aCBhZGRpdGlvbiBvZiBpbmZvcm1hdGlvbnNcbiAgICogQHBhcmFtICBtYXAgLSBNYXAgb2YgdGhlIGFwcFxuICAgKiBAcGFyYW0gIGZvcm1hdCAtIEltYWdlIGZvcm1hdC4gZGVmYXVsdCB2YWx1ZSB0byBcInBuZ1wiXG4gICAqIEBwYXJhbSAgcHJvamVjdGlvbiAtIEluZGljYXRlIGlmIHByb2plY3Rpb24gbmVlZCB0byBiZSBhZGQuIERlZmF1bHQgdG8gZmFsc2VcbiAgICogQHBhcmFtICBzY2FsZSAtIEluZGljYXRlIGlmIHNjYWxlIG5lZWQgdG8gYmUgYWRkLiBEZWZhdWx0IHRvIGZhbHNlXG4gICAqIEBwYXJhbSAgbGVnZW5kIC0gSW5kaWNhdGUgaWYgdGhlIGxlZ2VuZCBvZiBsYXllcnMgbmVlZCB0byBiZSBkb3dubG9hZC4gRGVmYXVsdCB0byBmYWxzZVxuICAgKiBAcGFyYW0gIHRpdGxlIC0gVGl0bGUgdG8gYWRkIGZvciB0aGUgbWFwIC0gRGVmYXVsdCB0byBibGFua1xuICAgKiBAcGFyYW0gIHN1YnRpdGxlIC0gU3VidGl0bGUgdG8gYWRkIGZvciB0aGUgbWFwIC0gRGVmYXVsdCB0byBibGFua1xuICAgKiBAcGFyYW0gIGNvbW1lbnQgLSBDb21tZW50IHRvIGFkZCBmb3IgdGhlIG1hcCAtIERlZmF1bHQgdG8gYmxhbmtcbiAgICogQHBhcmFtICBkb1ppcEZpbGUgLSBJbmRpY2F0ZSBpZiB3ZSBkbyBhIHppcCB3aXRoIHRoZSBmaWxlXG4gICAqIEByZXR1cm4gSW1hZ2UgZmlsZSBvZiB0aGUgbWFwIHdpdGggZXh0ZW5zaW9uIGZvcm1hdCBnaXZlbiBhcyBwYXJhbWV0ZXJcbiAgICovXG4gIGRvd25sb2FkTWFwSW1hZ2UoXG4gICAgbWFwOiBJZ29NYXAsXG4gICAgcmVzb2x1dGlvbjogbnVtYmVyLFxuICAgIGZvcm1hdCA9ICdwbmcnLFxuICAgIHByb2plY3Rpb24gPSBmYWxzZSxcbiAgICBzY2FsZSA9IGZhbHNlLFxuICAgIHRpdGxlID0gJycsXG4gICAgc3VidGl0bGUgPSAnJyxcbiAgICBjb21tZW50ID0gJycsXG4gICAgZG9aaXBGaWxlID0gdHJ1ZSxcbiAgICBsZWdlbmRQb3NpdGlvbjogc3RyaW5nXG4gICkge1xuICAgIGNvbnN0IHN0YXR1cyQgPSBuZXcgU3ViamVjdCgpO1xuICAgIC8vIGNvbnN0IHJlc29sdXRpb24gPSBtYXAub2wuZ2V0VmlldygpLmdldFJlc29sdXRpb24oKTtcbiAgICB0aGlzLmFjdGl2aXR5SWQgPSB0aGlzLmFjdGl2aXR5U2VydmljZS5yZWdpc3RlcigpO1xuICAgIGNvbnN0IHRyYW5zbGF0ZSA9IHRoaXMubGFuZ3VhZ2VTZXJ2aWNlLnRyYW5zbGF0ZTtcbiAgICBtYXAub2wub25jZSgncmVuZGVyY29tcGxldGUnLCBhc3luYyAoZXZlbnQ6IGFueSkgPT4ge1xuICAgICAgZm9ybWF0ID0gZm9ybWF0LnRvTG93ZXJDYXNlKCk7XG4gICAgICBjb25zdCBvbGRDYW52YXMgPSBldmVudC50YXJnZXRcbiAgICAgICAgLmdldFZpZXdwb3J0KClcbiAgICAgICAgLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdjYW52YXMnKVswXTtcbiAgICAgIGNvbnN0IG5ld0NhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgY29uc3QgbmV3Q29udGV4dCA9IG5ld0NhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgLy8gUG9zdGlvbiBpbiBoZWlnaHQgdG8gc2V0IHRoZSBjYW52YXMgaW4gbmV3IGNhbnZhc1xuICAgICAgbGV0IHBvc2l0aW9uSENhbnZhcyA9IDA7XG4gICAgICAvLyBHZXQgaGVpZ2h0L3dpZHRoIG9mIG1hcCBjYW52YXNcbiAgICAgIGNvbnN0IHdpZHRoID0gb2xkQ2FudmFzLndpZHRoO1xuICAgICAgbGV0IGhlaWdodCA9IG9sZENhbnZhcy5oZWlnaHQ7XG4gICAgICAvLyBTZXQgRm9udCB0byBjYWxjdWxhdGUgY29tbWVudCB3aWR0aFxuICAgICAgbmV3Q29udGV4dC5mb250ID0gJzIwcHggQ2FsaWJyaSc7XG4gICAgICBjb25zdCBjb21tZW50V2lkdGggPSBuZXdDb250ZXh0Lm1lYXN1cmVUZXh0KGNvbW1lbnQpLndpZHRoO1xuICAgICAgLy8gQWRkIGhlaWdodCBmb3IgdGl0bGUgaWYgZGVmaW5lZFxuICAgICAgaGVpZ2h0ID0gdGl0bGUgIT09ICcnID8gaGVpZ2h0ICsgMzAgOiBoZWlnaHQ7XG4gICAgICAvLyBBZGQgaGVpZ2h0IGZvciB0aXRsZSBpZiBkZWZpbmVkXG4gICAgICBoZWlnaHQgPSBzdWJ0aXRsZSAhPT0gJycgPyBoZWlnaHQgKyAzMCA6IGhlaWdodDtcbiAgICAgIC8vIEFkZCBoZWlnaHQgZm9yIHByb2plY3Rpb24gb3Igc2NhbGUgKHNhbWUgbGluZSkgaWYgZGVmaW5lZFxuICAgICAgaGVpZ2h0ID0gcHJvamVjdGlvbiAhPT0gZmFsc2UgfHwgc2NhbGUgIT09IGZhbHNlID8gaGVpZ2h0ICsgMzAgOiBoZWlnaHQ7XG4gICAgICBjb25zdCBwb3NpdGlvbkhQcm9qU2NhbGUgPSBoZWlnaHQgLSAxMDtcbiAgICAgIC8vIERlZmluZSBudW1iZXIgb2YgbGluZSBkZXBlbmRpbmcgb2YgdGhlIGNvbW1lbnQgbGVuZ3RoXG4gICAgICBjb25zdCBjb21tZW50TmJMaW5lID0gTWF0aC5jZWlsKGNvbW1lbnRXaWR0aCAvIHdpZHRoKTtcbiAgICAgIC8vIEFkZCBoZWlnaHQgZm9yIG11bHRpbGluZSBjb21tZW50IGlmIGRlZmluZWRcbiAgICAgIGhlaWdodCA9IGNvbW1lbnQgIT09ICcnID8gaGVpZ2h0ICsgY29tbWVudE5iTGluZSAqIDMwIDogaGVpZ2h0O1xuICAgICAgbGV0IHBvc2l0aW9uSENvbW1lbnQgPSBoZWlnaHQgLSBjb21tZW50TmJMaW5lICogMjAgKyA1O1xuICAgICAgLy8gU2V0IHRoZSBuZXcgY2FudmFzIHdpdGggdGhlIG5ldyBjYWxjdWxhdGVkIHNpemVcbiAgICAgIG5ld0NhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgbmV3Q2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgIGlmIChbJ2JtcCcsJ2dpZicsICdqcGVnJywgJ3BuZycsICd0aWZmJ10uaW5kZXhPZihmb3JtYXQpID4gLTEpIHtcbiAgICAgICAgLy8gUGF0Y2ggSnBlZyBkZWZhdWx0IGJsYWNrIGJhY2tncm91bmQgdG8gd2hpdGVcbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ2pwZWcnKSB7XG4gICAgICAgICAgbmV3Q29udGV4dC5maWxsU3R5bGUgPSAnI2ZmZmZmZic7XG4gICAgICAgICAgbmV3Q29udGV4dC5maWxsUmVjdCgwLCAwLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICBuZXdDb250ZXh0LmZpbGxTdHlsZSA9ICcjMDAwMDAwJztcbiAgICAgICAgfSBlbHNlIGlmICh0aXRsZSAhPT0gJycgfHwgc3VidGl0bGUgIT09ICcnIHx8IGNvbW1lbnQgIT09ICcnIHx8XG4gICAgICAgICAgICBwcm9qZWN0aW9uICE9PSBmYWxzZSB8fCBzY2FsZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgbmV3Q29udGV4dC5maWxsU3R5bGUgPSAnI2ZmZmZmZic7XG4gICAgICAgICAgICAgIG5ld0NvbnRleHQuZmlsbFJlY3QoMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICAgIG5ld0NvbnRleHQuZmlsbFN0eWxlID0gJyMwMDAwMDAnO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIElmIGEgdGl0bGUgbmVlZCB0byBiZSBhZGRlZCB0byBjYW52YXNcbiAgICAgIGlmICh0aXRsZSAhPT0gJycpIHtcbiAgICAgICAgLy8gU2V0IGZvbnQgZm9yIHRpdGxlXG4gICAgICAgIC8vIEFkanVzdCBhY2NvcmRpbmcgdG8gdGl0bGUgbGVuZ3RoXG4gICAgICAgIG5ld0NvbnRleHQuZm9udCA9ICcyNnB4IENhbGlicmknO1xuICAgICAgICBwb3NpdGlvbkhDYW52YXMgPSAzMDtcbiAgICAgICAgbmV3Q29udGV4dC50ZXh0QWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgbmV3Q29udGV4dC5maWxsVGV4dCh0aXRsZSwgd2lkdGggLyAyLCAyMCwgd2lkdGggKiAwLjkpO1xuICAgICAgfVxuICAgICAgaWYgKHN1YnRpdGxlICE9PSAnJykge1xuICAgICAgICAvLyBTZXQgZm9udCBmb3Igc3VidGl0bGVcbiAgICAgICAgLy8gQWRqdXN0IGFjY29yZGluZyB0byB0aXRsZSBsZW5ndGhcbiAgICAgICAgbmV3Q29udGV4dC5mb250ID0gJzI2cHggQ2FsaWJyaSc7XG4gICAgICAgIHBvc2l0aW9uSENhbnZhcyA9IDYwO1xuICAgICAgICBuZXdDb250ZXh0LnRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICBuZXdDb250ZXh0LmZpbGxUZXh0KHN1YnRpdGxlLCB3aWR0aCAvIDIsIDUwLCB3aWR0aCAqIDAuOSk7XG4gICAgICB9XG4gICAgICAvLyBTZXQgZm9udCBmb3IgbmV4dCBzZWN0aW9uXG4gICAgICBuZXdDb250ZXh0LmZvbnQgPSAnMjBweCBDYWxpYnJpJztcbiAgICAgIC8vIElmIHByb2plY3Rpb24gb3IvZW5kIHNjYWxlIG5lZWQgdG8gYmUgYWRkZWQgdG8gY2FudmFzXG4gICAgICBpZigocHJvamVjdGlvbiAhPT0gZmFsc2UpIHx8IChzY2FsZSAhPT0gZmFsc2UpKSB7XG4gICAgICAgIGxldCBwcm9qZWN0aW9uU2NhbGVUZXh0ID0gJyc7XG4gICAgICAgIGlmIChwcm9qZWN0aW9uICE9PSBmYWxzZSkge1xuICAgICAgICAgIGNvbnN0IHByb2pUZXh0ID0gdHJhbnNsYXRlLmluc3RhbnQoJ2lnby5nZW8ucHJpbnRGb3JtLnByb2plY3Rpb24nKTtcbiAgICAgICAgICBwcm9qZWN0aW9uU2NhbGVUZXh0ID0gcHJvalRleHQgKyAnOiAnICsgbWFwLnByb2plY3Rpb24gKyAnICAgICAgICAgJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzY2FsZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICBjb25zdCBzY2FsZVRleHQgPSB0cmFuc2xhdGUuaW5zdGFudCgnaWdvLmdlby5wcmludEZvcm0uc2NhbGUnKTtcbiAgICAgICAgICBjb25zdCBtYXBTY2FsZSA9IG1hcC52aWV3Q29udHJvbGxlci5nZXRTY2FsZShyZXNvbHV0aW9uKTtcbiAgICAgICAgICBwcm9qZWN0aW9uU2NhbGVUZXh0ICs9IHNjYWxlVGV4dCArICc6IH4gMSAvICcgKyBmb3JtYXRTY2FsZShtYXBTY2FsZSk7XG4gICAgICAgIH1cbiAgICAgICAgbmV3Q29udGV4dC50ZXh0QWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgbmV3Q29udGV4dC5maWxsVGV4dChwcm9qZWN0aW9uU2NhbGVUZXh0LCB3aWR0aCAvIDIsIHBvc2l0aW9uSFByb2pTY2FsZSwgd2lkdGggKiAwLjkpO1xuICAgICAgfVxuXG4gICAgICAvLyBJZiBhIGNvbW1lbnQgbmVlZCB0byBiZSBhZGRlZCB0byBjYW52YXNcbiAgICAgIGlmIChjb21tZW50ICE9PSAnJykge1xuICAgICAgICBuZXdDb250ZXh0LnRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAvLyBJZiBvbmx5IG9uZSBsaW5lLCBubyBuZWVkIHRvIG11bHRpbGluZSB0aGUgY29tbWVudFxuICAgICAgICBpZiAoY29tbWVudE5iTGluZSA9PT0gMSkge1xuICAgICAgICAgIG5ld0NvbnRleHQuZmlsbFRleHQoY29tbWVudCwgd2lkdGggLyAyLCBwb3NpdGlvbkhDb21tZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBTZXBhcmF0ZSB0aGUgc2V0ZW5zZXMgdG8gYmUgYXBwcm94LiB0aGUgc2FtZSBsZW5ndGhcbiAgICAgICAgICBjb25zdCBuYkNvbW1lbnRDaGFyID0gY29tbWVudC5sZW5ndGg7XG4gICAgICAgICAgY29uc3QgQ29tbWVudExlbmd0aFRvQ3V0ID0gTWF0aC5mbG9vcihuYkNvbW1lbnRDaGFyIC8gY29tbWVudE5iTGluZSk7XG4gICAgICAgICAgbGV0IGNvbW1lbnRDdXJyZW50TGluZSA9ICcnO1xuICAgICAgICAgIGxldCBwb3NpdGlvbkZpcnN0Q3V0Q2hhciA9IDA7XG4gICAgICAgICAgbGV0IHBvc2l0aW9uTGFzdEJsYW5rO1xuICAgICAgICAgIC8vIExvb3AgZm9yIHRoZSBudW1iZXIgb2YgbGluZSBjYWxjdWxhdGVkXG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb21tZW50TmJMaW5lOyBpKyspIHtcbiAgICAgICAgICAgIC8vIEZvciBhbGwgbGluZSBleGNlcHQgbGFzdFxuICAgICAgICAgICAgaWYgKGNvbW1lbnROYkxpbmUgLSAxID4gaSkge1xuICAgICAgICAgICAgICAvLyBHZXQgY29tbWVudCBjdXJyZW50IGxpbmUgdG8gZmluZCB0aGUgcmlnaHQgcGxhY2UgdHUgY3V0IGNvbW1lbnRcbiAgICAgICAgICAgICAgY29tbWVudEN1cnJlbnRMaW5lID0gY29tbWVudC5zdWJzdHIoXG4gICAgICAgICAgICAgICAgcG9zaXRpb25GaXJzdEN1dENoYXIsXG4gICAgICAgICAgICAgICAgQ29tbWVudExlbmd0aFRvQ3V0XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIC8vIEN1dCB0aGUgc2V0ZW5jZSBhdCBibGFua1xuICAgICAgICAgICAgICBwb3NpdGlvbkxhc3RCbGFuayA9IGNvbW1lbnRDdXJyZW50TGluZS5sYXN0SW5kZXhPZignICcpO1xuICAgICAgICAgICAgICBuZXdDb250ZXh0LmZpbGxUZXh0KFxuICAgICAgICAgICAgICAgIGNvbW1lbnRDdXJyZW50TGluZS5zdWJzdHIoMCwgcG9zaXRpb25MYXN0QmxhbmspLFxuICAgICAgICAgICAgICAgIHdpZHRoIC8gMixcbiAgICAgICAgICAgICAgICBwb3NpdGlvbkhDb21tZW50XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIHBvc2l0aW9uRmlyc3RDdXRDaGFyICs9IHBvc2l0aW9uTGFzdEJsYW5rO1xuICAgICAgICAgICAgICAvLyBHbyB0byBuZXh0IGxpbmUgZm9yIGluc2VydGlvblxuICAgICAgICAgICAgICBwb3NpdGlvbkhDb21tZW50ICs9IDIwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gRG9uJ3QgY3V0IGxhc3QgcGFydFxuICAgICAgICAgICAgICBuZXdDb250ZXh0LmZpbGxUZXh0KFxuICAgICAgICAgICAgICAgIGNvbW1lbnQuc3Vic3RyKHBvc2l0aW9uRmlyc3RDdXRDaGFyKSxcbiAgICAgICAgICAgICAgICB3aWR0aCAvIDIsXG4gICAgICAgICAgICAgICAgcG9zaXRpb25IQ29tbWVudFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBBZGQgbWFwIHRvIG5ldyBjYW52YXNcbiAgICAgIG5ld0NvbnRleHQuZHJhd0ltYWdlKG9sZENhbnZhcywgMCwgcG9zaXRpb25IQ2FudmFzKTtcblxuICAgICAgLy8gQ2hlY2sgdGhlIGxlZ2VuZFBvc2l0aW9uXG4gICAgICBpZiAobGVnZW5kUG9zaXRpb24gIT09ICdub25lJykge1xuICAgICAgICBpZiAoWyd0b3BsZWZ0JywgJ3RvcHJpZ2h0JywgJ2JvdHRvbWxlZnQnLCAnYm90dG9tcmlnaHQnXS5pbmRleE9mKGxlZ2VuZFBvc2l0aW9uKSA+IC0xKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5hZGRMZWdlbmRUb0ltYWdlKFxuICAgICAgICAgICAgbmV3Q2FudmFzLFxuICAgICAgICAgICAgbWFwLFxuICAgICAgICAgICAgcmVzb2x1dGlvbixcbiAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uLFxuICAgICAgICAgICAgZm9ybWF0XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBsZXQgc3RhdHVzID0gU3ViamVjdFN0YXR1cy5Eb25lO1xuICAgICAgbGV0IGZpbGVOYW1lV2l0aEV4dCA9ICdtYXAuJyArIGZvcm1hdDtcbiAgICAgIGlmIChmb3JtYXQudG9Mb3dlckNhc2UoKSA9PT0gJ3RpZmYnKSB7XG4gICAgICAgIGZpbGVOYW1lV2l0aEV4dCA9ICdtYXAnICsgbWFwLnByb2plY3Rpb24ucmVwbGFjZSgnOicsICdfJykgKyAnLicgKyBmb3JtYXQ7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIFNhdmUgdGhlIGNhbnZhcyBhcyBmaWxlXG4gICAgICAgIGlmICghZG9aaXBGaWxlKSB7XG4gICAgICAgICAgdGhpcy5zYXZlQ2FudmFzSW1hZ2VBc0ZpbGUobmV3Q2FudmFzLCBmaWxlTmFtZVdpdGhFeHQsIGZvcm1hdCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZm9ybWF0LnRvTG93ZXJDYXNlKCkgPT09ICd0aWZmJykge1xuICAgICAgICAgIC8vIEFkZCB0aGUgY2FudmFzIHRvIHppcFxuICAgICAgICAgIHRoaXMuZ2VuZXJhdGVDYW52YUZpbGVUb1ppcChuZXdDYW52YXMsIGZpbGVOYW1lV2l0aEV4dCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gQWRkIHRoZSBjYW52YXMgdG8gemlwXG4gICAgICAgICAgdGhpcy5nZW5lcmF0ZUNhbnZhRmlsZVRvWmlwKG5ld0NhbnZhcywgZmlsZU5hbWVXaXRoRXh0KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHN0YXR1cyA9IFN1YmplY3RTdGF0dXMuRXJyb3I7XG4gICAgICB9XG5cbiAgICAgIHN0YXR1cyQubmV4dChzdGF0dXMpO1xuXG4gICAgICBpZiAoZm9ybWF0LnRvTG93ZXJDYXNlKCkgPT09ICd0aWZmJykge1xuICAgICAgICBjb25zdCB0ZndGaWxlTmFtZVdpdGhFeHQgPSBmaWxlTmFtZVdpdGhFeHQuc3Vic3RyaW5nKDAsIGZpbGVOYW1lV2l0aEV4dC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJy50aWZmJykpICsgJy50ZncnO1xuICAgICAgICBjb25zdCB0aXdDb250ZW50ID0gdGhpcy5nZXRXb3JsZEZpbGVJbmZvcm1hdGlvbihtYXApO1xuICAgICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW3Rpd0NvbnRlbnRdLCB7XG4gICAgICAgICAgdHlwZTogJ3RleHQvcGxhaW47Y2hhcnNldD11dGYtOCdcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghZG9aaXBGaWxlKSB7XG4gICAgICAgICAgLy8gc2F2ZUFzIGF1dG9tYXRpY2x5IHJlcGxhY2UgJzonIGZvciAnXydcbiAgICAgICAgICBzYXZlQXMoYmxvYiwgdGZ3RmlsZU5hbWVXaXRoRXh0KTtcbiAgICAgICAgICB0aGlzLnNhdmVGaWxlUHJvY2Vzc2luZygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEFkZCB0aGUgY2FudmFzIHRvIHppcFxuICAgICAgICAgIHRoaXMuYWRkRmlsZVRvWmlwKHRmd0ZpbGVOYW1lV2l0aEV4dCxibG9iKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIG1hcC5vbC5yZW5kZXJTeW5jKCk7XG5cbiAgICByZXR1cm4gc3RhdHVzJDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYW5kIEFkZCBMZWdlbmQgdG8gdGhlIG1hcCBjYW52YXNcbiAgICogQHBhcmFtICBjYW52YXMgQ2FudmFzIG9mIHRoZSBtYXBcbiAgICogQHBhcmFtICBtYXAgTWFwIG9mIHRoZSBhcHBcbiAgICogQHBhcmFtICByZXNvbHV0aW9uIFJlc29sdXRpb24gb2YgbWFwXG4gICAqIEBwYXJhbSAgbGVnZW5kUG9zaXRpb24gTGVnZW5kIHBvc2l0aW9uXG4gICAqIEBwYXJhbSAgZm9ybWF0IEltYWdlIGZvcm1hdFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBhZGRMZWdlbmRUb0ltYWdlKFxuICAgICAgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCxcbiAgICAgIG1hcDogSWdvTWFwLFxuICAgICAgcmVzb2x1dGlvbjogbnVtYmVyLFxuICAgICAgbGVnZW5kUG9zaXRpb246IHN0cmluZyxcbiAgICAgIGZvcm1hdDogc3RyaW5nXG4gICkge1xuICAgIGNvbnN0IGZpbGVOYW1lV2l0aEV4dCA9ICdtYXAuJyArIGZvcm1hdDtcbiAgICBjb25zdCBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICAvLyBHZXQgaHRtbCBjb2RlIGZvciB0aGUgbGVnZW5kXG4gICAgY29uc3QgaHRtbCA9IGF3YWl0IHRoaXMuZ2V0TGF5ZXJzTGVnZW5kSHRtbChcbiAgICAgIG1hcCxcbiAgICAgIGNhbnZhcy53aWR0aCxcbiAgICAgIHJlc29sdXRpb25cbiAgICApLnRvUHJvbWlzZSgpO1xuICAgIC8vIElmIG5vIGxlZ2VuZCwgc2F2ZSB0aGUgbWFwIGRpcmVjdGx5XG4gICAgaWYgKGh0bWwgPT09ICcnKSB7XG4gICAgICBhd2FpdCB0aGlzLnNhdmVDYW52YXNJbWFnZUFzRmlsZShjYW52YXMsIGZpbGVOYW1lV2l0aEV4dCwgZm9ybWF0KTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvLyBDcmVhdGUgZGl2IHRvIGNvbnRhaW4gaHRtbCBjb2RlIGZvciBsZWdlbmRcbiAgICBjb25zdCBkaXYgPSB3aW5kb3cuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZGl2LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBkaXYuc3R5bGUudG9wID0gJzAnO1xuICAgIC8vIEFkZCBodG1sIGNvZGUgdG8gY29udmVydCBpbiB0aGUgbmV3IHdpbmRvd1xuICAgIHdpbmRvdy5kb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdik7XG4gICAgZGl2LmlubmVySFRNTCA9IGh0bWw7XG4gICAgYXdhaXQgdGhpcy50aW1lb3V0KDEpO1xuICAgIGNvbnN0IGNhbnZhc0xlZ2VuZCA9IGF3YWl0IGh0bWwyY2FudmFzKGRpdiwgeyB1c2VDT1JTOiB0cnVlIH0pLmNhdGNoKChlKSA9PiB7XG4gICAgICBjb25zb2xlLmxvZyhlKTtcbiAgICB9KTtcblxuICAgIGlmIChjYW52YXNMZWdlbmQpIHtcbiAgICAgIGNvbnN0IGNhbnZhc0hlaWdodCA9IGNhbnZhcy5oZWlnaHQ7XG4gICAgICBjb25zdCBjYW52YXNXaWR0aCA9IGNhbnZhcy53aWR0aDtcbiAgICAgIGNvbnN0IGxlZ2VuZEhlaWdodCA9IGNhbnZhc0xlZ2VuZC5oZWlnaHQ7XG4gICAgICBjb25zdCBsZWdlbmRXaWR0aCA9IGNhbnZhc0xlZ2VuZC53aWR0aDtcbiAgICAgIC8vIE1vdmUgdGhlIGxlZ2VuZCB0byB0aGUgY29ycmVjdCBwb3NpdGlvbiBvbiB0aGUgcGFnZVxuICAgICAgY29uc3Qgb2Zmc2V0ID0gY2FudmFzSGVpZ2h0ICogMC4wMTtcbiAgICAgIGxldCBsZWdlbmRYOiBudW1iZXI7XG4gICAgICBsZXQgbGVnZW5kWTogbnVtYmVyO1xuXG4gICAgICBpZiAobGVnZW5kUG9zaXRpb24gPT09ICdib3R0b21yaWdodCcpIHtcbiAgICAgICAgbGVnZW5kWCA9IGNhbnZhc1dpZHRoIC0gbGVnZW5kV2lkdGggLSBvZmZzZXQ7XG4gICAgICAgIGxlZ2VuZFkgPSBjYW52YXNIZWlnaHQgLSBsZWdlbmRIZWlnaHQgLSBvZmZzZXQ7XG4gICAgICB9IGVsc2UgaWYgKGxlZ2VuZFBvc2l0aW9uID09PSAndG9wcmlnaHQnKSB7XG4gICAgICAgIGxlZ2VuZFggPSBjYW52YXNXaWR0aCAtIGxlZ2VuZFdpZHRoIC0gb2Zmc2V0O1xuICAgICAgICBsZWdlbmRZID0gb2Zmc2V0O1xuICAgICAgfSBlbHNlIGlmIChsZWdlbmRQb3NpdGlvbiA9PT0gJ2JvdHRvbWxlZnQnKSB7XG4gICAgICAgIGxlZ2VuZFggPSBvZmZzZXQ7XG4gICAgICAgIGxlZ2VuZFkgPSBjYW52YXNIZWlnaHQgLSBsZWdlbmRIZWlnaHQgLSBvZmZzZXQ7XG4gICAgICB9IGVsc2UgaWYgKGxlZ2VuZFBvc2l0aW9uID09PSAndG9wbGVmdCcpIHtcbiAgICAgICAgbGVnZW5kWCA9IG9mZnNldDtcbiAgICAgICAgbGVnZW5kWSA9IG9mZnNldDtcbiAgICAgIH1cblxuICAgICAgY29udGV4dC5kcmF3SW1hZ2UoY2FudmFzTGVnZW5kLCBsZWdlbmRYLCBsZWdlbmRZLCBsZWdlbmRXaWR0aCwgbGVnZW5kSGVpZ2h0KTtcbiAgICAgIGNvbnRleHQuc3Ryb2tlUmVjdChsZWdlbmRYLCBsZWdlbmRZLCBsZWdlbmRXaWR0aCwgbGVnZW5kSGVpZ2h0KTtcbiAgICAgIGRpdi5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRpdik7IC8vIHJlbW92ZSB0ZW1wIGRpdiAoSUUgc3R5bGUpXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbmRlck1hcChtYXAsIHNpemUsIGV4dGVudCkge1xuICAgIG1hcC5vbC51cGRhdGVTaXplKCk7XG4gICAgbWFwLm9sLnJlbmRlclN5bmMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYXZlIGRvY3VtZW50XG4gICAqIEBwYXJhbSAgZG9jIC0gRG9jdW1lbnQgdG8gc2F2ZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHNhdmVEb2MoZG9jOiBqc1BERikge1xuICAgIGF3YWl0IGRvYy5zYXZlKCdtYXBfZ2VvcmVmLnBkZicsIHsgcmV0dXJuUHJvbWlzZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIGJlc3QgSW1hZ2Ugc2l6ZSB0byBmaXQgaW4gcGRmXG4gICAqIEBwYXJhbSBkb2MgLSBQZGYgRG9jdW1lbnRcbiAgICogQHBhcmFtIGNhbnZhcyAtIENhbnZhcyBvZiBpbWFnZVxuICAgKiBAcGFyYW0gbWFyZ2lucyAtIFBhZ2UgbWFyZ2luc1xuICAgKi9cbiAgcHJpdmF0ZSBnZXRJbWFnZVNpemVUb0ZpdFBkZihkb2MsIGNhbnZhcywgbWFyZ2lucykge1xuICAgIC8vIERlZmluZSB2YXJpYWJsZSB0byBjYWxjdWxhdGUgYmVzdCBzaXplIHRvIGZpdCBpbiBvbmUgcGFnZVxuICAgIGNvbnN0IHBhZ2VIZWlnaHQgPSBkb2MuaW50ZXJuYWwucGFnZVNpemUuZ2V0SGVpZ2h0KCkgLSAobWFyZ2luc1swXSArIG1hcmdpbnNbMl0pO1xuICAgIGNvbnN0IHBhZ2VXaWR0aCA9IGRvYy5pbnRlcm5hbC5wYWdlU2l6ZS5nZXRXaWR0aCgpIC0gKG1hcmdpbnNbMV0gKyBtYXJnaW5zWzNdKTtcbiAgICBjb25zdCBjYW5IZWlnaHQgPSB0aGlzLnBkZl91bml0czJwb2ludHMoY2FudmFzLmhlaWdodCwgJ21tJyk7XG4gICAgY29uc3QgY2FuV2lkdGggPSB0aGlzLnBkZl91bml0czJwb2ludHMoY2FudmFzLndpZHRoLCAnbW0nKTtcblxuICAgIGNvbnN0IGhlaWdodFJhdGlvID0gY2FuSGVpZ2h0IC8gcGFnZUhlaWdodDtcbiAgICBjb25zdCB3aWR0aFJhdGlvID0gY2FuV2lkdGggLyBwYWdlV2lkdGg7XG4gICAgY29uc3QgbWF4UmF0aW8gPSBoZWlnaHRSYXRpbyA+IHdpZHRoUmF0aW8gPyBoZWlnaHRSYXRpbyA6IHdpZHRoUmF0aW87XG4gICAgY29uc3QgaW1nSGVpZ2ggPSBtYXhSYXRpbyA+IDEgPyBjYW5IZWlnaHQgLyBtYXhSYXRpbyA6IGNhbkhlaWdodDtcbiAgICBjb25zdCBpbWdXaWR0aCA9IG1heFJhdGlvID4gMSA/IGNhbldpZHRoIC8gbWF4UmF0aW8gOiBjYW5XaWR0aDtcblxuICAgIHJldHVybiBbaW1nV2lkdGgsIGltZ0hlaWdoXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYSB3b3JsZCBmaWxlIGluZm9ybWF0aW9uIGZvciB0aWZmXG4gICAqIEBwYXJhbSAgbWFwIC0gTWFwIG9mIHRoZSBhcHBcbiAgICovXG4gIHByaXZhdGUgZ2V0V29ybGRGaWxlSW5mb3JtYXRpb24obWFwKSB7XG4gICAgY29uc3QgY3VycmVudFJlc29sdXRpb24gPSBtYXAudmlld0NvbnRyb2xsZXIuZ2V0UmVzb2x1dGlvbigpO1xuICAgIGNvbnN0IGN1cnJlbnRFeHRlbnQgPSBtYXAudmlld0NvbnRyb2xsZXIuZ2V0RXh0ZW50KCk7IC8vIFJldHVybiBbbWlueCwgbWlueSwgbWF4eCwgbWF4eV1cbiAgICByZXR1cm4gW1xuICAgICAgY3VycmVudFJlc29sdXRpb24sXG4gICAgICAwLFxuICAgICAgMCxcbiAgICAgIC1jdXJyZW50UmVzb2x1dGlvbixcbiAgICAgIGN1cnJlbnRFeHRlbnRbMF0gKyBjdXJyZW50UmVzb2x1dGlvbiAvIDAuNSxcbiAgICAgIGN1cnJlbnRFeHRlbnRbM10gLSBjdXJyZW50UmVzb2x1dGlvbiAvIDAuNVxuICAgIF0uam9pbignXFxuJyk7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZSBjYW52YXMgaW1hZ2UgYXMgZmlsZVxuICAgKiBAcGFyYW0gY2FudmFzIC0gQ2FudmFzIHRvIHNhdmVcbiAgICogQHBhcmFtIG5hbWUgLSBOYW1lIG9mIHRoZSBmaWxlXG4gICAqIEBwYXJhbSBmb3JtYXQgLSBmaWxlIGZvcm1hdFxuICAgKi9cbiAgcHJpdmF0ZSBzYXZlQ2FudmFzSW1hZ2VBc0ZpbGUoY2FudmFzLCBuYW1lV2l0aEV4dCwgZm9ybWF0KSB7XG4gICAgY29uc3QgYmxvYkZvcm1hdCA9ICdpbWFnZS8nICsgZm9ybWF0O1xuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNhbnZhcy50b0RhdGFVUkwoKTsgLy8gSnVzdCB0byBtYWtlIHRoZSBjYXRjaCB0cmlnZ2VyIHdpaHRvdXQgdG9CbG9iIEVycm9yIHRocm93IG5vdCBjYXRjaGVkXG4gICAgICAvLyBJZiBuYXZpZ2F0b3IgaXMgSW50ZXJuZXQgRXhwbG9yZXJcbiAgICAgIGlmIChuYXZpZ2F0b3IubXNTYXZlQmxvYikge1xuICAgICAgICBuYXZpZ2F0b3IubXNTYXZlQmxvYihjYW52YXMubXNUb0Jsb2IoKSwgbmFtZVdpdGhFeHQpO1xuICAgICAgICB0aGlzLnNhdmVGaWxlUHJvY2Vzc2luZygpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2FudmFzLnRvQmxvYigoYmxvYikgPT4ge1xuICAgICAgICAgIC8vIGRvd25sb2FkIGltYWdlXG4gICAgICAgICAgc2F2ZUFzKGJsb2IsIG5hbWVXaXRoRXh0KTtcbiAgICAgICAgICB0aGF0LnNhdmVGaWxlUHJvY2Vzc2luZygpO1xuICAgICAgICB9LCBibG9iRm9ybWF0KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRoaXMubWVzc2FnZVNlcnZpY2UuZXJyb3IoXG4gICAgICAgIHRoaXMubGFuZ3VhZ2VTZXJ2aWNlLnRyYW5zbGF0ZS5pbnN0YW50KFxuICAgICAgICAgICdpZ28uZ2VvLnByaW50Rm9ybS5jb3JzRXJyb3JNZXNzYWdlQm9keSdcbiAgICAgICAgKSxcbiAgICAgICAgdGhpcy5sYW5ndWFnZVNlcnZpY2UudHJhbnNsYXRlLmluc3RhbnQoXG4gICAgICAgICAgJ2lnby5nZW8ucHJpbnRGb3JtLmNvcnNFcnJvck1lc3NhZ2VIZWFkZXInXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBmaWxlIHRvIGEgemlwXG4gICAqIEBwYXJhbSBjYW52YXMgLSBGaWxlIHRvIGFkZCB0byB0aGUgemlwXG4gICAqIEBwYXJhbSAgbmFtZSAtTmFtZSBvZiB0aGUgZmlsZW92ZXJ2aWV3XG4gICAqL1xuICBwcml2YXRlIGdlbmVyYXRlQ2FudmFGaWxlVG9aaXAoY2FudmFzLCBuYW1lKSB7XG4gICAgY29uc3QgYmxvYkZvcm1hdCA9ICdpbWFnZS8nICsgJ2pwZWcnO1xuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgIGlmIChcbiAgICAgICF0aGlzLmhhc093blByb3BlcnR5KCd6aXBGaWxlJykgfHxcbiAgICAgIHR5cGVvZiB0aGlzLnppcEZpbGUgPT09ICd1bmRlZmluZWQnXG4gICAgKSB7XG4gICAgICB0aGlzLnppcEZpbGUgPSBuZXcgSlNaaXAoKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY2FudmFzLnRvRGF0YVVSTCgpOyAvLyBKdXN0IHRvIG1ha2UgdGhlIGNhdGNoIHRyaWdnZXIgd2lodG91dCB0b0Jsb2IgRXJyb3IgdGhyb3cgbm90IGNhdGNoZWRcbiAgICAgIGlmIChuYXZpZ2F0b3IubXNTYXZlQmxvYikge1xuICAgICAgICB0aGlzLmFkZEZpbGVUb1ppcChuYW1lLCBjYW52YXMubXNUb0Jsb2IoKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYW52YXMudG9CbG9iKChibG9iKSA9PiB7XG4gICAgICAgICAgdGhhdC5hZGRGaWxlVG9aaXAobmFtZSwgYmxvYik7XG4gICAgICAgIH0sIGJsb2JGb3JtYXQpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5tZXNzYWdlU2VydmljZS5lcnJvcihcbiAgICAgICAgdGhpcy5sYW5ndWFnZVNlcnZpY2UudHJhbnNsYXRlLmluc3RhbnQoXG4gICAgICAgICAgJ2lnby5nZW8ucHJpbnRGb3JtLmNvcnNFcnJvck1lc3NhZ2VCb2R5J1xuICAgICAgICApLFxuICAgICAgICB0aGlzLmxhbmd1YWdlU2VydmljZS50cmFuc2xhdGUuaW5zdGFudChcbiAgICAgICAgICAnaWdvLmdlby5wcmludEZvcm0uY29yc0Vycm9yTWVzc2FnZUhlYWRlcidcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkIGZpbGUgdG8gemlwLCBpZiBhbGwgZmlsZSBhcmUgemlwcGVkLCBkb3dubG9hZFxuICAgKiBAcGFyYW0gbmFtZSAtIE5hbWUgb2YgdGhlIGZpbGVzXG4gICAqIEBwYXJhbSBibG9iIC0gQ29udGFpbiBvZiBmaWxlXG4gICAqL1xuICBwcml2YXRlIGFkZEZpbGVUb1ppcChuYW1lLCBibG9iKSB7XG4gICAgLy8gYWRkIGZpbGUgdG8gemlwXG4gICAgdGhpcy56aXBGaWxlLmZpbGUobmFtZSwgYmxvYik7XG4gICAgdGhpcy5uYkZpbGVUb1Byb2Nlc3MtLTtcblxuICAgIC8vIElmIGFsbCBmaWxlcyBhcmUgcHJvY2Nlc3NlZFxuICAgIGlmICh0aGlzLm5iRmlsZVRvUHJvY2VzcyA9PT0gMCkge1xuICAgICAgLy8gRG93bmxvYWQgemlwIGZpbGVcbiAgICAgIHRoaXMuZ2V0WmlwRmlsZSgpO1xuICAgICAgLy8gU3RvcCBsb2FkaW5nXG4gICAgICB0aGlzLmFjdGl2aXR5U2VydmljZS51bnJlZ2lzdGVyKHRoaXMuYWN0aXZpdHlJZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzYXZlRmlsZVByb2Nlc3NpbmcoKSB7XG4gICAgdGhpcy5uYkZpbGVUb1Byb2Nlc3MtLTtcblxuICAgIC8vIElmIGFsbCBmaWxlcyBhcmUgcHJvY2Nlc3NlZFxuICAgIGlmICh0aGlzLm5iRmlsZVRvUHJvY2VzcyA9PT0gMCkge1xuICAgICAgLy8gU3RvcCBsb2FkaW5nXG4gICAgICB0aGlzLmFjdGl2aXR5U2VydmljZS51bnJlZ2lzdGVyKHRoaXMuYWN0aXZpdHlJZCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgemlwcGVkIGZpbGVcbiAgICogQHJldHVybiBSZXR1biBhIHppcCBmaWxlXG4gICAqL1xuICBwcml2YXRlIGdldFppcEZpbGUoKSB7XG4gICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgdGhpcy56aXBGaWxlLmdlbmVyYXRlQXN5bmMoeyB0eXBlOiAnYmxvYicgfSkudGhlbigoYmxvYikgPT4ge1xuICAgICAgLy8gMSkgZ2VuZXJhdGUgdGhlIHppcCBmaWxlXG4gICAgICBzYXZlQXMoYmxvYiwgJ21hcC56aXAnKTtcbiAgICAgIGRlbGV0ZSB0aGF0LnppcEZpbGU7XG4gICAgfSk7XG4gIH1cblxuXG4gIHByaXZhdGUgcGRmX3VuaXRzMnBvaW50cyhuLCB1bml0KTogbnVtYmVyIHtcbiAgICBsZXQgayA9IDE7XG5cbiAgICAvLyB0aGlzIGNvZGUgaXMgYm9ycm93ZWQgZnJvbSBqc1BERlxuICAgIC8vICBhcyBpdCBkb2VzIG5vdCBleHBvc2UgYSBwdWJsaWMgQVBJXG4gICAgLy8gIGZvciBjb252ZXJ0aW5nIHVuaXRzIHRvIHBvaW50cy5cbiAgICBzd2l0Y2ggKHVuaXQpIHtcbiAgICAgICAgY2FzZSAncHQnOlxuICAgICAgICAgICAgayA9IDE7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgayA9IDcyIC8gMjUuNDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdjbSc6XG4gICAgICAgICAgICBrID0gNzIgLyAyLjU0O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2luJzpcbiAgICAgICAgICAgIGsgPSA3MjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdweCc6XG4gICAgICAgICAgICBrID0gOTYgLyA3MjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdwYyc6XG4gICAgICAgICAgICBrID0gMTI7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZW0nOlxuICAgICAgICAgICAgayA9IDEyO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2V4JzpcbiAgICAgICAgICAgIGsgPSA2O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdW5pdDogJyArIHVuaXQpO1xuICAgIH1cblxuICAgIHJldHVybiBuICogaztcbiAgfVxuXG59XG4iXX0=