{"id":51200319,"url":"https://github.com/softwarity/sigmet-draw","last_synced_at":"2026-06-28T00:01:32.519Z","repository":{"id":362262878,"uuid":"1257983642","full_name":"softwarity/sigmet-draw","owner":"softwarity","description":"Draw \u0026 edit ICAO SIGMET hazard areas on a map (MapLibre / OpenLayers / Leaflet).","archived":false,"fork":false,"pushed_at":"2026-06-19T06:34:34.000Z","size":7349,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-19T08:26:01.475Z","etag":null,"topics":["aviation","draw-adapter","fir","icao","leaflet","map","maplibre","openlayers","opmet","sigmet","typescript","weather","wmo"],"latest_commit_sha":null,"homepage":"https://softwarity.github.io/sigmet-draw/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/softwarity.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-03T07:11:42.000Z","updated_at":"2026-06-19T06:34:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/softwarity/sigmet-draw","commit_stats":null,"previous_names":["softwarity/sigmet-draw"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/softwarity/sigmet-draw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwarity%2Fsigmet-draw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwarity%2Fsigmet-draw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwarity%2Fsigmet-draw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwarity%2Fsigmet-draw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/softwarity","download_url":"https://codeload.github.com/softwarity/sigmet-draw/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwarity%2Fsigmet-draw/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34872279,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aviation","draw-adapter","fir","icao","leaflet","map","maplibre","openlayers","opmet","sigmet","typescript","weather","wmo"],"created_at":"2026-06-28T00:01:32.014Z","updated_at":"2026-06-28T00:01:32.510Z","avatar_url":"https://github.com/softwarity.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @softwarity/sigmet-draw\n\n[![npm version](https://img.shields.io/npm/v/@softwarity/sigmet-draw.svg)](https://www.npmjs.com/package/@softwarity/sigmet-draw)\n[![unpacked size](https://img.shields.io/npm/unpacked-size/@softwarity/sigmet-draw)](https://www.npmjs.com/package/@softwarity/sigmet-draw?activeTab=code)\n\n**Works with** \u0026nbsp;\u003csub\u003e(via \u003ccode\u003e@softwarity/draw-adapter\u003c/code\u003e)\u003c/sub\u003e\n\n\u003cp align=\"left\"\u003e\n  \u003ca href=\"https://maplibre.org/\" title=\"MapLibre\"\u003e\u003cimg src=\"demo/src/assets/logos/maplibre.svg\" alt=\"MapLibre\" height=\"24\"\u003e\u003c/a\u003e\n  \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"https://openlayers.org/\" title=\"OpenLayers\"\u003e\u003cimg src=\"demo/src/assets/logos/openlayers.svg\" alt=\"\" height=\"22\"\u003e\u0026nbsp;\u003cb\u003eOpenLayers\u003c/b\u003e\u003c/a\u003e\n  \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n  \u003ca href=\"https://leafletjs.com/\" title=\"Leaflet\"\u003e\u003cimg src=\"demo/src/assets/logos/leaflet.png\" alt=\"Leaflet\" height=\"26\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nDraw **SIGMET/AIRMET geometries** on a map and (de)serialize them to/from\n**ICAO/WMO TAC** (the coded text form, WMO-No.49 Vol II, App. 6).\n\nIt is a **headless library that grafts onto your map** — like Terra Draw. You\nbring a MapLibre, OpenLayers **or** Leaflet map (basemap, controls, projection\nare yours); the library adds the SIGMET drawing on top through a thin adapter, exposes\nimperative tools (`circle()`, `meridian()`, …) and a `change` event, and never\ndepends on a concrete map engine.\n\nThe user picks a tool, a default geometry is **dropped** on the map, and they\njust drag the handles — there is no freehand drawing. Each shape is clipped to\nthe FIR and its TAC is produced live.\n\n## The 12 geometry templates\n\nEach form is **parametric** (a few parameters + handles); the displayed area is\n*derived* and clipped to the FIR, and the TAC is *serialized* from the parameters.\n\n| # | Kind | TAC form | Handles |\n|---|------|----------|---------|\n| 1 | `meridian` | `E OF W012` | vertical line, pick side (E/W) |\n| 2 | `parallel` | `N OF N54` | horizontal line, pick side (N/S) |\n| 3 | `lineSide` | `SW OF LINE p1 - p2 [- p3 - p4]` | oblique line (2–4 pts, ends snap to the FIR border), pick side |\n| 4 | `latBand` | `N OF S50 AND S OF N54` | two horizontal lines |\n| 5 | `lonBand` | `E OF W012 AND W OF E005` | two vertical lines |\n| 6 | `corridor` | `… OF LINE … AND … OF LINE …` | two oblique lines, area between |\n| 7 | `quadrant` | `N OF N54 AND E OF W012` | a corner, click to pick the quadrant |\n| 8 | `polygon` | `WI p1 - p2 - … - pn` | polygon vertices |\n| 9 | `circle` | `WI 250NM OF PSN N2706 W07306` | centre + radius handle |\n| 9b | `tropicalCyclone(center)` | `WI 250NM OF TC CENTRE` | **fixed** centre (caller-provided) + radius handle |\n| 10 | `wideLine` | `APRX 50KM WID LINE BTN p1 - p2 [- p3 - p4]` | polyline (2–4 pts) + width handle |\n| 11 | `entireFir` | `ENTIRE FIR` | — |\n| 12 | `point` | `N48 E010` | single marker (constrained to the FIR) |\n\nLines/polygons drop their interior points **collinear** with their neighbours\nfrom the result (and grey them out); line endpoints snap to the FIR boundary;\ndragging a vertex near collinearity snaps it onto the line.\n\n**Rigid line drag** — dragging the *body* of a `lineSide` / `corridor` line normally\nlets it flex: each endpoint snaps to the *nearest* border point, which bends the end\nsegments. Hold **Ctrl** (⌘ on Mac) to keep the line's **direction frozen** instead —\nthe interior stays rigid and each endpoint keeps following the FIR border by stretching\nits end segment (only the length adapts, not the angle).\n\n**Radius/width units** follow the 2-digit/3-digit TAC rule: KM up to the cap,\nthen NM (physically larger), capped — circle/wide-line `0…99`, tropical cyclone\n`0…999`. Pass `nauticalMilesOnly: true` to always emit NM. The tropical-cyclone\ncentre is **not** part of the TAC (it lives in the TC SIGMET's `PSN` element), so\n`fromTAC(\"WI 250NM OF TC CENTRE\")` returns the geometry with a placeholder centre\nthat `SigmetDraw` resolves to the FIR centroid for display.\n\n## Usage\n\n### Headless graft (the primary API)\n\n```ts\nimport { Map } from \"maplibre-gl\";\nimport { SigmetDraw, MapLibreAdapter } from \"@softwarity/sigmet-draw\";\n\nconst map = new Map({ container: \"map\", style, center, zoom }); // YOUR map\nconst sigmet = new SigmetDraw({\n  adapter: new MapLibreAdapter({ map }),\n  fir,                                   // GeoJSON Polygon/MultiPolygon — required\n  label: (r) =\u003e r.tac,                   // optional on-shape text (omit for none)\n  tooltip: (r) =\u003e r.tac,                 // optional floating tooltip on hover\n  nauticalMilesOnly: false,              // optional — never emit KM when true\n  toolbar: { position: \"top-left\" },     // optional turnkey toolbar (see below)\n  style: { area: { fill: \"#e11d48\", opacity: 0.3 } }, // optional, see below\n});\n\nsigmet.on(\"tac\", (tac) =\u003e console.log(tac));                    // just the TAC — common case\nsigmet.on(\"change\", ({ geometry, tac, area }) =\u003e { /* full result */ });\n\ncircleBtn.onclick   = () =\u003e sigmet.circle();   // wire YOUR buttons\nmeridianBtn.onclick = () =\u003e sigmet.meridian();\nclearBtn.onclick    = () =\u003e sigmet.clear();\n```\n\nOpenLayers is identical with `new OpenLayersAdapter({ map })` (an `ol/Map`), and\nLeaflet with `new LeafletAdapter({ map })` (an `L.Map`, from\n`@softwarity/sigmet-draw/leaflet`). The consumer loads the engine's stylesheet\n(`maplibre-gl/dist/maplibre-gl.css`, `ol/ol.css`, or `leaflet/dist/leaflet.css`).\nEach engine is an **optional** `peerDependency` — install only the one(s) you use.\nEngine capabilities differ: globe is MapLibre-only (OpenLayers \u0026 Leaflet are 2D).\n\n`SigmetDraw` methods: `circle()`, `tropicalCyclone(center)`, `meridian()`, `parallel()`,\n`latBand()`, `lonBand()`, `quadrant()`, `lineSide()`, `corridor()`, `polygon()`,\n`wideLine()`, `point()`, `entireFir()`, `clear()`, plus `on/off(\"change\"|\"tac\", cb)`,\n`load(geometry)`, `setFir(fir)`, `firBounds()`, `firCenter()`, `setStyle(…)`,\n`setLabel(fn)`, `setTooltip(fn)`, `setReadonly(bool)`/`isReadonly`,\n`setSelected(bool)`/`isSelected`, `snapshot(opts?)`, `ready()`, `destroy()`, and\nthe `toolbar` controller (when the `toolbar` option is enabled). See the full\nreference below.\n\n### Turnkey toolbar (batteries-included)\n\nInstead of wiring your own buttons, enable the built-in toolbar **in the options**\n(native control group, built-in icons, every tool wired):\n\n```ts\nconst sigmet = new SigmetDraw({\n  adapter, fir,\n  toolbar: {                                       // presence renders the toolbar\n    position: \"top-left\",                          // see the 12 positions below\n    padding: { top: \"12px\", left: \"8px\" },         // CSS length, or per-side\n    gap: \"2px\",                                     // spacing between buttons (flow is derived from position)\n    className: \"my-toolbar\",                        // extra class for your CSS\n    tools: [\"circle\", \"tropicalCyclone\", \"polygon\"],// pick/order (default: all)\n    clear: true,                                    // include the clear button\n    snapshot: { quality: \"native\", onClick: \"download\", shutter: true }, // 📷 button. quality: native|low|medium|high;\n                                                    // onClick: download|clipboard (⌘/Ctrl-click does the other); shutter:false → no capture flash.\n                                                    // \"none\"/false hides it; disabled on Leaflet.\n    lock: true,                                     // 🔒 \"lock map\" button (freezes pan/zoom while drawing); false hides it\n    tcCenter: null,                                 // see below\n  },\n});\n```\n\n**Positions** — the first token is the anchored edge (which also sets the bar's\nflow: `top`/`bottom` ⇒ horizontal, `left`/`right` ⇒ vertical); a bare edge\nis centred along it:\n\n```\ntop         top-left     top-right\nbottom      bottom-left  bottom-right\nleft        left-top     left-bottom\nright       right-top    right-bottom\n```\n\n**Padding** is a CSS length applied to the anchored edge(s), or a per-side object\n`{ top?, right?, bottom?, left? }`.\n\nThe **🔒 lock-map** button (`lock`, default on) and the **📷 snapshot** button sit at\nthe end of the bar; set `lock: false` to hide the lock button.\n\nThen tweak it **live** through `sigmet.toolbar`:\n\n```ts\nsigmet.toolbar.tcCenter = { lat, lon };          // enable the TC button (real TC position)\nsigmet.toolbar.tcCenter = null;                  // grey it out again\nsigmet.toolbar.position = \"right\";               // re-place on the fly (vertical bar)\nsigmet.toolbar.padding  = { top: \"20px\", left: \"12px\" };\n```\n\nThe **tropical-cyclone button is disabled until `tcCenter` is set** — it needs a\ncentre, and there is no sensible default (a real host has the TC position; the\ndemo uses the FIR centroid). The buttons live inside the engine's **native control\ngroup** (`maplibregl-ctrl-group` / `ol-control`), so they automatically inherit\nthe host engine's native button look; the library only ensures the SVG icons are\ncentred and visible. Override anything via the `.sigmet-toolbar` class (or your\n`className`). Prefer full control? Build your own `ToolbarItem[]` and call\n`adapter.addToolbar(items, options)` directly — `DEFAULT_TOOLS` and `TOOL_ICONS`\nare exported.\n\n### Styling \u0026 dynamic label\n\nOne engine-agnostic `SigmetStyle` (baked into the data by `decorate`, rendered\nidentically on MapLibre / OpenLayers / Leaflet). Override only what you want, at construction (`style`) or\nlive (`setStyle`). A dynamic `label` prints text **on** the shape; a `tooltip`\nshows a floating box **on hover** over it — both are `(result) =\u003e string`.\n\n```ts\nsigmet.setStyle({\n  area: { fill: \"#e11d48\", opacity: 0.3, stroke: \"#e11d48\", width: 2 },\n  lineHandle: { stroke: \"#22d3ee\", width: 3 },        // draggable meridian/parallel lines\n  iconHandle: { fill: \"#fff\", stroke: \"#22d3ee\" },    // all dot handles + glyphs (glyph colour = stroke)\n  label: { color: \"#fff\", halo: \"#0b1622\", size: 13, width: 180 }, // width = max px → wraps\n  tooltip: { color: \"#e6edf3\", background: \"#0b1622\", size: 12 },\n});\nsigmet.setLabel((r) =\u003e r.geometry.kind);   // on-shape text (null to hide)\nsigmet.setTooltip((r) =\u003e r.tac);           // hover tooltip (null to hide)\n```\n\nTokens: `area`, `iconHandle` (dots: vertices + move/resize/transform/radius),\n`lineHandle` (the draggable meridian/parallel lines), `label`, `tooltip`. Collinear\n(TAC-redundant) vertices are **always greyed** and not configurable. See\n`DEFAULT_STYLE` / `mergeStyle`.\n\n### Core only (no map)\n\n```ts\nimport { toTAC, fromTAC, toArea } from \"@softwarity/sigmet-draw/core\";\n\nconst g = fromTAC(\"WI 250NM OF PSN N2706 W07306\");\ntoTAC(g);                          // \"WI 250NM OF PSN N2706 W07306\"\ntoTAC(g, { minutes: \"always\" });   // pad whole-degree minutes (N5400)\ntoArea(g, { fir });                // GeoJSON Feature, clipped to the FIR\n```\n\n## Reference\n\n### `new SigmetDraw(options)`\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `adapter` | `MapAdapter` | — | Wraps your map (`new MapLibreAdapter({ map })` / `new OpenLayersAdapter({ map })`). **Required.** |\n| `fir` | `Feature \\| Polygon \\| MultiPolygon` | — | FIR polygon for clipping/constraints/snapping. **Required.** |\n| `label` | `(r: SigmetResult) =\u003e string` | — | On-shape text (return `\"\"` to hide). |\n| `tooltip` | `(r: SigmetResult) =\u003e string` | — | Floating text on hover over the geometry. |\n| `nauticalMilesOnly` | `boolean` | `false` | Force NM for radii/widths (never emit KM). |\n| `toolbar` | `boolean \\| ToolbarConfig` | — | Render the turnkey toolbar (see below). |\n| `style` | `SigmetStyleInput` | — | Partial style override (merged onto `DEFAULT_STYLE`). |\n\n### Events — `on(event, cb)` / `off(event, cb)`\n\n| Event | Callback | Fires |\n|-------|----------|-------|\n| `\"tac\"` | `(tac: string) =\u003e void` | on every placement/edit — **the common case** |\n| `\"change\"` | `(r: SigmetResult) =\u003e void` | same, with the full result `{ geometry, tac, area }` |\n\n### Methods\n\n`circle()`, `tropicalCyclone(center)`, `meridian()`, `parallel()`, `latBand()`,\n`lonBand()`, `quadrant()`, `lineSide()`, `corridor()`, `polygon()`, `wideLine()`,\n`point()`, `entireFir()` · `clear()` · `load(geometry)` · `setFir(fir)` ·\n`firBounds()` → `[minLon,minLat,maxLon,maxLat]` · `firCenter()` → `LatLng` ·\n`setStyle(partial)` · `setLabel(fn|null)` · `setTooltip(fn|null)` ·\n`setReadonly(bool)` / `isReadonly` (read-only mode — hides handles + toolbar,\nfreezes editing; area + label stay) ·\n`setSelected(bool)` / `isSelected` (deselect to hide the editing handles/guides\nfor a clean view — area + label only, e.g. before a snapshot — while staying\neditable: clicking the shape re-selects it, clicking the empty map deselects it) ·\n`snapshot(opts?)` → `Promise\u003cBlob\u003e` (PNG of the current map — basemap + drawing;\nthe editing chrome (handles/guides) is hidden for the capture. `opts.scale` =\noutput pixel-ratio, default the screen's; `opts.target` = `download`/`clipboard`/`blob`;\n`opts.hideOverlays` overrides what's hidden. MapLibre \u0026 OpenLayers only; rejects on Leaflet) ·\n`ready(): Promise` · `destroy()` · `toolbar` (the controller, see below).\n\n### `SigmetStyle` tokens\n\n| Token | Fields |\n|-------|--------|\n| `area` | `fill`, `stroke`, `width`, `opacity` |\n| `iconHandle` | `fill`, `stroke`, `width`, `radius` |\n| `lineHandle` | `stroke`, `width` |\n| `label` | `color`, `halo`, `size`, `width` *(width = max px before wrapping; halo thickness derived from size)* |\n| `tooltip` | `color`, `background`, `size` |\n\nAll grab handles (vertices, move / resize / transform / radius) share `iconHandle`; the move/resize dot is rendered smaller and the chevron/rotate glyphs are coloured from `iconHandle.stroke` (recoloured live on `setStyle`). **Collinear (TAC-redundant) vertices are always shown as a smaller, stroke-less grey dot** — that state isn't styleable.\n\nHelpers: `DEFAULT_STYLE`, `mergeStyle(base, partial)`, `rgba(hex, opacity)`.\n\n### `ToolbarConfig` / `sigmet.toolbar`\n\nConfig (construction): `position` (12 values, see above — the bar's flow is derived\nfrom it), `padding` (`string | { top?, right?, bottom?, left? }`), `gap`, `className`,\n`tools` (`ToolName[]`), `clear` (`boolean`), `snapshot`, `lock` (`boolean`, the 🔒\n\"lock map\" button — default on), `tcCenter` (`LatLng | null`).\nLive via `sigmet.toolbar`: `tcCenter` (set to enable the TC button / `null` to grey\nit out), `position`, `padding`, `gap`. Build a fully custom toolbar with\n`adapter.addToolbar(items, options)` + the exported `DEFAULT_TOOLS` / `TOOL_ICONS`.\n\n## Architecture\n\nOne repo, **one npm package** (built with `tsc`), plus a standalone **Angular\ndemo** in `demo/` (deployed to GitHub Pages). The map engine is confined to the\nadapters; everything above is agnostic.\n\nThe per-engine map adapters live in the shared **[`@softwarity/draw-adapter`](https://www.npmjs.com/package/@softwarity/draw-adapter)**\npackage (generic, data-driven, reused across the @softwarity drawing libs). The\nadapters here are thin wrappers that pre-bind the SIGMET layer manifest; styling\nis carried by the feature data (`style-features.ts`/`decorate`), so the adapter\nnever sees a domain type.\n\n```\nsrc/\n  core/                pure logic — 12 templates, TAC ↔ params, area (turf) — no map dep\n  map/\n    adapter.ts         back-compat shim → @softwarity/draw-adapter types\n    maplibre-adapter.ts   MapLibreAdapter({ map })   + createMapLibreMap   (thin wrapper)\n    openlayers-adapter.ts OpenLayersAdapter({ map }) + createOpenLayersMap (thin wrapper)\n    leaflet-adapter.ts    LeafletAdapter({ map })    + createLeafletMap    (thin wrapper)\n    style-features.ts  SIGMET_LAYERS / SIGMET_HIT + decorate() (bakes SigmetStyle into data)\n    sigmet-draw.ts     SigmetDraw — the engine-agnostic drawing logic\n    style.ts           SigmetStyle spec + DEFAULT_STYLE / mergeStyle\n    tools.ts           DEFAULT_TOOLS + TOOL_ICONS (turnkey toolbar)\n    geometry.ts        pure helpers (collapse, snap, radius/width units)\ntest/                  vitest (core + geometry/style helpers + controller harness)\ndemo/                  Angular demo: graft on all three engines, FIR selector grouped\n                       by geometry (antimeridian, poles, equator, huge, …), live\n                       style editor, turnkey toolbar\n```\n\nPackage exports: `.` (all), `./core` (pure logic), `./maplibre`, `./openlayers`,\n`./leaflet`\n(per-engine adapters, so a consumer pulls only the engine it uses). MapLibre,\nOpenLayers and Leaflet are optional `peerDependencies`; `@softwarity/draw-adapter`\nis a regular dependency (the shared adapter core).\n\n### Notable details\n\n- **FIR is required** — used for clipping, the centre/point-inside-FIR\n  constraint and line-endpoint snapping. The **host** draws the FIR outline on\n  its own map; the library only consumes the polygon.\n- **Antimeridian** — a FIR straddling 180° is detected and handled in an\n  unwrapped longitude frame; TAC is re-normalised to ±180.\n- Geometry via **Turf 7** (`circle`, `buffer`, `intersect`, `booleanPointInPolygon`).\n\n## Development\n\n```bash\nnpm install\nnpm run build            # tsc → dist\nnpm test                 # vitest (core + geometry/style helpers)\n\n# demo (separate Angular app that consumes ../dist):\ncd demo \u0026\u0026 npm install\nnpm run build            # lib first, then…\ncd demo \u0026\u0026 npx ng serve  # dev server\n```\n\n## References\n\n- WMO-No.49 Vol II, Appendix 6 — SIGMET/AIRMET templates \u0026 examples (A6-1/2/3).\n- ICAO Annex 3 / PANS-ABC (Doc 8400) for abbreviations.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftwarity%2Fsigmet-draw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoftwarity%2Fsigmet-draw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftwarity%2Fsigmet-draw/lists"}