Skip to content

Commit

Permalink
Debug option, export option, grid
Browse files Browse the repository at this point in the history
  • Loading branch information
santhoshtr committed Sep 7, 2024
1 parent 317aa78 commit 39201c5
Show file tree
Hide file tree
Showing 6 changed files with 225 additions and 10 deletions.
49 changes: 49 additions & 0 deletions static/annotate.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#annotationLayer {
display: none;
position: absolute;
top: 0;
left: 0;
}
body:has(#debug:checked) {
#annotationLayer {
display: block;
}

#result {
--s: 100px; /* control the size */

--_g: #0000 90deg, #d8dee910 0;
background: conic-gradient(from 90deg at 2px 2px, var(--_g)) 0 0 / var(--s)
var(--s),
conic-gradient(from 90deg at 1px 1px, var(--_g)) 0 0 / calc(var(--s) / 5)
calc(var(--s) / 5);
/* compensate for viewport adjustment to see the labels*/
background-position-x: 20px;
background-position-y: 20px;
}
}
.annotation {
fill: none;
stroke: #5e81ac;
}
.point {
fill: #d8dee9;
stroke: #bf616a;
cursor: pointer;
}
.control-point {
fill: #d8dee9;
stroke: #a3be8c;
cursor: pointer;
}

.coordinate-text {
font-size: 0.8em;
fill: #ebcb8b;
}

#originalSVG {
path {
stroke-width: 1px;
}
}
14 changes: 12 additions & 2 deletions static/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ header {
padding-bottom: 0;
display: grid;
grid-template-columns: auto 1fr auto;
grid-template-areas: "title name save compile share profile";
grid-template-areas: "title name debug save compile export share profile";
align-content: end;
align-items: center;
.sample-title {
Expand Down Expand Up @@ -79,7 +79,7 @@ h1 {
}

svg {
width: 100%;
width: max-content;
}

.nav-item {
Expand Down Expand Up @@ -130,11 +130,21 @@ svg {
justify-self: end;
}

#b-export {
grid-area: export;
justify-self: end;
}

#b-samples {
grid-area: samples;
justify-self: end;
}

#check-debug {
grid-area: debug;
justify-self: end;
}

.hidden {
display: none !important;
}
Expand Down
36 changes: 34 additions & 2 deletions static/main.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

import PocketBase from './pocketbase.es.js'
import { annotate } from './svgannotate.js'

var editor;
var editor, authorid, loginBtn, profileBtn, saveBtn, compileBtn, logoutBtn, sampleid;
var editor, authorid, loginBtn, profileBtn, saveBtn, exportBtn, compileBtn, logoutBtn, sampleid;
var pockethost_client;
var authData;

Expand Down Expand Up @@ -85,6 +86,22 @@ function doLogout() {
}
}

function exportSVG() {
const svgEl = document.getElementById('result').querySelector('svg');
const name = `${sampleid}.svg`;
svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
var svgData = svgEl.outerHTML;
var preface = '<?xml version="1.0" standalone="no"?>\r\n';
var svgBlob = new Blob([preface, svgData], { type: "image/svg+xml;charset=utf-8" });
var svgUrl = URL.createObjectURL(svgBlob);
var downloadLink = document.createElement("a");
downloadLink.href = svgUrl;
downloadLink.download = name;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}

function doCompile() {
const code = editor.getValue()
document.getElementById('log').innerText = 'Compiling..';
Expand All @@ -103,6 +120,14 @@ function doCompile() {
}
document.getElementById('log').innerHTML = result.stdout
document.getElementById('result').innerHTML = result.svg
const originalSVG = document.getElementById('result').querySelector('svg');
// incrrease the viewBox of the svg by 10%
const width = originalSVG.getAttribute('width');
const height = originalSVG.getAttribute('height');
const newViewBox = `${-20} ${-20} ${width * 1.1} ${height * 1.1}`;
originalSVG.setAttribute('viewBox', newViewBox);
originalSVG.setAttribute('id', originalSVG);
annotate(originalSVG);
})
}

Expand All @@ -114,9 +139,11 @@ document.addEventListener("DOMContentLoaded", async (event) => {
saveBtn = document.getElementById('b-save');
compileBtn = document.getElementById('b-compile');
logoutBtn = document.getElementById('b-logout');
exportBtn = document.getElementById('b-export');


loginBtn.addEventListener('click', doGithubLogin);
exportBtn?.addEventListener('click', exportSVG);
compileBtn && compileBtn.addEventListener('click', doCompile);
saveBtn && saveBtn.addEventListener('click', doSave);
logoutBtn && logoutBtn.addEventListener('click', doLogout);
Expand Down Expand Up @@ -147,7 +174,12 @@ document.addEventListener("DOMContentLoaded", async (event) => {
"Ctrl-R": doCompile
}
});
// editor.on("change", doCompile);
let debouncer;
editor.on("change", () => {
clearTimeout(debouncer) //clear any existing timeout
debouncer = setTimeout(doCompile, 500);

});
sampleid = document.querySelector("meta[name='sampleid']")?.getAttribute("content");
authorid = document.querySelector("meta[name='authorid']")?.getAttribute("content");
if (sampleid) {
Expand Down
14 changes: 9 additions & 5 deletions static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ h1 {
grid-area: name;
background-color: var(--background-color);
color: var(--text-color);
padding: 4px;
padding: 0.5em;
border: none;
}

Expand All @@ -62,12 +62,16 @@ textarea {
margin: 10px;
}

#result {
border-inline-start: 1px solid var(--border-color);
}


#result {
display: inline-block;
position: relative;
}


