aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Beltran del Rio <jj@r.bdr.sh>2026-01-14 10:03:15 +0100
committerRuben Beltran del Rio <jj@r.bdr.sh>2026-01-14 23:21:34 +0100
commit1e4c4a588b7e00b9bbdd6de6449719e7cdf38a33 (patch)
tree23dabc920832c19014dfa6550db15afced195360
parentf842640e9d0d1c10d2a23fd93929d274ebd86ad1 (diff)
Use SVG rendering1.1.0
-rw-r--r--client/wmap.css4
-rw-r--r--package.json4
-rw-r--r--pnpm-lock.yaml198
-rw-r--r--pnpm-workspace.yaml3
-rw-r--r--src/wmap.js37
5 files changed, 95 insertions, 151 deletions
diff --git a/client/wmap.css b/client/wmap.css
index a524bcb..d5e6598 100644
--- a/client/wmap.css
+++ b/client/wmap.css
@@ -25,3 +25,7 @@
.wmap img {
width: 100%;
}
+
+.wardley-map.thumbnail text:nth-of-type(n + 7) {
+ cursor: pointer;
+}
diff --git a/package.json b/package.json
index ab61c53..4ca0169 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "wiki-plugin-wmap",
- "version": "1.0.1",
+ "version": "1.1.0",
"description": "Federated Wiki - Wmap Plugin",
"keywords": [
"wmap",
@@ -27,7 +27,7 @@
"jsdom": "^27.3.0",
"prettier": "^3.7.4",
"wmap-parser": "^1.0.1",
- "wmap-renderer-canvas": "^1.0.1"
+ "wmap-renderer-svg": "^1.0.0"
},
"license": "AGPL-3.0",
"type": "module",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 036cfd9..662e222 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4,6 +4,10 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
+overrides:
+ wmap-renderer-twojs: link:../../../Library/pnpm/global/5/node_modules/wmap-renderer-twojs
+ wmap-renderer-svg: link:../../../Library/pnpm/global/5/node_modules/wmap-renderer-svg
+
importers:
.:
@@ -35,9 +39,9 @@ importers:
wmap-parser:
specifier: ^1.0.1
version: 1.0.1
- wmap-renderer-canvas:
- specifier: ^1.0.1
- version: 1.0.1
+ wmap-renderer-svg:
+ specifier: link:../../../Library/pnpm/global/5/node_modules/wmap-renderer-svg
+ version: link:../../../Library/pnpm/global/5/node_modules/wmap-renderer-svg
packages:
@@ -295,33 +299,9 @@ packages:
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'}
- '@turf/clone@7.3.1':
- resolution: {integrity: sha512-r7xDOfw9ohA7PhZW+8X9RMsO4szB4YqkhEROaELJyLtQ1bo8VNFtndpZdE6YHQpD7Pjlvlb6i99q8w1QLisEPg==}
-
- '@turf/concave@7.3.1':
- resolution: {integrity: sha512-vZWqyAYH4qzOuiqPb+bj2jvpIGzYAH8byUhfFJ2gRFRL3/RfV8jdXL2r0Y6VFScqE6OLVGvtM3ITzXX1/9wTaA==}
-
- '@turf/distance@7.3.1':
- resolution: {integrity: sha512-DK//doTGgYYjBkcWUywAe7wbZYcdP97hdEJ6rXYVYRoULwGGR3lhY96GNjozg6gaW9q2eSNYnZLpcL5iFVHqgw==}
-
- '@turf/helpers@7.3.1':
- resolution: {integrity: sha512-zkL34JVhi5XhsuMEO0MUTIIFEJ8yiW1InMu4hu/oRqamlY4mMoZql0viEmH6Dafh/p+zOl8OYvMJ3Vm3rFshgg==}
-
- '@turf/invariant@7.3.1':
- resolution: {integrity: sha512-IdZJfDjIDCLH+Gu2yLFoSM7H23sdetIo5t4ET1/25X8gi3GE2XSqbZwaGjuZgNh02nisBewLqNiJs2bo+hrqZA==}
-
- '@turf/meta@7.3.1':
- resolution: {integrity: sha512-NWsfOE5RVtWpLQNkfOF/RrYvLRPwwruxhZUV0UFIzHqfiRJ50aO9Y6uLY4bwCUe2TumLJQSR4yaoA72Rmr2mnQ==}
-
- '@turf/tin@7.3.1':
- resolution: {integrity: sha512-pDtHE8rLXvV4zAC9mWmwToDDda2ZTty8IZqZIoUqTnlf6AJjzF7TJrhoE3a+zukRTUI1wowTFqe2NvwgNX0yew==}
-
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
- '@types/geojson@7946.0.16':
- resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
-
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
@@ -392,9 +372,6 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
- commander@2.20.3:
- resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
-
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
@@ -817,14 +794,6 @@ packages:
resolution: {integrity: sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==}
hasBin: true
- topojson-client@3.1.0:
- resolution: {integrity: sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==}
- hasBin: true
-
- topojson-server@3.0.1:
- resolution: {integrity: sha512-/VS9j/ffKr2XAOjlZ9CgyyeLmgJ9dMwq6Y0YEON8O7p/tGGk+dCWnrE03zEdu7i4L7YsFZLEPZPzCvcB7lEEXw==}
- hasBin: true
-
tough-cookie@6.0.0:
resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==}
engines: {node: '>=16'}
@@ -833,9 +802,6 @@ packages:
resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==}
engines: {node: '>=20'}
- tslib@2.8.1:
- resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
-
tunnel-agent@0.6.0:
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
@@ -877,9 +843,6 @@ packages:
wmap-parser@1.0.1:
resolution: {integrity: sha512-0zscjXgFdaD+56gFksdkfT4HPHfld2LXzGV5CxNUPVsAJWiXdkED0vpc4rIooklOBKoU5GEidKxS4AV1q6lvrw==}
- wmap-renderer-canvas@1.0.1:
- resolution: {integrity: sha512-O51y8cG9FE5htC7D5lrNCCh16rg5fSuez9FTLvnSLkZE1VdQOvCjQDifW8UfCGk7Aq1/91NcuDKXMZRdvHHJOA==}
-
word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
@@ -1089,58 +1052,8 @@ snapshots:
'@humanwhocodes/retry@0.4.3': {}
- '@turf/clone@7.3.1':
- dependencies:
- '@turf/helpers': 7.3.1
- '@types/geojson': 7946.0.16
- tslib: 2.8.1
-
- '@turf/concave@7.3.1':
- dependencies:
- '@turf/clone': 7.3.1
- '@turf/distance': 7.3.1
- '@turf/helpers': 7.3.1
- '@turf/invariant': 7.3.1
- '@turf/meta': 7.3.1
- '@turf/tin': 7.3.1
- '@types/geojson': 7946.0.16
- topojson-client: 3.1.0
- topojson-server: 3.0.1
- tslib: 2.8.1
-
- '@turf/distance@7.3.1':
- dependencies:
- '@turf/helpers': 7.3.1
- '@turf/invariant': 7.3.1
- '@types/geojson': 7946.0.16
- tslib: 2.8.1
-
- '@turf/helpers@7.3.1':
- dependencies:
- '@types/geojson': 7946.0.16
- tslib: 2.8.1
-
- '@turf/invariant@7.3.1':
- dependencies:
- '@turf/helpers': 7.3.1
- '@types/geojson': 7946.0.16
- tslib: 2.8.1
-
- '@turf/meta@7.3.1':
- dependencies:
- '@turf/helpers': 7.3.1
- '@types/geojson': 7946.0.16
-
- '@turf/tin@7.3.1':
- dependencies:
- '@turf/helpers': 7.3.1
- '@types/geojson': 7946.0.16
- tslib: 2.8.1
-
'@types/estree@1.0.8': {}
- '@types/geojson@7946.0.16': {}
-
'@types/json-schema@7.0.15': {}
'@types/trusted-types@2.0.7':
@@ -1169,7 +1082,8 @@ snapshots:
balanced-match@1.0.2: {}
- base64-js@1.5.1: {}
+ base64-js@1.5.1:
+ optional: true
bidi-js@1.0.3:
dependencies:
@@ -1180,6 +1094,7 @@ snapshots:
buffer: 5.7.1
inherits: 2.0.4
readable-stream: 3.6.2
+ optional: true
brace-expansion@1.1.12:
dependencies:
@@ -1190,6 +1105,7 @@ snapshots:
dependencies:
base64-js: 1.5.1
ieee754: 1.2.1
+ optional: true
callsites@3.1.0: {}
@@ -1197,13 +1113,15 @@ snapshots:
dependencies:
node-addon-api: 7.1.1
prebuild-install: 7.1.3
+ optional: true
chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
- chownr@1.1.4: {}
+ chownr@1.1.4:
+ optional: true
color-convert@2.0.1:
dependencies:
@@ -1211,8 +1129,6 @@ snapshots:
color-name@1.1.4: {}
- commander@2.20.3: {}
-
concat-map@0.0.1: {}
cross-spawn@7.0.6:
@@ -1246,12 +1162,15 @@ snapshots:
decompress-response@6.0.0:
dependencies:
mimic-response: 3.1.0
+ optional: true
- deep-extend@0.6.0: {}
+ deep-extend@0.6.0:
+ optional: true
deep-is@0.1.4: {}
- detect-libc@2.1.2: {}
+ detect-libc@2.1.2:
+ optional: true
dompurify@3.3.1:
optionalDependencies:
@@ -1260,6 +1179,7 @@ snapshots:
end-of-stream@1.4.5:
dependencies:
once: 1.4.0
+ optional: true
entities@6.0.1: {}
@@ -1364,7 +1284,8 @@ snapshots:
esutils@2.0.3: {}
- expand-template@2.0.3: {}
+ expand-template@2.0.3:
+ optional: true
fast-deep-equal@3.1.3: {}
@@ -1388,9 +1309,11 @@ snapshots:
flatted@3.3.3: {}
- fs-constants@1.0.0: {}
+ fs-constants@1.0.0:
+ optional: true
- github-from-package@0.0.0: {}
+ github-from-package@0.0.0:
+ optional: true
glob-parent@6.0.2:
dependencies:
@@ -1424,7 +1347,8 @@ snapshots:
dependencies:
safer-buffer: 2.1.2
- ieee754@1.2.1: {}
+ ieee754@1.2.1:
+ optional: true
ignore@5.3.2: {}
@@ -1435,9 +1359,11 @@ snapshots:
imurmurhash@0.1.4: {}
- inherits@2.0.4: {}
+ inherits@2.0.4:
+ optional: true
- ini@1.3.8: {}
+ ini@1.3.8:
+ optional: true
is-extglob@2.1.1: {}
@@ -1517,31 +1443,38 @@ snapshots:
mdn-data@2.12.2: {}
- mimic-response@3.1.0: {}
+ mimic-response@3.1.0:
+ optional: true
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
- minimist@1.2.8: {}
+ minimist@1.2.8:
+ optional: true
- mkdirp-classic@0.5.3: {}
+ mkdirp-classic@0.5.3:
+ optional: true
ms@2.1.3: {}
- napi-build-utils@2.0.0: {}
+ napi-build-utils@2.0.0:
+ optional: true
natural-compare@1.4.0: {}
node-abi@3.85.0:
dependencies:
semver: 7.7.3
+ optional: true
- node-addon-api@7.1.1: {}
+ node-addon-api@7.1.1:
+ optional: true
once@1.4.0:
dependencies:
wrappy: 1.0.2
+ optional: true
optionator@0.9.4:
dependencies:
@@ -1586,6 +1519,7 @@ snapshots:
simple-get: 4.0.1
tar-fs: 2.1.4
tunnel-agent: 0.6.0
+ optional: true
prelude-ls@1.2.1: {}
@@ -1595,6 +1529,7 @@ snapshots:
dependencies:
end-of-stream: 1.4.5
once: 1.4.0
+ optional: true
punycode@2.3.1: {}
@@ -1604,18 +1539,21 @@ snapshots:
ini: 1.3.8
minimist: 1.2.8
strip-json-comments: 2.0.1
+ optional: true
readable-stream@3.6.2:
dependencies:
inherits: 2.0.4
string_decoder: 1.3.0
util-deprecate: 1.0.2
+ optional: true
require-from-string@2.0.2: {}
resolve-from@4.0.0: {}
- safe-buffer@5.2.1: {}
+ safe-buffer@5.2.1:
+ optional: true
safer-buffer@2.1.2: {}
@@ -1623,7 +1561,8 @@ snapshots:
dependencies:
xmlchars: 2.2.0
- semver@7.7.3: {}
+ semver@7.7.3:
+ optional: true
shebang-command@2.0.0:
dependencies:
@@ -1631,21 +1570,25 @@ snapshots:
shebang-regex@3.0.0: {}
- simple-concat@1.0.1: {}
+ simple-concat@1.0.1:
+ optional: true
simple-get@4.0.1:
dependencies:
decompress-response: 6.0.0
once: 1.4.0
simple-concat: 1.0.1
+ optional: true
source-map-js@1.2.1: {}
string_decoder@1.3.0:
dependencies:
safe-buffer: 5.2.1
+ optional: true
- strip-json-comments@2.0.1: {}
+ strip-json-comments@2.0.1:
+ optional: true
strip-json-comments@3.1.1: {}
@@ -1661,6 +1604,7 @@ snapshots:
mkdirp-classic: 0.5.3
pump: 3.0.3
tar-stream: 2.2.0
+ optional: true
tar-stream@2.2.0:
dependencies:
@@ -1669,6 +1613,7 @@ snapshots:
fs-constants: 1.0.0
inherits: 2.0.4
readable-stream: 3.6.2
+ optional: true
tldts-core@7.0.19: {}
@@ -1676,14 +1621,6 @@ snapshots:
dependencies:
tldts-core: 7.0.19
- topojson-client@3.1.0:
- dependencies:
- commander: 2.20.3
-
- topojson-server@3.0.1:
- dependencies:
- commander: 2.20.3
-
tough-cookie@6.0.0:
dependencies:
tldts: 7.0.19
@@ -1692,11 +1629,10 @@ snapshots:
dependencies:
punycode: 2.3.1
- tslib@2.8.1: {}
-
tunnel-agent@0.6.0:
dependencies:
safe-buffer: 5.2.1
+ optional: true
type-check@0.4.0:
dependencies:
@@ -1706,7 +1642,8 @@ snapshots:
dependencies:
punycode: 2.3.1
- util-deprecate@1.0.2: {}
+ util-deprecate@1.0.2:
+ optional: true
w3c-xmlserializer@5.0.0:
dependencies:
@@ -1731,15 +1668,10 @@ snapshots:
wmap-parser@1.0.1: {}
- wmap-renderer-canvas@1.0.1:
- dependencies:
- '@turf/concave': 7.3.1
- '@turf/helpers': 7.3.1
- canvas: 3.2.0
-
word-wrap@1.2.5: {}
- wrappy@1.0.2: {}
+ wrappy@1.0.2:
+ optional: true
ws@8.18.3: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..6325456
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,3 @@
+overrides:
+ wmap-renderer-twojs: link:../../../Library/pnpm/global/5/node_modules/wmap-renderer-twojs
+ wmap-renderer-svg: link:../../../Library/pnpm/global/5/node_modules/wmap-renderer-svg
diff --git a/src/wmap.js b/src/wmap.js
index 4532368..6e9606e 100644
--- a/src/wmap.js
+++ b/src/wmap.js
@@ -1,5 +1,5 @@
import { parse } from "wmap-parser";
-import { renderToCanvas, StageType } from "wmap-renderer-canvas";
+import { renderToSVG, StageType } from "wmap-renderer-svg";
import DOMPurify from "isomorphic-dompurify";
const internals = {
@@ -45,17 +45,13 @@ const internals = {
async renderImage(source, dimensions) {
const parsedText = parse(source);
- const canvas = document.createElement("canvas");
- canvas.width = dimensions.map.mapWidth + 2 * dimensions.map.padding;
- canvas.height = dimensions.map.mapHeight + 2 * dimensions.map.padding;
-
// Further Improvements. The zoomed version could have a drop down
// to show the different StageTypes and allow one to see the image
// with the different types.
// This could also potentially be in the toolbar that appears
// on hover to also show this in the download. It requires some
// thought on what the right interaction model would be.
- await renderToCanvas(parsedText, canvas, StageType.ACTIVITIES, {
+ return await renderToSVG(parsedText, StageType.ACTIVITIES, {
theme: {
sizes: {
...dimensions.map,
@@ -65,30 +61,32 @@ const internals = {
},
},
});
- return canvas.toDataURL();
},
// Starts a download of the image.
download(filename, text) {
+ const svgWithNamespace = text.replace(
+ "<svg",
+ '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"',
+ );
+ const svgContent = '<?xml version="1.0" encoding="UTF-8"?>\n' + svgWithNamespace;
+ const blob = new Blob([svgContent], { type: "image/svg+xml" });
+ const url = URL.createObjectURL(blob);
const element = document.createElement("a");
- element.setAttribute("href", text);
+ element.setAttribute("href", url);
element.setAttribute("download", filename);
element.style.display = "none";
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
+ URL.revokeObjectURL(url);
},
// Replaces the image in a window. Intended for use in a dialog.
replaceImage(window, imageData) {
try {
const $container = window.document.querySelector("main");
- $container.querySelectorAll("img").forEach((img) => img.remove());
-
- const image = document.createElement("img");
- image.src = imageData;
- image.alt = "Wardley map rendered from source.";
- $container.appendChild(image);
+ $container.innerHTML = imageData;
} catch (error) {
console.error(
"wmap: Could not replace image. The DOM wasn't ready!",
@@ -148,7 +146,7 @@ const bind = async function bind($item, item) {
internals.kDimensions.full,
);
const slug = $item.parents(".page").attr("id");
- internals.download(`${slug}.png`, imageData);
+ internals.download(`${slug}.svg`, imageData);
}
break;
case "zoom":
@@ -202,7 +200,7 @@ const bind = async function bind($item, item) {
internals.kDimensions.thumbnail,
);
$item.find(".viewer").html(`
- <article class="wardley-map"><img src="${thumbnailData}"></article>
+ <article class="wardley-map thumbnail">${thumbnailData}</article>
<nav class="actions">
<menu>
<li><a href="#" data-action="download" title="Download"><img width="18" height="18" alt="download" src='data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" fill="grey"><g><rect fill="none" height="24" width="24"/></g><g><path d="M5,20h14v-2H5V20z M19,9h-4V3H9v6H5l7,7L19,9z"/></g></svg>'></a></li>
@@ -210,6 +208,13 @@ const bind = async function bind($item, item) {
</menu>
</nav>
`);
+
+ $item.find('svg text:gt(7)').on('click', function(event) {
+ const title = this.innerHTML;
+ let $page = $item.parents('.page')
+ wiki.pageHandler.context = wiki.lineup.atKey($page.data('key')).getContext()
+ wiki.doInternalLink(title, event.shiftKey ? null : $page)
+ });
} catch (err) {
console.log("Failed to parse wardley map: ", err);
$item.html(internals.message(err.message));