mediawiki-projects-list 1.2.10 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const {properties: {wikiProjects: {items: {properties: wikiProjectSchema}}}} = require('./projects-schema.json');
2
+ const PROJECTS = require('./projects.json');
2
3
 
3
4
  /**
4
5
  * A MediaWiki project
@@ -20,24 +21,38 @@ const {properties: {wikiProjects: {items: {properties: wikiProjectSchema}}}} = r
20
21
  * @property {?string} note - Note about the specific project
21
22
  */
22
23
 
24
+ /**
25
+ * A frontend proxy
26
+ * @typedef {object} FrontendProxy
27
+ * @property {string} name - Hostname of the proxy
28
+ * @property {string} regex - Regex to match the proxy url
29
+ * @property {string} namePath - Name path of the proxy
30
+ * @property {string} articlePath - Article path of the proxy
31
+ * @property {string} scriptPath - Script path of the proxy
32
+ */
33
+
23
34
  /**
24
35
  * @type {{
25
36
  * inputToWikiProject: Map<string, ?{fullArticlePath: string, fullScriptPath: string, wikiProject: WikiProject}>,
26
37
  * urlToIdString: Map<string, ?string>,
27
- * idStringToUrl: Map<string, ?string>
38
+ * idStringToUrl: Map<string, ?string>,
39
+ * inputToFrontendProxy: Map<string, ?{fullNamePath: string, fullArticlePath: string, fullScriptPath: string, frontendProxy: FrontendProxy}>,
40
+ * urlToFix: Map<string, ?((href:String,pagelink:String)=>String)>
28
41
  * }}
29
42
  */
30
43
  const functionCache = {
31
44
  inputToWikiProject: new Map(),
32
45
  urlToIdString: new Map(),
33
- idStringToUrl: new Map()
46
+ idStringToUrl: new Map(),
47
+ inputToFrontendProxy: new Map(),
48
+ urlToFix: new Map()
34
49
  };
35
50
 
36
51
  /**
37
52
  * List of MediaWiki projects
38
53
  * @type {WikiProject[]}
39
54
  */
