|
| 1 | +let copySvg = ` |
| 2 | +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy"> |
| 3 | +<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/> |
| 4 | +</svg> |
| 5 | +`; |
| 6 | + |
| 7 | +let checkSvg = ` |
| 8 | +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check green"> |
| 9 | +<path d="M20 6 9 17l-5-5"/> |
| 10 | +</svg> |
| 11 | +`; |
| 12 | + |
| 13 | +let downloadSvg = ` |
| 14 | +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download"> |
| 15 | +<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/> |
| 16 | +</svg> |
| 17 | +`; |
| 18 | + |
| 19 | +let controls = ` |
| 20 | +<div class="control"> |
| 21 | + <button class="icon-button puml-copy"> |
| 22 | + ${copySvg} |
| 23 | + </button> |
| 24 | + <button class="icon-button puml-download"> |
| 25 | + ${downloadSvg} |
| 26 | + </button> |
| 27 | + <hr /> |
| 28 | + <button class="icon-button puml-zoom-in"> |
| 29 | + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-plus"> |
| 30 | + <path d="M5 12h14"/><path d="M12 5v14"/> |
| 31 | + </svg> |
| 32 | + </button> |
| 33 | + <button class="icon-button puml-zoom-reset"> |
| 34 | + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-house"> |
| 35 | + <path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/> |
| 36 | + </svg> |
| 37 | + </button> |
| 38 | + <button class="icon-button puml-zoom-out"> |
| 39 | + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-minus"> |
| 40 | + <path d="M5 12h14"/> |
| 41 | + </svg> |
| 42 | + </button> |
| 43 | +</div> |
| 44 | +`; |
| 45 | + |
| 46 | +function processDiagrams() { |
| 47 | + const svgs = document.querySelectorAll('.puml .diagram'); |
| 48 | + svgs.forEach(svg => { |
| 49 | + // Get the computed width and height of each SVG |
| 50 | + // const rect = svg.querySelector('rect'); |
| 51 | + let width = svg.getAttribute('width'); |
| 52 | + let height = svg.getAttribute('height'); |
| 53 | + |
| 54 | + width = parseInt(width); |
| 55 | + height = parseInt(height); |
| 56 | + |
| 57 | + if(isNaN(width) || isNaN(height)) { |
| 58 | + return |
| 59 | + } |
| 60 | + |
| 61 | + if (width > height) { |
| 62 | + svg.classList.add('wide-svg'); |
| 63 | + } |
| 64 | + |
| 65 | + const g = svg.querySelector('g'); |
| 66 | + const panzoom = Panzoom(g, {canvas: true}); |
| 67 | + |
| 68 | + g.parentElement.addEventListener('wheel', function (event) { |
| 69 | + if (!event.shiftKey) return |
| 70 | + // Panzoom will automatically use `deltaX` here instead |
| 71 | + // of `deltaY`. On a mac, the shift modifier usually |
| 72 | + // translates to horizontal scrolling, but Panzoom assumes |
| 73 | + // the desired behavior is zooming. |
| 74 | + panzoom.zoomWithWheel(event) |
| 75 | + }); |
| 76 | + |
| 77 | + svg.insertAdjacentHTML("beforebegin", controls); |
| 78 | + |
| 79 | + const control = svg.parentElement.querySelector(".control"); |
| 80 | + const copyBtn = control.querySelector(".puml-copy"); |
| 81 | + const downloadBtn = control.querySelector(".puml-download"); |
| 82 | + const zoomResetBtn = control.querySelector(".puml-zoom-reset"); |
| 83 | + const zoomInBtn = control.querySelector(".puml-zoom-in"); |
| 84 | + const zoomOutBtn = control.querySelector(".puml-zoom-out"); |
| 85 | + |
| 86 | + zoomResetBtn.addEventListener("click", event => { |
| 87 | + panzoom.reset({animate: false}); |
| 88 | + }); |
| 89 | + zoomInBtn.addEventListener("click", event => { |
| 90 | + panzoom.zoomIn(); |
| 91 | + }); |
| 92 | + zoomOutBtn.addEventListener("click", event => { |
| 93 | + panzoom.zoomOut(); |
| 94 | + }); |
| 95 | + |
| 96 | + let timeout = null; |
| 97 | + copyBtn.addEventListener("click", event => { |
| 98 | + clearTimeout(timeout); |
| 99 | + |
| 100 | + let btn = event.target.closest('button'); |
| 101 | + btn.innerHTML = checkSvg; |
| 102 | + |
| 103 | + timeout = setTimeout(() => { |
| 104 | + btn.innerHTML = copySvg; |
| 105 | + }, 1500); |
| 106 | + }); |
| 107 | + copyBtn.addEventListener("click", e => { |
| 108 | + const svgString = new XMLSerializer().serializeToString(svg); |
| 109 | + // Copy svg as text |
| 110 | + navigator.clipboard.writeText(svgString); |
| 111 | + }); |
| 112 | + downloadBtn.addEventListener("click", e => { |
| 113 | + const svgString = new XMLSerializer().serializeToString(svg); |
| 114 | + let blob = new Blob([svgString], { type: 'image/svg+xml' }); |
| 115 | + let link = document.createElement('a'); |
| 116 | + link.href = URL.createObjectURL(blob); |
| 117 | + link.download = 'diagram.svg'; |
| 118 | + link.click(); |
| 119 | + URL.revokeObjectURL(link.href); |
| 120 | + }); |
| 121 | + }); |
| 122 | +} |
| 123 | + |
| 124 | +// This checks if mkdocs-material is installed, use document$.subscribe. |
| 125 | +// Otherwise, add listener to DOMContentLoaded |
| 126 | +if (typeof document$ !== 'undefined' && document$.subscribe){ |
| 127 | + document$.subscribe(processDiagrams); |
| 128 | +} else { |
| 129 | + document.addEventListener('DOMContentLoaded', processDiagrams); |
| 130 | +} |
0 commit comments