Skip to content

Commit 63bcaf3

Browse files
util: add diff URL parser
1 parent dc02cda commit 63bcaf3

4 files changed

Lines changed: 370 additions & 27 deletions

File tree

src/modules/ante/ui/pages/CopiedTemplateRowPage.tsx

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import RevisionDateGetButton from '../components/RevisionDateGetButton';
1616
import SmartTitleInputWidget from '../components/SmartTitleInputWidget';
1717
import PageLatestRevisionGetButton from '../components/PageLatestRevisionGetButton';
1818
import dangerModeConfirm from '../../../../util/dangerModeConfirm';
19+
import parseDiffUrl from '../../../../wiki/util/parseDiffUrl';
1920

2021
export interface CopiedTemplateRowPageData {
2122
/**
@@ -551,33 +552,12 @@ function initCopiedTemplateRowPage() {
551552
return;
552553
}
553554
}
554-
// From the same wiki, accept deprecation
555-
556-
// Attempt to get values from URL parameters (when using `/w/index.php?action=diff`)
557-
let oldid = url.searchParams.get( 'oldid' );
558-
let diff = url.searchParams.get( 'diff' );
559-
const title = url.searchParams.get( 'title' );
560-
561-
// Attempt to get values from Special:Diff short-link
562-
const diffSpecialPageCheck =
563-
// eslint-disable-next-line security/detect-unsafe-regex
564-
/\/wiki\/Special:Diff\/(prev|next|\d+)(?:\/(prev|next|\d+))?/.exec( url.pathname );
565-
if ( diffSpecialPageCheck != null ) {
566-
if (
567-
diffSpecialPageCheck[ 1 ] != null &&
568-
diffSpecialPageCheck[ 2 ] == null
569-
) {
570-
// Special:Diff/diff
571-
diff = diffSpecialPageCheck[ 1 ];
572-
} else if (
573-
diffSpecialPageCheck[ 1 ] != null &&
574-
diffSpecialPageCheck[ 2 ] != null
575-
) {
576-
// Special:Diff/oldid/diff
577-
oldid = diffSpecialPageCheck[ 1 ];
578-
diff = diffSpecialPageCheck[ 2 ];
579-
}
580-
}
555+
// From the same wiki, accept deprecation immediately.
556+
557+
// Parse out info from this diff URL
558+
const parseInfo = parseDiffUrl( url );
559+
let { diff, oldid } = parseInfo;
560+
const { title } = parseInfo;
581561

582562
// If only an oldid was provided, and no diff
583563
if ( oldid && !diff ) {

src/wiki/util/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export default {
4343
nsId: nsId,
4444
openWindow: openWindow,
4545
pagelinkToTitle: pagelinkToTitle,
46+
parseDiffUrl: parseDiffUrl,
4647
performHacks: performHacks,
4748
purge: purge,
4849
renderWikitext: renderWikitext,

src/wiki/util/parseDiffUrl.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
interface DiffInfo {
2+
diff?: number | string;
3+
oldid?: number | string;
4+
title?: string;
5+
}
6+
7+
/**
8+
* What it says on the tin. Attempt to parse out a `title`, `diff`,
9+
* or `oldid` from a URL. This is useful for converting diff URLs into actual
10+
* diff information, and especially useful for {{copied}} templates.
11+
*
12+
* @param url The URL to parse
13+
* @return Parsed info: `diff` or `oldid` revision IDs, and/or the page title.
14+
*/
15+
export default function parseDiffUrl( url: URL | string ): DiffInfo {
16+
if ( typeof url === 'string' ) {
17+
url = new URL( url );
18+
}
19+
20+
// Attempt to get values from URL parameters (when using `/w/index.php?action=diff`)
21+
let oldid: string | number = url.searchParams.get( 'oldid' );
22+
let diff: string | number = url.searchParams.get( 'diff' );
23+
let title = url.searchParams.get( 'title' );
24+
25+
// Attempt to get information from this URL.
26+
tryConvert: {
27+
if ( title && oldid && diff ) {
28+
// Skip if there's nothing else we need to get.
29+
break tryConvert;
30+
}
31+
32+
// Attempt to get values from Special:Diff short-link
33+
const diffSpecialPageCheck =
34+
// eslint-disable-next-line security/detect-unsafe-regex
35+
/\/wiki\/Special:Diff\/(prev|next|\d+)(?:\/(prev|next|\d+))?/i.exec( url.pathname );
36+
if ( diffSpecialPageCheck != null ) {
37+
if (
38+
diffSpecialPageCheck[ 1 ] != null &&
39+
diffSpecialPageCheck[ 2 ] == null
40+
) {
41+
// Special:Diff/diff
42+
diff = diffSpecialPageCheck[ 1 ];
43+
} else if (
44+
diffSpecialPageCheck[ 1 ] != null &&
45+
diffSpecialPageCheck[ 2 ] != null
46+
) {
47+
// Special:Diff/oldid/diff
48+
oldid = diffSpecialPageCheck[ 1 ];
49+
diff = diffSpecialPageCheck[ 2 ];
50+
}
51+
break tryConvert;
52+
}
53+
54+
// Attempt to get values from Special:PermanentLink short-link
55+
const permanentLinkCheck =
56+
/\/wiki\/Special:Perma(nent)?link\/(\d+)/i.exec( url.pathname );
57+
if ( permanentLinkCheck != null ) {
58+
oldid = permanentLinkCheck[ 2 ];
59+
break tryConvert;
60+
}
61+
62+
// Attempt to get values from article path with ?oldid or ?diff
63+
// eslint-disable-next-line security/detect-non-literal-regexp
64+
const articlePathRegex = new RegExp( mw.util.getUrl( '(.*)' ) )
65+
.exec( url.pathname );
66+
if ( articlePathRegex != null ) {
67+
title = articlePathRegex[ 1 ];
68+
break tryConvert;
69+
}
70+
}
71+
72+
// Convert numbers to numbers
73+
if ( oldid != null && !isNaN( +oldid ) ) {
74+
oldid = +oldid;
75+
}
76+
if ( diff != null && !isNaN( +diff ) ) {
77+
diff = +diff;
78+
}
79+
80+
// Try to convert a page title
81+
try {
82+
title = new mw.Title( title ).getPrefixedText();
83+
} catch ( e ) {
84+
console.warn( 'Failed to normalize page title during diff URL conversion.' );
85+
}
86+
87+
return {
88+
diff: diff,
89+
oldid: oldid,
90+
title: title
91+
};
92+
}

0 commit comments

Comments
 (0)