mirror of
https://github.com/sass/sass.git
synced 2024-09-21 10:37:22 +00:00
Refactor js-api.d.ts into multiple files
This commit is contained in:
parent
43055d8ef2
commit
6f7fbe6b8a
2
accepted/js-logger.d.ts
vendored
2
accepted/js-logger.d.ts
vendored
@ -53,7 +53,7 @@ import {URL} from 'url';
|
||||
import '../spec/js-api';
|
||||
import './new-js-api';
|
||||
|
||||
declare module '../spec/js-api' {
|
||||
declare module '../spec/js-api/legacy/options' {
|
||||
interface _Options {
|
||||
/**
|
||||
* An object that provides callbacks for the compiler to use in lieu of its
|
||||
|
321
spec/js-api.d.ts
vendored
321
spec/js-api.d.ts
vendored
@ -1,321 +0,0 @@
|
||||
/**
|
||||
* # JavaScript API
|
||||
*
|
||||
* Sass implementations that are available for use via JavaScript must expose
|
||||
* the following JavaScript API. As with the rest of this specification, they
|
||||
* must not add custom extensions that aren't shared across all implementations.
|
||||
*
|
||||
* > Having a shared, consistent API makes it easy for users to move between
|
||||
* > Sass implementations with minimal disruption, and for build system plugins
|
||||
* > to seamlessly work with multiple implementations.
|
||||
*
|
||||
* The JS API is specified as a TypeScript type declaration. Implementations
|
||||
* must adhere to this declaration and to the behavioral specifications written
|
||||
* in JSDoc comments on the declarations. Implementations may throw errors when
|
||||
* user code passes in values that don't adhere to the type declaration, but
|
||||
* unless otherwise indicated they may also handle these values in undefined
|
||||
* ways in accordance with the common JavaScript pattern of avoiding explicit
|
||||
* type checks. This must not be used as a way of adding custom extensions that
|
||||
* aren't shared across all implementations.
|
||||
*
|
||||
* As with other sections of this specification, the specification of the JS API
|
||||
* is incomplete, and is added to *lazily*. This means that portions of the
|
||||
* spec—particularly the documentation comments that serve as a behavioral
|
||||
* specification—are only written when they're necessary as background for new
|
||||
* API proposals.
|
||||
*/
|
||||
|
||||
/** ## API */
|
||||
|
||||
/** ### Options */
|
||||
|
||||
/**
|
||||
* All the options for a Sass compilation except those that specify the specific
|
||||
* input format.
|
||||
*
|
||||
* This is only exported so that it can be modified by proposals for new
|
||||
* features. It should not be referred to by user code.
|
||||
*/
|
||||
export interface _Options<sync = 'sync' | 'async'> {
|
||||
includePaths?: string[];
|
||||
indentedSyntax?: boolean;
|
||||
indentType?: 'space' | 'tab';
|
||||
indentWidth?: number;
|
||||
linefeed?: 'cr' | 'crlf' | 'lf' | 'lfcr';
|
||||
omitSourceMapUrl?: boolean;
|
||||
outFile?: string;
|
||||
outputStyle?: 'compressed' | 'expanded' | 'nested' | 'compact';
|
||||
sourceMap?: boolean | string;
|
||||
sourceMapContents?: boolean;
|
||||
sourceMapEmbed?: boolean;
|
||||
sourceMapRoot?: string;
|
||||
importer?: Importer<sync> | Importer<sync>[];
|
||||
functions?: {[key: string]: CustomFunction<sync>};
|
||||
|
||||
/**
|
||||
* If `true`, the compiler may prepend `@charset "UTF-8";` or U+FEFF
|
||||
* (byte-order marker) if it outputs non-ASCII CSS.
|
||||
*
|
||||
* If `false`, the compiler never emits these byte sequences. This is ideal
|
||||
* when concatenating or embedding in HTML `<style>` tags. (The output will
|
||||
* still be UTF-8.)
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
charset?: boolean;
|
||||
|
||||
/**
|
||||
* If true, the compiler must not print deprecation warnings for stylesheets
|
||||
* that are transitively loaded through an import path or importer.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
quietDeps?: boolean;
|
||||
|
||||
/**
|
||||
* If `true`, the compiler must print every single deprecation warning it
|
||||
* encounters.
|
||||
*
|
||||
* If `false`, the compiler may choose not to print repeated deprecation
|
||||
* warnings.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
verbose?: boolean;
|
||||
}
|
||||
|
||||
export type Options<sync = 'sync' | 'async'> = _Options<sync> &
|
||||
(
|
||||
| {
|
||||
file: string;
|
||||
}
|
||||
| {
|
||||
data: string;
|
||||
file?: string;
|
||||
}
|
||||
);
|
||||
|
||||
/** #### Shared Plugin Infrastructure */
|
||||
|
||||
/**
|
||||
* The shared interface for the `this` keyword for custom importers and custom
|
||||
* functions. The implementation must invoke importers and custom functions with
|
||||
* an appropriate `this`.
|
||||
*/
|
||||
interface PluginThis {
|
||||
options: {
|
||||
/** The `file` option passed to the `render()` or `renderSync()` call. */
|
||||
file?: string;
|
||||
|
||||
/** The `data` option passed to the `render()` or `renderSync()` call. */
|
||||
data?: string;
|
||||
|
||||
/**
|
||||
* A string that contains the current working directory followed by strings
|
||||
* passed in the `includePaths` option, separated by `";"` on Windows and
|
||||
* `":"` elsewhere.
|
||||
*/
|
||||
includePaths: string;
|
||||
|
||||
precision: 10;
|
||||
|
||||
/**
|
||||
* An integer. The specific semantics of this are left up to the
|
||||
* implementation. (The reference implementation always returns 1.)
|
||||
*/
|
||||
style: number;
|
||||
|
||||
/**
|
||||
* The number 1 if the `indentType` option was `tab`. The number 0
|
||||
* otherwise.
|
||||
*/
|
||||
indentType: 1 | 0;
|
||||
|
||||
/**
|
||||
* An integer indicating the number of spaces or tabs emitted by the
|
||||
* compiler for each level of indentation.
|
||||
*/
|
||||
indentWidth: number;
|
||||
|
||||
/**
|
||||
* The `linefeed` option passed to the `render()` or `renderSync()`, or
|
||||
* `'lf'` if no value was passed.
|
||||
*/
|
||||
linefeed: 'cr' | 'crlf' | 'lf' | 'lfcr';
|
||||
|
||||
result: {
|
||||
stats: {
|
||||
/**
|
||||
* The number of milliseconds since the Unix epoch (1 January 1970
|
||||
* 00:00:00 UT) at the point at which the user called `render()` or
|
||||
* `renderSync()`.
|
||||
*/
|
||||
start: number;
|
||||
|
||||
/**
|
||||
* The `file` option passed to the `render()` call, or the string
|
||||
* `"data"` if no file was passed.
|
||||
*/
|
||||
entry: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/** #### Importer Plugins */
|
||||
|
||||
/**
|
||||
* The interface for the `this` keyword for custom importers. The implementation
|
||||
* must invoke importers with an appropriate `this`.
|
||||
*/
|
||||
interface ImporterThis extends PluginThis {
|
||||
/**
|
||||
* `true` if this importer invocation was caused by an `@import` statement and
|
||||
* `false` otherwise.
|
||||
*
|
||||
* > This allows importers to look for `.import.scss` stylesheets if and only
|
||||
* > if an `@import` is being resolved.
|
||||
*/
|
||||
fromImport: boolean;
|
||||
}
|
||||
|
||||
type _SyncImporter = (
|
||||
this: ImporterThis,
|
||||
url: string,
|
||||
prev: string
|
||||
) => {file: string} | {contents: string};
|
||||
|
||||
type _AsyncImporter = (
|
||||
this: ImporterThis,
|
||||
url: string,
|
||||
prev: string,
|
||||
done: (data: {file: string} | {contents: string} | Error) => void
|
||||
) => void;
|
||||
|
||||
export type Importer<sync = 'sync' | 'async'> =
|
||||
| _SyncImporter
|
||||
| (sync extends 'async' ? _AsyncImporter : never);
|
||||
|
||||
/** #### Function Plugins */
|
||||
|
||||
type _SyncFunction = (this: PluginThis, ...args: Value[]) => Value;
|
||||
|
||||
type _AsyncFunction = (
|
||||
this: PluginThis,
|
||||
...args: [...Value[], (type: Value) => void]
|
||||
) => void;
|
||||
|
||||
export type CustomFunction<sync = 'sync' | 'async'> =
|
||||
| _SyncFunction
|
||||
| (sync extends 'async' ? _AsyncFunction : never);
|
||||
|
||||
export type Value =
|
||||
| types.Null
|
||||
| types.Number
|
||||
| types.String
|
||||
| types.Boolean
|
||||
| types.HslColor
|
||||
| types.RgbColor
|
||||
| types.List
|
||||
| types.Map;
|
||||
|
||||
export namespace types {
|
||||
export class Null {
|
||||
static NULL: Null;
|
||||
}
|
||||
|
||||
export class Number {
|
||||
constructor(value: number, unit?: string);
|
||||
getValue(): number;
|
||||
setValue(value: number): void;
|
||||
getUnit(): string;
|
||||
setUnit(unit: string): void;
|
||||
}
|
||||
|
||||
export class String {
|
||||
constructor(value: string);
|
||||
getValue(): string;
|
||||
setValue(value: string): void;
|
||||
}
|
||||
|
||||
export class Boolean<T extends boolean = boolean> {
|
||||
constructor(value: T);
|
||||
getValue(): T;
|
||||
static readonly TRUE: Boolean<true>;
|
||||
static readonly FALSE: Boolean<false>;
|
||||
}
|
||||
|
||||
export class HslColor {
|
||||
constructor(h: number, s: number, l: number, a?: number);
|
||||
getH(): number;
|
||||
setH(value: number): void;
|
||||
getS(): number;
|
||||
setS(value: number): void;
|
||||
getL(): number;
|
||||
setL(value: number): void;
|
||||
getA(): number;
|
||||
setA(value: number): void;
|
||||
}
|
||||
|
||||
export class RgbColor {
|
||||
constructor(r: number, g: number, b: number, a?: number);
|
||||
getR(): number;
|
||||
setR(value: number): void;
|
||||
getG(): number;
|
||||
setG(value: number): void;
|
||||
getB(): number;
|
||||
setB(value: number): void;
|
||||
getA(): number;
|
||||
setA(value: number): void;
|
||||
}
|
||||
|
||||
export class List {
|
||||
constructor(length: number, commaSeparator?: boolean);
|
||||
getValue(index: number): Value | undefined;
|
||||
setValue(index: number, value: Value): void;
|
||||
getSeparator(): boolean;
|
||||
setSeparator(isComma: boolean): void;
|
||||
getLength(): number;
|
||||
}
|
||||
|
||||
export class Map {
|
||||
constructor(length: number);
|
||||
getValue(index: number): Value;
|
||||
setValue(index: number, value: Value): void;
|
||||
getKey(index: number): Value;
|
||||
setKey(index: number, key: Value): void;
|
||||
getLength(): number;
|
||||
}
|
||||
}
|
||||
|
||||
/** ### Render */
|
||||
|
||||
export interface Result {
|
||||
css: Buffer;
|
||||
map?: Buffer;
|
||||
stats: {
|
||||
entry: string;
|
||||
start: number;
|
||||
end: number;
|
||||
duration: number;
|
||||
includedFiles: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export function renderSync(options: Options<'sync'>): Result;
|
||||
|
||||
export function render(
|
||||
options: Options<'async'>,
|
||||
callback: (exception: SassException, result: Result) => void
|
||||
): void;
|
||||
|
||||
/** ### Exceptions */
|
||||
|
||||
export interface SassException extends Error {
|
||||
message: string;
|
||||
formatted: string;
|
||||
line: number;
|
||||
column: number;
|
||||
status: number;
|
||||
file: string;
|
||||
}
|
31
spec/js-api/index.d.ts
vendored
Normal file
31
spec/js-api/index.d.ts
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* # JavaScript API
|
||||
*
|
||||
* Sass implementations that are available for use via JavaScript must expose
|
||||
* the following JavaScript API. As with the rest of this specification, they
|
||||
* must not add custom extensions that aren't shared across all implementations.
|
||||
*
|
||||
* > Having a shared, consistent API makes it easy for users to move between
|
||||
* > Sass implementations with minimal disruption, and for build system plugins
|
||||
* > to seamlessly work with multiple implementations.
|
||||
*
|
||||
* The JS API is specified as a TypeScript type declaration. Implementations
|
||||
* must adhere to this declaration and to the behavioral specifications written
|
||||
* in JSDoc comments on the declarations. Implementations may throw errors when
|
||||
* user code passes in values that don't adhere to the type declaration, but
|
||||
* unless otherwise indicated they may also handle these values in undefined
|
||||
* ways in accordance with the common JavaScript pattern of avoiding explicit
|
||||
* type checks. This must not be used as a way of adding custom extensions that
|
||||
* aren't shared across all implementations.
|
||||
*
|
||||
* As with other sections of this specification, the specification of the JS API
|
||||
* is incomplete, and is added to *lazily*. This means that portions of the
|
||||
* spec—particularly the documentation comments that serve as a behavioral
|
||||
* specification—are only written when they're necessary as background for new
|
||||
* API proposals. */
|
||||
|
||||
export {SassException} from './legacy/exception';
|
||||
export {CustomFunction, Value, types} from './legacy/function';
|
||||
export {Importer} from './legacy/importer';
|
||||
export {Options} from './legacy/options';
|
||||
export {Result, render, renderSync} from './legacy/render';
|
8
spec/js-api/legacy/exception.d.ts
vendored
Normal file
8
spec/js-api/legacy/exception.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
export interface SassException extends Error {
|
||||
message: string;
|
||||
formatted: string;
|
||||
line: number;
|
||||
column: number;
|
||||
status: number;
|
||||
file: string;
|
||||
}
|
91
spec/js-api/legacy/function.d.ts
vendored
Normal file
91
spec/js-api/legacy/function.d.ts
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
import {PluginThis} from './plugin_this';
|
||||
|
||||
type _SyncFunction = (this: PluginThis, ...args: Value[]) => Value;
|
||||
|
||||
type _AsyncFunction = (
|
||||
this: PluginThis,
|
||||
...args: [...Value[], (type: Value) => void]
|
||||
) => void;
|
||||
|
||||
export type CustomFunction<sync = 'sync' | 'async'> =
|
||||
| _SyncFunction
|
||||
| (sync extends 'async' ? _AsyncFunction : never);
|
||||
|
||||
export type Value =
|
||||
| types.Null
|
||||
| types.Number
|
||||
| types.String
|
||||
| types.Boolean
|
||||
| types.HslColor
|
||||
| types.RgbColor
|
||||
| types.List
|
||||
| types.Map;
|
||||
|
||||
export namespace types {
|
||||
export class Null {
|
||||
static NULL: Null;
|
||||
}
|
||||
|
||||
export class Number {
|
||||
constructor(value: number, unit?: string);
|
||||
getValue(): number;
|
||||
setValue(value: number): void;
|
||||
getUnit(): string;
|
||||
setUnit(unit: string): void;
|
||||
}
|
||||
|
||||
export class String {
|
||||
constructor(value: string);
|
||||
getValue(): string;
|
||||
setValue(value: string): void;
|
||||
}
|
||||
|
||||
export class Boolean<T extends boolean = boolean> {
|
||||
constructor(value: T);
|
||||
getValue(): T;
|
||||
static readonly TRUE: Boolean<true>;
|
||||
static readonly FALSE: Boolean<false>;
|
||||
}
|
||||
|
||||
export class HslColor {
|
||||
constructor(h: number, s: number, l: number, a?: number);
|
||||
getH(): number;
|
||||
setH(value: number): void;
|
||||
getS(): number;
|
||||
setS(value: number): void;
|
||||
getL(): number;
|
||||
setL(value: number): void;
|
||||
getA(): number;
|
||||
setA(value: number): void;
|
||||
}
|
||||
|
||||
export class RgbColor {
|
||||
constructor(r: number, g: number, b: number, a?: number);
|
||||
getR(): number;
|
||||
setR(value: number): void;
|
||||
getG(): number;
|
||||
setG(value: number): void;
|
||||
getB(): number;
|
||||
setB(value: number): void;
|
||||
getA(): number;
|
||||
setA(value: number): void;
|
||||
}
|
||||
|
||||
export class List {
|
||||
constructor(length: number, commaSeparator?: boolean);
|
||||
getValue(index: number): Value | undefined;
|
||||
setValue(index: number, value: Value): void;
|
||||
getSeparator(): boolean;
|
||||
setSeparator(isComma: boolean): void;
|
||||
getLength(): number;
|
||||
}
|
||||
|
||||
export class Map {
|
||||
constructor(length: number);
|
||||
getValue(index: number): Value;
|
||||
setValue(index: number, value: Value): void;
|
||||
getKey(index: number): Value;
|
||||
setKey(index: number, key: Value): void;
|
||||
getLength(): number;
|
||||
}
|
||||
}
|
33
spec/js-api/legacy/importer.d.ts
vendored
Normal file
33
spec/js-api/legacy/importer.d.ts
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
import {PluginThis} from './plugin_this';
|
||||
|
||||
/**
|
||||
* The interface for the `this` keyword for custom importers. The implementation
|
||||
* must invoke importers with an appropriate `this`.
|
||||
*/
|
||||
interface ImporterThis extends PluginThis {
|
||||
/**
|
||||
* `true` if this importer invocation was caused by an `@import` statement and
|
||||
* `false` otherwise.
|
||||
*
|
||||
* > This allows importers to look for `.import.scss` stylesheets if and only
|
||||
* > if an `@import` is being resolved.
|
||||
*/
|
||||
fromImport: boolean;
|
||||
}
|
||||
|
||||
type _SyncImporter = (
|
||||
this: ImporterThis,
|
||||
url: string,
|
||||
prev: string
|
||||
) => {file: string} | {contents: string};
|
||||
|
||||
type _AsyncImporter = (
|
||||
this: ImporterThis,
|
||||
url: string,
|
||||
prev: string,
|
||||
done: (data: {file: string} | {contents: string} | Error) => void
|
||||
) => void;
|
||||
|
||||
export type Importer<sync = 'sync' | 'async'> =
|
||||
| _SyncImporter
|
||||
| (sync extends 'async' ? _AsyncImporter : never);
|
68
spec/js-api/legacy/options.d.ts
vendored
Normal file
68
spec/js-api/legacy/options.d.ts
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
import {Importer} from './importer';
|
||||
import {CustomFunction} from './function';
|
||||
|
||||
/**
|
||||
* All the options for a Sass compilation except those that specify the specific
|
||||
* input format.
|
||||
*
|
||||
* This is only exported so that it can be modified by proposals for new
|
||||
* features. It should not be referred to by user code.
|
||||
*/
|
||||
export interface _Options<sync = 'sync' | 'async'> {
|
||||
includePaths?: string[];
|
||||
indentedSyntax?: boolean;
|
||||
indentType?: 'space' | 'tab';
|
||||
indentWidth?: number;
|
||||
linefeed?: 'cr' | 'crlf' | 'lf' | 'lfcr';
|
||||
omitSourceMapUrl?: boolean;
|
||||
outFile?: string;
|
||||
outputStyle?: 'compressed' | 'expanded' | 'nested' | 'compact';
|
||||
sourceMap?: boolean | string;
|
||||
sourceMapContents?: boolean;
|
||||
sourceMapEmbed?: boolean;
|
||||
sourceMapRoot?: string;
|
||||
importer?: Importer<sync> | Importer<sync>[];
|
||||
functions?: {[key: string]: CustomFunction<sync>};
|
||||
|
||||
/**
|
||||
* If `true`, the compiler may prepend `@charset "UTF-8";` or U+FEFF
|
||||
* (byte-order marker) if it outputs non-ASCII CSS.
|
||||
*
|
||||
* If `false`, the compiler never emits these byte sequences. This is ideal
|
||||
* when concatenating or embedding in HTML `<style>` tags. (The output will
|
||||
* still be UTF-8.)
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
charset?: boolean;
|
||||
|
||||
/**
|
||||
* If true, the compiler must not print deprecation warnings for stylesheets
|
||||
* that are transitively loaded through an import path or importer.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
quietDeps?: boolean;
|
||||
|
||||
/**
|
||||
* If `true`, the compiler must print every single deprecation warning it
|
||||
* encounters.
|
||||
*
|
||||
* If `false`, the compiler may choose not to print repeated deprecation
|
||||
* warnings.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
verbose?: boolean;
|
||||
}
|
||||
|
||||
export type Options<sync = 'sync' | 'async'> = _Options<sync> &
|
||||
(
|
||||
| {
|
||||
file: string;
|
||||
}
|
||||
| {
|
||||
data: string;
|
||||
file?: string;
|
||||
}
|
||||
);
|
64
spec/js-api/legacy/plugin_this.d.ts
vendored
Normal file
64
spec/js-api/legacy/plugin_this.d.ts
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* The shared interface for the `this` keyword for custom importers and custom
|
||||
* functions. The implementation must invoke importers and custom functions with
|
||||
* an appropriate `this`.
|
||||
*/
|
||||
export interface PluginThis {
|
||||
options: {
|
||||
/** The `file` option passed to the `render()` or `renderSync()` call. */
|
||||
file?: string;
|
||||
|
||||
/** The `data` option passed to the `render()` or `renderSync()` call. */
|
||||
data?: string;
|
||||
|
||||
/**
|
||||
* A string that contains the current working directory followed by strings
|
||||
* passed in the `includePaths` option, separated by `";"` on Windows and
|
||||
* `":"` elsewhere.
|
||||
*/
|
||||
includePaths: string;
|
||||
|
||||
precision: 10;
|
||||
|
||||
/**
|
||||
* An integer. The specific semantics of this are left up to the
|
||||
* implementation. (The reference implementation always returns 1.)
|
||||
*/
|
||||
style: number;
|
||||
|
||||
/**
|
||||
* The number 1 if the `indentType` option was `tab`. The number 0
|
||||
* otherwise.
|
||||
*/
|
||||
indentType: 1 | 0;
|
||||
|
||||
/**
|
||||
* An integer indicating the number of spaces or tabs emitted by the
|
||||
* compiler for each level of indentation.
|
||||
*/
|
||||
indentWidth: number;
|
||||
|
||||
/**
|
||||
* The `linefeed` option passed to the `render()` or `renderSync()`, or
|
||||
* `'lf'` if no value was passed.
|
||||
*/
|
||||
linefeed: 'cr' | 'crlf' | 'lf' | 'lfcr';
|
||||
|
||||
result: {
|
||||
stats: {
|
||||
/**
|
||||
* The number of milliseconds since the Unix epoch (1 January 1970
|
||||
* 00:00:00 UT) at the point at which the user called `render()` or
|
||||
* `renderSync()`.
|
||||
*/
|
||||
start: number;
|
||||
|
||||
/**
|
||||
* The `file` option passed to the `render()` call, or the string
|
||||
* `"data"` if no file was passed.
|
||||
*/
|
||||
entry: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
21
spec/js-api/legacy/render.d.ts
vendored
Normal file
21
spec/js-api/legacy/render.d.ts
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
import {SassException} from './exception';
|
||||
import {Options} from './options';
|
||||
|
||||
export interface Result {
|
||||
css: Buffer;
|
||||
map?: Buffer;
|
||||
stats: {
|
||||
entry: string;
|
||||
start: number;
|
||||
end: number;
|
||||
duration: number;
|
||||
includedFiles: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export function renderSync(options: Options<'sync'>): Result;
|
||||
|
||||
export function render(
|
||||
options: Options<'async'>,
|
||||
callback: (exception: SassException, result: Result) => void
|
||||
): void;
|
Loading…
Reference in New Issue
Block a user