diff --git a/mw/Map.d.ts b/mw/Map.d.ts new file mode 100644 index 0000000..6d42de8 --- /dev/null +++ b/mw/Map.d.ts @@ -0,0 +1,53 @@ +declare global { + namespace mw { + /** + * Create an object that can be read from or written to via methods that allow interaction both + * with single and multiple properties at once. + * + * **NOTE**: This is a private utility class for internal use by the framework. + * Don't rely on its existence. + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map + */ + class Map = any> { + private values: V; + + /** + * Get the value of one or more keys. + * + * If called with no arguments, all values are returned. + * @param selection Key or array of keys to retrieve values for. + * @param fallback Value for keys that don't exist. + * @returns If selection was a string, returns the value. If selection was an array, returns + * an object of key/values. If no selection is passed, a new object with all key/values is returned. + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map-method-get + */ + get(): V; + get>( + selection: S, + fallback?: any + ): Pick ? SS : never>; + get(selection: S, fallback?: V[S]): V[S]; + + /** + * Set the value of one or more keys. + * + * @param selection Key to set value for, or object mapping keys to values + * @param value Value to set (optional, only in use when key is a string) + * @returns True on success, false on failure + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map-method-set + */ + set(selection: S, value: V[S]): boolean; + set(selection: Partial): boolean; + + /** + * Check if a given key exists in the map. + * @param selection Key to check + * @returns True if the key exists + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map-method-exists + */ + exists(selection: keyof V): boolean; + } + } +} + +export {}; diff --git a/mw/index.d.ts b/mw/index.d.ts index c2fb29e..b96ee32 100644 --- a/mw/index.d.ts +++ b/mw/index.d.ts @@ -3,6 +3,7 @@ import "./language"; import "./util"; import "./user"; import "./loader"; +import "./Map"; import "./Title"; import "./Uri"; import "./hook"; @@ -28,7 +29,61 @@ declare global { * global `window` object. * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw-property-config */ - const config: mw.Map; + const config: mw.Map<{ + debug: boolean; + skin: string; + stylepath: string; + wgArticlePath: string; + wgCaseSensitiveNamespaces: string[]; + wgContentLanguage: string; + wgContentNamespaces: number[]; + wgDBname: string; + wgEnableAPI: boolean; + wgEnableWriteAPI: boolean; + wgExtensionAssetsPath: string; + wgFormattedNamespaces: Record; + wgNamespaceIds: Record; + wgScript: string; + wgScriptPath: string; + wgServer: string; + wgSiteName: string; + wgVariantArticlePath: string | false; + wgVersion: string; + wgAction: string; + wgArticleId: number; + wgCanonicalNamespace: string; + wgCanonicalSpecialPageName: string | false; + wgCategories: string[]; + wgCurRevisionId: number; + wgIsArticle: boolean; + wgIsProbablyEditable: boolean; + wgNamespaceNumber: number; + wgPageContentLanguage: string; + wgPageContentModel: string; + wgPageName: string; + wgRedirectedFrom: string; + wgRelevantPageName: string; + wgRelevantUserName: string; + wgRelevantPageIsProbablyEditable: boolean; + wgRestrictionEdit: string[]; + wgRestrictionMove: string[]; + wgRevisionId: number; + wgSearchType: string; + wgTitle: string; + wgUserEditCount: number; + wgUserGroups: string[]; + wgUserId: number; + wgUserLanguage: string; + wgUserName: string; + wgUserRegistration: number; + wgIsMainPage: boolean; + wgUserVariant: string; + wgPostEdit: string; + wgDiffOldId: number; + wgDiffNewId: number; + wgWikibaseItemId: string; + [key: string]: unknown; // more config keys can be added by extensions + }>; namespace html { function escape(s: string): string; @@ -50,47 +105,6 @@ declare global { function warn(...msg: string[]): void; } - /** - * Create an object that can be read from or written to via methods that allow interaction both - * with single and multiple properties at once. - * - * **NOTE**: This is a private utility class for internal use by the framework. - * Don't rely on its existence. - * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map - */ - class Map { - /** - * Get the value of one or more keys. - * - * If called with no arguments, all values are returned. - * @param selection Key or array of keys to retrieve values for. - * @param fallback Value for keys that don't exist. - * @returns If selection was a string, returns the value, If selection was an array, returns - * an object of key/values. If no selection is passed, a new object with all key/values is returned. - * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map-method-get - */ - get(selection: string | string[], fallback?: any): any; - - /** - * Get the value of one or more keys. - * - * If called with no arguments, all values are returned. - * @param selection Key to set value for, or object mapping keys to values - * @param value Value to set (optional, only in use when key is a string) - * @returns True on success, false on failure - * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map-method-set - */ - set(selection: string | Record, value?: any): boolean; - - /** - * Check if a given key exists in the map. - * @param selection Key to check - * @returns True if the key exists - * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Map-method-exists - */ - exists(selection: string): boolean; - } - // types for mw.widgets are out of scope! const widgets: any; } diff --git a/mw/message.d.ts b/mw/message.d.ts index 5a0f43e..0e7f828 100644 --- a/mw/message.d.ts +++ b/mw/message.d.ts @@ -21,7 +21,7 @@ declare global { * @param key * @param parameters */ - constructor(map: mw.Map, key: string, parameters?: string[]); + constructor(map: mw.Map>, key: string, parameters?: string[]); /** * Change the format to 'escaped' and convert message to string diff --git a/scripts/config-types-scraper.js b/scripts/config-types-scraper.js new file mode 100644 index 0000000..c820d7d --- /dev/null +++ b/scripts/config-types-scraper.js @@ -0,0 +1,33 @@ +// Go to +// paste this into the browser console, and copy the log output + +function processType(type) { + type = type.toLowerCase(); + type = type.replace(/or (unset|not defined)/, ""); + type = type.replace("integer", "number"); + type = type.replace(/ or /g, " | "); + if (type.startsWith("array of")) { + const element = type.replace(/array of (.*)s(\s|$)/, "$1"); + type = `${element}[]`; + } + if (type === "array") type = "string[]"; + if (type === "object") type = "Record"; + + return type.trim(); +} + +const types = {}; +const tables = document.querySelectorAll(".wikitable"); +for (const table of tables) { + const rows = table.querySelectorAll("tr:not([colspan])"); + for (const row of rows) { + const cells = row.querySelectorAll("td"); + if (!cells.length) continue; + const name = cells[0].innerText.trim(); + const type = processType(cells[1].innerText); + types[name] = type; + } +} + +const entries = Object.entries(types).map(([k, v]) => `${" ".repeat(12)}${k}: ${v};`); +console.log(`{\n${entries.join("\n")}${" ".repeat(8)}\n}`);