From 983f0bc58b4ebfd9cd19d611b739f95af39e9615 Mon Sep 17 00:00:00 2001 From: Gota Okabe <43296160+sirasagi62@users.noreply.github.com> Date: Sat, 13 Sep 2025 02:45:15 +0900 Subject: [PATCH 01/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73655=20[rea?= =?UTF-8?q?ct-big-calendar]=20Add=20missing=20props=20type=20definitions?= =?UTF-8?q?=20to=20`date`=20and=E2=80=A6=20by=20@sirasagi62?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: sirasagi62 --- types/react-big-calendar/index.d.ts | 15 +++++++-- .../react-big-calendar-tests.tsx | 31 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/types/react-big-calendar/index.d.ts b/types/react-big-calendar/index.d.ts index d376bd2b35006d..0a412f2120fb28 100644 --- a/types/react-big-calendar/index.d.ts +++ b/types/react-big-calendar/index.d.ts @@ -209,8 +209,8 @@ export interface Components> | undefined; agenda?: | { - date?: React.ComponentType | undefined; - time?: React.ComponentType | undefined; + date?: React.ComponentType | undefined; + time?: React.ComponentType | undefined; event?: React.ComponentType> | undefined; } | undefined; @@ -269,6 +269,17 @@ export interface EventProps { slotEnd: Date; } +export interface AgendaDateProps { + day: Date; + label: string; +} + +export interface AgendaTimeProps { + event: Event; + day: Date; + label: string; +} + export interface EventWrapperProps { // https://github.com/intljusticemission/react-big-calendar/blob/27a2656b40ac8729634d24376dff8ea781a66d50/src/TimeGridEvent.js#L28 style?: (React.CSSProperties & { xOffset: number }) | undefined; diff --git a/types/react-big-calendar/react-big-calendar-tests.tsx b/types/react-big-calendar/react-big-calendar-tests.tsx index b27230358f577e..cb5db668b04438 100644 --- a/types/react-big-calendar/react-big-calendar-tests.tsx +++ b/types/react-big-calendar/react-big-calendar-tests.tsx @@ -1,5 +1,7 @@ import * as React from "react"; import { + AgendaDateProps, + AgendaTimeProps, Calendar, CalendarProps, Culture, @@ -590,6 +592,35 @@ class Toolbar extends React.Component; } +// Test components.agenda +{ + const localizer: DateLocalizer = momentLocalizer(moment); + + const date: React.FC = ({day,label}) => <>date; + + const time: React.FC = ({day,label,event}) => <>time; + + const event: React.FC = ({ + event, + title, + continuesPrior, + continuesAfter, + isAllDay, + localizer, + slotStart, + slotEnd, + }) => { + const { formats, propType, startOfWeek, format, messages } = localizer; + return <>Event; + }; + + const Basic = ({ localizer }: CalendarProps) => ( + + ); + + ; +} + // test OnRangeChange return types { interface Props { From a8dfc5a25838f7db3571059d32e4a3cb89f94ff1 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Fri, 12 Sep 2025 17:45:51 +0000 Subject: [PATCH 02/17] =?UTF-8?q?=F0=9F=A4=96=20dprint=20fmt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/react-big-calendar/react-big-calendar-tests.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/types/react-big-calendar/react-big-calendar-tests.tsx b/types/react-big-calendar/react-big-calendar-tests.tsx index cb5db668b04438..a3ef2413dfcaed 100644 --- a/types/react-big-calendar/react-big-calendar-tests.tsx +++ b/types/react-big-calendar/react-big-calendar-tests.tsx @@ -596,9 +596,9 @@ class Toolbar extends React.Component = ({day,label}) => <>date; + const date: React.FC = ({ day, label }) => <>date; - const time: React.FC = ({day,label,event}) => <>time; + const time: React.FC = ({ day, label, event }) => <>time; const event: React.FC = ({ event, @@ -615,7 +615,7 @@ class Toolbar extends React.Component ( - + ); ; From 67740b19ae77a7873f5a522b3425e50fc587c425 Mon Sep 17 00:00:00 2001 From: "Sebastian \"Sebbie\" Silbermann" Date: Fri, 12 Sep 2025 20:12:02 +0200 Subject: [PATCH 03/17] [react] Move `` to Canary release channel (#73609) --- types/react/canary.d.ts | 22 ++++++++++++++++++++++ types/react/experimental.d.ts | 20 -------------------- types/react/test/canary.tsx | 18 ++++++++++++++++++ types/react/test/experimental.tsx | 18 ------------------ types/react/ts5.0/canary.d.ts | 22 ++++++++++++++++++++++ types/react/ts5.0/experimental.d.ts | 20 -------------------- types/react/ts5.0/test/canary.tsx | 18 ++++++++++++++++++ types/react/ts5.0/test/experimental.tsx | 18 ------------------ 8 files changed, 80 insertions(+), 76 deletions(-) diff --git a/types/react/canary.d.ts b/types/react/canary.d.ts index cb1dd88ee7b0ad..3f765a2f92bc0f 100644 --- a/types/react/canary.d.ts +++ b/types/react/canary.d.ts @@ -35,4 +35,26 @@ declare module "." { export interface CacheSignal {} export function cacheSignal(): null | CacheSignal; + + // @enableActivity + export interface ActivityProps { + /** + * @default "visible" + */ + mode?: + | "hidden" + | "visible" + | undefined; + /** + * A name for this Activity boundary for instrumentation purposes. + * The name will help identify this boundary in React DevTools. + */ + name?: string | undefined; + children: ReactNode; + } + + /** + * @see {@link https://react.dev/reference/react/Activity `` documentation} + */ + export const Activity: ExoticComponent; } diff --git a/types/react/experimental.d.ts b/types/react/experimental.d.ts index daf69d3f4f08c1..25d3ec5a9c17c7 100644 --- a/types/react/experimental.d.ts +++ b/types/react/experimental.d.ts @@ -217,26 +217,6 @@ declare module "." { ref?: Ref | undefined; } - // @enableActivity - export interface ActivityProps { - /** - * @default "visible" - */ - mode?: - | "hidden" - | "visible" - | undefined; - /** - * A name for this Activity boundary for instrumentation purposes. - * The name will help identify this boundary in React DevTools. - */ - name?: string | undefined; - children: ReactNode; - } - - /** */ - export const unstable_Activity: ExoticComponent; - // @enableSrcObject interface DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_IMG_SRC_TYPES { srcObject: Blob; diff --git a/types/react/test/canary.tsx b/types/react/test/canary.tsx index 91b959415a765f..cc72495d7c18ce 100644 --- a/types/react/test/canary.tsx +++ b/types/react/test/canary.tsx @@ -37,3 +37,21 @@ function cacheSignalTest() { signal.aborted; } } + +// @enableActivity +function activityTest() { + const Activity = React.Activity; + + ; + ; + ; + ; + // @ts-expect-error -- Forgot children + ; + ; + ; +} diff --git a/types/react/test/experimental.tsx b/types/react/test/experimental.tsx index 68de8555ed2d06..6a432e8f1bab83 100644 --- a/types/react/test/experimental.tsx +++ b/types/react/test/experimental.tsx @@ -318,21 +318,3 @@ function fragmentRefTest() {
; } - -// @enableActivity -function activityTest() { - const Activity = React.unstable_Activity; - - ; - ; - ; - ; - // @ts-expect-error -- Forgot children - ; - ; - ; -} diff --git a/types/react/ts5.0/canary.d.ts b/types/react/ts5.0/canary.d.ts index cb1dd88ee7b0ad..3f765a2f92bc0f 100644 --- a/types/react/ts5.0/canary.d.ts +++ b/types/react/ts5.0/canary.d.ts @@ -35,4 +35,26 @@ declare module "." { export interface CacheSignal {} export function cacheSignal(): null | CacheSignal; + + // @enableActivity + export interface ActivityProps { + /** + * @default "visible" + */ + mode?: + | "hidden" + | "visible" + | undefined; + /** + * A name for this Activity boundary for instrumentation purposes. + * The name will help identify this boundary in React DevTools. + */ + name?: string | undefined; + children: ReactNode; + } + + /** + * @see {@link https://react.dev/reference/react/Activity `` documentation} + */ + export const Activity: ExoticComponent; } diff --git a/types/react/ts5.0/experimental.d.ts b/types/react/ts5.0/experimental.d.ts index daf69d3f4f08c1..25d3ec5a9c17c7 100644 --- a/types/react/ts5.0/experimental.d.ts +++ b/types/react/ts5.0/experimental.d.ts @@ -217,26 +217,6 @@ declare module "." { ref?: Ref | undefined; } - // @enableActivity - export interface ActivityProps { - /** - * @default "visible" - */ - mode?: - | "hidden" - | "visible" - | undefined; - /** - * A name for this Activity boundary for instrumentation purposes. - * The name will help identify this boundary in React DevTools. - */ - name?: string | undefined; - children: ReactNode; - } - - /** */ - export const unstable_Activity: ExoticComponent; - // @enableSrcObject interface DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_IMG_SRC_TYPES { srcObject: Blob; diff --git a/types/react/ts5.0/test/canary.tsx b/types/react/ts5.0/test/canary.tsx index 91b959415a765f..cc72495d7c18ce 100644 --- a/types/react/ts5.0/test/canary.tsx +++ b/types/react/ts5.0/test/canary.tsx @@ -37,3 +37,21 @@ function cacheSignalTest() { signal.aborted; } } + +// @enableActivity +function activityTest() { + const Activity = React.Activity; + + ; + ; + ; + ; + // @ts-expect-error -- Forgot children + ; + ; + ; +} diff --git a/types/react/ts5.0/test/experimental.tsx b/types/react/ts5.0/test/experimental.tsx index 68de8555ed2d06..6a432e8f1bab83 100644 --- a/types/react/ts5.0/test/experimental.tsx +++ b/types/react/ts5.0/test/experimental.tsx @@ -318,21 +318,3 @@ function fragmentRefTest() {
; } - -// @enableActivity -function activityTest() { - const Activity = React.unstable_Activity; - - ; - ; - ; - ; - // @ts-expect-error -- Forgot children - ; - ; - ; -} From b04153186e868ede19ea1162631c1f34bc31a7ac Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Fri, 12 Sep 2025 20:56:29 +0200 Subject: [PATCH 04/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73536=20[chr?= =?UTF-8?q?ome]=20update=20i18n=20namespace=20by=20@erwanjugand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 52 ++++++++++++++++++-------------------- types/chrome/test/index.ts | 41 ++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index 7499abe67f537c..47ef775c54235c 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -5828,58 +5828,56 @@ declare namespace chrome { * Manifest: "default_locale" */ export namespace i18n { - /** Holds detected ISO language code and its percentage in the input string */ export interface DetectedLanguage { - /** An ISO language code such as 'en' or 'fr'. - * For a complete list of languages supported by this method, see [kLanguageInfoTable]{@link https://src.chromium.org/viewvc/chrome/trunk/src/third_party/cld/languages/internal/languages.cc}. - * For an unknown language, 'und' will be returned, which means that [percentage] of the text is unknown to CLD */ language: string; - /** The percentage of the detected language */ percentage: number; } - /** Holds detected language reliability and array of DetectedLanguage */ + /** Holds detected language reliability and array of {@link DetectedLanguage} */ export interface LanguageDetectionResult { /** CLD detected language reliability */ isReliable: boolean; - /** Array of detectedLanguage */ languages: DetectedLanguage[]; } + /** @since Chrome 79 */ + export interface GetMessageOptions { + /** Escape `<` in translation to `<`. This applies only to the message itself, not to the placeholders. Developers might want to use this if the translation is used in an HTML context. Closure Templates used with Closure Compiler generate this automatically. */ + escapeLt?: boolean | undefined; + } + /** - * Gets the accept-languages of the browser. This is different from the locale used by the browser; to get the locale, use i18n.getUILanguage. - * @return The `getAcceptLanguages` method provides its result via callback or returned as a `Promise` (MV3 only). - * @since MV3 + * Gets the accept-languages of the browser. This is different from the locale used by the browser; to get the locale, use {@link i18n.getUILanguage}. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 99. */ export function getAcceptLanguages(): Promise; - /** - * Gets the accept-languages of the browser. This is different from the locale used by the browser; to get the locale, use i18n.getUILanguage. - * Parameter languages: Array of the accept languages of the browser, such as en-US,en,zh-CN - */ export function getAcceptLanguages(callback: (languages: string[]) => void): void; + /** - * Gets the localized string for the specified message. If the message is missing, this method returns an empty string (''). If the format of the getMessage() call is wrong — for example, messageName is not a string or the substitutions array has more than 9 elements — this method returns undefined. - * @param messageName The name of the message, as specified in the messages.json file. - * @param substitutions Optional. Up to 9 substitution strings, if the message requires any. - */ - export function getMessage(messageName: string, substitutions?: string | string[]): string; - /** - * Gets the browser UI language of the browser. This is different from i18n.getAcceptLanguages which returns the preferred user languages. - * @since Chrome 35 + * Gets the localized string for the specified message. If the message is missing, this method returns an empty string (''). If the format of the `getMessage()` call is wrong — for example, messageName is not a string or the substitutions array has more than 9 elements — this method returns `undefined`. + * @param messageName The name of the message, as specified in the `messages.json` file. + * @param substitutions Up to 9 substitution strings, if the message requires any. */ + export function getMessage(messageName: string, substitutions?: string | Array): string; + export function getMessage( + messageName: string, + substitutions: string | Array | undefined, + options?: GetMessageOptions, + ): string; + + /** Gets the browser UI language of the browser. This is different from {@link i18n.getAcceptLanguages} which returns the preferred user languages. */ export function getUILanguage(): string; /** Detects the language of the provided text using CLD. * @param text User input string to be translated. - * @return The `detectLanguage` method provides its result via callback or returned as a `Promise` (MV3 only). - * @since MV3 + * + * Can return its result via Promise in Manifest V3 or later since Chrome 99. + * @since Chrome 47 */ export function detectLanguage(text: string): Promise; - /** Detects the language of the provided text using CLD. - * @param text User input string to be translated. - */ export function detectLanguage(text: string, callback: (result: LanguageDetectionResult) => void): void; } diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index d5086d576dfcea..aee9c3d0d2b521 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -4014,18 +4014,39 @@ async function testCommands() { }); } -// https://developer.chrome.com/docs/extensions/reference/i18n +// https://developer.chrome.com/docs/extensions/reference/api/i18n function testI18n() { - chrome.i18n.getAcceptLanguages((languages) => {}); - chrome.i18n.getMessage("dummy-id", "Hello World!"); - chrome.i18n.getUILanguage(); - chrome.i18n.detectLanguage("dummy-id", (result) => {}); -} + const text = "text"; + chrome.i18n.detectLanguage(text); // ExpectType Promise + chrome.i18n.detectLanguage(text, (result) => { // $ExpectType void + result.isReliable; // $ExpectType boolean + result.languages[0].language; // $ExpectType string + result.languages[0].percentage; // $ExpectType number + }); + // @ts-expect-error + chrome.i18n.detectLanguage(text, () => {}).then(() => {}); + + chrome.i18n.getAcceptLanguages(); // $ExpectType Promise + chrome.i18n.getAcceptLanguages(([language]) => { + language; // $ExpectType string + }); + // @ts-expect-error + chrome.i18n.getAcceptLanguages(() => {}).then(() => {}); + + const messageName = "messageName"; + const substitutions = ["hello", 10]; + + const options: chrome.i18n.GetMessageOptions = { + escapeLt: true, + }; + + chrome.i18n.getMessage(messageName); // $ExpectType string + chrome.i18n.getMessage(messageName, substitutions); // $ExpectType string + chrome.i18n.getMessage(messageName, substitutions, options); // $ExpectType string + // @ts-expect-error + chrome.i18n.getMessage(messageName, 10); -// https://developer.chrome.com/docs/extensions/reference/i18n -async function testI18nForPromise() { - await chrome.i18n.getAcceptLanguages(); - await chrome.i18n.detectLanguage("dummy-id"); + chrome.i18n.getUILanguage(); // $ExpectType string } async function testPageCapture() { From 2dbe179f54b168599cf118299e548ba4d120208d Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Fri, 12 Sep 2025 20:57:12 +0200 Subject: [PATCH 05/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73512=20[chr?= =?UTF-8?q?ome]=20update=20alarms=20namespace=20by=20@erwanjugand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 112 +++++++++++-------------------------- types/chrome/test/index.ts | 28 +++++----- 2 files changed, 47 insertions(+), 93 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index 47ef775c54235c..bf4e0708a2ab33 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -377,120 +377,76 @@ declare namespace chrome { */ export namespace alarms { export interface AlarmCreateInfo { - /** Optional. Length of time in minutes after which the onAlarm event should fire. */ + /** Length of time in minutes after which the {@link onAlarm} event should fire. */ delayInMinutes?: number | undefined; - /** Optional. If set, the onAlarm event should fire every periodInMinutes minutes after the initial event specified by when or delayInMinutes. If not set, the alarm will only fire once. */ + /** If set, the onAlarm event should fire every `periodInMinutes` minutes after the initial event specified by `when` or `delayInMinutes`. If not set, the alarm will only fire once. */ periodInMinutes?: number | undefined; - /** Optional. Time at which the alarm should fire, in milliseconds past the epoch (e.g. Date.now() + n). */ + /** Time at which the alarm should fire, in milliseconds past the epoch (e.g. `Date.now() + n`). */ when?: number | undefined; } export interface Alarm { - /** Optional. If not null, the alarm is a repeating alarm and will fire again in periodInMinutes minutes. */ - periodInMinutes?: number | undefined; - /** Time at which this alarm was scheduled to fire, in milliseconds past the epoch (e.g. Date.now() + n). For performance reasons, the alarm may have been delayed an arbitrary amount beyond this. */ + /** If not null, the alarm is a repeating alarm and will fire again in `periodInMinutes` minutes. */ + periodInMinutes?: number; + /** Time at which this alarm was scheduled to fire, in milliseconds past the epoch (e.g. `Date.now() + n`). For performance reasons, the alarm may have been delayed an arbitrary amount beyond this. */ scheduledTime: number; /** Name of this alarm. */ name: string; } - export interface AlarmEvent extends chrome.events.Event<(alarm: Alarm) => void> {} - - /** - * Creates an alarm. Near the time(s) specified by alarmInfo, the onAlarm event is fired. If there is another alarm with the same name (or no name if none is specified), it will be cancelled and replaced by this alarm. - * In order to reduce the load on the user's machine, Chrome limits alarms to at most once every 1 minute but may delay them an arbitrary amount more. That is, setting delayInMinutes or periodInMinutes to less than 1 will not be honored and will cause a warning. when can be set to less than 1 minute after "now" without warning but won't actually cause the alarm to fire for at least 1 minute. - * To help you debug your app or extension, when you've loaded it unpacked, there's no limit to how often the alarm can fire. - * @param alarmInfo Describes when the alarm should fire. The initial time must be specified by either when or delayInMinutes (but not both). If periodInMinutes is set, the alarm will repeat every periodInMinutes minutes after the initial event. If neither when or delayInMinutes is set for a repeating alarm, periodInMinutes is used as the default for delayInMinutes. - * @return The `create` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function create(alarmInfo: AlarmCreateInfo): Promise; /** - * Creates an alarm. Near the time(s) specified by alarmInfo, the onAlarm event is fired. If there is another alarm with the same name (or no name if none is specified), it will be cancelled and replaced by this alarm. - * In order to reduce the load on the user's machine, Chrome limits alarms to at most once every 1 minute but may delay them an arbitrary amount more. That is, setting delayInMinutes or periodInMinutes to less than 1 will not be honored and will cause a warning. when can be set to less than 1 minute after "now" without warning but won't actually cause the alarm to fire for at least 1 minute. + * Creates an alarm. Near the time(s) specified by `alarmInfo`, the {@link onAlarm} event is fired. If there is another alarm with the same name (or no name if none is specified), it will be cancelled and replaced by this alarm. + * + * In order to reduce the load on the user's machine, Chrome limits alarms to at most once every 30 seconds but may delay them an arbitrary amount more. That is, setting `delayInMinutes` or `periodInMinutes` to less than `0.5` will not be honored and will cause a warning. `when` can be set to less than 30 seconds after "now" without warning but won't actually cause the alarm to fire for at least 30 seconds. + * * To help you debug your app or extension, when you've loaded it unpacked, there's no limit to how often the alarm can fire. * @param name Optional name to identify this alarm. Defaults to the empty string. - * @param alarmInfo Describes when the alarm should fire. The initial time must be specified by either when or delayInMinutes (but not both). If periodInMinutes is set, the alarm will repeat every periodInMinutes minutes after the initial event. If neither when or delayInMinutes is set for a repeating alarm, periodInMinutes is used as the default for delayInMinutes. - * @return The `create` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function create(name: string, alarmInfo: AlarmCreateInfo): Promise; - /** - * Creates an alarm. Near the time(s) specified by alarmInfo, the onAlarm event is fired. If there is another alarm with the same name (or no name if none is specified), it will be cancelled and replaced by this alarm. - * In order to reduce the load on the user's machine, Chrome limits alarms to at most once every 1 minute but may delay them an arbitrary amount more. That is, setting delayInMinutes or periodInMinutes to less than 1 will not be honored and will cause a warning. when can be set to less than 1 minute after "now" without warning but won't actually cause the alarm to fire for at least 1 minute. - * To help you debug your app or extension, when you've loaded it unpacked, there's no limit to how often the alarm can fire. - * @param alarmInfo Describes when the alarm should fire. The initial time must be specified by either when or delayInMinutes (but not both). If periodInMinutes is set, the alarm will repeat every periodInMinutes minutes after the initial event. If neither when or delayInMinutes is set for a repeating alarm, periodInMinutes is used as the default for delayInMinutes. + * @param alarmInfo Describes when the alarm should fire. The initial time must be specified by either `when` or `delayInMinutes` (but not both). If `periodInMinutes` is set, the alarm will repeat every `periodInMinutes` minutes after the initial event. If neither `when` or `delayInMinutes` is set for a repeating alarm, `periodInMinutes` is used as the default for `delayInMinutes`. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 111. */ + export function create(alarmInfo: AlarmCreateInfo): Promise; + export function create(name: string | undefined, alarmInfo: AlarmCreateInfo): Promise; export function create(alarmInfo: AlarmCreateInfo, callback: () => void): void; - /** - * Creates an alarm. Near the time(s) specified by alarmInfo, the onAlarm event is fired. If there is another alarm with the same name (or no name if none is specified), it will be cancelled and replaced by this alarm. - * In order to reduce the load on the user's machine, Chrome limits alarms to at most once every 1 minute but may delay them an arbitrary amount more. That is, setting delayInMinutes or periodInMinutes to less than 1 will not be honored and will cause a warning. when can be set to less than 1 minute after "now" without warning but won't actually cause the alarm to fire for at least 1 minute. - * To help you debug your app or extension, when you've loaded it unpacked, there's no limit to how often the alarm can fire. - * @param name Optional name to identify this alarm. Defaults to the empty string. - * @param alarmInfo Describes when the alarm should fire. The initial time must be specified by either when or delayInMinutes (but not both). If periodInMinutes is set, the alarm will repeat every periodInMinutes minutes after the initial event. If neither when or delayInMinutes is set for a repeating alarm, periodInMinutes is used as the default for delayInMinutes. - */ - export function create(name: string, alarmInfo: AlarmCreateInfo, callback: () => void): void; - /** - * Gets an array of all the alarms. - */ - export function getAll(callback: (alarms: Alarm[]) => void): void; + export function create(name: string | undefined, alarmInfo: AlarmCreateInfo, callback: () => void): void; + /** * Gets an array of all the alarms. - * @return The `getAll` method provides its result via callback or returned as a `Promise` (MV3 only). + * + * Can return its result via Promise in Manifest V3 or later since Chrome 91. */ export function getAll(): Promise; + export function getAll(callback: (alarms: Alarm[]) => void): void; + /** * Clears all alarms. - * function(boolean wasCleared) {...}; - * @return The `clearAll` method provides its result via callback or returned as a `Promise` (MV3 only). + * + * Can return its result via Promise in Manifest V3 or later since Chrome 91. */ export function clearAll(): Promise; - /** - * Clears all alarms. - */ export function clearAll(callback: (wasCleared: boolean) => void): void; + /** * Clears the alarm with the given name. - * @param name The name of the alarm to clear. Defaults to the empty string. - * @return The `clear` method provides its result via callback or returned as a `Promise` (MV3 only). + * + * Can return its result via Promise in Manifest V3 or later since Chrome 91. */ export function clear(name?: string): Promise; - /** - * Clears the alarm with the given name. - * @param name The name of the alarm to clear. Defaults to the empty string. - */ export function clear(callback: (wasCleared: boolean) => void): void; - export function clear(name: string, callback: (wasCleared: boolean) => void): void; - /** - * Clears the alarm without a name. - */ - export function clear(callback: (wasCleared: boolean) => void): void; - /** - * Clears the alarm without a name. - * @return The `clear` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function clear(): Promise; - /** - * Retrieves details about the specified alarm. - */ - export function get(callback: (alarm?: Alarm) => void): void; - /** - * Retrieves details about the specified alarm. - * @return The `get` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function get(): Promise; - /** - * Retrieves details about the specified alarm. - * @param name The name of the alarm to get. Defaults to the empty string. - */ - export function get(name: string, callback: (alarm?: Alarm) => void): void; + export function clear(name: string | undefined, callback: (wasCleared: boolean) => void): void; + /** * Retrieves details about the specified alarm. * @param name The name of the alarm to get. Defaults to the empty string. - * @return The `get` method provides its result via callback or returned as a `Promise` (MV3 only). + * + * Can return its result via Promise in Manifest V3 or later since Chrome 91. */ - export function get(name: string): Promise; + export function get(name?: string): Promise; + export function get(callback: (alarm?: Alarm) => void): void; + export function get(name: string | undefined, callback: (alarm?: Alarm) => void): void; /** Fired when an alarm has elapsed. Useful for event pages. */ - export var onAlarm: AlarmEvent; + export const onAlarm: events.Event<(alarm: Alarm) => void>; } //////////////////// diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index aee9c3d0d2b521..ca5aeec2b8153d 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -1889,7 +1889,7 @@ async function testAction() { }); } -// https://developer.chrome.com/docs/extensions/reference/alarms/ +// https://developer.chrome.com/docs/extensions/reference/api/alarms async function testAlarms() { const alarmCreateInfo: chrome.alarms.AlarmCreateInfo = { delayInMinutes: 1, @@ -1905,10 +1905,10 @@ async function testAlarms() { chrome.alarms.create("name", alarmCreateInfo, () => {}).then(() => {}); chrome.alarms.getAll(); // $ExpectType Promise - chrome.alarms.getAll((alarms) => { // $ExpectType void - alarms[0].name; // $ExpectType string - alarms[0].periodInMinutes; // $ExpectType number | undefined - alarms[0].scheduledTime; // $ExpectType number + chrome.alarms.getAll(([alarm]) => { // $ExpectType void + alarm.name; // $ExpectType string + alarm.periodInMinutes; // $ExpectType number | undefined + alarm.scheduledTime; // $ExpectType number }); // @ts-expect-error chrome.alarms.getAll(() => {}).then(() => {}); @@ -1935,19 +1935,17 @@ async function testAlarms() { chrome.alarms.get("name"); // $ExpectType Promise chrome.alarms.get((alarm) => { // $ExpectType void alarm; // $ExpectType Alarm | undefined - if (alarm) { - alarm.name; // $ExpectType string - alarm.periodInMinutes; // $ExpectType number | undefined - alarm.scheduledTime; // $ExpectType number - } + if (!alarm) return; + alarm.name; // $ExpectType string + alarm.periodInMinutes; // $ExpectType number | undefined + alarm.scheduledTime; // $ExpectType number }); chrome.alarms.get("name", (alarm) => { // $ExpectType void alarm; // $ExpectType Alarm | undefined - if (alarm) { - alarm.name; // $ExpectType string - alarm.periodInMinutes; // $ExpectType number | undefined - alarm.scheduledTime; // $ExpectType number - } + if (!alarm) return; + alarm.name; // $ExpectType string + alarm.periodInMinutes; // $ExpectType number | undefined + alarm.scheduledTime; // $ExpectType number }); // @ts-expect-error chrome.alarms.get("name", () => {}).then(() => {}); From 2cbf2d07a178154c08a1de83fe04aea3e1b381f7 Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Fri, 12 Sep 2025 20:58:45 +0200 Subject: [PATCH 06/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73523=20[chr?= =?UTF-8?q?ome]=20update=20extension=20namespace=20by=20@erwanjugand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 121 ++++++++++++++++++------------------- types/chrome/test/index.ts | 92 ++++++++++++++++++++-------- 2 files changed, 126 insertions(+), 87 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index bf4e0708a2ab33..1084886d77ce42 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -4332,117 +4332,114 @@ declare namespace chrome { * The `chrome.extension` API has utilities that can be used by any extension page. It includes support for exchanging messages between an extension and its content scripts or between extensions, as described in detail in Message Passing. */ export namespace extension { + /** + * The type of extension view. + * @since Chrome 44 + */ + export enum ViewType { + TAB = "tab", + POPUP = "popup", + } + export interface FetchProperties { /** - * Optional. - * Chrome 54+ * Find a view according to a tab id. If this field is omitted, returns all views. + * @since Chrome 54 */ tabId?: number | undefined; - /** Optional. The window to restrict the search to. If omitted, returns all views. */ + /** The window to restrict the search to. If omitted, returns all views. */ windowId?: number | undefined; - /** Optional. The type of view to get. If omitted, returns all views (including background pages and tabs). Valid values: 'tab', 'notification', 'popup'. */ - type?: string | undefined; + /** The type of view to get. If omitted, returns all views (including background pages and tabs). */ + type?: `${ViewType}` | undefined; } - export interface LastError { - /** Description of the error that has taken place. */ - message: string; - } - - export interface OnRequestEvent extends - chrome.events.Event< - | ((request: any, sender: runtime.MessageSender, sendResponse: (response: any) => void) => void) - | ((sender: runtime.MessageSender, sendResponse: (response: any) => void) => void) - > - {} + /** True for content scripts running inside incognito tabs, and for extension pages running inside an incognito process. The latter only applies to extensions with 'split' incognito_behavior. */ + export const inIncognitoContext: boolean; /** - * @since Chrome 7 - * True for content scripts running inside incognito tabs, and for extension pages running inside an incognito process. The latter only applies to extensions with 'split' incognito_behavior. + * Set for the lifetime of a callback if an ansychronous extension api has resulted in an error. If no error has occurred lastError will be `undefined`. + * @deprecated since Chrome 58. Please use {@link runtime.lastError} */ - export var inIncognitoContext: boolean; - /** Set for the lifetime of a callback if an ansychronous extension api has resulted in an error. If no error has occurred lastError will be undefined. */ - export var lastError: LastError; + export const lastError: runtime.LastError | undefined; /** Returns the JavaScript 'window' object for the background page running inside the current extension. Returns null if the extension has no background page. */ export function getBackgroundPage(): Window | null; + /** * Converts a relative path within an extension install directory to a fully-qualified URL. * @param path A path to a resource within an extension expressed relative to its install directory. + * @deprecated since Chrome 58. Please use {@link runtime.getURL} */ export function getURL(path: string): string; - /** - * Sets the value of the ap CGI parameter used in the extension's update URL. This value is ignored for extensions that are hosted in the Chrome Extension Gallery. - * @since Chrome 9 - */ + + /** Sets the value of the ap CGI parameter used in the extension's update URL. This value is ignored for extensions that are hosted in the Chrome Extension Gallery. */ export function setUpdateUrlData(data: string): void; + /** Returns an array of the JavaScript 'window' objects for each of the pages running inside the current extension. */ export function getViews(fetchProperties?: FetchProperties): Window[]; + /** - * Retrieves the state of the extension's access to the 'file://' scheme (as determined by the user-controlled 'Allow access to File URLs' checkbox. - * @since Chrome 12 - * @return The `isAllowedFileSchemeAccess` method provides its result via callback or returned as a `Promise` (MV3 only). + * Retrieves the state of the extension's access to the 'file://' scheme. This corresponds to the user-controlled per-extension 'Allow access to File URLs' setting accessible via the `chrome://extensions` page. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 99. */ export function isAllowedFileSchemeAccess(): Promise; - /** - * Retrieves the state of the extension's access to the 'file://' scheme (as determined by the user-controlled 'Allow access to File URLs' checkbox. - * @since Chrome 12 - * Parameter isAllowedAccess: True if the extension can access the 'file://' scheme, false otherwise. - */ export function isAllowedFileSchemeAccess(callback: (isAllowedAccess: boolean) => void): void; + /** - * Retrieves the state of the extension's access to Incognito-mode (as determined by the user-controlled 'Allowed in Incognito' checkbox. - * @since Chrome 12 - * @return The `isAllowedIncognitoAccess` method provides its result via callback or returned as a `Promise` (MV3 only). + * Retrieves the state of the extension's access to Incognito-mode. This corresponds to the user-controlled per-extension 'Allowed in Incognito' setting accessible via the `chrome://extensions` page. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 99. */ export function isAllowedIncognitoAccess(): Promise; - /** - * Retrieves the state of the extension's access to Incognito-mode (as determined by the user-controlled 'Allowed in Incognito' checkbox. - * @since Chrome 12 - * Parameter isAllowedAccess: True if the extension has access to Incognito mode, false otherwise. - */ export function isAllowedIncognitoAccess(callback: (isAllowedAccess: boolean) => void): void; + /** - * Sends a single request to other listeners within the extension. Similar to runtime.connect, but only sends a single request with an optional response. The extension.onRequest event is fired in each page of the extension. - * @deprecated Deprecated since Chrome 33. Please use runtime.sendMessage. + * Sends a single request to other listeners within the extension. Similar to {@link runtime.connect}, but only sends a single request with an optional response. The {@link extension.onRequest} event is fired in each page of the extension. + * + * MV2 only * @param extensionId The extension ID of the extension you want to connect to. If omitted, default is your own extension. - * @param responseCallback If you specify the responseCallback parameter, it should be a function that looks like this: - * function(any response) {...}; - * Parameter response: The JSON response object sent by the handler of the request. If an error occurs while connecting to the extension, the callback will be called with no arguments and runtime.lastError will be set to the error message. + * @deprecated Please use {@link runtime.sendMessage} */ export function sendRequest( - extensionId: string, + extensionId: string | undefined, request: Request, - responseCallback?: (response: Response) => void, + callback?: (response: Response) => void, ): void; - /** - * Sends a single request to other listeners within the extension. Similar to runtime.connect, but only sends a single request with an optional response. The extension.onRequest event is fired in each page of the extension. - * @deprecated Deprecated since Chrome 33. Please use runtime.sendMessage. - * @param responseCallback If you specify the responseCallback parameter, it should be a function that looks like this: - * function(any response) {...}; - * Parameter response: The JSON response object sent by the handler of the request. If an error occurs while connecting to the extension, the callback will be called with no arguments and runtime.lastError will be set to the error message. - */ export function sendRequest( request: Request, - responseCallback?: (response: Response) => void, + callback?: (response: Response) => void, ): void; + /** - * Returns an array of the JavaScript 'window' objects for each of the tabs running inside the current extension. If windowId is specified, returns only the 'window' objects of tabs attached to the specified window. - * @deprecated Deprecated since Chrome 33. Please use extension.getViews {type: "tab"}. + * Returns an array of the JavaScript 'window' objects for each of the tabs running inside the current extension. If `windowId` is specified, returns only the 'window' objects of tabs attached to the specified window. + * + * MV2 only + * @deprecated Please use {@link extension.getViews} `{type: "tab"}`. */ export function getExtensionTabs(windowId?: number): Window[]; /** * Fired when a request is sent from either an extension process or a content script. - * @deprecated Deprecated since Chrome 33. Please use runtime.onMessage. + * + * MV2 only + * @deprecated Please use {@link runtime.onMessage}. */ - export var onRequest: OnRequestEvent; + export const onRequest: chrome.events.Event< + | ((request: any, sender: runtime.MessageSender, sendResponse: (response: any) => void) => void) + | ((sender: runtime.MessageSender, sendResponse: (response: any) => void) => void) + >; + /** * Fired when a request is sent from another extension. - * @deprecated Deprecated since Chrome 33. Please use runtime.onMessageExternal. + * + * MV2 only + * @deprecated Please use {@link runtime.onMessageExternal}. */ - export var onRequestExternal: OnRequestEvent; + export const onRequestExternal: chrome.events.Event< + | ((request: any, sender: runtime.MessageSender, sendResponse: (response: any) => void) => void) + | ((sender: runtime.MessageSender, sendResponse: (response: any) => void) => void) + >; } //////////////////// diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index ca5aeec2b8153d..34f9fc17730874 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -3425,18 +3425,6 @@ function testStorageForPromise() { ); } -function testExtensionSendRequest() { - chrome.extension.sendRequest("dummy-id", "Hello World!"); - chrome.extension.sendRequest("dummy-id", "Hello World!", console.log); - chrome.extension.sendRequest("dummy-id", "Hello World!", console.log); - chrome.extension.sendRequest("dummy-id", "Hello World!", console.log); - chrome.extension.sendRequest("dummy-id", "Hello World!", console.log); - // @ts-expect-error - chrome.extension.sendRequest("dummy-id", "Hello World!", console.log); - // @ts-expect-error - chrome.extension.sendRequest("dummy-id", "Hello World!", (num: number) => alert(num + 1)); -} - // https://developer.chrome.com/docs/extensions/reference/api/contextMenus function testContextMenus() { chrome.contextMenus.ContextType.ACTION === "action"; @@ -4333,21 +4321,75 @@ async function testDownloadsForPromise() { await chrome.downloads.setUiOptions({ enabled: true }); } -// https://developer.chrome.com/docs/extensions/reference/extension +// https://developer.chrome.com/docs/extensions/reference/api/extension function testExtension() { - chrome.extension.getBackgroundPage(); - chrome.extension.getURL("/"); - chrome.extension.setUpdateUrlData(""); - chrome.extension.getViews({}); - chrome.extension.isAllowedFileSchemeAccess((isAllowedAccess) => {}); - chrome.extension.isAllowedIncognitoAccess((isAllowedAccess) => {}); - chrome.extension.getExtensionTabs(1); -} + chrome.extension.ViewType.POPUP === "popup"; + chrome.extension.ViewType.TAB === "tab"; + + chrome.extension.inIncognitoContext; // ExpectType boolean + + chrome.extension.lastError; // ExpectType chrome.runtime.LastError + + chrome.extension.getBackgroundPage(); // ExpectType Window | null + + const fetchProperties: chrome.extension.FetchProperties = { + tabId: 1, + type: "tab", + windowId: 1, + }; + + chrome.extension.getViews(fetchProperties); // ExpectType Window[] + + chrome.extension.isAllowedFileSchemeAccess(); // ExpectType Promise + chrome.extension.isAllowedIncognitoAccess((isAllowedAccess) => { // ExpectType void + isAllowedAccess; // ExpectType boolean + }); + // @ts-expect-error + chrome.extension.isAllowedFileSchemeAccess(() => {}).then(() => {}); -// https://developer.chrome.com/docs/extensions/reference/extension -async function testExtensionForPromise() { - await chrome.extension.isAllowedFileSchemeAccess(); - await chrome.extension.isAllowedIncognitoAccess(); + chrome.extension.isAllowedIncognitoAccess(); // ExpectType Promise + chrome.extension.isAllowedIncognitoAccess((isAllowedAccess) => { // ExpectType void + isAllowedAccess; // ExpectType boolean + }); + // @ts-expect-error + chrome.extension.isAllowedIncognitoAccess(() => {}).then(() => {}); + + chrome.extension.setUpdateUrlData("data"); // ExpectType void + + chrome.extension.getExtensionTabs(); // ExpectType Window[] + chrome.extension.getExtensionTabs(1); // ExpectType Window[] + + chrome.extension.getURL("/path"); // ExpectType string + + const extensionId = "dummy-id"; + const request = {}; + + chrome.extension.sendRequest(request); // ExpectType void + chrome.extension.sendRequest(request, (response) => { // ExpectType void + response; // ExpectType any + }); + chrome.extension.sendRequest(extensionId, request); // ExpectType void + chrome.extension.sendRequest(extensionId, request, (response) => { // ExpectType void + response; // ExpectType any + }); + chrome.extension.sendRequest(1, (response) => { + response; // ExpectType boolean + }); + chrome.extension.sendRequest(extensionId, 1, (response) => { + response; // ExpectType boolean + }); + + checkChromeEvent(chrome.extension.onRequest, (request, sender, sendResponse) => { + request; // ExpectType any + sender; // ExpectType chrome.extension.MessageSender + sendResponse({}); // ExpectType void + }); + + checkChromeEvent(chrome.extension.onRequestExternal, (request, sender, sendResponse) => { + request; // ExpectType any + sender; // ExpectType chrome.extension.MessageSender + sendResponse({}); // ExpectType void + }); } // https://developer.chrome.com/docs/extensions/reference/fontSettings From a12a5d475db293b96a78eb160a53869340e5245d Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Fri, 12 Sep 2025 21:00:18 +0200 Subject: [PATCH 07/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73526=20[chr?= =?UTF-8?q?ome]=20update=20declarativeContent=20namespace=20by=20@erwanjug?= =?UTF-8?q?and?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 60 +++++++++++++++++++-------- types/chrome/test/index.ts | 83 +++++++++++++++++++++++++++++++------- 2 files changed, 112 insertions(+), 31 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index 1084886d77ce42..fb49019d690e1c 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -2406,45 +2406,70 @@ declare namespace chrome { * Permissions: "declarativeContent" */ export namespace declarativeContent { - export class PageStateMatcherProperties { - /** Optional. Filters URLs for various criteria. See event filtering. All criteria are case sensitive. */ + interface PageStateMatcherProperties { + /** Matches if the conditions of the `UrlFilter` are fulfilled for the top-level URL of the page. */ pageUrl?: events.UrlFilter | undefined; - /** Optional. Matches if all of the CSS selectors in the array match displayed elements in a frame with the same origin as the page's main frame. All selectors in this array must be compound selectors to speed up matching. Note that listing hundreds of CSS selectors or CSS selectors that match hundreds of times per page can still slow down web sites. */ + /** Matches if all of the CSS selectors in the array match displayed elements in a frame with the same origin as the page's main frame. All selectors in this array must be compound selectors to speed up matching. Note: Listing hundreds of CSS selectors or listing CSS selectors that match hundreds of times per page can slow down web sites. */ css?: string[] | undefined; /** - * Optional. - * @since Chrome 45 * Matches if the bookmarked state of the page is equal to the specified value. Requires the bookmarks permission. + * @since Chrome 45 */ isBookmarked?: boolean | undefined; } - /** Matches the state of a web page by various criteria. */ + /** Matches the state of a web page based on various criteria. */ export class PageStateMatcher { - constructor(options: PageStateMatcherProperties); + constructor(arg: PageStateMatcherProperties); + } + + export interface RequestContentScriptProperties { + /** Whether the content script runs in all frames of the matching page, or in only the top frame. Default is `false`. */ + allFrames?: boolean | undefined; + + /** Names of CSS files to be injected as a part of the content script. */ + css?: string[] | undefined; + + /** Names of JavaScript files to be injected as a part of the content script. */ + js?: string[] | undefined; + + /** Whether to insert the content script on `about:blank` and `about:srcdoc`. Default is `false`. */ + matchAboutBlank?: boolean | undefined; + } + + /** Declarative event action that injects a content script. */ + export class RequestContentScript { + constructor(arg: RequestContentScriptProperties); } /** - * Declarative event action that enables the extension's action while the corresponding conditions are met. - * Manifest v3. + * A declarative event action that sets the extension's toolbar {@link action} to an enabled state while the corresponding conditions are met. This action can be used without host permissions. If the extension has the `activeTab` permission, clicking the page action grants access to the active tab. + * + * On pages where the conditions are not met the extension's toolbar action will be grey-scale, and clicking it will open the context menu, instead of triggering the action. + * @since MV3 */ export class ShowAction {} /** - * Declarative event action that shows the extension's page action while the corresponding conditions are met. - * Manifest v2. + * A declarative event action that sets the extension's {@link pageAction} to an enabled state while the corresponding conditions are met. This action can be used without host permissions, but the extension must have a page action. If the extension has the `activeTab` permission, clicking the page action grants access to the active tab. + * + * On pages where the conditions are not met the extension's toolbar action will be grey-scale, and clicking it will open the context menu, instead of triggering the action. + * + * MV2 only */ export class ShowPageAction {} - /** Declarative event action that changes the icon of the page action while the corresponding conditions are met. */ + /** + * Declarative event action that sets the n-dip square icon for the extension's {@link pageAction} or {@link browserAction} while the corresponding conditions are met. This action can be used without host permissions, but the extension must have a page or browser action. + * + * Exactly one of `imageData` or `path` must be specified. Both are dictionaries mapping a number of pixels to an image representation. The image representation in `imageData` is an `ImageData` object; for example, from a `canvas` element, while the image representation in `path` is the path to an image file relative to the extension's manifest. If `scale` screen pixels fit into a device-independent pixel, the `scale * n` icon is used. If that scale is missing, another image is resized to the required size. + */ export class SetIcon { constructor(options?: { imageData?: ImageData | { [size: string]: ImageData } | undefined }); } - /** Provides the Declarative Event API consisting of addRules, removeRules, and getRules. */ - export interface PageChangedEvent extends chrome.events.Event<() => void> {} - - export var onPageChanged: PageChangedEvent; + /** Provides the Declarative Event API consisting of {@link events.Event.addRules addRules}, {@link events.Event.removeRules removeRules}, and {@link events.Event.getRules getRules}. */ + export const onPageChanged: events.Event<() => void>; } //////////////////// @@ -4287,7 +4312,8 @@ declare namespace chrome { * Unregisters currently registered rules. * @param ruleIdentifiers If an array is passed, only rules with identifiers contained in this array are unregistered. */ - removeRules(ruleIdentifiers?: string[] | undefined, callback?: () => void): void; + removeRules(ruleIdentifiers: string[] | undefined, callback?: () => void): void; + removeRules(callback?: () => void): void; /** * Registers rules to handle events. diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index 34f9fc17730874..4391774d3661cb 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -1071,24 +1071,79 @@ function testDebugger() { }); } -// https://developer.chrome.com/extensions/declarativeContent +// https://developer.chrome.com/docs/extensions/reference/api/declarativeContent function testDeclarativeContent() { - const activeIcon: ImageData = new ImageData(32, 32); + const pageStateMatcherProperties: chrome.declarativeContent.PageStateMatcherProperties = { + css: [""], + isBookmarked: true, + pageUrl: { + cidrBlocks: [""], + hostContains: "", + hostEquals: "", + hostPrefix: "", + hostSuffix: "", + originAndPathMatches: "", + pathContains: "", + pathEquals: "", + pathPrefix: "", + pathSuffix: "", + ports: [1], + queryContains: "", + queryEquals: "", + queryPrefix: "", + querySuffix: "", + schemes: ["https"], + urlContains: "", + urlEquals: "", + urlMatches: "", + urlPrefix: "", + urlSuffix: "", + }, + }; + + const condition = new chrome.declarativeContent.PageStateMatcher(pageStateMatcherProperties); // ExpectType PageStateMatcher + + const requestContentScriptProperties: chrome.declarativeContent.RequestContentScriptProperties = { + allFrames: true, + css: [""], + js: [""], + matchAboutBlank: true, + }; + + new chrome.declarativeContent.RequestContentScript(requestContentScriptProperties); // ExpectType RequestContentScript + + const imageData = new ImageData(32, 32); + + new chrome.declarativeContent.SetIcon({ imageData }); // ExpectType SetIcon + + const action = new chrome.declarativeContent.ShowAction(); // ExpectType ShowAction + + new chrome.declarativeContent.ShowPageAction(); // ExpectType ShowPageAction const rule: chrome.events.Rule = { - conditions: [ - new chrome.declarativeContent.PageStateMatcher({ - pageUrl: { - hostContains: "test.com", - }, - }), - ], - actions: [ - new chrome.declarativeContent.SetIcon({ - imageData: activeIcon, - }), - ], + conditions: [condition], + actions: [action], }; + + chrome.declarativeContent.onPageChanged.addRules([rule]); // $ExpectType void + chrome.declarativeContent.onPageChanged.addRules([rule], ([rule]) => { // $ExpectType void + rule; // $ExpectType Rule + }); + + chrome.declarativeContent.onPageChanged.getRules(([rule]) => { // $ExpectType void + rule; // $ExpectType Rule + }); + + chrome.declarativeContent.onPageChanged.getRules(([rule]) => { // $ExpectType void + rule; // $ExpectType Rule + }); + chrome.declarativeContent.onPageChanged.getRules(["identifier"], ([rule]) => { // $ExpectType void + rule; // $ExpectType Rule + }); + + chrome.declarativeContent.onPageChanged.removeRules(); // $ExpectType void + chrome.declarativeContent.onPageChanged.removeRules(() => void 0); // $ExpectType void + chrome.declarativeContent.onPageChanged.removeRules(["identifier"], () => void 0); // $ExpectType void } // https://developer.chrome.com/extensions/storage#type-StorageArea From 79ec5fb57c5a9ef8fcb79f0fcae74c90ce90c20b Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Fri, 12 Sep 2025 21:00:42 +0200 Subject: [PATCH 08/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73528=20[chr?= =?UTF-8?q?ome]=20update=20fileBrowserHandler=20namespace=20by=20@erwanjug?= =?UTF-8?q?and?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 37 +++---------------------------------- types/chrome/test/index.ts | 10 ++++++++++ 2 files changed, 13 insertions(+), 34 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index fb49019d690e1c..69a7701d28512b 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -4556,47 +4556,16 @@ declare namespace chrome { * @platform ChromeOS only */ export namespace fileBrowserHandler { - export interface SelectionParams { - /** - * Optional. - * List of file extensions that the selected file can have. The list is also used to specify what files to be shown in the select file dialog. Files with the listed extensions are only shown in the dialog. Extensions should not include the leading '.'. Example: ['jpg', 'png'] - * @since Chrome 23 - */ - allowedFileExtensions?: string[] | undefined; - /** Suggested name for the file. */ - suggestedName: string; - } - - export interface SelectionResult { - /** Optional. Selected file entry. It will be null if a file hasn't been selected. */ - entry?: object | null | undefined; - /** Whether the file has been selected. */ - success: boolean; - } - /** Event details payload for fileBrowserHandler.onExecute event. */ export interface FileHandlerExecuteEventDetails { - /** Optional. The ID of the tab that raised this event. Tab IDs are unique within a browser session. */ - tab_id?: number | undefined; + /** The ID of the tab that raised this event. Tab IDs are unique within a browser session. */ + tab_id?: number; /** Array of Entry instances representing files that are targets of this action (selected in ChromeOS file browser). */ entries: any[]; } - export interface FileBrowserHandlerExecuteEvent - extends chrome.events.Event<(id: string, details: FileHandlerExecuteEventDetails) => void> - {} - - /** - * Prompts user to select file path under which file should be saved. When the file is selected, file access permission required to use the file (read, write and create) are granted to the caller. The file will not actually get created during the function call, so function caller must ensure its existence before using it. The function has to be invoked with a user gesture. - * @since Chrome 21 - * @param selectionParams Parameters that will be used while selecting the file. - * @param callback Function called upon completion. - * Parameter result: Result of the method. - */ - export function selectFile(selectionParams: SelectionParams, callback: (result: SelectionResult) => void): void; - /** Fired when file system action is executed from ChromeOS file browser. */ - export var onExecute: FileBrowserHandlerExecuteEvent; + export const onExecute: events.Event<(id: string, details: FileHandlerExecuteEventDetails) => void>; } //////////////////// diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index 4391774d3661cb..e0d5b6395fc567 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -4686,6 +4686,16 @@ async function testOffscreenDocument() { await chrome.offscreen.closeDocument(); } +// https://developer.chrome.com/docs/extensions/reference/api/fileBrowserHandler +function testFileBrowserHandler() { + checkChromeEvent(chrome.fileBrowserHandler.onExecute, (id, details) => { + id; // $ExpectType string + details; // $ExpectType FileHandlerExecuteEventDetails + details.entries; // $ExpectType any[] + details.tab_id; // $ExpectType number | undefined + }); +} + // https://developer.chrome.com/docs/extensions/reference/api/fileSystemProvider function testFileSystemProvider() { chrome.fileSystemProvider.ChangeType.CHANGED === "CHANGED"; From 4e3e1ee2ef71e97933399ed16dcaf7d642a64ee0 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Fri, 12 Sep 2025 20:01:47 +0100 Subject: [PATCH 09/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73522=20[@ty?= =?UTF-8?q?pes/govuk-frontend]=20Update=20for=20GOV.UK=20Frontend=20v5.11.?= =?UTF-8?q?2=20by=20@colinrotherham?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dist/govuk/common/configuration.d.ts | 20 ++ .../dist/govuk/common/index.d.ts | 30 +-- .../dist/govuk/errors/index.d.ts | 16 +- types/govuk-frontend/dist/govuk/init.d.ts | 73 +++-- types/govuk-frontend/govuk-frontend-tests.mts | 255 ++++++++++++++++-- types/govuk-frontend/govuk-frontend-tests.ts | 255 ++++++++++++++++-- types/govuk-frontend/package.json | 6 +- 7 files changed, 570 insertions(+), 85 deletions(-) diff --git a/types/govuk-frontend/dist/govuk/common/configuration.d.ts b/types/govuk-frontend/dist/govuk/common/configuration.d.ts index 2fa940a020485f..61c8f3f893347c 100644 --- a/types/govuk-frontend/dist/govuk/common/configuration.d.ts +++ b/types/govuk-frontend/dist/govuk/common/configuration.d.ts @@ -1,4 +1,5 @@ import { Component } from "../component.js"; +import { type CompatibleClass, type Config, type CreateAllOptions, type OnErrorCallback } from "../init.js"; /** * Normalise string @@ -44,6 +45,25 @@ export function normaliseDataset< dataset: DOMStringMap, ): ObjectNested; +/** + * Normalise options passed to `initAll` or `createAll` + * + * @internal + * @template {CompatibleClass} ComponentClass + * @param {Config | CreateAllOptions | OnErrorCallback | Element | Document | null} [scopeOrOptions] - Scope of the document to search within, initialisation options or error callback function + * @returns {CreateAllOptions} Normalised options + */ +export function normaliseOptions< + ComponentClass extends CompatibleClass, +>( + scopeOrOptions?: + | Config + | CreateAllOptions + | OnErrorCallback + | Element + | Document + | null, +): CreateAllOptions; /** * Config merging function * diff --git a/types/govuk-frontend/dist/govuk/common/index.d.ts b/types/govuk-frontend/dist/govuk/common/index.d.ts index 640b55c119fd27..71b75b5a76d54b 100644 --- a/types/govuk-frontend/dist/govuk/common/index.d.ts +++ b/types/govuk-frontend/dist/govuk/common/index.d.ts @@ -1,5 +1,3 @@ -import { type ObjectNested } from "./configuration.js"; - /** * Common helpers which do not require polyfill. * @@ -7,18 +5,6 @@ import { type ObjectNested } from "./configuration.js"; * so that the polyfill can be properly tree-shaken and does not burden * the components that do not need that helper */ - -/** - * Get hash fragment from URL - * - * Extract the hash fragment (everything after the hash) from a URL, - * but not including the hash symbol - * - * @param {string} url - URL - * @returns {string | undefined} Fragment from URL, without the hash - */ -export function getFragmentFromUrl(url: string): string | undefined; - /** * Get GOV.UK Frontend breakpoint value from CSS custom property * @@ -75,14 +61,26 @@ export function isSupported($scope?: HTMLElement | null): boolean; * Check for an object * * @internal - * @template {Partial>} [ObjectType=ObjectNested] + * @template {Partial>} ObjectType * @param {unknown | ObjectType} option - Option to check * @returns {option is ObjectType} Whether the option is an object */ export function isObject< - ObjectType extends Partial> = ObjectNested, + ObjectType extends Partial>, >(option: unknown | ObjectType): option is ObjectType; +/** + * Check for valid scope + * + * @internal + * @template {Element | Document} ScopeType + * @param {unknown | ScopeType} $scope - Scope of the document to search within + * @returns {$scope is ScopeType} Whether the scope can be queried + */ +export function isScope( + $scope: unknown | ScopeType, +): $scope is ScopeType; + /** * Format error message * diff --git a/types/govuk-frontend/dist/govuk/errors/index.d.ts b/types/govuk-frontend/dist/govuk/errors/index.d.ts index e8e4125620a14b..32309906aa6b0a 100644 --- a/types/govuk-frontend/dist/govuk/errors/index.d.ts +++ b/types/govuk-frontend/dist/govuk/errors/index.d.ts @@ -73,22 +73,22 @@ export class InitError extends GOVUKFrontendError { */ export interface ElementErrorOptions { /** - * - An identifier that'll let the user understand which element has an error. This is whatever makes the most sense + * - The element in error (optional) */ - identifier: string; + element?: Document | Element | null | undefined; /** - * - The element in error + * - Component throwing the error (optional) */ - element?: Element | null | undefined; + component?: ComponentWithModuleName | undefined; /** - * - The type that was expected for the identifier + * - An identifier that'll let the user understand which element has an error. This is whatever makes the most sense */ - expectedType?: string | undefined; + identifier: string; /** - * - Component throwing the error + * - The type that was expected for the identifier (optional) */ - component: ComponentWithModuleName; + expectedType?: string | undefined; } diff --git a/types/govuk-frontend/dist/govuk/init.d.ts b/types/govuk-frontend/dist/govuk/init.d.ts index aafce8636ee873..2536e2513740da 100644 --- a/types/govuk-frontend/dist/govuk/init.d.ts +++ b/types/govuk-frontend/dist/govuk/init.d.ts @@ -1,11 +1,14 @@ -import { type AccordionConfig } from "./components/accordion/accordion.js"; -import { type ButtonConfig } from "./components/button/button.js"; -import { type CharacterCountConfig } from "./components/character-count/character-count.js"; -import { type ErrorSummaryConfig } from "./components/error-summary/error-summary.js"; -import { type ExitThisPageConfig } from "./components/exit-this-page/exit-this-page.js"; -import { type FileUploadConfig } from "./components/file-upload/file-upload.js"; -import { type NotificationBannerConfig } from "./components/notification-banner/notification-banner.js"; -import { type PasswordInputConfig } from "./components/password-input/password-input.js"; +import { Accordion, type AccordionConfig } from "./components/accordion/accordion.js"; +import { Button, type ButtonConfig } from "./components/button/button.js"; +import { CharacterCount, type CharacterCountConfig } from "./components/character-count/character-count.js"; +import { ErrorSummary, type ErrorSummaryConfig } from "./components/error-summary/error-summary.js"; +import { ExitThisPage, type ExitThisPageConfig } from "./components/exit-this-page/exit-this-page.js"; +import { FileUpload, type FileUploadConfig } from "./components/file-upload/file-upload.js"; +import { + NotificationBanner, + type NotificationBannerConfig, +} from "./components/notification-banner/notification-banner.js"; +import { PasswordInput, type PasswordInputConfig } from "./components/password-input/password-input.js"; export interface CompatibleClass { new(...args: any[]): any; @@ -16,6 +19,28 @@ export interface CompatibleClass { * Config for all components via `initAll()` */ export interface Config { + /** + * - Scope of the document to search within + */ + scope?: Document | Element | null | undefined; + + /** + * - Initialisation error callback + */ + onError?: + | OnErrorCallback< + | typeof Accordion + | typeof Button + | typeof CharacterCount + | typeof ErrorSummary + | typeof ExitThisPage + | typeof FileUpload + | typeof NotificationBanner + | typeof PasswordInput + | undefined + > + | undefined; + /** * - Accordion config */ @@ -60,15 +85,18 @@ export interface Config { /** * Component config keys, e.g. `accordion` and `characterCount` */ -export type ConfigKey = keyof Config; +export type ConfigKey = keyof Omit; export type ComponentConfig = ConstructorParameters[1]; -export interface ErrorContext { +export interface ErrorContext< + ComponentClass extends CompatibleClass | undefined = undefined, +> { /** * - Element used for component module initialisation */ - element?: Element | undefined; + element?: ComponentClass extends CompatibleClass ? Element + : undefined; /** * - Class of component @@ -76,12 +104,15 @@ export interface ErrorContext { component?: ComponentClass | undefined; /** - * - Config supplied to component + * - Config supplied to components */ - config: ComponentConfig; + config?: ComponentClass extends CompatibleClass ? ComponentConfig + : Config; } -export type OnErrorCallback = ( +export type OnErrorCallback< + ComponentClass extends CompatibleClass | undefined = undefined, +> = ( error: unknown, context: ErrorContext, ) => any; @@ -90,7 +121,7 @@ export interface CreateAllOptions { /** * - scope of the document to search within */ - scope?: Document | Element | undefined; + scope?: Document | Element | null | undefined; /** * - callback function if error throw by component on init @@ -104,13 +135,10 @@ export interface CreateAllOptions { * Use the `data-module` attributes to find, instantiate and init all of the * components provided as part of GOV.UK Frontend. * - * @param {Config & { scope?: Element, onError?: OnErrorCallback }} [config] - Config for all components (with optional scope) + * @param {Config | Element | Document | null} [scopeOrConfig] - Scope of the document to search within or config for all components (with optional scope) */ export function initAll( - config?: Config & { - scope?: Element; - onError?: OnErrorCallback; - }, + scopeOrConfig?: Config | Element | Document | null, ): void; /** @@ -125,15 +153,16 @@ export function initAll( * @template {CompatibleClass} ComponentClass * @param {ComponentClass} Component - class of the component to create * @param {ComponentConfig} [config] - Config supplied to component - * @param {OnErrorCallback | Element | Document | CreateAllOptions } [createAllOptions] - options for createAll including scope of the document to search within and callback function if error throw by component on init + * @param {OnErrorCallback | Element | Document | null | CreateAllOptions} [scopeOrOptions] - options for createAll including scope of the document to search within and callback function if error throw by component on init * @returns {Array>} - array of instantiated components */ export function createAll( Component: ComponentClass, config?: ComponentConfig, - createAllOptions?: + scopeOrOptions?: | OnErrorCallback | Element | Document + | null | CreateAllOptions, ): Array>; diff --git a/types/govuk-frontend/govuk-frontend-tests.mts b/types/govuk-frontend/govuk-frontend-tests.mts index 633c6991b0fa9c..53c0ca615a6ae3 100644 --- a/types/govuk-frontend/govuk-frontend-tests.mts +++ b/types/govuk-frontend/govuk-frontend-tests.mts @@ -122,164 +122,357 @@ isSupported(); createAll(Accordion); createAll(Accordion, Accordion.defaults); +createAll(Accordion, Accordion.defaults, null); +createAll(Accordion, Accordion.defaults, undefined); +createAll(Accordion, Accordion.defaults, document); createAll(Accordion, Accordion.defaults, document.body); createAll(Accordion, Accordion.defaults, console.error); createAll(Accordion, Accordion.defaults, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof Button; + context.config?.i18n; + context.config?.rememberExpanded; + }, }); createAll(Button); createAll(Button, Button.defaults); +createAll(Button, Button.defaults, null); +createAll(Button, Button.defaults, undefined); +createAll(Button, Button.defaults, document); createAll(Button, Button.defaults, document.body); createAll(Button, Button.defaults, console.error); createAll(Button, Button.defaults, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof Button; + context.config?.preventDoubleClick; + }, }); createAll(CharacterCount); createAll(CharacterCount, CharacterCount.defaults); +createAll(CharacterCount, CharacterCount.defaults, null); +createAll(CharacterCount, CharacterCount.defaults, undefined); +createAll(CharacterCount, CharacterCount.defaults, document); createAll(CharacterCount, CharacterCount.defaults, document.body); createAll(CharacterCount, CharacterCount.defaults, console.error); createAll(CharacterCount, CharacterCount.defaults, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof CharacterCount; + context.config?.i18n; + context.config?.maxlength; + context.config?.maxwords; + context.config?.threshold; + }, }); createAll(Checkboxes); createAll(Checkboxes, undefined); +createAll(Checkboxes, undefined, null); +createAll(Checkboxes, undefined, undefined); +createAll(Checkboxes, undefined, document); createAll(Checkboxes, undefined, document.body); createAll(Checkboxes, undefined, console.error); createAll(Checkboxes, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof Checkboxes; + context.config === undefined; + }, }); createAll(Header); createAll(Header, undefined); +createAll(Header, undefined, null); +createAll(Header, undefined, undefined); +createAll(Header, undefined, document); createAll(Header, undefined, document.body); createAll(Header, undefined, console.error); createAll(Header, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof Header; + context.config === undefined; + }, }); createAll(ErrorSummary); createAll(ErrorSummary, ErrorSummary.defaults); +createAll(ErrorSummary, ErrorSummary.defaults, null); +createAll(ErrorSummary, ErrorSummary.defaults, undefined); +createAll(ErrorSummary, ErrorSummary.defaults, document); createAll(ErrorSummary, ErrorSummary.defaults, document.body); createAll(ErrorSummary, ErrorSummary.defaults, console.error); createAll(ErrorSummary, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof ErrorSummary; + context.config; + context.config?.disableAutoFocus; + }, }); createAll(ExitThisPage); createAll(ExitThisPage, ExitThisPage.defaults); +createAll(ExitThisPage, ExitThisPage.defaults, null); +createAll(ExitThisPage, ExitThisPage.defaults, undefined); +createAll(ExitThisPage, ExitThisPage.defaults, document); createAll(ExitThisPage, ExitThisPage.defaults, document.body); createAll(ExitThisPage, ExitThisPage.defaults, console.error); createAll(ExitThisPage, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof ExitThisPage; + context.config; + context.config?.i18n; + }, }); createAll(FileUpload); createAll(FileUpload, FileUpload.defaults); +createAll(FileUpload, FileUpload.defaults, null); +createAll(FileUpload, FileUpload.defaults, undefined); +createAll(FileUpload, FileUpload.defaults, document); createAll(FileUpload, FileUpload.defaults, document.body); createAll(FileUpload, FileUpload.defaults, console.error); createAll(FileUpload, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof FileUpload; + context.config; + context.config?.i18n; + }, }); createAll(NotificationBanner); createAll(NotificationBanner, NotificationBanner.defaults); +createAll(NotificationBanner, NotificationBanner.defaults, null); +createAll(NotificationBanner, NotificationBanner.defaults, undefined); +createAll(NotificationBanner, NotificationBanner.defaults, document); createAll(NotificationBanner, NotificationBanner.defaults, document.body); createAll(NotificationBanner, NotificationBanner.defaults, console.error); createAll(NotificationBanner, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof NotificationBanner; + context.config; + context.config?.disableAutoFocus; + }, }); createAll(PasswordInput); createAll(PasswordInput, PasswordInput.defaults); +createAll(PasswordInput, PasswordInput.defaults, null); +createAll(PasswordInput, PasswordInput.defaults, undefined); +createAll(PasswordInput, PasswordInput.defaults, document); createAll(PasswordInput, PasswordInput.defaults, document.body); createAll(PasswordInput, PasswordInput.defaults, console.error); createAll(PasswordInput, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof PasswordInput; + context.config; + context.config?.i18n; + }, }); createAll(Radios); createAll(Radios, undefined); +createAll(Radios, undefined, null); +createAll(Radios, undefined, undefined); +createAll(Radios, undefined, document); createAll(Radios, undefined, document.body); createAll(Radios, undefined, console.error); createAll(Radios, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof Radios; + context.config === undefined; + }, }); createAll(ServiceNavigation); createAll(ServiceNavigation, undefined); +createAll(ServiceNavigation, undefined, null); +createAll(ServiceNavigation, undefined, undefined); +createAll(ServiceNavigation, undefined, document); createAll(ServiceNavigation, undefined, document.body); createAll(ServiceNavigation, undefined, console.error); createAll(ServiceNavigation, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof ServiceNavigation; + context.config === undefined; + }, }); createAll(SkipLink); createAll(SkipLink, undefined); +createAll(SkipLink, undefined, null); +createAll(SkipLink, undefined, undefined); +createAll(SkipLink, undefined, document); createAll(SkipLink, undefined, document.body); createAll(SkipLink, undefined, console.error); createAll(SkipLink, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof SkipLink; + context.config === undefined; + }, }); createAll(Tabs); createAll(Tabs, undefined); +createAll(Tabs, undefined, null); +createAll(Tabs, undefined, undefined); +createAll(Tabs, undefined, document); createAll(Tabs, undefined, document.body); createAll(Tabs, undefined, console.error); createAll(Tabs, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof Tabs; + context.config === undefined; + }, }); createAll(MyComponent1); createAll(MyComponent1, undefined); +createAll(MyComponent1, undefined, null); +createAll(MyComponent1, undefined, undefined); +createAll(MyComponent1, undefined, document); createAll(MyComponent1, undefined, document.body); createAll(MyComponent1, undefined, console.error); createAll(MyComponent1, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof MyComponent1; + context.config === undefined; + }, }); createAll(MyComponent2); createAll(MyComponent2, undefined); +createAll(MyComponent2, undefined, null); +createAll(MyComponent2, undefined, undefined); +createAll(MyComponent2, undefined, document); createAll(MyComponent2, undefined, document.body); createAll(MyComponent2, undefined, console.error); createAll(MyComponent2, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof MyComponent2; + context.config === undefined; + }, }); createAll(MyComponent3); createAll(MyComponent3, { anOption: "overridden" }); +createAll(MyComponent3, { anOption: "overridden" }, null); +createAll(MyComponent3, { anOption: "overridden" }, undefined); +createAll(MyComponent3, { anOption: "overridden" }, document); createAll(MyComponent3, { anOption: "overridden" }, document.body); createAll(MyComponent3, { anOption: "overridden" }, console.error); createAll(MyComponent3, { anOption: "overridden" }, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof MyComponent3; + context.config; + context.config?.anOption; + context.config?.aNumberOption; + context.config?.aBooleanOption; + context.config?.anOptionWithNesting; + context.config?.anOptionWithNesting?.aNestedOption; + context.config?.anOptionWithNesting?.anotherLevel; + }, }); createAll(MyComponent3); createAll(MyComponent3, MyComponent3.defaults); +createAll(MyComponent3, MyComponent3.defaults, null); +createAll(MyComponent3, MyComponent3.defaults, undefined); +createAll(MyComponent3, MyComponent3.defaults, document); createAll(MyComponent3, MyComponent3.defaults, document.body); createAll(MyComponent3, MyComponent3.defaults, console.error); createAll(MyComponent3, MyComponent3.defaults, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof MyComponent3; + context.config; + context.config?.anOption; + context.config?.aNumberOption; + context.config?.aBooleanOption; + context.config?.anOptionWithNesting; + context.config?.anOptionWithNesting?.aNestedOption; + context.config?.anOptionWithNesting?.anotherLevel; + }, }); const config: Config = { @@ -291,6 +484,12 @@ const config: Config = { fileUpload: FileUpload.defaults, notificationBanner: NotificationBanner.defaults, passwordInput: PasswordInput.defaults, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.config; + }, }; const accordionConfig: Config[ConfigKey] = config.accordion; @@ -303,6 +502,19 @@ const notificationBannerConfig: Config[ConfigKey] = config.notificationBanner; const passwordInputConfig: Config[ConfigKey] = config.passwordInput; initAll(); +initAll(null); +initAll(undefined); +initAll(document); +initAll(document.body); +initAll({ + scope: document.body, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.config; + }, +}); initAll({ accordion: accordionConfig, button: buttonConfig, @@ -312,6 +524,11 @@ initAll({ fileUpload: fileUploadConfig, notificationBanner: notificationBannerConfig, passwordInput: passwordInputConfig, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.config; + }, }); initAll(config); diff --git a/types/govuk-frontend/govuk-frontend-tests.ts b/types/govuk-frontend/govuk-frontend-tests.ts index 0cbaa1b880ec15..92ae69007d922a 100644 --- a/types/govuk-frontend/govuk-frontend-tests.ts +++ b/types/govuk-frontend/govuk-frontend-tests.ts @@ -123,164 +123,357 @@ isSupported(); createAll(Accordion); createAll(Accordion, Accordion.defaults); +createAll(Accordion, Accordion.defaults, null); +createAll(Accordion, Accordion.defaults, undefined); +createAll(Accordion, Accordion.defaults, document); createAll(Accordion, Accordion.defaults, document.body); createAll(Accordion, Accordion.defaults, console.error); createAll(Accordion, Accordion.defaults, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof Button; + context.config?.i18n; + context.config?.rememberExpanded; + }, }); createAll(Button); createAll(Button, Button.defaults); +createAll(Button, Button.defaults, null); +createAll(Button, Button.defaults, undefined); +createAll(Button, Button.defaults, document); createAll(Button, Button.defaults, document.body); createAll(Button, Button.defaults, console.error); createAll(Button, Button.defaults, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof Button; + context.config?.preventDoubleClick; + }, }); createAll(CharacterCount); createAll(CharacterCount, CharacterCount.defaults); +createAll(CharacterCount, CharacterCount.defaults, null); +createAll(CharacterCount, CharacterCount.defaults, undefined); +createAll(CharacterCount, CharacterCount.defaults, document); createAll(CharacterCount, CharacterCount.defaults, document.body); createAll(CharacterCount, CharacterCount.defaults, console.error); createAll(CharacterCount, CharacterCount.defaults, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof CharacterCount; + context.config?.i18n; + context.config?.maxlength; + context.config?.maxwords; + context.config?.threshold; + }, }); createAll(Checkboxes); createAll(Checkboxes, undefined); +createAll(Checkboxes, undefined, null); +createAll(Checkboxes, undefined, undefined); +createAll(Checkboxes, undefined, document); createAll(Checkboxes, undefined, document.body); createAll(Checkboxes, undefined, console.error); createAll(Checkboxes, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof Checkboxes; + context.config === undefined; + }, }); createAll(Header); createAll(Header, undefined); +createAll(Header, undefined, null); +createAll(Header, undefined, undefined); +createAll(Header, undefined, document); createAll(Header, undefined, document.body); createAll(Header, undefined, console.error); createAll(Header, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof Header; + context.config === undefined; + }, }); createAll(ErrorSummary); createAll(ErrorSummary, ErrorSummary.defaults); +createAll(ErrorSummary, ErrorSummary.defaults, null); +createAll(ErrorSummary, ErrorSummary.defaults, undefined); +createAll(ErrorSummary, ErrorSummary.defaults, document); createAll(ErrorSummary, ErrorSummary.defaults, document.body); createAll(ErrorSummary, ErrorSummary.defaults, console.error); createAll(ErrorSummary, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof ErrorSummary; + context.config; + context.config?.disableAutoFocus; + }, }); createAll(ExitThisPage); createAll(ExitThisPage, ExitThisPage.defaults); +createAll(ExitThisPage, ExitThisPage.defaults, null); +createAll(ExitThisPage, ExitThisPage.defaults, undefined); +createAll(ExitThisPage, ExitThisPage.defaults, document); createAll(ExitThisPage, ExitThisPage.defaults, document.body); createAll(ExitThisPage, ExitThisPage.defaults, console.error); createAll(ExitThisPage, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof ExitThisPage; + context.config; + context.config?.i18n; + }, }); createAll(FileUpload); createAll(FileUpload, FileUpload.defaults); +createAll(FileUpload, FileUpload.defaults, null); +createAll(FileUpload, FileUpload.defaults, undefined); +createAll(FileUpload, FileUpload.defaults, document); createAll(FileUpload, FileUpload.defaults, document.body); createAll(FileUpload, FileUpload.defaults, console.error); createAll(FileUpload, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof FileUpload; + context.config; + context.config?.i18n; + }, }); createAll(NotificationBanner); createAll(NotificationBanner, NotificationBanner.defaults); +createAll(NotificationBanner, NotificationBanner.defaults, null); +createAll(NotificationBanner, NotificationBanner.defaults, undefined); +createAll(NotificationBanner, NotificationBanner.defaults, document); createAll(NotificationBanner, NotificationBanner.defaults, document.body); createAll(NotificationBanner, NotificationBanner.defaults, console.error); createAll(NotificationBanner, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof NotificationBanner; + context.config; + context.config?.disableAutoFocus; + }, }); createAll(PasswordInput); createAll(PasswordInput, PasswordInput.defaults); +createAll(PasswordInput, PasswordInput.defaults, null); +createAll(PasswordInput, PasswordInput.defaults, undefined); +createAll(PasswordInput, PasswordInput.defaults, document); createAll(PasswordInput, PasswordInput.defaults, document.body); createAll(PasswordInput, PasswordInput.defaults, console.error); createAll(PasswordInput, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof PasswordInput; + context.config; + context.config?.i18n; + }, }); createAll(Radios); createAll(Radios, undefined); +createAll(Radios, undefined, null); +createAll(Radios, undefined, undefined); +createAll(Radios, undefined, document); createAll(Radios, undefined, document.body); createAll(Radios, undefined, console.error); createAll(Radios, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof Radios; + context.config === undefined; + }, }); createAll(ServiceNavigation); createAll(ServiceNavigation, undefined); +createAll(ServiceNavigation, undefined, null); +createAll(ServiceNavigation, undefined, undefined); +createAll(ServiceNavigation, undefined, document); createAll(ServiceNavigation, undefined, document.body); createAll(ServiceNavigation, undefined, console.error); createAll(ServiceNavigation, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof ServiceNavigation; + context.config === undefined; + }, }); createAll(SkipLink); createAll(SkipLink, undefined); +createAll(SkipLink, undefined, null); +createAll(SkipLink, undefined, undefined); +createAll(SkipLink, undefined, document); createAll(SkipLink, undefined, document.body); createAll(SkipLink, undefined, console.error); createAll(SkipLink, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof SkipLink; + context.config === undefined; + }, }); createAll(Tabs); createAll(Tabs, undefined); +createAll(Tabs, undefined, null); +createAll(Tabs, undefined, undefined); +createAll(Tabs, undefined, document); createAll(Tabs, undefined, document.body); createAll(Tabs, undefined, console.error); createAll(Tabs, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof Tabs; + context.config === undefined; + }, }); createAll(MyComponent1); createAll(MyComponent1, undefined); +createAll(MyComponent1, undefined, null); +createAll(MyComponent1, undefined, undefined); +createAll(MyComponent1, undefined, document); createAll(MyComponent1, undefined, document.body); createAll(MyComponent1, undefined, console.error); createAll(MyComponent1, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof MyComponent1; + context.config === undefined; + }, }); createAll(MyComponent2); createAll(MyComponent2, undefined); +createAll(MyComponent2, undefined, null); +createAll(MyComponent2, undefined, undefined); +createAll(MyComponent2, undefined, document); createAll(MyComponent2, undefined, document.body); createAll(MyComponent2, undefined, console.error); createAll(MyComponent2, undefined, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.component instanceof MyComponent2; + context.config === undefined; + }, }); createAll(MyComponent3); createAll(MyComponent3, { anOption: "overridden" }); +createAll(MyComponent3, { anOption: "overridden" }, null); +createAll(MyComponent3, { anOption: "overridden" }, undefined); +createAll(MyComponent3, { anOption: "overridden" }, document); createAll(MyComponent3, { anOption: "overridden" }, document.body); createAll(MyComponent3, { anOption: "overridden" }, console.error); createAll(MyComponent3, { anOption: "overridden" }, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof MyComponent3; + context.config; + context.config?.anOption; + context.config?.aNumberOption; + context.config?.aBooleanOption; + context.config?.anOptionWithNesting; + context.config?.anOptionWithNesting?.aNestedOption; + context.config?.anOptionWithNesting?.anotherLevel; + }, }); createAll(MyComponent3); createAll(MyComponent3, MyComponent3.defaults); +createAll(MyComponent3, MyComponent3.defaults, null); +createAll(MyComponent3, MyComponent3.defaults, undefined); +createAll(MyComponent3, MyComponent3.defaults, document); createAll(MyComponent3, MyComponent3.defaults, document.body); createAll(MyComponent3, MyComponent3.defaults, console.error); createAll(MyComponent3, MyComponent3.defaults, { scope: document.body, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.defaults; + context.component?.moduleName; + context.component instanceof MyComponent3; + context.config; + context.config?.anOption; + context.config?.aNumberOption; + context.config?.aBooleanOption; + context.config?.anOptionWithNesting; + context.config?.anOptionWithNesting?.aNestedOption; + context.config?.anOptionWithNesting?.anotherLevel; + }, }); const config: Config = { @@ -292,6 +485,12 @@ const config: Config = { fileUpload: FileUpload.defaults, notificationBanner: NotificationBanner.defaults, passwordInput: PasswordInput.defaults, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.config; + }, }; const accordionConfig: Config[ConfigKey] = config.accordion; @@ -304,6 +503,19 @@ const notificationBannerConfig: Config[ConfigKey] = config.notificationBanner; const passwordInputConfig: Config[ConfigKey] = config.passwordInput; initAll(); +initAll(null); +initAll(undefined); +initAll(document); +initAll(document.body); +initAll({ + scope: document.body, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.config; + }, +}); initAll({ accordion: accordionConfig, button: buttonConfig, @@ -313,6 +525,11 @@ initAll({ fileUpload: fileUploadConfig, notificationBanner: notificationBannerConfig, passwordInput: passwordInputConfig, - onError: console.error, + onError(error, context) { + error instanceof Error; + context.element; + context.component?.moduleName; + context.config; + }, }); initAll(config); diff --git a/types/govuk-frontend/package.json b/types/govuk-frontend/package.json index 81087367249939..4ac4016056454a 100644 --- a/types/govuk-frontend/package.json +++ b/types/govuk-frontend/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@types/govuk-frontend", - "version": "5.9.9999", + "version": "5.11.9999", "projects": [ "https://github.com/alphagov/govuk-frontend", "https://frontend.design-system.service.gov.uk" @@ -20,6 +20,10 @@ "name": "Colin Rotherham", "githubUsername": "colinrotherham" }, + { + "name": "Paul Robert Lloyd", + "githubUsername": "paulrobertlloyd" + }, { "name": "Romaric Pascal", "githubUsername": "romaricpascal" From 0ce90e6c5b7e8e806f3006873193a3721eed995a Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Fri, 12 Sep 2025 21:03:18 +0200 Subject: [PATCH 10/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73531=20[chr?= =?UTF-8?q?ome]=20update=20fontSettings=20namespace=20by=20@erwanjugand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 428 ++++++++++++++++++++++++++----------- types/chrome/test/index.ts | 334 ++++++++++++++++++++++++++--- 2 files changed, 602 insertions(+), 160 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index 69a7701d28512b..e5ea6bef55742a 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -5348,212 +5348,382 @@ declare namespace chrome { fontId: string; } - export interface DefaultFontSizeDetails { - /** The font size in pixels. */ - pixelSize: number; - } - - export interface FontDetails { - /** The generic font family for the font. */ - genericFamily: - | "cursive" - | "fantasy" - | "fixed" - | "sansserif" - | "serif" - | "standard"; - /** Optional. The script for the font. If omitted, the global script font setting is affected. */ - script?: string | undefined; + /** A CSS generic font family. */ + export enum GenericFamily { + STANDARD = "standard", + SANSSERIF = "sansserif", + SERIF = "serif", + FIXED = "fixed", + CURSIVE = "cursive", + FANTASY = "fantasy", + MATH = "math", + } + + export enum LevelOfControl { + /** Cannot be controlled by any extension */ + NOT_CONTROLLABLE = "not_controllable", + /** Controlled by extensions with higher precedence */ + CONTROLLED_BY_OTHER_EXTENSIONS = "controlled_by_other_extensions", + /** Can be controlled by this extension */ + CONTROLLABLE_BY_THIS_EXTENSION = "controllable_by_this_extension", + /** Controlled by this extension */ + CONTROLLED_BY_THIS_EXTENSION = "controlled_by_this_extension", + } + + /** An ISO 15924 script code. The default, or global, script is represented by script code "Zyyy". */ + export enum ScriptCode { + AFAK = "Afak", + ARAB = "Arab", + ARMI = "Armi", + ARMN = "Armn", + AVST = "Avst", + BALI = "Bali", + BAMU = "Bamu", + BASS = "Bass", + BATK = "Batk", + BENG = "Beng", + BLIS = "Blis", + BOPO = "Bopo", + BRAH = "Brah", + BRAI = "Brai", + BUGI = "Bugi", + BUHD = "Buhd", + CAKM = "Cakm", + CANS = "Cans", + CARI = "Cari", + CHAM = "Cham", + CHER = "Cher", + CIRT = "Cirt", + COPT = "Copt", + CPRT = "Cprt", + CYRL = "Cyrl", + CYRS = "Cyrs", + DEVA = "Deva", + DSRT = "Dsrt", + DUPL = "Dupl", + EGYD = "Egyd", + EGYH = "Egyh", + EGYP = "Egyp", + ELBA = "Elba", + ETHI = "Ethi", + GEOK = "Geok", + GEOR = "Geor", + GLAG = "Glag", + GOTH = "Goth", + GRAN = "Gran", + GREK = "Grek", + GUJR = "Gujr", + GURU = "Guru", + HANG = "Hang", + HANI = "Hani", + HANO = "Hano", + HANS = "Hans", + HANT = "Hant", + HEBR = "Hebr", + HLUW = "Hluw", + HMNG = "Hmng", + HUNG = "Hung", + INDS = "Inds", + ITAL = "Ital", + JAVA = "Java", + JPAN = "Jpan", + JURC = "Jurc", + KALI = "Kali", + KHAR = "Khar", + KHMR = "Khmr", + KHOJ = "Khoj", + KNDA = "Knda", + KPEL = "Kpel", + KTHI = "Kthi", + LANA = "Lana", + LAOO = "Laoo", + LATF = "Latf", + LATG = "Latg", + LATN = "Latn", + LEPC = "Lepc", + LIMB = "Limb", + LINA = "Lina", + LINB = "Linb", + LISU = "Lisu", + LOMA = "Loma", + LYCI = "Lyci", + LYDI = "Lydi", + MAND = "Mand", + MANI = "Mani", + MAYA = "Maya", + MEND = "Mend", + MERC = "Merc", + MERO = "Mero", + MLYM = "Mlym", + MONG = "Mong", + MOON = "Moon", + MROO = "Mroo", + MTEI = "Mtei", + MYMR = "Mymr", + NARB = "Narb", + NBAT = "Nbat", + NKGB = "Nkgb", + NKOO = "Nkoo", + NSHU = "Nshu", + OGAM = "Ogam", + OLCK = "Olck", + ORKH = "Orkh", + ORYA = "Orya", + OSMA = "Osma", + PALM = "Palm", + PERM = "Perm", + PHAG = "Phag", + PHLI = "Phli", + PHLP = "Phlp", + PHLV = "Phlv", + PHNX = "Phnx", + PLRD = "Plrd", + PRTI = "Prti", + RJNG = "Rjng", + RORO = "Roro", + RUNR = "Runr", + SAMR = "Samr", + SARA = "Sara", + SARB = "Sarb", + SAUR = "Saur", + SGNW = "Sgnw", + SHAW = "Shaw", + SHRD = "Shrd", + SIND = "Sind", + SINH = "Sinh", + SORA = "Sora", + SUND = "Sund", + SYLO = "Sylo", + SYRC = "Syrc", + SYRE = "Syre", + SYRJ = "Syrj", + SYRN = "Syrn", + TAGB = "Tagb", + TAKR = "Takr", + TALE = "Tale", + TALU = "Talu", + TAML = "Taml", + TANG = "Tang", + TAVT = "Tavt", + TELU = "Telu", + TENG = "Teng", + TFNG = "Tfng", + TGLG = "Tglg", + THAA = "Thaa", + THAI = "Thai", + TIBT = "Tibt", + TIRH = "Tirh", + UGAR = "Ugar", + VAII = "Vaii", + VISP = "Visp", + WARA = "Wara", + WOLE = "Wole", + XPEO = "Xpeo", + XSUX = "Xsux", + YIII = "Yiii", + ZMTH = "Zmth", + ZSYM = "Zsym", + ZYYY = "Zyyy", + } + + export interface ClearFontDetails { + /** The generic font family for which the font should be cleared. */ + genericFamily: `${GenericFamily}`; + /** The script for which the font should be cleared. If omitted, the global script font setting is cleared. */ + script?: `${ScriptCode}` | undefined; + } + + export interface GetFontDetails { + /** The generic font family for which the font should be retrieved. */ + genericFamily: `${GenericFamily}`; + /** The script for which the font should be retrieved. If omitted, the font setting for the global script (script code "Zyyy") is retrieved. */ + script?: `${ScriptCode}` | undefined; + } + + export interface SetFontDetails { + /** The font ID. The empty string means to fallback to the global script font setting. */ + fontId: string; + /** The generic font family for which the font should be set. */ + genericFamily: `${GenericFamily}`; + /** The script code which the font should be set. If omitted, the font setting for the global script (script code "Zyyy") is set. */ + script?: `${ScriptCode}` | undefined; } - export interface FullFontDetails { + export interface FontChangedResult { /** The generic font family for which the font setting has changed. */ - genericFamily: string; + genericFamily: `${GenericFamily}`; /** The level of control this extension has over the setting. */ - levelOfControl: string; + levelOfControl: `${LevelOfControl}`; /** Optional. The script code for which the font setting has changed. */ - script?: string | undefined; - /** The font ID. See the description in getFont. */ + script?: `${ScriptCode}`; + /** The font ID. See the description in {@link getFont}. */ fontId: string; } - export interface FontDetailsResult { + export interface FontResult { /** The level of control this extension has over the setting. */ - levelOfControl: string; - /** The font ID. Rather than the literal font ID preference value, this may be the ID of the font that the system resolves the preference value to. So, fontId can differ from the font passed to setFont, if, for example, the font is not available on the system. The empty string signifies fallback to the global script font setting. */ + levelOfControl: `${LevelOfControl}`; + /** The font ID. Rather than the literal font ID preference value, this may be the ID of the font that the system resolves the preference value to. So, `fontId` can differ from the font passed to {@link setFont}, if, for example, the font is not available on the system. The empty string signifies fallback to the global script font setting. */ fontId: string; } - export interface FontSizeDetails { + export interface FontSizeResult { /** The font size in pixels. */ pixelSize: number; /** The level of control this extension has over the setting. */ - levelOfControl: string; + levelOfControl: `${LevelOfControl}`; } - export interface SetFontSizeDetails { + export interface FontSizeDetails { /** The font size in pixels. */ pixelSize: number; } - export interface SetFontDetails extends FontDetails { - /** The font ID. The empty string means to fallback to the global script font setting. */ - fontId: string; - } - - export interface DefaultFixedFontSizeChangedEvent - extends chrome.events.Event<(details: FontSizeDetails) => void> - {} - - export interface DefaultFontSizeChangedEvent extends chrome.events.Event<(details: FontSizeDetails) => void> {} - - export interface MinimumFontSizeChangedEvent extends chrome.events.Event<(details: FontSizeDetails) => void> {} - - export interface FontChangedEvent extends chrome.events.Event<(details: FullFontDetails) => void> {} - /** * Sets the default font size. - * @return The `setDefaultFontSize` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function setDefaultFontSize(details: DefaultFontSizeDetails): Promise; - /** - * Sets the default font size. - */ - export function setDefaultFontSize(details: DefaultFontSizeDetails, callback: () => void): void; - /** - * Gets the font for a given script and generic font family. - * @return The `getFont` method provides its result via callback or returned as a `Promise` (MV3 only). + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ - export function getFont(details: FontDetails): Promise; + export function setDefaultFontSize(details: FontSizeDetails): Promise; + export function setDefaultFontSize(details: FontSizeDetails, callback: () => void): void; + /** * Gets the font for a given script and generic font family. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ - export function getFont(details: FontDetails, callback: (details: FontDetailsResult) => void): void; - /** - * Gets the default font size. - * @param details This parameter is currently unused. - * @return The `getDefaultFontSize` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function getDefaultFontSize(details?: unknown): Promise; + export function getFont(details: GetFontDetails): Promise; + export function getFont(details: GetFontDetails, callback: (details: FontResult) => void): void; + /** * Gets the default font size. * @param details This parameter is currently unused. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ - export function getDefaultFontSize(callback: (options: FontSizeDetails) => void): void; - export function getDefaultFontSize(details: unknown, callback: (options: FontSizeDetails) => void): void; - /** - * Gets the minimum font size. - * @param details This parameter is currently unused. - * @return The `getMinimumFontSize` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function getMinimumFontSize(details?: unknown): Promise; + export function getDefaultFontSize(details?: { [key: string]: unknown }): Promise; + export function getDefaultFontSize(callback: (options: FontSizeResult) => void): void; + export function getDefaultFontSize( + details: { [key: string]: unknown } | undefined, + callback: (options: FontSizeResult) => void, + ): void; + /** * Gets the minimum font size. * @param details This parameter is currently unused. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ - export function getMinimumFontSize(callback: (options: FontSizeDetails) => void): void; - export function getMinimumFontSize(details: unknown, callback: (options: FontSizeDetails) => void): void; - /** - * Sets the minimum font size. - * @return The `setMinimumFontSize` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function setMinimumFontSize(details: SetFontSizeDetails): Promise; + export function getMinimumFontSize(details?: { [key: string]: unknown }): Promise; + export function getMinimumFontSize(callback: (options: FontSizeResult) => void): void; + export function getMinimumFontSize( + details: { [key: string]: unknown } | undefined, + callback: (options: FontSizeResult) => void, + ): void; + /** * Sets the minimum font size. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ - export function setMinimumFontSize(details: SetFontSizeDetails, callback: () => void): void; - /** - * Gets the default size for fixed width fonts. - * @param details This parameter is currently unused. - * @return The `getDefaultFixedFontSize` method provides its result via callback or returned as a `Promise` (MV3 only). - */ - export function getDefaultFixedFontSize(details?: unknown): Promise; + export function setMinimumFontSize(details: FontSizeDetails): Promise; + export function setMinimumFontSize(details: FontSizeDetails, callback: () => void): void; + /** * Gets the default size for fixed width fonts. * @param details This parameter is currently unused. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ - export function getDefaultFixedFontSize(callback: (details: FontSizeDetails) => void): void; - export function getDefaultFixedFontSize(details: unknown, callback: (details: FontSizeDetails) => void): void; - /** - * Clears the default font size set by this extension, if any. - * @param details This parameter is currently unused. - * @return The `clearDefaultFontSize` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function clearDefaultFontSize(details?: unknown): Promise; + export function getDefaultFixedFontSize(details?: { [key: string]: unknown }): Promise; + export function getDefaultFixedFontSize(callback: (details: FontSizeResult) => void): void; + export function getDefaultFixedFontSize( + details: { [key: string]: unknown } | undefined, + callback: (details: FontSizeResult) => void, + ): void; + /** * Clears the default font size set by this extension, if any. * @param details This parameter is currently unused. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ + export function clearDefaultFontSize(details?: { [key: string]: unknown }): Promise; export function clearDefaultFontSize(callback: () => void): void; - export function clearDefaultFontSize(details: unknown, callback: () => void): void; - /** - * Sets the default size for fixed width fonts. - * @return The `setDefaultFixedFontSize` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function setDefaultFixedFontSize(details: SetFontSizeDetails): Promise; + export function clearDefaultFontSize( + details: { [key: string]: unknown } | undefined, + callback: () => void, + ): void; + /** * Sets the default size for fixed width fonts. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ - export function setDefaultFixedFontSize(details: SetFontSizeDetails, callback: () => void): void; - /** - * Clears the font set by this extension, if any. - * @return The `clearFont` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function clearFont(details: FontDetails): Promise; + export function setDefaultFixedFontSize(details: FontSizeDetails): Promise; + export function setDefaultFixedFontSize(details: FontSizeDetails, callback: () => void): void; + /** * Clears the font set by this extension, if any. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ - export function clearFont(details: FontDetails, callback: () => void): void; + export function clearFont(details: ClearFontDetails): Promise; + export function clearFont(details: ClearFontDetails, callback: () => void): void; + /** * Sets the font for a given script and generic font family. - * @return The `setFont` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ export function setFont(details: SetFontDetails): Promise; - /** - * Sets the font for a given script and generic font family. - */ export function setFont(details: SetFontDetails, callback: () => void): void; + /** * Clears the minimum font size set by this extension, if any. * @param details This parameter is currently unused. - * @return The `clearMinimumFontSize` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function clearMinimumFontSize(details?: unknown): Promise; - /** - * Clears the minimum font size set by this extension, if any. - * @param details This parameter is currently unused. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ + export function clearMinimumFontSize(details?: { [key: string]: unknown }): Promise; export function clearMinimumFontSize(callback: () => void): void; - export function clearMinimumFontSize(details: unknown, callback: () => void): void; + export function clearMinimumFontSize( + details: { [key: string]: unknown } | undefined, + callback: () => void, + ): void; + /** * Gets a list of fonts on the system. - * @return The `getFontList` method provides its result via callback or returned as a `Promise` (MV3 only). + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ export function getFontList(): Promise; - /** - * Gets a list of fonts on the system. - */ export function getFontList(callback: (results: FontName[]) => void): void; + /** * Clears the default fixed font size set by this extension, if any. * @param details This parameter is currently unused. - * @return The `clearDefaultFixedFontSize` method provides its result via callback or returned as a `Promise` (MV3 only). It has no parameters. - */ - export function clearDefaultFixedFontSize(details: unknown): Promise; - /** - * Clears the default fixed font size set by this extension, if any. - * @param details This parameter is currently unused. + * + * Can return its result via Promise in Manifest V3 or later since Chrome 96. */ - export function clearDefaultFixedFontSize(details: unknown, callback: () => void): void; + export function clearDefaultFixedFontSize(details?: { [key: string]: unknown }): Promise; + export function clearDefaultFixedFontSize(callback: () => void): void; + export function clearDefaultFixedFontSize( + details: { [key: string]: unknown } | undefined, + callback: () => void, + ): void; /** Fired when the default fixed font size setting changes. */ - export var onDefaultFixedFontSizeChanged: DefaultFixedFontSizeChangedEvent; + export const onDefaultFixedFontSizeChanged: events.Event<(details: FontSizeResult) => void>; + /** Fired when the default font size setting changes. */ - export var onDefaultFontSizeChanged: DefaultFontSizeChangedEvent; + export const onDefaultFontSizeChanged: events.Event<(details: FontSizeResult) => void>; + /** Fired when the minimum font size setting changes. */ - export var onMinimumFontSizeChanged: MinimumFontSizeChangedEvent; + export const onMinimumFontSizeChanged: events.Event<(details: FontSizeResult) => void>; + /** Fired when a font setting changes. */ - export var onFontChanged: FontChangedEvent; + export const onFontChanged: events.Event<(details: FontChangedResult) => void>; } //////////////////// diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index e0d5b6395fc567..6465127f8e3d57 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -4447,42 +4447,314 @@ function testExtension() { }); } -// https://developer.chrome.com/docs/extensions/reference/fontSettings +// https://developer.chrome.com/docs/extensions/reference/api/fontSettings function testFontSettings() { - chrome.fontSettings.setDefaultFontSize({ pixelSize: 1 }, () => {}); + chrome.fontSettings.GenericFamily.CURSIVE === "cursive"; + chrome.fontSettings.GenericFamily.FANTASY === "fantasy"; + chrome.fontSettings.GenericFamily.FIXED === "fixed"; + chrome.fontSettings.GenericFamily.MATH === "math"; + chrome.fontSettings.GenericFamily.SANSSERIF === "sansserif"; + chrome.fontSettings.GenericFamily.SERIF === "serif"; + chrome.fontSettings.GenericFamily.STANDARD === "standard"; + + chrome.fontSettings.LevelOfControl.CONTROLLABLE_BY_THIS_EXTENSION === "controllable_by_this_extension"; + chrome.fontSettings.LevelOfControl.CONTROLLED_BY_OTHER_EXTENSIONS === "controlled_by_other_extensions"; + chrome.fontSettings.LevelOfControl.CONTROLLED_BY_THIS_EXTENSION === "controlled_by_this_extension"; + chrome.fontSettings.LevelOfControl.NOT_CONTROLLABLE === "not_controllable"; + + chrome.fontSettings.ScriptCode.AFAK === "Afak"; + chrome.fontSettings.ScriptCode.ARAB === "Arab"; + chrome.fontSettings.ScriptCode.ARMI === "Armi"; + chrome.fontSettings.ScriptCode.ARMN === "Armn"; + chrome.fontSettings.ScriptCode.AVST === "Avst"; + chrome.fontSettings.ScriptCode.BALI === "Bali"; + chrome.fontSettings.ScriptCode.BAMU === "Bamu"; + chrome.fontSettings.ScriptCode.BASS === "Bass"; + chrome.fontSettings.ScriptCode.BATK === "Batk"; + chrome.fontSettings.ScriptCode.BENG === "Beng"; + chrome.fontSettings.ScriptCode.BLIS === "Blis"; + chrome.fontSettings.ScriptCode.BOPO === "Bopo"; + chrome.fontSettings.ScriptCode.BRAH === "Brah"; + chrome.fontSettings.ScriptCode.BRAI === "Brai"; + chrome.fontSettings.ScriptCode.BUGI === "Bugi"; + chrome.fontSettings.ScriptCode.BUHD === "Buhd"; + chrome.fontSettings.ScriptCode.CAKM === "Cakm"; + chrome.fontSettings.ScriptCode.CANS === "Cans"; + chrome.fontSettings.ScriptCode.CARI === "Cari"; + chrome.fontSettings.ScriptCode.CHAM === "Cham"; + chrome.fontSettings.ScriptCode.CHER === "Cher"; + chrome.fontSettings.ScriptCode.CIRT === "Cirt"; + chrome.fontSettings.ScriptCode.COPT === "Copt"; + chrome.fontSettings.ScriptCode.CPRT === "Cprt"; + chrome.fontSettings.ScriptCode.CYRL === "Cyrl"; + chrome.fontSettings.ScriptCode.CYRS === "Cyrs"; + chrome.fontSettings.ScriptCode.DEVA === "Deva"; + chrome.fontSettings.ScriptCode.DSRT === "Dsrt"; + chrome.fontSettings.ScriptCode.DUPL === "Dupl"; + chrome.fontSettings.ScriptCode.EGYD === "Egyd"; + chrome.fontSettings.ScriptCode.EGYH === "Egyh"; + chrome.fontSettings.ScriptCode.EGYP === "Egyp"; + chrome.fontSettings.ScriptCode.ELBA === "Elba"; + chrome.fontSettings.ScriptCode.ETHI === "Ethi"; + chrome.fontSettings.ScriptCode.GEOK === "Geok"; + chrome.fontSettings.ScriptCode.GEOR === "Geor"; + chrome.fontSettings.ScriptCode.GLAG === "Glag"; + chrome.fontSettings.ScriptCode.GOTH === "Goth"; + chrome.fontSettings.ScriptCode.GRAN === "Gran"; + chrome.fontSettings.ScriptCode.GREK === "Grek"; + chrome.fontSettings.ScriptCode.GUJR === "Gujr"; + chrome.fontSettings.ScriptCode.GURU === "Guru"; + chrome.fontSettings.ScriptCode.HANG === "Hang"; + chrome.fontSettings.ScriptCode.HANI === "Hani"; + chrome.fontSettings.ScriptCode.HANO === "Hano"; + chrome.fontSettings.ScriptCode.HANS === "Hans"; + chrome.fontSettings.ScriptCode.HANT === "Hant"; + chrome.fontSettings.ScriptCode.HEBR === "Hebr"; + chrome.fontSettings.ScriptCode.HLUW === "Hluw"; + chrome.fontSettings.ScriptCode.HMNG === "Hmng"; + chrome.fontSettings.ScriptCode.HUNG === "Hung"; + chrome.fontSettings.ScriptCode.INDS === "Inds"; + chrome.fontSettings.ScriptCode.ITAL === "Ital"; + chrome.fontSettings.ScriptCode.JAVA === "Java"; + chrome.fontSettings.ScriptCode.JPAN === "Jpan"; + chrome.fontSettings.ScriptCode.JURC === "Jurc"; + chrome.fontSettings.ScriptCode.KALI === "Kali"; + chrome.fontSettings.ScriptCode.KHAR === "Khar"; + chrome.fontSettings.ScriptCode.KHMR === "Khmr"; + chrome.fontSettings.ScriptCode.KHOJ === "Khoj"; + chrome.fontSettings.ScriptCode.KNDA === "Knda"; + chrome.fontSettings.ScriptCode.KPEL === "Kpel"; + chrome.fontSettings.ScriptCode.KTHI === "Kthi"; + chrome.fontSettings.ScriptCode.LANA === "Lana"; + chrome.fontSettings.ScriptCode.LAOO === "Laoo"; + chrome.fontSettings.ScriptCode.LATF === "Latf"; + chrome.fontSettings.ScriptCode.LATG === "Latg"; + chrome.fontSettings.ScriptCode.LATN === "Latn"; + chrome.fontSettings.ScriptCode.LEPC === "Lepc"; + chrome.fontSettings.ScriptCode.LIMB === "Limb"; + chrome.fontSettings.ScriptCode.LINA === "Lina"; + chrome.fontSettings.ScriptCode.LINB === "Linb"; + chrome.fontSettings.ScriptCode.LISU === "Lisu"; + chrome.fontSettings.ScriptCode.LOMA === "Loma"; + chrome.fontSettings.ScriptCode.LYCI === "Lyci"; + chrome.fontSettings.ScriptCode.LYDI === "Lydi"; + chrome.fontSettings.ScriptCode.MAND === "Mand"; + chrome.fontSettings.ScriptCode.MANI === "Mani"; + chrome.fontSettings.ScriptCode.MAYA === "Maya"; + chrome.fontSettings.ScriptCode.MEND === "Mend"; + chrome.fontSettings.ScriptCode.MERC === "Merc"; + chrome.fontSettings.ScriptCode.MERO === "Mero"; + chrome.fontSettings.ScriptCode.MLYM === "Mlym"; + chrome.fontSettings.ScriptCode.MONG === "Mong"; + chrome.fontSettings.ScriptCode.MOON === "Moon"; + chrome.fontSettings.ScriptCode.MROO === "Mroo"; + chrome.fontSettings.ScriptCode.MTEI === "Mtei"; + chrome.fontSettings.ScriptCode.MYMR === "Mymr"; + chrome.fontSettings.ScriptCode.NARB === "Narb"; + chrome.fontSettings.ScriptCode.NBAT === "Nbat"; + chrome.fontSettings.ScriptCode.NKGB === "Nkgb"; + chrome.fontSettings.ScriptCode.NKOO === "Nkoo"; + chrome.fontSettings.ScriptCode.NSHU === "Nshu"; + chrome.fontSettings.ScriptCode.OGAM === "Ogam"; + chrome.fontSettings.ScriptCode.OLCK === "Olck"; + chrome.fontSettings.ScriptCode.ORKH === "Orkh"; + chrome.fontSettings.ScriptCode.ORYA === "Orya"; + chrome.fontSettings.ScriptCode.OSMA === "Osma"; + chrome.fontSettings.ScriptCode.PALM === "Palm"; + chrome.fontSettings.ScriptCode.PERM === "Perm"; + chrome.fontSettings.ScriptCode.PHAG === "Phag"; + chrome.fontSettings.ScriptCode.PHLI === "Phli"; + chrome.fontSettings.ScriptCode.PHLP === "Phlp"; + chrome.fontSettings.ScriptCode.PHLV === "Phlv"; + chrome.fontSettings.ScriptCode.PHNX === "Phnx"; + chrome.fontSettings.ScriptCode.PLRD === "Plrd"; + chrome.fontSettings.ScriptCode.PRTI === "Prti"; + chrome.fontSettings.ScriptCode.RJNG === "Rjng"; + chrome.fontSettings.ScriptCode.RORO === "Roro"; + chrome.fontSettings.ScriptCode.RUNR === "Runr"; + chrome.fontSettings.ScriptCode.SAMR === "Samr"; + chrome.fontSettings.ScriptCode.SARA === "Sara"; + chrome.fontSettings.ScriptCode.SARB === "Sarb"; + chrome.fontSettings.ScriptCode.SAUR === "Saur"; + chrome.fontSettings.ScriptCode.SGNW === "Sgnw"; + chrome.fontSettings.ScriptCode.SHAW === "Shaw"; + chrome.fontSettings.ScriptCode.SHRD === "Shrd"; + chrome.fontSettings.ScriptCode.SIND === "Sind"; + chrome.fontSettings.ScriptCode.SINH === "Sinh"; + chrome.fontSettings.ScriptCode.SORA === "Sora"; + chrome.fontSettings.ScriptCode.SUND === "Sund"; + chrome.fontSettings.ScriptCode.SYLO === "Sylo"; + chrome.fontSettings.ScriptCode.SYRC === "Syrc"; + chrome.fontSettings.ScriptCode.SYRE === "Syre"; + chrome.fontSettings.ScriptCode.SYRJ === "Syrj"; + chrome.fontSettings.ScriptCode.SYRN === "Syrn"; + chrome.fontSettings.ScriptCode.TAGB === "Tagb"; + chrome.fontSettings.ScriptCode.TAKR === "Takr"; + chrome.fontSettings.ScriptCode.TALE === "Tale"; + chrome.fontSettings.ScriptCode.TALU === "Talu"; + chrome.fontSettings.ScriptCode.TAML === "Taml"; + chrome.fontSettings.ScriptCode.TANG === "Tang"; + chrome.fontSettings.ScriptCode.TAVT === "Tavt"; + chrome.fontSettings.ScriptCode.TELU === "Telu"; + chrome.fontSettings.ScriptCode.TENG === "Teng"; + chrome.fontSettings.ScriptCode.TFNG === "Tfng"; + chrome.fontSettings.ScriptCode.TGLG === "Tglg"; + chrome.fontSettings.ScriptCode.THAA === "Thaa"; + chrome.fontSettings.ScriptCode.THAI === "Thai"; + chrome.fontSettings.ScriptCode.TIBT === "Tibt"; + chrome.fontSettings.ScriptCode.TIRH === "Tirh"; + chrome.fontSettings.ScriptCode.UGAR === "Ugar"; + chrome.fontSettings.ScriptCode.VAII === "Vaii"; + chrome.fontSettings.ScriptCode.VISP === "Visp"; + chrome.fontSettings.ScriptCode.WARA === "Wara"; + chrome.fontSettings.ScriptCode.WOLE === "Wole"; + chrome.fontSettings.ScriptCode.XPEO === "Xpeo"; + chrome.fontSettings.ScriptCode.XSUX === "Xsux"; + chrome.fontSettings.ScriptCode.YIII === "Yiii"; + chrome.fontSettings.ScriptCode.ZMTH === "Zmth"; + chrome.fontSettings.ScriptCode.ZSYM === "Zsym"; + chrome.fontSettings.ScriptCode.ZYYY === "Zyyy"; + + chrome.fontSettings.clearDefaultFixedFontSize(); // Expected Promise + chrome.fontSettings.clearDefaultFontSize(() => void 0); // Expected void + chrome.fontSettings.clearDefaultFixedFontSize(); // Expected Promise + chrome.fontSettings.clearDefaultFixedFontSize({}, () => void 0); // Expected void + // @ts-expect-error + chrome.fontSettings.clearDefaultFixedFontSize({}, () => {}).then(() => {}); + + chrome.fontSettings.clearDefaultFontSize(); // Expected Promise + chrome.fontSettings.clearDefaultFontSize(() => void 0); // Expected void + chrome.fontSettings.clearDefaultFontSize({}); // Expected Promise + chrome.fontSettings.clearDefaultFontSize({}, () => void 0); // Expected void + // @ts-expect-error + chrome.fontSettings.clearDefaultFontSize({}, () => {}).then(() => {}); + + const clearFontDetails: chrome.fontSettings.ClearFontDetails = { + genericFamily: "standard", + script: "Afak", + }; + + chrome.fontSettings.clearFont(clearFontDetails); // Expected Promise + chrome.fontSettings.clearFont(clearFontDetails, () => void 0); // Expected void + // @ts-expect-error + chrome.fontSettings.clearFont(clearFontDetails, () => {}).then(() => {}); + + chrome.fontSettings.clearMinimumFontSize(); // Expected Promise + chrome.fontSettings.clearMinimumFontSize(() => void 0); // Expected void + chrome.fontSettings.clearMinimumFontSize({}); // Expected Promise + chrome.fontSettings.clearMinimumFontSize({}, () => void 0); // Expected void + // @ts-expect-error + chrome.fontSettings.clearMinimumFontSize(() => {}).then(() => {}); + + chrome.fontSettings.getDefaultFixedFontSize(); // Expected Promise + chrome.fontSettings.getDefaultFixedFontSize((details) => { // Expected void + details.pixelSize; // Expected number + details.levelOfControl; // Expected LevelOfControl + }); + chrome.fontSettings.getDefaultFixedFontSize({}); // Expected Promise + chrome.fontSettings.getDefaultFixedFontSize({}, (details) => { // Expected void + details.pixelSize; // Expected number + details.levelOfControl; // Expected LevelOfControl + }); + // @ts-expect-error + chrome.fontSettings.getDefaultFixedFontSize(() => {}).then(() => {}); + + chrome.fontSettings.getDefaultFontSize(); // Expected Promise + chrome.fontSettings.getDefaultFontSize((details) => { // Expected void + details.pixelSize; // Expected number + details.levelOfControl; // Expected LevelOfControl + }); + chrome.fontSettings.getDefaultFontSize({}); // Expected Promise + chrome.fontSettings.getDefaultFontSize({}, (details) => { // Expected void + details.pixelSize; // Expected number + details.levelOfControl; // Expected LevelOfControl + }); + // @ts-expect-error + chrome.fontSettings.getDefaultFontSize({}, () => {}).then(() => {}); + + const getFontDetails: chrome.fontSettings.GetFontDetails = { + genericFamily: "standard", + script: "Afak", + }; + + chrome.fontSettings.getFont(getFontDetails); // Expected Promise + chrome.fontSettings.getFont(getFontDetails, (details) => { // Expected void + details.fontId; // Expected string + details.levelOfControl; // Expected LevelOfControl + }); // @ts-expect-error chrome.fontSettings.getFont({}, (details) => {}); + + chrome.fontSettings.getFontList(); // Expected Promise + chrome.fontSettings.getFontList(([result]) => { // Expected void + result.fontId; // Expected string + result.displayName; // Expected string + }); + + chrome.fontSettings.getMinimumFontSize(); // Expected Promise + chrome.fontSettings.getMinimumFontSize((details) => { // Expected void + details.pixelSize; // Expected number + details.levelOfControl; // Expected LevelOfControl + }); + chrome.fontSettings.getMinimumFontSize({}); // Expected Promise + chrome.fontSettings.getMinimumFontSize({}, (details) => { // Expected void + details.pixelSize; // Expected number + details.levelOfControl; // Expected LevelOfControl + }); // @ts-expect-error - chrome.fontSettings.getFont({ genericFamily: "" }, (details) => {}); - chrome.fontSettings.getFont({ genericFamily: "cursive" }, (details) => {}); - chrome.fontSettings.getDefaultFontSize({}, (options) => {}); - chrome.fontSettings.getMinimumFontSize({}, (options) => {}); - chrome.fontSettings.setMinimumFontSize({ pixelSize: 1 }, () => {}); - chrome.fontSettings.getDefaultFixedFontSize({}, (details) => {}); - chrome.fontSettings.clearDefaultFontSize({}, () => {}); - chrome.fontSettings.setDefaultFixedFontSize({ pixelSize: 1 }, () => {}); - chrome.fontSettings.clearFont({ genericFamily: "cursive" }, () => {}); - chrome.fontSettings.setFont({ genericFamily: "cursive", fontId: "" }, () => {}); - chrome.fontSettings.clearMinimumFontSize({}, () => {}); - chrome.fontSettings.getFontList((results) => {}); - chrome.fontSettings.clearDefaultFixedFontSize({}, () => {}); -} + chrome.fontSettings.getMinimumFontSize({}, () => {}).then(() => {}); + + const setFontSizeDetails: chrome.fontSettings.FontSizeDetails = { + pixelSize: 12, + }; + + chrome.fontSettings.setDefaultFixedFontSize(setFontSizeDetails); // Expected Promise + chrome.fontSettings.setDefaultFixedFontSize(setFontSizeDetails, () => void 0); // Expected void + // @ts-expect-error + chrome.fontSettings.setDefaultFixedFontSize(() => {}).then(() => {}); -// https://developer.chrome.com/docs/extensions/reference/fontSettings -async function testFontSettingsForPromise() { - await chrome.fontSettings.setDefaultFontSize({ pixelSize: 1 }); - await chrome.fontSettings.getFont({ genericFamily: "cursive" }); - await chrome.fontSettings.getDefaultFontSize({}); - await chrome.fontSettings.getMinimumFontSize({}); - await chrome.fontSettings.setMinimumFontSize({ pixelSize: 1 }); - await chrome.fontSettings.getDefaultFixedFontSize({}); - await chrome.fontSettings.clearDefaultFontSize({}); - await chrome.fontSettings.setDefaultFixedFontSize({ pixelSize: 1 }); - await chrome.fontSettings.clearFont({ genericFamily: "cursive" }); - await chrome.fontSettings.setFont({ genericFamily: "cursive", fontId: "" }); - await chrome.fontSettings.clearMinimumFontSize({}); - await chrome.fontSettings.getFontList(); - await chrome.fontSettings.clearDefaultFixedFontSize({}); + chrome.fontSettings.setDefaultFontSize(setFontSizeDetails); // Expected Promise + chrome.fontSettings.setDefaultFontSize(setFontSizeDetails, () => void 0); // Expected void + // @ts-expect-error + chrome.fontSettings.setDefaultFontSize(() => {}).then(() => {}); + + const setFontDetails: chrome.fontSettings.SetFontDetails = { + genericFamily: "standard", + script: "Afak", + fontId: "fontId", + }; + + chrome.fontSettings.setFont(setFontDetails); // Expected Promise + chrome.fontSettings.setFont(setFontDetails, () => void 0); // Expected void + // @ts-expect-error + chrome.fontSettings.setFont(() => {}).then(() => {}); + + chrome.fontSettings.setMinimumFontSize(setFontSizeDetails); // Expected Promise + chrome.fontSettings.setMinimumFontSize(setFontSizeDetails, () => void 0); // Expected void + // @ts-expect-error + chrome.fontSettings.setMinimumFontSize(() => {}).then(() => {}); + + checkChromeEvent(chrome.fontSettings.onDefaultFixedFontSizeChanged, (details) => { + details.pixelSize; // Expected number + details.levelOfControl; // Expected LevelOfControl + }); + + checkChromeEvent(chrome.fontSettings.onDefaultFontSizeChanged, (details) => { + details.pixelSize; // Expected number + details.levelOfControl; // Expected LevelOfControl + }); + + checkChromeEvent(chrome.fontSettings.onFontChanged, (details) => { + details.fontId; // Expected string + details.genericFamily; // Expected GenericFamily + details.levelOfControl; // Expected LevelOfControl + details.script; // Expected ScriptCode | undefined + }); + + checkChromeEvent(chrome.fontSettings.onMinimumFontSizeChanged, (details) => { + details.pixelSize; // Expected number + details.levelOfControl; // Expected LevelOfControl + }); } // https://developer.chrome.com/docs/extensions/reference/api/gcm From 8f60370e76f09a7334155b19b590356b5e74d8ba Mon Sep 17 00:00:00 2001 From: auvred <61150013+auvred@users.noreply.github.com> Date: Fri, 12 Sep 2025 22:08:21 +0300 Subject: [PATCH 11/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73578=20fix(?= =?UTF-8?q?node/http):=20properly=20re-export=20WebSocket,=20MessageEvent,?= =?UTF-8?q?=20CloseEvent=20types=20by=20@auvred?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/node/http.d.ts | 6 +++--- types/node/test/http.ts | 6 ++++++ types/node/v22/http.d.ts | 6 +++--- types/node/v22/test/http.ts | 6 ++++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/types/node/http.d.ts b/types/node/http.d.ts index 4df8fad912fdae..01c2695bc21320 100644 --- a/types/node/http.d.ts +++ b/types/node/http.d.ts @@ -2031,15 +2031,15 @@ declare module "http" { * A browser-compatible implementation of [WebSocket](https://nodejs.org/docs/latest/api/http.html#websocket). * @since v22.5.0 */ - const WebSocket: import("undici-types").WebSocket; + const WebSocket: typeof import("undici-types").WebSocket; /** * @since v22.5.0 */ - const CloseEvent: import("undici-types").CloseEvent; + const CloseEvent: typeof import("undici-types").CloseEvent; /** * @since v22.5.0 */ - const MessageEvent: import("undici-types").MessageEvent; + const MessageEvent: typeof import("undici-types").MessageEvent; } declare module "node:http" { export * from "http"; diff --git a/types/node/test/http.ts b/types/node/test/http.ts index 5116be6402af0f..7efd061b907149 100644 --- a/types/node/test/http.ts +++ b/types/node/test/http.ts @@ -730,3 +730,9 @@ import * as url from "node:url"; http.setMaxIdleHTTPParsers(1337); } + +{ + new http.WebSocket("ws://example.com", ["protocol"]); + new http.CloseEvent("close"); + new http.MessageEvent("message", { data: "data" }); +} diff --git a/types/node/v22/http.d.ts b/types/node/v22/http.d.ts index 946d90159d352f..a398c51f465362 100644 --- a/types/node/v22/http.d.ts +++ b/types/node/v22/http.d.ts @@ -2031,15 +2031,15 @@ declare module "http" { * A browser-compatible implementation of `WebSocket`. * @since v22.5.0 */ - const WebSocket: import("undici-types").WebSocket; + const WebSocket: typeof import("undici-types").WebSocket; /** * @since v22.5.0 */ - const CloseEvent: import("undici-types").CloseEvent; + const CloseEvent: typeof import("undici-types").CloseEvent; /** * @since v22.5.0 */ - const MessageEvent: import("undici-types").MessageEvent; + const MessageEvent: typeof import("undici-types").MessageEvent; } declare module "node:http" { export * from "http"; diff --git a/types/node/v22/test/http.ts b/types/node/v22/test/http.ts index 5116be6402af0f..7efd061b907149 100644 --- a/types/node/v22/test/http.ts +++ b/types/node/v22/test/http.ts @@ -730,3 +730,9 @@ import * as url from "node:url"; http.setMaxIdleHTTPParsers(1337); } + +{ + new http.WebSocket("ws://example.com", ["protocol"]); + new http.CloseEvent("close"); + new http.MessageEvent("message", { data: "data" }); +} From 29420d43bbc2163e93d711e4e00a74282ca46488 Mon Sep 17 00:00:00 2001 From: TheLazySquid <76746384+TheLazySquid@users.noreply.github.com> Date: Fri, 12 Sep 2025 15:09:05 -0400 Subject: [PATCH 12/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73641=20Add?= =?UTF-8?q?=20@types/gimloader=20package=20by=20@TheLazySquid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/gimloader/.npmignore | 5 + types/gimloader/gimloader-tests.ts | 33 ++ types/gimloader/index.d.ts | 745 +++++++++++++++++++++++++++++ types/gimloader/package.json | 23 + types/gimloader/tsconfig.json | 20 + 5 files changed, 826 insertions(+) create mode 100644 types/gimloader/.npmignore create mode 100644 types/gimloader/gimloader-tests.ts create mode 100644 types/gimloader/index.d.ts create mode 100644 types/gimloader/package.json create mode 100644 types/gimloader/tsconfig.json diff --git a/types/gimloader/.npmignore b/types/gimloader/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/gimloader/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/gimloader/gimloader-tests.ts b/types/gimloader/gimloader-tests.ts new file mode 100644 index 00000000000000..7ed00a97ac0aec --- /dev/null +++ b/types/gimloader/gimloader-tests.ts @@ -0,0 +1,33 @@ +GL; // $ExpectType typeof Api +api; // $ExpectType Api + +new GL(); // $ExpectType Api + +api.React; // $ExpectType typeof React +api.UI; // $ExpectType Readonly +api.hotkeys; // $ExpectType Readonly +api.libs; // $ExpectType Readonly +api.net; // $ExpectType Readonly +api.patcher; // $ExpectType Readonly +api.plugins; // $ExpectType Readonly +api.rewriter; // $ExpectType Readonly +api.storage; // $ExpectType Readonly + +GL.React; // $ExpectType typeof React +GL.UI; // $ExpectType Readonly +GL.hotkeys; // $ExpectType Readonly +GL.libs; // $ExpectType Readonly +GL.net; // $ExpectType Readonly +GL.patcher; // $ExpectType Readonly +GL.plugins; // $ExpectType Readonly +GL.rewriter; // $ExpectType Readonly +GL.storage; // $ExpectType Readonly + +// @ts-expect-error +GL.onStop; +// @ts-expect-error +GL.openSettingsMenu; +// @ts-expect-error +api.onStop(); +// @ts-expect-error +api.openSettingsMenu(); diff --git a/types/gimloader/index.d.ts b/types/gimloader/index.d.ts new file mode 100644 index 00000000000000..9626e01841936e --- /dev/null +++ b/types/gimloader/index.d.ts @@ -0,0 +1,745 @@ +declare namespace Gimloader { + type event = symbol | string; + type eventNS = string | event[]; + + interface ConstructorOptions { + /** + * @default false + * @description set this to `true` to use wildcards. + */ + wildcard?: boolean; + /** + * @default '.' + * @description the delimiter used to segment namespaces. + */ + delimiter?: string; + /** + * @default false + * @description set this to `true` if you want to emit the newListener events. + */ + newListener?: boolean; + /** + * @default false + * @description set this to `true` if you want to emit the removeListener events. + */ + removeListener?: boolean; + /** + * @default 10 + * @description the maximum amount of listeners that can be assigned to an event. + */ + maxListeners?: number; + /** + * @default false + * @description show event name in memory leak message when more than maximum amount of listeners is assigned, default false + */ + verboseMemoryLeak?: boolean; + /** + * @default false + * @description disable throwing uncaughtException if an error event is emitted and it has no listeners + */ + ignoreErrors?: boolean; + } + interface ListenerFn { + (...values: any[]): void; + } + interface EventAndListener { + (event: string | string[], ...values: any[]): void; + } + + interface WaitForFilter { + (...values: any[]): boolean; + } + + interface WaitForOptions { + /** + * @default 0 + */ + timeout: number; + /** + * @default null + */ + filter: WaitForFilter; + /** + * @default false + */ + handleError: boolean; + /** + * @default Promise + */ + Promise: any; + /** + * @default false + */ + overload: boolean; + } + + interface CancelablePromise extends Promise { + cancel(reason: string): undefined; + } + + interface OnceOptions { + /** + * @default 0 + */ + timeout: number; + /** + * @default Promise + */ + Promise: any; + /** + * @default false + */ + overload: boolean; + } + + interface ListenToOptions { + on?: { (event: event | eventNS, handler: ListenerFn): void }; + off?: { (event: event | eventNS, handler: ListenerFn): void }; + reducers: (event: any) => boolean | object; + } + + interface GeneralEventEmitter { + addEventListener(event: event, handler: ListenerFn): this; + removeEventListener(event: event, handler: ListenerFn): this; + addListener?(event: event, handler: ListenerFn): this; + removeListener?(event: event, handler: ListenerFn): this; + on?(event: event, handler: ListenerFn): this; + off?(event: event, handler: ListenerFn): this; + } + + interface OnOptions { + async?: boolean; + promisify?: boolean; + nextTick?: boolean; + objectify?: boolean; + } + + interface Listener { + emitter: EventEmitter2; + event: event | eventNS; + listener: ListenerFn; + off(): this; + } + + class EventEmitter2 { + constructor(options?: ConstructorOptions); + emit(event: event | eventNS, ...values: any[]): boolean; + emitAsync(event: event | eventNS, ...values: any[]): Promise; + addListener(event: event | eventNS, listener: ListenerFn): this | Listener; + on(event: event | eventNS, listener: ListenerFn, options?: boolean | OnOptions): this | Listener; + prependListener(event: event | eventNS, listener: ListenerFn, options?: boolean | OnOptions): this | Listener; + once(event: event | eventNS, listener: ListenerFn, options?: true | OnOptions): this | Listener; + prependOnceListener( + event: event | eventNS, + listener: ListenerFn, + options?: boolean | OnOptions, + ): this | Listener; + many( + event: event | eventNS, + timesToListen: number, + listener: ListenerFn, + options?: boolean | OnOptions, + ): this | Listener; + prependMany( + event: event | eventNS, + timesToListen: number, + listener: ListenerFn, + options?: boolean | OnOptions, + ): this | Listener; + onAny(listener: EventAndListener): this; + prependAny(listener: EventAndListener): this; + offAny(listener: ListenerFn): this; + removeListener(event: event | eventNS, listener: ListenerFn): this; + off(event: event | eventNS, listener: ListenerFn): this; + removeAllListeners(event?: event | eventNS): this; + setMaxListeners(n: number): void; + getMaxListeners(): number; + eventNames(nsAsArray?: boolean): (event | eventNS)[]; + listenerCount(event?: event | eventNS): number; + listeners(event?: event | eventNS): ListenerFn[]; + listenersAny(): ListenerFn[]; + waitFor(event: event | eventNS, timeout?: number): CancelablePromise; + waitFor(event: event | eventNS, filter?: WaitForFilter): CancelablePromise; + waitFor(event: event | eventNS, options?: WaitForOptions): CancelablePromise; + listenTo(target: GeneralEventEmitter, events: event | eventNS, options?: ListenToOptions): this; + listenTo(target: GeneralEventEmitter, events: event[], options?: ListenToOptions): this; + listenTo(target: GeneralEventEmitter, events: object, options?: ListenToOptions): this; + stopListeningTo(target?: GeneralEventEmitter, event?: event | eventNS): boolean; + hasListeners(event?: string): boolean; + static once(emitter: EventEmitter2, event: event | eventNS, options?: OnceOptions): CancelablePromise; + static defaultMaxListeners: number; + } + + class PluginsApi { + /** A list of all the plugins installed */ + get list(): string[]; + /** Whether a plugin exists and is enabled */ + isEnabled(name: string): boolean; + /** Gets the headers of a plugin, such as version, author, and description */ + getHeaders(name: string): { + name: string; + description: string; + author: string; + version: string | null; + reloadRequired: string; + isLibrary: string; + downloadUrl: string | null; + webpage: string | null; + needsLib: string[]; + optionalLib: string[]; + syncEval: string; + hasSettings: string; + }; + /** Gets the exported values of a plugin, if it has been enabled */ + get(name: string): any; + /** + * @deprecated Use {@link get} instead + * @hidden + */ + getPlugin(name: string): { + return: any; + }; + } + + class LibsApi { + /** A list of all the libraries installed */ + get list(): string[]; + /** Gets whether or not a plugin is installed and enabled */ + isEnabled(name: string): boolean; + /** Gets the headers of a library, such as version, author, and description */ + getHeaders(name: string): { + name: string; + description: string; + author: string; + version: string | null; + reloadRequired: string; + isLibrary: string; + downloadUrl: string | null; + webpage: string | null; + needsLib: string[]; + optionalLib: string[]; + syncEval: string; + hasSettings: string; + }; + /** Gets the exported values of a library */ + get(name: string): any; + } + + class ScopedRewriterApi { + private readonly id; + constructor(id: string); + /** + * Creates a hook that will modify the code of a script before it is run. + * This value is cached, so this hook may not run on subsequent page loads. + * addParseHook should always be called in the top level of a script. + * @param prefix Limits the hook to only running on scripts beginning with this prefix. + * Passing `true` will only run on the index script, and passing `false` will run on all scripts. + * @param callback The function that will modify the code. Should return the modified code. Cannot have side effects. + */ + addParseHook(prefix: string | boolean, callback: (code: string) => string): () => void; + /** + * Creates a shared value that can be accessed from any script. + * @param id A unique identifier for the shared value. + * @param value The value to be shared. + * @returns A string representing the code to access the shared value. + */ + createShared(id: string, value: any): string; + /** Removes the shared value with a certain id created by {@link createShared} */ + removeSharedById(id: string): void; + } + + class RewriterApi { + /** + * Creates a hook that will modify the code of a script before it is run. + * This value is cached, so this hook may not run on subsequent page loads. + * addParseHook should always be called in the top level of a script. + * @param pluginName The name of the plugin creating the hook. + * @param prefix Limits the hook to only running on scripts beginning with this prefix. + * Passing `true` will only run on the index script, and passing `false` will run on all scripts. + * @param callback The function that will modify the code. Should return the modified code. Cannot have side effects. + */ + addParseHook(pluginName: string, prefix: string | boolean, callback: (code: string) => string): () => void; + /** Removes all hooks created by a certain plugin */ + removeParseHooks(pluginName: string): void; + /** + * Creates a shared value that can be accessed from any script. + * @param pluginName The name of the plugin creating the shared value. + * @param id A unique identifier for the shared value. + * @param value The value to be shared. + * @returns A string representing the code to access the shared value. + */ + createShared(pluginName: string, id: string, value: any): string; + /** Removes all values created by {@link createShared} by a certain plugin */ + removeShared(pluginName: string): void; + /** Removes the shared value with a certain id created by {@link createShared} */ + removeSharedById(pluginName: string, id: string): void; + } + + class ScopedPatcherApi { + private readonly id; + constructor(id: string); + /** + * Runs a callback after a function on an object has been run + * @returns A function to remove the patch + */ + after(object: any, method: string, callback: PatcherAfterCallback): () => void; + /** + * Runs a callback before a function on an object has been run. + * Return true from the callback to prevent the function from running + * @returns A function to remove the patch + */ + before(object: any, method: string, callback: PatcherBeforeCallback): () => void; + /** + * Runs a function instead of a function on an object + * @returns A function to remove the patch + */ + instead(object: any, method: string, callback: PatcherInsteadCallback): () => void; + } + + type PatcherInsteadCallback = (thisVal: any, args: IArguments) => void; + + type PatcherBeforeCallback = (thisVal: any, args: IArguments) => boolean | undefined; + + type PatcherAfterCallback = (thisVal: any, args: IArguments, returnVal: any) => any; + + class PatcherApi { + /** + * Runs a callback after a function on an object has been run + * @returns A function to remove the patch + */ + after(id: string, object: any, method: string, callback: PatcherAfterCallback): () => void; + /** + * Runs a callback before a function on an object has been run. + * Return true from the callback to prevent the function from running + * @returns A function to remove the patch + */ + before(id: string, object: any, method: string, callback: PatcherBeforeCallback): () => void; + /** + * Runs a function instead of a function on an object + * @returns A function to remove the patch + */ + instead(id: string, object: any, method: string, callback: PatcherInsteadCallback): () => void; + /** Removes all patches with a given id */ + unpatchAll(id: string): void; + } + + class ScopedStorageApi { + private readonly id; + constructor(id: string); + /** Gets a value that has previously been saved */ + getValue(key: string, defaultValue?: any): any; + /** Sets a value which can be retrieved later, persisting through reloads */ + setValue(key: string, value: any): void; + /** Removes a value which has been saved */ + deleteValue(key: string): void; + /** Adds a listener for when a stored value with a certain key changes */ + onChange(key: string, callback: ValueChangeCallback): () => void; + } + + type ValueChangeCallback = (value: any, remote: boolean) => void; + + class StorageApi { + /** Gets a value that has previously been saved */ + getValue(pluginName: string, key: string, defaultValue?: any): any; + /** Sets a value which can be retrieved later, through reloads */ + setValue(pluginName: string, key: string, value: any): void; + /** Removes a value which has been saved */ + deleteValue(pluginName: string, key: string): void; + /** + * @deprecated use {@link deleteValue} + * @hidden + */ + get removeValue(): (pluginName: string, key: string) => void; + /** Adds a listener for when a plugin's stored value with a certain key changes */ + onChange(pluginName: string, key: string, callback: ValueChangeCallback): () => void; + /** Removes a listener added by onChange */ + offChange(pluginName: string, key: string, callback: ValueChangeCallback): void; + /** Removes all listeners added by onChange for a certain plugin */ + offAllChanges(pluginName: string): void; + } + + class ScopedUIApi extends BaseUIApi { + private readonly id; + constructor(id: string); + /** + * Adds a style to the DOM + * @returns A function to remove the styles + */ + addStyles(style: string): () => void; + } + + interface ModalButton { + text: string; + style?: "primary" | "danger" | "close"; + onClick?: (event: MouseEvent) => boolean | undefined; + } + + interface ModalOptions { + id: string; + title: string; + style: string; + className: string; + closeOnBackgroundClick: boolean; + buttons: ModalButton[]; + onClosed: () => void; + } + + class BaseUIApi { + /** Shows a customizable modal to the user */ + showModal(element: HTMLElement | import("react").ReactElement, options?: Partial): void; + } + + class UIApi extends BaseUIApi { + /** + * Adds a style to the DOM + * @returns A function to remove the styles + */ + addStyles(id: string, style: string): () => void; + /** Remove all styles with a given id */ + removeStyles(id: string): void; + } + + class ScopedNetApi extends BaseNetApi { + private readonly id; + constructor(id: string); + /** + * Runs a callback when the game is loaded, or runs it immediately if the game has already loaded + * @returns A function to cancel waiting for load + */ + onLoad(callback: (type: ConnectionType) => void): () => void; + } + + type ConnectionType = "None" | "Colyseus" | "Blueboat"; + + class BaseNetApi extends EventEmitter2 { + constructor(); + /** Which type of server the client is currently connected to */ + get type(): ConnectionType; + /** The room that the client is connected to, or null if there is no connection */ + get room(): any; + /** Whether the user is the one hosting the current game */ + get isHost(): boolean; + /** Sends a message to the server on a specific channel */ + send(channel: string, message: any): void; + } + + class NetApi extends BaseNetApi { + constructor(); + /** + * Runs a callback when the game is loaded, or runs it immediately if the game has already loaded + * @returns A function to cancel waiting for load + */ + onLoad(id: string, callback: (type: ConnectionType) => void): () => void; + /** Cancels any calls to {@link onLoad} with the same id */ + offLoad(id: string): void; + /** + * @deprecated Methods for both transports are now on the base net api + * @hidden + */ + get colyseus(): this; + /** + * @deprecated Methods for both transports are now on the base net api + * @hidden + */ + get blueboat(): this; + /** @hidden */ + private wrappedListeners; + /** + * @deprecated use net.on + * @hidden + */ + addEventListener(channel: string, callback: (...args: any[]) => void): void; + /** + * @deprecated use net.off + * @hidden + */ + removeEventListener(channel: string, callback: (...args: any[]) => void): void; + } + + class ScopedParcelApi extends BaseParcelApi { + private readonly id; + constructor(id: string); + /** + * Waits for a module to be loaded, then runs a callback + * @returns A function to cancel waiting for the module + */ + getLazy(): () => void; + } + + class BaseParcelApi { + /** + * Gets a module based on a filter, returns null if none are found + * Be cautious when using this- plugins will often run before any modules load in, + * meaning that if this is run on startup it will likely return nothing. + * Consider using getLazy instead. + */ + query(): any; + /** + * Returns an array of all loaded modules matching a filter + * Be cautious when using this- plugins will often run before any modules load in, + * meaning that if this is run on startup it will likely return nothing. + * Consider using getLazy instead. + */ + queryAll(): any[]; + } + + class ParcelApi extends BaseParcelApi { + /** + * Waits for a module to be loaded, then runs a callback + * @returns A function to cancel waiting for the module + */ + getLazy(): () => void; + /** Cancels any calls to getLazy with the same id */ + stopLazy(): void; + /** + * @deprecated Use {@link getLazy} instead + * @hidden + */ + get interceptRequire(): () => () => void; + /** + * @deprecated Use {@link stopLazy} instead + * @hidden + */ + get stopIntercepts(): () => void; + } + + class ScopedHotkeysApi extends BaseHotkeysApi { + private readonly id; + constructor(id: string); + /** + * Adds a hotkey which will fire when certain keys are pressed + * @returns A function to remove the hotkey + */ + addHotkey(options: HotkeyOptions, callback: KeyboardCallback): () => void; + /** + * Adds a hotkey which can be changed by the user + * @returns A function to remove the hotkey + */ + addConfigurableHotkey(options: ConfigurableHotkeyOptions, callback: KeyboardCallback): () => void; + } + + type KeyboardCallback = (e: KeyboardEvent) => void; + + class BaseHotkeysApi { + /** + * Releases all keys, needed if a hotkey opens something that will + * prevent keyup events from being registered, such as an alert + */ + releaseAll(): void; + /** Which key codes are currently being pressed */ + get pressed(): Set; + /** + * @deprecated Use {@link pressed} instead + * @hidden + */ + get pressedKeys(): Set; + } + + interface OldConfigurableOptions { + category: string; + title: string; + preventDefault?: boolean; + defaultKeys?: Set; + } + + interface ConfigurableHotkeyOptions { + category: string; + /** There should be no duplicate titles within a category */ + title: string; + preventDefault?: boolean; + default?: HotkeyTrigger; + } + + interface HotkeyTrigger { + /** Should be a keyboardevent [code](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code) */ + key?: string; + /** Should be keyboardevent [codes](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code) */ + keys?: string[]; + ctrl?: boolean; + shift?: boolean; + alt?: boolean; + } + + interface HotkeyOptions extends HotkeyTrigger { + preventDefault?: boolean; + } + + class HotkeysApi extends BaseHotkeysApi { + /** + * Adds a hotkey with a given id + * @returns A function to remove the hotkey + */ + addHotkey(id: string, options: HotkeyOptions, callback: KeyboardCallback): () => void; + /** Removes all hotkeys with a given id */ + removeHotkeys(id: string): void; + /** + * Adds a hotkey which can be changed by the user + * @param id A unique id for the hotkey, such as `myplugin-myhotkey` + * @returns A function to remove the hotkey + */ + addConfigurableHotkey(id: string, options: ConfigurableHotkeyOptions, callback: KeyboardCallback): () => void; + /** Removes a configurable hotkey with a given id */ + removeConfigurableHotkey(id: string): void; + /** + * @deprecated Use {@link addHotkey} instead + * @hidden + */ + add(keys: Set, callback: KeyboardCallback, preventDefault?: boolean): void; + /** + * @deprecated Use {@link removeHotkeys} instead + * @hidden + */ + remove(keys: Set): void; + /** + * @deprecated Use {@link addConfigurableHotkey} instead + * @hidden + */ + addConfigurable( + pluginName: string, + hotkeyId: string, + callback: KeyboardCallback, + options: OldConfigurableOptions, + ): void; + /** + * @deprecated Use {@link removeConfigurableHotkeys} instead + * @hidden + */ + removeConfigurable(pluginName: string, hotkeyId: string): void; + } + + class Api { + /** + * @deprecated Gimkit has switched from Parcel to vite, rendering this api useless. + * @hidden + */ + static parcel: Readonly; + /** Functions to edit Gimkit's code */ + static rewriter: Readonly; + /** Functions to listen for key combinations */ + static hotkeys: Readonly; + /** + * Ways to interact with the current connection to the server, + * and functions to send general requests + */ + static net: Readonly; + /** Functions for interacting with the DOM */ + static UI: Readonly; + /** Functions for persisting data between reloads */ + static storage: Readonly; + /** Functions for intercepting the arguments and return values of functions */ + static patcher: Readonly; + /** Methods for getting info on libraries */ + static libs: Readonly; + /** Gets the exported values of a library */ + static lib: (name: string) => any; + /** Methods for getting info on plugins */ + static plugins: Readonly; + /** Gets the exported values of a plugin, if it has been enabled */ + static plugin: (name: string) => any; + /** Gimkit's internal react instance */ + static get React(): typeof import("react"); + /** Gimkit's internal reactDom instance */ + static get ReactDOM(): typeof import("react-dom/client"); + /** A variety of Gimkit internal objects available in 2d gamemodes */ + static get stores(): any; + /** + * Gimkit's notification object, only available when joining or playing a game + * + * {@link https://ant.design/components/notification} + */ + static get notification(): any; + /** + * @deprecated No longer supported + * @hidden + */ + static get contextMenu(): { + showContextMenu: () => void; + createReactContextMenu: () => void; + }; + /** + * @deprecated No longer supported + * @hidden + */ + static get platformerPhysics(): any; + /** + * @deprecated The api no longer emits events. Use GL.net.loaded to listen to load events + * @hidden + */ + static addEventListener(type: string, callback: () => void): void; + /** + * @deprecated The api no longer emits events + * @hidden + */ + static removeEventListener(type: string, callback: () => void): void; + /** + * @deprecated Use {@link plugins} instead + * @hidden + */ + static get pluginManager(): Readonly; + constructor(type?: string, name?: string); + /** + * @deprecated Gimkit has switched from Parcel to vite, rendering this api useless. + * @hidden + */ + parcel: Readonly; + /** Functions to edit Gimkit's code */ + rewriter: Readonly; + /** Functions to listen for key combinations */ + hotkeys: Readonly; + /** + * Ways to interact with the current connection to the server, + * and functions to send general requests + */ + net: Readonly; + /** Functions for interacting with the DOM */ + UI: Readonly; + /** Functions for persisting data between reloads */ + storage: Readonly; + /** Functions for intercepting the arguments and return values of functions */ + patcher: Readonly; + /** Methods for getting info on libraries */ + libs: Readonly; + /** Gets the exported values of a library */ + lib: (name: string) => any; + /** Methods for getting info on plugins */ + plugins: Readonly; + /** Gets the exported values of a plugin, if it has been enabled */ + plugin: (name: string) => any; + /** Gimkit's internal react instance */ + get React(): typeof import("react"); + /** Gimkit's internal reactDom instance */ + get ReactDOM(): typeof import("react-dom/client"); + /** A variety of gimkit internal objects available in 2d gamemodes */ + get stores(): any; + /** + * Gimkit's notification object, only available when joining or playing a game + * + * {@link https://ant.design/components/notification} + */ + get notification(): any; + /** Run a callback when the plugin or library is disabled */ + onStop: (callback: () => void) => void; + /** + * Run a callback when the plugin's settings menu button is clicked + * + * This function is not available for libraries + */ + openSettingsMenu: (callback: () => void) => void; + } +} + +declare const api: Gimloader.Api; +declare const GL: typeof Gimloader.Api; +/** @deprecated Use GL.stores */ +declare const stores: any; +/** @deprecated No longer supported */ +declare const platformerPhysics: any; + +interface Window { + api: Gimloader.Api; + GL: typeof Gimloader.Api; + /** @deprecated Use GL.stores */ + stores: any; + /** @deprecated No longer supported */ + platformerPhysics: any; +} diff --git a/types/gimloader/package.json b/types/gimloader/package.json new file mode 100644 index 00000000000000..30d88efb82efcc --- /dev/null +++ b/types/gimloader/package.json @@ -0,0 +1,23 @@ +{ + "private": true, + "name": "@types/gimloader", + "version": "1.6.9999", + "nonNpm": "conflict", + "nonNpmDescription": "Types for the Gimloader global variables", + "projects": [ + "https://github.com/Gimloader/Gimloader#readme" + ], + "dependencies": { + "@types/react": "*", + "@types/react-dom": "*" + }, + "devDependencies": { + "@types/gimloader": "workspace:." + }, + "owners": [ + { + "name": "TheLazySquid", + "githubUsername": "TheLazySquid" + } + ] +} diff --git a/types/gimloader/tsconfig.json b/types/gimloader/tsconfig.json new file mode 100644 index 00000000000000..b16298e1f1b900 --- /dev/null +++ b/types/gimloader/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": [ + "es6", + "DOM" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "gimloader-tests.ts" + ] +} From 2095d59cbb6208fd05626e96f496d559aa8fdac3 Mon Sep 17 00:00:00 2001 From: szenadam <42336465+szenadam@users.noreply.github.com> Date: Fri, 12 Sep 2025 21:53:28 +0200 Subject: [PATCH 13/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73517=20Fix?= =?UTF-8?q?=20type=20definition=20of=20cross()=20for=20d3-array=20v2=20and?= =?UTF-8?q?=20v3=20by=20@szenadam?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/d3-array/d3-array-tests.ts | 8 ++-- types/d3-array/index.d.ts | 61 ++++++++++++++++++++++------- types/d3-array/v2/d3-array-tests.ts | 8 ++-- types/d3-array/v2/index.d.ts | 61 ++++++++++++++++++++++------- 4 files changed, 100 insertions(+), 38 deletions(-) diff --git a/types/d3-array/d3-array-tests.ts b/types/d3-array/d3-array-tests.ts index bf5811538d8a19..42c803438bcca0 100644 --- a/types/d3-array/d3-array-tests.ts +++ b/types/d3-array/d3-array-tests.ts @@ -2530,9 +2530,9 @@ const chars = ["x", "y"]; const nums = [1, 2]; crossed = d3Array.cross(chars, nums); -crossed = d3Array.cross(chars, nums); +crossed = d3Array.cross<[string, number]>(chars, nums); -let strArray: string[] = d3Array.cross([2, 3], [5, 6], (a, b) => (a + b) + "px"); +let strArray: string[] = d3Array.cross<[number, number], string>([2, 3], [5, 6], (a, b) => (a + b) + "px"); strArray = d3Array.cross([2, 3], [5, 6], (a, b) => { const aa: number = a; const bb: number = b; @@ -2543,9 +2543,9 @@ const readonlyChars = chars as readonly string[]; const readonlyNums = new Uint8Array(nums); crossed = d3Array.cross(readonlyChars, readonlyNums); -crossed = d3Array.cross(readonlyChars, readonlyNums); +crossed = d3Array.cross<[string, number]>(readonlyChars, readonlyNums); -strArray = d3Array.cross( +strArray = d3Array.cross<[number, number], string>( [2, 3] as readonly number[], new Uint8ClampedArray([5, 6]), (a, b) => (a + b) + "px", diff --git a/types/d3-array/index.d.ts b/types/d3-array/index.d.ts index 5021041c057771..aa489e7676f906 100644 --- a/types/d3-array/index.d.ts +++ b/types/d3-array/index.d.ts @@ -648,25 +648,56 @@ export function count( ): number; /** - * Returns the Cartesian product of the two arrays a and b. - * For each element i in the specified array a and each element j in the specified array b, in order, - * it creates a two-element array for each pair. + * Computes the Cartesian product of any number of iterables. * - * @param a First input array. - * @param b Second input array. - */ -export function cross(a: Iterable, b: Iterable): Array<[S, T]>; + * When called **without** a reducer, the result is an array of tuples, + * where each tuple contains one element from each input iterable. + * + * @typeParam T - A tuple type describing the element type of each iterable argument. + * For example, passing `[number[], string[]]` infers `T` as `[number, string]`. + * + * @param iterables - Two or more iterables to combine into a Cartesian product. + * @returns An array of tuples containing one value from each iterable. + * + * @example + * ```ts + * const nums = [1, 2]; + * const chars = ['a', 'b']; + * const out = cross(nums, chars); + * // ^? type: [number, string][] + * // Example value: [[1,'a'], [1,'b'], [2,'a'], [2,'b']] + * ``` + */ +export function cross( + ...iterables: { [K in keyof T]: Iterable } +): T[]; /** - * Returns the Cartesian product of the two arrays a and b. - * For each element i in the specified array a and each element j in the specified array b, in order, - * invokes the specified reducer function passing the element i and element j. + * Computes the Cartesian product of any number of iterables and then applies + * a reducer to each tuple, returning the reduced values. * - * @param a First input array. - * @param b Second input array. - * @param reducer A reducer function taking as input an element from "a" and "b" and returning a reduced value. - */ -export function cross(a: Iterable, b: Iterable, reducer: (a: S, b: T) => U): U[]; + * The final argument **must** be the reducer function; all prior arguments are iterables. + * + * @typeParam T - A tuple type describing the element type of each iterable argument. + * @typeParam U - The result type produced by the reducer. + * + * @param args - The iterables to combine, followed by a reducer function. + * @param args.reducer - A function invoked with one element from each iterable + * (spread as individual parameters) that returns a reduced value. + * @returns An array of reduced values returned by the reducer. + * + * @example + * ```ts + * const nums = [1, 2]; + * const chars = ['a', 'b']; + * const out = cross(nums, chars, (n, c) => `${n}${c}`); + * // ^? type: string[] + * // Example value: ['1a', '1b', '2a', '2b'] + * ``` + */ +export function cross( + ...args: [...iterables: { [K in keyof T]: Iterable }, reducer: (...values: T) => U] +): U[]; /** * Merges the specified arrays into a single array. diff --git a/types/d3-array/v2/d3-array-tests.ts b/types/d3-array/v2/d3-array-tests.ts index bac98ba7b4e752..1df0fdea104ecf 100644 --- a/types/d3-array/v2/d3-array-tests.ts +++ b/types/d3-array/v2/d3-array-tests.ts @@ -901,9 +901,9 @@ const chars = ["x", "y"]; const nums = [1, 2]; crossed = d3Array.cross(chars, nums); -crossed = d3Array.cross(chars, nums); +crossed = d3Array.cross<[string, number]>(chars, nums); -let strArray: string[] = d3Array.cross([2, 3], [5, 6], (a, b) => (a + b) + "px"); +let strArray: string[] = d3Array.cross<[number, number], string>([2, 3], [5, 6], (a, b) => (a + b) + "px"); strArray = d3Array.cross([2, 3], [5, 6], (a, b) => { const aa: number = a; const bb: number = b; @@ -914,9 +914,9 @@ const readonlyChars = chars as readonly string[]; const readonlyNums = new Uint8Array(nums); crossed = d3Array.cross(readonlyChars, readonlyNums); -crossed = d3Array.cross(readonlyChars, readonlyNums); +crossed = d3Array.cross<[string, number]>(readonlyChars, readonlyNums); -strArray = d3Array.cross( +strArray = d3Array.cross<[number, number], string>( [2, 3] as readonly number[], new Uint8ClampedArray([5, 6]), (a, b) => (a + b) + "px", diff --git a/types/d3-array/v2/index.d.ts b/types/d3-array/v2/index.d.ts index cf8fc736231d3c..66177a82707311 100644 --- a/types/d3-array/v2/index.d.ts +++ b/types/d3-array/v2/index.d.ts @@ -702,25 +702,56 @@ export function count( ): number; /** - * Returns the Cartesian product of the two arrays a and b. - * For each element i in the specified array a and each element j in the specified array b, in order, - * it creates a two-element array for each pair. + * Computes the Cartesian product of any number of iterables. * - * @param a First input array. - * @param b Second input array. - */ -export function cross(a: Iterable, b: Iterable): Array<[S, T]>; + * When called **without** a reducer, the result is an array of tuples, + * where each tuple contains one element from each input iterable. + * + * @typeParam T - A tuple type describing the element type of each iterable argument. + * For example, passing `[number[], string[]]` infers `T` as `[number, string]`. + * + * @param iterables - Two or more iterables to combine into a Cartesian product. + * @returns An array of tuples containing one value from each iterable. + * + * @example + * ```ts + * const nums = [1, 2]; + * const chars = ['a', 'b']; + * const out = cross(nums, chars); + * // ^? type: [number, string][] + * // Example value: [[1,'a'], [1,'b'], [2,'a'], [2,'b']] + * ``` + */ +export function cross( + ...iterables: { [K in keyof T]: Iterable } +): T[]; /** - * Returns the Cartesian product of the two arrays a and b. - * For each element i in the specified array a and each element j in the specified array b, in order, - * invokes the specified reducer function passing the element i and element j. + * Computes the Cartesian product of any number of iterables and then applies + * a reducer to each tuple, returning the reduced values. * - * @param a First input array. - * @param b Second input array. - * @param reducer A reducer function taking as input an element from "a" and "b" and returning a reduced value. - */ -export function cross(a: Iterable, b: Iterable, reducer: (a: S, b: T) => U): U[]; + * The final argument **must** be the reducer function; all prior arguments are iterables. + * + * @typeParam T - A tuple type describing the element type of each iterable argument. + * @typeParam U - The result type produced by the reducer. + * + * @param args - The iterables to combine, followed by a reducer function. + * @param args.reducer - A function invoked with one element from each iterable + * (spread as individual parameters) that returns a reduced value. + * @returns An array of reduced values returned by the reducer. + * + * @example + * ```ts + * const nums = [1, 2]; + * const chars = ['a', 'b']; + * const out = cross(nums, chars, (n, c) => `${n}${c}`); + * // ^? type: string[] + * // Example value: ['1a', '1b', '2a', '2b'] + * ``` + */ +export function cross( + ...args: [...iterables: { [K in keyof T]: Iterable }, reducer: (...values: T) => U] +): U[]; /** * Merges the specified arrays into a single array. From 5ee273af65ef2a96ada9382e91f2a66872c641bd Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Sat, 13 Sep 2025 04:16:06 +0800 Subject: [PATCH 14/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73538=20fix(?= =?UTF-8?q?libmime):=20fix=20export=20style,=20export=20the=20class=20Libm?= =?UTF-8?q?ime=20export=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/libmime/index.d.ts | 393 +++++++++++++++++---------------- types/libmime/libmime-tests.ts | 5 +- types/libmime/package.json | 2 +- 3 files changed, 206 insertions(+), 194 deletions(-) diff --git a/types/libmime/index.d.ts b/types/libmime/index.d.ts index 688226bb34d4b1..c7bc5a33f5c52c 100644 --- a/types/libmime/index.d.ts +++ b/types/libmime/index.d.ts @@ -1,195 +1,204 @@ /// -export type MimeWordEncoding = "Q" | "B"; - -/** - * Encodes a string into mime [encoded word](http://en.wikipedia.org/wiki/MIME#Encoded-Word) format. - * - * @param data Value to be encoded. - * @param mimeWordEncoding Encoding for the mime word. Defaults to `'Q'`. - * @param maxLength If set, split mime words into several chunks if needed. Defaults to `0`. - * @returns Single or several mime words joined together. - * - * @example - * import * as libmime from 'libmime'; - * - * libmime.encodeWord('See on õhin test', 'Q'); - * // --> =?UTF-8?Q?See_on_=C3=B5hin_test?= - */ -export function encodeWord(data: string | Buffer, mimeWordEncoding?: MimeWordEncoding, maxLength?: number): string; - -/** - * Encodes non ascii sequences in a string to mime words. - * - * @param data Value to be encoded. - * @param mimeWordEncoding Encoding for the mime word. Defaults to `'Q'`. - * @param maxLength If set, split mime words into several chunks if needed. - * @param fromCharset Source sharacter set. Defaults to `'UTF-8'`. - * @returns String with possible mime words. - */ -export function encodeWords( - data: string | Buffer, - mimeWordEncoding?: MimeWordEncoding, - maxLength?: number, - fromCharset?: string, -): string; -export function encodeWords(data: string | Buffer, mimeWordEncoding?: MimeWordEncoding, fromCharset?: string): string; - -/** - * Decode a complete mime word encoded string. - * - * @param charset Character set for the string. - * @param mimeWordEncoding Mime encoding for the string. - * @param str Mime word encoded string. - * @returns Decoded unicode string. - */ -export function decodeWord(charset: string, mimeWordEncoding: MimeWordEncoding, str: string): string; - -/** - * Decodes a string that might include one or several mime words. If no mime words are found from the string, - * the original string is returned. - * - * @param str String to be decoded. - * @returns Decoded unicode string. - */ -export function decodeWords(str: string): string; - -/** - * Folds a long line according to the [RFC 5322](http://tools.ietf.org/html/rfc5322#section-2.1.1). - * Mostly needed for folding header lines. - * - * @param str String to be folded. - * @param lineLength Maximum length of a line. Defaults to `76`. - * @param afterSpace If `true`, leave a space in the end of a line. - * @returns String with folded lines. - * - * @example - * import * as libmime from 'libmime'; - * - * libmime.foldLines('Content-Type: multipart/alternative; boundary="----zzzz----"'); - * // --> - * // Content-Type: multipart/alternative; - * // boundary="----zzzz----" - */ -export function foldLines(str: string, lineLength?: number, afterSpace?: boolean): string; - -/** - * Adds soft line breaks to content marked with `format=flowed` to ensure that no line - * in the message is longer than `lineLength`. - * - * @param str Plaintext string that requires wrapping. - * @param lineLength Maximum length of a line. Defaults to `76`. - * @returns String with forced line breaks. - */ -export function encodeFlowed(str: string, lineLength?: number): string; - -/** - * Unwraps a plaintext string in `format=flowed` soft wrapping. - * - * @param str Plaintext string with `format=flowed` to decode. - * @param delSp If `true`, delete leading spaces. Defaults to `false`. - * @returns Mime decoded string. - */ -export function decodeFlowed(str: string, delSp?: boolean): string; - -/** - * Unfolds a header line and splits it to key and value pair. The value is not mime word decoded, - * you need to do your own decoding based on the rules for the specific header key. - * - * @param headerLine Single header line, might include linebreaks as well if folded. - */ -export function decodeHeader(headerLine: string): { key: string; value: string }; - -/** - * Parses a block of header lines. Does not decode mime words as every header might have its own - * rules (eg. formatted email addresses and such). - * - * @param headers Headers string. - */ -export function decodeHeaders(headers: string): { [key: string]: string[] }; - -export interface StructuredHeader { - value: string; - params: { [key: string]: string }; +declare namespace libmime { + type MimeWordEncoding = "Q" | "B"; + + interface StructuredHeader { + value: string; + params: { [key: string]: string }; + } +} + +declare class Libmime { + /** + * Encodes a string into mime [encoded word](http://en.wikipedia.org/wiki/MIME#Encoded-Word) format. + * + * @param data Value to be encoded. + * @param mimeWordEncoding Encoding for the mime word. Defaults to `'Q'`. + * @param maxLength If set, split mime words into several chunks if needed. Defaults to `0`. + * @returns Single or several mime words joined together. + * + * @example + * import * as libmime from 'libmime'; + * + * libmime.encodeWord('See on õhin test', 'Q'); + * // --> =?UTF-8?Q?See_on_=C3=B5hin_test?= + */ + encodeWord(data: string | Buffer, mimeWordEncoding?: libmime.MimeWordEncoding, maxLength?: number): string; + + /** + * Encodes non ascii sequences in a string to mime words. + * + * @param data Value to be encoded. + * @param mimeWordEncoding Encoding for the mime word. Defaults to `'Q'`. + * @param maxLength If set, split mime words into several chunks if needed. + * @param fromCharset Source sharacter set. Defaults to `'UTF-8'`. + * @returns String with possible mime words. + */ + encodeWords( + data: string | Buffer, + mimeWordEncoding?: libmime.MimeWordEncoding, + maxLength?: number, + fromCharset?: string, + ): string; + encodeWords(data: string | Buffer, mimeWordEncoding?: libmime.MimeWordEncoding, fromCharset?: string): string; + + /** + * Decode a complete mime word encoded string. + * + * @param charset Character set for the string. + * @param mimeWordEncoding Mime encoding for the string. + * @param str Mime word encoded string. + * @returns Decoded unicode string. + */ + decodeWord(charset: string, mimeWordEncoding: libmime.MimeWordEncoding, str: string): string; + + /** + * Decodes a string that might include one or several mime words. If no mime words are found from the string, + * the original string is returned. + * + * @param str String to be decoded. + * @returns Decoded unicode string. + */ + decodeWords(str: string): string; + + /** + * Folds a long line according to the [RFC 5322](http://tools.ietf.org/html/rfc5322#section-2.1.1). + * Mostly needed for folding header lines. + * + * @param str String to be folded. + * @param lineLength Maximum length of a line. Defaults to `76`. + * @param afterSpace If `true`, leave a space in the end of a line. + * @returns String with folded lines. + * + * @example + * import * as libmime from 'libmime'; + * + * libmime.foldLines('Content-Type: multipart/alternative; boundary="----zzzz----"'); + * // --> + * // Content-Type: multipart/alternative; + * // boundary="----zzzz----" + */ + foldLines(str: string, lineLength?: number, afterSpace?: boolean): string; + + /** + * Adds soft line breaks to content marked with `format=flowed` to ensure that no line + * in the message is longer than `lineLength`. + * + * @param str Plaintext string that requires wrapping. + * @param lineLength Maximum length of a line. Defaults to `76`. + * @returns String with forced line breaks. + */ + encodeFlowed(str: string, lineLength?: number): string; + + /** + * Unwraps a plaintext string in `format=flowed` soft wrapping. + * + * @param str Plaintext string with `format=flowed` to decode. + * @param delSp If `true`, delete leading spaces. Defaults to `false`. + * @returns Mime decoded string. + */ + decodeFlowed(str: string, delSp?: boolean): string; + + /** + * Unfolds a header line and splits it to key and value pair. The value is not mime word decoded, + * you need to do your own decoding based on the rules for the specific header key. + * + * @param headerLine Single header line, might include linebreaks as well if folded. + */ + decodeHeader(headerLine: string): { key: string; value: string }; + + /** + * Parses a block of header lines. Does not decode mime words as every header might have its own + * rules (eg. formatted email addresses and such). + * + * @param headers Headers string. + */ + decodeHeaders(headers: string): { [key: string]: string[] }; + + /** + * Parses a header value with `key=value` arguments into a structured object. Useful when dealing + * with `content-type` and such. Continuation encoded params are joined into mime encoded words. + * + * @param valueString A header value without the key. + * + * @example + * import * as libmime from 'libmime'; + * + * libmime.parseHeaderValue('content-type: text/plain; CHARSET="UTF-8"'); + * // --> + * // { + * // "value": "text/plain", + * // "params": { + * // "charset": "UTF-8" + * // } + * // } + */ + parseHeaderValue(valueString: string): libmime.StructuredHeader; + + /** + * Joins structured header value together as `'value; param1=value1; param2=value2'`. + * + * @param structuredHeader A header value formatted with `parseHeaderValue`. + * `filename` argument is encoded with continuation encoding if needed. + */ + buildHeaderValue(structuredHeader: libmime.StructuredHeader): string; + + /** + * Encodes and splits a header param value according to [RFC2231](https://tools.ietf.org/html/rfc2231#section-3) + * Parameter Value Continuations. + * + * @param key Parameter key (eg. `filename`). + * @param data Value to encode. + * @param maxLength Maximum length of the encoded string part (not line length). Defaults to `50`. + * @param fromCharset Source sharacter set. Defaults to `'UTF-8'`. + * @returns A list of encoded keys and headers. + * + * @example + * import * as libmime from 'libmime'; + * + * libmime.buildHeaderParam('filename', 'filename õäöü.txt', 20); + * // --> + * // [ + * // { key: 'filename*0*', value: 'utf-8\'\'filename%20' }, + * // { key: 'filename*1*', value: '%C3%B5%C3%A4%C3%B6' }, + * // { key: 'filename*2*', value: '%C3%BC.txt' } + * // ] + */ + buildHeaderParam( + key: string, + data: string | Buffer, + maxLength?: number, + fromCharset?: string, + ): Array<{ key: string; value: string }>; + + /** + * @param mimeType Content type to be checked for. + * @returns File extension for a content type string. If no suitable extensions are found, + * `'bin'` is used as the default extension. + * + * @example + * import * as libmime from 'libmime'; + * + * libmime.detectExtension('image/jpeg'); + * // --> 'jpeg' + */ + detectExtension(mimeType: string): string; + + /** + * @param extension Extension (or filename) to be checked for. + * @returns Content type for a file extension. If no suitable content types are found, + * `'application/octet-stream'` is used as the default content type. + * + * @example + * import * as libmime from 'libmime'; + * + * libmime.detectMimeType('logo.jpg'); + * // --> 'image/jpeg' + */ + detectMimeType(extension: string): string; } -/** - * Parses a header value with `key=value` arguments into a structured object. Useful when dealing - * with `content-type` and such. Continuation encoded params are joined into mime encoded words. - * - * @param valueString A header value without the key. - * - * @example - * import * as libmime from 'libmime'; - * - * libmime.parseHeaderValue('content-type: text/plain; CHARSET="UTF-8"'); - * // --> - * // { - * // "value": "text/plain", - * // "params": { - * // "charset": "UTF-8" - * // } - * // } - */ -export function parseHeaderValue(valueString: string): StructuredHeader; - -/** - * Joins structured header value together as `'value; param1=value1; param2=value2'`. - * - * @param structuredHeader A header value formatted with `parseHeaderValue`. - * `filename` argument is encoded with continuation encoding if needed. - */ -export function buildHeaderValue(structuredHeader: StructuredHeader): string; - -/** - * Encodes and splits a header param value according to [RFC2231](https://tools.ietf.org/html/rfc2231#section-3) - * Parameter Value Continuations. - * - * @param key Parameter key (eg. `filename`). - * @param data Value to encode. - * @param maxLength Maximum length of the encoded string part (not line length). Defaults to `50`. - * @param fromCharset Source sharacter set. Defaults to `'UTF-8'`. - * @returns A list of encoded keys and headers. - * - * @example - * import * as libmime from 'libmime'; - * - * libmime.buildHeaderParam('filename', 'filename õäöü.txt', 20); - * // --> - * // [ - * // { key: 'filename*0*', value: 'utf-8\'\'filename%20' }, - * // { key: 'filename*1*', value: '%C3%B5%C3%A4%C3%B6' }, - * // { key: 'filename*2*', value: '%C3%BC.txt' } - * // ] - */ -export function buildHeaderParam( - key: string, - data: string | Buffer, - maxLength?: number, - fromCharset?: string, -): Array<{ key: string; value: string }>; - -/** - * @param mimeType Content type to be checked for. - * @returns File extension for a content type string. If no suitable extensions are found, - * `'bin'` is used as the default extension. - * - * @example - * import * as libmime from 'libmime'; - * - * libmime.detectExtension('image/jpeg'); - * // --> 'jpeg' - */ -export function detectExtension(mimeType: string): string; - -/** - * @param extension Extension (or filename) to be checked for. - * @returns Content type for a file extension. If no suitable content types are found, - * `'application/octet-stream'` is used as the default content type. - * - * @example - * import * as libmime from 'libmime'; - * - * libmime.detectMimeType('logo.jpg'); - * // --> 'image/jpeg' - */ -export function detectMimeType(extension: string): string; + +declare const libmime: Libmime & { Libmime: typeof Libmime }; + +export = libmime; diff --git a/types/libmime/libmime-tests.ts b/types/libmime/libmime-tests.ts index 00828c145132f6..abca1453ae2698 100644 --- a/types/libmime/libmime-tests.ts +++ b/types/libmime/libmime-tests.ts @@ -1,4 +1,4 @@ -import * as libmime from "libmime"; +import libmime from "libmime"; // test type exports type MimeWordEncoding = libmime.MimeWordEncoding; @@ -67,3 +67,6 @@ libmime.buildHeaderParam("filename", Buffer.from("bla.txt"), 1, "UTF-8"); // $Ex libmime.detectExtension("image/jpeg"); // $ExpectType string libmime.detectMimeType("logo.jpg"); // $ExpectType string + +let anotherLibmimeInstance = new libmime.Libmime(); // $ExpectType Libmime +libmime === anotherLibmimeInstance; // Equality applies to same class of variables on typescript diff --git a/types/libmime/package.json b/types/libmime/package.json index 85ac30343f93da..afe3ff527f31b8 100644 --- a/types/libmime/package.json +++ b/types/libmime/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@types/libmime", - "version": "5.0.9999", + "version": "5.3.9999", "projects": [ "https://github.com/nodemailer/libmime" ], From b43b29da94519cf411cd695126e3aad8584fe0f0 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Sat, 13 Sep 2025 04:16:37 +0800 Subject: [PATCH 15/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73533=20feat?= =?UTF-8?q?(plotly.js):=20update=20Font=20Interface=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/plotly.js/index.d.ts | 27 +++++++++++++++---- types/plotly.js/test/index-tests.ts | 36 +++++++++++++++----------- types/plotly.js/v2/index.d.ts | 27 +++++++++++++++---- types/plotly.js/v2/test/index-tests.ts | 35 +++++++++++++++---------- 4 files changed, 86 insertions(+), 39 deletions(-) diff --git a/types/plotly.js/index.d.ts b/types/plotly.js/index.d.ts index a2f3d6c0fb9c12..3706785053d8b8 100644 --- a/types/plotly.js/index.d.ts +++ b/types/plotly.js/index.d.ts @@ -1938,7 +1938,8 @@ export interface Font { */ family: string; /** - * Sets the shape and color of the shadow behind text. "auto" places minimal shadow and applies contrast text font color. See https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow for additional options. + * Sets the shape and color of the shadow behind text. "auto" places minimal shadow and applies contrast text font color. + * See https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow for additional options. * @default "none" */ shadow: string; @@ -1950,9 +1951,9 @@ export interface Font { /** * Sets the weight (or boldness) of the font. * number between or equal to 1 and 1000 - * @default normal + * @default "normal" */ - weight: number; + weight: number | "normal" | "bold"; /** * Sets whether a font should be styled with a normal or italic face from its family. * @default "normal" @@ -1972,7 +1973,23 @@ export interface Font { * Sets the kind of decoration line(s) with text, such as an "under", "over" or "through" as well as combinations e.g. "under+over". * @default "none" */ - lineposition: "under" | "over" | "through" | "under+over" | "under+over+through" | "none"; + lineposition: + | "none" + | "under" + | "over" + | "through" + | "under+over" + | "over+under" + | "over+through" + | "through+over" + | "through+under" + | "under+through" + | "under+over+through" + | "under+through+over" + | "over+under+through" + | "over+through+under" + | "through+under+over" + | "through+over+under"; } export interface Edits { @@ -2900,7 +2917,7 @@ export interface Slider { /** * Sets the font of the slider step labels. */ - font: Font; + font: Partial; /** * Sets the background color of the slider grip * while dragging. diff --git a/types/plotly.js/test/index-tests.ts b/types/plotly.js/test/index-tests.ts index 5aad931a8c1093..ce3445f16036c3 100644 --- a/types/plotly.js/test/index-tests.ts +++ b/types/plotly.js/test/index-tests.ts @@ -1,8 +1,20 @@ import * as Plotly from "plotly.js"; -import { Config, Datum, Layout, newPlot, PlotData, Template, XAxisName, YAxisName } from "plotly.js"; +import { Config, Datum, Font, Layout, newPlot, PlotData, Template, XAxisName, YAxisName } from "plotly.js"; const graphDiv = "#test"; +const font: Font = { + color: "#fff", + family: "Arial, sans-serif", + lineposition: "under", + shadow: "auto", + size: 15, + style: "italic", + textcase: "word caps", + variant: "all-petite-caps", + weight: "bold", +}; + const config: Partial = { staticPlot: false, typesetMath: true, @@ -407,15 +419,15 @@ const config: Partial = { bgcolor: "#ffffff", bordercolor: "#444444", borderwidth: 1, - font: { size: 15, style: "italic" }, + font, groupclick: "togglegroup", - grouptitlefont: { size: 15 }, + grouptitlefont: font, itemclick: "toggleothers", itemdoubleclick: "toggle", itemsizing: "constant", itemwidth: 50, orientation: "h", - title: { font: { size: 15 }, side: "top right", text: "Legend Title" }, + title: { font, side: "top right", text: "Legend Title" }, tracegroupgap: 15, traceorder: "reversed+grouped", valign: "bottom", @@ -498,7 +510,7 @@ const config: Partial = { colorbar: { title: { text: "Test", - font: { size: 20, color: "#666", textcase: "lower" }, + font, side: "top", }, orientation: "v", @@ -534,7 +546,7 @@ const config: Partial = { ticklabelstep: 1, showticklabels: true, labelalias: "labelalias", - tickfont: { size: 10, color: "#666" }, + tickfont: font, tickangle: "auto", tickformat: "", tickformatstops: [], @@ -574,7 +586,7 @@ const config: Partial = { visible: true, prefix: "Date:", xanchor: "right", - font: { size: 20, color: "#666", variant: "all-small-caps" }, + font, }, steps: [ { @@ -724,10 +736,7 @@ const config: Partial = { const update = { title: { text: "some new title", - font: { - size: 1.2, - lineposition: "through", - }, + font, x: 0.9, pad: { t: 20, @@ -1147,10 +1156,7 @@ function rand() { type: "contour", contours: { coloring: "lines", - labelfont: { - color: "black", - family: "monospace", - }, + labelfont: font, showlabels: true, }, autocontour: true, diff --git a/types/plotly.js/v2/index.d.ts b/types/plotly.js/v2/index.d.ts index 7793ddc2385166..d23c561ae5a4b5 100644 --- a/types/plotly.js/v2/index.d.ts +++ b/types/plotly.js/v2/index.d.ts @@ -1988,7 +1988,8 @@ export interface Font { */ family: string; /** - * Sets the shape and color of the shadow behind text. "auto" places minimal shadow and applies contrast text font color. See https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow for additional options. + * Sets the shape and color of the shadow behind text. "auto" places minimal shadow and applies contrast text font color. + * See https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow for additional options. * @default "none" */ shadow: string; @@ -2000,9 +2001,9 @@ export interface Font { /** * Sets the weight (or boldness) of the font. * number between or equal to 1 and 1000 - * @default normal + * @default "normal" */ - weight: number; + weight: number | "normal" | "bold"; /** * Sets whether a font should be styled with a normal or italic face from its family. * @default "normal" @@ -2022,7 +2023,23 @@ export interface Font { * Sets the kind of decoration line(s) with text, such as an "under", "over" or "through" as well as combinations e.g. "under+over". * @default "none" */ - lineposition: "under" | "over" | "through" | "under+over" | "under+over+through" | "none"; + lineposition: + | "none" + | "under" + | "over" + | "through" + | "under+over" + | "over+under" + | "over+through" + | "through+over" + | "through+under" + | "under+through" + | "under+over+through" + | "under+through+over" + | "over+under+through" + | "over+through+under" + | "through+under+over" + | "through+over+under"; } export interface Edits { @@ -2950,7 +2967,7 @@ export interface Slider { /** * Sets the font of the slider step labels. */ - font: Font; + font: Partial; /** * Sets the background color of the slider grip * while dragging. diff --git a/types/plotly.js/v2/test/index-tests.ts b/types/plotly.js/v2/test/index-tests.ts index 6a9dae77544f63..1dc0fca6e35630 100644 --- a/types/plotly.js/v2/test/index-tests.ts +++ b/types/plotly.js/v2/test/index-tests.ts @@ -1,8 +1,20 @@ import * as Plotly from "plotly.js"; -import { Config, Datum, Layout, newPlot, PlotData, Template, XAxisName, YAxisName } from "plotly.js"; +import { Config, Datum, Font, Layout, newPlot, PlotData, Template, XAxisName, YAxisName } from "plotly.js"; const graphDiv = "#test"; +const font: Font = { + color: "#fff", + family: "Arial, sans-serif", + lineposition: "under", + shadow: "auto", + size: 15, + style: "italic", + textcase: "word caps", + variant: "all-petite-caps", + weight: "bold", +}; + const config: Partial = { staticPlot: false, typesetMath: true, @@ -428,15 +440,15 @@ const config: Partial = { bgcolor: "#ffffff", bordercolor: "#444444", borderwidth: 1, - font: { size: 15, style: "italic" }, + font, groupclick: "togglegroup", - grouptitlefont: { size: 15 }, + grouptitlefont: font, itemclick: "toggleothers", itemdoubleclick: "toggle", itemsizing: "constant", itemwidth: 50, orientation: "h", - title: { font: { size: 15 }, side: "top right", text: "Legend Title" }, + title: { font, side: "top right", text: "Legend Title" }, tracegroupgap: 15, traceorder: "reversed+grouped", valign: "bottom", @@ -511,7 +523,7 @@ const config: Partial = { colorbar: { title: { text: "Test", - font: { size: 20, color: "#666", textcase: "lower" }, + font, side: "top", }, orientation: "v", @@ -547,7 +559,7 @@ const config: Partial = { ticklabelstep: 1, showticklabels: true, labelalias: "labelalias", - tickfont: { size: 10, color: "#666" }, + tickfont: font, tickangle: "auto", tickformat: "", tickformatstops: [], @@ -585,7 +597,7 @@ const config: Partial = { visible: true, prefix: "Date:", xanchor: "right", - font: { size: 20, color: "#666", lineposition: "through" }, + font, }, steps: [ { @@ -731,9 +743,7 @@ const config: Partial = { const update = { title: { text: "some new title", - font: { - size: 1.2, - }, + font, x: 0.9, pad: { t: 20, @@ -1151,10 +1161,7 @@ function rand() { type: "contour", contours: { coloring: "lines", - labelfont: { - color: "black", - family: "monospace", - }, + labelfont: font, showlabels: true, }, autocontour: true, From 492a7ba2b1da8e389e4d3284cf7c5630f129fa40 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Sat, 13 Sep 2025 04:16:57 +0800 Subject: [PATCH 16/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73534=20feat?= =?UTF-8?q?(plotly.js):=20add=20MapboxBounds,=20supplement=20jsdoc=20for?= =?UTF-8?q?=20Mapbox=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/plotly.js/index.d.ts | 48 ++++++++++++++++++++++++++ types/plotly.js/test/index-tests.ts | 13 ++++++- types/plotly.js/v2/index.d.ts | 48 ++++++++++++++++++++++++++ types/plotly.js/v2/test/index-tests.ts | 13 ++++++- 4 files changed, 120 insertions(+), 2 deletions(-) diff --git a/types/plotly.js/index.d.ts b/types/plotly.js/index.d.ts index 3706785053d8b8..6d520a0de7284f 100644 --- a/types/plotly.js/index.d.ts +++ b/types/plotly.js/index.d.ts @@ -195,15 +195,63 @@ export interface MapboxLayers { name: string; templateitemname: string; } + +export interface MapboxBounds { + /** + * Sets the maximum longitude of the map (in degrees East) if `west`, `south` and `north` are declared. + */ + east: number; + /** + * Sets the maximum latitude of the map (in degrees North) if `east`, `west` and `south` are declared. + */ + north: number; + /** + * Sets the minimum latitude of the map (in degrees North) if `east`, `west` and `north` are declared. + */ + south: number; + /** + * Sets the minimum longitude of the map (in degrees East) if `east`, `south` and `north` are declared. + */ + west: number; +} + export interface Mapbox { domain: Partial; + /** + * Sets the mapbox access token to be used for this mapbox map. + * Alternatively, the mapbox access token can be set in the configuration options under `mapboxAccessToken`. + * Note that accessToken are only required when `style` (e.g with values : basic, streets, outdoors, light, dark, satellite, satellite-streets ) and/or a layout layer references the Mapbox server. + */ accesstoken: string; + /** + * Defines the map layers that are rendered by default below the trace layers defined in `data`, which are themselves by default rendered below the layers defined in `layout.mapbox.layers`. + * These layers can be defined either explicitly as a Mapbox Style object which can contain multiple layer definitions that load data from any public or private Tile Map Service (TMS or XYZ) or Web Map Service (WMS) or implicitly by using one of the built-in style objects which use WMSes which do not require any access tokens, or by using a default Mapbox style or custom Mapbox style URL, both of which require a Mapbox access token. + * Note that Mapbox access token can be set in the `accesstoken` attribute or in the `mapboxAccessToken` config option. + * Mapbox Style objects are of the form described in the Mapbox GL JS documentation available at https://docs.mapbox.com/mapbox-gl-js/style-spec. + * The built-in plotly.js styles objects are: carto-darkmatter, carto-positron, open-street-map, stamen-terrain, stamen-toner, stamen-watercolor, white-bg. + * The built-in Mapbox styles are: basic, streets, outdoors, light, dark, satellite, satellite-streets. + * Mapbox style URLs are of the form: mapbox://mapbox.mapbox-- + */ style: number | string; center: Partial; + /** + * Sets the zoom level of the map (mapbox.zoom). + */ zoom: number; + /** + * Sets the bearing angle of the map in degrees counter-clockwise from North (mapbox.bearing). + */ bearing: number; + bounds: MapboxBounds; + /** + * Sets the pitch angle of the map (in degrees, where *0* means perpendicular to the surface of the map) (mapbox.pitch). + */ pitch: number; layers: Array>; + /** + * Controls persistence of user-driven changes in the view: `center`, `zoom`, `bearing`, `pitch`. + * Defaults to `layout.uirevision`. + */ uirevision: number | string; uid: string; } diff --git a/types/plotly.js/test/index-tests.ts b/types/plotly.js/test/index-tests.ts index ce3445f16036c3..f153a1f2a5a20e 100644 --- a/types/plotly.js/test/index-tests.ts +++ b/types/plotly.js/test/index-tests.ts @@ -1232,7 +1232,18 @@ function rand() { const layout: Partial = { dragmode: "zoom", - mapbox: { style: "open-street-map", center: { lat: 0, lon: -0 }, zoom: 3 }, + mapbox: { + accesstoken: "accesstoken", + domain: { x: [0], y: [0], row: 0, column: 0 }, + style: "open-street-map", + center: { lat: 0, lon: -0 }, + zoom: 3, + bearing: 30, + bounds: { east: 0, west: 0, south: 0, north: 0 }, + pitch: 0, + layers: [], + uirevision: "uirevision", + }, margin: { r: 0, t: 0, b: 0, l: 0 }, }; diff --git a/types/plotly.js/v2/index.d.ts b/types/plotly.js/v2/index.d.ts index d23c561ae5a4b5..65ceb554fbb546 100644 --- a/types/plotly.js/v2/index.d.ts +++ b/types/plotly.js/v2/index.d.ts @@ -195,15 +195,63 @@ export interface MapboxLayers { name: string; templateitemname: string; } + +export interface MapboxBounds { + /** + * Sets the maximum longitude of the map (in degrees East) if `west`, `south` and `north` are declared. + */ + east: number; + /** + * Sets the maximum latitude of the map (in degrees North) if `east`, `west` and `south` are declared. + */ + north: number; + /** + * Sets the minimum latitude of the map (in degrees North) if `east`, `west` and `north` are declared. + */ + south: number; + /** + * Sets the minimum longitude of the map (in degrees East) if `east`, `south` and `north` are declared. + */ + west: number; +} + export interface Mapbox { domain: Partial; + /** + * Sets the mapbox access token to be used for this mapbox map. + * Alternatively, the mapbox access token can be set in the configuration options under `mapboxAccessToken`. + * Note that accessToken are only required when `style` (e.g with values : basic, streets, outdoors, light, dark, satellite, satellite-streets ) and/or a layout layer references the Mapbox server. + */ accesstoken: string; + /** + * Defines the map layers that are rendered by default below the trace layers defined in `data`, which are themselves by default rendered below the layers defined in `layout.mapbox.layers`. + * These layers can be defined either explicitly as a Mapbox Style object which can contain multiple layer definitions that load data from any public or private Tile Map Service (TMS or XYZ) or Web Map Service (WMS) or implicitly by using one of the built-in style objects which use WMSes which do not require any access tokens, or by using a default Mapbox style or custom Mapbox style URL, both of which require a Mapbox access token. + * Note that Mapbox access token can be set in the `accesstoken` attribute or in the `mapboxAccessToken` config option. + * Mapbox Style objects are of the form described in the Mapbox GL JS documentation available at https://docs.mapbox.com/mapbox-gl-js/style-spec. + * The built-in plotly.js styles objects are: carto-darkmatter, carto-positron, open-street-map, stamen-terrain, stamen-toner, stamen-watercolor, white-bg. + * The built-in Mapbox styles are: basic, streets, outdoors, light, dark, satellite, satellite-streets. + * Mapbox style URLs are of the form: mapbox://mapbox.mapbox-- + */ style: number | string; center: Partial; + /** + * Sets the zoom level of the map (mapbox.zoom). + */ zoom: number; + /** + * Sets the bearing angle of the map in degrees counter-clockwise from North (mapbox.bearing). + */ bearing: number; + bounds: MapboxBounds; + /** + * Sets the pitch angle of the map (in degrees, where *0* means perpendicular to the surface of the map) (mapbox.pitch). + */ pitch: number; layers: Array>; + /** + * Controls persistence of user-driven changes in the view: `center`, `zoom`, `bearing`, `pitch`. + * Defaults to `layout.uirevision`. + */ uirevision: number | string; uid: string; } diff --git a/types/plotly.js/v2/test/index-tests.ts b/types/plotly.js/v2/test/index-tests.ts index 1dc0fca6e35630..109e852acc1a05 100644 --- a/types/plotly.js/v2/test/index-tests.ts +++ b/types/plotly.js/v2/test/index-tests.ts @@ -1237,7 +1237,18 @@ function rand() { const layout: Partial = { dragmode: "zoom", - mapbox: { style: "open-street-map", center: { lat: 0, lon: -0 }, zoom: 3 }, + mapbox: { + accesstoken: "accesstoken", + domain: { x: [0], y: [0], row: 0, column: 0 }, + style: "open-street-map", + center: { lat: 0, lon: -0 }, + zoom: 3, + bearing: 30, + bounds: { east: 0, west: 0, south: 0, north: 0 }, + pitch: 0, + layers: [], + uirevision: "uirevision", + }, margin: { r: 0, t: 0, b: 0, l: 0 }, }; From 2840242c68e7053109a7b4eb0e1c3adf802bb4b6 Mon Sep 17 00:00:00 2001 From: SongYoungUk Date: Sat, 13 Sep 2025 06:49:17 +0900 Subject: [PATCH 17/17] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#73616=20feat?= =?UTF-8?q?(emscripten)=20:=20Update=20`writeFile`=20API=20by=20@R3gardles?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/emscripten/emscripten-tests.ts | 10 ++++++++++ types/emscripten/index.d.ts | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/types/emscripten/emscripten-tests.ts b/types/emscripten/emscripten-tests.ts index 03c1863241755f..62d644f3671929 100644 --- a/types/emscripten/emscripten-tests.ts +++ b/types/emscripten/emscripten-tests.ts @@ -108,6 +108,16 @@ function FSTest(): void { FS.symlink("file", "link"); FS.writeFile("/foobar.txt", "Hello, world"); + + // Test writeFile with extended options + FS.writeFile("/test-with-mode.txt", "content", { mode: parseInt("0644", 8) }); + FS.writeFile("/test-with-flags.txt", "content", { flags: "w+" }); + FS.writeFile("/test-with-canown.txt", "content", { canOwn: true }); + FS.writeFile("/test-with-all-opts.txt", "content", { + flags: "w", + mode: parseInt("0755", 8), + canOwn: false, + }); FS.unlink("/foobar.txt"); FS.writeFile("file", "foobar"); diff --git a/types/emscripten/index.d.ts b/types/emscripten/index.d.ts index 17d83f5a52453d..87082b3141cac1 100644 --- a/types/emscripten/index.d.ts +++ b/types/emscripten/index.d.ts @@ -336,7 +336,11 @@ declare namespace FS { function readFile(path: string, opts: { encoding: "binary"; flags?: string | undefined }): Uint8Array; function readFile(path: string, opts: { encoding: "utf8"; flags?: string | undefined }): string; function readFile(path: string, opts?: { flags?: string | undefined }): Uint8Array; - function writeFile(path: string, data: string | ArrayBufferView, opts?: { flags?: string | undefined }): void; + function writeFile( + path: string, + data: string | ArrayBufferView, + opts?: { flags?: string | undefined; mode?: number | undefined; canOwn?: boolean | undefined }, + ): void; // // module-level FS code