@scoova/mgl 1.0.0

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 (565) hide show
  1. package/LICENSE.txt +116 -0
  2. package/README.md +174 -0
  3. package/build/banner.ts +12 -0
  4. package/build/bump-version-changelog.js +26 -0
  5. package/build/check-bundle-size.js +77 -0
  6. package/build/generate-dist-package.js +26 -0
  7. package/build/generate-doc-images.ts +78 -0
  8. package/build/generate-docs.ts +190 -0
  9. package/build/generate-shaders.ts +68 -0
  10. package/build/generate-struct-arrays.ts +438 -0
  11. package/build/generate-style-code.ts +283 -0
  12. package/build/readme.md +56 -0
  13. package/build/release-notes.js +45 -0
  14. package/build/rollup/bundle_prelude.js +29 -0
  15. package/build/rollup/maplibregl.js +22 -0
  16. package/build/rollup_plugins.ts +58 -0
  17. package/dist/LICENSE.txt +116 -0
  18. package/dist/maplibre-gl.css +1 -0
  19. package/dist/maplibre-gl.d.ts +13304 -0
  20. package/dist/maplibre-gl.js +59 -0
  21. package/dist/maplibre-gl.js.map +1 -0
  22. package/dist/package.json +1 -0
  23. package/package.json +192 -0
  24. package/src/css/maplibre-gl.css +854 -0
  25. package/src/css/svg/maplibregl-ctrl-attrib.svg +3 -0
  26. package/src/css/svg/maplibregl-ctrl-compass.svg +4 -0
  27. package/src/css/svg/maplibregl-ctrl-fullscreen.svg +3 -0
  28. package/src/css/svg/maplibregl-ctrl-geolocate.svg +5 -0
  29. package/src/css/svg/maplibregl-ctrl-logo.svg +11 -0
  30. package/src/css/svg/maplibregl-ctrl-shrink.svg +3 -0
  31. package/src/css/svg/maplibregl-ctrl-terrain.svg +3 -0
  32. package/src/css/svg/maplibregl-ctrl-zoom-in.svg +3 -0
  33. package/src/css/svg/maplibregl-ctrl-zoom-out.svg +3 -0
  34. package/src/data/array_types.g.ts +1130 -0
  35. package/src/data/bucket/circle_attributes.ts +8 -0
  36. package/src/data/bucket/circle_bucket.ts +197 -0
  37. package/src/data/bucket/fill_attributes.ts +8 -0
  38. package/src/data/bucket/fill_bucket.test.ts +95 -0
  39. package/src/data/bucket/fill_bucket.ts +228 -0
  40. package/src/data/bucket/fill_extrusion_attributes.ts +13 -0
  41. package/src/data/bucket/fill_extrusion_bucket.ts +305 -0
  42. package/src/data/bucket/heatmap_bucket.ts +12 -0
  43. package/src/data/bucket/line_attributes.ts +8 -0
  44. package/src/data/bucket/line_attributes_ext.ts +8 -0
  45. package/src/data/bucket/line_bucket.test.ts +142 -0
  46. package/src/data/bucket/line_bucket.ts +592 -0
  47. package/src/data/bucket/pattern_attributes.ts +9 -0
  48. package/src/data/bucket/pattern_bucket_features.ts +57 -0
  49. package/src/data/bucket/symbol_attributes.ts +122 -0
  50. package/src/data/bucket/symbol_bucket.test.ts +243 -0
  51. package/src/data/bucket/symbol_bucket.ts +975 -0
  52. package/src/data/bucket.ts +123 -0
  53. package/src/data/dem_data.test.ts +237 -0
  54. package/src/data/dem_data.ts +171 -0
  55. package/src/data/evaluation_feature.ts +18 -0
  56. package/src/data/extent.ts +13 -0
  57. package/src/data/feature_index.ts +337 -0
  58. package/src/data/feature_position_map.test.ts +33 -0
  59. package/src/data/feature_position_map.ts +126 -0
  60. package/src/data/index_array_type.ts +9 -0
  61. package/src/data/load_geometry.test.ts +49 -0
  62. package/src/data/load_geometry.ts +44 -0
  63. package/src/data/pos3d_attributes.ts +5 -0
  64. package/src/data/pos_attributes.ts +5 -0
  65. package/src/data/program_configuration.ts +735 -0
  66. package/src/data/raster_bounds_attributes.ts +6 -0
  67. package/src/data/segment.ts +89 -0
  68. package/src/geo/edge_insets.test.ts +83 -0
  69. package/src/geo/edge_insets.ts +146 -0
  70. package/src/geo/lng_lat.test.ts +65 -0
  71. package/src/geo/lng_lat.ts +169 -0
  72. package/src/geo/lng_lat_bounds.test.ts +357 -0
  73. package/src/geo/lng_lat_bounds.ts +356 -0
  74. package/src/geo/mercator_coordinate.test.ts +34 -0
  75. package/src/geo/mercator_coordinate.ts +157 -0
  76. package/src/geo/projection/projection.ts +72 -0
  77. package/src/geo/transform.test.ts +509 -0
  78. package/src/geo/transform.ts +1072 -0
  79. package/src/gl/color_mode.ts +31 -0
  80. package/src/gl/context.ts +321 -0
  81. package/src/gl/cull_face_mode.ts +22 -0
  82. package/src/gl/depth_mode.ts +26 -0
  83. package/src/gl/framebuffer.ts +48 -0
  84. package/src/gl/index_buffer.ts +55 -0
  85. package/src/gl/render_pool.test.ts +69 -0
  86. package/src/gl/render_pool.ts +93 -0
  87. package/src/gl/state.test.ts +125 -0
  88. package/src/gl/stencil_mode.ts +27 -0
  89. package/src/gl/types.ts +59 -0
  90. package/src/gl/value.ts +534 -0
  91. package/src/gl/vertex_buffer.test.ts +57 -0
  92. package/src/gl/vertex_buffer.ts +111 -0
  93. package/src/gl/webgl2.ts +12 -0
  94. package/src/index.test.ts +121 -0
  95. package/src/index.ts +250 -0
  96. package/src/render/draw_background.ts +53 -0
  97. package/src/render/draw_circle.ts +113 -0
  98. package/src/render/draw_collision_debug.ts +168 -0
  99. package/src/render/draw_custom.test.ts +73 -0
  100. package/src/render/draw_custom.ts +45 -0
  101. package/src/render/draw_debug.test.ts +122 -0
  102. package/src/render/draw_debug.ts +148 -0
  103. package/src/render/draw_fill.test.ts +137 -0
  104. package/src/render/draw_fill.ts +128 -0
  105. package/src/render/draw_fill_extrusion.ts +97 -0
  106. package/src/render/draw_heatmap.ts +228 -0
  107. package/src/render/draw_hillshade.ts +119 -0
  108. package/src/render/draw_line.ts +125 -0
  109. package/src/render/draw_raster.ts +133 -0
  110. package/src/render/draw_sky.ts +44 -0
  111. package/src/render/draw_symbol.test.ts +223 -0
  112. package/src/render/draw_symbol.ts +499 -0
  113. package/src/render/draw_terrain.ts +99 -0
  114. package/src/render/glyph_atlas.ts +83 -0
  115. package/src/render/glyph_manager.test.ts +147 -0
  116. package/src/render/glyph_manager.ts +198 -0
  117. package/src/render/image_atlas.ts +159 -0
  118. package/src/render/image_manager.ts +337 -0
  119. package/src/render/line_atlas.test.ts +38 -0
  120. package/src/render/line_atlas.ts +214 -0
  121. package/src/render/mesh.ts +25 -0
  122. package/src/render/painter.test.ts +51 -0
  123. package/src/render/painter.ts +666 -0
  124. package/src/render/program/background_program.ts +100 -0
  125. package/src/render/program/circle_program.ts +61 -0
  126. package/src/render/program/clipping_mask_program.ts +19 -0
  127. package/src/render/program/collision_program.ts +47 -0
  128. package/src/render/program/debug_program.ts +29 -0
  129. package/src/render/program/fill_extrusion_program.ts +120 -0
  130. package/src/render/program/fill_program.ts +121 -0
  131. package/src/render/program/heatmap_program.ts +76 -0
  132. package/src/render/program/hillshade_program.ts +116 -0
  133. package/src/render/program/line_program.ts +207 -0
  134. package/src/render/program/pattern.ts +102 -0
  135. package/src/render/program/program_uniforms.ts +46 -0
  136. package/src/render/program/raster_program.ts +88 -0
  137. package/src/render/program/sky_program.ts +28 -0
  138. package/src/render/program/symbol_program.ts +266 -0
  139. package/src/render/program/terrain_program.ts +116 -0
  140. package/src/render/program.ts +233 -0
  141. package/src/render/render_to_texture.test.ts +151 -0
  142. package/src/render/render_to_texture.ts +197 -0
  143. package/src/render/terrain.test.ts +322 -0
  144. package/src/render/terrain.ts +464 -0
  145. package/src/render/texture.ts +114 -0
  146. package/src/render/uniform_binding.test.ts +122 -0
  147. package/src/render/uniform_binding.ts +157 -0
  148. package/src/render/update_pattern_positions_in_program.test.ts +74 -0
  149. package/src/render/update_pattern_positions_in_program.ts +50 -0
  150. package/src/render/vertex_array_object.ts +163 -0
  151. package/src/shaders/README.md +42 -0
  152. package/src/shaders/_prelude.fragment.glsl +19 -0
  153. package/src/shaders/_prelude.fragment.glsl.g.ts +2 -0
  154. package/src/shaders/_prelude.vertex.glsl +148 -0
  155. package/src/shaders/_prelude.vertex.glsl.g.ts +2 -0
  156. package/src/shaders/background.fragment.glsl +10 -0
  157. package/src/shaders/background.fragment.glsl.g.ts +2 -0
  158. package/src/shaders/background.vertex.glsl +7 -0
  159. package/src/shaders/background.vertex.glsl.g.ts +2 -0
  160. package/src/shaders/background_pattern.fragment.glsl +28 -0
  161. package/src/shaders/background_pattern.fragment.glsl.g.ts +2 -0
  162. package/src/shaders/background_pattern.vertex.glsl +19 -0
  163. package/src/shaders/background_pattern.vertex.glsl.g.ts +2 -0
  164. package/src/shaders/circle.fragment.glsl +34 -0
  165. package/src/shaders/circle.fragment.glsl.g.ts +2 -0
  166. package/src/shaders/circle.vertex.glsl +68 -0
  167. package/src/shaders/circle.vertex.glsl.g.ts +2 -0
  168. package/src/shaders/clipping_mask.fragment.glsl +3 -0
  169. package/src/shaders/clipping_mask.fragment.glsl.g.ts +2 -0
  170. package/src/shaders/clipping_mask.vertex.glsl +7 -0
  171. package/src/shaders/clipping_mask.vertex.glsl.g.ts +2 -0
  172. package/src/shaders/collision_box.fragment.glsl +20 -0
  173. package/src/shaders/collision_box.fragment.glsl.g.ts +2 -0
  174. package/src/shaders/collision_box.vertex.glsl +27 -0
  175. package/src/shaders/collision_box.vertex.glsl.g.ts +2 -0
  176. package/src/shaders/collision_circle.fragment.glsl +17 -0
  177. package/src/shaders/collision_circle.fragment.glsl.g.ts +2 -0
  178. package/src/shaders/collision_circle.vertex.glsl +59 -0
  179. package/src/shaders/collision_circle.vertex.glsl.g.ts +2 -0
  180. package/src/shaders/debug.fragment.glsl +9 -0
  181. package/src/shaders/debug.fragment.glsl.g.ts +2 -0
  182. package/src/shaders/debug.vertex.glsl +12 -0
  183. package/src/shaders/debug.vertex.glsl.g.ts +2 -0
  184. package/src/shaders/encode_attribute.test.ts +11 -0
  185. package/src/shaders/encode_attribute.ts +13 -0
  186. package/src/shaders/fill.fragment.glsl +13 -0
  187. package/src/shaders/fill.fragment.glsl.g.ts +2 -0
  188. package/src/shaders/fill.vertex.glsl +13 -0
  189. package/src/shaders/fill.vertex.glsl.g.ts +2 -0
  190. package/src/shaders/fill_extrusion.fragment.glsl +9 -0
  191. package/src/shaders/fill_extrusion.fragment.glsl.g.ts +2 -0
  192. package/src/shaders/fill_extrusion.vertex.glsl +84 -0
  193. package/src/shaders/fill_extrusion.vertex.glsl.g.ts +2 -0
  194. package/src/shaders/fill_extrusion_pattern.fragment.glsl +47 -0
  195. package/src/shaders/fill_extrusion_pattern.fragment.glsl.g.ts +2 -0
  196. package/src/shaders/fill_extrusion_pattern.vertex.glsl +96 -0
  197. package/src/shaders/fill_extrusion_pattern.vertex.glsl.g.ts +2 -0
  198. package/src/shaders/fill_outline.fragment.glsl +17 -0
  199. package/src/shaders/fill_outline.fragment.glsl.g.ts +2 -0
  200. package/src/shaders/fill_outline.vertex.glsl +17 -0
  201. package/src/shaders/fill_outline.vertex.glsl.g.ts +2 -0
  202. package/src/shaders/fill_outline_pattern.fragment.glsl +43 -0
  203. package/src/shaders/fill_outline_pattern.fragment.glsl.g.ts +2 -0
  204. package/src/shaders/fill_outline_pattern.vertex.glsl +44 -0
  205. package/src/shaders/fill_outline_pattern.vertex.glsl.g.ts +2 -0
  206. package/src/shaders/fill_pattern.fragment.glsl +39 -0
  207. package/src/shaders/fill_pattern.fragment.glsl.g.ts +2 -0
  208. package/src/shaders/fill_pattern.vertex.glsl +39 -0
  209. package/src/shaders/fill_pattern.vertex.glsl.g.ts +2 -0
  210. package/src/shaders/heatmap.fragment.glsl +22 -0
  211. package/src/shaders/heatmap.fragment.glsl.g.ts +2 -0
  212. package/src/shaders/heatmap.vertex.glsl +54 -0
  213. package/src/shaders/heatmap.vertex.glsl.g.ts +2 -0
  214. package/src/shaders/heatmap_texture.fragment.glsl +15 -0
  215. package/src/shaders/heatmap_texture.fragment.glsl.g.ts +2 -0
  216. package/src/shaders/heatmap_texture.vertex.glsl +11 -0
  217. package/src/shaders/heatmap_texture.vertex.glsl.g.ts +2 -0
  218. package/src/shaders/hillshade.fragment.glsl +52 -0
  219. package/src/shaders/hillshade.fragment.glsl.g.ts +2 -0
  220. package/src/shaders/hillshade.vertex.glsl +11 -0
  221. package/src/shaders/hillshade.vertex.glsl.g.ts +2 -0
  222. package/src/shaders/hillshade_prepare.fragment.glsl +77 -0
  223. package/src/shaders/hillshade_prepare.fragment.glsl.g.ts +2 -0
  224. package/src/shaders/hillshade_prepare.vertex.glsl +15 -0
  225. package/src/shaders/hillshade_prepare.vertex.glsl.g.ts +2 -0
  226. package/src/shaders/line.fragment.glsl +30 -0
  227. package/src/shaders/line.fragment.glsl.g.ts +2 -0
  228. package/src/shaders/line.vertex.glsl +89 -0
  229. package/src/shaders/line.vertex.glsl.g.ts +2 -0
  230. package/src/shaders/line_gradient.fragment.glsl +34 -0
  231. package/src/shaders/line_gradient.fragment.glsl.g.ts +2 -0
  232. package/src/shaders/line_gradient.vertex.glsl +92 -0
  233. package/src/shaders/line_gradient.vertex.glsl.g.ts +2 -0
  234. package/src/shaders/line_pattern.fragment.glsl +77 -0
  235. package/src/shaders/line_pattern.fragment.glsl.g.ts +2 -0
  236. package/src/shaders/line_pattern.vertex.glsl +103 -0
  237. package/src/shaders/line_pattern.vertex.glsl.g.ts +2 -0
  238. package/src/shaders/line_sdf.fragment.glsl +45 -0
  239. package/src/shaders/line_sdf.fragment.glsl.g.ts +2 -0
  240. package/src/shaders/line_sdf.vertex.glsl +101 -0
  241. package/src/shaders/line_sdf.vertex.glsl.g.ts +2 -0
  242. package/src/shaders/raster.fragment.glsl +53 -0
  243. package/src/shaders/raster.fragment.glsl.g.ts +2 -0
  244. package/src/shaders/raster.vertex.glsl +21 -0
  245. package/src/shaders/raster.vertex.glsl.g.ts +2 -0
  246. package/src/shaders/shaders.ts +197 -0
  247. package/src/shaders/sky.fragment.glsl +17 -0
  248. package/src/shaders/sky.fragment.glsl.g.ts +2 -0
  249. package/src/shaders/sky.vertex.glsl +5 -0
  250. package/src/shaders/sky.vertex.glsl.g.ts +2 -0
  251. package/src/shaders/symbol_icon.fragment.glsl +17 -0
  252. package/src/shaders/symbol_icon.fragment.glsl.g.ts +2 -0
  253. package/src/shaders/symbol_icon.vertex.glsl +117 -0
  254. package/src/shaders/symbol_icon.vertex.glsl.g.ts +2 -0
  255. package/src/shaders/symbol_sdf.fragment.glsl +58 -0
  256. package/src/shaders/symbol_sdf.fragment.glsl.g.ts +2 -0
  257. package/src/shaders/symbol_sdf.vertex.glsl +142 -0
  258. package/src/shaders/symbol_sdf.vertex.glsl.g.ts +2 -0
  259. package/src/shaders/symbol_text_and_icon.fragment.glsl +68 -0
  260. package/src/shaders/symbol_text_and_icon.fragment.glsl.g.ts +2 -0
  261. package/src/shaders/symbol_text_and_icon.vertex.glsl +140 -0
  262. package/src/shaders/symbol_text_and_icon.vertex.glsl.g.ts +2 -0
  263. package/src/shaders/terrain.fragment.glsl +32 -0
  264. package/src/shaders/terrain.fragment.glsl.g.ts +2 -0
  265. package/src/shaders/terrain.vertex.glsl +17 -0
  266. package/src/shaders/terrain.vertex.glsl.g.ts +2 -0
  267. package/src/shaders/terrain_coords.fragment.glsl +11 -0
  268. package/src/shaders/terrain_coords.fragment.glsl.g.ts +2 -0
  269. package/src/shaders/terrain_coords.vertex.glsl +13 -0
  270. package/src/shaders/terrain_coords.vertex.glsl.g.ts +2 -0
  271. package/src/shaders/terrain_depth.fragment.glsl +15 -0
  272. package/src/shaders/terrain_depth.fragment.glsl.g.ts +2 -0
  273. package/src/shaders/terrain_depth.vertex.glsl +13 -0
  274. package/src/shaders/terrain_depth.vertex.glsl.g.ts +2 -0
  275. package/src/source/canvas_source.test.ts +210 -0
  276. package/src/source/canvas_source.ts +227 -0
  277. package/src/source/geojson_source.test.ts +492 -0
  278. package/src/source/geojson_source.ts +431 -0
  279. package/src/source/geojson_source_diff.test.ts +364 -0
  280. package/src/source/geojson_source_diff.ts +172 -0
  281. package/src/source/geojson_worker_source.test.ts +399 -0
  282. package/src/source/geojson_worker_source.ts +303 -0
  283. package/src/source/geojson_wrapper.test.ts +32 -0
  284. package/src/source/geojson_wrapper.ts +81 -0
  285. package/src/source/image_source.test.ts +235 -0
  286. package/src/source/image_source.ts +338 -0
  287. package/src/source/load_tilejson.ts +47 -0
  288. package/src/source/pixels_to_tile_units.ts +25 -0
  289. package/src/source/protocol_crud.ts +48 -0
  290. package/src/source/query_features.test.ts +31 -0
  291. package/src/source/query_features.ts +252 -0
  292. package/src/source/raster_dem_tile_source.test.ts +158 -0
  293. package/src/source/raster_dem_tile_source.ts +166 -0
  294. package/src/source/raster_dem_tile_worker_source.test.ts +36 -0
  295. package/src/source/raster_dem_tile_worker_source.ts +38 -0
  296. package/src/source/raster_tile_source.test.ts +206 -0
  297. package/src/source/raster_tile_source.ts +227 -0
  298. package/src/source/rtl_text_plugin_main_thread.test.ts +170 -0
  299. package/src/source/rtl_text_plugin_main_thread.ts +89 -0
  300. package/src/source/rtl_text_plugin_status.ts +33 -0
  301. package/src/source/rtl_text_plugin_worker.ts +49 -0
  302. package/src/source/source.test.ts +41 -0
  303. package/src/source/source.ts +186 -0
  304. package/src/source/source_cache.test.ts +2069 -0
  305. package/src/source/source_cache.ts +1102 -0
  306. package/src/source/source_state.ts +157 -0
  307. package/src/source/terrain_source_cache.test.ts +105 -0
  308. package/src/source/terrain_source_cache.ts +204 -0
  309. package/src/source/tile.test.ts +290 -0
  310. package/src/source/tile.ts +478 -0
  311. package/src/source/tile_bounds.ts +34 -0
  312. package/src/source/tile_cache.test.ts +130 -0
  313. package/src/source/tile_cache.ts +208 -0
  314. package/src/source/tile_id.test.ts +112 -0
  315. package/src/source/tile_id.ts +221 -0
  316. package/src/source/vector_tile_source.test.ts +401 -0
  317. package/src/source/vector_tile_source.ts +283 -0
  318. package/src/source/vector_tile_worker_source.test.ts +396 -0
  319. package/src/source/vector_tile_worker_source.ts +199 -0
  320. package/src/source/video_source.test.ts +124 -0
  321. package/src/source/video_source.ts +204 -0
  322. package/src/source/worker.test.ts +233 -0
  323. package/src/source/worker.ts +301 -0
  324. package/src/source/worker_source.ts +117 -0
  325. package/src/source/worker_tile.test.ts +226 -0
  326. package/src/source/worker_tile.ts +208 -0
  327. package/src/style/create_style_layer.ts +39 -0
  328. package/src/style/evaluation_parameters.ts +62 -0
  329. package/src/style/format_section_override.test.ts +62 -0
  330. package/src/style/format_section_override.ts +50 -0
  331. package/src/style/light.test.ts +86 -0
  332. package/src/style/light.ts +135 -0
  333. package/src/style/load_glyph_range.test.ts +40 -0
  334. package/src/style/load_glyph_range.ts +32 -0
  335. package/src/style/load_sprite.test.ts +227 -0
  336. package/src/style/load_sprite.ts +71 -0
  337. package/src/style/parse_glyph_pbf.ts +42 -0
  338. package/src/style/pauseable_placement.ts +138 -0
  339. package/src/style/properties.ts +726 -0
  340. package/src/style/query_utils.test.ts +107 -0
  341. package/src/style/query_utils.ts +70 -0
  342. package/src/style/sky.ts +127 -0
  343. package/src/style/style.test.ts +2654 -0
  344. package/src/style/style.ts +1814 -0
  345. package/src/style/style_glyph.ts +25 -0
  346. package/src/style/style_image.ts +188 -0
  347. package/src/style/style_layer/background_style_layer.ts +17 -0
  348. package/src/style/style_layer/background_style_layer_properties.g.ts +40 -0
  349. package/src/style/style_layer/circle_style_layer.ts +98 -0
  350. package/src/style/style_layer/circle_style_layer_properties.g.ts +76 -0
  351. package/src/style/style_layer/custom_style_layer.ts +233 -0
  352. package/src/style/style_layer/fill_extrusion_style_layer.ts +224 -0
  353. package/src/style/style_layer/fill_extrusion_style_layer_properties.g.ts +55 -0
  354. package/src/style/style_layer/fill_style_layer.test.ts +37 -0
  355. package/src/style/style_layer/fill_style_layer.ts +65 -0
  356. package/src/style/style_layer/fill_style_layer_properties.g.ts +64 -0
  357. package/src/style/style_layer/heatmap_style_layer.ts +74 -0
  358. package/src/style/style_layer/heatmap_style_layer_properties.g.ts +46 -0
  359. package/src/style/style_layer/hillshade_style_layer.ts +21 -0
  360. package/src/style/style_layer/hillshade_style_layer_properties.g.ts +49 -0
  361. package/src/style/style_layer/line_style_layer.test.ts +50 -0
  362. package/src/style/style_layer/line_style_layer.ts +131 -0
  363. package/src/style/style_layer/line_style_layer_properties.g.ts +88 -0
  364. package/src/style/style_layer/overlap_mode.test.ts +57 -0
  365. package/src/style/style_layer/overlap_mode.ts +25 -0
  366. package/src/style/style_layer/raster_style_layer.ts +17 -0
  367. package/src/style/style_layer/raster_style_layer_properties.g.ts +55 -0
  368. package/src/style/style_layer/symbol_style_layer.ts +195 -0
  369. package/src/style/style_layer/symbol_style_layer_properties.g.ts +218 -0
  370. package/src/style/style_layer/typed_style_layer.ts +9 -0
  371. package/src/style/style_layer/variable_text_anchor.test.ts +117 -0
  372. package/src/style/style_layer/variable_text_anchor.ts +163 -0
  373. package/src/style/style_layer.test.ts +372 -0
  374. package/src/style/style_layer.ts +287 -0
  375. package/src/style/style_layer_index.test.ts +99 -0
  376. package/src/style/style_layer_index.ts +78 -0
  377. package/src/style/validate_style.ts +53 -0
  378. package/src/style/zoom_history.ts +40 -0
  379. package/src/symbol/anchor.test.ts +14 -0
  380. package/src/symbol/anchor.ts +22 -0
  381. package/src/symbol/check_max_angle.test.ts +54 -0
  382. package/src/symbol/check_max_angle.ts +76 -0
  383. package/src/symbol/clip_line.test.ts +154 -0
  384. package/src/symbol/clip_line.ts +66 -0
  385. package/src/symbol/collision_feature.test.ts +98 -0
  386. package/src/symbol/collision_feature.ts +114 -0
  387. package/src/symbol/collision_index.test.ts +19 -0
  388. package/src/symbol/collision_index.ts +618 -0
  389. package/src/symbol/cross_tile_symbol_index.test.ts +260 -0
  390. package/src/symbol/cross_tile_symbol_index.ts +367 -0
  391. package/src/symbol/get_anchors.test.ts +113 -0
  392. package/src/symbol/get_anchors.ts +167 -0
  393. package/src/symbol/grid_index.test.ts +75 -0
  394. package/src/symbol/grid_index.ts +414 -0
  395. package/src/symbol/merge_lines.test.ts +30 -0
  396. package/src/symbol/merge_lines.ts +80 -0
  397. package/src/symbol/one_em.ts +3 -0
  398. package/src/symbol/opacity_state.ts +23 -0
  399. package/src/symbol/path_interpolator.test.ts +134 -0
  400. package/src/symbol/path_interpolator.ts +55 -0
  401. package/src/symbol/placement.ts +1371 -0
  402. package/src/symbol/projection.test.ts +171 -0
  403. package/src/symbol/projection.ts +833 -0
  404. package/src/symbol/quads.test.ts +157 -0
  405. package/src/symbol/quads.ts +349 -0
  406. package/src/symbol/shaping.test.ts +360 -0
  407. package/src/symbol/shaping.ts +911 -0
  408. package/src/symbol/symbol_layout.ts +739 -0
  409. package/src/symbol/symbol_size.ts +129 -0
  410. package/src/symbol/symbol_style_layer.test.ts +103 -0
  411. package/src/symbol/transform_text.ts +27 -0
  412. package/src/ui/anchor.ts +27 -0
  413. package/src/ui/camera.test.ts +2301 -0
  414. package/src/ui/camera.ts +1520 -0
  415. package/src/ui/control/attribution_control.test.ts +543 -0
  416. package/src/ui/control/attribution_control.ts +209 -0
  417. package/src/ui/control/control.ts +67 -0
  418. package/src/ui/control/fullscreen_control.test.ts +114 -0
  419. package/src/ui/control/fullscreen_control.ts +189 -0
  420. package/src/ui/control/geolocate_control.test.ts +619 -0
  421. package/src/ui/control/geolocate_control.ts +725 -0
  422. package/src/ui/control/logo_control.test.ts +88 -0
  423. package/src/ui/control/logo_control.ts +86 -0
  424. package/src/ui/control/navigation_control.test.ts +238 -0
  425. package/src/ui/control/navigation_control.ts +294 -0
  426. package/src/ui/control/scale_control.test.ts +52 -0
  427. package/src/ui/control/scale_control.ts +152 -0
  428. package/src/ui/control/terrain_control.test.ts +58 -0
  429. package/src/ui/control/terrain_control.ts +74 -0
  430. package/src/ui/default_locale.ts +25 -0
  431. package/src/ui/events.ts +758 -0
  432. package/src/ui/handler/box_zoom.test.ts +163 -0
  433. package/src/ui/handler/box_zoom.ts +171 -0
  434. package/src/ui/handler/click_zoom.ts +55 -0
  435. package/src/ui/handler/cooperative_gestures.test.ts +338 -0
  436. package/src/ui/handler/cooperative_gestures.ts +111 -0
  437. package/src/ui/handler/dblclick_zoom.test.ts +151 -0
  438. package/src/ui/handler/drag_handler.ts +174 -0
  439. package/src/ui/handler/drag_move_state_manager.ts +115 -0
  440. package/src/ui/handler/drag_pan.test.ts +487 -0
  441. package/src/ui/handler/drag_rotate.test.ts +859 -0
  442. package/src/ui/handler/handler_util.ts +10 -0
  443. package/src/ui/handler/keyboard.test.ts +235 -0
  444. package/src/ui/handler/keyboard.ts +212 -0
  445. package/src/ui/handler/map_event.test.ts +158 -0
  446. package/src/ui/handler/map_event.ts +161 -0
  447. package/src/ui/handler/mouse.ts +92 -0
  448. package/src/ui/handler/mouse_handler_interface.test.ts +111 -0
  449. package/src/ui/handler/mouse_rotate.test.ts +62 -0
  450. package/src/ui/handler/one_finger_touch_drag.ts +45 -0
  451. package/src/ui/handler/one_finger_touch_drag_handler_interface.test.ts +77 -0
  452. package/src/ui/handler/scroll_zoom.test.ts +382 -0
  453. package/src/ui/handler/scroll_zoom.ts +379 -0
  454. package/src/ui/handler/shim/dblclick_zoom.ts +64 -0
  455. package/src/ui/handler/shim/drag_pan.ts +104 -0
  456. package/src/ui/handler/shim/drag_rotate.ts +76 -0
  457. package/src/ui/handler/shim/two_fingers_touch.ts +112 -0
  458. package/src/ui/handler/tap_drag_zoom.test.ts +113 -0
  459. package/src/ui/handler/tap_drag_zoom.ts +112 -0
  460. package/src/ui/handler/tap_recognizer.ts +138 -0
  461. package/src/ui/handler/tap_zoom.ts +98 -0
  462. package/src/ui/handler/touch_pan.ts +115 -0
  463. package/src/ui/handler/transform-provider.ts +44 -0
  464. package/src/ui/handler/two_fingers_touch.test.ts +283 -0
  465. package/src/ui/handler/two_fingers_touch.ts +336 -0
  466. package/src/ui/handler_inertia.ts +157 -0
  467. package/src/ui/handler_manager.ts +637 -0
  468. package/src/ui/hash.test.ts +404 -0
  469. package/src/ui/hash.ts +153 -0
  470. package/src/ui/map.ts +3393 -0
  471. package/src/ui/map_tests/map_animation.test.ts +61 -0
  472. package/src/ui/map_tests/map_basic.test.ts +223 -0
  473. package/src/ui/map_tests/map_bounds.test.ts +123 -0
  474. package/src/ui/map_tests/map_calculate_camera_options.test.ts +113 -0
  475. package/src/ui/map_tests/map_canvas.test.ts +59 -0
  476. package/src/ui/map_tests/map_control.test.ts +61 -0
  477. package/src/ui/map_tests/map_disable_handlers.test.ts +38 -0
  478. package/src/ui/map_tests/map_events.test.ts +1001 -0
  479. package/src/ui/map_tests/map_feature_state.test.ts +421 -0
  480. package/src/ui/map_tests/map_images.test.ts +175 -0
  481. package/src/ui/map_tests/map_is_moving.test.ts +164 -0
  482. package/src/ui/map_tests/map_is_rotating.test.ts +62 -0
  483. package/src/ui/map_tests/map_is_zooming.test.ts +86 -0
  484. package/src/ui/map_tests/map_layer.test.ts +457 -0
  485. package/src/ui/map_tests/map_options.test.ts +64 -0
  486. package/src/ui/map_tests/map_pitch.test.ts +90 -0
  487. package/src/ui/map_tests/map_pixel_ratio.test.ts +75 -0
  488. package/src/ui/map_tests/map_query_rendered_features.test.ts +93 -0
  489. package/src/ui/map_tests/map_render.test.ts +90 -0
  490. package/src/ui/map_tests/map_request_render_frame.test.ts +51 -0
  491. package/src/ui/map_tests/map_resize.test.ts +120 -0
  492. package/src/ui/map_tests/map_style.test.ts +541 -0
  493. package/src/ui/map_tests/map_terrian.test.ts +104 -0
  494. package/src/ui/map_tests/map_webgl.test.ts +72 -0
  495. package/src/ui/map_tests/map_world_copies.test.ts +103 -0
  496. package/src/ui/map_tests/map_zoom.test.ts +95 -0
  497. package/src/ui/marker.test.ts +1149 -0
  498. package/src/ui/marker.ts +880 -0
  499. package/src/ui/popup.test.ts +827 -0
  500. package/src/ui/popup.ts +717 -0
  501. package/src/util/abort_error.ts +21 -0
  502. package/src/util/actor.test.ts +218 -0
  503. package/src/util/actor.ts +241 -0
  504. package/src/util/actor_messages.ts +149 -0
  505. package/src/util/ajax.test.ts +237 -0
  506. package/src/util/ajax.ts +297 -0
  507. package/src/util/browser.test.ts +23 -0
  508. package/src/util/browser.ts +63 -0
  509. package/src/util/color_ramp.test.ts +105 -0
  510. package/src/util/color_ramp.ts +56 -0
  511. package/src/util/config.ts +29 -0
  512. package/src/util/dictionary_coder.ts +23 -0
  513. package/src/util/dispatcher.test.ts +76 -0
  514. package/src/util/dispatcher.ts +78 -0
  515. package/src/util/dom.ts +135 -0
  516. package/src/util/evented.test.ts +231 -0
  517. package/src/util/evented.ts +178 -0
  518. package/src/util/find_pole_of_inaccessibility.test.ts +21 -0
  519. package/src/util/find_pole_of_inaccessibility.ts +130 -0
  520. package/src/util/geolocation_support.test.ts +43 -0
  521. package/src/util/geolocation_support.ts +23 -0
  522. package/src/util/global_worker_pool.ts +65 -0
  523. package/src/util/image.ts +150 -0
  524. package/src/util/image_request.test.ts +408 -0
  525. package/src/util/image_request.ts +246 -0
  526. package/src/util/intersection_tests.ts +206 -0
  527. package/src/util/is_char_in_unicode_block.test.ts +15 -0
  528. package/src/util/is_char_in_unicode_block.ts +345 -0
  529. package/src/util/offscreen_canvas_distorted.test.ts +13 -0
  530. package/src/util/offscreen_canvas_distorted.ts +39 -0
  531. package/src/util/offscreen_canvas_supported.ts +11 -0
  532. package/src/util/performance.ts +117 -0
  533. package/src/util/primitives.test.ts +140 -0
  534. package/src/util/primitives.ts +143 -0
  535. package/src/util/request_manager.ts +42 -0
  536. package/src/util/resolve_tokens.test.ts +45 -0
  537. package/src/util/resolve_tokens.ts +17 -0
  538. package/src/util/script_detection.test.ts +138 -0
  539. package/src/util/script_detection.ts +376 -0
  540. package/src/util/smart_wrap.test.ts +97 -0
  541. package/src/util/smart_wrap.ts +58 -0
  542. package/src/util/struct_array.test.ts +101 -0
  543. package/src/util/struct_array.ts +246 -0
  544. package/src/util/style.test.ts +34 -0
  545. package/src/util/style.ts +28 -0
  546. package/src/util/task_queue.test.ts +114 -0
  547. package/src/util/task_queue.ts +64 -0
  548. package/src/util/test/util.ts +185 -0
  549. package/src/util/throttle.test.ts +42 -0
  550. package/src/util/throttle.ts +28 -0
  551. package/src/util/throttled_invoker.ts +41 -0
  552. package/src/util/transferable_grid_index.test.ts +56 -0
  553. package/src/util/transferable_grid_index.ts +214 -0
  554. package/src/util/util.test.ts +414 -0
  555. package/src/util/util.ts +724 -0
  556. package/src/util/vectortile_to_geojson.ts +72 -0
  557. package/src/util/verticalize_punctuation.ts +110 -0
  558. package/src/util/web_worker.ts +16 -0
  559. package/src/util/web_worker_transfer.test.ts +153 -0
  560. package/src/util/web_worker_transfer.ts +254 -0
  561. package/src/util/webp_supported.ts +63 -0
  562. package/src/util/worker_pool.test.ts +43 -0
  563. package/src/util/worker_pool.ts +58 -0
  564. package/src/util/world_bounds.test.ts +59 -0
  565. package/src/util/world_bounds.ts +46 -0
