isard 1.0.0 → 1.2.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 (268) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/{basemaps.d.ts → basemap/basemaps.d.ts} +3 -3
  3. package/dist/{basemaps.js → basemap/basemaps.js} +3 -3
  4. package/dist/basemap/basemaps.js.map +1 -0
  5. package/dist/{grid.d.ts → basemap/grid.d.ts} +6 -6
  6. package/dist/{grid.js → basemap/grid.js} +61 -67
  7. package/dist/basemap/grid.js.map +1 -0
  8. package/dist/{mvt.d.ts → basemap/mvt.d.ts} +1 -1
  9. package/dist/{mvt.js → basemap/mvt.js} +6 -6
  10. package/dist/basemap/mvt.js.map +1 -0
  11. package/dist/{pmtiles.d.ts → basemap/pmtiles.d.ts} +16 -10
  12. package/dist/{pmtiles.js → basemap/pmtiles.js} +41 -33
  13. package/dist/basemap/pmtiles.js.map +1 -0
  14. package/dist/{resample.d.ts → basemap/resample.d.ts} +11 -2
  15. package/dist/{resample.js → basemap/resample.js} +18 -16
  16. package/dist/basemap/resample.js.map +1 -0
  17. package/dist/{terrain.d.ts → basemap/terrain.d.ts} +3 -3
  18. package/dist/{terrain.js → basemap/terrain.js} +7 -7
  19. package/dist/basemap/terrain.js.map +1 -0
  20. package/dist/{vectorstyle.d.ts → basemap/vectorstyle.d.ts} +12 -10
  21. package/dist/{vectorstyle.js → basemap/vectorstyle.js} +129 -111
  22. package/dist/basemap/vectorstyle.js.map +1 -0
  23. package/dist/{vectortiles.d.ts → basemap/vectortiles.d.ts} +18 -18
  24. package/dist/{vectortiles.js → basemap/vectortiles.js} +157 -109
  25. package/dist/basemap/vectortiles.js.map +1 -0
  26. package/dist/{wmts.d.ts → basemap/wmts.d.ts} +3 -3
  27. package/dist/{wmts.js → basemap/wmts.js} +19 -14
  28. package/dist/basemap/wmts.js.map +1 -0
  29. package/dist/basemap.worker.js +2 -2
  30. package/dist/basemap.worker.js.map +14 -13
  31. package/dist/bind/layers.d.ts +46 -0
  32. package/dist/bind/layers.js +154 -0
  33. package/dist/bind/layers.js.map +1 -0
  34. package/dist/{crs.d.ts → data/crs.d.ts} +11 -11
  35. package/dist/{crs.js → data/crs.js} +38 -34
  36. package/dist/data/crs.js.map +1 -0
  37. package/dist/{gpx.d.ts → data/gpx.d.ts} +2 -2
  38. package/dist/{gpx.js → data/gpx.js} +20 -20
  39. package/dist/data/gpx.js.map +1 -0
  40. package/dist/{kml.d.ts → data/kml.d.ts} +2 -2
  41. package/dist/{kml.js → data/kml.js} +42 -39
  42. package/dist/data/kml.js.map +1 -0
  43. package/dist/{topojson.d.ts → data/topojson.d.ts} +2 -2
  44. package/dist/{topojson.js → data/topojson.js} +15 -10
  45. package/dist/data/topojson.js.map +1 -0
  46. package/dist/{xml.d.ts → data/xml.d.ts} +5 -5
  47. package/dist/{xml.js → data/xml.js} +19 -18
  48. package/dist/data/xml.js.map +1 -0
  49. package/dist/decoder.worker.js +4 -4
  50. package/dist/decoder.worker.js.map +7 -7
  51. package/dist/{decoders.d.ts → engine/decoders.d.ts} +3 -3
  52. package/dist/{decoders.js → engine/decoders.js} +28 -25
  53. package/dist/engine/decoders.js.map +1 -0
  54. package/dist/{loader.d.ts → engine/loader.d.ts} +1 -1
  55. package/dist/{loader.js → engine/loader.js} +17 -14
  56. package/dist/engine/loader.js.map +1 -0
  57. package/dist/{protocol.d.ts → engine/protocol.d.ts} +1 -1
  58. package/dist/engine/protocol.js +3 -0
  59. package/dist/engine/protocol.js.map +1 -0
  60. package/dist/{requests.d.ts → engine/requests.d.ts} +1 -1
  61. package/dist/{requests.js → engine/requests.js} +19 -16
  62. package/dist/engine/requests.js.map +1 -0
  63. package/dist/engine-loader.d.ts +13 -9
  64. package/dist/engine-loader.js +30 -30
  65. package/dist/engine-loader.js.map +1 -1
  66. package/dist/formats.d.ts +3 -3
  67. package/dist/formats.js +3 -3
  68. package/dist/formats.js.map +1 -1
  69. package/dist/geoplateforme.d.ts +13 -13
  70. package/dist/geoplateforme.js +23 -21
  71. package/dist/geoplateforme.js.map +1 -1
  72. package/dist/index.d.ts +30 -29
  73. package/dist/index.js +18 -18
  74. package/dist/index.js.map +1 -1
  75. package/dist/isard_bg.wasm +0 -0
  76. package/dist/isard_core_bg.wasm +0 -0
  77. package/dist/isard_points_bg.wasm +0 -0
  78. package/dist/{extrusions.d.ts → layers/extrusions.d.ts} +1 -1
  79. package/dist/{extrusions.js → layers/extrusions.js} +10 -5
  80. package/dist/layers/extrusions.js.map +1 -0
  81. package/dist/{features.d.ts → layers/features.d.ts} +10 -10
  82. package/dist/{features.js → layers/features.js} +44 -45
  83. package/dist/layers/features.js.map +1 -0
  84. package/dist/{glyphs.d.ts → layers/glyphs.d.ts} +6 -6
  85. package/dist/{glyphs.js → layers/glyphs.js} +45 -41
  86. package/dist/layers/glyphs.js.map +1 -0
  87. package/dist/{icons.d.ts → layers/icons.d.ts} +10 -10
  88. package/dist/{icons.js → layers/icons.js} +84 -69
  89. package/dist/layers/icons.js.map +1 -0
  90. package/dist/{layers.d.ts → layers/layers.d.ts} +9 -4
  91. package/dist/{layers.js → layers/layers.js} +35 -31
  92. package/dist/layers/layers.js.map +1 -0
  93. package/dist/{panoramas.d.ts → layers/panoramas.d.ts} +3 -3
  94. package/dist/{panoramas.js → layers/panoramas.js} +54 -43
  95. package/dist/layers/panoramas.js.map +1 -0
  96. package/dist/{pointclouds.d.ts → layers/pointclouds.d.ts} +5 -5
  97. package/dist/{pointclouds.js → layers/pointclouds.js} +26 -34
  98. package/dist/layers/pointclouds.js.map +1 -0
  99. package/dist/{symbols.d.ts → layers/symbols.d.ts} +3 -3
  100. package/dist/{symbols.js → layers/symbols.js} +69 -72
  101. package/dist/layers/symbols.js.map +1 -0
  102. package/dist/map/basemap-layers.d.ts +26 -0
  103. package/dist/map/basemap-layers.js +61 -0
  104. package/dist/map/basemap-layers.js.map +1 -0
  105. package/dist/map/canvas.d.ts +17 -0
  106. package/dist/map/canvas.js +56 -0
  107. package/dist/map/canvas.js.map +1 -0
  108. package/dist/map/checks.d.ts +11 -0
  109. package/dist/map/checks.js +39 -0
  110. package/dist/map/checks.js.map +1 -0
  111. package/dist/map/credits.d.ts +17 -0
  112. package/dist/map/credits.js +34 -0
  113. package/dist/map/credits.js.map +1 -0
  114. package/dist/map/engine-settings.d.ts +15 -0
  115. package/dist/map/engine-settings.js +45 -0
  116. package/dist/map/engine-settings.js.map +1 -0
  117. package/dist/map/engines.d.ts +41 -0
  118. package/dist/map/engines.js +77 -0
  119. package/dist/map/engines.js.map +1 -0
  120. package/dist/map/events.d.ts +14 -0
  121. package/dist/map/events.js +46 -0
  122. package/dist/map/events.js.map +1 -0
  123. package/dist/map/frame-loop.d.ts +61 -0
  124. package/dist/map/frame-loop.js +139 -0
  125. package/dist/map/frame-loop.js.map +1 -0
  126. package/dist/map/hover-pick.d.ts +30 -0
  127. package/dist/map/hover-pick.js +56 -0
  128. package/dist/map/hover-pick.js.map +1 -0
  129. package/dist/map/layer-spec.d.ts +42 -0
  130. package/dist/map/layer-spec.js +34 -0
  131. package/dist/map/layer-spec.js.map +1 -0
  132. package/dist/map/layer-stack.d.ts +36 -0
  133. package/dist/map/layer-stack.js +101 -0
  134. package/dist/map/layer-stack.js.map +1 -0
  135. package/dist/map/overlay-host.d.ts +36 -0
  136. package/dist/map/overlay-host.js +101 -0
  137. package/dist/map/overlay-host.js.map +1 -0
  138. package/dist/map/panorama-host.d.ts +5 -0
  139. package/dist/map/panorama-host.js +32 -0
  140. package/dist/map/panorama-host.js.map +1 -0
  141. package/dist/map/raster-source.d.ts +11 -0
  142. package/dist/map/raster-source.js +26 -0
  143. package/dist/map/raster-source.js.map +1 -0
  144. package/dist/map/symbol-atlases.d.ts +26 -0
  145. package/dist/map/symbol-atlases.js +59 -0
  146. package/dist/map/symbol-atlases.js.map +1 -0
  147. package/dist/map/viewshed.d.ts +5 -0
  148. package/dist/map/viewshed.js +28 -0
  149. package/dist/map/viewshed.js.map +1 -0
  150. package/dist/map/workers.d.ts +46 -0
  151. package/dist/map/workers.js +73 -0
  152. package/dist/map/workers.js.map +1 -0
  153. package/dist/map.d.ts +46 -127
  154. package/dist/map.js +183 -698
  155. package/dist/map.js.map +1 -1
  156. package/dist/projections.d.ts +3 -3
  157. package/dist/projections.js +2 -2
  158. package/dist/projections.js.map +1 -1
  159. package/dist/react/Control.d.ts +11 -0
  160. package/dist/react/Control.js +18 -0
  161. package/dist/react/Control.js.map +1 -0
  162. package/dist/react/CustomLayer.d.ts +11 -0
  163. package/dist/react/CustomLayer.js +30 -0
  164. package/dist/react/CustomLayer.js.map +1 -0
  165. package/dist/react/IsardMap.d.ts +43 -0
  166. package/dist/react/IsardMap.js +146 -0
  167. package/dist/react/IsardMap.js.map +1 -0
  168. package/dist/react/Layer.d.ts +42 -0
  169. package/dist/react/Layer.js +74 -0
  170. package/dist/react/Layer.js.map +1 -0
  171. package/dist/react/Marker.d.ts +24 -0
  172. package/dist/react/Marker.js +53 -0
  173. package/dist/react/Marker.js.map +1 -0
  174. package/dist/react/Panel.d.ts +11 -0
  175. package/dist/react/Panel.js +37 -0
  176. package/dist/react/Panel.js.map +1 -0
  177. package/dist/react/Popup.d.ts +18 -0
  178. package/dist/react/Popup.js +60 -0
  179. package/dist/react/Popup.js.map +1 -0
  180. package/dist/react/Swipe.d.ts +9 -0
  181. package/dist/react/Swipe.js +41 -0
  182. package/dist/react/Swipe.js.map +1 -0
  183. package/dist/react/Viewshed.d.ts +5 -0
  184. package/dist/react/Viewshed.js +28 -0
  185. package/dist/react/Viewshed.js.map +1 -0
  186. package/dist/react/context.d.ts +32 -0
  187. package/dist/react/context.js +20 -0
  188. package/dist/react/context.js.map +1 -0
  189. package/dist/react/index.d.ts +26 -0
  190. package/dist/react/index.js +22 -0
  191. package/dist/react/index.js.map +1 -0
  192. package/dist/settings.d.ts +6 -10
  193. package/dist/settings.js +19 -17
  194. package/dist/settings.js.map +1 -1
  195. package/dist/types.d.ts +8 -8
  196. package/dist/types.js +1 -0
  197. package/dist/types.js.map +1 -1
  198. package/dist/{controls.d.ts → ui/controls.d.ts} +1 -1
  199. package/dist/{controls.js → ui/controls.js} +6 -4
  200. package/dist/ui/controls.js.map +1 -0
  201. package/dist/{interaction.d.ts → ui/interaction.d.ts} +9 -5
  202. package/dist/{interaction.js → ui/interaction.js} +9 -8
  203. package/dist/ui/interaction.js.map +1 -0
  204. package/dist/{overlay.d.ts → ui/overlay.d.ts} +2 -2
  205. package/dist/{overlay.js → ui/overlay.js} +18 -20
  206. package/dist/ui/overlay.js.map +1 -0
  207. package/dist/{style.d.ts → ui/style.d.ts} +1 -1
  208. package/dist/{style.js → ui/style.js} +2 -2
  209. package/dist/ui/style.js.map +1 -0
  210. package/dist/{animation.d.ts → util/animation.d.ts} +9 -5
  211. package/dist/{animation.js → util/animation.js} +6 -6
  212. package/dist/util/animation.js.map +1 -0
  213. package/dist/{color.d.ts → util/color.d.ts} +1 -1
  214. package/dist/{color.js → util/color.js} +14 -16
  215. package/dist/util/color.js.map +1 -0
  216. package/dist/{geo.d.ts → util/geo.d.ts} +6 -6
  217. package/dist/{geo.js → util/geo.js} +12 -12
  218. package/dist/util/geo.js.map +1 -0
  219. package/dist/util/guards.d.ts +7 -0
  220. package/dist/util/guards.js +8 -0
  221. package/dist/util/guards.js.map +1 -0
  222. package/dist/util/lru.js.map +1 -0
  223. package/dist/wasm/isard.d.ts +168 -0
  224. package/dist/wasm/isard.js +146 -0
  225. package/dist/wasm/isard_core.d.ts +144 -0
  226. package/dist/wasm/isard_core.js +122 -0
  227. package/dist/{basemap.worker.d.ts → workers/basemap.worker.d.ts} +17 -7
  228. package/dist/workers/basemap.worker.js +658 -0
  229. package/dist/workers/basemap.worker.js.map +1 -0
  230. package/package.json +24 -1
  231. package/vite.js +1 -1
  232. package/dist/animation.js.map +0 -1
  233. package/dist/basemaps.js.map +0 -1
  234. package/dist/color.js.map +0 -1
  235. package/dist/controls.js.map +0 -1
  236. package/dist/crs.js.map +0 -1
  237. package/dist/decoders.js.map +0 -1
  238. package/dist/extrusions.js.map +0 -1
  239. package/dist/features.js.map +0 -1
  240. package/dist/geo.js.map +0 -1
  241. package/dist/glyphs.js.map +0 -1
  242. package/dist/gpx.js.map +0 -1
  243. package/dist/grid.js.map +0 -1
  244. package/dist/icons.js.map +0 -1
  245. package/dist/interaction.js.map +0 -1
  246. package/dist/kml.js.map +0 -1
  247. package/dist/layers.js.map +0 -1
  248. package/dist/loader.js.map +0 -1
  249. package/dist/lru.js.map +0 -1
  250. package/dist/mvt.js.map +0 -1
  251. package/dist/overlay.js.map +0 -1
  252. package/dist/panoramas.js.map +0 -1
  253. package/dist/pmtiles.js.map +0 -1
  254. package/dist/pointclouds.js.map +0 -1
  255. package/dist/protocol.js +0 -2
  256. package/dist/protocol.js.map +0 -1
  257. package/dist/requests.js.map +0 -1
  258. package/dist/resample.js.map +0 -1
  259. package/dist/style.js.map +0 -1
  260. package/dist/symbols.js.map +0 -1
  261. package/dist/terrain.js.map +0 -1
  262. package/dist/topojson.js.map +0 -1
  263. package/dist/vectorstyle.js.map +0 -1
  264. package/dist/vectortiles.js.map +0 -1
  265. package/dist/wmts.js.map +0 -1
  266. package/dist/xml.js.map +0 -1
  267. /package/dist/{lru.d.ts → util/lru.d.ts} +0 -0
  268. /package/dist/{lru.js → util/lru.js} +0 -0
