Skip to content

Commit

Permalink
Perform only necessary modifications
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergei Zharinov committed Aug 11, 2021
1 parent ff740b2 commit 60c2e2f
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 39 deletions.
14 changes: 14 additions & 0 deletions lib/platform/github/massage-markdown-links.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@ import { getName } from '../../../test/util';
import { massageMarkdownLinks } from './massage-markdown-links';

describe(getName(), () => {
it('performs multiple replacements', () => {
const input = [
'Link [foo/bar#1](https://github.com/foo/bar/pull/1) points to https://github.com/foo/bar/pull/1.',
'URL https://github.com/foo/bar/pull/1 becomes [foo/bar#1](https://github.com/foo/bar/pull/1).',
].join('\n');
const res = massageMarkdownLinks(input);
expect(res).toEqual(
[
'Link [foo/bar#1](https://togithub.com/foo/bar/pull/1) points to [https://github.com/foo/bar/pull/1](https://togithub.com/foo/bar/pull/1).',
'URL [https://github.com/foo/bar/pull/1](https://togithub.com/foo/bar/pull/1) becomes [foo/bar#1](https://togithub.com/foo/bar/pull/1).',
].join('\n')
);
});

test.each`
input
${'github.com'}
Expand Down
95 changes: 60 additions & 35 deletions lib/platform/github/massage-markdown-links.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,79 @@
import findAndReplace from 'mdast-util-find-and-replace';
import is from '@sindresorhus/is';
import remark from 'remark';
import type { Plugin, Transformer } from 'unified';
// eslint-disable-next-line import/no-unresolved
import type { Node } from 'unist';
import visit from 'unist-util-visit';
import type { Plugin } from 'unified';
import { logger } from '../../logger';

interface UrlMatch {
start: number;
end: number;
replaceTo: string;
}

const urlRegex =
/(?:https?:)?(?:\/\/)?(?:www\.)?(?<!api\.)(?:to)?github\.com\/[-_a-z0-9]+\/[-_a-z0-9]+\/(?:discussions|issues|pull)\/[0-9]+(?:#[-_a-z0-9]+)?/i;

function massageLink(input: string): string {
return urlRegex.test(input)
? input.replace(/(?:to)?github\.com/, 'togithub.com')
: /* istanbul ignore next */
input;
return input.replace(/(?:to)?github\.com/i, 'togithub.com');
}

function linkifyText(url: string): Node | boolean {
const newUrl = massageLink(url);
if (newUrl !== url) {
const content = { type: 'text', value: url };
return {
type: 'link',
url: newUrl,
title: null,
children: [content],
} as Node;
}
return false;
}
function collectLinkPosition(input: string, matches: UrlMatch[]): Plugin<any> {
const transformer = (tree: any): void => {
const type = tree.type;
const children = is.array<any>(tree.children) ? tree.children : [];
const startOffset: number = tree.position.start.offset;
const endOffset: number = tree.position.end.offset;

if (type === 'link') {
const substr = input.slice(startOffset, endOffset);
const url: string = tree.url;
const offset: number = startOffset + substr.lastIndexOf(url);
if (urlRegex.test(url)) {
matches.push({
start: offset,
end: offset + url.length,
replaceTo: massageLink(url),
});
}
} else if (type === 'text') {
let text: string = tree.value;
let match = urlRegex.exec(text);
let currentOffset = 0;
while (match) {
const [url] = match;

function transformer(tree: Node): void {
findAndReplace(tree, urlRegex, linkifyText, {
ignore: ['link', 'linkReference'],
});
visit(tree, 'link', (node: any) => {
if (node?.url) {
// eslint-disable-next-line no-param-reassign
node.url = massageLink(node.url);
currentOffset += match.index;
const start = startOffset + currentOffset;

currentOffset += url.length;
const end = startOffset + currentOffset;

const newUrl = massageLink(url);
matches.push({ start, end, replaceTo: `[${url}](${newUrl})` });

text = text.slice(currentOffset);
match = urlRegex.exec(text);
}
} else {
children.forEach((child) => {
transformer(child);
});
}
});
}
};

const githubExtra: Plugin<any> = (): Transformer => transformer;
return () => transformer;
}

export function massageMarkdownLinks(content: string): string {
try {
const output = remark().use(githubExtra).processSync(content);
const rightSpaces = content.replace(content.trimRight(), '');
return output.toString().trimRight() + rightSpaces;
const matches: UrlMatch[] = [];
remark().use(collectLinkPosition(content, matches)).processSync(content);
const result = matches.reduceRight((acc, { start, end, replaceTo }) => {
const leftPart = acc.slice(0, start);
const rightPart = acc.slice(end);
return leftPart + replaceTo + rightPart;
}, content);
return result.trimRight() + rightSpaces;
} catch (err) /* istanbul ignore next */ {
logger.warn({ err }, `Unable to massage markdown text`);
return content;
Expand Down
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@
"luxon": "2.0.1",
"markdown-it": "12.2.0",
"markdown-table": "2.0.0",
"mdast-util-find-and-replace": "1.1.1",
"minimatch": "3.0.4",
"moo": "0.5.1",
"node-html-parser": "3.3.6",
Expand All @@ -188,7 +187,6 @@
"simple-git": "2.42.0",
"slugify": "1.6.0",
"traverse": "0.6.6",
"unist-util-visit": "2.0.3",
"upath": "2.0.1",
"url-join": "4.0.1",
"validate-npm-package-name": "3.0.0",
Expand Down
4 changes: 2 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6507,7 +6507,7 @@ matcher@^3.0.0:
dependencies:
escape-string-regexp "^4.0.0"

mdast-util-find-and-replace@1.1.1, mdast-util-find-and-replace@^1.0.0:
mdast-util-find-and-replace@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz#b7db1e873f96f66588c321f1363069abf607d1b5"
integrity sha512-9cKl33Y21lyckGzpSmEQnIDjEfeeWelN5s1kUW1LwdB0Fkuq2u+4GdqcGEygYxJE8GVqCl0741bYXHgamfWAZA==
Expand Down Expand Up @@ -9455,7 +9455,7 @@ unist-util-visit-parents@^3.0.0:
"@types/unist" "^2.0.0"
unist-util-is "^4.0.0"

unist-util-visit@2.0.3, unist-util-visit@^2.0.0:
unist-util-visit@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c"
integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==
Expand Down

0 comments on commit 60c2e2f

Please sign in to comment.