Skip to content

Commit

Permalink
Mod: make links in preview clickable (#572)
Browse files Browse the repository at this point in the history
  • Loading branch information
qjebbs committed Mar 30, 2024
1 parent b0141c5 commit 30a4ed6
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 11 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion src/plantuml/exporter/exportDiagram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ export function exportDiagram(diagram: Diagram, format: string, savePath: string
bar.text = localize(7, null, diagram.name + "." + format.split(":")[0]);
}
let renderTask = appliedRender(diagram.parentUri).render(diagram, format, savePath);
if (!config.exportMapFile(diagram.parentUri) || !savePath) return renderTask;
if (!savePath) {
// when exporting to buffer include map to make links clickable
let mapTask = appliedRender(diagram.parentUri).getMapData(diagram, savePath);
return combine(renderTask, mapTask);
}

if (!config.exportMapFile(diagram.parentUri)) return renderTask;

let bsName = path.basename(savePath);
let ext = path.extname(savePath);
Expand Down
33 changes: 28 additions & 5 deletions src/providers/previewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ class Previewer extends vscode.Disposable {
let env = {
localize: localize,
images: this.images.reduce((p, c) => {
return `${p}<img src="${c}">`
if (c.startsWith('data:image/')) {
return `${p}<img src="${c}">`
} else {
return `${p}${c.replaceAll('<area ', '<area target="_blank"')}`
}
}, ""),
imageError: "",
error: "",
Expand Down Expand Up @@ -169,9 +173,22 @@ class Previewer extends vscode.Disposable {
this.images = result.reduce((p, buf) => {
let sigPNG = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
let isPNG = buf.slice(0, sigPNG.length).equals(sigPNG);
let b64 = buf.toString('base64');
if (!b64) return p;
p.push(`data:image/${isPNG ? 'png' : "svg+xml"};base64,${b64}`);
let isSVG = (buf.slice(0, 256).indexOf('<svg') >= 0);

if (isPNG || isSVG) {
let b64 = buf.toString('base64');
if (!b64) return p;

// push image
p.push(`data:image/${isPNG ? 'png' : "svg+xml"};base64,${b64}`);
} else {
// push image map
let imageMap = '<map></map>';
if (buf.toString().trim().length > 0)
imageMap = buf.toString()

p.push(imageMap);
}
return p;
}, <string[]>[]);
this.updateWebView();
Expand Down Expand Up @@ -224,7 +241,13 @@ class Previewer extends vscode.Disposable {
);
this._disposables.push(this._uiPreview);

this._uiPreview.addEventListener("message", e => this.setUIStatus(JSON.stringify(e.message)));
this._uiPreview.addEventListener("message", e => {
if (e.message.action == "openExternalLink") {
vscode.env.openExternal(e.message.href);
} else {
this.setUIStatus(JSON.stringify(e.message));
}
});
this._uiPreview.addEventListener("open", () => this.startWatch());
this._uiPreview.addEventListener("close", () => { this.stopWatch(); this.killTasks(); });
}
Expand Down
27 changes: 27 additions & 0 deletions templates/js/hyperlink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
function addHyperlinkManager(vscode) {
let imgContainer= document.getElementById('image-container');
imgContainer.addEventListener('click', e => {
if (e.button == 0 && e.target.target == "_blank") {
vscode.postMessage({
"action": "openExternalLink",
"href": e.target.href
});

e.stopImmediatePropagation();
}
});

imgContainer.addEventListener('mousedown', e => {
if (e.button == 0 && e.target.target == "_blank") {
// prevent zoom selection when clicking on links
e.stopImmediatePropagation();
}
});

imgContainer.addEventListener('mouseup', e => {
if (e.button == 0 && e.target.target == "_blank") {
// prevent zoom action when clicking on links
e.stopImmediatePropagation();
}
});
}
164 changes: 164 additions & 0 deletions templates/js/imageMapResizer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*! Image Map Resizer
* Desc: Resize HTML imageMap to scaled image.
* Copyright: (c) 2014-15 David J. Bradshaw - [email protected]
* License: MIT
*/

;(function() {
'use strict'

function scaleImageMap() {
function resizeMap() {
function resizeAreaTag(cachedAreaCoords, idx) {
function scale(coord) {
var dimension = 1 === (isWidth = 1 - isWidth) ? 'width' : 'height'
return (
padding[dimension] +
Math.floor(Number(coord) * scalingFactor[dimension])
)
}

var isWidth = 0
areas[idx].coords = cachedAreaCoords
.split(',')
.map(scale)
.join(',')
}

var scalingFactor = {
width: image.width / image.naturalWidth,
height: image.height / image.naturalHeight,
}

var padding = {
width: parseInt(
window.getComputedStyle(image, null).getPropertyValue('padding-left'),
10
),
height: parseInt(
window.getComputedStyle(image, null).getPropertyValue('padding-top'),
10
),
}

cachedAreaCoordsArray.forEach(resizeAreaTag)
}

function getCoords(e) {
//Normalize coord-string to csv format without any space chars
return e.coords.replace(/ *, */g, ',').replace(/ +/g, ',')
}

function debounce() {
clearTimeout(timer)
timer = setTimeout(resizeMap, 250)
}

function start() {
if (
image.width !== image.naturalWidth ||
image.height !== image.naturalHeight
) {
resizeMap()
}
}

function addEventListeners() {
image.addEventListener('load', resizeMap, false) //Detect late image loads in IE11
window.addEventListener('focus', resizeMap, false) //Cope with window being resized whilst on another tab
window.addEventListener('resize', debounce, false)
window.addEventListener('readystatechange', resizeMap, false)
document.addEventListener('fullscreenchange', resizeMap, false)
}

function beenHere() {
return 'function' === typeof map._resize
}

function getImg(name) {
return document.querySelector('img[usemap="' + name + '"]')
}

function setup() {
areas = map.getElementsByTagName('area')
cachedAreaCoordsArray = Array.prototype.map.call(areas, getCoords)
image = getImg('#' + map.name) || getImg(map.name)
map._resize = resizeMap //Bind resize method to HTML map element
}

var /*jshint validthis:true */
map = this,
areas = null,
cachedAreaCoordsArray = null,
image = null,
timer = null

if (!beenHere()) {
setup()
addEventListeners()
start()
} else {
map._resize() //Already setup, so just resize map
}
}

function factory() {
function chkMap(element) {
if (!element.tagName) {
throw new TypeError('Object is not a valid DOM element')
} else if ('MAP' !== element.tagName.toUpperCase()) {
throw new TypeError(
'Expected <MAP> tag, found <' + element.tagName + '>.'
)
}
}

function init(element) {
if (element) {
chkMap(element)
scaleImageMap.call(element)
maps.push(element)
}
}

var maps

return function imageMapResizeF(target) {
maps = [] // Only return maps from this call

switch (typeof target) {
case 'undefined':
case 'string':
Array.prototype.forEach.call(
document.querySelectorAll(target || 'map'),
init
)
break
case 'object':
init(target)
break
default:
throw new TypeError('Unexpected data type (' + typeof target + ').')
}

return maps
}
}

if (typeof define === 'function' && define.amd) {
define([], factory)
} else if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = factory() //Node for browserfy
} else {
window.imageMapResize = factory()
}

if ('jQuery' in window) {
window.jQuery.fn.imageMapResize = function $imageMapResizeF() {
return this.filter('map')
.each(scaleImageMap)
.end()
}
}
})()

14 changes: 14 additions & 0 deletions templates/js/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,27 @@ window.addEventListener("load", () => {
zoomer = new Zoom(settings);
switcher.moveTo(previewStatus.page);
addCursorManager(settings);
addHyperlinkManager(vscode);
addSelectionBox(settings);
addDrageScroll(settings);
initializeHelpModal();
} else {
document.getElementById("ctrl-container").remove();
document.getElementById("image-container").remove();
}

// see imageMapResizer.js
imageMapResize('#image-map');
let image = document.getElementById('image')
if (image) {
new MutationObserver(() => {
imageMapResize('#image-map');
})
.observe(
image,
{'attributes': true}
);
}
});
window.addEventListener(
"resize",
Expand Down
13 changes: 11 additions & 2 deletions templates/js/switcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ class Switcher {
constructor() {
this.current = 0;
this.images = [];
this.imageMaps = [];
this.image = document.getElementById("image");
this.imageMap = document.getElementById("image-map");
this.pInfo = document.getElementById("pageInfo");
this.pInfoTpl = this.pInfo.innerText;
for (let e of document.getElementById("images").getElementsByTagName("img")) {
this.images.push(e.src);
this.images.push(e);
}
for (let e of document.getElementById("images").getElementsByTagName("map")) {
this.imageMaps.push(e);
}
if (this.images.length <= 1) {
document.getElementById("page-ctrls").style.display = "none";
Expand Down Expand Up @@ -34,7 +39,11 @@ class Switcher {
if (this.current == page) return;

// switch page
this.image.src = this.images[page - 1];
let image = this.images[page - 1];
let imageMap = this.imageMaps[page - 1];

this.image.src = image.src;
this.imageMap.innerHTML = imageMap?.innerHTML ?? "";
this.pInfo.innerText = String.format(this.pInfoTpl, page, this.images.length);
this.current = page;

Expand Down
5 changes: 4 additions & 1 deletion templates/preview.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
<head>
<link rel="stylesheet" href="css/preview.css">
<script src="js/dragscroll.js"></script>
<script src="js/hyperlink.js"></script>
<script src="js/switcher.js"></script>
<script src="js/zoom.js"></script>
<script src="js/imageMapResizer.js"></script>
<script src="js/preview.js"></script>
<script src="js/cursor.js"></script>
<script src="js/selectionZoom.js"></script>
Expand Down Expand Up @@ -42,7 +44,8 @@
</div>
</div>
<div id="image-container" style="margin: 10px;">
<img id="image" src="" draggable="false">
<img id="image" src="" draggable="false" usemap="#image-map">
<map id="image-map" name="image-map" data=""></map>
</div>
<div id="ctrl-container">
<div id="controls">
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": ["es2021"],
"target": "es6",
"outDir": "out",
"sourceMap": true,
Expand Down

0 comments on commit 30a4ed6

Please sign in to comment.