@trailstash/ultra
Version:
A web based tool for making MapLibre GL maps with data from sources such as Overpass, GeoJSON, GPX, KML, TCX, etc
73 lines (64 loc) • 1.75 kB
JavaScript
import DOMPurify from "dompurify";
import { Liquid } from "liquidjs";
import { h, t } from "../lib/dom.js";
import { normalizeCSS } from "../lib/normalize.js";
const engine = new Liquid();
const style = new CSSStyleSheet();
style.replaceSync(`
a {
text-decoration: none;
}
h1,h2,h3,h4,h5,h6 {
margin: .5em 0;
}
`);
const defaultTemplate = `
<h3>Properties</h3>
{%- for prop in properties %}
<code>{{ prop[0] }} = {{ prop[1] | json }}</code>
<br>
{%- endfor %}
`;
const defaultContextBuilder = ({ properties, geometry }) => {
const context = { properties: structuredClone(properties) };
if (geometry.type === "Point") context.geometry = geometry;
return context;
};
export class MapPopup extends HTMLElement {
constructor() {
super();
this.template = defaultTemplate;
this.contextBuilder = defaultContextBuilder;
}
connectedCallback() {
const shadow = this.attachShadow({ mode: "open" });
shadow.adoptedStyleSheets.push(normalizeCSS);
shadow.adoptedStyleSheets.push(style);
const div = h("div");
div.style.maxHeight = "1000px";
div.style.overflowY = "auto";
let first = true;
for (const f of Object.values(this.features)) {
if (first) {
first = false;
} else {
div.appendChild(h("hr"));
}
const html = engine.parseAndRenderSync(
this.template,
this.contextBuilder(f),
);
div.appendChild(
h(
"div",
{},
DOMPurify.sanitize(html, {
ALLOWED_URI_REGEXP:
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|geo):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,
}),
),
);
}
shadow.appendChild(div);
}
}