From dca7dfc450eec789800d9208ae590ad2c81cbe37 Mon Sep 17 00:00:00 2001 From: USER Date: Sat, 23 Jan 2021 18:32:58 +0100 Subject: [PATCH 01/12] Fix paste bug --- js/linkmap.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/js/linkmap.js b/js/linkmap.js index 45f299b..a37917a 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -697,10 +697,8 @@ function pasteURL(e) { let paste = (e.clipboardData || window.clipboardData).getData('text'); if (paste.startsWith("http")) { - let m = codeBox.value.match(/#+/); - finalIndex = (m) ? m.index - 1 : 0; - - codeBox.value = stringSubstituteAt(codeBox.value,finalIndex, 0, `\n[](${paste}))\n`); + finalIndex = codeBox.selectionStart; + codeBox.value = stringSubstituteAt(codeBox.value,finalIndex, 0, `\n[](${paste})\n`); parseText(); codeBox.select(); codeBox.selectionStart = finalIndex+2; From a747d480a0109313ea81e9c741732bba60733b67 Mon Sep 17 00:00:00 2001 From: Leopoldo Date: Sat, 23 Jan 2021 19:04:05 +0100 Subject: [PATCH 02/12] Keyboard commands: escape hides the code box, arrow keys move the background --- js/linkmap.js | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/js/linkmap.js b/js/linkmap.js index a37917a..b3bbbd9 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -22,15 +22,52 @@ let infoBoxDescription = document.querySelector("#infobox-description") // Default spacing between objects (in px) let standardMargin = 20; + + +document.onkeydown = (e) => { + if (e.code === 'Escape') { + escapeAction() + } + + if (document.activeElement !== codeBox) { + console.log(e.code) + let delta = 75; + // Translation goes in the opposite direction, because + // we translate the background instead of moving the camera! + let movement = { + "ArrowLeft": { dX: delta, dY: 0 }, + "ArrowRight": { dX: -delta, dY: 0 }, + "ArrowUp": { dX: 0, dY: delta }, + "ArrowDown": { dX: 0, dY: -delta } + } + + if (movement[e.code]) { + let currentTransform = getTransformScale(linkMap.style.transform); + console.log("trigger",movement[e.code]) + linkMap.style.transform = setTransformScale( + dX = parseFloat(currentTransform[0]) + movement[e.code].dX, + dY = parseFloat(currentTransform[1]) + movement[e.code].dY, + scale = currentTransform[2]); + } + } + +} + + + // Set up toolbox buttons: // Show or hide the textarea panel -let iconCode = document.querySelector("#icon-code"); -iconCode.onclick = (e) => { +escapeAction = () => { showCode = !showCode; toggleCodePanel(showCode) saveSettings(); } +let iconCode = document.querySelector("#icon-code"); +iconCode.onclick = escapeAction + + + // Toggle drag mode let iconEditing = document.querySelector("#icon-editing"); iconEditing.onclick = (e) => { @@ -698,10 +735,10 @@ function pasteURL(e) { if (paste.startsWith("http")) { finalIndex = codeBox.selectionStart; - codeBox.value = stringSubstituteAt(codeBox.value,finalIndex, 0, `\n[](${paste})\n`); + codeBox.value = stringSubstituteAt(codeBox.value, finalIndex, 0, `\n[](${paste})\n`); parseText(); codeBox.select(); - codeBox.selectionStart = finalIndex+2; + codeBox.selectionStart = finalIndex + 2; codeBox.selectionEnd = codeBox.selectionStart; e.preventDefault(); } From bcb93d62c7f921423281312117c2ad6645078049 Mon Sep 17 00:00:00 2001 From: Leopoldo Date: Sat, 23 Jan 2021 19:28:39 +0100 Subject: [PATCH 03/12] Download an interactive html linkmap --- js/linkmap.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/js/linkmap.js b/js/linkmap.js index b3bbbd9..55f0814 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -30,7 +30,6 @@ document.onkeydown = (e) => { } if (document.activeElement !== codeBox) { - console.log(e.code) let delta = 75; // Translation goes in the opposite direction, because // we translate the background instead of moving the camera! @@ -43,7 +42,6 @@ document.onkeydown = (e) => { if (movement[e.code]) { let currentTransform = getTransformScale(linkMap.style.transform); - console.log("trigger",movement[e.code]) linkMap.style.transform = setTransformScale( dX = parseFloat(currentTransform[0]) + movement[e.code].dX, dY = parseFloat(currentTransform[1]) + movement[e.code].dY, @@ -54,7 +52,6 @@ document.onkeydown = (e) => { } - // Set up toolbox buttons: // Show or hide the textarea panel escapeAction = () => { @@ -79,7 +76,12 @@ iconEditing.onclick = (e) => { // Download current text to user's disk let iconSave = document.querySelector("#icon-save"); iconSave.onclick = function () { - download("linkmap.md", codeBox.value) + var path = document.URL.replace("linkmap.html", "") + var doc = document.documentElement.innerHTML + .replaceAll(`"css/`, `"${path}css/`) + .replaceAll(`"js/`, `"${path}js/`) + .replaceAll(`"fonts/`, `"${path}fonts/`) + download("linkmap.html", doc) saveSettings(); } From 1061fc32512223a46d269ce151f32a2084481891 Mon Sep 17 00:00:00 2001 From: Leopoldo Date: Sat, 23 Jan 2021 20:13:51 +0100 Subject: [PATCH 04/12] Nested blocks Hopefully fixes unexpected behavior with # in the markdown. Now incomplete # tags should be ignored --- js/linkmap.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/js/linkmap.js b/js/linkmap.js index 55f0814..37d4a3a 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -379,8 +379,9 @@ function trackHierarchy(child, parent) { if (child.codeInfo) { let currentCode = codeBox.value; + // Find the extent of the root block let finalIndex = 0 - let m = currentCode.match(/#+/); + let m = currentCode.match(forcedHeaderPattern) if (m) finalIndex = m.index - 1; // In case the code starts with a container @@ -395,7 +396,7 @@ function trackHierarchy(child, parent) { let m = currentCode.slice(match.index + parent.codeInfo.indentation, match.index + match.code.length + parent.codeInfo.indentation) - .match(/#+/); + m = m.match(forcedHeaderPattern); if (m) { finalIndex = match.index + parent.codeInfo.indentation + m.index - 1; } @@ -408,8 +409,13 @@ function trackHierarchy(child, parent) { let match = trackContainer(initialCode, child) // Change a conteiner's indentation if required codeToAdd = match.code - let replaceString = new RegExp(`#{${child.codeInfo.indentation}}(#*)`, "g") + + // Fix indentation of all children + let replaceString = new RegExp(`#{${child.codeInfo.indentation}}(#*.*\\[)`, "g") + console.log(replaceString) codeToAdd = codeToAdd.replaceAll(replaceString, "#".repeat(parent.codeInfo.indentation + 1) + "$1") + + // Fix the indentation of the current block itself codeToAdd = codeToAdd.replace(/#*/, "#".repeat(parent.codeInfo.indentation + 1)) } @@ -441,6 +447,7 @@ function trackIndex(threshold, delta) { } function trackContainer(txt, child) { + // Returns the exact location of the given container in the code and including all children links let beginning = child.codeInfo.matchedPattern; let arr = [escapeRegExp(beginning), child.codeInfo.indentation] let searchPattern = headerPattern.replace(/\@/g, () => arr.shift()); @@ -889,12 +896,13 @@ let clean = (piece) => (piece .replace(/((^|\n)(?:[^\/\\]|\/[^\/]|\\.)*?)\s*\/\/[^\n]*/g, '$1') .replace(/\n\s*/g, '') ); -window.regex = ({ raw }, ...interpolations) => ( - new RegExp(interpolations.reduce( +window.regex = ({ raw }, ...interpolations) => { + console.log(interpolations) + return new RegExp(interpolations.reduce( (regex, insert, index) => (regex + insert + clean(raw[index + 1])), clean(raw[0]) )) -); +}; // Escape an entire string in regex // https://stackoverflow.com/a/6969486 @@ -985,9 +993,9 @@ let linkPatternSingle = regex` )? ` -linkPattern = new RegExp(linkPatternSingle, "g"); - - +let linkPattern = new RegExp(linkPatternSingle, "g"); +// Make the # tag mandatory +let forcedHeaderPattern = /(?#+).*\[(?[^\]]*)\]\((?<link>[^\)]*)\)/ //********************************/ // Load settings From d60d0f459c6cdd850a085560aedd52e5d46e6832 Mon Sep 17 00:00:00 2001 From: Leopoldo <EMAIL> Date: Sat, 23 Jan 2021 20:18:51 +0100 Subject: [PATCH 05/12] clean --- js/linkmap.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/js/linkmap.js b/js/linkmap.js index 37d4a3a..7f87738 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -412,7 +412,6 @@ function trackHierarchy(child, parent) { // Fix indentation of all children let replaceString = new RegExp(`#{${child.codeInfo.indentation}}(#*.*\\[)`, "g") - console.log(replaceString) codeToAdd = codeToAdd.replaceAll(replaceString, "#".repeat(parent.codeInfo.indentation + 1) + "$1") // Fix the indentation of the current block itself @@ -896,13 +895,12 @@ let clean = (piece) => (piece .replace(/((^|\n)(?:[^\/\\]|\/[^\/]|\\.)*?)\s*\/\/[^\n]*/g, '$1') .replace(/\n\s*/g, '') ); -window.regex = ({ raw }, ...interpolations) => { - console.log(interpolations) - return new RegExp(interpolations.reduce( +window.regex = ({ raw }, ...interpolations) => ( + new RegExp(interpolations.reduce( (regex, insert, index) => (regex + insert + clean(raw[index + 1])), clean(raw[0]) )) -}; +); // Escape an entire string in regex // https://stackoverflow.com/a/6969486 From cb82127b460a97b0a79364d17a44cd847c26571b Mon Sep 17 00:00:00 2001 From: Leopoldo <EMAIL> Date: Sat, 23 Jan 2021 20:27:48 +0100 Subject: [PATCH 06/12] fix version number #5 --- js/linkmap.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/linkmap.js b/js/linkmap.js index 7f87738..8e36bae 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -96,8 +96,7 @@ Activate the tool icon to drag boxes around. Write text in the line after a link to display in a panel. Add 'width|height|' before color to produce larger rectangles. Copy&paste wiki text into any text editor to save it. -Press Escape to close this panel. -V0.8 (C) 2020 Florian Marquardt (MIT license)` +V0.9 (C) 2021 Florian Marquardt, Leopoldo Sarra (MIT license)` showInfoBox("About", helpText, { X: 60, Y: 50 }); iconHelp.classList.add("selected"); } From 054fc027eaa2eefedcc2f98d6b09e26b7a13955c Mon Sep 17 00:00:00 2001 From: Leopoldo <EMAIL> Date: Sat, 23 Jan 2021 21:09:23 +0100 Subject: [PATCH 07/12] Generate linkmap file The file should automatically load the required dependencies #4 One may consider in alternative to embed all the js and the css in the file so that the map is self-contained --- js/linkmap.js | 53 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/js/linkmap.js b/js/linkmap.js index 8e36bae..dc40342 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -77,14 +77,39 @@ iconEditing.onclick = (e) => { let iconSave = document.querySelector("#icon-save"); iconSave.onclick = function () { var path = document.URL.replace("linkmap.html", "") - var doc = document.documentElement.innerHTML - .replaceAll(`"css/`, `"${path}css/`) - .replaceAll(`"js/`, `"${path}js/`) - .replaceAll(`"fonts/`, `"${path}fonts/`) + + var doc = `<a>${path}</a> + <code>${codeBox.value}</code> + <script>${load_dependencies.toString()} + load_dependencies(); + </script>` + download("linkmap.html", doc) saveSettings(); } +// Function to load the dependencies of a linkmap file +function load_dependencies() { + let path = document.querySelector("a").innerHTML; + let myLinkmap = document.querySelector("code").innerHTML; + fetch(`${path}linkmap.html`).then(res => res.text().then(res => { + res = res.replaceAll(`"css/`, `"${path}css/`) + .replaceAll(`"js/`, `"${path}js/`) + .replaceAll(`"fonts/`, `"${path}fonts/`) + document.querySelector("html").innerHTML = res; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = `${path}js/linkmap.js`; + document.body.appendChild(script); + script.onload = () => { + codeBox.value = myLinkmap; + parseText(); + } + })) +} + + + // Show the information popup let iconHelp = document.querySelector("#icon-help"); iconHelp.onclick = (e) => { @@ -720,12 +745,20 @@ function loadSettings() { toggleCodePanel(showCode) if (codeBox.value == "") { - // Load default document - fetch("https://lsarra.github.io/linkmap/examples/deeplearning_formatted_2.md").then(res => res.text().then(res => { - codeBox.value = res; - // Trigger the rendering of the textarea to draw the map - parseText(); - })) + + // restore saved linkmap + if (typeof myLinkmap !== "undefined") { + codeBox.value = myLinkmap; + } else { + + // Load default document + fetch("https://lsarra.github.io/linkmap/examples/deeplearning_formatted_2.md").then(res => res.text().then(res => { + codeBox.value = res; + // Trigger the rendering of the textarea to draw the map + parseText(); + })) + } + } } From 77072fcd7fb927035d8942afed8b572b8f024d67 Mon Sep 17 00:00:00 2001 From: Leopoldo <EMAIL> Date: Sat, 23 Jan 2021 21:17:44 +0100 Subject: [PATCH 08/12] fix global variable --- js/linkmap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/linkmap.js b/js/linkmap.js index dc40342..9f671a1 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -91,7 +91,7 @@ iconSave.onclick = function () { // Function to load the dependencies of a linkmap file function load_dependencies() { let path = document.querySelector("a").innerHTML; - let myLinkmap = document.querySelector("code").innerHTML; + myLinkmap = document.querySelector("code").innerHTML; fetch(`${path}linkmap.html`).then(res => res.text().then(res => { res = res.replaceAll(`"css/`, `"${path}css/`) .replaceAll(`"js/`, `"${path}js/`) From 38ce35b8487c3ba009d5cffcf685b3d22bcba01f Mon Sep 17 00:00:00 2001 From: Leopoldo <EMAIL> Date: Sat, 23 Jan 2021 21:22:36 +0100 Subject: [PATCH 09/12] linkmap file generator: load dependency timer --- js/linkmap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/linkmap.js b/js/linkmap.js index 9f671a1..a9d82fe 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -101,10 +101,10 @@ function load_dependencies() { script.type = 'text/javascript'; script.src = `${path}js/linkmap.js`; document.body.appendChild(script); - script.onload = () => { + setInterval(() => { codeBox.value = myLinkmap; parseText(); - } + }, 500) })) } From 7d0bf0d50819f14420baee16a1bfc28e5e1534f5 Mon Sep 17 00:00:00 2001 From: Leopoldo <EMAIL> Date: Sat, 23 Jan 2021 21:23:03 +0100 Subject: [PATCH 10/12] --- js/linkmap.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/linkmap.js b/js/linkmap.js index a9d82fe..3e31b54 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -101,6 +101,10 @@ function load_dependencies() { script.type = 'text/javascript'; script.src = `${path}js/linkmap.js`; document.body.appendChild(script); + + // For some reason the load event is fired too early + // A manual timer works + // TODO: fix by triggering the proper event! setInterval(() => { codeBox.value = myLinkmap; parseText(); From 29afa3ec10655b83d9d35698f1be1042d8b18d18 Mon Sep 17 00:00:00 2001 From: Leopoldo <EMAIL> Date: Sat, 23 Jan 2021 21:24:10 +0100 Subject: [PATCH 11/12] fix timer --- js/linkmap.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/linkmap.js b/js/linkmap.js index 3e31b54..7fbc552 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -105,7 +105,7 @@ function load_dependencies() { // For some reason the load event is fired too early // A manual timer works // TODO: fix by triggering the proper event! - setInterval(() => { + setTimeout(() => { codeBox.value = myLinkmap; parseText(); }, 500) From 66ed1b2da862ad3f9d787cc0650e238e206f0189 Mon Sep 17 00:00:00 2001 From: Leopoldo <EMAIL> Date: Sat, 23 Jan 2021 21:26:15 +0100 Subject: [PATCH 12/12] absolute URL --- js/linkmap.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/linkmap.js b/js/linkmap.js index 7fbc552..77a634a 100644 --- a/js/linkmap.js +++ b/js/linkmap.js @@ -76,7 +76,9 @@ iconEditing.onclick = (e) => { // Download current text to user's disk let iconSave = document.querySelector("#icon-save"); iconSave.onclick = function () { - var path = document.URL.replace("linkmap.html", "") + // var path = document.URL.replace("linkmap.html", "") + // Always include the correct absolute path + var path = "https://lsarra.github.io/linkmap/" var doc = `<a>${path}</a> <code>${codeBox.value}</code>