From 4c8d24c319091a11b4472c12e3efbad427a25bb4 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Thu, 4 Apr 2024 00:18:39 +0100 Subject: [PATCH] Consolidate markdown linkification, and add support for authors, blobs, and messages. --- apps/ssb.json | 2 +- apps/ssb/commonmark-hashtag.js | 130 +++++++++++++++++---------------- apps/ssb/commonmark-linkify.js | 91 ----------------------- apps/ssb/index.html | 1 - apps/ssb/tf-utils.js | 2 - 5 files changed, 68 insertions(+), 158 deletions(-) delete mode 100644 apps/ssb/commonmark-linkify.js diff --git a/apps/ssb.json b/apps/ssb.json index 593a2dfb..71608ef3 100644 --- a/apps/ssb.json +++ b/apps/ssb.json @@ -1,5 +1,5 @@ { "type": "tildefriends-app", "emoji": "🐌", - "previous": "&Xs1X5TzLCk6KVr+5IDc80JAHYxJyoD10cXKBUYpFqWQ=.sha256" + "previous": "&0WzpczDOhxawXBY8fAPMQWwOuF8bVRO+cMJJTxBpYOQ=.sha256" } diff --git a/apps/ssb/commonmark-hashtag.js b/apps/ssb/commonmark-hashtag.js index 824cbb7a..32df77fe 100644 --- a/apps/ssb/commonmark-hashtag.js +++ b/apps/ssb/commonmark-hashtag.js @@ -1,90 +1,94 @@ function textNode(text) { - const node = new commonmark.Node("text", undefined); - node.literal = text; - return node; + const node = new commonmark.Node('text', undefined); + node.literal = text; + return node; } function linkNode(text, link) { - const linkNode = new commonmark.Node("link", undefined); - linkNode.destination = `#q=${encodeURIComponent(link)}`; - linkNode.appendChild(textNode(text)); - return linkNode; + const linkNode = new commonmark.Node('link', undefined); + if (link.startsWith('#')) { + linkNode.destination = `#q=${encodeURIComponent(link)}`; + } else { + linkNode.destination = link; + } + linkNode.appendChild(textNode(text)); + return linkNode; } function splitMatches(text, regexp) { - // Regexp must be sticky. - regexp = new RegExp(regexp, "gm"); + // Regexp must be sticky. + regexp = new RegExp(regexp, 'gm'); - let i = 0; - const result = []; + let i = 0; + const result = []; - let match = regexp.exec(text); - while (match) { - const matchText = match[0]; + let match = regexp.exec(text); + while (match) { + const matchText = match[0]; - if (match.index > i) { - result.push([text.substring(i, match.index), false]); - } + if (match.index > i) { + result.push([text.substring(i, match.index), false]); + } - result.push([matchText, true]); - i = match.index + matchText.length; + result.push([matchText, true]); + i = match.index + matchText.length; - match = regexp.exec(text); - } + match = regexp.exec(text); + } - if (i < text.length) { - result.push([text.substring(i, text.length), false]); - } + if (i < text.length) { + result.push([text.substring(i, text.length), false]); + } - return result; + return result; } -const regex = new RegExp("(? n.literal).join(""); - const parts = splitMatches(text, regex); + const text = textNodes.map((n) => n.literal).join(''); + const parts = splitMatches(text, regex); - return parts.map(part => { - if (part[1]) { - return linkNode(part[0], part[0]); - } else { - return textNode(part[0]); - } - }); + return parts.map((part) => { + if (part[1]) { + return linkNode(part[0], part[0]); + } else { + return textNode(part[0]); + } + }); } export function transform(parsed) { - const walker = parsed.walker(); - let event; + const walker = parsed.walker(); + let event; - let nodes = []; - while ((event = walker.next())) { - const node = event.node; - if (event.entering && node.type === "text") { - nodes.push(node); - } else { - if (nodes.length > 0) { - split(nodes) - .reverse() - .forEach(newNode => { - nodes[0].insertAfter(newNode); - }); + let nodes = []; + while ((event = walker.next())) { + const node = event.node; + if (event.entering && node.type === 'text') { + nodes.push(node); + } else { + if (nodes.length > 0) { + split(nodes) + .reverse() + .forEach((newNode) => { + nodes[0].insertAfter(newNode); + }); - nodes.forEach(n => n.unlink()); - nodes = []; - } - } - } + nodes.forEach((n) => n.unlink()); + nodes = []; + } + } + } - if (nodes.length > 0) { - split(nodes) - .reverse() - .forEach(newNode => { - nodes[0].insertAfter(newNode); - }); - nodes.forEach(n => n.unlink()); - } + if (nodes.length > 0) { + split(nodes) + .reverse() + .forEach((newNode) => { + nodes[0].insertAfter(newNode); + }); + nodes.forEach((n) => n.unlink()); + } - return parsed; + return parsed; } diff --git a/apps/ssb/commonmark-linkify.js b/apps/ssb/commonmark-linkify.js deleted file mode 100644 index decdbf0b..00000000 --- a/apps/ssb/commonmark-linkify.js +++ /dev/null @@ -1,91 +0,0 @@ -function textNode(text) { - const node = new commonmark.Node("text", undefined); - node.literal = text; - return node; -} - -function linkNode(text, url) { - const urlNode = new commonmark.Node("link", undefined); - urlNode.destination = url; - urlNode.appendChild(textNode(text)); - - return urlNode; -} - -function splitMatches(text, regexp) { - // Regexp must be sticky. - regexp = new RegExp(regexp, "gm"); - - let i = 0; - const result = []; - - let match = regexp.exec(text); - while (match) { - const matchText = match[0]; - - if (match.index > i) { - result.push([text.substring(i, match.index), false]); - } - - result.push([matchText, true]); - i = match.index + matchText.length; - - match = regexp.exec(text); - } - - if (i < text.length) { - result.push([text.substring(i, text.length), false]); - } - - return result; -} - -const urlRegexp = new RegExp("https?://[^ ]+[^ .,]"); - -function splitURLs(textNodes) { - const text = textNodes.map(n => n.literal).join(""); - const parts = splitMatches(text, urlRegexp); - - return parts.map(part => { - if (part[1]) { - return linkNode(part[0], part[0]); - } else { - return textNode(part[0]); - } - }); -} - -export function transform(parsed) { - const walker = parsed.walker(); - let event; - - let nodes = []; - while ((event = walker.next())) { - const node = event.node; - if (event.entering && node.type === "text") { - nodes.push(node); - } else { - if (nodes.length > 0) { - splitURLs(nodes) - .reverse() - .forEach(newNode => { - nodes[0].insertAfter(newNode); - }); - - nodes.forEach(n => n.unlink()); - nodes = []; - } - } - } - - if (nodes.length > 0) { - splitURLs(nodes) - .reverse() - .forEach(newNode => { - nodes[0].insertAfter(newNode); - }); - nodes.forEach(n => n.unlink()); - } - - return parsed; -} diff --git a/apps/ssb/index.html b/apps/ssb/index.html index fc8fb9e1..35a782dd 100644 --- a/apps/ssb/index.html +++ b/apps/ssb/index.html @@ -17,7 +17,6 @@ - diff --git a/apps/ssb/tf-utils.js b/apps/ssb/tf-utils.js index e0539480..6b0e280a 100644 --- a/apps/ssb/tf-utils.js +++ b/apps/ssb/tf-utils.js @@ -1,4 +1,3 @@ -import * as linkify from './commonmark-linkify.js'; import * as hashtagify from './commonmark-hashtag.js'; function image(node, entering) { @@ -67,7 +66,6 @@ export function markdown(md) { writer.image = image; let parsed = reader.parse(md || ''); parsed = hashtagify.transform(parsed); - parsed = linkify.transform(parsed); let walker = parsed.walker(); let event, node; while ((event = walker.next())) {