svg {
height: 100%;
height: max-content;
}

#log {
Expand Down
113 changes: 113 additions & 0 deletions static/svgannotate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
class Point {
constructor(x, y) {
this.x = Math.round(x);
this.y = Math.round(y);
}

toString() {
return `(${this.x},${this.y})`;
}
}

class Curve {
constructor(p1, c1, c2, p2,) {
this.p1 = p1;
this.c1 = c1;
this.c2 = c2;
this.p2 = p2;
}
annotate(index) {
annotateControlLine(annotationLayer, this.p1, this.c1);
annotateControlLine(annotationLayer, this.c2, this.p2);
annotatePoint(annotationLayer, this.p1, index + 0, false);
annotatePoint(annotationLayer, this.c1, index + 0, true);
annotatePoint(annotationLayer, this.c2, index + 1, true);
annotatePoint(annotationLayer, this.p2, index + 1, false);
}
}

function annotate(originalSVG) {

const annotationLayer = document.createElementNS("http://www.w3.org/2000/svg", "svg");
annotationLayer.setAttribute("id", "annotationLayer");
originalSVG.parentNode.appendChild(annotationLayer);
annotationLayer.setAttribute("width", originalSVG.getAttribute("width"));
annotationLayer.setAttribute("height", originalSVG.getAttribute("height"));
annotationLayer.setAttribute("viewBox", originalSVG.getAttribute("viewBox"));

const paths = originalSVG.getElementsByTagName("path");

for (let path of paths) {
const d = path.getAttribute("d");
const commands = d.match(/[MmLlHhVvCcSsQqTtAaZz][^MmLlHhVvCcSsQqTtAaZz]*/g);

let pointIndex = 0;
let lastPoint = null;
commands.forEach((cmd) => {
const type = cmd[0];
const points = parsePoints(cmd.slice(1).trim());

if (type === "M") {
// annotatePoint(annotationLayer, points[0], pointIndex++);
}
if (type === "L") {
annotatePoint(annotationLayer, points[0], pointIndex++);
}
if (type === "C") {
const p1 = lastPoint;
const c1 = points[0];
const c2 = points[1];
const p2 = points[2];
const c = new Curve(p1, c1, c2, p2);
c.annotate(pointIndex++);
}
lastPoint = points[points.length - 1];
});
}
}

function parsePoints(pointString) {
const coordinates = pointString.split(/[\s,]+/).map(Number);
const points = [];
for (let i = 0; i < coordinates.length; i += 2) {
points.push(new Point(coordinates[i], coordinates[i + 1]));
}
return points;
}

function annotatePoint(svg, point, index, isControlPoint = false) {
const circle = document.createElementNS(
"http://www.w3.org/2000/svg",
"circle"
);
circle.setAttribute("cx", point.x);
circle.setAttribute("cy", point.y);
circle.setAttribute("r", "3");

circle.classList.add(isControlPoint ? "control-point" : "point");
const titleElement = document.createElementNS("http://www.w3.org/2000/svg", "title");
titleElement.textContent = point.toString();
circle.appendChild(titleElement);
svg.appendChild(circle);
if (!isControlPoint) {
const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
text.setAttribute("x", point.x + 5);
text.setAttribute("y", point.y - 5);
text.textContent = `${index}`;
text.classList.add("coordinate-text");
svg.appendChild(text);
}
}

function annotateControlLine(svg, start, end) {
const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
line.setAttribute("x1", start.x);
line.setAttribute("y1", start.y);
line.setAttribute("x2", end.x);
line.setAttribute("y2", end.y);
line.classList.add("annotation");
svg.appendChild(line);
}


export { annotate };
9 changes: 8 additions & 1 deletion templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
{% endif %}
<link id="theme-style" rel="stylesheet" href="../static/common.css">
<link id="theme-style" rel="stylesheet" href="../static/style.css">
<link id="theme-style" rel="stylesheet" href="../static/annotate.css">
<link id="theme-style" rel="stylesheet" href="../static/codemirror.css">
<link id="theme-style" rel="stylesheet" href="../static/nord.css">
<script src="../static/main.js" type="module"></script>
Expand All @@ -36,13 +37,19 @@
<h1 class="title">Metapost Sandbox</h1>
</a>
<input class="sample-title" value="{{ title }}" id="title" name="title" />
<label for="debug" id="check-debug" class="nav-item">Debug<input type="checkbox" id="debug" name="debug" value="debug"
checked></label>
<button id="b-save" class="nav-item" title="Save [Control+S]"><span class="material-symbols-outlined">
save
</span>Save</button>
<button id="b-compile" class="nav-item" title="Compile [Control+R]"><span class="material-symbols-outlined">
play_arrow
</span>Run</button>

<button id="b-export" class="nav-item" title="Export SVG"><span class="material-symbols-outlined">
download
</span>Export</button>

<div class="dropdown">
<button id="b-share" class="nav-item" title="Share" ><span
class="material-symbols-outlined">
Expand Down Expand Up @@ -95,7 +102,7 @@ <h3>Embed</h3>
<textarea id="metapost" oninput="doCompile()">
{{metapost}}
</textarea>
<div id="result" disabled></div>
<div id="result"></div>
</section>
<section class="logs">
<p id="log"></p>
Expand Down

0 comments on commit 39201c5

Please sign in to comment.