From ad5747a954aeed6a3985d0d9192d2829907319bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20LES=C3=89N=C3=89CHAL?= Date: Mon, 11 Dec 2023 20:24:55 +0100 Subject: [PATCH 01/15] Add a type variable to Hook (#26) --- mw/hook.d.ts | 10 +++++----- tslint.json | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/mw/hook.d.ts b/mw/hook.d.ts index 0655c4c..c9fe93b 100644 --- a/mw/hook.d.ts +++ b/mw/hook.d.ts @@ -41,14 +41,14 @@ * * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.hook */ -interface Hook { +interface Hook { /** * Register a hook handler * * @param {...Function} handler Function to bind. * @chainable */ - add(...handler: Array<(...args: any[]) => any>): Hook; + add(...handler: Array<(...data: T) => any>): this; /** * Run a hook. @@ -56,7 +56,7 @@ interface Hook { * @param {*} data * @chainable */ - fire(data?: any): Hook; + fire(...data: T): this; /** * Unregister a hook handler @@ -64,7 +64,7 @@ interface Hook { * @param {...Function} handler Function to unbind. * @chainable */ - remove(handler: (...args: any[]) => any): Hook; + remove(...handler: Array<(...data: T) => any>): this; } declare global { @@ -76,7 +76,7 @@ declare global { * @member mw * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.hook */ - function hook(event: string): Hook; + function hook(event: string): Hook; } } diff --git a/tslint.json b/tslint.json index 7ea2968..f0759b2 100644 --- a/tslint.json +++ b/tslint.json @@ -7,6 +7,7 @@ "no-padding": false, "no-unnecessary-qualifier": false, "unified-signatures": false, - "no-redundant-jsdoc": false + "no-redundant-jsdoc": false, + "no-unnecessary-generics": false } } From 47911de012beb8df4f4c8ce6121d0894365d031c Mon Sep 17 00:00:00 2001 From: Bhsd <55071315+bhsd-harry@users.noreply.github.com> Date: Thu, 21 Dec 2023 10:42:43 +0800 Subject: [PATCH 02/15] Update config.d.ts by adding wgUrlProtocols --- mw/config.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/mw/config.d.ts b/mw/config.d.ts index 8fd76c2..557515d 100644 --- a/mw/config.d.ts +++ b/mw/config.d.ts @@ -64,6 +64,7 @@ declare global { wgDiffOldId: number | false; wgDiffNewId: number; wgWikibaseItemId: string; + wgUrlProtocols: string; [key: string]: unknown; // more config keys can be added by extensions }>; } From bf526f205cc136aa8755efba939295071c6c80ce Mon Sep 17 00:00:00 2001 From: Bhsd <55071315+bhsd-harry@users.noreply.github.com> Date: Thu, 21 Dec 2023 10:50:11 +0800 Subject: [PATCH 03/15] Update textSelection.d.ts by adding commands Refer to https://github.com/wikimedia/mediawiki/blob/41bb695a68c4f2d875ae1a54f00846a15a57923f/resources/src/jquery/jquery.textSelection.js#L42-L43 --- jquery/textSelection.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jquery/textSelection.d.ts b/jquery/textSelection.d.ts index faacea4..0a85786 100644 --- a/jquery/textSelection.d.ts +++ b/jquery/textSelection.d.ts @@ -52,6 +52,10 @@ declare global { force?: boolean; } ): JQuery; + + textSelection(command: "unregister"): void; + + textSelection(command: "register", commandOptions: Record any>): void; } } From fcabe10c5ce77a3e33ad0e4232066829b3db80d4 Mon Sep 17 00:00:00 2001 From: Siddharth VP Date: Fri, 22 Dec 2023 13:30:16 +0530 Subject: [PATCH 04/15] update types and add doc comments for mw.storage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 安忆 --- mw/storage.d.ts | 130 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/mw/storage.d.ts b/mw/storage.d.ts index cc01051..b740de6 100644 --- a/mw/storage.d.ts +++ b/mw/storage.d.ts @@ -1,15 +1,104 @@ +/** + * A wrapper for the HTML5 Storage interface (`localStorage` or `sessionStorage`) + * that is safe to call in all browsers. + * + * @class mw.SafeStorage + * @private + * @param {Object|undefined} store The Storage instance to wrap around + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.SafeStorage + */ interface SafeStorage { + /** + * Retrieve value from device storage. + * + * @param {string} key Key of item to retrieve + * @return {string|null|boolean} String value, null if no value exists, or false + * if storage is not available. + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.SafeStorage-method-get + */ get(key: string): string | null | boolean; + /** + * Retrieve JSON object from device storage. + * + * @param {string} key Key of item to retrieve + * @return {Object|null|boolean} Object, null if no value exists or value + * is not JSON-parseable, or false if storage is not available. + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.SafeStorage-method-getObject + */ getObject(key: string): any; + /** + * Remove a value from device storage. + * + * @param {string} key Key of item to remove + * @return {boolean} Whether the key was removed + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.SafeStorage-method-remove + */ remove(key: string): boolean; + /** + * Set a value in device storage. + * + * @param {string} key Key name to store under + * @param {string} value Value to be stored + * @param {number} [expiry] Number of seconds after which this item can be deleted + * @return {boolean} The value was set + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.SafeStorage-method-set + */ set(key: string, value: string, expiry?: number): boolean; + /** + * Set the expiry time for an item in the store + * + * @param {string} key Key name + * @param {number} [expiry] Number of seconds after which this item can be deleted, + * omit to clear the expiry (either making the item never expire, or to clean up + * when deleting a key). + * @return {boolean} The expiry was set (or cleared) [since 1.41] + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.SafeStorage-method-setExpires + */ setExpires(key: string, expiry?: number): void; + /** + * Set an object value in device storage by JSON encoding + * + * @param {string} key Key name to store under + * @param {Object} value Object value to be stored + * @param {number} [expiry] Number of seconds after which this item can be deleted + * @return {boolean} The value was set + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.SafeStorage-method-setObject + */ setObject(key: string, value: any, expiry?: number): boolean; + + /** + * Clear any expired items from the store + * + * @private + * @return {JQuery.Promise} Resolves when items have been expired + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.SafeStorage-method-clearExpired + */ + clearExpired(): JQuery.Promise; + + /** + * Get all keys with expiry values + * + * @private + * @return {JQuery.Promise} Promise resolving with all the keys which have + * expiry values (unprefixed), or as many could be retrieved in the allocated time. + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.SafeStorage-method-getExpiryKeys + */ + getExpiryKeys(): JQuery.Promise; + + /** + * Check if a given key has expired + * + * @private + * @param {string} key Key name + * @return {boolean} Whether key is expired + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.SafeStorage-method-isExpired + */ + isExpired(key: string): boolean; } interface MwStorage extends SafeStorage { @@ -18,6 +107,47 @@ interface MwStorage extends SafeStorage { declare global { namespace mw { + /** + * A safe interface to HTML5 `localStorage`. + * + * This normalises differences across browsers and silences any and all + * exceptions that may occur. + * + * **Note**: Storage keys are not automatically prefixed in relation to + * MediaWiki and/or the current wiki. Always **prefix your keys** with "mw" to + * avoid conflicts with gadgets, JavaScript libraries, browser extensions, + * internal CDN or webserver cookies, and third-party applications that may + * be embedded on the page. + * + * **Warning**: This API has limited storage space and does not use an expiry + * by default. This means unused **keys are stored forever**, unless you + * opt-in to the `expiry` parameter or otherwise make sure that your code + * can rediscover and delete keys you created in the past. + * + * If you don't use the `expiry` parameter, avoid keys with variable + * components as this leads to untracked keys that your code has no way + * to know about and delete when the data is no longer needed. Instead, + * store dynamic values in an object under a single constant key that you + * manage or replace over time. + * See also . + * + * Example: + * + * mw.storage.set( key, value, expiry ); + * mw.storage.set( key, value ); // stored indefinitely + * mw.storage.get( key ); + * + * Example: + * + * var local = require( 'mediawiki.storage' ).local; + * local.set( key, value, expiry ); + * local.get( key ); + * + * @class + * @singleton + * @extends mw.SafeStorage + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.storage + */ const storage: MwStorage; } } From 43a08e3972a0c0a8bc4e7593a283eb74d265e8b7 Mon Sep 17 00:00:00 2001 From: Siddharth VP Date: Fri, 22 Dec 2023 13:42:40 +0530 Subject: [PATCH 05/15] update types and add doc comments for mw.language MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 安忆 --- mw/language.d.ts | 245 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 242 insertions(+), 3 deletions(-) diff --git a/mw/language.d.ts b/mw/language.d.ts index 370023c..44568e2 100644 --- a/mw/language.d.ts +++ b/mw/language.d.ts @@ -1,35 +1,274 @@ declare global { namespace mw { + /** + * Base language object with methods related to language support, attempting to mirror some of the + * functionality of the Language class in MediaWiki: + * + * - storing and retrieving language data + * - transforming message syntax (`{{PLURAL:}}`, `{{GRAMMAR:}}`, `{{GENDER:}}`) + * - formatting numbers + * + * @class + * @singleton + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language + */ namespace language { + /** + * Language-related data (keyed by language, contains instances of mw.Map). + * + * Exported dynamically by the ResourceLoader\LanguageDataModule class in PHP. + * + * To set data: + * + * // Override, extend or create the language data object of 'nl' + * mw.language.setData( 'nl', 'myKey', 'My value' ); + * + * // Set multiple key/values pairs at once + * mw.language.setData( 'nl', { foo: 'X', bar: 'Y' } ); + * + * To get GrammarForms data for language 'nl': + * + * var grammarForms = mw.language.getData( 'nl', 'grammarForms' ); + * + * Possible data keys: + * + * - `digitTransformTable` + * - `separatorTransformTable` + * - `minimumGroupingDigits` + * - `grammarForms` + * - `pluralRules` + * - `digitGroupingPattern` + * - `fallbackLanguages` + * - `bcp47Map` + * - `languageNames` + * + * @property {Object} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-property-data + */ + const data: Record; + + /** + * Information about month names in current UI language. + * + * Object keys: + * + * - `names`: array of month names (in nominative case in languages which have the distinction), + * zero-indexed + * - `genitive`: array of month names in genitive case, zero-indexed + * - `abbrev`: array of three-letter-long abbreviated month names, zero-indexed + * - `keys`: object with three keys like the above, containing zero-indexed arrays of message keys + * for appropriate messages which can be passed to mw.msg. + * + * @property {Object} + * @member mw.language + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-property-months + */ + const months: Record; + + /** + * Formats language tags according the BCP 47 standard. + * See LanguageCode::bcp47 for the PHP implementation. + * + * @param {string} languageTag Well-formed language tag + * @return {string} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-bcp47 + */ function bcp47(languageTag: string): string; + /** + * Grammatical transformations, needed for inflected languages. + * Invoked by putting `{{grammar:case|word}}` in a message. + * + * The rules can be defined in $wgGrammarForms global or computed + * dynamically by overriding this method per language. + * + * @param {string} word + * @param {string} form + * @return {string} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-convertGrammar + */ function convertGrammar(word: string, form: string): string; + /** + * Converts a number using #getDigitTransformTable. + * + * @param {number} num Value to be converted + * @param {boolean} [integer=false] Whether to convert the return value to an integer + * @return {number|string} Formatted number + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-convertNumber + */ function convertNumber(num: number, integer?: boolean): number | string; + /** + * Plural form transformations, needed for some languages. + * + * @param {number} count Non-localized quantifier + * @param {Array} forms List of plural forms + * @param {Object} [explicitPluralForms] List of explicit plural forms + * @return {string} Correct form for quantifier in this language + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-convertPlural + */ function convertPlural( count: number, forms: string[], - explicitPluralForms?: any + explicitPluralForms?: Record ): string; - function flipTransform(...Transformation: any[]): any; + /** + * Helper function to flip transformation tables. + * + * @param {...Object} Transformation tables + * @return {Object} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-flipTransform + */ + function flipTransform( + ...Transformation: Array> + ): Record; + /** + * Provides an alternative text depending on specified gender. + * + * Usage in message text: `{{gender:[gender|user object]|masculine|feminine|neutral}}`. + * If second or third parameter are not specified, masculine is used. + * + * These details may be overridden per language. + * + * @param {string} gender 'male', 'female', or anything else for neutral. + * @param {Array} forms List of gender forms + * @return {string} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-gender + */ function gender(gender: string, forms: string[]): string; + /** + * Convenience method for retrieving language data. + * + * Structured by language code and data key, covering for the potential inexistence of a + * data object for this language. + * + * @param {string} langCode + * @param {string} dataKey + * @return {any} Value stored in the mw.Map (or `undefined` if there is no map for the + * specified langCode) + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-getData + */ function getData(langCode: string, dataKey: string): any; + /** + * Get the digit transform table for current UI language. + * + * @return {Object|Array} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-getDigitTransformTable + */ function getDigitTransformTable(): any; + /** + * Get the language fallback chain for current UI language, including the language itself. + * + * @return {string[]} List of language keys, e.g. `['pfl', de', 'en']` + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-getFallbackLanguageChain + */ function getFallbackLanguageChain(): string[]; + /** + * Get the language fallback chain for current UI language (not including the language itself). + * + * @return {string[]} List of language keys, e.g. `['de', 'en']` + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-getFallbackLanguages + */ function getFallbackLanguages(): string[]; + /** + * Get the separator transform table for current UI language. + * + * @return {Object|Array} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-getSeparatorTransformTable + */ function getSeparatorTransformTable(): any; + /** + * Turn a list of string into a simple list using commas and 'and'. + * + * See Language::listToText in languages/Language.php + * + * @param {string[]} list + * @return {string} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-listToText + */ function listToText(list: string[]): string; - function setData(langCode: string, dataKey: string, value?: any): void; + /** + * Convenience method for setting language data. + * + * Creates the data mw.Map if there isn't one for the specified language already. + * + * @param {string} langCode + * @param {string|Object} dataKey Key or object of key/values + * @param {any} [value] Value for dataKey, omit if dataKey is an object + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-setData + */ + function setData(langCode: string, dataKey: any, value?: any): void; + + /** + * Apply numeric pattern to absolute value using options. Gives no + * consideration to local customs. + * + * Adapted from dojo/number library with thanks + * + * + * @private + * @param {number} value the number to be formatted, ignores sign + * @param {string} pattern the number portion of a pattern (e.g. `#,##0.00`) + * @param {Object} [options] If provided, all option keys must be present: + * @param {string} options.decimal The decimal separator. Defaults to: `'.'`. + * @param {string} options.group The group separator. Defaults to: `','`. + * @param {number|null} options.minimumGroupingDigits + * @return {string} + */ + function commafyNumber( + value: number, + pattern: string, + options?: { decimal: string; group: string; minimumGroupingDigits: number | null } + ): string; + + /** + * Pad a string to guarantee that it is at least `size` length by + * filling with the character `ch` at either the start or end of the + * string. Pads at the start, by default. + * + * Example: Fill the string to length 10 with '+' characters on the right. + * + * pad( 'blah', 10, '+', true ); // => 'blah++++++' + * + * @private + * @param {string} text The string to pad + * @param {number} size The length to pad to + * @param {string} [ch='0'] Character to pad with + * @param {boolean} [end=false] Adds padding at the end if true, otherwise pads at start + * @return {string} + */ + function pad(text: string, size: number, ch?: string, end?: boolean): string; + + /** + * Pads an array to a specific length by copying the last one element. + * + * @private + * @param {Array} forms Number of forms given to convertPlural + * @param {number} count Number of forms required + * @return {Array} Padded array of forms + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.language-method-preConvertPlural + */ + function preConvertPlural(forms: string[], count: number): string[]; + + /** + * Replicate a string 'n' times. + * + * @private + * @param {string} str The string to replicate + * @param {number} num Number of times to replicate the string + * @return {string} + */ + function replicate(str: string, num: number): string; } } } From 4caca81d132ffdaab8e3348cbba596ba4078ff83 Mon Sep 17 00:00:00 2001 From: Siddharth VP Date: Fri, 22 Dec 2023 13:46:22 +0530 Subject: [PATCH 06/15] update doc comments for mw.experiments --- mw/experiments.d.ts | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/mw/experiments.d.ts b/mw/experiments.d.ts index 89bc5ff..09a96e3 100644 --- a/mw/experiments.d.ts +++ b/mw/experiments.d.ts @@ -4,25 +4,54 @@ interface Experiment { */ name: string; /** - * Whether the experiment is enabled + * Whether the experiment is enabled. If the experiment is disabled, then the user is always assigned to the control bucket */ enabled: boolean; /** - * An object consisting of the experiment's buckets ("control" and at least one bucket) and their probabilities (a number < 1, eg 0.25) + * A map of bucket name to probability that the user will be assigned to that bucket */ buckets: Record; } declare global { namespace mw { + /** + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.experiments + */ namespace experiment { /** - * Get a bucket for a user for the given experiment - * @param {string} token A unique identifier for the user - * @param {Experiment} experiment The expermient to get a bucket from - * @returns {string} The name of the chosen bucket (for example, if the buckets were "control", "a" and "b", it could return "b") + * Gets the bucket for the experiment given the token. + * + * The name of the experiment and the token are hashed. The hash is converted + * to a number which is then used to get a bucket. + * + * @example + * // The experiment has three buckets: control, A, and B. The user has a 50% chance of + * // being assigned to the control bucket, and a 25% chance of being assigned to either + * // the A or B bucket. If the experiment were disabled, then the user would always be + * // assigned to the control bucket. + * { + * name: 'My first experiment', + * enabled: true, + * buckets: { + * control: 0.5 + * A: 0.25, + * B: 0.25 + * } + * } + * + * @param {Object} experiment + * @param {string} experiment.name The name of the experiment + * @param {boolean} experiment.enabled Whether or not the experiment is + * enabled. If the experiment is disabled, then the user is always assigned + * to the control bucket + * @param {Object} experiment.buckets A map of bucket name to probability + * that the user will be assigned to that bucket + * @param {string} token A token that uniquely identifies the user for the + * duration of the experiment + * @return {string|undefined} The bucket */ - function getBucket(experiment: Experiment, token: string): string; + function getBucket(experiment: Experiment, token: string): string | undefined; } } } From 842e7eb83ec91e9d96cb75331d2aec72bef4698b Mon Sep 17 00:00:00 2001 From: Siddharth VP Date: Fri, 22 Dec 2023 13:47:04 +0530 Subject: [PATCH 07/15] add global.d.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 安忆 --- mw/global.d.ts | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ mw/index.d.ts | 1 + 2 files changed, 65 insertions(+) create mode 100644 mw/global.d.ts diff --git a/mw/global.d.ts b/mw/global.d.ts new file mode 100644 index 0000000..4c20dc8 --- /dev/null +++ b/mw/global.d.ts @@ -0,0 +1,64 @@ +declare global { + /** + * Global variables and functions. + * + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/global + */ + + /** + * Schedule a function to run once the page is ready (DOM loaded). + * + * @since 1.5.8 + * @member global + * @param {Function} fn + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/global-method-addOnloadHook + */ + function addOnloadHook(fn: (...args: any[]) => any): void; + + /** + * Import a local JS content page, for use by user scripts and site-wide scripts. + * + * Note that if the same title is imported multiple times, it will only + * be loaded and executed once. + * + * @since 1.12.2 + * @member global + * @param {string} title + * @return {HTMLScriptElement|null} Script tag, or null if it was already imported before + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/global-method-importScript + */ + function importScript(title: string): HTMLScriptElement | null; + + /** + * @since 1.12.2 + * @method importScriptURI + * @member global + * @param {string} url + * @return {HTMLScriptElement|null} Script tag, or null if it was already imported before + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/global-method-importScriptURI + */ + function importScriptURI(url: string): HTMLScriptElement | null; + + /** + * Import a local CSS content page, for use by user scripts and site-wide scripts. + * + * @since 1.12.2 + * @member global + * @param {string} title + * @return {HTMLLinkElement} Link tag + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/global-method-importStylesheet + */ + function importStylesheet(title: string): HTMLLinkElement | null; + + /** + * @since 1.12.2 + * @member global + * @param {string} url + * @param {string} media + * @return {HTMLLinkElement} Link tag + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/global-method-importStylesheetURI + */ + function importStylesheetURI(url: string, media: string): HTMLLinkElement | null; +} + +export {}; diff --git a/mw/index.d.ts b/mw/index.d.ts index cdc1b86..56d073e 100644 --- a/mw/index.d.ts +++ b/mw/index.d.ts @@ -3,6 +3,7 @@ import "./config"; import "./cookie"; import "./ForeignApi"; import "./ForeignRest"; +import "./global"; import "./hook"; import "./html"; import "./language"; From c42bab1b1f74670289fabb16de3ccebe543066fc Mon Sep 17 00:00:00 2001 From: Siddharth VP Date: Fri, 22 Dec 2023 14:09:50 +0530 Subject: [PATCH 08/15] update types and add doc comments for mw.loader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 安忆 --- mw/loader.d.ts | 483 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 463 insertions(+), 20 deletions(-) diff --git a/mw/loader.d.ts b/mw/loader.d.ts index c7daa14..9b48087 100644 --- a/mw/loader.d.ts +++ b/mw/loader.d.ts @@ -1,10 +1,192 @@ declare global { namespace mw { + /** + * Client for ResourceLoader server end point. + * + * This client is in charge of maintaining the module registry and state + * machine, initiating network (batch) requests for loading modules, as + * well as dependency resolution and execution of source code. + * + * For more information, refer to + * + * + * @class mw.loader + * @singleton + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader + */ namespace loader { - function addStyleTag(text: string, nextNode?: Node): HTMLStyleElement; + /** + * Create a new style element and add it to the DOM. + * + * @param {string} text CSS text + * @param {Node|null} [nextNode] The element where the style tag + * should be inserted before + * @return {HTMLStyleElement} Reference to the created style element + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-method-addStyleTag + */ + function addStyleTag(text: string, nextNode?: Node | null): HTMLStyleElement; + /** + * Get the names of all registered ResourceLoader modules. + * + * @member mw.loader + * @return {string[]} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-method-getModuleNames + */ function getModuleNames(): string[]; + /** + * Load a script by URL. + * + * Example: + * + * mw.loader.getScript( + * 'https://example.org/x-1.0.0.js' + * ) + * .then( function () { + * // Script succeeded. You can use X now. + * }, function ( e ) { + * // Script failed. X is not avaiable + * mw.log.error( e.message ); // => "Failed to load script" + * } ); + * } ); + * + * @member mw.loader + * @param {string} url Script URL + * @return {JQuery.Promise} Resolved when the script is loaded + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-method-getScript + */ + function getScript(url: string): JQuery.Promise; + + /** + * Get the state of a module. + * + * @param {string} module Name of module + * @return {string|null} The state, or null if the module (or its state) is not + * in the registry. + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-method-getState + */ + function getState(module: string): string | null; + + /** + * Load an external script or one or more modules. + * + * This method takes a list of unrelated modules. Use cases: + * + * - A web page will be composed of many different widgets. These widgets independently + * queue their ResourceLoader modules (`OutputPage::addModules()`). If any of them + * have problems, or are no longer known (e.g. cached HTML), the other modules + * should still be loaded. + * - This method is used for preloading, which must not throw. Later code that + * calls #using() will handle the error. + * + * @param {string|Array} modules Either the name of a module, array of modules, + * or a URL of an external script or style + * @param {string} [type='text/javascript'] MIME type to use if calling with a URL of an + * external script or style; acceptable values are "text/css" and + * "text/javascript"; if no type is provided, text/javascript is assumed. + * @throws {Error} If type is invalid + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-method-load + */ + function load(modules: string | string[], type?: string): void; + + /** + * Register a module, letting the system know about it and its properties. + * + * The startup module calls this method. + * + * When using multiple module registration by passing an array, dependencies that + * are specified as references to modules within the array will be resolved before + * the modules are registered. + * + * @param {string|Array} modules Module name or array of arrays, each containing + * a list of arguments compatible with this method + * @param {string|number} [version] Module version hash (falls backs to empty string) + * Can also be a number (timestamp) for compatibility with MediaWiki 1.25 and earlier. + * @param {string[]} [dependencies] Array of module names on which this module depends. + * @param {string} [group=null] Group which the module is in + * @param {string} [source='local'] Name of the source + * @param {string} [skip=null] Script body of the skip function + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-method-register + */ + function register( + modules: string | string[], + version?: string | number, + dependencies?: string[], + group?: string | null, + source?: string, + skip?: string | null + ): void; + + /** + * Change the state of one or more modules. + * + * @param {Object} states Object of module name/state pairs + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-method-state + */ + function state(states: Record): void; + + /** + * Execute a function after one or more modules are ready. + * + * Use this method if you need to dynamically control which modules are loaded + * and/or when they loaded (instead of declaring them as dependencies directly + * on your module.) + * + * This uses the same loader as for regular module dependencies. This means + * ResourceLoader will not re-download or re-execute a module for the second + * time if something else already needed it. And the same browser HTTP cache, + * and localStorage are checked before considering to fetch from the network. + * And any on-going requests from other dependencies or using() calls are also + * automatically re-used. + * + * Example of inline dependency on OOjs: + * + * mw.loader.using( 'oojs', function () { + * OO.compare( [ 1 ], [ 1 ] ); + * } ); + * + * Example of inline dependency obtained via `require()`: + * + * mw.loader.using( [ 'mediawiki.util' ], function ( require ) { + * var util = require( 'mediawiki.util' ); + * } ); + * + * Since MediaWiki 1.23 this returns a promise. + * + * Since MediaWiki 1.28 the promise is resolved with a `require` function. + * + * @member mw.loader + * @param {string|Array} dependencies Module name or array of modules names the + * callback depends on to be ready before executing + * @param {Function} [ready] Callback to execute when all dependencies are ready + * @param {Function} [error] Callback to execute if one or more dependencies failed + * @return {JQuery.Promise} With a `require` function + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-method-using + */ + function using( + dependencies: string | string[], + ready?: (...args: any[]) => any, + error?: (...args: any[]) => any + ): JQuery.Promise; + + /** + * Exposed for testing and debugging only. + * + * @private + * @property {number} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-property-maxQueryLength + */ + const maxQueryLength: number; + + /** + * The module registry is exposed as an aid for debugging and inspecting page + * state; it is not a public interface for modifying the registry. + * + * @private + * @property {Object} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-property-moduleRegistry + */ const moduleRegistry: Record< string, { @@ -14,35 +196,296 @@ declare global { exports: any; }; packageExports: any; - skip: string | null; + skip: "string" | null; source: string; - state: "registered" | "ready"; + state: "error" | "loaded" | "missing" | "registered" | "ready"; version: string; } >; - function getScript(url: string): JQuery.Promise; - - function getState(module: string): string | null; + /** + * Utility function for execute() + * + * @private + * @param {string} url URL + * @param {string} [media] Media attribute + * @param {Node|null} [nextNode] + * @return {HTMLLinkElement} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/source/mediawiki.loader.html#global-method-addLinkTag + */ + function addLinkTag( + url: string, + media?: string, + nextNode?: Node | null + ): HTMLLinkElement; - function load(modules: string | string[], type?: string): void; + /** + * Load and execute a script. + * + * @private + * @param {string} src URL to script, will be used as the src attribute in the script tag + * @param {Function} [callback] Callback to run after request resolution + * @param {string[]} [modules] List of modules being requested, for state to be marked as error + * in case the script fails to load + * @return {HTMLScriptElement} + * @see https://doc.wikimedia.org/mediawiki-core/master/js/source/mediawiki.loader.html#mw-loader-method-addScriptTag + */ + function addScriptTag( + src: string, + callback?: (...args: any[]) => any, + modules?: string[] + ): HTMLScriptElement; + /** + * Add one or more modules to the module load queue. + * + * See also #work(). + * + * @private + * @param {string[]} dependencies Array of module names in the registry + * @param {Function} [ready] Callback to execute when all dependencies are ready + * @param {Function} [error] Callback to execute when any dependency fails + * @see https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.loader-method-enqueue + */ + function enqueue( + dependencies: string[], + ready?: (...args: any[]) => any, + error?: (...args: any[]) => any + ): void; - function register( - modules: string | string[], - version?: string | number, - dependencies?: string[], - group?: string, - source?: string, - skip?: string + /** + * Implement a module given the components that make up the module. + * + * When #load() or #using() requests one or more modules, the server + * response contain calls to this function. + * + * @param {string} module Name of module and current module version. Formatted + * as '`[name]@[version]`". This version should match the requested version + * (from #batchRequest and #registry). This avoids race conditions (T117587). + * For back-compat with MediaWiki 1.27 and earlier, the version may be omitted. + * @param {Function|Array|string|Object} [script] Module code. This can be a function, + * a list of URLs to load via `