forked from cory/tildefriends
95 lines
1.9 KiB
JavaScript
95 lines
1.9 KiB
JavaScript
function textNode(text) {
|
|
const node = new commonmark.Node('text', undefined);
|
|
node.literal = text;
|
|
return node;
|
|
}
|
|
|
|
function linkNode(text, link) {
|
|
const linkNode = new commonmark.Node('link', undefined);
|
|
if (link.startsWith('#')) {
|
|
linkNode.destination = `#${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');
|
|
|
|
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 regex = new RegExp('(?:https?://[^ ]+[^ .,])|(?:(?<!\\w)#[\\w-]+)|(?:@[A-Za-z0-9+/]+=.ed25519)|(?:[%&][A-Za-z0-9+/]+=.sha256)');
|
|
|
|
function split(textNodes) {
|
|
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]);
|
|
}
|
|
});
|
|
}
|
|
|
|
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) {
|
|
split(nodes)
|
|
.reverse()
|
|
.forEach((newNode) => {
|
|
nodes[0].insertAfter(newNode);
|
|
});
|
|
|
|
nodes.forEach((n) => n.unlink());
|
|
nodes = [];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nodes.length > 0) {
|
|
split(nodes)
|
|
.reverse()
|
|
.forEach((newNode) => {
|
|
nodes[0].insertAfter(newNode);
|
|
});
|
|
nodes.forEach((n) => n.unlink());
|
|
}
|
|
|
|
return parsed;
|
|
}
|