@@ -0,0 +1,399 @@
1
+ import {GeoJSONWorkerSource, LoadGeoJSONParameters} from './geojson_worker_source';
2
+ import {StyleLayerIndex} from '../style/style_layer_index';
3
+ import {OverscaledTileID} from './tile_id';
4
+ import perf from '../util/performance';
5
+ import {LayerSpecification} from '@maplibre/maplibre-gl-style-spec';
6
+ import {Actor} from '../util/actor';
7
+ import {WorkerTileParameters} from './worker_source';
8
+ import {setPerformance, sleep} from '../util/test/util';
9
+ import {type FakeServer, fakeServer} from 'nise';
10
+
11
+ const actor = {send: () => {}} as any as Actor;
12
+
13
+ beforeEach(() => {
14
+ setPerformance();
15
+ });
16
+
17
+ describe('reloadTile', () => {
18
+ test('does not rebuild vector data unless data has changed', async () => {
19
+ const layers = [
20
+ {
21
+ id: 'mylayer',
22
+ source: 'sourceId',
23
+ type: 'symbol',
24
+ }
25
+ ] as LayerSpecification[];
26
+ const layerIndex = new StyleLayerIndex(layers);
27
+ const source = new GeoJSONWorkerSource(actor, layerIndex, []);
28
+ const spy = jest.spyOn(source, 'loadVectorTile');
29
+ const geoJson = {
30
+ 'type': 'Feature',
31
+ 'geometry': {
32
+ 'type': 'Point',
33
+ 'coordinates': [0, 0]
34
+ }
35
+ };
36
+ const tileParams = {
37
+ source: 'sourceId',
38
+ uid: 0,
39
+ tileID: new OverscaledTileID(0, 0, 0, 0, 0),
40
+ maxZoom: 10
41
+ };
42
+
43
+ await source.loadData({source: 'sourceId', data: JSON.stringify(geoJson)} as LoadGeoJSONParameters);
44
+
45
+ // first call should load vector data from geojson
46
+ const firstData = await source.reloadTile(tileParams as any as WorkerTileParameters);
47
+ expect(spy).toHaveBeenCalledTimes(1);
48
+
49
+ // second call won't give us new rawTileData
50
+ let data = await source.reloadTile(tileParams as any as WorkerTileParameters);
51
+ expect('rawTileData' in data).toBeFalsy();
52
+ data.rawTileData = firstData.rawTileData;
53
+ expect(data).toEqual(firstData);
54
+
55
+ // also shouldn't call loadVectorData again
56
+ expect(spy).toHaveBeenCalledTimes(1);
57
+
58
+ // replace geojson data
59
+ await source.loadData({source: 'sourceId', data: JSON.stringify(geoJson)} as LoadGeoJSONParameters);
60
+
61
+ // should call loadVectorData again after changing geojson data
62
+ data = await source.reloadTile(tileParams as any as WorkerTileParameters);
63
+ expect('rawTileData' in data).toBeTruthy();
64
+ expect(data).toEqual(firstData);
65
+ expect(spy).toHaveBeenCalledTimes(2);
66
+ });
67
+
68
+ });
69
+
70
+ describe('resourceTiming', () => {
71
+
72
+ const layers = [
73
+ {
74
+ id: 'mylayer',
75
+ source: 'sourceId',
76
+ type: 'symbol',
77
+ }
78
+ ] as LayerSpecification[];
79
+ const geoJson = {
80
+ 'type': 'Feature',
81
+ 'geometry': {
82
+ 'type': 'Point',
83
+ 'coordinates': [0, 0]
84
+ }
85
+ } as GeoJSON.GeoJSON;
86
+
87
+ test('loadData - url', async () => {
88
+ const exampleResourceTiming = {
89
+ connectEnd: 473,
90
+ connectStart: 473,
91
+ decodedBodySize: 86494,
92
+ domainLookupEnd: 473,
93
+ domainLookupStart: 473,
94
+ duration: 341,
95
+ encodedBodySize: 52528,
96
+ entryType: 'resource',
97
+ fetchStart: 473.5,
98
+ initiatorType: 'xmlhttprequest',
99
+ name: 'http://localhost:2900/fake.geojson',
100
+ nextHopProtocol: 'http/1.1',
101
+ redirectEnd: 0,
102
+ redirectStart: 0,
103
+ requestStart: 477,
104
+ responseEnd: 815,
105
+ responseStart: 672,
106
+ secureConnectionStart: 0
107
+ } as any as PerformanceEntry;
108
+
109
+ window.performance.getEntriesByName = jest.fn().mockReturnValue([exampleResourceTiming]);
110
+
111
+ const layerIndex = new StyleLayerIndex(layers);
112
+ const source = new GeoJSONWorkerSource(actor, layerIndex, []);
113
+ source.loadGeoJSON = () => Promise.resolve(geoJson);
114
+
115
+ const result = await source.loadData({source: 'testSource', request: {url: 'http://localhost/nonexistent', collectResourceTiming: true}} as LoadGeoJSONParameters);
116
+
117
+ expect(result.resourceTiming.testSource).toEqual([exampleResourceTiming]);
118
+ });
119
+
120
+ test('loadData - url (resourceTiming fallback method)', async () => {
121
+ const sampleMarks = [100, 350];
122
+ const marks = {};
123
+ const measures = {};
124
+ window.performance.getEntriesByName = jest.fn().mockImplementation((name) => { return measures[name] || []; });
125
+ jest.spyOn(perf, 'mark').mockImplementation((name) => {
126
+ marks[name] = sampleMarks.shift();
127
+ return null;
128
+ });
129
+ window.performance.measure = jest.fn().mockImplementation((name, start, end) => {
130
+ measures[name] = measures[name] || [];
131
+ measures[name].push({
132
+ duration: marks[end] - marks[start],
133
+ entryType: 'measure',
134
+ name,
135
+ startTime: marks[start]
136
+ });
137
+ return null;
138
+ });
139
+ jest.spyOn(perf, 'clearMarks').mockImplementation(() => { return null; });
140
+ jest.spyOn(perf, 'clearMeasures').mockImplementation(() => { return null; });
141
+
142
+ const layerIndex = new StyleLayerIndex(layers);
143
+ const source = new GeoJSONWorkerSource(actor, layerIndex, []);
144
+ source.loadGeoJSON = () => Promise.resolve(geoJson);
145
+
146
+ const result = await source.loadData({source: 'testSource', request: {url: 'http://localhost/nonexistent', collectResourceTiming: true}} as LoadGeoJSONParameters);
147
+
148
+ expect(result.resourceTiming.testSource).toEqual(
149
+ [{'duration': 250, 'entryType': 'measure', 'name': 'http://localhost/nonexistent', 'startTime': 100}]
150
+ );
151
+ });
152
+
153
+ test('loadData - data', async () => {
154
+ const layerIndex = new StyleLayerIndex(layers);
155
+ const source = new GeoJSONWorkerSource(actor, layerIndex, []);
156
+
157
+ const result = await source.loadData({source: 'testSource', data: JSON.stringify(geoJson)} as LoadGeoJSONParameters);
158
+ expect(result.resourceTiming).toBeUndefined();
159
+ });
160
+
161
+ });
162
+
163
+ describe('loadData', () => {
164
+ let server: FakeServer;
165
+ beforeEach(() => {
166
+ global.fetch = null;
167
+ server = fakeServer.create();
168
+ });
169
+ afterEach(() => {
170
+ server.restore();
171
+ });
172
+
173
+ const layers = [
174
+ {
175
+ id: 'layer1',
176
+ source: 'source1',
177
+ type: 'symbol',
178
+ },
179
+ {
180
+ id: 'layer2',
181
+ source: 'source2',
182
+ type: 'symbol',
183
+ }
184
+ ] as LayerSpecification[];
185
+
186
+ const geoJson = {
187
+ 'type': 'Feature',
188
+ 'geometry': {
189
+ 'type': 'Point',
190
+ 'coordinates': [0, 0]
191
+ }
192
+ } as GeoJSON.GeoJSON;
193
+
194
+ const updateableGeoJson = {
195
+ type: 'Feature',
196
+ id: 'point',
197
+ geometry: {
198
+ type: 'Point',
199
+ coordinates: [0, 0],
200
+ },
201
+ properties: {},
202
+ } as GeoJSON.GeoJSON;
203
+
204
+ const layerIndex = new StyleLayerIndex(layers);
205
+ function createWorker() {
206
+ return new GeoJSONWorkerSource(actor, layerIndex, []);
207
+ }
208
+
209
+ test('abandons previous requests', async () => {
210
+ const worker = createWorker();
211
+
212
+ server.respondWith(request => {
213
+ request.respond(200, {'Content-Type': 'application/json'}, JSON.stringify(geoJson));
214
+ });
215
+
216
+ const p1 = worker.loadData({source: 'source1', request: {url: ''}} as LoadGeoJSONParameters);
217
+ await sleep(0);
218
+
219
+ const p2 = worker.loadData({source: 'source1', request: {url: ''}} as LoadGeoJSONParameters);
220
+
221
+ await sleep(0);
222
+
223
+ server.respond();
224
+
225
+ const firstCallResult = await p1;
226
+ expect(firstCallResult && firstCallResult.abandoned).toBeTruthy();
227
+ const result = await p2;
228
+ expect(result && result.abandoned).toBeFalsy();
229
+ });
230
+
231
+ test('removeSource aborts requests', async () => {
232
+ const worker = createWorker();
233
+
234
+ server.respondWith(request => {
235
+ request.respond(200, {'Content-Type': 'application/json'}, JSON.stringify(geoJson));
236
+ });
237
+
238
+ const loadPromise = worker.loadData({source: 'source1', request: {url: ''}} as LoadGeoJSONParameters);
239
+ await sleep(0);
240
+ const removePromise = worker.removeSource({source: 'source1', type: 'type'});
241
+ await sleep(0);
242
+
243
+ server.respond();
244
+
245
+ const result = await loadPromise;
246
+ expect(result && result.abandoned).toBeTruthy();
247
+ await removePromise;
248
+ });
249
+
250
+ test('loadData with geojson creates an non-updateable source', async () => {
251
+ const worker = new GeoJSONWorkerSource(actor, layerIndex, []);
252
+
253
+ await worker.loadData({source: 'source1', data: JSON.stringify(geoJson)} as LoadGeoJSONParameters);
254
+ await expect(worker.loadData({source: 'source1', dataDiff: {removeAll: true}} as LoadGeoJSONParameters)).rejects.toBeDefined();
255
+ });
256
+
257
+ test('loadData with geojson creates an updateable source', async () => {
258
+ const worker = new GeoJSONWorkerSource(actor, layerIndex, []);
259
+
260
+ await worker.loadData({source: 'source1', data: JSON.stringify(updateableGeoJson)} as LoadGeoJSONParameters);
261
+ await expect(worker.loadData({source: 'source1', dataDiff: {removeAll: true}} as LoadGeoJSONParameters)).resolves.toBeDefined();
262
+ });
263
+
264
+ test('loadData with geojson network call creates an updateable source', async () => {
265
+ const worker = new GeoJSONWorkerSource(actor, layerIndex, []);
266
+
267
+ server.respondWith(request => {
268
+ request.respond(200, {'Content-Type': 'application/json'}, JSON.stringify(updateableGeoJson));
269
+ });
270
+
271
+ const load1Promise = worker.loadData({source: 'source1', request: {url: ''}} as LoadGeoJSONParameters);
272
+ server.respond();
273
+
274
+ await load1Promise;
275
+ await expect(worker.loadData({source: 'source1', dataDiff: {removeAll: true}} as LoadGeoJSONParameters)).resolves.toBeDefined();
276
+ });
277
+
278
+ test('loadData with geojson network call creates a non-updateable source', async () => {
279
+ const worker = new GeoJSONWorkerSource(actor, layerIndex, []);
280
+
281
+ server.respondWith(request => {
282
+ request.respond(200, {'Content-Type': 'application/json'}, JSON.stringify(geoJson));
283
+ });
284
+
285
+ const promise = worker.loadData({source: 'source1', request: {url: ''}} as LoadGeoJSONParameters);
286
+
287
+ server.respond();
288
+
289
+ await promise;
290
+
291
+ await expect(worker.loadData({source: 'source1', dataDiff: {removeAll: true}} as LoadGeoJSONParameters)).rejects.toBeDefined();
292
+ });
293
+
294
+ test('loadData with diff updates', async () => {
295
+ const worker = new GeoJSONWorkerSource(actor, layerIndex, []);
296
+
297
+ await worker.loadData({source: 'source1', data: JSON.stringify(updateableGeoJson)} as LoadGeoJSONParameters);
298
+ await expect(worker.loadData({source: 'source1', dataDiff: {
299
+ add: [{
300
+ type: 'Feature',
301
+ id: 'update_point',
302
+ geometry: {type: 'Point', coordinates: [0, 0]},
303
+ properties: {}
304
+ }]
305
+ }} as LoadGeoJSONParameters)).resolves.toBeDefined();
306
+ });
307
+ });
308
+
309
+ describe('getData', () => {
310
+ let server: FakeServer;
311
+ beforeEach(() => {
312
+ global.fetch = null;
313
+ server = fakeServer.create();
314
+ });
315
+ afterEach(() => {
316
+ server.restore();
317
+ });
318
+
319
+ const layers = [
320
+ {
321
+ id: 'layer1',
322
+ source: 'source1',
323
+ type: 'symbol',
324
+ },
325
+ {
326
+ id: 'layer2',
327
+ source: 'source2',
328
+ type: 'symbol',
329
+ }
330
+ ] as LayerSpecification[];
331
+
332
+ const geoJson = {
333
+ 'type': 'Feature',
334
+ 'geometry': {
335
+ 'type': 'Point',
336
+ 'coordinates': [0, 0]
337
+ }
338
+ } as GeoJSON.GeoJSON;
339
+
340
+ const updateableGeoJson = {
341
+ type: 'Feature',
342
+ id: 'point',
343
+ geometry: {
344
+ type: 'Point',
345
+ coordinates: [0, 0],
346
+ },
347
+ properties: {},
348
+ } as GeoJSON.GeoJSON;
349
+
350
+ const layerIndex = new StyleLayerIndex(layers);
351
+
352
+ test('getData returns correct geojson when the source was loaded with geojson', async () => {
353
+ const worker = new GeoJSONWorkerSource(actor, layerIndex, []);
354
+
355
+ await worker.loadData({source: 'source1', data: JSON.stringify(geoJson)} as LoadGeoJSONParameters);
356
+ await expect(worker.getData()).resolves.toStrictEqual(geoJson);
357
+ });
358
+
359
+ test('getData after a geojson network call returns actual loaded geojson', async () => {
360
+ const worker = new GeoJSONWorkerSource(actor, layerIndex, []);
361
+
362
+ server.respondWith(request => {
363
+ request.respond(200, {'Content-Type': 'application/json'}, JSON.stringify(updateableGeoJson));
364
+ });
365
+
366
+ const load1Promise = worker.loadData({source: 'source1', request: {url: ''}} as LoadGeoJSONParameters);
367
+ server.respond();
368
+
369
+ await load1Promise;
370
+ await expect(worker.getData()).resolves.toStrictEqual(updateableGeoJson);
371
+ });
372
+
373
+ test('getData after diff updates returns updated geojson', async () => {
374
+ const worker = new GeoJSONWorkerSource(actor, layerIndex, []);
375
+
376
+ await worker.loadData({source: 'source1', data: JSON.stringify(updateableGeoJson)} as LoadGeoJSONParameters);
377
+ await expect(worker.loadData({source: 'source1', dataDiff: {
378
+ add: [{
379
+ type: 'Feature',
380
+ id: 'update_point',
381
+ geometry: {type: 'Point', coordinates: [0, 0]},
382
+ properties: {}
383
+ }]
384
+ }} as LoadGeoJSONParameters)).resolves.toBeDefined();
385
+
386
+ await expect(worker.getData()).resolves.toStrictEqual({
387
+ type: 'FeatureCollection',
388
+ features: [
389
+ {...updateableGeoJson},
390
+ {
391
+ type: 'Feature',
392
+ id: 'update_point',
393
+ geometry: {type: 'Point', coordinates: [0, 0]},
394
+ properties: {}
395
+ }
396
+ ]
397
+ });
398
+ });
399
+ });
@@ -0,0 +1,303 @@
1
+ import {getJSON} from '../util/ajax';
2
+ import {RequestPerformance} from '../util/performance';
3
+ import rewind from '@mapbox/geojson-rewind';
4
+ import {GeoJSONWrapper} from './geojson_wrapper';
5
+ import vtpbf from 'vt-pbf';
6
+ import Supercluster, {type Options as SuperclusterOptions, type ClusterProperties} from 'supercluster';
7
+ import geojsonvt, {type Options as GeoJSONVTOptions} from 'geojson-vt';
8
+ import {VectorTileWorkerSource} from './vector_tile_worker_source';
9
+ import {createExpression} from '@maplibre/maplibre-gl-style-spec';
10
+ import {isAbortError} from '../util/abort_error';
11
+
12
+ import type {
13
+ WorkerTileParameters,
14
+ WorkerTileResult,
15
+ } from '../source/worker_source';
16
+
17
+ import type {LoadVectorTileResult} from './vector_tile_worker_source';
18
+ import type {RequestParameters} from '../util/ajax';
19
+ import {isUpdateableGeoJSON, type GeoJSONSourceDiff, applySourceDiff, toUpdateable, GeoJSONFeatureId} from './geojson_source_diff';
20
+ import type {ClusterIDAndSource, GeoJSONWorkerSourceLoadDataResult, RemoveSourceParams} from '../util/actor_messages';
21
+
22
+ /**
23
+ * The geojson worker options that can be passed to the worker
24
+ */
25
+ export type GeoJSONWorkerOptions = {
26
+ source?: string;
27
+ cluster?: boolean;
28
+ geojsonVtOptions?: GeoJSONVTOptions;
29
+ superclusterOptions?: SuperclusterOptions<any, any>;
30
+ clusterProperties?: ClusterProperties;
31
+ filter?: Array<unknown>;
32
+ promoteId?: string;
33
+ collectResourceTiming?: boolean;
34
+ }
35
+
36
+ /**
37
+ * Parameters needed to load a geojson to the worker
38
+ */
39
+ export type LoadGeoJSONParameters = GeoJSONWorkerOptions & {
40
+ type: 'geojson';
41
+ request?: RequestParameters;
42
+ /**
43
+ * Literal GeoJSON data. Must be provided if `request.url` is not.
44
+ */
45
+ data?: string;
46
+ dataDiff?: GeoJSONSourceDiff;
47
+ };
48
+
49
+ export type LoadGeoJSON = (params: LoadGeoJSONParameters, abortController: AbortController) => Promise<GeoJSON.GeoJSON>;
50
+
51
+ type GeoJSONIndex = ReturnType<typeof geojsonvt> | Supercluster;
52
+
53
+ /**
54
+ * The {@link WorkerSource} implementation that supports {@link GeoJSONSource}.
55
+ * This class is designed to be easily reused to support custom source types
56
+ * for data formats that can be parsed/converted into an in-memory GeoJSON
57
+ * representation. To do so, create it with
58
+ * `new GeoJSONWorkerSource(actor, layerIndex, customLoadGeoJSONFunction)`.
59
+ * For a full example, see [mapbox-gl-topojson](https://github.com/developmentseed/mapbox-gl-topojson).
60
+ */
61
+ export class GeoJSONWorkerSource extends VectorTileWorkerSource {
62
+ /**
63
+ * The actual GeoJSON takes some time to load (as there may be a need to parse a diff, or to apply filters, or the
64
+ * data may even need to be loaded via a URL). This promise resolves with a ready-to-be-consumed GeoJSON which is
65
+ * ready to be returned by the `getData` method.
66
+ */
67
+ _pendingData: Promise<GeoJSON.GeoJSON>;
68
+ _pendingRequest: AbortController;
69
+ _geoJSONIndex: GeoJSONIndex;
70
+ _dataUpdateable = new Map<GeoJSONFeatureId, GeoJSON.Feature>();
71
+
72
+ override async loadVectorTile(params: WorkerTileParameters, _abortController: AbortController): Promise<LoadVectorTileResult | null> {
73
+ const canonical = params.tileID.canonical;
74
+
75
+ if (!this._geoJSONIndex) {
76
+ throw new Error('Unable to parse the data into a cluster or geojson');
77
+ }
78
+
79
+ const geoJSONTile = this._geoJSONIndex.getTile(canonical.z, canonical.x, canonical.y);
80
+ if (!geoJSONTile) {
81
+ return null;
82
+ }
83
+
84
+ const geojsonWrapper = new GeoJSONWrapper(geoJSONTile.features);
85
+ // Encode the geojson-vt tile into binary vector tile form. This
86
+ // is a convenience that allows `FeatureIndex` to operate the same way
87
+ // across `VectorTileSource` and `GeoJSONSource` data.
88
+ let pbf = vtpbf(geojsonWrapper);
89
+ if (pbf.byteOffset !== 0 || pbf.byteLength !== pbf.buffer.byteLength) {
90
+ // Compatibility with node Buffer (https://github.com/mapbox/pbf/issues/35)
91
+ pbf = new Uint8Array(pbf);
92
+ }
93
+
94
+ return {
95
+ vectorTile: geojsonWrapper,
96
+ rawData: pbf.buffer
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Fetches (if appropriate), parses, and index geojson data into tiles. This
102
+ * preparatory method must be called before {@link GeoJSONWorkerSource#loadTile}
103
+ * can correctly serve up tiles.
104
+ *
105
+ * Defers to {@link GeoJSONWorkerSource#loadAndProcessGeoJSON} for the pre-processing.
106
+ *
107
+ * When a `loadData` request comes in while a previous one is being processed,
108
+ * the previous one is aborted.
109
+ *
110
+ * @param params - the parameters
111
+ * @returns a promise that resolves when the data is loaded and parsed into a GeoJSON object
112
+ */
113
+ async loadData(params: LoadGeoJSONParameters): Promise<GeoJSONWorkerSourceLoadDataResult> {
114
+ this._pendingRequest?.abort();
115
+ const perf = (params && params.request && params.request.collectResourceTiming) ?
116
+ new RequestPerformance(params.request) : false;
117
+
118
+ this._pendingRequest = new AbortController();
119
+ try {
120
+ this._pendingData = this.loadAndProcessGeoJSON(params, this._pendingRequest);
121
+
122
+ this._geoJSONIndex = params.cluster ?
123
+ new Supercluster(getSuperclusterOptions(params)).load((await this._pendingData as any).features) :
124
+ geojsonvt(await this._pendingData, params.geojsonVtOptions);
125
+
126
+ this.loaded = {};
127
+
128
+ const result = {} as GeoJSONWorkerSourceLoadDataResult;
129
+ if (perf) {
130
+ const resourceTimingData = perf.finish();
131
+ // it's necessary to eval the result of getEntriesByName() here via parse/stringify
132
+ // late evaluation in the main thread causes TypeError: illegal invocation
133
+ if (resourceTimingData) {
134
+ result.resourceTiming = {};
135
+ result.resourceTiming[params.source] = JSON.parse(JSON.stringify(resourceTimingData));
136
+ }
137
+ }
138
+ return result;
139
+ } catch (err) {
140
+ delete this._pendingRequest;
141
+ if (isAbortError(err)) {
142
+ return {abandoned: true};
143
+ }
144
+ throw err;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Allows to get the source's actual GeoJSON.
150
+ *
151
+ * @returns a promise which is resolved with the source's actual GeoJSON
152
+ */
153
+ async getData(): Promise<GeoJSON.GeoJSON> {
154
+ return this._pendingData;
155
+ }
156
+
157
+ /**
158
+ * Implements {@link WorkerSource#reloadTile}.
159
+ *
160
+ * If the tile is loaded, uses the implementation in VectorTileWorkerSource.
161
+ * Otherwise, such as after a setData() call, we load the tile fresh.
162
+ *
163
+ * @param params - the parameters
164
+ * @returns A promise that resolves when the tile is reloaded
165
+ */
166
+ reloadTile(params: WorkerTileParameters): Promise<WorkerTileResult> {
167
+ const loaded = this.loaded,
168
+ uid = params.uid;
169
+
170
+ if (loaded && loaded[uid]) {
171
+ return super.reloadTile(params);
172
+ } else {
173
+ return this.loadTile(params);
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Fetch, parse and process GeoJSON according to the given params.
179
+ *
180
+ * Defers to {@link GeoJSONWorkerSource#loadGeoJSON} for the fetching and parsing.
181
+ *
182
+ * @param params - the parameters
183
+ * @param abortController - the abort controller that allows aborting this operation
184
+ * @returns a promise that is resolved with the processes GeoJSON
185
+ */
186
+ async loadAndProcessGeoJSON(params: LoadGeoJSONParameters, abortController: AbortController): Promise<GeoJSON.GeoJSON> {
187
+ let data = await this.loadGeoJSON(params, abortController);
188
+
189
+ delete this._pendingRequest;
190
+ if (typeof data !== 'object') {
191
+ throw new Error(`Input data given to '${params.source}' is not a valid GeoJSON object.`);
192
+ }
193
+ rewind(data, true);
194
+
195
+ if (params.filter) {
196
+ const compiled = createExpression(params.filter, {type: 'boolean', 'property-type': 'data-driven', overridable: false, transition: false} as any);
197
+ if (compiled.result === 'error')
198
+ throw new Error(compiled.value.map(err => `${err.key}: ${err.message}`).join(', '));
199
+
200
+ const features = (data as any).features.filter(feature => compiled.value.evaluate({zoom: 0}, feature));
201
+ data = {type: 'FeatureCollection', features};
202
+ }
203
+
204
+ return data;
205
+ }
206
+
207
+ /**
208
+ * Fetch and parse GeoJSON according to the given params.
209
+ *
210
+ * GeoJSON is loaded and parsed from `params.url` if it exists, or else
211
+ * expected as a literal (string or object) `params.data`.
212
+ *
213
+ * @param params - the parameters
214
+ * @param abortController - the abort controller that allows aborting this operation
215
+ * @returns a promise that resolves when the data is loaded
216
+ */
217
+ async loadGeoJSON(params: LoadGeoJSONParameters, abortController: AbortController): Promise<GeoJSON.GeoJSON> {
218
+ const {promoteId} = params;
219
+ if (params.request) {
220
+ const response = await getJSON<GeoJSON.GeoJSON>(params.request, abortController);
221
+ this._dataUpdateable = isUpdateableGeoJSON(response.data, promoteId) ? toUpdateable(response.data, promoteId) : undefined;
222
+ return response.data;
223
+ }
224
+ if (typeof params.data === 'string') {
225
+ try {
226
+ const parsed = JSON.parse(params.data);
227
+ this._dataUpdateable = isUpdateableGeoJSON(parsed, promoteId) ? toUpdateable(parsed, promoteId) : undefined;
228
+ return parsed;
229
+ } catch (e) {
230
+ throw new Error(`Input data given to '${params.source}' is not a valid GeoJSON object.`);
231
+ }
232
+ }
233
+ if (!params.dataDiff) {
234
+ throw new Error(`Input data given to '${params.source}' is not a valid GeoJSON object.`);
235
+ }
236
+ if (!this._dataUpdateable) {
237
+ throw new Error(`Cannot update existing geojson data in ${params.source}`);
238
+ }
239
+ applySourceDiff(this._dataUpdateable, params.dataDiff, promoteId);
240
+ return {type: 'FeatureCollection', features: Array.from(this._dataUpdateable.values())};
241
+ }
242
+
243
+ async removeSource(_params: RemoveSourceParams): Promise<void> {
244
+ if (this._pendingRequest) {
245
+ this._pendingRequest.abort();
246
+ }
247
+ }
248
+
249
+ getClusterExpansionZoom(params: ClusterIDAndSource): number {
250
+ return (this._geoJSONIndex as Supercluster).getClusterExpansionZoom(params.clusterId);
251
+ }
252
+
253
+ getClusterChildren(params: ClusterIDAndSource): Array<GeoJSON.Feature> {
254
+ return (this._geoJSONIndex as Supercluster).getChildren(params.clusterId);
255
+ }
256
+
257
+ getClusterLeaves(params: {
258
+ clusterId: number;
259
+ limit: number;
260
+ offset: number;
261
+ }): Array<GeoJSON.Feature> {
262
+ return (this._geoJSONIndex as Supercluster).getLeaves(params.clusterId, params.limit, params.offset);
263
+ }
264
+ }
265
+
266
+ function getSuperclusterOptions({superclusterOptions, clusterProperties}: LoadGeoJSONParameters) {
267
+ if (!clusterProperties || !superclusterOptions) return superclusterOptions;
268
+
269
+ const mapExpressions = {};
270
+ const reduceExpressions = {};
271
+ const globals = {accumulated: null, zoom: 0};
272
+ const feature = {properties: null};
273
+ const propertyNames = Object.keys(clusterProperties);
274
+
275
+ for (const key of propertyNames) {
276
+ const [operator, mapExpression] = clusterProperties[key];
277
+
278
+ const mapExpressionParsed = createExpression(mapExpression);
279
+ const reduceExpressionParsed = createExpression(
280
+ typeof operator === 'string' ? [operator, ['accumulated'], ['get', key]] : operator);
281
+
282
+ mapExpressions[key] = mapExpressionParsed.value;
283
+ reduceExpressions[key] = reduceExpressionParsed.value;
284
+ }
285
+
286
+ superclusterOptions.map = (pointProperties) => {
287
+ feature.properties = pointProperties;
288
+ const properties = {};
289
+ for (const key of propertyNames) {
290
+ properties[key] = mapExpressions[key].evaluate(globals, feature);
291
+ }
292
+ return properties;
293
+ };
294
+ superclusterOptions.reduce = (accumulated, clusterProperties) => {
295
+ feature.properties = clusterProperties;
296
+ for (const key of propertyNames) {
297
+ globals.accumulated = accumulated[key];
298
+ accumulated[key] = reduceExpressions[key].evaluate(globals, feature);
299
+ }
300
+ };
301
+
302
+ return superclusterOptions;
303
+ }