forked from cory/tildefriends
Consolidate markdown linkification, and add support for authors, blobs, and messages.
This commit is contained in:
parent
e50144bd34
commit
4c8d24c319
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🐌",
|
"emoji": "🐌",
|
||||||
"previous": "&Xs1X5TzLCk6KVr+5IDc80JAHYxJyoD10cXKBUYpFqWQ=.sha256"
|
"previous": "&0WzpczDOhxawXBY8fAPMQWwOuF8bVRO+cMJJTxBpYOQ=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
function textNode(text) {
|
function textNode(text) {
|
||||||
const node = new commonmark.Node("text", undefined);
|
const node = new commonmark.Node('text', undefined);
|
||||||
node.literal = text;
|
node.literal = text;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
function linkNode(text, link) {
|
function linkNode(text, link) {
|
||||||
const linkNode = new commonmark.Node("link", undefined);
|
const linkNode = new commonmark.Node('link', undefined);
|
||||||
|
if (link.startsWith('#')) {
|
||||||
linkNode.destination = `#q=${encodeURIComponent(link)}`;
|
linkNode.destination = `#q=${encodeURIComponent(link)}`;
|
||||||
|
} else {
|
||||||
|
linkNode.destination = link;
|
||||||
|
}
|
||||||
linkNode.appendChild(textNode(text));
|
linkNode.appendChild(textNode(text));
|
||||||
return linkNode;
|
return linkNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function splitMatches(text, regexp) {
|
function splitMatches(text, regexp) {
|
||||||
// Regexp must be sticky.
|
// Regexp must be sticky.
|
||||||
regexp = new RegExp(regexp, "gm");
|
regexp = new RegExp(regexp, 'gm');
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
const result = [];
|
const result = [];
|
||||||
@ -39,13 +43,13 @@ function splitMatches(text, regexp) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const regex = new RegExp("(?<!\\w)#[\\w-]+");
|
const regex = new RegExp('(?:https?://[^ ]+[^ .,])|(?:(?<!\\w)#[\\w-]+)|(?:@[A-Za-z0-9+/]+=.ed25519)|(?:[%&][A-Za-z0-9+/]+=.sha256)');
|
||||||
|
|
||||||
function split(textNodes) {
|
function split(textNodes) {
|
||||||
const text = textNodes.map(n => n.literal).join("");
|
const text = textNodes.map((n) => n.literal).join('');
|
||||||
const parts = splitMatches(text, regex);
|
const parts = splitMatches(text, regex);
|
||||||
|
|
||||||
return parts.map(part => {
|
return parts.map((part) => {
|
||||||
if (part[1]) {
|
if (part[1]) {
|
||||||
return linkNode(part[0], part[0]);
|
return linkNode(part[0], part[0]);
|
||||||
} else {
|
} else {
|
||||||
@ -61,17 +65,17 @@ export function transform(parsed) {
|
|||||||
let nodes = [];
|
let nodes = [];
|
||||||
while ((event = walker.next())) {
|
while ((event = walker.next())) {
|
||||||
const node = event.node;
|
const node = event.node;
|
||||||
if (event.entering && node.type === "text") {
|
if (event.entering && node.type === 'text') {
|
||||||
nodes.push(node);
|
nodes.push(node);
|
||||||
} else {
|
} else {
|
||||||
if (nodes.length > 0) {
|
if (nodes.length > 0) {
|
||||||
split(nodes)
|
split(nodes)
|
||||||
.reverse()
|
.reverse()
|
||||||
.forEach(newNode => {
|
.forEach((newNode) => {
|
||||||
nodes[0].insertAfter(newNode);
|
nodes[0].insertAfter(newNode);
|
||||||
});
|
});
|
||||||
|
|
||||||
nodes.forEach(n => n.unlink());
|
nodes.forEach((n) => n.unlink());
|
||||||
nodes = [];
|
nodes = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,10 +84,10 @@ export function transform(parsed) {
|
|||||||
if (nodes.length > 0) {
|
if (nodes.length > 0) {
|
||||||
split(nodes)
|
split(nodes)
|
||||||
.reverse()
|
.reverse()
|
||||||
.forEach(newNode => {
|
.forEach((newNode) => {
|
||||||
nodes[0].insertAfter(newNode);
|
nodes[0].insertAfter(newNode);
|
||||||
});
|
});
|
||||||
nodes.forEach(n => n.unlink());
|
nodes.forEach((n) => n.unlink());
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsed;
|
return parsed;
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -17,7 +17,6 @@
|
|||||||
</script>
|
</script>
|
||||||
<script src="filesaver.min.js"></script>
|
<script src="filesaver.min.js"></script>
|
||||||
<script src="commonmark.min.js"></script>
|
<script src="commonmark.min.js"></script>
|
||||||
<script src="commonmark-linkify.js" type="module"></script>
|
|
||||||
<script src="commonmark-hashtag.js" type="module"></script>
|
<script src="commonmark-hashtag.js" type="module"></script>
|
||||||
<script src="script.js" type="module"></script>
|
<script src="script.js" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import * as linkify from './commonmark-linkify.js';
|
|
||||||
import * as hashtagify from './commonmark-hashtag.js';
|
import * as hashtagify from './commonmark-hashtag.js';
|
||||||
|
|
||||||
function image(node, entering) {
|
function image(node, entering) {
|
||||||
@ -67,7 +66,6 @@ export function markdown(md) {
|
|||||||
writer.image = image;
|
writer.image = image;
|
||||||
let parsed = reader.parse(md || '');
|
let parsed = reader.parse(md || '');
|
||||||
parsed = hashtagify.transform(parsed);
|
parsed = hashtagify.transform(parsed);
|
||||||
parsed = linkify.transform(parsed);
|
|
||||||
let walker = parsed.walker();
|
let walker = parsed.walker();
|
||||||
let event, node;
|
let event, node;
|
||||||
while ((event = walker.next())) {
|
while ((event = walker.next())) {
|
||||||
|
Loading…
Reference in New Issue
Block a user