krackedmaps 0.1.0 → 0.1.2

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 CHANGED
@@ -5,7 +5,7 @@ Kuala Lumpur, Putrajaya, Labuan) and **159 admin-2 *daerah*** — with **zero ru
5
5
  dependencies**. Use it as a live component, a CLI, an MCP server for Claude, an embeddable
6
6
  iframe, or raw SVG / GeoJSON.
7
7
 
8
- **Customize & export:** https://map.themasterofnone.xyz · **Live demo:** https://map.themasterofnone.xyz/demo.html
8
+ **Customize & export:** https://maps.krackeddevs.com · **Live demo:** https://maps.krackeddevs.com/demo.html
9
9
 
10
10
  Two aligned layers from one shared projection: click a state to **drill in** (carve its
11
11
  districts + info panel); hover a district for its name; press Esc to step back out. East
package/bin/cli.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  STATES, DISTRICTS, PROJECTION, PRESETS,
8
8
  } from "../dist/krackedmaps.esm.js";
9
9
 
10
- const VERSION = "0.1.0";
10
+ const VERSION = "0.1.2";
11
11
  const readGeo = (f) => readFileSync(fileURLToPath(new URL("../dist/" + f, import.meta.url)), "utf8");
12
12
 
13
13
  // crude flag parser → { _: [positional], flag: value | true }
@@ -16,6 +16,8 @@ function parseArgs(argv) {
16
16
  for (let i = 0; i < argv.length; i++) {
17
17
  const a = argv[i];
18
18
  if (a.startsWith("--")) {
19
+ const eq = a.indexOf("=");
20
+ if (eq !== -1) { out[a.slice(2, eq)] = a.slice(eq + 1); continue; } // --flag=value
19
21
  const next = argv[i + 1];
20
22
  if (next !== undefined && !next.startsWith("--")) { out[a.slice(2)] = next; i++; }
21
23
  else out[a.slice(2)] = true;
@@ -25,6 +27,7 @@ function parseArgs(argv) {
25
27
  }
26
28
 
27
29
  function emit(text, args) {
30
+ if (args.out === true) process.stderr.write("krackedmaps: --out needs a filename; writing to stdout\n");
28
31
  if (typeof args.out === "string") {
29
32
  writeFileSync(args.out, text.endsWith("\n") ? text : text + "\n");
30
33
  process.stderr.write(`wrote ${args.out}\n`);
@@ -52,7 +55,7 @@ Commands:
52
55
  mcp start the MCP server (stdio)
53
56
 
54
57
  Themes: ${Object.keys(PRESETS).join(", ")}
55
- Docs: https://map.themasterofnone.xyz`;
58
+ Docs: https://maps.krackeddevs.com`;
56
59
 
57
60
  async function main() {
58
61
  const [cmd, ...rest] = process.argv.slice(2);
package/bin/mcp.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  STATES, DISTRICTS, PROJECTION, PRESETS,
9
9
  } from "../dist/krackedmaps.esm.js";
10
10
 
11
- const VERSION = "0.1.0";
11
+ const VERSION = "0.1.2";
12
12
  const readGeo = (f) => readFileSync(fileURLToPath(new URL("../dist/" + f, import.meta.url)), "utf8");
13
13
  const themeEnum = Object.keys(PRESETS);
14
14
 
@@ -28,7 +28,11 @@ const TOOLS = [
28
28
  { name: "krackedmaps_project",
29
29
  description: "Project a real-world lng/lat to the map's SVG coordinates (pins land exactly).",
30
30
  inputSchema: { type: "object", properties: { lng: { type: "number" }, lat: { type: "number" } }, required: ["lng", "lat"] },
31
- run: (a) => JSON.stringify(project(Number(a.lng), Number(a.lat))) },
31
+ run: (a) => {
32
+ const lng = Number(a.lng), lat = Number(a.lat);
33
+ if (!Number.isFinite(lng) || !Number.isFinite(lat)) throw new Error("project requires numeric lng and lat");
34
+ return JSON.stringify(project(lng, lat));
35
+ } },
32
36
  { name: "krackedmaps_states",
33
37
  description: "List the 16 states/territories (slug, name, type).",
34
38
  inputSchema: { type: "object", properties: {} },
@@ -43,8 +47,8 @@ const TOOLS = [
43
47
  run: (a) => reactComponent(a.theme || "blueprint") },
44
48
  { name: "krackedmaps_embed",
45
49
  description: "An iframe embed snippet for the hosted, interactive map.",
46
- inputSchema: { type: "object", properties: { theme: { type: "string", enum: themeEnum }, districts: { type: "boolean" } } },
47
- run: (a) => embedSnippet({ theme: a.theme || "blueprint", districts: !!a.districts }) },
50
+ inputSchema: { type: "object", properties: { theme: { type: "string", enum: themeEnum }, districts: { type: "boolean" }, labels: { type: "boolean" }, static: { type: "boolean" } } },
51
+ run: (a) => embedSnippet({ theme: a.theme || "blueprint", districts: !!a.districts, labels: !!a.labels, static: !!a.static }) },
48
52
  ];
49
53
 
50
54
  const send = (msg) => process.stdout.write(JSON.stringify(msg) + "\n");
@@ -85,6 +89,7 @@ let buf = "";
85
89
  process.stdin.setEncoding("utf8");
86
90
  process.stdin.on("data", (chunk) => {
87
91
  buf += chunk;
92
+ if (buf.length > 8_000_000) buf = ""; // drop a runaway no-newline stream (memory guard)
88
93
  let nl;
89
94
  while ((nl = buf.indexOf("\n")) >= 0) {
90
95
  const line = buf.slice(0, nl).trim();
package/dist/index.d.ts CHANGED
@@ -44,8 +44,8 @@ export interface MalaysiaMapOptions {
44
44
  meta?: Record<string, StateMeta> | null;
45
45
  /** default choropleth colour ramp */
46
46
  colors?: { from?: string; to?: string };
47
- /** override the info-panel body; return an HTML string */
48
- renderPanel?: (info: Record<string, unknown>) => string;
47
+ /** override the info-panel rows; return [label, value] pairs (Trusted-Types-safe) */
48
+ renderPanel?: (info: Record<string, unknown>) => Array<[string, string]>;
49
49
  }
50
50
 
51
51
  export type EventName = "select" | "hover" | "drill";