mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-17 12:03:31 +01:00
fix(website): remove several obsolete special handling of dtypes (#10898)
* fix(website): remove several obsolete special handling of dtypes * fix: reduce hardcoded places * chore: api-extractor.json setting mainEntryPointName
This commit is contained in:
@@ -17,24 +17,21 @@ export function EntryPointSelect({
|
|||||||
const { entryPoints: parsedEntrypoints } = parseDocsPathParams(params.item as string[] | undefined);
|
const { entryPoints: parsedEntrypoints } = parseDocsPathParams(params.item as string[] | undefined);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select aria-label="Select an entrypoint" defaultSelectedKey={parsedEntrypoints.join('/')}>
|
||||||
aria-label="Select an entrypoint"
|
|
||||||
defaultSelectedKey={parsedEntrypoints.length ? parsedEntrypoints.join('/') : 'global'}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="bg-[#f3f3f4] dark:bg-[#121214]" />
|
<SelectTrigger className="bg-[#f3f3f4] dark:bg-[#121214]" />
|
||||||
<SelectList classNames={{ popover: 'bg-[#f3f3f4] dark:bg-[#28282d]' }} items={entryPoints}>
|
<SelectList classNames={{ popover: 'bg-[#f3f3f4] dark:bg-[#28282d]' }} items={entryPoints}>
|
||||||
{(item) => (
|
{(item) => (
|
||||||
<SelectOption
|
<SelectOption
|
||||||
className="dark:pressed:bg-[#313135] bg-[#f3f3f4] dark:bg-[#28282d] dark:hover:bg-[#313135]"
|
className="dark:pressed:bg-[#313135] bg-[#f3f3f4] dark:bg-[#28282d] dark:hover:bg-[#313135]"
|
||||||
href={`/docs/packages/${params.packageName}/${params.version}/${item.entryPoint}`}
|
href={`/docs/packages/${params.packageName}/${params.version}/${item.entryPoint}`}
|
||||||
id={item.entryPoint || 'global'}
|
id={item.entryPoint}
|
||||||
key={item.entryPoint || 'global'}
|
key={item.entryPoint}
|
||||||
onHoverStart={() =>
|
onHoverStart={() =>
|
||||||
router.prefetch(`/docs/packages/${params.packageName}/${params.version}/${item.entryPoint}`)
|
router.prefetch(`/docs/packages/${params.packageName}/${params.version}/${item.entryPoint}`)
|
||||||
}
|
}
|
||||||
textValue={item.entryPoint || 'global'}
|
textValue={item.entryPoint}
|
||||||
>
|
>
|
||||||
{item.entryPoint || 'global'}
|
{item.entryPoint}
|
||||||
</SelectOption>
|
</SelectOption>
|
||||||
)}
|
)}
|
||||||
</SelectList>
|
</SelectList>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Cloudflare from 'cloudflare';
|
import Cloudflare from 'cloudflare';
|
||||||
import { NextResponse, type NextRequest } from 'next/server';
|
import { NextResponse, type NextRequest } from 'next/server';
|
||||||
import { PACKAGES } from './util/constants';
|
import { DEFAULT_ENTRY_POINT, PACKAGES, PACKAGES_WITH_ENTRY_POINTS } from './util/constants';
|
||||||
import { ENV } from './util/env';
|
import { ENV } from './util/env';
|
||||||
|
|
||||||
const client = new Cloudflare({
|
const client = new Cloudflare({
|
||||||
@@ -8,7 +8,12 @@ const client = new Cloudflare({
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function fetchLatestVersion(packageName: string): Promise<string> {
|
async function fetchLatestVersion(packageName: string): Promise<string> {
|
||||||
|
const hasEntryPoints = PACKAGES_WITH_ENTRY_POINTS.includes(packageName);
|
||||||
if (ENV.IS_LOCAL_DEV) {
|
if (ENV.IS_LOCAL_DEV) {
|
||||||
|
if (hasEntryPoints) {
|
||||||
|
return ['main', ...DEFAULT_ENTRY_POINT].join('/');
|
||||||
|
}
|
||||||
|
|
||||||
return 'main';
|
return 'main';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +24,7 @@ async function fetchLatestVersion(packageName: string): Promise<string> {
|
|||||||
params: [packageName],
|
params: [packageName],
|
||||||
});
|
});
|
||||||
|
|
||||||
return (result[0]?.results as { version: string }[] | undefined)?.[0]?.version ?? 'main';
|
return `${(result[0]?.results as { version: string }[] | undefined)?.[0]?.version ?? 'main'}${hasEntryPoints ? ['', ...DEFAULT_ENTRY_POINT].join('/') : ''}`;
|
||||||
} catch {
|
} catch {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,5 +16,7 @@ export const PACKAGES = [
|
|||||||
|
|
||||||
export const PACKAGES_WITH_ENTRY_POINTS = ['discord-api-types'];
|
export const PACKAGES_WITH_ENTRY_POINTS = ['discord-api-types'];
|
||||||
|
|
||||||
|
export const DEFAULT_ENTRY_POINT = ['v10'];
|
||||||
|
|
||||||
export const DESCRIPTION =
|
export const DESCRIPTION =
|
||||||
"discord.js is a powerful Node.js module that allows you to interact with the Discord API very easily. It takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code significantly tidier and easier to comprehend.";
|
"discord.js is a powerful Node.js module that allows you to interact with the Discord API very easily. It takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code significantly tidier and easier to comprehend.";
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { DEFAULT_ENTRY_POINT } from './constants';
|
||||||
|
|
||||||
export function parseDocsPathParams(item: string[] | undefined): {
|
export function parseDocsPathParams(item: string[] | undefined): {
|
||||||
entryPoints: string[];
|
entryPoints: string[];
|
||||||
foundItem: string | undefined;
|
foundItem: string | undefined;
|
||||||
@@ -10,7 +12,7 @@ export function parseDocsPathParams(item: string[] | undefined): {
|
|||||||
const hasTypeMarker = lastElement?.includes('%3A');
|
const hasTypeMarker = lastElement?.includes('%3A');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entryPoints: hasTypeMarker ? item.slice(0, -1) : item,
|
entryPoints: hasTypeMarker ? item.slice(0, -1) : lastElement?.length === 0 ? DEFAULT_ENTRY_POINT : item,
|
||||||
foundItem: hasTypeMarker ? lastElement : undefined,
|
foundItem: hasTypeMarker ? lastElement : undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,16 +15,14 @@ import { ApiPackage } from './ApiPackage.js';
|
|||||||
export interface IApiEntryPointOptions extends IApiItemContainerMixinOptions, IApiNameMixinOptions {}
|
export interface IApiEntryPointOptions extends IApiItemContainerMixinOptions, IApiNameMixinOptions {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the entry point for an NPM package.
|
* Represents an entry point for an NPM package.
|
||||||
*
|
*
|
||||||
* @remarks
|
* @remarks
|
||||||
*
|
*
|
||||||
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
* This is part of the {@link ApiModel} hierarchy of classes, which are serializable representations of
|
||||||
* API declarations.
|
* API declarations.
|
||||||
*
|
*
|
||||||
* `ApiEntryPoint` represents the entry point to an NPM package. API Extractor does not currently support
|
* `ApiEntryPoint` represents an entry point to an NPM package.
|
||||||
* analysis of multiple entry points, but the `ApiEntryPoint` object is included to support a future feature.
|
|
||||||
* In the current implementation, `ApiEntryPoint.importPath` is always the empty string.
|
|
||||||
*
|
*
|
||||||
* For example, suppose the package.json file looks like this:
|
* For example, suppose the package.json file looks like this:
|
||||||
*
|
*
|
||||||
@@ -37,7 +35,7 @@ export interface IApiEntryPointOptions extends IApiItemContainerMixinOptions, IA
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* In this example, the `ApiEntryPoint` would represent the TypeScript module for `./lib/index.js`.
|
* In this example, the main `ApiEntryPoint` would represent the TypeScript module for `./lib/index.js`.
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export class ApiEntryPoint extends ApiItemContainerMixin(ApiNameMixin(ApiItem)) {
|
export class ApiEntryPoint extends ApiItemContainerMixin(ApiNameMixin(ApiItem)) {
|
||||||
@@ -62,12 +60,7 @@ export class ApiEntryPoint extends ApiItemContainerMixin(ApiNameMixin(ApiItem))
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The module path for this entry point, relative to the parent `ApiPackage`. In the current implementation,
|
* The module path for this entry point, relative to the parent `ApiPackage`. In the current implementation,
|
||||||
* this is always the empty string, indicating the default entry point.
|
* this is used to distinguish different entry points,
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
*
|
|
||||||
* API Extractor does not currently support analysis of multiple entry points. If that feature is implemented
|
|
||||||
* in the future, then the `ApiEntryPoint.importPath` will be used to distinguish different entry points,
|
|
||||||
* for example: `controls/Button` in `import { Button } from "example-package/controls/Button";`.
|
* for example: `controls/Button` in `import { Button } from "example-package/controls/Button";`.
|
||||||
*
|
*
|
||||||
* The `ApiEntryPoint.name` property stores the same value as `ApiEntryPoint.importPath`.
|
* The `ApiEntryPoint.name` property stores the same value as `ApiEntryPoint.importPath`.
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ interface IExtractorConfigParameters {
|
|||||||
docModelIncludeForgottenExports: boolean;
|
docModelIncludeForgottenExports: boolean;
|
||||||
enumMemberOrder: EnumMemberOrder;
|
enumMemberOrder: EnumMemberOrder;
|
||||||
mainEntryPointFilePath: string;
|
mainEntryPointFilePath: string;
|
||||||
|
mainEntryPointName: string;
|
||||||
messages: IExtractorMessagesConfig;
|
messages: IExtractorMessagesConfig;
|
||||||
newlineKind: NewlineKind;
|
newlineKind: NewlineKind;
|
||||||
omitTrimmingComments: boolean;
|
omitTrimmingComments: boolean;
|
||||||
@@ -474,6 +475,7 @@ export class ExtractorConfig {
|
|||||||
projectFolder,
|
projectFolder,
|
||||||
packageJson,
|
packageJson,
|
||||||
packageFolder,
|
packageFolder,
|
||||||
|
mainEntryPointName,
|
||||||
mainEntryPointFilePath,
|
mainEntryPointFilePath,
|
||||||
additionalEntryPoints,
|
additionalEntryPoints,
|
||||||
bundledPackages,
|
bundledPackages,
|
||||||
@@ -509,7 +511,7 @@ export class ExtractorConfig {
|
|||||||
this.packageJson = packageJson;
|
this.packageJson = packageJson;
|
||||||
this.packageFolder = packageFolder;
|
this.packageFolder = packageFolder;
|
||||||
this.mainEntryPointFilePath = {
|
this.mainEntryPointFilePath = {
|
||||||
modulePath: '',
|
modulePath: mainEntryPointName,
|
||||||
filePath: mainEntryPointFilePath,
|
filePath: mainEntryPointFilePath,
|
||||||
};
|
};
|
||||||
this.additionalEntryPoints = additionalEntryPoints;
|
this.additionalEntryPoints = additionalEntryPoints;
|
||||||
@@ -1003,6 +1005,8 @@ export class ExtractorConfig {
|
|||||||
tokenContext,
|
tokenContext,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const mainEntryPointName = configObject.mainEntryPointName ?? '';
|
||||||
|
|
||||||
if (!ExtractorConfig.hasDtsFileExtension(mainEntryPointFilePath)) {
|
if (!ExtractorConfig.hasDtsFileExtension(mainEntryPointFilePath)) {
|
||||||
throw new Error('The "mainEntryPointFilePath" value is not a declaration file: ' + mainEntryPointFilePath);
|
throw new Error('The "mainEntryPointFilePath" value is not a declaration file: ' + mainEntryPointFilePath);
|
||||||
}
|
}
|
||||||
@@ -1289,6 +1293,7 @@ export class ExtractorConfig {
|
|||||||
packageJson,
|
packageJson,
|
||||||
packageFolder,
|
packageFolder,
|
||||||
mainEntryPointFilePath,
|
mainEntryPointFilePath,
|
||||||
|
mainEntryPointName,
|
||||||
additionalEntryPoints,
|
additionalEntryPoints,
|
||||||
bundledPackages,
|
bundledPackages,
|
||||||
tsconfigFilePath,
|
tsconfigFilePath,
|
||||||
|
|||||||
@@ -491,6 +491,11 @@ export interface IConfigFile {
|
|||||||
*/
|
*/
|
||||||
mainEntryPointFilePath: string;
|
mainEntryPointFilePath: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the import path of the entrypoint used as the starting point for analysis.
|
||||||
|
*/
|
||||||
|
mainEntryPointName: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc IExtractorMessagesConfig}
|
* {@inheritDoc IExtractorMessagesConfig}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -291,6 +291,7 @@ export class ApiModelGenerator {
|
|||||||
docComment: packageDocComment,
|
docComment: packageDocComment,
|
||||||
tsdocConfiguration: this._collector.extractorConfig.tsdocConfiguration,
|
tsdocConfiguration: this._collector.extractorConfig.tsdocConfiguration,
|
||||||
projectFolderUrl: this._collector.extractorConfig.projectFolderUrl,
|
projectFolderUrl: this._collector.extractorConfig.projectFolderUrl,
|
||||||
|
preserveMemberOrder: true,
|
||||||
});
|
});
|
||||||
this._apiModel.addMember(apiPackage);
|
this._apiModel.addMember(apiPackage);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
// ("mainEntryPointFilePath" is required)
|
// ("mainEntryPointFilePath" is required)
|
||||||
|
|
||||||
|
"mainEntryPointName": "",
|
||||||
|
|
||||||
"bundledPackages": [],
|
"bundledPackages": [],
|
||||||
|
|
||||||
"newlineKind": "crlf",
|
"newlineKind": "crlf",
|
||||||
|
|||||||
@@ -47,6 +47,11 @@
|
|||||||
*/
|
*/
|
||||||
"mainEntryPointFilePath": "<projectFolder>/lib/index.d.ts",
|
"mainEntryPointFilePath": "<projectFolder>/lib/index.d.ts",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the import path of the entrypoint used as the starting point for analysis.
|
||||||
|
*/
|
||||||
|
// "mainEntryPointName": "",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of NPM package names whose exports should be treated as part of this package.
|
* A list of NPM package names whose exports should be treated as part of this package.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,6 +23,11 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"mainEntryPointName": {
|
||||||
|
"description": "Specifies the import path of the entrypoint used as the starting point for analysis.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
|
||||||
"additionalEntryPoints": {
|
"additionalEntryPoints": {
|
||||||
"description": "Specifies the .d.ts files to be used as the starting points for analysis.",
|
"description": "Specifies the .d.ts files to be used as the starting points for analysis.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
|||||||
@@ -223,39 +223,8 @@ function resolveItemURI(item: ApiItemLike, entryPoint?: ApiEntryPoint): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function itemExcerptText(excerpt: Excerpt, apiPackage: ApiPackage, parent?: ApiTypeParameterListMixin) {
|
function itemExcerptText(excerpt: Excerpt, apiPackage: ApiPackage, parent?: ApiTypeParameterListMixin) {
|
||||||
const DISCORD_API_TYPES_VERSION = 'v10';
|
|
||||||
const DISCORD_API_TYPES_DOCS_URL = `https://discord-api-types.dev/api/discord-api-types-${DISCORD_API_TYPES_VERSION}`;
|
|
||||||
|
|
||||||
return excerpt.spannedTokens.map((token) => {
|
return excerpt.spannedTokens.map((token) => {
|
||||||
if (token.kind === ExcerptTokenKind.Reference) {
|
if (token.kind === ExcerptTokenKind.Reference) {
|
||||||
const source = token.canonicalReference?.source;
|
|
||||||
const symbol = token.canonicalReference?.symbol;
|
|
||||||
|
|
||||||
if (source && 'packageName' in source && source.packageName === 'discord-api-types' && symbol) {
|
|
||||||
const { meaning, componentPath: path } = symbol;
|
|
||||||
let href = DISCORD_API_TYPES_DOCS_URL;
|
|
||||||
|
|
||||||
// dapi-types doesn't have routes for class members
|
|
||||||
// so we can assume this member is for an enum
|
|
||||||
if (meaning === 'member' && path && 'parent' in path) {
|
|
||||||
// unless it's a variable like FormattingPatterns.Role
|
|
||||||
if (path.parent.toString() === '__type') {
|
|
||||||
href += `#${token.text.split('.')[0]}`;
|
|
||||||
} else {
|
|
||||||
href += `/enum/${path.parent}#${path.component}`;
|
|
||||||
}
|
|
||||||
} else if (meaning === 'type' || meaning === 'var') {
|
|
||||||
href += `#${token.text}`;
|
|
||||||
} else {
|
|
||||||
href += `/${meaning}/${token.text}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
text: token.text,
|
|
||||||
href,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.canonicalReference) {
|
if (token.canonicalReference) {
|
||||||
const resolved = resolveCanonicalReference(token.canonicalReference, apiPackage);
|
const resolved = resolveCanonicalReference(token.canonicalReference, apiPackage);
|
||||||
|
|
||||||
@@ -316,9 +285,6 @@ function itemExcerptText(excerpt: Excerpt, apiPackage: ApiPackage, parent?: ApiT
|
|||||||
}
|
}
|
||||||
|
|
||||||
function itemTsDoc(item: DocNode, apiItem: ApiItem) {
|
function itemTsDoc(item: DocNode, apiItem: ApiItem) {
|
||||||
const DISCORD_API_TYPES_VERSION = 'v10';
|
|
||||||
const DISCORD_API_TYPES_DOCS_URL = `https://discord-api-types.dev/api/discord-api-types-${DISCORD_API_TYPES_VERSION}`;
|
|
||||||
|
|
||||||
const createNode = (node: DocNode): any => {
|
const createNode = (node: DocNode): any => {
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
case DocNodeKind.PlainText:
|
case DocNodeKind.PlainText:
|
||||||
@@ -380,29 +346,6 @@ function itemTsDoc(item: DocNode, apiItem: ApiItem) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resolved && resolved.package === 'discord-api-types') {
|
|
||||||
const { displayName, kind, members, containerKey } = resolved.item;
|
|
||||||
let href = DISCORD_API_TYPES_DOCS_URL;
|
|
||||||
|
|
||||||
// dapi-types doesn't have routes for class members
|
|
||||||
// so we can assume this member is for an enum
|
|
||||||
if (kind === 'enum' && members?.[0]) {
|
|
||||||
href += `/enum/${displayName}#${members[0].displayName}`;
|
|
||||||
} else if (kind === 'type' || kind === 'var') {
|
|
||||||
href += `#${displayName}`;
|
|
||||||
} else {
|
|
||||||
href += `/${kind}/${displayName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
kind: DocNodeKind.LinkTag,
|
|
||||||
text: displayName,
|
|
||||||
containerKey,
|
|
||||||
uri: href,
|
|
||||||
members: members?.map((member) => `.${member.displayName}`).join('') ?? '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
kind: DocNodeKind.LinkTag,
|
kind: DocNodeKind.LinkTag,
|
||||||
text: linkText ?? foundItem?.displayName ?? resolved!.item.displayName,
|
text: linkText ?? foundItem?.displayName ?? resolved!.item.displayName,
|
||||||
@@ -545,8 +488,6 @@ function itemInfo(item: ApiDeclaredItem) {
|
|||||||
|
|
||||||
function resolveFileUrl(item: ApiDeclaredItem) {
|
function resolveFileUrl(item: ApiDeclaredItem) {
|
||||||
const {
|
const {
|
||||||
displayName,
|
|
||||||
kind,
|
|
||||||
sourceLocation: { fileUrl, fileLine },
|
sourceLocation: { fileUrl, fileLine },
|
||||||
} = item;
|
} = item;
|
||||||
if (fileUrl?.includes('/node_modules/')) {
|
if (fileUrl?.includes('/node_modules/')) {
|
||||||
@@ -571,20 +512,12 @@ function resolveFileUrl(item: ApiDeclaredItem) {
|
|||||||
|
|
||||||
// https://github.com/discordjs/discord.js/tree/main/node_modules/.pnpm/discord-api-types@0.37.97/node_modules/discord-api-types/payloads/v10/gateway.d.ts#L240
|
// https://github.com/discordjs/discord.js/tree/main/node_modules/.pnpm/discord-api-types@0.37.97/node_modules/discord-api-types/payloads/v10/gateway.d.ts#L240
|
||||||
if (pkgName === 'discord-api-types') {
|
if (pkgName === 'discord-api-types') {
|
||||||
const DISCORD_API_TYPES_VERSION = 'v10';
|
let currentItem = item;
|
||||||
const DISCORD_API_TYPES_DOCS_URL = `https://discord-api-types.dev/api/discord-api-types-${DISCORD_API_TYPES_VERSION}`;
|
while (currentItem.parent && currentItem.parent.kind !== ApiItemKind.EntryPoint)
|
||||||
let href = DISCORD_API_TYPES_DOCS_URL;
|
currentItem = currentItem.parent as ApiDeclaredItem;
|
||||||
|
|
||||||
if (kind === ApiItemKind.EnumMember) {
|
|
||||||
href += `/enum/${item.parent!.displayName}#${displayName}`;
|
|
||||||
} else if (kind === ApiItemKind.TypeAlias || kind === ApiItemKind.Variable) {
|
|
||||||
href += `#${displayName}`;
|
|
||||||
} else {
|
|
||||||
href += `/${kindToMeaning.get(kind)}/${displayName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sourceURL: href,
|
sourceURL: `/docs/packages/${pkgName}/${version}/${(currentItem.parent as ApiEntryPoint).importPath}/${currentItem.displayName}:${currentItem.kind}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else if (fileUrl?.includes('/dist/') && fileUrl.includes('/main/packages/')) {
|
} else if (fileUrl?.includes('/dist/') && fileUrl.includes('/main/packages/')) {
|
||||||
|
|||||||
Reference in New Issue
Block a user