@@ -1,20 +1,20 @@
1
1
  import { child, children, childText, parseXml } from "./xml.js";
2
2
  /** The fields of a waypoint, route or track kept as properties when present */
3
3
  const FIELDS = ['name', 'cmt', 'desc', 'src', 'sym', 'type', 'number'];
4
- function properties(element) {
4
+ const properties = (element) => {
5
5
  const out = {};
6
- for (const key of FIELDS) {
6
+ FIELDS.forEach((key) => {
7
7
  const value = childText(element, key);
8
8
  if (value !== undefined)
9
9
  out[key] = key === 'number' ? Number(value) : value;
10
- }
10
+ });
11
11
  const link = child(element, 'link')?.attributes.href;
12
12
  if (link !== undefined)
13
13
  out.link = link;
14
14
  return out;
15
- }
15
+ };
16
16
  /** A point of a GPX file (wpt, rtept, trkpt): its position, its altitude third if any, and its time */
17
- function point(element) {
17
+ const point = (element) => {
18
18
  const lon = Number(element.attributes.lon);
19
19
  const lat = Number(element.attributes.lat);
20
20
  if (!Number.isFinite(lon) || !Number.isFinite(lat) || element.attributes.lon === undefined)
@@ -22,44 +22,44 @@ function point(element) {
22
22
  const ele = childText(element, 'ele');
23
23
  const position = ele !== undefined && Number.isFinite(Number(ele)) ? [lon, lat, Number(ele)] : [lon, lat];
24
24
  return { position, time: childText(element, 'time') };
25
- }
25
+ };
26
26
  /** The positions of a line of points, and their times when every point has one */
27
- function line(points) {
27
+ const line = (points) => {
28
28
  const read = points.map(point).filter((p) => p !== undefined);
29
- const times = read.map((p) => p.time);
29
+ const times = read.map((p) => p.time).filter((t) => t !== undefined);
30
30
  return {
31
31
  coordinates: read.map((p) => p.position),
32
- times: read.length > 0 && times.every((t) => t !== undefined) ? times : undefined,
32
+ times: read.length > 0 && times.length === read.length ? times : undefined,
33
33
  };
34
- }
34
+ };
35
35
  /**
36
36
  * The waypoints, routes and tracks of a GPX file as GeoJSON features: a waypoint as a point (its `time` a property),
37
37
  * a route as a line, a track as a line or, of several segments, a multi-line; altitudes (`ele`) as the third
38
38
  * coordinate; `name`, `desc`, `cmt`, `type`… as properties, and the times of the points as `times` (one list, or one
39
39
  * per segment) when they all have one
40
40
  */
41
- export function parseGpx(text) {
41
+ export const parseGpx = (text) => {
42
42
  const root = parseXml(text);
43
43
  const features = [];
44
44
  const add = (geometry, props) => features.push({ type: 'Feature', geometry, properties: props });
45
- for (const wpt of children(root, 'wpt')) {
45
+ children(root, 'wpt').forEach((wpt) => {
46
46
  const p = point(wpt);
47
47
  if (!p)
48
- continue;
48
+ return;
49
49
  add({ type: 'Point', coordinates: p.position }, { ...properties(wpt), ...(p.time ? { time: p.time } : {}) });
50
- }
51
- for (const rte of children(root, 'rte')) {
50
+ });
51
+ children(root, 'rte').forEach((rte) => {
52
52
  const { coordinates, times } = line(children(rte, 'rtept'));
53
53
  if (coordinates.length >= 2)
54
54
  add({ type: 'LineString', coordinates }, { ...properties(rte), ...(times ? { times } : {}) });
55
- }
56
- for (const trk of children(root, 'trk')) {
55
+ });
56
+ children(root, 'trk').forEach((trk) => {
57
57
  const segments = children(trk, 'trkseg')
58
58
  .map((s) => line(children(s, 'trkpt')))
59
59
  .filter((s) => s.coordinates.length >= 2);
60
60
  const [first] = segments;
61
61
  if (!first)
62
- continue;
62
+ return;
63
63
  const props = properties(trk);
64
64
  if (segments.length === 1) {
65
65
  add({ type: 'LineString', coordinates: first.coordinates }, { ...props, ...(first.times ? { times: first.times } : {}) });
@@ -68,7 +68,7 @@ export function parseGpx(text) {
68
68
  const times = segments.every((s) => s.times) ? { times: segments.map((s) => s.times) } : {};
69
69
  add({ type: 'MultiLineString', coordinates: segments.map((s) => s.coordinates) }, { ...props, ...times });
70
70
  }
71
- }
71
+ });
72
72
  return { type: 'FeatureCollection', features };
73
- }
73
+ };
74
74
  //# sourceMappingURL=gpx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpx.js","sourceRoot":"","sources":["../../src/data/gpx.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GPX to GeoJSON, for the feature layers: `map.addLines({ data: parseGpx(await (await fetch(url)).text()) })`.\n */\nimport type { Feature, FeatureCollection, Geometry, Position, Properties } from '../layers/features.ts';\nimport { child, children, childText, parseXml, type XmlElement } from './xml.ts';\n\n/** The fields of a waypoint, route or track kept as properties when present */\nconst FIELDS = ['name', 'cmt', 'desc', 'src', 'sym', 'type', 'number'];\n\nconst properties = (element: XmlElement): Properties => {\n const out: Properties = {};\n\n FIELDS.forEach((key) => {\n const value = childText(element, key);\n\n if (value !== undefined) out[key] = key === 'number' ? Number(value) : value;\n });\n\n const link = child(element, 'link')?.attributes.href;\n\n if (link !== undefined) out.link = link;\n\n return out;\n};\n\n/** A point of a GPX file (wpt, rtept, trkpt): its position, its altitude third if any, and its time */\nconst point = (element: XmlElement): { position: Position; time: string | undefined } | undefined => {\n const lon = Number(element.attributes.lon);\n const lat = Number(element.attributes.lat);\n\n if (!Number.isFinite(lon) || !Number.isFinite(lat) || element.attributes.lon === undefined) return undefined;\n\n const ele = childText(element, 'ele');\n const position: Position = ele !== undefined && Number.isFinite(Number(ele)) ? [lon, lat, Number(ele)] : [lon, lat];\n\n return { position, time: childText(element, 'time') };\n};\n\n/** The positions of a line of points, and their times when every point has one */\nconst line = (points: XmlElement[]): { coordinates: Position[]; times: string[] | undefined } => {\n const read = points.map(point).filter((p) => p !== undefined);\n const times = read.map((p) => p.time).filter((t) => t !== undefined);\n\n return {\n coordinates: read.map((p) => p.position),\n times: read.length > 0 && times.length === read.length ? times : undefined,\n };\n};\n\n/**\n * The waypoints, routes and tracks of a GPX file as GeoJSON features: a waypoint as a point (its `time` a property),\n * a route as a line, a track as a line or, of several segments, a multi-line; altitudes (`ele`) as the third\n * coordinate; `name`, `desc`, `cmt`, `type`… as properties, and the times of the points as `times` (one list, or one\n * per segment) when they all have one\n */\nexport const parseGpx = <P = Properties>(text: string): FeatureCollection<P> => {\n const root = parseXml(text);\n const features: Feature<P>[] = [];\n const add = (geometry: Geometry, props: Properties) =>\n features.push({ type: 'Feature', geometry, properties: props as P });\n\n children(root, 'wpt').forEach((wpt) => {\n const p = point(wpt);\n\n if (!p) return;\n add({ type: 'Point', coordinates: p.position }, { ...properties(wpt), ...(p.time ? { time: p.time } : {}) });\n });\n children(root, 'rte').forEach((rte) => {\n const { coordinates, times } = line(children(rte, 'rtept'));\n\n if (coordinates.length >= 2)\n add({ type: 'LineString', coordinates }, { ...properties(rte), ...(times ? { times } : {}) });\n });\n children(root, 'trk').forEach((trk) => {\n const segments = children(trk, 'trkseg')\n .map((s) => line(children(s, 'trkpt')))\n .filter((s) => s.coordinates.length >= 2);\n const [first] = segments;\n\n if (!first) return;\n\n const props = properties(trk);\n\n if (segments.length === 1) {\n add(\n { type: 'LineString', coordinates: first.coordinates },\n { ...props, ...(first.times ? { times: first.times } : {}) },\n );\n } else {\n const times = segments.every((s) => s.times) ? { times: segments.map((s) => s.times) } : {};\n\n add({ type: 'MultiLineString', coordinates: segments.map((s) => s.coordinates) }, { ...props, ...times });\n }\n });\n\n return { type: 'FeatureCollection', features };\n};\n"]}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * KML to GeoJSON, for the feature layers: `map.addLines({ data: parseKml(await (await fetch(url)).text()) })`.
3
3
  */
4
- import type { FeatureCollection, Properties } from './features.ts';
4
+ import type { FeatureCollection, Properties } from '../layers/features.ts';
5
5
  /**
6
6
  * The placemarks of a KML document as GeoJSON features: their points, lines (and gx:Track), polygons (with their
7
7
  * holes) and MultiGeometry (a Multi… of one type, else a GeometryCollection); their `name`, `description`, extended
@@ -9,4 +9,4 @@ import type { FeatureCollection, Properties } from './features.ts';
9
9
  * `StyleMap`) as `stroke`, `stroke-opacity`, `stroke-width`, `fill`, `fill-opacity`, `marker-color`. A placemark
10
10
  * without geometry has a null one
11
11
  */
12
- export declare function parseKml<P = Properties>(text: string): FeatureCollection<P>;
12
+ export declare const parseKml: <P = Properties>(text: string) => FeatureCollection<P>;
@@ -1,18 +1,20 @@
1
1
  import { child, children, childText, descendants, parseXml } from "./xml.js";
2
+ /** Longitude, latitude and maybe more, all finite */
3
+ const isPosition = (values) => values.length >= 2 && values.every(Number.isFinite);
2
4
  /** Positions of a `coordinates` element: `lon,lat[,alt]` tuples separated by spaces */
3
- function positions(element) {
5
+ const positions = (element) => {
4
6
  const out = [];
5
7
  for (const tuple of (element?.text ?? '').trim().split(/\s+/)) {
6
8
  const values = tuple.split(',').map(Number);
7
- if (values.length >= 2 && values.every(Number.isFinite))
9
+ if (isPosition(values))
8
10
  out.push(values);
9
11
  }
10
12
  return out;
11
- }
13
+ };
12
14
  /** The geometries of an element (a Placemark, a MultiGeometry), in order */
13
- function geometries(parent) {
15
+ const geometries = (parent) => {
14
16
  const out = [];
15
- for (const g of parent.children) {
17
+ parent.children.forEach((g) => {
16
18
  if (g.name === 'Point') {
17
19
  const [p] = positions(child(g, 'coordinates'));
18
20
  if (p)
@@ -34,46 +36,46 @@ function geometries(parent) {
34
36
  // gx:Track: its gx:coord, `lon lat alt`
35
37
  const line = children(g, 'coord')
36
38
  .map((c) => c.text.trim().split(/\s+/).map(Number))
37
- .filter((p) => p.length >= 2 && p.every(Number.isFinite));
39
+ .filter(isPosition);
38
40
  if (line.length >= 2)
39
41
  out.push({ type: 'LineString', coordinates: line });
40
42
  }
41
43
  else if (g.name === 'MultiGeometry' || g.name === 'MultiTrack') {
42
44
  out.push(...geometries(g));
43
45
  }
44
- }
46
+ });
45
47
  return out;
46
- }
48
+ };
47
49
  /** One geometry of several: a Multi… of one type, else a collection */
48
- function merge(list) {
50
+ const merge = (list) => {
49
51
  const [first] = list;
50
52
  if (!first)
51
53
  return null;
52
54
  if (list.length === 1)
53
55
  return first;
54
- const same = list.every((g) => g.type === first.type);
55
- if (same && first.type === 'Point') {
56
- return { type: 'MultiPoint', coordinates: list.map((g) => g.coordinates) };
57
- }
58
- if (same && first.type === 'LineString') {
59
- return { type: 'MultiLineString', coordinates: list.map((g) => g.coordinates) };
60
- }
61
- if (same && first.type === 'Polygon') {
62
- return { type: 'MultiPolygon', coordinates: list.map((g) => g.coordinates) };
56
+ const points = list.filter((g) => g.type === 'Point');
57
+ const lines = list.filter((g) => g.type === 'LineString');
58
+ const polygons = list.filter((g) => g.type === 'Polygon');
59
+ if (points.length === list.length)
60
+ return { type: 'MultiPoint', coordinates: points.map((g) => g.coordinates) };
61
+ if (lines.length === list.length)
62
+ return { type: 'MultiLineString', coordinates: lines.map((g) => g.coordinates) };
63
+ if (polygons.length === list.length) {
64
+ return { type: 'MultiPolygon', coordinates: polygons.map((g) => g.coordinates) };
63
65
  }
64
66
  return { type: 'GeometryCollection', geometries: list };
65
- }
67
+ };
66
68
  /** A KML color (`aabbggrr`, hexadecimal) as a CSS color and an opacity */
67
- function color(element) {
69
+ const color = (element) => {
68
70
  const value = childText(element, 'color')?.replace(/^#/, '');
69
71
  if (!value || !/^[\da-f]{8}$/i.test(value))
70
72
  return undefined;
71
- const [a, b, g, r] = [0, 2, 4, 6].map((i) => value.slice(i, i + 2));
73
+ const [a = '', b, g, r] = [0, 2, 4, 6].map((i) => value.slice(i, i + 2));
72
74
  return [`#${r}${g}${b}`.toLowerCase(), Math.round((Number.parseInt(a, 16) / 255) * 1000) / 1000];
73
- }
75
+ };
74
76
  /** The properties of a style (simplestyle's names, as togeojson): stroke, stroke-opacity, stroke-width, fill,
75
77
  * fill-opacity, marker-color */
76
- function styleProperties(style) {
78
+ const styleProperties = (style) => {
77
79
  const out = {};
78
80
  if (!style)
79
81
  return out;
@@ -96,7 +98,7 @@ function styleProperties(style) {
96
98
  if (icon)
97
99
  out['marker-color'] = icon[0];
98
100
  return out;
99
- }
101
+ };
100
102
  /**
101
103
  * The placemarks of a KML document as GeoJSON features: their points, lines (and gx:Track), polygons (with their
102
104
  * holes) and MultiGeometry (a Multi… of one type, else a GeometryCollection); their `name`, `description`, extended
@@ -104,19 +106,20 @@ function styleProperties(style) {
104
106
  * `StyleMap`) as `stroke`, `stroke-opacity`, `stroke-width`, `fill`, `fill-opacity`, `marker-color`. A placemark
105
107
  * without geometry has a null one
106
108
  */
107
- export function parseKml(text) {
109
+ export const parseKml = (text) => {
108
110
  const root = parseXml(text);
109
111
  const styles = new Map();
110
- for (const s of descendants(root, 'Style'))
112
+ descendants(root, 'Style').forEach((s) => {
111
113
  if (s.attributes.id)
112
114
  styles.set(s.attributes.id, s);
115
+ });
113
116
  const maps = new Map();
114
- for (const m of descendants(root, 'StyleMap')) {
117
+ descendants(root, 'StyleMap').forEach((m) => {
115
118
  const normal = children(m, 'Pair').find((p) => childText(p, 'key') === 'normal');
116
119
  const url = childText(normal, 'styleUrl');
117
120
  if (m.attributes.id && url)
118
121
  maps.set(m.attributes.id, url);
119
- }
122
+ });
120
123
  /** The style of a `styleUrl` in this document (`#id`, through a StyleMap) */
121
124
  const shared = (url, depth = 0) => {
122
125
  const id = url?.slice(url.indexOf('#') + 1);
@@ -127,25 +130,25 @@ export function parseKml(text) {
127
130
  const features = descendants(root, 'Placemark').map((placemark) => {
128
131
  const properties = { ...styleProperties(shared(childText(placemark, 'styleUrl'))) };
129
132
  Object.assign(properties, styleProperties(child(placemark, 'Style')));
130
- for (const key of ['name', 'description', 'address', 'styleUrl']) {
133
+ ['name', 'description', 'address', 'styleUrl'].forEach((key) => {
131
134
  const value = childText(placemark, key);
132
135
  if (value !== undefined)
133
136
  properties[key] = value;
134
- }
137
+ });
135
138
  const time = childText(child(placemark, 'TimeStamp'), 'when');
136
139
  if (time !== undefined)
137
140
  properties.time = time;
138
141
  const extended = child(placemark, 'ExtendedData');
139
- for (const data of children(extended, 'Data')) {
142
+ children(extended, 'Data').forEach((data) => {
140
143
  if (data.attributes.name)
141
144
  properties[data.attributes.name] = childText(data, 'value') ?? '';
142
- }
143
- for (const schema of children(extended, 'SchemaData')) {
144
- for (const data of children(schema, 'SimpleData')) {
145
- if (data.attributes.name)
146
- properties[data.attributes.name] = data.text.trim();
147
- }
148
- }
145
+ });
146
+ children(extended, 'SchemaData')
147
+ .flatMap((schema) => children(schema, 'SimpleData'))
148
+ .forEach((data) => {
149
+ if (data.attributes.name)
150
+ properties[data.attributes.name] = data.text.trim();
151
+ });
149
152
  const id = placemark.attributes.id;
150
153
  return {
151
154
  type: 'Feature',
@@ -155,5 +158,5 @@ export function parseKml(text) {
155
158
  };
156
159
  });
157
160
  return { type: 'FeatureCollection', features };
158
- }
161
+ };
159
162
  //# sourceMappingURL=kml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kml.js","sourceRoot":"","sources":["../../src/data/kml.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * KML to GeoJSON, for the feature layers: `map.addLines({ data: parseKml(await (await fetch(url)).text()) })`.\n */\nimport type { Feature, FeatureCollection, Geometry, Position, Properties } from '../layers/features.ts';\nimport { child, children, childText, descendants, parseXml, type XmlElement } from './xml.ts';\n\n/** Longitude, latitude and maybe more, all finite */\nconst isPosition = (values: number[]): values is Position => values.length >= 2 && values.every(Number.isFinite);\n\n/** Positions of a `coordinates` element: `lon,lat[,alt]` tuples separated by spaces */\nconst positions = (element: XmlElement | undefined): Position[] => {\n const out: Position[] = [];\n\n for (const tuple of (element?.text ?? '').trim().split(/\\s+/)) {\n const values = tuple.split(',').map(Number);\n\n if (isPosition(values)) out.push(values);\n }\n\n return out;\n};\n\n/** The geometries of an element (a Placemark, a MultiGeometry), in order */\nconst geometries = (parent: XmlElement): Geometry[] => {\n const out: Geometry[] = [];\n\n parent.children.forEach((g) => {\n if (g.name === 'Point') {\n const [p] = positions(child(g, 'coordinates'));\n\n if (p) out.push({ type: 'Point', coordinates: p });\n } else if (g.name === 'LineString' || g.name === 'LinearRing') {\n const line = positions(child(g, 'coordinates'));\n\n if (line.length >= 2) out.push({ type: 'LineString', coordinates: line });\n } else if (g.name === 'Polygon') {\n const ring = (b: XmlElement) => positions(child(child(b, 'LinearRing'), 'coordinates'));\n const outer = child(g, 'outerBoundaryIs');\n const rings = [...(outer ? [ring(outer)] : []), ...children(g, 'innerBoundaryIs').map(ring)];\n\n if ((rings[0]?.length ?? 0) >= 4) out.push({ type: 'Polygon', coordinates: rings.filter((r) => r.length >= 4) });\n } else if (g.name === 'Track') {\n // gx:Track: its gx:coord, `lon lat alt`\n const line = children(g, 'coord')\n .map((c) => c.text.trim().split(/\\s+/).map(Number))\n .filter(isPosition);\n\n if (line.length >= 2) out.push({ type: 'LineString', coordinates: line });\n } else if (g.name === 'MultiGeometry' || g.name === 'MultiTrack') {\n out.push(...geometries(g));\n }\n });\n\n return out;\n};\n\n/** One geometry of several: a Multi… of one type, else a collection */\nconst merge = (list: Geometry[]): Geometry | null => {\n const [first] = list;\n\n if (!first) return null;\n if (list.length === 1) return first;\n\n const points = list.filter((g) => g.type === 'Point');\n const lines = list.filter((g) => g.type === 'LineString');\n const polygons = list.filter((g) => g.type === 'Polygon');\n\n if (points.length === list.length) return { type: 'MultiPoint', coordinates: points.map((g) => g.coordinates) };\n if (lines.length === list.length) return { type: 'MultiLineString', coordinates: lines.map((g) => g.coordinates) };\n if (polygons.length === list.length) {\n return { type: 'MultiPolygon', coordinates: polygons.map((g) => g.coordinates) };\n }\n\n return { type: 'GeometryCollection', geometries: list };\n};\n\n/** A KML color (`aabbggrr`, hexadecimal) as a CSS color and an opacity */\nconst color = (element: XmlElement | undefined): [css: string, opacity: number] | undefined => {\n const value = childText(element, 'color')?.replace(/^#/, '');\n\n if (!value || !/^[\\da-f]{8}$/i.test(value)) return undefined;\n\n const [a = '', b, g, r] = [0, 2, 4, 6].map((i) => value.slice(i, i + 2));\n\n return [`#${r}${g}${b}`.toLowerCase(), Math.round((Number.parseInt(a, 16) / 255) * 1000) / 1000];\n};\n\n/** The properties of a style (simplestyle's names, as togeojson): stroke, stroke-opacity, stroke-width, fill,\n * fill-opacity, marker-color */\nconst styleProperties = (style: XmlElement | undefined): Properties => {\n const out: Properties = {};\n\n if (!style) return out;\n\n const line = child(style, 'LineStyle');\n const stroke = color(line);\n\n if (stroke) [out.stroke, out['stroke-opacity']] = stroke;\n\n const width = Number(childText(line, 'width'));\n\n if (childText(line, 'width') !== undefined && Number.isFinite(width)) out['stroke-width'] = width;\n\n const poly = child(style, 'PolyStyle');\n const fill = color(poly);\n\n if (fill) [out.fill, out['fill-opacity']] = fill;\n if (childText(poly, 'fill') === '0') out['fill-opacity'] = 0;\n if (childText(poly, 'outline') === '0') out['stroke-opacity'] = 0;\n\n const icon = color(child(style, 'IconStyle'));\n\n if (icon) out['marker-color'] = icon[0];\n\n return out;\n};\n\n/**\n * The placemarks of a KML document as GeoJSON features: their points, lines (and gx:Track), polygons (with their\n * holes) and MultiGeometry (a Multi… of one type, else a GeometryCollection); their `name`, `description`, extended\n * data (`Data`, `SimpleData`) as properties, and the colors of their style (inline, or shared through `styleUrl` and\n * `StyleMap`) as `stroke`, `stroke-opacity`, `stroke-width`, `fill`, `fill-opacity`, `marker-color`. A placemark\n * without geometry has a null one\n */\nexport const parseKml = <P = Properties>(text: string): FeatureCollection<P> => {\n const root = parseXml(text);\n const styles = new Map<string, XmlElement>();\n\n descendants(root, 'Style').forEach((s) => {\n if (s.attributes.id) styles.set(s.attributes.id, s);\n });\n\n const maps = new Map<string, string>();\n\n descendants(root, 'StyleMap').forEach((m) => {\n const normal = children(m, 'Pair').find((p) => childText(p, 'key') === 'normal');\n const url = childText(normal, 'styleUrl');\n\n if (m.attributes.id && url) maps.set(m.attributes.id, url);\n });\n\n /** The style of a `styleUrl` in this document (`#id`, through a StyleMap) */\n const shared = (url: string | undefined, depth = 0): XmlElement | undefined => {\n const id = url?.slice(url.indexOf('#') + 1);\n\n if (id === undefined || depth > 4) return undefined;\n\n return styles.get(id) ?? shared(maps.get(id), depth + 1);\n };\n const features = descendants(root, 'Placemark').map((placemark): Feature<P> => {\n const properties: Properties = { ...styleProperties(shared(childText(placemark, 'styleUrl'))) };\n\n Object.assign(properties, styleProperties(child(placemark, 'Style')));\n ['name', 'description', 'address', 'styleUrl'].forEach((key) => {\n const value = childText(placemark, key);\n\n if (value !== undefined) properties[key] = value;\n });\n\n const time = childText(child(placemark, 'TimeStamp'), 'when');\n\n if (time !== undefined) properties.time = time;\n\n const extended = child(placemark, 'ExtendedData');\n\n children(extended, 'Data').forEach((data) => {\n if (data.attributes.name) properties[data.attributes.name] = childText(data, 'value') ?? '';\n });\n children(extended, 'SchemaData')\n .flatMap((schema) => children(schema, 'SimpleData'))\n .forEach((data) => {\n if (data.attributes.name) properties[data.attributes.name] = data.text.trim();\n });\n\n const id = placemark.attributes.id;\n\n return {\n type: 'Feature',\n geometry: merge(geometries(placemark)),\n properties: properties as P,\n ...(id === undefined ? {} : { id }),\n };\n });\n\n return { type: 'FeatureCollection', features };\n};\n"]}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * TopoJSON to GeoJSON, for the feature layers: `map.addFills({ data: parseTopoJson(topology, 'counties') })`.
3
3
  */
4
- import type { FeatureCollection, Properties } from './features.ts';
4
+ import type { FeatureCollection, Properties } from '../layers/features.ts';
5
5
  /** A TopoJSON geometry object (arcs by index, `~i` for arc i reversed; positions quantized with a transform) */
6
6
  export interface TopoGeometry {
7
7
  type: 'Point' | 'MultiPoint' | 'LineString' | 'MultiLineString' | 'Polygon' | 'MultiPolygon' | 'GeometryCollection' | null;
@@ -26,4 +26,4 @@ export interface Topology {
26
26
  * The features of object `name` of a TopoJSON topology (default its first object): a GeometryCollection gives one
27
27
  * feature per geometry, another geometry one feature; arcs are stitched and dequantized, ids and properties kept
28
28
  */
29
- export declare function parseTopoJson<P = Properties>(topology: Topology, name?: string): FeatureCollection<P>;
29
+ export declare const parseTopoJson: <P = Properties>(topology: Topology, name?: string) => FeatureCollection<P>;
@@ -1,8 +1,12 @@
1
+ import { isNumbers } from "../util/guards.js";
2
+ /** The members of a geometry, checked: the topology is JSON from elsewhere */
3
+ const isLists = (value) => Array.isArray(value) && value.every(isNumbers);
4
+ const isListsOfLists = (value) => Array.isArray(value) && value.every(isLists);
1
5
  /**
2
6
  * The features of object `name` of a TopoJSON topology (default its first object): a GeometryCollection gives one
3
7
  * feature per geometry, another geometry one feature; arcs are stitched and dequantized, ids and properties kept
4
8
  */
5
- export function parseTopoJson(topology, name) {
9
+ export const parseTopoJson = (topology, name) => {
6
10
  const object = name === undefined ? Object.values(topology.objects)[0] : topology.objects[name];
7
11
  if (!object)
8
12
  throw new Error(`isard: no TopoJSON object ${name ?? ''}`);
@@ -24,27 +28,28 @@ export function parseTopoJson(topology, name) {
24
28
  /** A line from arcs, each after the first without its first point (the last of the one before) */
25
29
  const stitch = (indices) => {
26
30
  const out = [];
27
- for (const i of indices) {
31
+ indices.forEach((i) => {
28
32
  const arc = arcs[i < 0 ? ~i : i] ?? [];
29
33
  const points = i < 0 ? [...arc].reverse() : arc;
30
34
  out.push(...(out.length > 0 ? points.slice(1) : points));
31
- }
35
+ });
32
36
  return out;
33
37
  };
34
38
  const geometry = (g) => {
39
+ const { coordinates, arcs } = g;
35
40
  switch (g.type) {
36
41
  case 'Point':
37
- return { type: 'Point', coordinates: position(g.coordinates) };
42
+ return isNumbers(coordinates) ? { type: 'Point', coordinates: position(coordinates) } : null;
38
43
  case 'MultiPoint':
39
- return { type: 'MultiPoint', coordinates: g.coordinates.map(position) };
44
+ return isLists(coordinates) ? { type: 'MultiPoint', coordinates: coordinates.map(position) } : null;
40
45
  case 'LineString':
41
- return { type: 'LineString', coordinates: stitch(g.arcs) };
46
+ return isNumbers(arcs) ? { type: 'LineString', coordinates: stitch(arcs) } : null;
42
47
  case 'MultiLineString':
43
- return { type: 'MultiLineString', coordinates: g.arcs.map(stitch) };
48
+ return isLists(arcs) ? { type: 'MultiLineString', coordinates: arcs.map(stitch) } : null;
44
49
  case 'Polygon':
45
- return { type: 'Polygon', coordinates: g.arcs.map(stitch) };
50
+ return isLists(arcs) ? { type: 'Polygon', coordinates: arcs.map(stitch) } : null;
46
51
  case 'MultiPolygon':
47
- return { type: 'MultiPolygon', coordinates: g.arcs.map((p) => p.map(stitch)) };
52
+ return isListsOfLists(arcs) ? { type: 'MultiPolygon', coordinates: arcs.map((p) => p.map(stitch)) } : null;
48
53
  case 'GeometryCollection':
49
54
  return {
50
55
  type: 'GeometryCollection',
@@ -62,5 +67,5 @@ export function parseTopoJson(topology, name) {
62
67
  });
63
68
  const features = object.type === 'GeometryCollection' ? (object.geometries ?? []).map(feature) : [feature(object)];
64
69
  return { type: 'FeatureCollection', features };
65
- }
70
+ };
66
71
  //# sourceMappingURL=topojson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topojson.js","sourceRoot":"","sources":["../../src/data/topojson.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TopoJSON to GeoJSON, for the feature layers: `map.addFills({ data: parseTopoJson(topology, 'counties') })`.\n */\nimport type { Feature, FeatureCollection, Geometry, Position, Properties } from '../layers/features.ts';\nimport { isNumbers } from '../util/guards.ts';\n\n/** A TopoJSON geometry object (arcs by index, `~i` for arc i reversed; positions quantized with a transform) */\nexport interface TopoGeometry {\n type:\n | 'Point'\n | 'MultiPoint'\n | 'LineString'\n | 'MultiLineString'\n | 'Polygon'\n | 'MultiPolygon'\n | 'GeometryCollection'\n | null;\n id?: string | number;\n properties?: Properties;\n coordinates?: number[] | number[][];\n arcs?: number[] | number[][] | number[][][];\n geometries?: TopoGeometry[];\n}\n\n/** A TopoJSON topology */\nexport interface Topology {\n type: 'Topology';\n /** Quantized positions: x × scale + translate (arcs delta-encoded) */\n transform?: { scale: [number, number]; translate: [number, number] };\n arcs: number[][][];\n objects: Record<string, TopoGeometry>;\n}\n\n/** The members of a geometry, checked: the topology is JSON from elsewhere */\nconst isLists = (value: unknown): value is number[][] => Array.isArray(value) && value.every(isNumbers);\nconst isListsOfLists = (value: unknown): value is number[][][] => Array.isArray(value) && value.every(isLists);\n\n/**\n * The features of object `name` of a TopoJSON topology (default its first object): a GeometryCollection gives one\n * feature per geometry, another geometry one feature; arcs are stitched and dequantized, ids and properties kept\n */\nexport const parseTopoJson = <P = Properties>(topology: Topology, name?: string): FeatureCollection<P> => {\n const object = name === undefined ? Object.values(topology.objects)[0] : topology.objects[name];\n\n if (!object) throw new Error(`isard: no TopoJSON object ${name ?? ''}`);\n\n const { scale = [1, 1], translate = [0, 0] } = topology.transform ?? {};\n const quantized = topology.transform !== undefined;\n const at = (p: number[]): Position => [p[0] ?? 0, p[1] ?? 0, ...p.slice(2)];\n // The arcs decoded once\n const arcs = topology.arcs.map((arc) => {\n let [x, y] = [0, 0];\n\n return arc.map((p): Position => {\n if (!quantized) return at(p);\n x += p[0] ?? 0;\n y += p[1] ?? 0;\n\n return [x * scale[0] + translate[0], y * scale[1] + translate[1], ...p.slice(2)];\n });\n });\n const position = (p: number[]): Position =>\n quantized ? [(p[0] ?? 0) * scale[0] + translate[0], (p[1] ?? 0) * scale[1] + translate[1], ...p.slice(2)] : at(p);\n /** A line from arcs, each after the first without its first point (the last of the one before) */\n const stitch = (indices: number[]): Position[] => {\n const out: Position[] = [];\n\n indices.forEach((i) => {\n const arc = arcs[i < 0 ? ~i : i] ?? [];\n const points = i < 0 ? [...arc].reverse() : arc;\n\n out.push(...(out.length > 0 ? points.slice(1) : points));\n });\n\n return out;\n };\n const geometry = (g: TopoGeometry): Geometry | null => {\n const { coordinates, arcs } = g;\n\n switch (g.type) {\n case 'Point':\n return isNumbers(coordinates) ? { type: 'Point', coordinates: position(coordinates) } : null;\n case 'MultiPoint':\n return isLists(coordinates) ? { type: 'MultiPoint', coordinates: coordinates.map(position) } : null;\n case 'LineString':\n return isNumbers(arcs) ? { type: 'LineString', coordinates: stitch(arcs) } : null;\n case 'MultiLineString':\n return isLists(arcs) ? { type: 'MultiLineString', coordinates: arcs.map(stitch) } : null;\n case 'Polygon':\n return isLists(arcs) ? { type: 'Polygon', coordinates: arcs.map(stitch) } : null;\n case 'MultiPolygon':\n return isListsOfLists(arcs) ? { type: 'MultiPolygon', coordinates: arcs.map((p) => p.map(stitch)) } : null;\n case 'GeometryCollection':\n return {\n type: 'GeometryCollection',\n geometries: (g.geometries ?? []).map(geometry).filter((c) => c !== null),\n };\n default:\n return null;\n }\n };\n const feature = (g: TopoGeometry): Feature<P> => ({\n type: 'Feature',\n geometry: geometry(g),\n properties: (g.properties ?? {}) as P,\n ...(g.id === undefined ? {} : { id: g.id }),\n });\n const features = object.type === 'GeometryCollection' ? (object.geometries ?? []).map(feature) : [feature(object)];\n\n return { type: 'FeatureCollection', features };\n};\n"]}
@@ -15,12 +15,12 @@ export interface XmlElement {
15
15
  text: string;
16
16
  }
17
17
  /** The document's root element; throws if there is none */
18
- export declare function parseXml(source: string): XmlElement;
18
+ export declare const parseXml: (source: string) => XmlElement;
19
19
  /** The first child element of a name */
20
- export declare function child(element: XmlElement | undefined, name: string): XmlElement | undefined;
20
+ export declare const child: (element: XmlElement | undefined, name: string) => XmlElement | undefined;
21
21
  /** The child elements of a name */
22
- export declare function children(element: XmlElement | undefined, name: string): XmlElement[];
22
+ export declare const children: (element: XmlElement | undefined, name: string) => XmlElement[];
23
23
  /** The trimmed text of the first child of a name; undefined without one */
24
- export declare function childText(element: XmlElement | undefined, name: string): string | undefined;
24
+ export declare const childText: (element: XmlElement | undefined, name: string) => string | undefined;
25
25
  /** Every element of a name under an element, in document order (not inside a match) */
26
- export declare function descendants(element: XmlElement, name: string, out?: XmlElement[]): XmlElement[];
26
+ export declare const descendants: (element: XmlElement, name: string, out?: XmlElement[]) => XmlElement[];
@@ -7,7 +7,7 @@
7
7
  */
8
8
  const ENTITIES = { lt: '<', gt: '>', amp: '&', quot: '"', apos: "'" };
9
9
  /** Text with its entities decoded (unknown ones kept as they are) */
10
- function decode(text) {
10
+ const decode = (text) => {
11
11
  if (!text.includes('&'))
12
12
  return text;
13
13
  return text.replace(/&(#x[\da-f]+|#\d+|\w+);/gi, (whole, entity) => {
@@ -17,15 +17,15 @@ function decode(text) {
17
17
  }
18
18
  return ENTITIES[entity] ?? whole;
19
19
  });
20
- }
20
+ };
21
21
  const local = (name) => name.slice(name.indexOf(':') + 1);
22
22
  /** A start tag at the reader's position: its name, its attributes (quoted values may hold '>'), whether it closes */
23
23
  const START = /<([^\s/>]+)((?:\s+[^\s=/>]+\s*=\s*(?:"[^"]*"|'[^']*'))*)\s*(\/?)>/y;
24
24
  /** The document's root element; throws if there is none */
25
- export function parseXml(source) {
25
+ export const parseXml = (source) => {
26
26
  const root = { name: '#document', attributes: {}, children: [], text: '' };
27
27
  const stack = [root];
28
- const top = () => stack[stack.length - 1];
28
+ const top = () => stack.at(-1) ?? root;
29
29
  let i = 0;
30
30
  while (i < source.length) {
31
31
  const lt = source.indexOf('<', i);
@@ -69,12 +69,13 @@ export function parseXml(source) {
69
69
  i = lt + 1;
70
70
  continue;
71
71
  }
72
- const element = { name: local(tag[1]), attributes: {}, children: [], text: '' };
73
- for (const [, key, double, single] of tag[2].matchAll(/([^\s=]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g)) {
72
+ const [, name = '', attributes = '', closes] = tag;
73
+ const element = { name: local(name), attributes: {}, children: [], text: '' };
74
+ for (const [, key = '', double, single] of attributes.matchAll(/([^\s=]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g)) {
74
75
  element.attributes[local(key)] = decode(double ?? single ?? '');
75
76
  }
76
77
  top().children.push(element);
77
- if (!tag[3])
78
+ if (!closes)
78
79
  stack.push(element);
79
80
  i = START.lastIndex;
80
81
  }
@@ -83,27 +84,27 @@ export function parseXml(source) {
83
84
  if (!first)
84
85
  throw new Error('isard: no XML element');
85
86
  return first;
86
- }
87
+ };
87
88
  /** The first child element of a name */
88
- export function child(element, name) {
89
+ export const child = (element, name) => {
89
90
  return element?.children.find((c) => c.name === name);
90
- }
91
+ };
91
92
  /** The child elements of a name */
92
- export function children(element, name) {
93
+ export const children = (element, name) => {
93
94
  return element?.children.filter((c) => c.name === name) ?? [];
94
- }
95
+ };
95
96
  /** The trimmed text of the first child of a name; undefined without one */
96
- export function childText(element, name) {
97
+ export const childText = (element, name) => {
97
98
  return child(element, name)?.text.trim();
98
- }
99
+ };
99
100
  /** Every element of a name under an element, in document order (not inside a match) */
100
- export function descendants(element, name, out = []) {
101
- for (const c of element.children) {
101
+ export const descendants = (element, name, out = []) => {
102
+ element.children.forEach((c) => {
102
103
  if (c.name === name)
103
104
  out.push(c);
104
105
  else
105
106
  descendants(c, name, out);
106
- }
107
+ });
107
108
  return out;
108
- }
109
+ };
109
110
  //# sourceMappingURL=xml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xml.js","sourceRoot":"","sources":["../../src/data/xml.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A small XML reader for the formats read here (KML, GPX, WMTS capabilities): elements, their attributes and text,\n * CDATA, comments, entities. The same in the page, in workers and in tests (which have no `DOMParser`), and lenient:\n * a closing tag without its opening one is ignored, an unclosed element ends with its parent. Names are kept without\n * their namespace prefix (`ows:Identifier` is `Identifier`): the formats read here never mix two meanings of a name.\n * No DTD is read (no external entity, no entity expansion).\n */\n\nexport interface XmlElement {\n /** Local name, without its prefix */\n name: string;\n /** Attributes by local name */\n attributes: Record<string, string>;\n children: XmlElement[];\n /** Text directly inside, CDATA included, entities decoded */\n text: string;\n}\n\nconst ENTITIES: Record<string, string> = { lt: '<', gt: '>', amp: '&', quot: '\"', apos: \"'\" };\n\n/** Text with its entities decoded (unknown ones kept as they are) */\nconst decode = (text: string): string => {\n if (!text.includes('&')) return text;\n\n return text.replace(/&(#x[\\da-f]+|#\\d+|\\w+);/gi, (whole, entity: string) => {\n if (entity[0] === '#') {\n const code =\n entity[1] === 'x' || entity[1] === 'X' ? Number.parseInt(entity.slice(2), 16) : Number(entity.slice(1));\n\n return Number.isFinite(code) && code >= 0 && code <= 0x10ffff ? String.fromCodePoint(code) : whole;\n }\n\n return ENTITIES[entity] ?? whole;\n });\n};\n\nconst local = (name: string) => name.slice(name.indexOf(':') + 1);\n\n/** A start tag at the reader's position: its name, its attributes (quoted values may hold '>'), whether it closes */\nconst START = /<([^\\s/>]+)((?:\\s+[^\\s=/>]+\\s*=\\s*(?:\"[^\"]*\"|'[^']*'))*)\\s*(\\/?)>/y;\n\n/** The document's root element; throws if there is none */\nexport const parseXml = (source: string): XmlElement => {\n const root: XmlElement = { name: '#document', attributes: {}, children: [], text: '' };\n const stack = [root];\n const top = () => stack.at(-1) ?? root;\n let i = 0;\n\n while (i < source.length) {\n const lt = source.indexOf('<', i);\n const end = lt < 0 ? source.length : lt;\n\n if (end > i) top().text += decode(source.slice(i, end));\n if (lt < 0) break;\n if (source.startsWith('<!--', lt)) {\n const close = source.indexOf('-->', lt + 4);\n\n i = close < 0 ? source.length : close + 3;\n } else if (source.startsWith('<![CDATA[', lt)) {\n const close = source.indexOf(']]>', lt + 9);\n\n top().text += source.slice(lt + 9, close < 0 ? source.length : close);\n i = close < 0 ? source.length : close + 3;\n } else if (source[lt + 1] === '?' || source[lt + 1] === '!') {\n // A declaration, a processing instruction, a DOCTYPE (its internal subset skipped whole)\n const bracket = source.indexOf('[', lt);\n const gt = source.indexOf('>', lt);\n const subset = source[lt + 1] === '!' && bracket >= 0 && bracket < gt ? source.indexOf(']', bracket) : lt;\n const close = source.indexOf('>', subset);\n\n i = close < 0 ? source.length : close + 1;\n } else if (source[lt + 1] === '/') {\n const gt = source.indexOf('>', lt);\n const name = local(source.slice(lt + 2, gt < 0 ? source.length : gt).trim());\n let at = stack.length - 1;\n\n while (at > 0 && stack[at]?.name !== name) at -= 1;\n if (at > 0) stack.length = at;\n i = gt < 0 ? source.length : gt + 1;\n } else {\n START.lastIndex = lt;\n\n const tag = START.exec(source);\n\n if (!tag) {\n top().text += '<';\n i = lt + 1;\n continue;\n }\n\n const [, name = '', attributes = '', closes] = tag;\n const element: XmlElement = { name: local(name), attributes: {}, children: [], text: '' };\n\n for (const [, key = '', double, single] of attributes.matchAll(/([^\\s=]+)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')/g)) {\n element.attributes[local(key)] = decode(double ?? single ?? '');\n }\n top().children.push(element);\n if (!closes) stack.push(element);\n i = START.lastIndex;\n }\n }\n\n const first = root.children[0];\n\n if (!first) throw new Error('isard: no XML element');\n\n return first;\n};\n\n/** The first child element of a name */\nexport const child = (element: XmlElement | undefined, name: string): XmlElement | undefined => {\n return element?.children.find((c) => c.name === name);\n};\n\n/** The child elements of a name */\nexport const children = (element: XmlElement | undefined, name: string): XmlElement[] => {\n return element?.children.filter((c) => c.name === name) ?? [];\n};\n\n/** The trimmed text of the first child of a name; undefined without one */\nexport const childText = (element: XmlElement | undefined, name: string): string | undefined => {\n return child(element, name)?.text.trim();\n};\n\n/** Every element of a name under an element, in document order (not inside a match) */\nexport const descendants = (element: XmlElement, name: string, out: XmlElement[] = []): XmlElement[] => {\n element.children.forEach((c) => {\n if (c.name === name) out.push(c);\n else descendants(c, name, out);\n });\n\n return out;\n};\n"]}