40
- const wikiProjects = require('./projects.json').wikiProjects.map( wikiProject => {
55
+ const wikiProjects = PROJECTS.wikiProjects.map( wikiProject => {
41
56
  if ( wikiProject.idString ) {
42
57
  wikiProject.idString.separator ??= wikiProjectSchema.idString.properties.separator.default;
43
58
  wikiProject.idString.direction ??= wikiProjectSchema.idString.properties.direction.default;
@@ -50,6 +65,12 @@ const wikiProjects = require('./projects.json').wikiProjects.map( wikiProject =>
50
65
  return wikiProject;
51
66
  } );
52
67
 
68
+ /**
69
+ * List of frontend proxies
70
+ * @type {FrontendProxy[]}
71
+ */
72
+ const frontendProxies = PROJECTS.frontendProxies;
73
+
53
74
  /**
54
75
  *
55
76
  * @param {string} input
@@ -73,6 +94,10 @@ function inputToWikiProject(input) {
73
94
  fullScriptPath: 'https://' + regex[1] + scriptPath,
74
95
  wikiProject: wikiProject
75
96
  };
97
+ if ( result.fullArticlePath.includes('?') && !result.fullArticlePath.endsWith('=') ) {
98
+ result.fullArticlePath = result.fullArticlePath.replace( '?', '$1?' );
99
+ }
100
+ else result.fullArticlePath += '$1';
76
101
  }
77
102
  }
78
103
  functionCache.inputToWikiProject.set(input, result);
@@ -123,9 +148,75 @@ function idStringToUrl(idString, projectName) {
123
148
  return ( result ? new URL(result) : result );
124
149
  }
125
150
 
151
+ /**
152
+ *
153
+ * @param {string} input
154
+ * @returns {?{fullNamePath: string, fullArticlePath: string, fullScriptPath: string, frontendProxy: FrontendProxy}}
155
+ */
156
+ function inputToFrontendProxy(input) {
157
+ if ( functionCache.inputToFrontendProxy.has(input) ) return structuredClone(functionCache.inputToFrontendProxy.get(input));
158
+ let result = null;
159
+ let frontendProxy = frontendProxies.find( frontendProxy => input.split('/').slice(0, 3).some( part => part.endsWith( frontendProxy.name ) ) );
160
+ if ( frontendProxy ) {
161
+ let regex = input.match( new RegExp( frontendProxy.regex ) );
162
+ if ( regex ) {
163
+ result = {
164
+ fullNamePath: frontendProxy.namePath.replace( /\$(\d)/g, (match, n) => regex[n] ),
165
+ fullArticlePath: frontendProxy.articlePath.replace( /\$(\d)/g, (match, n) => regex[n] ),
166
+ fullScriptPath: frontendProxy.scriptPath.replace( /\$(\d)/g, (match, n) => regex[n] ),
167
+ frontendProxy: frontendProxy
168
+ };
169
+ if ( result.fullArticlePath.includes('?') && !result.fullArticlePath.endsWith('=') ) {
170
+ result.fullArticlePath = result.fullArticlePath.replace( '?', '$1?' );
171
+ }
172
+ else result.fullArticlePath += '$1';
173
+ }
174
+ }
175
+ functionCache.inputToFrontendProxy.set(input, result);
176
+ return structuredClone(result);
177
+ }
178
+
179
+ /**
180
+ *
181
+ * @param {string} url
182
+ * @returns {?((href:String,pagelink:String)=>String)}
183
+ */
184
+ function urlToFix(url) {
185
+ let hostname = url.split('/')[2];
186
+ if ( functionCache.urlToFix.has(hostname) ) return functionCache.urlToFix.get(hostname);
187
+ let result = null;
188
+ let frontendProxy = frontendProxies.find( frontendProxy => hostname.endsWith( frontendProxy.name ) );
189
+ if ( frontendProxy ) {
190
+ let splitLength = frontendProxy.namePath.split('/').length;
191
+ let querykeys = frontendProxy.namePath.split('?').slice(1).join('?').split('&').flatMap( query => query.split('=', 1) );
192
+ if ( splitLength > 4 && querykeys.length ) {
193
+ result = (href, pagelink) => {
194
+ let prepend = '/' + pagelink.split('/', splitLength).slice(3, -1).join('/');
195
+ let querystring = pagelink.split('?').slice(1).join('?').split('&').filter( query => querykeys.includes( query.split('=', 1)[0] ) );
196
+ let append = ( href.includes('?') ? '&' : '?' ) + querystring.join('&');
197
+ return prepend + href + append;
198
+ };
199
+ }
200
+ else if ( splitLength > 4 ) {
201
+ result = (href, pagelink) => '/' + pagelink.split('/', splitLength).slice(3, -1).join('/') + href;
202
+ }
203
+ else if ( querykeys.length ) {
204
+ result = (href, pagelink) => {
205
+ let querystring = pagelink.split('?').slice(1).join('?').split('&').filter( query => querykeys.includes( query.split('=', 1)[0] ) );
206
+ return href + ( href.includes('?') ? '&' : '?' ) + querystring.join('&');
207
+ }
208
+ }
209
+ }
210
+ functionCache.urlToFix.set(hostname, result);
211
+ return result;
212
+ }
213
+
126
214
  module.exports = {
127
215
  wikiProjects,
216
+ frontendProxies,
128
217
  inputToWikiProject,
129
218
  urlToIdString,
130
- idStringToUrl
219
+ idStringToUrl,
220
+ inputToFrontendProxy,
221
+ urlToFix
131
222
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mediawiki-projects-list",
3
- "version": "1.2.10",
3
+ "version": "2.0.0",
4
4
  "type": "commonjs",
5
5
  "description": "List of MediaWiki projects for use in discord-wiki-bot",
6
6
  "main": "index.js",
@@ -9,6 +9,46 @@
9
9
  "type": "string",
10
10
  "format": "path"
11
11
  },
12
+ "frontendProxies": {
13
+ "type": "array",
14
+ "description": "List of frontend proxies",
15
+ "items": {
16
+ "type": "object",
17
+ "description": "A frontend proxy",
18
+ "properties": {
19
+ "name": {
20
+ "type": "string",
21
+ "description": "Hostname of the proxy"
22
+ },
23
+ "regex": {
24
+ "type": "string",
25
+ "description": "Regex to match the proxy url"
26
+ },
27
+ "namePath": {
28
+ "type": "string",
29
+ "description": "Name path of the proxy"
30
+ },
31
+ "articlePath": {
32
+ "type": "string",
33
+ "description": "Article path of the proxy"
34
+ },
35
+ "scriptPath": {
36
+ "type": "string",
37
+ "description": "Script path of the project"
38
+ }
39
+ },
40
+ "required": [
41
+ "name",
42
+ "regex",
43
+ "namePath",
44
+ "articlePath",
45
+ "scriptPath"
46
+ ],
47
+ "additionalProperties": false
48
+ },
49
+ "uniqueItemProperties": ["name"],
50
+ "additionalItems": false
51
+ },
12
52
  "wikiProjects": {
13
53
  "type": "array",
14
54
  "description": "List of MediaWiki projects",
package/projects.json CHANGED
@@ -1,5 +1,35 @@
1
1
  {
2
2
  "$schema": "./projects-schema.json",
3
+ "frontendProxies": [
4
+ {
5
+ "name": "wikiless.org",
6
+ "regex": "wikiless\\.org/.*?\\?(?:.*?&)?lang=([a-z\\d-]{1,50})(?:&|$)",
7
+ "namePath": "https://wikiless.org/?lang=$1",
8
+ "articlePath": "https://wikiless.org/wiki/?lang=$1",
9
+ "scriptPath": "https://$1.wikipedia.org/w/"
10
+ },
11
+ {
12
+ "name": ".breezewiki.com",
13
+ "regex": "([a-z\\d-]{1,50})\\.breezewiki\\.com(?:/wiki/|/?$)",
14
+ "namePath": "https://breezewiki.com/$1/",
15
+ "articlePath": "https://breezewiki.com/$1/wiki/",
16
+ "scriptPath": "https://$1.fandom.com/"
17
+ },
18
+ {
19
+ "name": "breezewiki.com",
20
+ "regex": "breezewiki\\.com/([a-z\\d-]{1,50})(?:/wiki/|/?$)",
21
+ "namePath": "https://breezewiki.com/$1/",
22
+ "articlePath": "https://breezewiki.com/$1/wiki/",
23
+ "scriptPath": "https://$1.fandom.com/"
24
+ },
25
+ {
26
+ "name": "breezewiki.pussthecat.org",
27
+ "regex": "breezewiki\\.pussthecat\\.org/([a-z\\d-]{1,50})(?:/wiki/|/?$)",
28
+ "namePath": "https://breezewiki.pussthecat.org/$1/",
29
+ "articlePath": "https://breezewiki.pussthecat.org/$1/wiki/",
30
+ "scriptPath": "https://$1.fandom.com/"
31
+ }
32
+ ],
3
33
  "wikiProjects": [
4
34
  {
5
35
  "name": "fandom.com",