92 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			92 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								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;
							 | 
						||
| 
								 | 
							
								}
							 |