From 8ec288fa2738519211a5e254b9c540c52c4c6e14 Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Wed, 4 Sep 2024 14:35:12 +0200 Subject: [PATCH 01/12] fix(gnoweb): replace & to & --- gno.land/pkg/gnoweb/static/js/renderer.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gno.land/pkg/gnoweb/static/js/renderer.js b/gno.land/pkg/gnoweb/static/js/renderer.js index 0aa6400633d..d2514096f4f 100644 --- a/gno.land/pkg/gnoweb/static/js/renderer.js +++ b/gno.land/pkg/gnoweb/static/js/renderer.js @@ -9,6 +9,9 @@ function renderUsernames(raw) { function parseContent(source, isCode) { if (isCode) { + // replace &r; with & in code blocks + source = source.replace(/&/g, "&"); + const highlightedCode = hljs.highlightAuto(source).value; const codeElement = document.createElement("code"); codeElement.classList.add("hljs"); From 394a99faa4b6d3c7e22575959d964a2f663236c6 Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Wed, 4 Sep 2024 14:42:56 +0200 Subject: [PATCH 02/12] feat(gnoweb): link to modules --- gno.land/pkg/gnoweb/static/js/renderer.js | 31 ++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/gno.land/pkg/gnoweb/static/js/renderer.js b/gno.land/pkg/gnoweb/static/js/renderer.js index d2514096f4f..ab2bd8c0fcf 100644 --- a/gno.land/pkg/gnoweb/static/js/renderer.js +++ b/gno.land/pkg/gnoweb/static/js/renderer.js @@ -13,9 +13,38 @@ function parseContent(source, isCode) { source = source.replace(/&/g, "&"); const highlightedCode = hljs.highlightAuto(source).value; + + const parser = new DOMParser(); + const doc = parser.parseFromString(highlightedCode, "text/html"); + // get all span nodes of class hljs-keyword and a value of 'import' + const nodes = doc.querySelectorAll("span.hljs-keyword"); + for (const node of nodes) { + if (node.textContent === "import") { + // skip "(" + let nextNode = node.nextElementSibling; + while (true) { + nextNode = nextNode.nextElementSibling; + if (nextNode) { + if (nextNode.textContent === ")") { + break; + } else if (nextNode.textContent.includes("/p") || nextNode.textContent.includes("/r")) { + const cleanPath = nextNode.textContent.replace(/(https?:\/\/)?gno\.land\/p\//, "/p/").replace(/^"|"$/g, ''); + const link = document.createElement("a"); + link.href = cleanPath; + link.className = "hljs-link"; + link.appendChild(nextNode.cloneNode(true)); + nextNode.replaceWith(link); + } + } else { + break; + } + } + } + } + const codeElement = document.createElement("code"); codeElement.classList.add("hljs"); - codeElement.innerHTML = highlightedCode; + codeElement.innerHTML = doc.body.innerHTML; const preElement = document.createElement("pre"); preElement.appendChild(codeElement); From 373ead6f78239152efb9baf952a357f2c698bac5 Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Wed, 4 Sep 2024 16:31:03 +0200 Subject: [PATCH 03/12] feat(gnoweb): counter at each line of code --- gno.land/pkg/gnoweb/static/js/renderer.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/gno.land/pkg/gnoweb/static/js/renderer.js b/gno.land/pkg/gnoweb/static/js/renderer.js index ab2bd8c0fcf..216dc85cab2 100644 --- a/gno.land/pkg/gnoweb/static/js/renderer.js +++ b/gno.land/pkg/gnoweb/static/js/renderer.js @@ -9,13 +9,25 @@ function renderUsernames(raw) { function parseContent(source, isCode) { if (isCode) { - // replace &r; with & in code blocks + // replace & with & in code blocks source = source.replace(/&/g, "&"); const highlightedCode = hljs.highlightAuto(source).value; + // Split the highlighted code into lines + const lines = highlightedCode.split('\n'); + + // Add line numbers to each line + const numberedLines = lines.map((line, index) => { + return `${index + 1} ${line}`; + }); + + // Join the lines back into a single string + const numberedCode = numberedLines.join('\n'); + const parser = new DOMParser(); - const doc = parser.parseFromString(highlightedCode, "text/html"); + const doc = parser.parseFromString(numberedCode, "text/html"); + // get all span nodes of class hljs-keyword and a value of 'import' const nodes = doc.querySelectorAll("span.hljs-keyword"); for (const node of nodes) { From 0565c535074c55da8e459d697078c127aac374df Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Fri, 13 Sep 2024 17:00:23 +0200 Subject: [PATCH 04/12] fix: all imported realms or packages are taken into account --- gno.land/pkg/gnoweb/static/js/renderer.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gno.land/pkg/gnoweb/static/js/renderer.js b/gno.land/pkg/gnoweb/static/js/renderer.js index 216dc85cab2..64ff012229c 100644 --- a/gno.land/pkg/gnoweb/static/js/renderer.js +++ b/gno.land/pkg/gnoweb/static/js/renderer.js @@ -32,12 +32,11 @@ function parseContent(source, isCode) { const nodes = doc.querySelectorAll("span.hljs-keyword"); for (const node of nodes) { if (node.textContent === "import") { - // skip "(" - let nextNode = node.nextElementSibling; + let nextNode = node; while (true) { - nextNode = nextNode.nextElementSibling; + nextNode = nextNode.nextSibling; if (nextNode) { - if (nextNode.textContent === ")") { + if (nextNode.textContent.includes(")")) { break; } else if (nextNode.textContent.includes("/p") || nextNode.textContent.includes("/r")) { const cleanPath = nextNode.textContent.replace(/(https?:\/\/)?gno\.land\/p\//, "/p/").replace(/^"|"$/g, ''); @@ -46,6 +45,7 @@ function parseContent(source, isCode) { link.className = "hljs-link"; link.appendChild(nextNode.cloneNode(true)); nextNode.replaceWith(link); + nextNode = link; } } else { break; From b94ae0ac0ad3acafe3b095940a84292565447baa Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Fri, 13 Sep 2024 18:06:45 +0200 Subject: [PATCH 05/12] style(gnoweb): hljs-link now only underline on hover --- gno.land/pkg/gnoweb/static/css/app.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gno.land/pkg/gnoweb/static/css/app.css b/gno.land/pkg/gnoweb/static/css/app.css index c10fc8ec0e0..a72f0b03da1 100644 --- a/gno.land/pkg/gnoweb/static/css/app.css +++ b/gno.land/pkg/gnoweb/static/css/app.css @@ -825,6 +825,13 @@ code.hljs { color: var(--highlight-variable, #54790d); } +.hljs-link { + text-decoration: none; /* Remove underline by default */ +} +.hljs-link:hover { + text-decoration: underline; /* Add underline on hover */ +} + .hljs-meta, .hljs-selector-pseudo { color: var(--highlight-keyword, #015692); From 53918b48282d5dc8dc71d39240e61ee30631bf09 Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Fri, 13 Sep 2024 18:07:20 +0200 Subject: [PATCH 06/12] feat(gnoweb): '"' are not underlined in code viewer --- gno.land/pkg/gnoweb/static/js/renderer.js | 47 +++++++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/gno.land/pkg/gnoweb/static/js/renderer.js b/gno.land/pkg/gnoweb/static/js/renderer.js index 64ff012229c..5afb853612c 100644 --- a/gno.land/pkg/gnoweb/static/js/renderer.js +++ b/gno.land/pkg/gnoweb/static/js/renderer.js @@ -7,6 +7,14 @@ function renderUsernames(raw) { return raw.replace(/( |\n)@([_a-z0-9]{5,16})/, "$1[@$2](/r/demo/users:$2)"); } +// Create text nodes for the quotes with class names +const createQuoteNode = (quote) => { + const node = document.createElement("span"); + node.textContent = quote; + node.className = "hljs-string"; + return node; +}; + function parseContent(source, isCode) { if (isCode) { // replace & with & in code blocks @@ -32,24 +40,47 @@ function parseContent(source, isCode) { const nodes = doc.querySelectorAll("span.hljs-keyword"); for (const node of nodes) { if (node.textContent === "import") { - let nextNode = node; + let nextNode = node.nextSibling; while (true) { - nextNode = nextNode.nextSibling; if (nextNode) { if (nextNode.textContent.includes(")")) { break; } else if (nextNode.textContent.includes("/p") || nextNode.textContent.includes("/r")) { + const nextSibling = nextNode.nextSibling; const cleanPath = nextNode.textContent.replace(/(https?:\/\/)?gno\.land\/p\//, "/p/").replace(/^"|"$/g, ''); - const link = document.createElement("a"); - link.href = cleanPath; - link.className = "hljs-link"; - link.appendChild(nextNode.cloneNode(true)); - nextNode.replaceWith(link); - nextNode = link; + // Extract the text content + const textContent = nextNode.textContent; + + // Split the text content into parts + const openingQuote = textContent.charAt(0); + const mainContent = textContent.slice(1, -1); + const closingQuote = textContent.charAt(textContent.length - 1); + + // Create text nodes for the quotes + const openingQuoteNode = createQuoteNode(openingQuote); + const closingQuoteNode = createQuoteNode(closingQuote); + + // Create a span for the main content and add the hljs-link class + const mainContentNode = document.createElement("span"); + mainContentNode.className = "hljs-link"; + mainContentNode.textContent = mainContent; + mainContentNode.href = cleanPath; + + // Create a document fragment to hold the new nodes + const fragment = document.createElement("span"); + fragment.appendChild(openingQuoteNode); + fragment.appendChild(mainContentNode); + fragment.appendChild(closingQuoteNode); + + // Replace the original node with the new nodes + nextNode.replaceWith(fragment); + nextNode = nextSibling; + continue; } } else { break; } + nextNode = nextNode.nextSibling; } } } From dd272bdae5a7a186ae81d9521e1878f26cc834f2 Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Fri, 13 Sep 2024 18:34:27 +0200 Subject: [PATCH 07/12] fix(gnoweb): replace span to a for href to works in imports --- gno.land/pkg/gnoweb/static/js/renderer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gno.land/pkg/gnoweb/static/js/renderer.js b/gno.land/pkg/gnoweb/static/js/renderer.js index 5afb853612c..e7241fe9b20 100644 --- a/gno.land/pkg/gnoweb/static/js/renderer.js +++ b/gno.land/pkg/gnoweb/static/js/renderer.js @@ -9,7 +9,7 @@ function renderUsernames(raw) { // Create text nodes for the quotes with class names const createQuoteNode = (quote) => { - const node = document.createElement("span"); + const node = document.createElement("a"); node.textContent = quote; node.className = "hljs-string"; return node; @@ -61,7 +61,7 @@ function parseContent(source, isCode) { const closingQuoteNode = createQuoteNode(closingQuote); // Create a span for the main content and add the hljs-link class - const mainContentNode = document.createElement("span"); + const mainContentNode = document.createElement("a"); mainContentNode.className = "hljs-link"; mainContentNode.textContent = mainContent; mainContentNode.href = cleanPath; From a92ba96f6e8350b25e431a5bc3ec2a32860424ad Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Sat, 28 Sep 2024 19:17:19 +0200 Subject: [PATCH 08/12] refactor: remove import link logic --- gno.land/pkg/gnoweb/static/js/renderer.js | 49 ----------------------- 1 file changed, 49 deletions(-) diff --git a/gno.land/pkg/gnoweb/static/js/renderer.js b/gno.land/pkg/gnoweb/static/js/renderer.js index e7241fe9b20..b4e7648ac9e 100644 --- a/gno.land/pkg/gnoweb/static/js/renderer.js +++ b/gno.land/pkg/gnoweb/static/js/renderer.js @@ -36,55 +36,6 @@ function parseContent(source, isCode) { const parser = new DOMParser(); const doc = parser.parseFromString(numberedCode, "text/html"); - // get all span nodes of class hljs-keyword and a value of 'import' - const nodes = doc.querySelectorAll("span.hljs-keyword"); - for (const node of nodes) { - if (node.textContent === "import") { - let nextNode = node.nextSibling; - while (true) { - if (nextNode) { - if (nextNode.textContent.includes(")")) { - break; - } else if (nextNode.textContent.includes("/p") || nextNode.textContent.includes("/r")) { - const nextSibling = nextNode.nextSibling; - const cleanPath = nextNode.textContent.replace(/(https?:\/\/)?gno\.land\/p\//, "/p/").replace(/^"|"$/g, ''); - // Extract the text content - const textContent = nextNode.textContent; - - // Split the text content into parts - const openingQuote = textContent.charAt(0); - const mainContent = textContent.slice(1, -1); - const closingQuote = textContent.charAt(textContent.length - 1); - - // Create text nodes for the quotes - const openingQuoteNode = createQuoteNode(openingQuote); - const closingQuoteNode = createQuoteNode(closingQuote); - - // Create a span for the main content and add the hljs-link class - const mainContentNode = document.createElement("a"); - mainContentNode.className = "hljs-link"; - mainContentNode.textContent = mainContent; - mainContentNode.href = cleanPath; - - // Create a document fragment to hold the new nodes - const fragment = document.createElement("span"); - fragment.appendChild(openingQuoteNode); - fragment.appendChild(mainContentNode); - fragment.appendChild(closingQuoteNode); - - // Replace the original node with the new nodes - nextNode.replaceWith(fragment); - nextNode = nextSibling; - continue; - } - } else { - break; - } - nextNode = nextNode.nextSibling; - } - } - } - const codeElement = document.createElement("code"); codeElement.classList.add("hljs"); codeElement.innerHTML = doc.body.innerHTML; From c79bdc383e8f5a52329fcc409d2000fc32d3fb0b Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Sat, 28 Sep 2024 19:29:37 +0200 Subject: [PATCH 09/12] style: make the line number not selectable --- gno.land/pkg/gnoweb/static/css/app.css | 9 +++++++++ gno.land/pkg/gnoweb/static/js/renderer.js | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/gno.land/pkg/gnoweb/static/css/app.css b/gno.land/pkg/gnoweb/static/css/app.css index a72f0b03da1..0223f29e9a2 100644 --- a/gno.land/pkg/gnoweb/static/css/app.css +++ b/gno.land/pkg/gnoweb/static/css/app.css @@ -756,6 +756,15 @@ code { margin-left: 1.5rem; } +.not-selectable { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + /*** HLJS ***/ /* Copyright (c) 2006, Ivan Sagalaev. diff --git a/gno.land/pkg/gnoweb/static/js/renderer.js b/gno.land/pkg/gnoweb/static/js/renderer.js index b4e7648ac9e..5a4b993e32b 100644 --- a/gno.land/pkg/gnoweb/static/js/renderer.js +++ b/gno.land/pkg/gnoweb/static/js/renderer.js @@ -27,7 +27,7 @@ function parseContent(source, isCode) { // Add line numbers to each line const numberedLines = lines.map((line, index) => { - return `${index + 1} ${line}`; + return `${index + 1} ${line}`; }); // Join the lines back into a single string From ba13a934348264a5dca3ebdcbe37392d4d2affb5 Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Sat, 28 Sep 2024 19:31:42 +0200 Subject: [PATCH 10/12] feat: give the innerText instead of innerHTML to the renderer --- gno.land/pkg/gnoweb/views/funcs.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gno.land/pkg/gnoweb/views/funcs.html b/gno.land/pkg/gnoweb/views/funcs.html index d676fec9a69..04de6a6c39c 100644 --- a/gno.land/pkg/gnoweb/views/funcs.html +++ b/gno.land/pkg/gnoweb/views/funcs.html @@ -172,7 +172,7 @@ const extension = window.location.pathname.split(".").pop(); const isCode = key === "package_render" && extension !== "md"; - const parsed = parseContent(document.getElementById("source").innerHTML, isCode); + const parsed = parseContent(document.getElementById("source").innerText, isCode); el.innerHTML = DOMPurify.sanitize(parsed, { USE_PROFILES: { html: true } }); } } From ce603b9c6eb28ae50d9e410219fa63a58d7ee88f Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Sat, 28 Sep 2024 19:34:30 +0200 Subject: [PATCH 11/12] feat: remove hljs-link css override --- gno.land/pkg/gnoweb/static/css/app.css | 7 ------- 1 file changed, 7 deletions(-) diff --git a/gno.land/pkg/gnoweb/static/css/app.css b/gno.land/pkg/gnoweb/static/css/app.css index 0223f29e9a2..82f0c615a52 100644 --- a/gno.land/pkg/gnoweb/static/css/app.css +++ b/gno.land/pkg/gnoweb/static/css/app.css @@ -834,13 +834,6 @@ code.hljs { color: var(--highlight-variable, #54790d); } -.hljs-link { - text-decoration: none; /* Remove underline by default */ -} -.hljs-link:hover { - text-decoration: underline; /* Add underline on hover */ -} - .hljs-meta, .hljs-selector-pseudo { color: var(--highlight-keyword, #015692); From eb78a371e9f67f8f0063e1e77e277234f9ed0f61 Mon Sep 17 00:00:00 2001 From: 0xtekgrinder <0xtekgrinder@protonmail.com> Date: Sat, 28 Sep 2024 19:34:45 +0200 Subject: [PATCH 12/12] feat: remove temporary fix for & inside renderer --- gno.land/pkg/gnoweb/static/js/renderer.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/gno.land/pkg/gnoweb/static/js/renderer.js b/gno.land/pkg/gnoweb/static/js/renderer.js index 5a4b993e32b..7b3b9b8840e 100644 --- a/gno.land/pkg/gnoweb/static/js/renderer.js +++ b/gno.land/pkg/gnoweb/static/js/renderer.js @@ -17,9 +17,6 @@ const createQuoteNode = (quote) => { function parseContent(source, isCode) { if (isCode) { - // replace & with & in code blocks - source = source.replace(/&/g, "&"); - const highlightedCode = hljs.highlightAuto(source).value; // Split the highlighted code into lines