@tileflow/dev 0.1.0-alpha.16 → 0.1.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -1
- package/THIRD_PARTY_NOTICES.md +11 -0
- package/assets/streets-poi/cafe.svg +10 -0
- package/assets/streets-poi/hospital.svg +10 -0
- package/assets/streets-poi/hotel.svg +10 -0
- package/assets/streets-poi/museum.svg +10 -0
- package/assets/streets-poi/restaurant.svg +10 -0
- package/assets/streets-poi/school.svg +10 -0
- package/assets/streets-poi/services.svg +10 -0
- package/assets/streets-poi/shopping.svg +10 -0
- package/assets/streets-poi/train.svg +10 -0
- package/dist/index.d.ts +22 -7
- package/dist/index.js +205 -36
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -45,6 +45,24 @@ edits retain the last good snapshot, and caller-supplied output directories can
|
|
|
45
45
|
feedback loops. `tileflow dev`, `capture --watch`, and framework adapters use this shared status
|
|
46
46
|
vocabulary.
|
|
47
47
|
|
|
48
|
+
Custom preview servers can select the same map or standalone scene semantics as the CLI:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import {createTileflowDevRequestHandler} from '@tileflow/dev';
|
|
52
|
+
|
|
53
|
+
const fetch = createTileflowDevRequestHandler({
|
|
54
|
+
session,
|
|
55
|
+
scene: 'madrid-mobile',
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`map` and `scene` are mutually exclusive. Map preview uses the configured `view`; scene preview
|
|
60
|
+
uses its committed camera and CSS viewport. `resolveTileflowPreview()` exposes the validated
|
|
61
|
+
selection for custom integrations. Application-target scenes remain the responsibility of the
|
|
62
|
+
application's development server. The built-in preview records longitude, latitude, zoom, bearing,
|
|
63
|
+
and pitch in the current URL after the camera moves, so browser refreshes and config-triggered
|
|
64
|
+
reloads return to the same view. Removing those query parameters restores the configured camera.
|
|
65
|
+
|
|
48
66
|
If a map uses `icons: './icons/brand'`, build artifacts include the generated
|
|
49
67
|
MapLibre `sprite.json`, `sprite.png`, `sprite@2x.json`, and `sprite@2x.png`
|
|
50
68
|
assets alongside the styles.
|
|
@@ -86,8 +104,14 @@ const result = await compileTileflowIconPackages(project, {
|
|
|
86
104
|
});
|
|
87
105
|
```
|
|
88
106
|
|
|
107
|
+
When a Streets map does not select a local or external icon set, the pipeline compiles the built-in
|
|
108
|
+
`tileflow-streets` POI catalog and merges any mapping-only overrides on top of its semantic mapping.
|
|
109
|
+
`modules.poi.icons: false`, a disabled POI module, or the `none` POI preset suppresses that implicit
|
|
110
|
+
package. An explicit local source or hosted sprite always replaces it.
|
|
111
|
+
|
|
89
112
|
The hosted target enforces repository containment, portable icon IDs, safe SVG
|
|
90
|
-
references, deterministic ordering, and the public package limits.
|
|
113
|
+
references, deterministic ordering, and the public package limits. The package-owned Streets
|
|
114
|
+
catalog is trusted input and is the only source exempt from project-root containment. It returns
|
|
91
115
|
deduplicated generated files plus a canonical manifest/content hash. Upload only
|
|
92
116
|
those generated files: source icons and absolute paths remain local. External
|
|
93
117
|
sprite URLs are preserved as references and are not downloaded.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
## Google Places icons
|
|
4
|
+
|
|
5
|
+
The glyph artwork in `assets/streets-poi` is adapted from Google Places icons published in the
|
|
6
|
+
[Google Places API documentation](https://developers.google.com/maps/documentation/places/web-service/icons).
|
|
7
|
+
Copyright Google LLC. The documentation content is licensed under the
|
|
8
|
+
[Creative Commons Attribution 4.0 License](https://creativecommons.org/licenses/by/4.0/).
|
|
9
|
+
|
|
10
|
+
Tileflow modifies the source artwork by resizing and recoloring the glyphs, then composing them
|
|
11
|
+
inside circular category markers with a white rim and shadow.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
|
2
|
+
<title>Cafe</title>
|
|
3
|
+
<circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
|
|
4
|
+
<circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
|
|
5
|
+
<circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
|
|
6
|
+
<circle cx="12" cy="11" r="8.25" fill="#FF9E67"/>
|
|
7
|
+
<svg x="6.75" y="7" width="10.5" height="7.875" viewBox="0 0 12 9" fill="#FFFFFF">
|
|
8
|
+
<path transform="translate(-5 -7)" fill-rule="evenodd" d="M13.4656593,7 L15.1589761,7 C15.6924964,7 16.125,7.43246448 16.125,7.96611494 L16.125,9.90201693 C16.125,10.4355875 15.6906762,10.8681319 15.1589761,10.8681319 L13.7074176,10.8681319 L11.8942308,13.043956 L8.0260989,13.043956 L6.09203297,10.8681319 L5.125,7 L13.4656593,7 Z M5.48763736,14.2527473 L15.157967,14.2527473 L15.157967,15.7032967 L5.48763736,15.7032967 Z M13.7074176,7.96703297 L15.157967,7.96703297 L15.157967,9.9010989 L13.7074176,9.9010989 Z"/>
|
|
9
|
+
</svg>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
|
2
|
+
<title>Hospital</title>
|
|
3
|
+
<circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
|
|
4
|
+
<circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
|
|
5
|
+
<circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
|
|
6
|
+
<circle cx="12" cy="11" r="8.25" fill="#F88181"/>
|
|
7
|
+
<svg x="8.5" y="6" width="7" height="10" viewBox="0 0 7 10" fill="#FFFFFF">
|
|
8
|
+
<path transform="translate(-7 -5)" fill-rule="evenodd" d="M8.55555556,14.8333333 L7,14.8333333 L7,5.5 L8.55555556,5.5 L8.55555556,9.38888889 L12.4444444,9.38888889 L12.4444444,5.5 L14,5.5 L14,14.8333333 L12.4444444,14.8333333 L12.4444444,10.9444444 L8.55555556,10.9444444 Z"/>
|
|
9
|
+
</svg>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
|
2
|
+
<title>Lodging</title>
|
|
3
|
+
<circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
|
|
4
|
+
<circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
|
|
5
|
+
<circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
|
|
6
|
+
<circle cx="12" cy="11" r="8.25" fill="#909CE1"/>
|
|
7
|
+
<svg x="6.5" y="7.5" width="11" height="7" viewBox="0 0 11 7" fill="#FFFFFF">
|
|
8
|
+
<path transform="translate(-5 -7)" fill-rule="evenodd" d="M5.86454849,7 C6.07788926,7 6.25083612,7.16733023 6.25083612,7.38333841 L6.25026087,11.23 L13.8162609,11.23 L13.8162609,11.229 L9.55363082,11.2296026 L9.55363082,7.94186138 C9.55363082,7.94186138 10.4141238,8.05735202 10.7150234,8.05735206 C12.2129784,8.05735203 13.5048382,9.50607239 14.0681491,10.3167693 L14.7461904,7.83035651 L14.7482609,8.617 L14.7491639,8.01836305 C14.7491639,7.83291732 14.8863533,7.67819481 15.0593924,7.64241177 L15.1354515,7.63461538 C15.3487923,7.63461538 15.5217391,7.8115966 15.5217391,8.01836305 L15.5217391,13.7692308 L14.7491639,13.7692308 L14.7482609,12.5 L6.25026087,12.5 L6.25083612,13.7692308 L5.47826087,13.7692308 L5.47826087,7.38333841 C5.47826087,7.19809045 5.61545027,7.04353295 5.78848942,7.00778807 L5.86454849,7 Z M7.98913043,8.05769231 C8.62915273,8.05769231 9.14799331,8.62594628 9.14799331,9.32692308 C9.14799331,10.0278999 8.62915273,10.5961538 7.98913043,10.5961538 C7.34910814,10.5961538 6.83026756,10.0278999 6.83026756,9.32692308 C6.83026756,8.62594628 7.34910814,8.05769231 7.98913043,8.05769231 Z"/>
|
|
9
|
+
</svg>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
|
2
|
+
<title>Museum</title>
|
|
3
|
+
<circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
|
|
4
|
+
<circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
|
|
5
|
+
<circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
|
|
6
|
+
<circle cx="12" cy="11" r="8.25" fill="#13B5C7"/>
|
|
7
|
+
<svg x="7.5" y="5.75" width="9" height="9.82" viewBox="0 0 11 12" fill="#FFFFFF">
|
|
8
|
+
<path transform="translate(-5 -4)" fill-rule="evenodd" d="M10.5,4.5 L16,8.5 L16,9.5 L15,9.5 L15,15 L16,15 L16,16 L5,16 L5,15 L6,15 L6,9.5 L5,9.5 L5,8.5 L10.5,4.5 Z M14,8.5 L7,8.5 L7,15 L14,15 L14,8.5 Z M8.99948459,9.49839952 L10.5053982,11.6376682 L12,9.512 L12,9.5 L13,9.5 L13,14 L12,14 L12,11.264 L10.5053982,13.6524794 L8.999,11.277 L9,14 L8,14 L8,9.5 L9,9.5 Z"/>
|
|
9
|
+
</svg>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
|
2
|
+
<title>Restaurant</title>
|
|
3
|
+
<circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
|
|
4
|
+
<circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
|
|
5
|
+
<circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
|
|
6
|
+
<circle cx="12" cy="11" r="8.25" fill="#FF9E67"/>
|
|
7
|
+
<svg x="8.5" y="6" width="7" height="9.625" viewBox="0 0 8 11" fill="#FFFFFF">
|
|
8
|
+
<path transform="translate(-6 -6)" fill-rule="evenodd" d="M12.4864865,12.0540541 L12.4864865,16.1621622 L14,16.1621622 L14,6.21621622 L12.4864865,6.21621622 L11.6216216,7.94594595 L11.6216216,10.7567568 L12.4864865,12.0540541 Z M9.02702703,10.7567568 L9.02702703,11.1891892 L10.7567568,10.3243243 L10.7567568,9.89189189 L10.7567568,7.08108108 L9.67567568,6.21621622 L9.67567568,9.45945946 L9.13513514,9.45945946 L8.81081081,9.45945946 L8.81081081,6 L7.94594595,6 L7.94594595,9.45945946 L7.62162162,9.45945946 L7.08108108,9.45945946 L7.08108108,6.21621622 L6,7.08108108 L6,9.89189189 L6,10.3243243 L7.72972973,11.1891892 L7.72972973,10.7567568 L7.72972973,16.1621622 L9.02702703,16.1621622 Z"/>
|
|
9
|
+
</svg>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
|
2
|
+
<title>School</title>
|
|
3
|
+
<circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
|
|
4
|
+
<circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
|
|
5
|
+
<circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
|
|
6
|
+
<circle cx="12" cy="11" r="8.25" fill="#7B9EB0"/>
|
|
7
|
+
<svg x="6.75" y="6.5" width="10.5" height="8.9" viewBox="0 0 13 11" fill="#FFFFFF">
|
|
8
|
+
<path transform="translate(-4 -5)" fill-rule="evenodd" d="M14.0097657,12.019911 L14.0097657,13.8695475 C13.1038778,15.4241579 10.6537375,15.3674047 10.5024279,15.3623802 C10.3511182,15.3674047 7.90097798,15.4241579 6.99509006,13.8695475 L6.99509006,12.019911 C6.99509006,12.019911 9.60423929,13.5859459 10.5024279,13.6268096 C11.4006164,13.5859459 14.0097657,12.019911 14.0097657,12.019911 Z M10.5,5 L17,8.25037977 L17,9.23855252 L16,9.738 L16,14.7579754 L15,14.7579754 L15,10.238 L10.5,12.4889323 L4,9.23855252 L4,8.25037977 L10.5,5 Z"/>
|
|
9
|
+
</svg>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
|
2
|
+
<title>Services</title>
|
|
3
|
+
<circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
|
|
4
|
+
<circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
|
|
5
|
+
<circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
|
|
6
|
+
<circle cx="12" cy="11" r="8.25" fill="#7B9EB0"/>
|
|
7
|
+
<svg x="6.75" y="6.25" width="10.5" height="9.55" viewBox="0 0 11 10" fill="#FFFFFF">
|
|
8
|
+
<path transform="translate(-5 -6)" fill-rule="evenodd" d="M11.015625,7.32533488 C13.2436218,5.65449747 15.9996948,6.04597697 15.9996948,6.04597697 L15.999,7.327 L16,7.32722697 L16,14.327227 L15.9140184,14.3269458 C11.9704111,14.3496822 11.930542,15.8108695 11.930542,15.8108695 L11.0158997,15.8108695 L11.015,14.327 L11,14.327227 L11,7.32722697 L12.123,7.327 Z M5.0078125,6.03795084 C5.0078125,6.03795084 7.7638855,5.65449747 9.99188232,7.32533488 L8.883,7.327 L10.0075073,7.32722697 L10.0075073,14.327227 L9.991,14.327 L9.99160767,15.8108695 L9.07696533,15.8108695 C9.06464946,15.6770402 8.85223435,14.3486164 5.09348894,14.3269458 L5.00750732,14.327227 L5.0078125,6.03795084 Z"/>
|
|
9
|
+
</svg>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
|
2
|
+
<title>Shopping</title>
|
|
3
|
+
<circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
|
|
4
|
+
<circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
|
|
5
|
+
<circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
|
|
6
|
+
<circle cx="12" cy="11" r="8.25" fill="#4B96F3"/>
|
|
7
|
+
<svg x="7" y="6.25" width="10" height="9.23" viewBox="0 0 13 12" fill="#FFFFFF">
|
|
8
|
+
<path transform="translate(-4 -3)" fill-rule="evenodd" d="M7.49019231,10.9275 C7.49019231,10.6215865 7.75802885,10.3747356 8.09141827,10.3747356 C8.42242788,10.3747356 8.69286058,10.6215865 8.69286058,10.9275 C8.69286058,11.6896875 9.46045673,12.3811298 10.5012981,12.3852404 C11.5421394,12.3811298 12.3060577,11.6896875 12.3086538,10.9275 C12.311899,10.6215865 12.5777885,10.3747356 12.9107452,10.3747356 C13.2415385,10.3747356 13.5137019,10.6215865 13.5137019,10.9275 C13.503101,12.3852404 12.1208654,13.4855769 10.5012981,13.4864423 C8.88259615,13.4855769 7.49689904,12.3852404 7.49019231,10.9275 Z M9.41415865,5.7046875 C9.77740385,5.03704327 10.2157212,4.76574519 10.5038942,4.78024038 C10.7881731,4.76574519 11.2264904,5.03704327 11.5901683,5.7046875 C11.8982452,6.26675481 12.1091827,7.15074519 12.1665144,8.03971154 L8.83608173,8.03971154 C8.89341346,7.15074519 9.10478365,6.26675481 9.41415865,5.7046875 M15.5291827,8.18855769 C15.4253365,8.09293269 15.2786538,8.03971154 15.130024,8.03971154 L13.2858894,8.03971154 C13.1439663,5.85439904 12.2803125,3.879375 10.5038942,3.75 C8.72314904,3.879375 7.85819712,5.85439904 7.71670673,8.03971154 L5.87213942,8.03971154 C5.72394231,8.03971154 5.57725962,8.09293269 5.47254808,8.18855769 C5.36848558,8.28569712 5.30769231,8.4159375 5.30769231,8.55439904 L4.875,14.4861779 C4.875,14.6222596 4.93665865,14.7548798 5.03985577,14.8496394 C5.14802885,14.9459135 5.29125,15 5.43944712,15 L15.5627163,15 C15.7139423,15 15.8541346,14.9476442 15.9590625,14.8496394 C16.0678846,14.7525 16.125,14.6248558 16.125,14.4861779 L15.6923077,8.55439904 C15.6923077,8.41918269 15.6328125,8.28569712 15.5291827,8.18855769"/>
|
|
9
|
+
</svg>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
|
2
|
+
<title>Train and rail</title>
|
|
3
|
+
<circle cx="12" cy="13" r="10.5" fill="#44515E" opacity=".08"/>
|
|
4
|
+
<circle cx="12" cy="12.5" r="10" fill="#44515E" opacity=".22"/>
|
|
5
|
+
<circle cx="12" cy="11" r="10" fill="#FFFFFF"/>
|
|
6
|
+
<circle cx="12" cy="11" r="8.25" fill="#10BDFF"/>
|
|
7
|
+
<svg x="7.875" y="5.9" width="8.25" height="9.8" viewBox="0 0 16 19" fill="#FFFFFF">
|
|
8
|
+
<path d="M8,0C4,0,0,.5,0,4v9.5A3.5,3.5,0,0,0,3.5,17L2,18.5V19H4.23l2-2H10l2,2h2v-.5L12.5,17A3.5,3.5,0,0,0,16,13.5V4c0-3.5-3.58-4-8-4ZM3.5,15A1.5,1.5,0,1,1,5,13.5,1.5,1.5,0,0,1,3.5,15ZM7,8H2V4H7V8ZM9,8V4h5V8Zm3.5,7A1.5,1.5,0,1,1,14,13.5,1.5,1.5,0,0,1,12.5,15Z"/>
|
|
9
|
+
</svg>
|
|
10
|
+
</svg>
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
-
import { TileflowIconPackageFileName, TileflowIconPackageManifest, TileflowProjectConfig, MapLibreStyle, TileflowManifest, ValidationMessage, TileflowStyleOptions } from '@tileflow/core';
|
|
2
|
+
import { TileflowIconPackageFileName, TileflowIconPackageManifest, TileflowProjectConfig, MapLibreStyle, NormalizedTileflowCaptureScene, TileflowManifest, ValidationMessage, TileflowStyleOptions } from '@tileflow/core';
|
|
3
3
|
|
|
4
4
|
declare const tileflowArtifactSessionSchemaVersion: 1;
|
|
5
5
|
type TileflowArtifactDiagnostic = {
|
|
@@ -163,6 +163,7 @@ declare function prepareTileflowProjectIcons(project: TileflowProjectConfig, opt
|
|
|
163
163
|
}): Promise<PreparedTileflowProject>;
|
|
164
164
|
|
|
165
165
|
type TileflowFeatureInspectionOptions = {
|
|
166
|
+
apiBaseUrl?: string;
|
|
166
167
|
center: readonly [number, number];
|
|
167
168
|
fetch?: typeof fetch;
|
|
168
169
|
height?: number;
|
|
@@ -170,7 +171,6 @@ type TileflowFeatureInspectionOptions = {
|
|
|
170
171
|
properties?: readonly string[];
|
|
171
172
|
signal?: AbortSignal;
|
|
172
173
|
sourceLayers: readonly string[];
|
|
173
|
-
tileBaseUrl?: string;
|
|
174
174
|
timeoutMs?: number;
|
|
175
175
|
width?: number;
|
|
176
176
|
zoom: number;
|
|
@@ -231,30 +231,44 @@ declare function validateTileflowStyle(style: MapLibreStyle, map: string): Tilef
|
|
|
231
231
|
declare const defaultTileflowApiUrl = "https://api.tileflow.dev";
|
|
232
232
|
declare const defaultTileflowConfigPath = "tileflow.config.ts";
|
|
233
233
|
declare const defaultTileflowManifestPath = "public/tileflow/manifest.json";
|
|
234
|
-
declare const defaultTileflowTileset = "world";
|
|
235
234
|
type LoadTileflowConfigOptions = {
|
|
236
235
|
cwd?: string;
|
|
237
236
|
fresh?: boolean;
|
|
238
237
|
};
|
|
239
238
|
type TileflowManifestOptions = {
|
|
240
239
|
styleBaseUrl?: string;
|
|
241
|
-
tileBaseUrl?: string;
|
|
242
240
|
};
|
|
243
241
|
type TileflowDevRequestHandlerOptions = {
|
|
242
|
+
apiBaseUrl?: string;
|
|
244
243
|
basePath?: string;
|
|
245
244
|
config?: string;
|
|
246
245
|
cwd?: string;
|
|
246
|
+
map?: string;
|
|
247
247
|
onError?: (error: unknown) => void;
|
|
248
|
+
scene?: string;
|
|
248
249
|
session?: TileflowArtifactSession;
|
|
249
250
|
styleBaseUrl?: string;
|
|
250
|
-
tileBaseUrl?: string;
|
|
251
251
|
};
|
|
252
|
+
type TileflowPreviewSelection = {
|
|
253
|
+
map?: string;
|
|
254
|
+
scene?: string;
|
|
255
|
+
};
|
|
256
|
+
type ResolvedTileflowPreview = {
|
|
257
|
+
camera: NormalizedTileflowCaptureScene['camera'];
|
|
258
|
+
label: string;
|
|
259
|
+
mapName: string;
|
|
260
|
+
viewport?: NormalizedTileflowCaptureScene['viewport'];
|
|
261
|
+
};
|
|
262
|
+
declare class TileflowPreviewSelectionError extends Error {
|
|
263
|
+
readonly code: "PREVIEW_SELECTION_INVALID";
|
|
264
|
+
constructor(message: string);
|
|
265
|
+
}
|
|
252
266
|
type TileflowBuildArtifactsOptions = {
|
|
267
|
+
apiBaseUrl?: string;
|
|
253
268
|
assetBaseUrl?: string;
|
|
254
269
|
config?: string;
|
|
255
270
|
cwd?: string;
|
|
256
271
|
styleBaseUrl?: string;
|
|
257
|
-
tileBaseUrl?: string;
|
|
258
272
|
};
|
|
259
273
|
type TileflowBuildArtifacts = {
|
|
260
274
|
assets: TileflowBuildAsset[];
|
|
@@ -278,6 +292,7 @@ declare function assertValidTileflowConfig(project: TileflowProjectConfig): void
|
|
|
278
292
|
declare function asTileflowProjectConfig(input: unknown): TileflowProjectConfig;
|
|
279
293
|
declare function getTileflowMapNames(project: TileflowProjectConfig): string[];
|
|
280
294
|
declare function getFirstTileflowMapName(project: TileflowProjectConfig): string;
|
|
295
|
+
declare function resolveTileflowPreview(project: TileflowProjectConfig, selection?: TileflowPreviewSelection): ResolvedTileflowPreview;
|
|
281
296
|
declare function getTileflowStyleMapName(path: string): string;
|
|
282
297
|
declare function createTileflowManifest(project: TileflowProjectConfig, options?: TileflowManifestOptions): TileflowManifest;
|
|
283
298
|
declare function createTileflowStyle(project: TileflowProjectConfig, mapName: string, options?: TileflowStyleOptions): MapLibreStyle;
|
|
@@ -302,4 +317,4 @@ declare function createTileflowArtifactStatus(state: TileflowArtifactSessionStat
|
|
|
302
317
|
};
|
|
303
318
|
declare function normalizeTileflowBasePath(value?: string): string;
|
|
304
319
|
|
|
305
|
-
export { type CompileTileflowIconPackagesResult, type CompiledTileflowIconPackage, type CompiledTileflowIconPackageFile, type InspectTileflowIconCatalogsOptions, type LoadTileflowConfigOptions, type PreparedTileflowProject, type TileflowArtifactDiagnostic, type TileflowArtifactSession, type TileflowArtifactSessionOptions, type TileflowArtifactSessionState, type TileflowBuildArtifacts, type TileflowBuildArtifactsOptions, type TileflowBuildAsset, type TileflowDevRequestHandlerOptions, type TileflowFeatureInspection, type TileflowFeatureInspectionOptions, type TileflowIconCatalog, type TileflowIconCatalogAtlasRectangle, type TileflowIconCatalogIcon, type TileflowIconCatalogInspection, type TileflowIconCatalogMap, type TileflowIconCatalogMappedFrom, type TileflowIconCatalogMapping, type TileflowIconCatalogRenderedDensity, type TileflowIconCatalogSourceFormat, TileflowIconCompilationError, type TileflowIconCompilationIssue, type TileflowIconCompilationTarget, type TileflowInspectedFeature, type TileflowInspectedProperty, type TileflowManifestOptions, type TileflowMapIconPackageBinding, TileflowStyleValidationError, type TileflowStyleValidationIssue, TileflowValidationError, type WriteTileflowBuildArtifactsOptions, asTileflowProjectConfig, assertValidTileflowConfig, assertValidTileflowStyle, compileTileflowIconPackages, createTileflowArtifactDiagnostics, createTileflowArtifactSession, createTileflowArtifactStatus, createTileflowBuildArtifacts, createTileflowDevRequestHandler, createTileflowManifest, createTileflowNodeRequest, createTileflowStyle, createTileflowStyles, defaultTileflowApiUrl, defaultTileflowConfigPath, defaultTileflowManifestPath,
|
|
320
|
+
export { type CompileTileflowIconPackagesResult, type CompiledTileflowIconPackage, type CompiledTileflowIconPackageFile, type InspectTileflowIconCatalogsOptions, type LoadTileflowConfigOptions, type PreparedTileflowProject, type ResolvedTileflowPreview, type TileflowArtifactDiagnostic, type TileflowArtifactSession, type TileflowArtifactSessionOptions, type TileflowArtifactSessionState, type TileflowBuildArtifacts, type TileflowBuildArtifactsOptions, type TileflowBuildAsset, type TileflowDevRequestHandlerOptions, type TileflowFeatureInspection, type TileflowFeatureInspectionOptions, type TileflowIconCatalog, type TileflowIconCatalogAtlasRectangle, type TileflowIconCatalogIcon, type TileflowIconCatalogInspection, type TileflowIconCatalogMap, type TileflowIconCatalogMappedFrom, type TileflowIconCatalogMapping, type TileflowIconCatalogRenderedDensity, type TileflowIconCatalogSourceFormat, TileflowIconCompilationError, type TileflowIconCompilationIssue, type TileflowIconCompilationTarget, type TileflowInspectedFeature, type TileflowInspectedProperty, type TileflowManifestOptions, type TileflowMapIconPackageBinding, type TileflowPreviewSelection, TileflowPreviewSelectionError, TileflowStyleValidationError, type TileflowStyleValidationIssue, TileflowValidationError, type WriteTileflowBuildArtifactsOptions, asTileflowProjectConfig, assertValidTileflowConfig, assertValidTileflowStyle, compileTileflowIconPackages, createTileflowArtifactDiagnostics, createTileflowArtifactSession, createTileflowArtifactStatus, createTileflowBuildArtifacts, createTileflowDevRequestHandler, createTileflowManifest, createTileflowNodeRequest, createTileflowStyle, createTileflowStyles, defaultTileflowApiUrl, defaultTileflowConfigPath, defaultTileflowManifestPath, getFirstTileflowMapName, getTileflowAssetBasePath, getTileflowAssetFileName, getTileflowMapNames, getTileflowStyleMapName, getTileflowWatchPaths, iconFileExtensions, inspectTileflowFeatures, inspectTileflowIconCatalogs, isTileflowRequestUrl, joinTileflowPublicUrl, loadTileflowConfig, loadValidTileflowConfig, normalizeTileflowBasePath, prepareTileflowProjectIcons, resolveTileflowPreview, tileflowArtifactSessionSchemaVersion, validateTileflowStyle, writeTileflowBuildArtifacts, writeTileflowNodeResponse };
|
package/dist/index.js
CHANGED
|
@@ -8,12 +8,14 @@ import {
|
|
|
8
8
|
compareCodeUnits as compareCodeUnits3,
|
|
9
9
|
createManifest,
|
|
10
10
|
createStyleFromProject as createStyleFromProject2,
|
|
11
|
+
normalizeTileflowCaptureScene,
|
|
11
12
|
validateConfig
|
|
12
13
|
} from "@tileflow/core";
|
|
13
14
|
|
|
14
15
|
// src/icons.ts
|
|
15
16
|
import { readdir, readFile, realpath, stat } from "fs/promises";
|
|
16
17
|
import { basename, extname, isAbsolute, relative, resolve, sep } from "path";
|
|
18
|
+
import { fileURLToPath } from "url";
|
|
17
19
|
import { SaxesParser } from "saxes";
|
|
18
20
|
import {
|
|
19
21
|
compareCodeUnits,
|
|
@@ -24,7 +26,8 @@ import {
|
|
|
24
26
|
tileflowHostedIconIdPattern,
|
|
25
27
|
tileflowIconPackageLabelSchema,
|
|
26
28
|
tileflowIconPackageLimits,
|
|
27
|
-
tileflowIconPackageManifestSchema
|
|
29
|
+
tileflowIconPackageManifestSchema,
|
|
30
|
+
tileflowStreetsPoiIconMapping
|
|
28
31
|
} from "@tileflow/core";
|
|
29
32
|
var TileflowIconCompilationError = class extends Error {
|
|
30
33
|
code = "ICON_INVALID";
|
|
@@ -43,6 +46,7 @@ var TileflowIconCompilationError = class extends Error {
|
|
|
43
46
|
};
|
|
44
47
|
var iconFileExtensions = /* @__PURE__ */ new Set([".svg", ".png", ".jpg", ".jpeg", ".webp"]);
|
|
45
48
|
var iconSpriteSize = 24;
|
|
49
|
+
var streetsPoiIconSourceDir = fileURLToPath(new URL("../assets/streets-poi", import.meta.url));
|
|
46
50
|
async function compileTileflowIconPackages(project, options) {
|
|
47
51
|
const result = await compileIconSources(project, options);
|
|
48
52
|
const packagesByHash = /* @__PURE__ */ new Map();
|
|
@@ -66,7 +70,11 @@ async function compileTileflowIconPackages(project, options) {
|
|
|
66
70
|
packages: [...packagesByHash.values()].sort(
|
|
67
71
|
(left, right) => compareCodeUnits(left.contentHash, right.contentHash)
|
|
68
72
|
),
|
|
69
|
-
watchPaths: [
|
|
73
|
+
watchPaths: [
|
|
74
|
+
...new Set(
|
|
75
|
+
result.resolvedRequests.filter((request) => !request.builtIn).map((request) => request.realSourceDir)
|
|
76
|
+
)
|
|
77
|
+
].sort(compareCodeUnits)
|
|
70
78
|
};
|
|
71
79
|
}
|
|
72
80
|
async function inspectTileflowIconCatalogs(project, options) {
|
|
@@ -192,7 +200,7 @@ async function compileIconSources(project, options) {
|
|
|
192
200
|
for (const request of requests) {
|
|
193
201
|
try {
|
|
194
202
|
const realSourceDir = await realpath(request.sourceDir);
|
|
195
|
-
if (options.target === "hosted" && realCwd && !isPathInside(realCwd, realSourceDir)) {
|
|
203
|
+
if (options.target === "hosted" && realCwd && !request.builtIn && !isPathInside(realCwd, realSourceDir)) {
|
|
196
204
|
issues.push({
|
|
197
205
|
message: "Hosted icon sources must remain inside the selected working tree",
|
|
198
206
|
path: sourcePath(request.mapName)
|
|
@@ -292,9 +300,9 @@ async function prepareTileflowProjectIcons(project, options) {
|
|
|
292
300
|
};
|
|
293
301
|
}
|
|
294
302
|
function getTileflowIconWatchPaths(project, cwd) {
|
|
295
|
-
return uniqueStrings(
|
|
296
|
-
|
|
297
|
-
);
|
|
303
|
+
return uniqueStrings(
|
|
304
|
+
getLocalIconRequests(project, cwd).filter((request) => !request.builtIn).map((request) => request.sourceDir)
|
|
305
|
+
).sort(compareCodeUnits);
|
|
298
306
|
}
|
|
299
307
|
function getLocalIconRequests(project, cwd) {
|
|
300
308
|
return getMapIconRequests(project, cwd).filter(
|
|
@@ -309,6 +317,18 @@ function getMapIconRequests(project, cwd, mapNames) {
|
|
|
309
317
|
throw new Error(`Unknown Tileflow map: ${mapName}`);
|
|
310
318
|
}
|
|
311
319
|
const iconSet = resolveIconSet(mapConfig.icons, project.icons);
|
|
320
|
+
if (!iconSet?.source && !iconSet?.sprite && usesBuiltInStreetsPoiIcons(mapConfig)) {
|
|
321
|
+
const mapping2 = sortMapping({ ...tileflowStreetsPoiIconMapping, ...iconSet?.mapping });
|
|
322
|
+
return {
|
|
323
|
+
builtIn: true,
|
|
324
|
+
kind: "local",
|
|
325
|
+
label: "tileflow-streets",
|
|
326
|
+
mapName,
|
|
327
|
+
...mapping2 ? { mapping: mapping2 } : {},
|
|
328
|
+
source: "@tileflow/dev/assets/streets-poi",
|
|
329
|
+
sourceDir: streetsPoiIconSourceDir
|
|
330
|
+
};
|
|
331
|
+
}
|
|
312
332
|
const mapping = sortMapping(iconSet?.mapping);
|
|
313
333
|
if (iconSet?.source) {
|
|
314
334
|
return {
|
|
@@ -327,6 +347,10 @@ function getMapIconRequests(project, cwd, mapNames) {
|
|
|
327
347
|
};
|
|
328
348
|
});
|
|
329
349
|
}
|
|
350
|
+
function usesBuiltInStreetsPoiIcons(mapConfig) {
|
|
351
|
+
const poi = mapConfig.modules?.poi;
|
|
352
|
+
return mapConfig.basemap?.type === "streets" && poi?.enabled !== false && poi?.preset !== "none" && poi?.icons !== false;
|
|
353
|
+
}
|
|
330
354
|
function resolveIconSet(icons, iconSets, path = []) {
|
|
331
355
|
if (!icons) {
|
|
332
356
|
return void 0;
|
|
@@ -993,11 +1017,11 @@ var TileflowArtifactSessionImpl = class {
|
|
|
993
1017
|
this.#ignoredPaths = (options.ignoredPaths ?? []).map((path) => resolve2(this.#cwd, path));
|
|
994
1018
|
this.#buildArtifacts = buildArtifacts;
|
|
995
1019
|
this.#buildOptions = {
|
|
1020
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
996
1021
|
assetBaseUrl: options.assetBaseUrl,
|
|
997
1022
|
config: options.config,
|
|
998
1023
|
cwd: this.#cwd,
|
|
999
|
-
styleBaseUrl: options.styleBaseUrl
|
|
1000
|
-
tileBaseUrl: options.tileBaseUrl
|
|
1024
|
+
styleBaseUrl: options.styleBaseUrl
|
|
1001
1025
|
};
|
|
1002
1026
|
}
|
|
1003
1027
|
async start() {
|
|
@@ -1428,7 +1452,7 @@ async function inspectTileflowFeatures(project, mapName, input) {
|
|
|
1428
1452
|
`Unknown map "${mapName}". Available maps: ${available.join(", ") || "(none)"}`
|
|
1429
1453
|
);
|
|
1430
1454
|
}
|
|
1431
|
-
const style = createStyleFromProject(project, mapName, {
|
|
1455
|
+
const style = createStyleFromProject(project, mapName, { apiBaseUrl: options.apiBaseUrl });
|
|
1432
1456
|
assertValidTileflowStyle(style, mapName);
|
|
1433
1457
|
const source = resolveVectorSource(style, options.sourceLayers);
|
|
1434
1458
|
const fetchImplementation = options.fetch ?? globalThis.fetch;
|
|
@@ -1494,7 +1518,8 @@ async function inspectTileflowFeatures(project, mapName, input) {
|
|
|
1494
1518
|
}
|
|
1495
1519
|
const uniqueFeatures = deduplicateFeatures(features).sort(compareInspectedFeatures);
|
|
1496
1520
|
const limitedFeatures = uniqueFeatures.slice(0, options.limit);
|
|
1497
|
-
const
|
|
1521
|
+
const dataIdentity = style.metadata?.["tileflow:data"];
|
|
1522
|
+
const metadataVersion = dataIdentity && typeof dataIdentity === "object" && "revision" in dataIdentity ? dataIdentity.revision : void 0;
|
|
1498
1523
|
return {
|
|
1499
1524
|
schemaVersion: 1,
|
|
1500
1525
|
map: mapName,
|
|
@@ -1839,7 +1864,13 @@ function isRecord(value) {
|
|
|
1839
1864
|
var defaultTileflowApiUrl = "https://api.tileflow.dev";
|
|
1840
1865
|
var defaultTileflowConfigPath = "tileflow.config.ts";
|
|
1841
1866
|
var defaultTileflowManifestPath = "public/tileflow/manifest.json";
|
|
1842
|
-
var
|
|
1867
|
+
var TileflowPreviewSelectionError = class extends Error {
|
|
1868
|
+
code = "PREVIEW_SELECTION_INVALID";
|
|
1869
|
+
constructor(message) {
|
|
1870
|
+
super(message);
|
|
1871
|
+
this.name = "TileflowPreviewSelectionError";
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1843
1874
|
var TileflowValidationError = class extends Error {
|
|
1844
1875
|
code = "CONFIG_INVALID";
|
|
1845
1876
|
messages;
|
|
@@ -1881,17 +1912,7 @@ function asTileflowProjectConfig(input) {
|
|
|
1881
1912
|
if (input && typeof input === "object" && "maps" in input && typeof input.maps === "object") {
|
|
1882
1913
|
return input;
|
|
1883
1914
|
}
|
|
1884
|
-
return {
|
|
1885
|
-
tilesets: {
|
|
1886
|
-
[defaultTileflowTileset]: {
|
|
1887
|
-
id: defaultTileflowTileset,
|
|
1888
|
-
name: "World"
|
|
1889
|
-
}
|
|
1890
|
-
},
|
|
1891
|
-
maps: {
|
|
1892
|
-
main: input
|
|
1893
|
-
}
|
|
1894
|
-
};
|
|
1915
|
+
return { maps: { main: input } };
|
|
1895
1916
|
}
|
|
1896
1917
|
function getTileflowMapNames(project) {
|
|
1897
1918
|
return Object.keys(project.maps);
|
|
@@ -1903,6 +1924,52 @@ function getFirstTileflowMapName(project) {
|
|
|
1903
1924
|
}
|
|
1904
1925
|
return mapName;
|
|
1905
1926
|
}
|
|
1927
|
+
function resolveTileflowPreview(project, selection = {}) {
|
|
1928
|
+
if (selection.map !== void 0 && selection.scene !== void 0) {
|
|
1929
|
+
throw new TileflowPreviewSelectionError(
|
|
1930
|
+
"Choose either a Tileflow preview map or scene, not both."
|
|
1931
|
+
);
|
|
1932
|
+
}
|
|
1933
|
+
if (selection.scene !== void 0) {
|
|
1934
|
+
const scene = Object.hasOwn(project.scenes ?? {}, selection.scene) ? project.scenes?.[selection.scene] : void 0;
|
|
1935
|
+
if (!scene) {
|
|
1936
|
+
throw new TileflowPreviewSelectionError(`Unknown Tileflow scene: ${selection.scene}`);
|
|
1937
|
+
}
|
|
1938
|
+
const normalized = normalizeTileflowCaptureScene(scene);
|
|
1939
|
+
if (normalized.target.kind === "application") {
|
|
1940
|
+
throw new TileflowPreviewSelectionError(
|
|
1941
|
+
`Tileflow scene "${selection.scene}" targets an application. Preview it through the application's development server.`
|
|
1942
|
+
);
|
|
1943
|
+
}
|
|
1944
|
+
if (!Object.hasOwn(project.maps, normalized.map)) {
|
|
1945
|
+
throw new TileflowPreviewSelectionError(
|
|
1946
|
+
`Tileflow scene "${selection.scene}" references an unknown map: ${normalized.map}`
|
|
1947
|
+
);
|
|
1948
|
+
}
|
|
1949
|
+
return {
|
|
1950
|
+
camera: normalized.camera,
|
|
1951
|
+
label: `${normalized.map} / ${selection.scene} \xB7 ${normalized.viewport.width}\xD7${normalized.viewport.height}`,
|
|
1952
|
+
mapName: normalized.map,
|
|
1953
|
+
viewport: normalized.viewport
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
const mapName = selection.map ?? getFirstTileflowMapName(project);
|
|
1957
|
+
const map = Object.hasOwn(project.maps, mapName) ? project.maps[mapName] : void 0;
|
|
1958
|
+
if (!map) {
|
|
1959
|
+
throw new TileflowPreviewSelectionError(`Unknown Tileflow map: ${mapName}`);
|
|
1960
|
+
}
|
|
1961
|
+
return {
|
|
1962
|
+
camera: {
|
|
1963
|
+
type: "center",
|
|
1964
|
+
center: map.view?.center ? [map.view.center[0], map.view.center[1]] : [0, 0],
|
|
1965
|
+
zoom: map.view?.zoom ?? 0,
|
|
1966
|
+
bearing: map.view?.bearing ?? 0,
|
|
1967
|
+
pitch: map.view?.pitch ?? 0
|
|
1968
|
+
},
|
|
1969
|
+
label: mapName,
|
|
1970
|
+
mapName
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1906
1973
|
function getTileflowStyleMapName(path) {
|
|
1907
1974
|
const fileName = path.split("/").pop() ?? "";
|
|
1908
1975
|
return fileName.replace(/\.json$/, "");
|
|
@@ -1937,13 +2004,12 @@ async function createTileflowBuildArtifacts(options = {}) {
|
|
|
1937
2004
|
assetBaseUrl: resolveAssetBaseUrl(options),
|
|
1938
2005
|
cwd: options.cwd ?? process.cwd()
|
|
1939
2006
|
});
|
|
1940
|
-
const styleOptions = {
|
|
2007
|
+
const styleOptions = { apiBaseUrl: options.apiBaseUrl };
|
|
1941
2008
|
const styles = createTileflowStyles(prepared.project, styleOptions);
|
|
1942
2009
|
return {
|
|
1943
2010
|
assets: prepared.assets,
|
|
1944
2011
|
manifest: createManifest(prepared.project, {
|
|
1945
|
-
styleBaseUrl: options.styleBaseUrl
|
|
1946
|
-
tileBaseUrl: options.tileBaseUrl
|
|
2012
|
+
styleBaseUrl: options.styleBaseUrl
|
|
1947
2013
|
}),
|
|
1948
2014
|
project: prepared.project,
|
|
1949
2015
|
styles,
|
|
@@ -2048,7 +2114,7 @@ function createTileflowDevRequestHandler(options = {}) {
|
|
|
2048
2114
|
const basePath = normalizeTileflowBasePath(options.basePath);
|
|
2049
2115
|
const configPath = options.config ?? defaultTileflowConfigPath;
|
|
2050
2116
|
const cwd = options.cwd ?? process.cwd();
|
|
2051
|
-
const
|
|
2117
|
+
const apiBaseUrl = options.apiBaseUrl ?? defaultTileflowApiUrl;
|
|
2052
2118
|
return async function handleTileflowDevRequest(request) {
|
|
2053
2119
|
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
2054
2120
|
return jsonResponse({ error: "Method not allowed" }, 405);
|
|
@@ -2079,7 +2145,7 @@ function createTileflowDevRequestHandler(options = {}) {
|
|
|
2079
2145
|
config: configPath,
|
|
2080
2146
|
cwd,
|
|
2081
2147
|
styleBaseUrl: options.styleBaseUrl ?? `${url.origin}${basePath}`,
|
|
2082
|
-
|
|
2148
|
+
apiBaseUrl
|
|
2083
2149
|
});
|
|
2084
2150
|
state = {
|
|
2085
2151
|
artifacts,
|
|
@@ -2092,8 +2158,8 @@ function createTileflowDevRequestHandler(options = {}) {
|
|
|
2092
2158
|
return jsonResponse(createTileflowArtifactStatus(state));
|
|
2093
2159
|
}
|
|
2094
2160
|
if (path === "/" || path === "") {
|
|
2095
|
-
const
|
|
2096
|
-
return htmlResponse(previewHtml(
|
|
2161
|
+
const preview = artifacts ? resolveTileflowPreview(artifacts.project, { map: options.map, scene: options.scene }) : void 0;
|
|
2162
|
+
return htmlResponse(previewHtml(preview, basePath, state));
|
|
2097
2163
|
}
|
|
2098
2164
|
if (!artifacts) return unavailableArtifactsResponse(state);
|
|
2099
2165
|
if (path === "/manifest.json") {
|
|
@@ -2199,6 +2265,9 @@ function stripTileflowBasePath(pathname, basePath) {
|
|
|
2199
2265
|
return null;
|
|
2200
2266
|
}
|
|
2201
2267
|
function tileflowErrorResponse(error) {
|
|
2268
|
+
if (error instanceof TileflowPreviewSelectionError) {
|
|
2269
|
+
return jsonResponse({ error: error.message }, 400);
|
|
2270
|
+
}
|
|
2202
2271
|
if (error instanceof TileflowStyleValidationError) {
|
|
2203
2272
|
return jsonResponse(
|
|
2204
2273
|
{
|
|
@@ -2263,9 +2332,23 @@ function resolveAssetBaseUrl(options) {
|
|
|
2263
2332
|
function isRelativePublicUrl(value) {
|
|
2264
2333
|
return !(value.startsWith("http://") || value.startsWith("https://") || value.startsWith("/") || value.startsWith("data:"));
|
|
2265
2334
|
}
|
|
2266
|
-
function previewHtml(
|
|
2267
|
-
const styleUrl =
|
|
2335
|
+
function previewHtml(preview, basePath, state) {
|
|
2336
|
+
const styleUrl = preview ? `${basePath}/styles/${preview.mapName}.json` : void 0;
|
|
2268
2337
|
const initialStatus = createTileflowArtifactStatus(state);
|
|
2338
|
+
const mapOptions = preview ? previewMapOptions(preview) : void 0;
|
|
2339
|
+
const viewportCss = preview?.viewport ? `
|
|
2340
|
+
html, body { min-height: 100%; margin: 0; }
|
|
2341
|
+
body {
|
|
2342
|
+
display: grid;
|
|
2343
|
+
place-items: center;
|
|
2344
|
+
overflow: auto;
|
|
2345
|
+
background: #E8E5DE;
|
|
2346
|
+
}
|
|
2347
|
+
#map {
|
|
2348
|
+
width: ${preview.viewport.width}px;
|
|
2349
|
+
height: ${preview.viewport.height}px;
|
|
2350
|
+
box-shadow: 0 24px 80px rgba(37, 34, 29, 0.18);
|
|
2351
|
+
}` : "html, body, #map { height: 100%; margin: 0; }";
|
|
2269
2352
|
return `<!doctype html>
|
|
2270
2353
|
<html lang="en">
|
|
2271
2354
|
<head>
|
|
@@ -2274,7 +2357,7 @@ function previewHtml(mapName, basePath, state) {
|
|
|
2274
2357
|
<title>Tileflow Preview</title>
|
|
2275
2358
|
<link rel="stylesheet" href="${basePath}/__runtime/maplibre-gl.css" />
|
|
2276
2359
|
<style>
|
|
2277
|
-
|
|
2360
|
+
${viewportCss}
|
|
2278
2361
|
body { font-family: ui-sans-serif, system-ui, sans-serif; }
|
|
2279
2362
|
.badge {
|
|
2280
2363
|
position: fixed;
|
|
@@ -2315,20 +2398,85 @@ function previewHtml(mapName, basePath, state) {
|
|
|
2315
2398
|
const initialGeneration = initialStatus.generation;
|
|
2316
2399
|
const badge = document.getElementById("badge");
|
|
2317
2400
|
const status = document.getElementById("status");
|
|
2401
|
+
const previewLabel = ${JSON.stringify(preview?.label)};
|
|
2318
2402
|
const styleUrl = ${JSON.stringify(styleUrl)};
|
|
2403
|
+
const previewMapOptions = ${JSON.stringify(mapOptions)};
|
|
2404
|
+
|
|
2405
|
+
const cameraRanges = {
|
|
2406
|
+
bearing: [-180, 180],
|
|
2407
|
+
lat: [-90, 90],
|
|
2408
|
+
lng: [-180, 180],
|
|
2409
|
+
pitch: [0, 85],
|
|
2410
|
+
zoom: [0, 24]
|
|
2411
|
+
};
|
|
2412
|
+
|
|
2413
|
+
function readCameraFromUrl() {
|
|
2414
|
+
const params = new URL(location.href).searchParams;
|
|
2415
|
+
const camera = {};
|
|
2416
|
+
|
|
2417
|
+
for (const [name, range] of Object.entries(cameraRanges)) {
|
|
2418
|
+
const values = params.getAll(name);
|
|
2419
|
+
if (values.length !== 1 || values[0].trim() === "") return undefined;
|
|
2420
|
+
const value = Number(values[0]);
|
|
2421
|
+
if (!Number.isFinite(value) || value < range[0] || value > range[1]) return undefined;
|
|
2422
|
+
camera[name] = value;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
return {
|
|
2426
|
+
bearing: camera.bearing,
|
|
2427
|
+
center: [camera.lng, camera.lat],
|
|
2428
|
+
pitch: camera.pitch,
|
|
2429
|
+
zoom: camera.zoom
|
|
2430
|
+
};
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
function resolveInitialMapOptions(options) {
|
|
2434
|
+
const camera = readCameraFromUrl();
|
|
2435
|
+
if (!camera) return options;
|
|
2436
|
+
const resolved = {...options};
|
|
2437
|
+
delete resolved.bounds;
|
|
2438
|
+
delete resolved.fitBoundsOptions;
|
|
2439
|
+
return {...resolved, ...camera};
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
function formatCameraNumber(value) {
|
|
2443
|
+
return String(Number(value.toFixed(6)));
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
function wrapLongitude(value) {
|
|
2447
|
+
return ((value + 180) % 360 + 360) % 360 - 180;
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
function writeCameraToUrl(map) {
|
|
2451
|
+
const center = map.getCenter();
|
|
2452
|
+
const url = new URL(location.href);
|
|
2453
|
+
const camera = {
|
|
2454
|
+
bearing: map.getBearing(),
|
|
2455
|
+
lat: center.lat,
|
|
2456
|
+
lng: wrapLongitude(center.lng),
|
|
2457
|
+
pitch: map.getPitch(),
|
|
2458
|
+
zoom: map.getZoom()
|
|
2459
|
+
};
|
|
2460
|
+
|
|
2461
|
+
for (const [name, value] of Object.entries(camera)) {
|
|
2462
|
+
url.searchParams.set(name, formatCameraNumber(value));
|
|
2463
|
+
}
|
|
2464
|
+
history.replaceState(history.state, "", url.href);
|
|
2465
|
+
}
|
|
2319
2466
|
|
|
2320
2467
|
if (styleUrl) {
|
|
2321
2468
|
const map = new maplibregl.Map({
|
|
2322
2469
|
container: "map",
|
|
2323
2470
|
style: styleUrl,
|
|
2324
|
-
|
|
2325
|
-
zoom: 12
|
|
2471
|
+
...resolveInitialMapOptions(previewMapOptions)
|
|
2326
2472
|
});
|
|
2327
2473
|
map.addControl(new maplibregl.NavigationControl(), "top-right");
|
|
2474
|
+
map.on("load", () => writeCameraToUrl(map));
|
|
2475
|
+
map.on("moveend", () => writeCameraToUrl(map));
|
|
2328
2476
|
}
|
|
2329
2477
|
|
|
2330
2478
|
function applyStatus(next) {
|
|
2331
|
-
badge.textContent = "Tileflow preview
|
|
2479
|
+
badge.textContent = ["Tileflow preview", previewLabel, next.status].filter(Boolean).join(" \xB7 ");
|
|
2332
2480
|
if (next.status === "invalid") {
|
|
2333
2481
|
const diagnostics = next.diagnostics || [];
|
|
2334
2482
|
status.textContent = diagnostics.map((item) =>
|
|
@@ -2352,6 +2500,26 @@ function previewHtml(mapName, basePath, state) {
|
|
|
2352
2500
|
</body>
|
|
2353
2501
|
</html>`;
|
|
2354
2502
|
}
|
|
2503
|
+
function previewMapOptions(preview) {
|
|
2504
|
+
if (preview.camera.type === "center") {
|
|
2505
|
+
return {
|
|
2506
|
+
bearing: preview.camera.bearing,
|
|
2507
|
+
center: preview.camera.center,
|
|
2508
|
+
pitch: preview.camera.pitch,
|
|
2509
|
+
zoom: preview.camera.zoom
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
const [west, south, east, north] = preview.camera.bounds;
|
|
2513
|
+
return {
|
|
2514
|
+
bearing: preview.camera.bearing,
|
|
2515
|
+
bounds: [
|
|
2516
|
+
[west, south],
|
|
2517
|
+
[east, north]
|
|
2518
|
+
],
|
|
2519
|
+
fitBoundsOptions: { padding: preview.camera.padding },
|
|
2520
|
+
pitch: preview.camera.pitch
|
|
2521
|
+
};
|
|
2522
|
+
}
|
|
2355
2523
|
var localRequire = createRequire(import.meta.url);
|
|
2356
2524
|
var localMapLibreJavaScript;
|
|
2357
2525
|
var localMapLibreStylesheet;
|
|
@@ -2398,6 +2566,7 @@ function isPathWithin(root, candidate) {
|
|
|
2398
2566
|
}
|
|
2399
2567
|
export {
|
|
2400
2568
|
TileflowIconCompilationError,
|
|
2569
|
+
TileflowPreviewSelectionError,
|
|
2401
2570
|
TileflowStyleValidationError,
|
|
2402
2571
|
TileflowValidationError,
|
|
2403
2572
|
asTileflowProjectConfig,
|
|
@@ -2416,7 +2585,6 @@ export {
|
|
|
2416
2585
|
defaultTileflowApiUrl,
|
|
2417
2586
|
defaultTileflowConfigPath,
|
|
2418
2587
|
defaultTileflowManifestPath,
|
|
2419
|
-
defaultTileflowTileset,
|
|
2420
2588
|
getFirstTileflowMapName,
|
|
2421
2589
|
getTileflowAssetBasePath,
|
|
2422
2590
|
getTileflowAssetFileName,
|
|
@@ -2432,6 +2600,7 @@ export {
|
|
|
2432
2600
|
loadValidTileflowConfig,
|
|
2433
2601
|
normalizeTileflowBasePath,
|
|
2434
2602
|
prepareTileflowProjectIcons,
|
|
2603
|
+
resolveTileflowPreview,
|
|
2435
2604
|
tileflowArtifactSessionSchemaVersion,
|
|
2436
2605
|
validateTileflowStyle,
|
|
2437
2606
|
writeTileflowBuildArtifacts,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tileflow/dev",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.18",
|
|
4
4
|
"description": "Node development utilities for Tileflow configs and builds.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"main": "./dist/index.js",
|
|
24
24
|
"types": "./dist/index.d.ts",
|
|
25
25
|
"files": [
|
|
26
|
-
"
|
|
26
|
+
"assets",
|
|
27
|
+
"dist",
|
|
28
|
+
"THIRD_PARTY_NOTICES.md"
|
|
27
29
|
],
|
|
28
30
|
"exports": {
|
|
29
31
|
".": {
|
|
@@ -38,12 +40,12 @@
|
|
|
38
40
|
"dependencies": {
|
|
39
41
|
"@mapbox/vector-tile": "2.0.5",
|
|
40
42
|
"@maplibre/maplibre-gl-style-spec": "24.8.5",
|
|
43
|
+
"@tileflow/core": ">=0.1.0-alpha.19 <0.1.0-beta.0",
|
|
41
44
|
"chokidar": "4.0.3",
|
|
42
45
|
"jiti": "^2.7.0",
|
|
43
46
|
"maplibre-gl": "5.24.0",
|
|
44
47
|
"pbf": "4.0.2",
|
|
45
|
-
"saxes": "6.0.0"
|
|
46
|
-
"@tileflow/core": "0.1.0-alpha.16"
|
|
48
|
+
"saxes": "6.0.0"
|
|
47
49
|
},
|
|
48
50
|
"optionalDependencies": {
|
|
49
51
|
"sharp": "0.35.3"
|