{"_id":"@blogmcp/tripmap-core","_rev":"11-33334dd511aa77ed156a5baf0ee05341","name":"@blogmcp/tripmap-core","dist-tags":{"latest":"0.1.9"},"versions":{"0.1.0":{"name":"@blogmcp/tripmap-core","version":"0.1.0","keywords":["maplibre","pmtiles","trip","map","photo"],"license":"MIT","_id":"@blogmcp/tripmap-core@0.1.0","maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"}],"dist":{"shasum":"d191eff184c9108c554f3c5148883714058a5a9b","tarball":"https://registry.npmjs.org/@blogmcp/tripmap-core/-/tripmap-core-0.1.0.tgz","fileCount":42,"integrity":"sha512-XiNJnL6WFinECCZVXwd6t+fkRQt2YpgDm7T2g4x6/Z1pAanQ53JYQ2Y61vF63F7zYwfvQA8NKrZeWH3+SL8cnw==","signatures":[{"sig":"MEQCIFkab6wO4lxV0vMlYLESZYKk7h3v2Hxegdi2SMy7ViNHAiA7r6oUbZwssMQaVMmxEvKoAjnU7tUIHGHA4iT3hJPedg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1159082},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./nodes":{"types":"./dist/nodes.d.ts","import":"./dist/nodes.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"}},"scripts":{"dev":"vite build --watch","test":"vitest run","build":"vite build && tsc -p tsconfig.build.json --emitDeclarationOnly","prebuild":"node scripts/bundle-worker.mjs","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"huararanga","email":"lukas.zubal@gmail.com"},"_npmVersion":"10.9.7","description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","directories":{},"_nodeVersion":"22.22.2","dependencies":{"pmtiles":"^4.0.0","maplibre-gl":"^6.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","vitest":"^3.0.0","esbuild":"^0.24.0","happy-dom":"^17.4.0","typescript":"^5.3.3","@types/node":"^20.10.0","@types/geojson":"^7946.0.14"},"_npmOperationalInternal":{"tmp":"tmp/tripmap-core_0.1.0_1788611727532_0.5392981751593775","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@blogmcp/tripmap-core","version":"0.1.1","keywords":["maplibre","pmtiles","trip","map","photo"],"license":"MIT","_id":"@blogmcp/tripmap-core@0.1.1","maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"},{"name":"blog-mcp-owner","email":"lukerovo@gmail.com"}],"dist":{"shasum":"0b15eb2d6a365989475cba0199819d720de00f9f","tarball":"https://registry.npmjs.org/@blogmcp/tripmap-core/-/tripmap-core-0.1.1.tgz","fileCount":42,"integrity":"sha512-NwHU+Haqlhi3HiPY/SDCGgI5BrF6k7p3C0mxo2K4vcv1sh3Mwl1enaHxZR/9/wRSB4NFs/+RbXxEPdx3oL5aiQ==","signatures":[{"sig":"MEYCIQCjrZgWi31qVdTQVDWWzYRLFfNaQz1b4pIYr5Y6v4ZMhwIhAJAIBHTdlSILNmHxA72aIntpNV9EtmxpDy4thQGFidA3","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1165486},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./nodes":{"types":"./dist/nodes.d.ts","import":"./dist/nodes.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"}},"scripts":{"dev":"vite build --watch","test":"vitest run","build":"vite build && tsc -p tsconfig.build.json --emitDeclarationOnly","prebuild":"node scripts/bundle-worker.mjs","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"huararanga","email":"lukas.zubal@gmail.com"},"_npmVersion":"10.9.7","description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","directories":{},"_nodeVersion":"22.22.2","dependencies":{"pmtiles":"^4.0.0","maplibre-gl":"^6.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","vitest":"^3.0.0","esbuild":"^0.24.0","happy-dom":"^17.4.0","typescript":"^5.3.3","@types/node":"^20.10.0","@types/geojson":"^7946.0.14"},"_npmOperationalInternal":{"tmp":"tmp/tripmap-core_0.1.1_1788674131290_0.6662773242882083","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@blogmcp/tripmap-core","version":"0.1.2","keywords":["maplibre","pmtiles","trip","map","photo"],"license":"MIT","_id":"@blogmcp/tripmap-core@0.1.2","maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"},{"name":"blog-mcp-owner","email":"lukerovo@gmail.com"}],"dist":{"shasum":"8b7eacf838782fc654af1783f3663c4e53f56d28","tarball":"https://registry.npmjs.org/@blogmcp/tripmap-core/-/tripmap-core-0.1.2.tgz","fileCount":55,"integrity":"sha512-DM1s4QfHTR0LgCAuC++Ktq5Fct3DAD+fG/yVLkeKSUZul6EhtQ9STtGaWIL2l5k4bKbvdiKyQGiaCBNK7q1QYA==","signatures":[{"sig":"MEYCIQDAt4g91072xlq8yinWv2FwjkMPZTigIOWBtYxSPXDL7wIhAO0UmQVn8J8KJHC1SjlvxDTT/mvC8CQ9RCjZwvRN1O44","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1246600},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./nodes":{"types":"./dist/nodes.d.ts","import":"./dist/nodes.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"}},"scripts":{"dev":"vite build --watch","test":"vitest run","build":"vite build && tsc -p tsconfig.build.json --emitDeclarationOnly","prebuild":"node scripts/bundle-worker.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","dev:playground":"node scripts/bundle-worker.mjs && vite --config dev/vite.config.ts"},"_npmUser":{"name":"huararanga","email":"lukas.zubal@gmail.com"},"_npmVersion":"10.9.7","description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","directories":{},"_nodeVersion":"22.22.2","dependencies":{"pmtiles":"^4.0.0","maplibre-gl":"^6.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","vitest":"^3.0.0","esbuild":"^0.24.0","happy-dom":"^17.4.0","typescript":"^5.3.3","@types/node":"^20.10.0","@types/geojson":"^7946.0.14"},"_npmOperationalInternal":{"tmp":"tmp/tripmap-core_0.1.2_1788684255044_0.5853801944220982","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@blogmcp/tripmap-core","version":"0.1.3","keywords":["maplibre","pmtiles","trip","map","photo"],"license":"MIT","_id":"@blogmcp/tripmap-core@0.1.3","maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"},{"name":"blog-mcp-owner","email":"lukerovo@gmail.com"}],"dist":{"shasum":"72b40e76dc8bde8978bb5e53eef35164653dc176","tarball":"https://registry.npmjs.org/@blogmcp/tripmap-core/-/tripmap-core-0.1.3.tgz","fileCount":55,"integrity":"sha512-+t/aeGZU6AOyp2v2W0BYXt/oXYBwszJkMRMvo/GupUii2sAiBzUAh/jYfTgySgKnxXtu/r/XiEVy7rFF81Ut8A==","signatures":[{"sig":"MEUCIBwnx1LqR64IY+TPqFjMheFOD/D1vVpPkZt62tCaJxoLAiEAhyGf3aLCAk64lFaL0Sz51R/Dn/I1cVtx8BfR6xhgFjg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1248341},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./nodes":{"types":"./dist/nodes.d.ts","import":"./dist/nodes.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"}},"scripts":{"dev":"vite build --watch","test":"vitest run","build":"vite build && tsc -p tsconfig.build.json --emitDeclarationOnly && node scripts/bundle-hosted-engine.mjs","prebuild":"node scripts/bundle-worker.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","build:hosted":"node scripts/bundle-hosted-engine.mjs","dev:playground":"node scripts/bundle-worker.mjs && vite --config dev/vite.config.ts"},"_npmUser":{"name":"huararanga","email":"lukas.zubal@gmail.com"},"_npmVersion":"10.9.7","description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","directories":{},"_nodeVersion":"22.22.2","dependencies":{"pmtiles":"^4.0.0","maplibre-gl":"^6.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","vitest":"^3.0.0","esbuild":"^0.24.0","happy-dom":"^17.4.0","typescript":"^5.3.3","@types/node":"^20.10.0","@types/geojson":"^7946.0.14"},"_npmOperationalInternal":{"tmp":"tmp/tripmap-core_0.1.3_1788762643048_0.8695217723423756","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@blogmcp/tripmap-core","version":"0.1.4","keywords":["maplibre","pmtiles","trip","map","photo"],"license":"MIT","_id":"@blogmcp/tripmap-core@0.1.4","maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"},{"name":"blog-mcp-owner","email":"lukerovo@gmail.com"}],"dist":{"shasum":"577530fd0e371d00a0854470fb101dd853627401","tarball":"https://registry.npmjs.org/@blogmcp/tripmap-core/-/tripmap-core-0.1.4.tgz","fileCount":55,"integrity":"sha512-rSJew3y1uor+XCexQgg0KMdu/7mzLpXcACrGG5aMqjTJTuBQAL51PSvVVJwpaR3pBD1Mz69sag5rMfPNEdAJzQ==","signatures":[{"sig":"MEQCIEyc0+ITt8DFAkGpLxF4BFfsU4GL/r9/GFNLAHPxR+xfAiBIZjY9Tjxkh0XafwCGff5uO0eKxAzw3R0S1n2CoPxL/w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1250713},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./nodes":{"types":"./dist/nodes.d.ts","import":"./dist/nodes.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"}},"scripts":{"dev":"vite build --watch","test":"vitest run","build":"vite build && tsc -p tsconfig.build.json --emitDeclarationOnly && node scripts/bundle-hosted-engine.mjs","prebuild":"node scripts/bundle-worker.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","build:hosted":"node scripts/bundle-hosted-engine.mjs","dev:playground":"node scripts/bundle-worker.mjs && vite --config dev/vite.config.ts"},"_npmUser":{"name":"huararanga","email":"lukas.zubal@gmail.com"},"_npmVersion":"10.9.7","description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","directories":{},"_nodeVersion":"22.22.2","dependencies":{"pmtiles":"^4.0.0","maplibre-gl":"^6.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","vitest":"^3.0.0","esbuild":"^0.24.0","happy-dom":"^17.4.0","typescript":"^5.3.3","@types/node":"^20.10.0","@types/geojson":"^7946.0.14"},"_npmOperationalInternal":{"tmp":"tmp/tripmap-core_0.1.4_1788763562663_0.7636342553379893","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@blogmcp/tripmap-core","version":"0.1.5","keywords":["maplibre","pmtiles","trip","map","photo"],"license":"MIT","_id":"@blogmcp/tripmap-core@0.1.5","maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"},{"name":"blog-mcp-owner","email":"lukerovo@gmail.com"}],"dist":{"shasum":"70db64fb4f62e8b854f58be4b959f962b101c16f","tarball":"https://registry.npmjs.org/@blogmcp/tripmap-core/-/tripmap-core-0.1.5.tgz","fileCount":55,"integrity":"sha512-Vb1TMxeSY2i5Wwbwhpe0omlB9D8CYfSzATi6+ZlFGCUou88/azeqr55MhwOpT0ouqqjHKqmzWJeeD/MAKbF/2Q==","signatures":[{"sig":"MEQCICO5MQb9UXFnMD1L5TVeD+0RwopM0+DsXXcPPlPbiR1WAiAVlb1vbb+bUr2q3p8kB/b0MQ3z+jm2Pzf0mdlCBwXK9Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1252554},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./nodes":{"types":"./dist/nodes.d.ts","import":"./dist/nodes.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"}},"scripts":{"dev":"vite build --watch","test":"vitest run","build":"vite build && tsc -p tsconfig.build.json --emitDeclarationOnly && node scripts/bundle-hosted-engine.mjs","prebuild":"node scripts/bundle-worker.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","build:hosted":"node scripts/bundle-hosted-engine.mjs","dev:playground":"node scripts/bundle-worker.mjs && vite --config dev/vite.config.ts"},"_npmUser":{"name":"huararanga","email":"lukas.zubal@gmail.com"},"_npmVersion":"10.9.7","description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","directories":{},"_nodeVersion":"22.22.2","dependencies":{"pmtiles":"^4.0.0","maplibre-gl":"^6.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","vitest":"^3.0.0","esbuild":"^0.24.0","happy-dom":"^17.4.0","typescript":"^5.3.3","@types/node":"^20.10.0","@types/geojson":"^7946.0.14"},"_npmOperationalInternal":{"tmp":"tmp/tripmap-core_0.1.5_1788781221684_0.3448375960390522","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@blogmcp/tripmap-core","version":"0.1.6","keywords":["maplibre","pmtiles","trip","map","photo"],"license":"MIT","_id":"@blogmcp/tripmap-core@0.1.6","maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"},{"name":"blog-mcp-owner","email":"lukerovo@gmail.com"}],"dist":{"shasum":"49c85ecfd566e5d6a495e5bece2821d3a65ad286","tarball":"https://registry.npmjs.org/@blogmcp/tripmap-core/-/tripmap-core-0.1.6.tgz","fileCount":55,"integrity":"sha512-XhUFLouzrXBjY1m4LN5Z9AmGrri1a3wUWPc/xwS4MpEHHofbMFdEj0+Md/xWMknLpZcqJFq9hHATm1S3BDP6Cg==","signatures":[{"sig":"MEYCIQDpZ9WgGxNqUR4matRRzGcnAAr6XGg4cQ5R1JR8F/oaGwIhAOX4TsgTIOjKnJaxr2OUt9Mhj6kzYT/7qB2NFsulJNJy","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1263226},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./nodes":{"types":"./dist/nodes.d.ts","import":"./dist/nodes.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"}},"scripts":{"dev":"vite build --watch","test":"vitest run","build":"vite build && tsc -p tsconfig.build.json --emitDeclarationOnly && node scripts/bundle-hosted-engine.mjs","prebuild":"node scripts/bundle-worker.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","build:hosted":"node scripts/bundle-hosted-engine.mjs","dev:playground":"node scripts/bundle-worker.mjs && vite --config dev/vite.config.ts"},"_npmUser":{"name":"huararanga","email":"lukas.zubal@gmail.com"},"_npmVersion":"10.9.7","description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","directories":{},"_nodeVersion":"22.22.2","dependencies":{"pmtiles":"^4.0.0","maplibre-gl":"^6.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","vitest":"^3.0.0","esbuild":"^0.24.0","happy-dom":"^17.4.0","typescript":"^5.3.3","@types/node":"^20.10.0","@types/geojson":"^7946.0.14"},"_npmOperationalInternal":{"tmp":"tmp/tripmap-core_0.1.6_1789015718992_0.6109336431967114","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"@blogmcp/tripmap-core","version":"0.1.7","keywords":["maplibre","pmtiles","trip","map","photo"],"license":"MIT","_id":"@blogmcp/tripmap-core@0.1.7","maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"},{"name":"blog-mcp-owner","email":"lukerovo@gmail.com"}],"dist":{"shasum":"ad4e239539695a07b2950052e6e3a6924db7bcaa","tarball":"https://registry.npmjs.org/@blogmcp/tripmap-core/-/tripmap-core-0.1.7.tgz","fileCount":58,"integrity":"sha512-ivBiF0kfEmyh2I1LN3rYgdoppKJQTyI0SLKGy+XFPm79+XTeor5PK42b7j7V1OZ0UU+LyZILxQ0sSRguGR3+hg==","signatures":[{"sig":"MEQCIC3puGpdQY9LRQ9GDZh0Qo8csYRAex0ok7xCEt2UZonrAiBaj5rVTFmJIicDqUxOlaYvbtiuNBxnooMrkGKgF7vW7g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1272700},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./nodes":{"types":"./dist/nodes.d.ts","import":"./dist/nodes.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"}},"scripts":{"dev":"vite build --watch","test":"vitest run","build":"vite build && tsc -p tsconfig.build.json --emitDeclarationOnly && node scripts/bundle-hosted-engine.mjs","prebuild":"node scripts/bundle-worker.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","build:hosted":"node scripts/bundle-hosted-engine.mjs","dev:playground":"node scripts/bundle-worker.mjs && vite --config dev/vite.config.ts"},"_npmUser":{"name":"huararanga","email":"lukas.zubal@gmail.com"},"_npmVersion":"10.9.7","description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","directories":{},"_nodeVersion":"22.22.2","dependencies":{"pmtiles":"^4.0.0","maplibre-gl":"^6.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","vitest":"^3.0.0","esbuild":"^0.24.0","happy-dom":"^17.4.0","typescript":"^5.3.3","@types/node":"^20.10.0","@types/geojson":"^7946.0.14"},"_npmOperationalInternal":{"tmp":"tmp/tripmap-core_0.1.7_1789016858740_0.7486885792830842","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@blogmcp/tripmap-core","version":"0.1.8","keywords":["maplibre","pmtiles","trip","map","photo"],"license":"MIT","_id":"@blogmcp/tripmap-core@0.1.8","maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"},{"name":"blog-mcp-owner","email":"lukerovo@gmail.com"}],"dist":{"shasum":"1ad0716d65e9f142533e2010bd6148ff1afd23a8","tarball":"https://registry.npmjs.org/@blogmcp/tripmap-core/-/tripmap-core-0.1.8.tgz","fileCount":58,"integrity":"sha512-1b3fatZ9otWWW1aO/UZnfScl1xFPSPTQ1qRdlUJuhAhB2nRL55kwQ12aJVYVqSRDebZB7L89JEJvXooYSiQK/A==","signatures":[{"sig":"MEUCIQCZcwFVljv1eShFJz11EG8Sm6slmsep3N2xtclm0oYuNwIgZH1A5aBnuQCZXdVJPvFxCEW9uSWRUFkGaC9XUqZendM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1273240},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./nodes":{"types":"./dist/nodes.d.ts","import":"./dist/nodes.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"}},"scripts":{"dev":"vite build --watch","test":"vitest run","build":"vite build && tsc -p tsconfig.build.json --emitDeclarationOnly && node scripts/bundle-hosted-engine.mjs","prebuild":"node scripts/bundle-worker.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","build:hosted":"node scripts/bundle-hosted-engine.mjs","dev:playground":"node scripts/bundle-worker.mjs && vite --config dev/vite.config.ts"},"_npmUser":{"name":"huararanga","email":"lukas.zubal@gmail.com"},"_npmVersion":"10.9.7","description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","directories":{},"_nodeVersion":"22.22.2","dependencies":{"pmtiles":"^4.0.0","maplibre-gl":"^6.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","vitest":"^3.0.0","esbuild":"^0.24.0","happy-dom":"^17.4.0","typescript":"^5.3.3","@types/node":"^20.10.0","@types/geojson":"^7946.0.14"},"_npmOperationalInternal":{"tmp":"tmp/tripmap-core_0.1.8_1789020225322_0.5689109952126263","host":"s3://npm-registry-packages-npm-production"}},"0.1.9":{"_id":"@blogmcp/tripmap-core@0.1.9","dist":{"shasum":"1ad3c267cc96567c40059a68de8ad48085779111","tarball":"https://registry.npmjs.org/@blogmcp/tripmap-core/-/tripmap-core-0.1.9.tgz","fileCount":61,"integrity":"sha512-zppLs7kzcFsVflNLkmi+4YUedKdsFp1RgrxZ3ghK7VutO36TLMtZ4faT3hdb+sCIFSkQWUbOjqAwKYA0KHI6Kg==","signatures":[{"sig":"MEUCIQDZXw2B7e+wiym0nmL/5mCePG0le1yBl0BGz1LK06RQGQIgZYtsNWRvViPcrD0IWveCBusqtJMvIQ2fIeBADEOA2Hk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAYcGMTuX1o7/QCHmpD4Tcu2G6nYBAWKiwmcI/mVnC1OAiBVHqDxbvZAUnRrRWp0PW6WjDq705WuFPN4Xj2zATnBew=="}],"unpackedSize":1324544},"main":"./dist/index.js","name":"@blogmcp/tripmap-core","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./nodes":{"types":"./dist/nodes.d.ts","import":"./dist/nodes.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"}},"gitHead":"3ec0068322e4b9910955af557cf76981e994005e","license":"MIT","scripts":{"dev":"vite build --watch","test":"vitest run","build":"vite build && tsc -p tsconfig.build.json --emitDeclarationOnly && node scripts/bundle-hosted-engine.mjs","prebuild":"node scripts/bundle-worker.mjs","typecheck":"tsc --noEmit","test:watch":"vitest","build:hosted":"node scripts/bundle-hosted-engine.mjs","dev:playground":"node scripts/bundle-worker.mjs && vite --config dev/vite.config.ts"},"version":"0.1.9","_npmUser":{"name":"huararanga","email":"lukas.zubal@gmail.com"},"keywords":["maplibre","pmtiles","trip","map","photo"],"_npmVersion":"10.9.7","description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","directories":{},"maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"},{"name":"blog-mcp-owner","email":"lukerovo@gmail.com"}],"_nodeVersion":"22.22.2","dependencies":{"pmtiles":"^4.0.0","maplibre-gl":"^6.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","vitest":"^3.0.0","esbuild":"^0.24.0","happy-dom":"^17.4.0","typescript":"^5.3.3","@types/node":"^20.10.0","@types/geojson":"^7946.0.14"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tripmap-core_0.1.9_1790702945040_0.13692591042799096"}}},"time":{"created":"2026-09-05T12:35:27.418Z","modified":"2026-09-29T17:29:05.455Z","0.1.0":"2026-09-05T12:35:27.671Z","0.1.1":"2026-09-06T05:55:31.427Z","0.1.2":"2026-09-06T08:44:15.190Z","0.1.3":"2026-09-07T06:30:43.191Z","0.1.4":"2026-09-07T06:46:02.789Z","0.1.5":"2026-09-07T11:40:21.864Z","0.1.6":"2026-09-10T04:48:39.188Z","0.1.7":"2026-09-10T05:07:38.894Z","0.1.8":"2026-09-10T06:03:45.487Z","0.1.9":"2026-09-29T17:29:05.231Z"},"license":"MIT","keywords":["maplibre","pmtiles","trip","map","photo"],"description":"Framework-agnostic MapLibre trip-map engine for the TripMap MDX component. Photo nodes from GPS + capture time: thumbnail markers, clustering, chronological route line, filmstrip, playback. Consumed by @blogmcp/mdx-render-vue, @blogmcp/mdx-render-react an","maintainers":[{"name":"huararanga","email":"lukas.zubal@gmail.com"},{"name":"blog-mcp-owner","email":"lukerovo@gmail.com"}],"readme":"# @blogmcp/tripmap-core\n\nFramework-agnostic MapLibre engine for the **TripMap** MDX component: photo nodes from GPS +\ncapture time → thumbnail markers (clustered), a chronological route line, a synced filmstrip,\nfly-through playback, light/dark styles, and a hard-coded OSM attribution. Consumed through thin\nmount wrappers by `@blogmcp/mdx-render-vue`, `@blogmcp/mdx-render-react` and the drhoubicka\nstorefront — one behaviour surface, three frameworks.\n\n```ts\nimport { TripMap, buildTripNodes } from '@blogmcp/tripmap-core'\n\nconst map = new TripMap(container, {\n  styleUrl,\n  theme: 'auto',\n  title: 'Údolím Libochovky',\n  labels: { play: 'Přehrát trasu', stop: 'Zastavit', fullscreen: 'Celá obrazovka', exitFullscreen: 'Ukončit celou obrazovku', export: 'Export trasy' /* … see TripMapLabels */ },\n})\nmap.setNodes(buildTripNodes(mediaNodes, handNodes))   // buffered until init resolves\nawait map.init()                                       // ← the ONLY place maplibre loads\nmap.setActiveNode('img-a', { fly: true })\nmap.playSequence({ dwellMs: 2000 }).stop()\nmap.destroy()\n```\n\n## No framework required\n\nThe engine is plain TypeScript over the DOM and MapLibre. `new TripMap(el, options)` works in any\npage; the Vue/React packages are thin MDX wrappers around it. With a bundler, import the package;\nwithout one, `https://esm.sh/@blogmcp/tripmap-core` serves it with its dependencies resolved.\n`test/e2e/harness/vanilla.html` in `@blogmcp/mdx-render-vue` is the reference plain page and is\ncovered by `tripmap-vanilla.spec.ts`.\n\n## Module split — the load-bearing design\n\n| File | Imports maplibre? | Purpose |\n|---|---|---|\n| `src/index.ts` | **no** | types, `TripMap` facade (buffers calls until `init()`), `DEFAULT_STYLE_URLS`, pure helpers |\n| `src/nodes.ts` (`./nodes`) | no | `buildTripNodes` merge/sort/dedupe, `captureTimeMs`, `formatTimeHHMM`, `tripSummary`, `safeNodeHref` (from `href.ts`) — safe in SSR code |\n| `src/framing.ts`, `line.ts`, `markers.ts`, `filmstrip.ts`, `playback.ts`, `theme.ts`, `attribution.ts`, `css.ts` | no | testable units (happy-dom) |\n| `src/engine.ts` | **yes — the only one** | reached via `await import('./engine.js')` from the facade |\n\nConsequences a consumer relies on:\n\n- Every bundler emits the engine + maplibre as a **lazy chunk**; the facade is a few KB.\n- The single-file article-review MCP-App externalizes this package: its `import()` rejects in\n  the iframe, the facade's `init()` throws + calls `events.onError`, wrappers keep their static\n  facade. Renderer packages must therefore **never statically import** this package — not even\n  `/nodes` — a top-level bare import breaks that whole bundle at load.\n- **maplibre v6's worker resolution is broken under relocating bundlers** (vite prebundle,\n  Nuxt/Next builds): `new URL('./maplibre-gl-worker.mjs', import.meta.url)` 404s and the map\n  renders its background while no geojson source ever loads (no markers, no line — silently).\n  `scripts/bundle-worker.mjs` esbuild-bundles the worker + its shared module into\n  `src/generated/maplibre-worker.bundle.js` at `prebuild`; `engine.ts` inlines it (`?raw`) and\n  hands maplibre a Blob URL via `setWorkerUrl()`. ~490 kB raw / ~135 kB compressed, in the\n  lazy chunk only. Zero consumer config, works in every environment.\n- The maplibre CSS is inlined the same way (`?raw`) and injected once per document.\n- `vite.config.ts` `external` must stay the two exact specifiers `maplibre-gl` + `pmtiles` —\n  widening to a regex would externalize the `?raw` imports too.\n\n## Engine notes\n\n- **An invisible circle layer anchors the nodes source.** Without any layer referencing it,\n  maplibre never loads the source's tiles and `querySourceFeatures` returns `[]` forever — the\n  HTML-marker pattern needs the anchor (official cluster-HTML example does the same).\n- Markers are HTML `<img>` buttons managed by `MarkerPool` — elements created once per key,\n  diffed on every `idle`/`moveend`/`sourcedata`. Re-creating per update is the PhotoPrism\n  duplicate-listener leak.\n- Clusters: maplibre's supercluster (`clusterRadius` 40, `clusterMaxZoom` 17); cluster markers\n  show the first leaf's thumbnail + a count badge; click → `getClusterExpansionZoom`.\n- Route line: time-sorted LineString, `lineMetrics: true`, `line-gradient` progression.\n- Framing: `computeFramingBounds` drops transit outliers (Polarsteps heuristic: median-distance\n  trim, only when it shrinks the frame by half) — a photo from the train doesn't zoom the walk out.\n- Times are rendered as **HH:MM sliced from the ISO string** (`formatTimeHHMM`), never through\n  `Date` — EXIF capture times are timezone-ambiguous. `showTime: false` hides them everywhere the\n  core renders one (filmstrip bar, popup, detail panel, viewer caption). A time that formats to\n  nothing — hidden, or a `capturedAt` without an ISO clock such as JS `Date#toString` — renders no\n  element and no `·` separator. Ordering, the route line, GPX `<time>` and `tripSummary` read\n  `capturedAt` through one function, `captureTimeMs`: `Date.parse` (ISO with Z or an offset, JS\n  `Date#toString`), except that an ISO date-time **without a zone is read as UTC**, as if it\n  carried the Z the trip convention writes. Left to `Date.parse` it would land in the runtime's\n  zone, and a facade rendered on a UTC server would order the stops differently from the same page\n  in a Prague browser. `tripSummary().dateIso` is the date as written for an ISO value, the UTC day\n  otherwise.\n- **Node data is untrusted author data.** A node's `href` becomes the popup photo's link only when\n  `safeNodeHref` passes it: an `http(s)` URL, or an on-site reference starting `/`, `./`, `../`,\n  `#` or `?` (a `//host` reference, or a backslash variant a browser reads the same way, leaves the\n  site and does not count). Anything else — `javascript:`, `data:`, `vbscript:`, `file:`, `blob:`,\n  `mailto:`, a bare `www.…`, including the case/whitespace/tab/control-character disguises a\n  browser still reads as that scheme — renders as if unset, so the photo opens the viewer instead.\n  `normalizeHandNode` already drops such an `href`, so SSR code holding a hand node never sees it.\n  Every other node string reaches the DOM as text or an attribute value, never as HTML.\n- **Attribution is untrusted HTML too, and the core renders it — never maplibre's\n  `AttributionControl`.** The credit line carries the tenant's `extraAttribution` plus the\n  `attribution` of every source the style draws and of its TileJSON, and the style is a block prop\n  (`styleUrl`): an article author picks where those strings come from. maplibre writes them into\n  `innerHTML` past a sanitizer that removes only `<script>`, `on*` attributes and\n  `javascript:`/`data:` in `src`/`href`, so an `<iframe srcdoc=\"<script>…\">` or a\n  `<form action=\"javascript:…\">` would run on the host page. `TripMapAttributionControl`\n  (`src/attribution.ts`) keeps maplibre's markup, classes, corner and choice of credits but rebuilds\n  each credit from its text and absolute `http(s)` links only (new tab, `rel=\"noopener\"`): every\n  other element becomes its text or nothing, and no other attribute survives. What it cannot stop:\n  a hostile style still has readers' browsers fetch its tiles, sprites and glyphs — limiting\n  `styleUrl` to known map origins is up to the host.\n- Theme swap uses `transformStyle` to carry the `tripmap-*` sources/layers across `setStyle`.\n- `engine._map` (`@internal`) exposes the maplibre Map for e2e/diagnostics only.\n\n## Playback, popups, fullscreen (behaviour worth knowing)\n\n- **Playback preloads.** `playback.ts` calls the driver's `preload(node)` for the first node\n  before its flight and for node *i+1* the moment node *i* is shown; the engine's\n  `ImagePreloader` (`src/preload.ts`, LRU of 4) fetches + decodes the popup image and the popup\n  then mounts that very element, so it paints complete on its first frame regardless of the\n  thumbnail endpoint's cache headers. Popup images load `eager` (never `lazy`).\n- **Popups always fit the map.** Playback flies the node into the upper third (`flyTo` `offset`),\n  the popup image caps at 40 % of the map height and the whole popup at the map height minus\n  its offset (`--tripmap-popup-img-max`, `--tripmap-map-h`, set by the engine on resize; the\n  description scrolls beyond that), and `ensurePopupInView` pans the residual overflow after\n  layout and again after the image arrives. Maplibre alone only flips the anchor near an edge.\n- **Fullscreen** is maplibre's `FullscreenControl` over the whole component (map + filmstrip),\n  on by default (`showFullscreen: false` hides it); the control hides itself where the\n  Fullscreen API is missing (iOS Safari). Labels come from `labels.fullscreen` /\n  `labels.exitFullscreen` via maplibre's `locale`.\n- **Route export** (`showExport`, default on; needs a route of ≥ 2 timed nodes): a menu with\n  *Download GPX* — Web Share with the file where available, so on a phone the sheet opens\n  Garmin Connect / Strava / Komoot / Mapy.com directly, otherwise a plain download — plus\n  *Open in Mapy.com* (`/fnc/v1/route`, lon,lat, ≤ 15 evenly sampled waypoints, `foot_hiking`,\n  opens the app on phones) and *Open in Google Maps* (`/maps/dir/?api=1`, lat,lng, walking,\n  ≤ 3 waypoints on coarse pointers / ≤ 9 otherwise). `title` names the GPX track and file.\n  Pure builders live in `src/export.ts` (`buildGpx`, `mapyRouteUrl`, `googleMapsRouteUrl`). A GPX\n  `<time>` is written only for a `capturedAt` that `Date.parse` reads, normalised to UTC with\n  `toISOString()`; anything else is left out rather than copied verbatim into an invalid file.\n- **Full-screen viewer.** The popup photo (and the panel photo) is a button that opens a\n  lightbox over the whole viewport (`src/lightbox.ts`): `largeImageUrl` → `imageUrl` →\n  `thumbnailUrl`, prev/next through every node with an image (arrow keys, wrap-around,\n  neighbours preloaded), Escape / backdrop / × to close, focus and scroll restored. Mounted inside\n  the fullscreen element when the component is fullscreen, on `<body>` otherwise. Navigating in\n  the viewer keeps the map + filmstrip on the same photo; closing reveals the photo it ended on.\n- **`detail: 'panel'`** shows the selected photo UNDER the filmstrip at component width instead of\n  in a map popup (`src/detail.ts`). Wrappers that box the map in a fixed-height element pass a\n  sibling `detailHost`; without one the panel mounts inside the container, which switches to\n  `height: auto` while the map keeps its designed height. Same lightbox from the panel image.\n- **Cluster click = show me these photos.** Besides zooming in, a cluster click activates the\n  cluster's earliest member, so the filmstrip scrolls to that stretch of the trip.\n- **Marker roots belong to maplibre.** Never set `position`/`transform` (or a transform\n  transition) on `.tripmap-marker*` root selectors — see the comment in `css.ts` and\n  `test/css.spec.ts`; the 2026-09-06 cluster-drift bug was exactly that.\n\n## Playground (fast local iteration)\n\n`npm run dev:playground` serves `dev/` on http://127.0.0.1:5098 — the real engine straight from\n`src/` (HMR) over the real Níhov trip (69 photos, thumbnails from the drhoubicka tenant, tiles\nfrom tiles.blogmcp.ai), with knobs for map height, theme, clustering and page width. Not part of\nthe build, the tests or the published package.\n\n## Observable state (for hosts, CSS and tests)\n\nThe engine mirrors what the DOM cannot otherwise see onto the container: `data-tripmap-nodes`\n(count), `data-tripmap-route` (timed nodes = route points; the play/export controls need ≥ 2),\n`data-tripmap-line` (`true` when the route line layer exists), `data-tripmap-theme`\n(`light`/`dark` as resolved, also after `setTheme`). Filmstrip items are `role=\"option\"` with\n`aria-selected` always present; every marker/control carries an `aria-label`.\n\n## Tests\n\n`npm test` — vitest specs (happy-dom; the facade mocks the engine through `options.engineLoader`;\nmarkers, filmstrip, playback, preload, export, lightbox, detail panel, framing, line, theme,\nattribution, CSS contracts are unit-tested; `test/engine.spec.ts` drives the real engine over a\nfaked maplibre for the DOM it builds, e.g. node clock times with `showTime` and the attribution\nline, under the SSR transform and with the\nprebuild-only worker bundle aliased to a stub — see `vitest.config.ts`). The REAL engine is exercised in Chromium by `@blogmcp/mdx-render-vue`'s\nPlaywright harness — `test/e2e/specs/tripmap.spec.ts` (hand nodes: markers, clusters, popups,\nplayback, fullscreen, export, viewer, panel, keyboard) and `tripmap-api.spec.ts` (the\n`/api/media/geo` modes through the wrapper: AUTO via article context, exclude, slugs, 404, theme,\nline, no-route) and `tripmap-vanilla.spec.ts` (a plain HTML page, no framework) — on a desktop\nproject and a phone project (`Pixel 7`). `@blogmcp/mdx-render-react` has the same harness shape\n(`test/e2e`, port 5097, esbuild JSX). The drhoubicka storefront runs its island in vitest browser\nmode (`TripMapLive.browser.test.tsx`) and has an opt-in check of a deployed page\n(`tests/e2e/tripmap-live.spec.ts`, `E2E_TRIPMAP_URL`). md-editor covers the block round-trip\n(`mdx-block-tripmap.spec.ts`). All hermetic: local empty style, `data:` PNG photos.\n\n## Basemap\n\nDefault style URLs are OpenFreeMap (`https://tiles.openfreemap.org/styles/{liberty,dark}`, public\nand keyless; its TileJSON carries its own credit, shown next to the mandatory OSM notice) — a\nlibrary default has to work for any consumer. The blogmcp platform points tenants at its own `tiles.blogmcp.ai` through the\nstyle-URL chain (kb-api `GET /api/media/geo` `config`) — see\n`competitor-monitor/docs/internal/basemap-tiles.md`. Attribution is not disableable (ODbL).\n","readmeFilename":"README.md"}