Compare commits

..

1 Commits

Author SHA1 Message Date
iCrawl
d63bcbb9d4 chore(core): release @discordjs/core@0.2.0 2022-12-16 03:58:37 +01:00
635 changed files with 13450 additions and 24931 deletions

View File

@@ -7,5 +7,8 @@
"rules": {
"@typescript-eslint/consistent-type-definitions": ["error", "interface"]
},
"ignorePatterns": ["**/dist/*"]
"ignorePatterns": ["**/dist/*"],
"env": {
"jest": true
}
}

27
.github/CODEOWNERS vendored
View File

@@ -1,27 +0,0 @@
# Learn how to add code owners here:
# https://help.github.com/en/articles/about-code-owners
* @iCrawl
/apps/guide/ @discordjs/website @discordjs/guide
/apps/guide/src/content/ @discordjs/guide
/apps/website/ @discordjs/website
/packages/actions/ @discordjs/actions
/packages/api-extractor-utils/ @discordjs/api-extractor-utils
/packages/brokers/ @discordjs/brokers
/packages/builders/ @discordjs/builders
/packages/collection/ @discordjs/collection
/packages/core/ @discordjs/core
/packages/discord.js/ @discordjs/core
/packages/docgen/ @iCrawl
/packages/formatters/ @discordjs/formatters
/packages/next/ @discordjs/core
/packages/proxy/ @discordjs/proxy
/packages/proxy-container/ @discordjs/proxy
/packages/rest/ @discordjs/rest
/packages/scripts/ @discordjs/scripts
/packages/ui/ @discordjs/ui
/packages/util/ @discordjs/util
/packages/voice/ @discordjs/core
/packages/ws/ @discordjs/ws

View File

@@ -40,7 +40,7 @@ For example, to automatically recompile the `@discordjs/rest` project when chang
If you'd like to create another package under the `@discordjs` organization run the following command:
```sh
```bash
yarn create-package <package-name> [package-description]
```

View File

@@ -17,7 +17,6 @@ body:
- collection
- core
- formatters
- next
- proxy
- proxy-container
- rest
@@ -120,7 +119,7 @@ body:
- No Intents
- Guilds
- GuildMembers
- GuildModeration
- GuildBans
- GuildEmojisAndStickers
- GuildIntegrations
- GuildWebhooks

View File

@@ -11,7 +11,7 @@ body:
- type: dropdown
id: package
attributes:
label: Which package is this feature request for?
label: Which package is the feature request for?
options:
- discord.js
- brokers
@@ -19,7 +19,6 @@ body:
- collection
- core
- formatters
- next
- proxy
- proxy-container
- rest

8
.github/auto_assign.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
addReviewers: true
reviewers:
- iCrawl
- SpaceEEC
- kyranet
- vladfrangu
numberOfReviewers: 0
runOnDraft: true

View File

@@ -1,24 +0,0 @@
packages:brokers:
- '### Which package is this (bug report|feature request) for\?\n\nbrokers'
packages:builders:
- '### Which package is this (bug report|feature request) for\?\n\nbuilders'
packages:collection:
- '### Which package is this (bug report|feature request) for\?\n\ncollection'
packages:core:
- '### Which package is this (bug report|feature request) for\?\n\ncore'
packages:discord.js:
- '### Which package is this (bug report|feature request) for\?\n\ndiscord.js'
packages:formatters:
- '### Which package is this (bug report|feature request) for\?\n\nformatters'
packages:next:
- '### Which package is this (bug report|feature request) for\?\n\nnext'
packages:proxy:
- '### Which package is this (bug report|feature request) for\?\n\nproxy'
packages:proxy-container:
- '### Which package is this (bug report|feature request) for\?\n\nproxy-container'
packages:rest:
- '### Which package is this (bug report|feature request) for\?\n\nrest'
packages:voice:
- '### Which package is this (bug report|feature request) for\?\n\nvoice'
packages:ws:
- '### Which package is this (bug report|feature request) for\?\n\nws'

3
.github/labeler.yml vendored
View File

@@ -19,9 +19,6 @@ packages:core:
packages:discord.js:
- packages/discord.js/*
- packages/discord.js/**/*
packages:next:
- packages/next/*
- packages/next/**/*
packages:docgen:
- packages/docgen/*
- packages/docgen/**/*

4
.github/labels.yml vendored
View File

@@ -8,8 +8,6 @@
color: fbca04
- name: backlog
color: 7ef7ef
- name: backport
color: 88aabb
- name: blocked
color: fc1423
- name: bug
@@ -62,8 +60,6 @@
color: fbca04
- name: packages:discord.js
color: fbca04
- name: packages:next
color: fbca04
- name: packages:docgen
color: fbca04
- name: packages:formatters

View File

@@ -3,8 +3,6 @@ on:
push:
branches:
- 'main'
paths:
- 'packages/*/src/**'
tags:
- '**'
workflow_dispatch:
@@ -76,7 +74,6 @@ jobs:
'collection',
'core',
'discord.js',
'next',
'formatters',
'proxy',
'rest',
@@ -129,15 +126,6 @@ jobs:
with:
tag: ${{ github.ref_name }}
- name: Upload documentation to database
if: ${{ github.ref_type == 'tag' && matrix.package == steps.extract-tag.outputs.package }}
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
uses: ./packages/actions/src/uploadDocumentation
with:
package: ${{ steps.extract-tag.outputs.package }}
version: ${{ steps.extract-tag.outputs.semver }}
- name: Move docs to correct directory
if: ${{ github.ref_type == 'tag' && matrix.package == steps.extract-tag.outputs.package }}
env:
@@ -152,14 +140,6 @@ jobs:
mv docs/${PACKAGE}/docs/docs.api.json out/${PACKAGE}/${SEMVER}.api.json
fi
- name: Upload documentation to database
if: ${{ github.ref_type == 'branch' }}
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
uses: ./packages/actions/src/uploadDocumentation
with:
package: ${{ matrix.package }}
- name: Move docs to correct directory
if: ${{ github.ref_type == 'branch' }}
env:

View File

@@ -1,14 +0,0 @@
name: 'Issue Labeler'
on:
issues:
types: [opened]
jobs:
issue-triage:
runs-on: ubuntu-latest
steps:
- uses: github/issue-labeler@v2.5
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
configuration-path: .github/issue-labeler.yml
not-before: 2023-01-13T10:25:03.847Z
enable-versioned-regex: 0

View File

@@ -1,20 +0,0 @@
name: 'Lighthouse Audit (main)'
on:
workflow_dispatch:
jobs:
lighthouse_audit_main:
name: 'Lighthouse Audit (main)'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Audit production URLs with Lighthouse
id: lighthouse_audit
uses: treosh/lighthouse-ci-action@v9
with:
urls: |
https://discordjs.dev
https://guide.discordjs.dev
uploadArtifacts: true
temporaryPublicStorage: true

View File

@@ -1,88 +0,0 @@
name: 'Lighthouse Audit'
on:
issue_comment:
types: [created, edited]
jobs:
lighthouse_audit:
name: 'Lighthouse Audit'
if: ${{ github.event.issue.pull_request }}
runs-on: ubuntu-latest
steps:
- name: Get Vercel preview URL
id: get_preview_url
uses: actions/github-script@v3
with:
script: |
const comment = context.payload.comment;
const regex = /https:\/\/[a-z0-9-]+\.vercel\.app/g;
const matches = comment.body.match(regex);
let previewUrl = "";
if (matches && matches.length) {
previewUrl = matches[0];
console.log('Preview url found:', previewUrl);
}
console.log("No preview url found.");
core.setOutput('vercel_preview_url', previewUrl);
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Add comment to PR
if: ${{ steps.get_preview_url.outputs.vercel_preview_url != '' }}
id: loading_comment_to_pr
uses: marocchino/sticky-pull-request-comment@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
number: ${{ github.event.issue.number }}
header: lighthouse
message: |
Running Lighthouse audit...
- name: Checkout repository
if: ${{ steps.get_preview_url.outputs.vercel_preview_url != '' }}
uses: actions/checkout@v3
- name: Audit preview URL with Lighthouse
if: ${{ steps.get_preview_url.outputs.vercel_preview_url != '' }}
id: lighthouse_audit
uses: treosh/lighthouse-ci-action@v9
with:
urls: |
${{ steps.get_preview_url.outputs.vercel_preview_url }}
uploadArtifacts: true
temporaryPublicStorage: true
- name: Format lighthouse score
if: ${{ steps.get_preview_url.outputs.vercel_preview_url != '' }}
id: format_lighthouse_score
uses: actions/github-script@v3
with:
script: |
const result = ${{ steps.lighthouse_audit.outputs.manifest }}[0].summary
const links = ${{ steps.lighthouse_audit.outputs.links }}
const formatResult = (res) => Math.round((res * 100))
Object.keys(result).forEach(key => result[key] = formatResult(result[key]))
const score = res => res >= 90 ? '🟢' : res >= 50 ? '🟠' : '🔴'
const comment = [
`⚡️ [Lighthouse report](${Object.values(links)[0]}) for the changes in this PR:`,
'| Category | Score |',
'| --- | --- |',
`| ${score(result.performance)} Performance | ${result.performance} |`,
`| ${score(result.accessibility)} Accessibility | ${result.accessibility} |`,
`| ${score(result['best-practices'])} Best practices | ${result['best-practices']} |`,
`| ${score(result.seo)} SEO | ${result.seo} |`,
`| ${score(result.pwa)} PWA | ${result.pwa} |`,
' ',
`*Lighthouse ran on [${Object.keys(links)[0]}](${Object.keys(links)[0]})*`
].join('\n')
core.setOutput("comment", comment);
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Add comment to PR
if: ${{ steps.get_preview_url.outputs.vercel_preview_url != '' }}
id: comment_to_pr
uses: marocchino/sticky-pull-request-comment@v2
with:
number: ${{ github.event.issue.number }}
header: lighthouse
message: |
${{ steps.format_lighthouse_score.outputs.comment }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,19 +0,0 @@
name: Lock Ancient Issues
on:
schedule:
- cron: '0 16 * * *'
workflow_dispatch:
permissions:
issues: write
concurrency:
group: lock
jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
issue-inactive-days: 365
issue-lock-reason: resolved
process-only: issues

View File

@@ -21,6 +21,6 @@ jobs:
uses: ./packages/actions/src/yarnCache
- name: Deprecate versions
run: 'yarn npm-deprecate --name "*dev*" --package @discordjs/brokers @discordjs/builders @discordjs/collection @discordjs/core @discordjs/formatters discord.js @discordjs/next @discordjs/proxy @discordjs/rest @discordjs/util @discordjs/voice @discordjs/ws'
run: 'yarn npm-deprecate --name "*dev*" --package @discordjs/brokers @discordjs/builders @discordjs/collection @discordjs/core @discordjs/formatters discord.js @discordjs/proxy @discordjs/rest @discordjs/util @discordjs/voice @discordjs/ws'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}

View File

@@ -11,3 +11,7 @@ jobs:
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
sync-labels: true
- name: Automatically assign reviewers
if: github.event.action == 'opened'
uses: kentaro-m/auto-assign-action@v1.2.3

View File

@@ -12,17 +12,6 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install node.js v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
uses: ./packages/actions/src/yarnCache
- name: Build dependencies
run: yarn build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
@@ -30,7 +19,7 @@ jobs:
run: echo ${{ secrets.DOCKER_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Build the image
run: yarn docker build @discordjs/proxy-container -t discordjs/proxy:latest
run: docker build -t discordjs/proxy:latest -f packages/proxy-container/Dockerfile .
- name: Push image to DockerHub
run: docker push discordjs/proxy:latest

View File

@@ -22,8 +22,6 @@ jobs:
folder: 'formatters'
- package: 'discord.js'
folder: 'discord.js'
- package: '@discordjs/next'
folder: 'next'
- package: '@discordjs/proxy'
folder: 'proxy'
- package: '@discordjs/rest'

View File

@@ -9,17 +9,6 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install node.js v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
uses: ./packages/actions/src/yarnCache
- name: Build dependencies
run: yarn build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
@@ -27,7 +16,7 @@ jobs:
run: echo ${{ secrets.DOCKER_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Build docker image
run: yarn docker build @discordjs/proxy-container -t discordjs/proxy:latest
run: docker build -t discordjs/proxy:latest -f packages/proxy-container/Dockerfile .
- name: Tag image with major
run: docker tag discordjs/proxy discordjs/proxy:$(cut -d '.' -f1 <<< $(jq --raw-output '.version' packages/proxy-container/package.json))

View File

@@ -1,39 +0,0 @@
name: Publish Release
on:
release:
types: [released]
jobs:
npm-publish:
name: npm publish
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
if: github.repository_owner == 'discordjs'
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install node.js v16
uses: actions/setup-node@v3
with:
node-version: 16
registry-url: https://registry.npmjs.org/
- name: Install dependencies
uses: ./packages/actions/src/yarnCache
- name: Build dependencies
run: yarn build
- name: Extract package and semver from tag
id: extract-tag
uses: ./packages/actions/src/formatTag
with:
tag: ${{ github.ref_name }}
- name: Publish package
run: |
yarn workspace ${{ steps.extract-tag.outputs.subpackage == 'true' && '@discordjs/' || '' }}${{ steps.extract-tag.outputs.package }} npm publish
env:
YARN_NPM_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}

View File

@@ -3,8 +3,7 @@ on:
push:
pull_request:
concurrency:
# Group based on workflow name and PR if it exists, if no PR, let it run so carryforward flags work
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
tests:

2
.gitignore vendored
View File

@@ -16,7 +16,6 @@ pids
# Dist
dist/
dist-docs/
# Miscellaneous
.tmp/
@@ -42,4 +41,3 @@ out/
# Cache
.prettiercache
.eslintcache
.vercel

View File

@@ -1,5 +1,5 @@
{
"*": "prettier --ignore-unknown --write",
"{src/**,__tests__/**}.{mjs,js,cjs,ts,tsx}": "eslint --ext .mjs,.js,.cjs,.ts,.tsx --fix",
"{src/**,__tests__/**}.{mjs,js,cjs,ts,tsx,astro}": "eslint --ext .mjs,.js,.cjs,.ts,.tsx,.astro --fix",
"src/**.ts": "vitest related --run --config ../../vitest.config.ts"
}

View File

@@ -1 +0,0 @@
CODEOWNERS

View File

@@ -9,6 +9,7 @@
"christian-kohler.npm-intellisense",
"christian-kohler.path-intellisense",
"antfu.unocss",
"astro-build.astro-vscode",
"unifiedjs.vscode-mdx"
]
}

View File

@@ -1,6 +1,7 @@
{
"eslint.workingDirectories": [{ "pattern": "./apps/*" }, { "pattern": "./packages/*" }],
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"eslint.validate": ["javascript", "javascriptreact", "astro", "typescript", "typescriptreact"],
"prettier.documentSelectors": ["**/*.astro"],
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {

View File

@@ -0,0 +1,14 @@
diff --git a/lib/TSDocConfigFile.js b/lib/TSDocConfigFile.js
index caf3515d60fd386c5909db5a0aa8b4180b10d602..6fa4f1984b6ba6b3a7aecd05e54477ebf141af94 100644
--- a/lib/TSDocConfigFile.js
+++ b/lib/TSDocConfigFile.js
@@ -31,8 +31,7 @@ const ajv_1 = __importDefault(require("ajv"));
const jju = __importStar(require("jju"));
const ajv = new ajv_1.default({ verbose: true });
function initializeSchemaValidator() {
- const jsonSchemaPath = resolve.sync('@microsoft/tsdoc/schemas/tsdoc.schema.json', { basedir: __dirname });
- const jsonSchemaContent = fs.readFileSync(jsonSchemaPath).toString();
+ const jsonSchemaContent = "{\"title\":\"TSDoc Configuration\",\"description\":\"Describes the TSDoc configuration for a TypeScript project\",\"type\":\"object\",\"properties\":{\"$schema\":{\"description\":\"Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.\",\"type\":\"string\"},\"extends\":{\"description\":\"Optionally specifies one or more JSON config files that will be combined with this file. This provides a way for standard settings to be shared across multiple projects. Important: The \\\"extends\\\" paths are resolved using NodeJS module resolution, so a path to a local file MUST be prefixed with \\\"./\\\".\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"noStandardTags\":{\"description\":\"By default, the config file loader will predefine all of the standardized TSDoc tags. To disable this and start with a completely empty configuration, set \\\"noStandardTags\\\"=true.\",\"type\":\"boolean\"},\"tagDefinitions\":{\"description\":\"Additional tags to support when parsing documentation comments with TSDoc.\",\"type\":\"array\",\"items\":{\"$ref\":\"#/definitions/tsdocTagDefinition\"}},\"supportedHtmlElements\":{\"description\":\"The HTML element names that are supported in this configuration. Used in conjunction with the \\\"reportUnsupportedHtmlElements\\\" setting.\",\"type\":\"array\",\"items\":{\"type\":\"string\",\"pattern\":\"^[a-zA-Z0-9-]+$\"}},\"reportUnsupportedHtmlElements\":{\"description\":\"Whether an error should be reported when an unsupported HTML element is encountered in a doc comment. Defaults to \\\"true\\\" if the \\\"supportedHtmlElements\\\" field is present in this file, \\\"false\\\" if not.\",\"type\":\"boolean\"},\"supportForTags\":{\"description\":\"A collection of key/value pairs. The key is a TSDoc tag name (e.g. \\\"@myTag\\\") that must be defined in this configuration. The value is a boolean indicating whether the tag is supported. The TSDoc parser may report warnings when unsupported tags are encountered. If \\\"supportForTags\\\" is specified for at least one tag, then the \\\"reportUnsupportedTags\\\" validation check is enabled by default.\",\"type\":\"object\",\"patternProperties\":{\"@[a-zA-Z][a-zA-Z0-9]*$\":{\"type\":\"boolean\"}},\"additionalItems\":false}},\"required\":[\"$schema\"],\"additionalProperties\":false,\"definitions\":{\"tsdocTagDefinition\":{\"description\":\"Configuration for a custom supported TSDoc tag.\",\"type\":\"object\",\"properties\":{\"tagName\":{\"description\":\"Name of the custom tag. TSDoc tag names start with an at-sign (@) followed by ASCII letters using camelCase capitalization.\",\"type\":\"string\"},\"syntaxKind\":{\"description\":\"Syntax kind of the custom tag. \\\"inline\\\" means that this tag can appear inside other documentation sections (example: {@link}). \\\"block\\\" means that this tag starts a new documentation section (example: @remarks). \\\"modifier\\\" means that this tag's presence indicates an aspect of the associated API item (example: @internal).\",\"type\":\"string\",\"enum\":[\"inline\",\"block\",\"modifier\"]},\"allowMultiple\":{\"description\":\"If true, then this tag may appear multiple times in a doc comment. By default, a tag may only appear once.\",\"type\":\"boolean\"}},\"required\":[\"tagName\",\"syntaxKind\"],\"additionalProperties\":false}}}";
const jsonSchema = jju.parse(jsonSchemaContent, { mode: 'cjson' });
return ajv.compile(jsonSchema);
}

View File

@@ -1,14 +0,0 @@
diff --git a/lib/TSDocConfigFile.js b/lib/TSDocConfigFile.js
index caf3515d60fd386c5909db5a0aa8b4180b10d602..5f7cfed7611e3fe660b5265ff99c5da0beb7caec 100644
--- a/lib/TSDocConfigFile.js
+++ b/lib/TSDocConfigFile.js
@@ -31,8 +31,7 @@ const ajv_1 = __importDefault(require("ajv"));
const jju = __importStar(require("jju"));
const ajv = new ajv_1.default({ verbose: true });
function initializeSchemaValidator() {
- const jsonSchemaPath = resolve.sync('@microsoft/tsdoc/schemas/tsdoc.schema.json', { basedir: __dirname });
- const jsonSchemaContent = fs.readFileSync(jsonSchemaPath).toString();
+ const jsonSchemaContent = '{\"title\":\"TSDoc Configuration\",\"description\":\"Describes the TSDoc configuration for a TypeScript project\",\"type\":\"object\",\"properties\":{\"$schema\":{\"description\":\"Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.\",\"type\":\"string\"},\"extends\":{\"description\":\"Optionally specifies one or more JSON config files that will be combined with this file. This provides a way for standard settings to be shared across multiple projects. Important: The \\\"extends\\\" paths are resolved using NodeJS module resolution, so a path to a local file MUST be prefixed with \\\".\/\\\".\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"noStandardTags\":{\"description\":\"By default, the config file loader will predefine all of the standardized TSDoc tags. To disable this and start with a completely empty configuration, set \\\"noStandardTags\\\"=true.\",\"type\":\"boolean\"},\"tagDefinitions\":{\"description\":\"Additional tags to support when parsing documentation comments with TSDoc.\",\"type\":\"array\",\"items\":{\"$ref\":\"#\/definitions\/tsdocTagDefinition\"}},\"supportedHtmlElements\":{\"description\":\"The HTML element names that are supported in this configuration. Used in conjunction with the \\\"reportUnsupportedHtmlElements\\\" setting.\",\"type\":\"array\",\"items\":{\"type\":\"string\",\"pattern\":\"^[a-zA-Z0-9-]+$\"}},\"reportUnsupportedHtmlElements\":{\"description\":\"Whether an error should be reported when an unsupported HTML element is encountered in a doc comment. Defaults to \\\"true\\\" if the \\\"supportedHtmlElements\\\" field is present in this file, \\\"false\\\" if not.\",\"type\":\"boolean\"},\"supportForTags\":{\"description\":\"A collection of key\/value pairs. The key is a TSDoc tag name (e.g. \\\"@myTag\\\") that must be defined in this configuration. The value is a boolean indicating whether the tag is supported. The TSDoc parser may report warnings when unsupported tags are encountered. If \\\"supportForTags\\\" is specified for at least one tag, then the \\\"reportUnsupportedTags\\\" validation check is enabled by default.\",\"type\":\"object\",\"patternProperties\":{\"@[a-zA-Z][a-zA-Z0-9]*$\":{\"type\":\"boolean\"}},\"additionalItems\":false}},\"required\":[\"$schema\"],\"additionalProperties\":false,\"definitions\":{\"tsdocTagDefinition\":{\"description\":\"Configuration for a custom supported TSDoc tag.\",\"type\":\"object\",\"properties\":{\"tagName\":{\"description\":\"Name of the custom tag. TSDoc tag names start with an at-sign (@) followed by ASCII letters using camelCase capitalization.\",\"type\":\"string\"},\"syntaxKind\":{\"description\":\"Syntax kind of the custom tag. \\\"inline\\\" means that this tag can appear inside other documentation sections (example: {@link}). \\\"block\\\" means that this tag starts a new documentation section (example: @remarks). \\\"modifier\\\" means that this tag\'s presence indicates an aspect of the associated API item (example: @internal).\",\"type\":\"string\",\"enum\":[\"inline\",\"block\",\"modifier\"]},\"allowMultiple\":{\"description\":\"If true, then this tag may appear multiple times in a doc comment. By default, a tag may only appear once.\",\"type\":\"boolean\"}},\"required\":[\"tagName\",\"syntaxKind\"],\"additionalProperties\":false}}}';
const jsonSchema = jju.parse(jsonSchemaContent, { mode: 'cjson' });
return ajv.compile(jsonSchema);
}

View File

@@ -1,257 +0,0 @@
/* eslint-disable */
module.exports = {
name: '@yarnpkg/plugin-docker-build',
factory: function (require) {
var plugin;
(() => {
'use strict';
var t = {
d: (e, o) => {
for (var r in o) t.o(o, r) && !t.o(e, r) && Object.defineProperty(e, r, { enumerable: !0, get: o[r] });
},
o: (t, e) => Object.prototype.hasOwnProperty.call(t, e),
r: (t) => {
'undefined' != typeof Symbol &&
Symbol.toStringTag &&
Object.defineProperty(t, Symbol.toStringTag, { value: 'Module' }),
Object.defineProperty(t, '__esModule', { value: !0 });
},
},
e = {};
t.r(e), t.d(e, { default: () => u });
const o = require('@yarnpkg/cli'),
r = require('clipanion'),
i = require('@yarnpkg/core'),
a = require('@yarnpkg/plugin-patch'),
n = require('@yarnpkg/fslib');
const s = require('@yarnpkg/plugin-pack');
async function c({ workspace: t, destination: e, report: o }) {
await s.packUtils.prepareForPack(t, { report: o }, async () => {
const r = await s.packUtils.genPackList(t),
a = i.Report.progressViaCounter(r.length),
c = o.reportProgress(a);
try {
for (const i of r) {
const r = n.ppath.join(t.cwd, i),
s = n.ppath.join(e, t.relativeCwd, i);
o.reportInfo(null, i), await n.xfs.copyPromise(s, r, { overwrite: !0 }), a.tick();
}
} finally {
c.stop();
}
});
}
function p(t, e) {
const o = (0, n.toFilename)(e);
return n.ppath.isAbsolute(o) ? n.ppath.relative(t, o) : o;
}
const l = /^builtin<([^>]+)>$/;
var d = function (t, e, o, r) {
var i,
a = arguments.length,
n = a < 3 ? e : null === r ? (r = Object.getOwnPropertyDescriptor(e, o)) : r;
if ('object' == typeof Reflect && 'function' == typeof Reflect.decorate) n = Reflect.decorate(t, e, o, r);
else
for (var s = t.length - 1; s >= 0; s--)
(i = t[s]) && (n = (a < 3 ? i(n) : a > 3 ? i(e, o, n) : i(e, o)) || n);
return a > 3 && n && Object.defineProperty(e, o, n), n;
};
class f extends o.BaseCommand {
constructor() {
super(...arguments), (this.args = []);
}
async execute() {
const t = await i.Configuration.find(this.context.cwd, this.context.plugins),
{ project: e } = await i.Project.find(t, this.context.cwd),
o = e.getWorkspaceByIdent(i.structUtils.parseIdent(this.workspaceName)),
r = (function ({
project: t,
workspaces: e,
production: o = !1,
scopes: r = o ? ['dependencies'] : i.Manifest.hardDependencies,
}) {
const a = new Set([...e]);
for (const e of a)
for (const o of r) {
const r = e.manifest.getForScope(o).values();
for (const e of r) {
const o = t.tryWorkspaceByDescriptor(e);
o && a.add(o);
}
}
for (const e of t.workspaces)
a.has(e)
? o && e.manifest.devDependencies.clear()
: (e.manifest.dependencies.clear(),
e.manifest.devDependencies.clear(),
e.manifest.peerDependencies.clear());
return a;
})({ project: e, workspaces: [o], production: this.production }),
s = await (async function (t, e = 'Dockerfile') {
const o = (0, n.toFilename)(e);
if (n.ppath.isAbsolute(o)) return o;
const r = [n.ppath.join(t.cwd, o), n.ppath.join(t.project.cwd, o)];
for (const t of r) if (await n.xfs.existsPromise(t)) return t;
throw new Error('Dockerfile is required');
})(o, this.dockerFilePath),
d = await i.Cache.find(t);
return (
await i.StreamReport.start(
{ configuration: t, stdout: this.context.stdout, includeLogs: !this.context.quiet },
async (t) => {
await t.startTimerPromise('Resolution Step', async () => {
await e.resolveEverything({ report: t, cache: d });
}),
await t.startTimerPromise('Fetch Step', async () => {
await e.fetchEverything({ report: t, cache: d });
}),
await n.xfs.mktempPromise(async (o) => {
const f = n.ppath.join(o, (0, n.toFilename)('manifests')),
u = n.ppath.join(o, (0, n.toFilename)('packs'));
await t.startTimerPromise('Copy files', async () => {
await (async function ({ destination: t, project: e, report: o }) {
const r = e.configuration.get('rcFilename');
o.reportInfo(null, r),
await n.xfs.copyPromise(n.ppath.join(t, r), n.ppath.join(e.cwd, r), { overwrite: !0 });
})({ destination: f, project: e, report: t }),
await (async function ({ destination: t, project: e, report: o }) {
const r = n.ppath.join((0, n.toFilename)('.yarn'), (0, n.toFilename)('plugins'));
o.reportInfo(null, r),
await n.xfs.copyPromise(n.ppath.join(t, r), n.ppath.join(e.cwd, r), { overwrite: !0 });
})({ destination: f, project: e, report: t }),
await (async function ({ destination: t, project: e, report: o }) {
const r = e.configuration.get('yarnPath'),
i = n.ppath.relative(e.cwd, r),
a = n.ppath.join(t, i);
o.reportInfo(null, i), await n.xfs.copyPromise(a, r, { overwrite: !0 });
})({ destination: f, project: e, report: t }),
await (async function ({ destination: t, workspaces: e, report: o }) {
for (const r of e) {
const e = n.ppath.join(r.relativeCwd, i.Manifest.fileName),
a = n.ppath.join(t, e),
s = {};
r.manifest.exportTo(s),
o.reportInfo(null, e),
await n.xfs.mkdirpPromise(n.ppath.dirname(a)),
await n.xfs.writeJsonPromise(a, s);
}
})({ destination: f, workspaces: e.workspaces, report: t }),
await (async function ({ destination: t, report: e, project: o, parseDescriptor: r }) {
const a = new Set();
for (const s of o.storedDescriptors.values()) {
const c = r(
i.structUtils.isVirtualDescriptor(s) ? i.structUtils.devirtualizeDescriptor(s) : s,
);
if (!c) continue;
const { parentLocator: p, paths: d } = c;
for (const r of d) {
if (l.test(r)) continue;
if (n.ppath.isAbsolute(r)) continue;
const i = o.getWorkspaceByLocator(p),
s = n.ppath.join(i.relativeCwd, r);
if (a.has(s)) continue;
a.add(s);
const c = n.ppath.join(i.cwd, r),
d = n.ppath.join(t, s);
e.reportInfo(null, s),
await n.xfs.mkdirpPromise(n.ppath.dirname(d)),
await n.xfs.copyFilePromise(c, d);
}
}
})({
destination: f,
report: t,
project: e,
parseDescriptor: (t) => {
if (t.range.startsWith('exec:')) {
const e = (function (t) {
const { params: e, selector: o } = i.structUtils.parseRange(t),
r = n.npath.toPortablePath(o);
return {
parentLocator:
e && 'string' == typeof e.locator ? i.structUtils.parseLocator(e.locator) : null,
path: r,
};
})(t.range);
if (!e || !e.parentLocator) return;
return { parentLocator: e.parentLocator, paths: [e.path] };
}
if (t.range.startsWith('patch:')) {
const { parentLocator: e, patchPaths: o } = a.patchUtils.parseDescriptor(t);
if (!e) return;
return { parentLocator: e, paths: o };
}
},
}),
await (async function ({ destination: t, project: e, cache: o, report: r }) {
for (const i of o.markedFiles) {
const o = n.ppath.relative(e.cwd, i);
(await n.xfs.existsPromise(i)) &&
(r.reportInfo(null, o), await n.xfs.copyPromise(n.ppath.join(t, o), i));
}
})({ destination: f, project: e, cache: d, report: t }),
await (async function ({ destination: t, project: e, report: o }) {
const r = (0, n.toFilename)(e.configuration.get('lockfileFilename')),
i = n.ppath.join(t, r);
o.reportInfo(null, r),
await n.xfs.mkdirpPromise(n.ppath.dirname(i)),
await n.xfs.writeFilePromise(i, e.generateLockfile());
})({ destination: f, project: e, report: t }),
this.copyFiles &&
this.copyFiles.length &&
(await (async function ({ destination: t, files: e, dockerFilePath: o, report: r }) {
const i = n.ppath.dirname(o);
for (const o of e) {
const e = p(i, o),
a = n.ppath.join(i, e),
s = n.ppath.join(t, e);
r.reportInfo(null, e), await n.xfs.copyPromise(s, a);
}
})({ destination: f, files: this.copyFiles, dockerFilePath: s, report: t }));
});
for (const e of r) {
const o = e.manifest.name ? i.structUtils.stringifyIdent(e.manifest.name) : '';
await t.startTimerPromise('Pack workspace ' + o, async () => {
await c({ workspace: e, report: t, destination: u });
});
}
await i.execUtils.pipevp('docker', ['build', ...this.args, '-f', s, '.'], {
cwd: o,
strict: !0,
stdin: this.context.stdin,
stdout: this.context.stdout,
stderr: this.context.stderr,
});
});
},
)
).exitCode();
}
}
(f.usage = r.Command.Usage({
category: 'Docker-related commands',
description: 'Build a Docker image for a workspace',
details:
'\n This command will build a efficient Docker image which only contains necessary dependencies for the specified workspace.\n\n You have to create a Dockerfile in your workspace or your project. You can also specify the path to Dockerfile using the "-f, --file" option.\n\n Additional arguments can be passed to "docker build" directly, please check the Docker docs for more info: https://docs.docker.com/engine/reference/commandline/build/\n\n You can copy additional files or folders to a Docker image using the "--copy" option. This is useful for secret keys or configuration files. The files will be copied to "manifests" folder. The path can be either a path relative to the Dockerfile or an absolute path.\n ',
examples: [
['Build a Docker image for a workspace', 'yarn docker build @foo/bar'],
['Pass additional arguments to docker build command', 'yarn docker build @foo/bar -t image-tag'],
[
'Copy additional files to a Docker image',
'yarn docker build --copy secret.key --copy config.json @foo/bar',
],
['Install production dependencies only', 'yarn docker build --production @foo/bar'],
],
})),
d([r.Command.String()], f.prototype, 'workspaceName', void 0),
d([r.Command.Proxy()], f.prototype, 'args', void 0),
d([r.Command.String('-f,--file')], f.prototype, 'dockerFilePath', void 0),
d([r.Command.Array('--copy')], f.prototype, 'copyFiles', void 0),
d([r.Command.Boolean('--production')], f.prototype, 'production', void 0),
d([r.Command.Path('docker', 'build')], f.prototype, 'execute', null);
const u = { commands: [f] };
plugin = e;
})();
return plugin;
},
};

File diff suppressed because one or more lines are too long

801
.yarn/releases/yarn-3.2.4.cjs vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -2,17 +2,10 @@ nodeLinker: node-modules
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: '@yarnpkg/plugin-interactive-tools'
spec: "@yarnpkg/plugin-interactive-tools"
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: '@yarnpkg/plugin-workspace-tools'
spec: "@yarnpkg/plugin-workspace-tools"
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
spec: '@yarnpkg/plugin-version'
- path: .yarn/plugins/@yarnpkg/plugin-docker-build.cjs
spec: 'https://github.com/Dcard/yarn-plugins/releases/latest/download/plugin-docker-build.js'
spec: "@yarnpkg/plugin-version"
yarnPath: .yarn/releases/yarn-3.5.0.cjs
packageExtensions:
'@storybook/core-common@*':
dependencies:
'@storybook/react-vite': '7.0.5'
yarnPath: .yarn/releases/yarn-3.2.4.cjs

119
README.md
View File

@@ -18,28 +18,96 @@
## About
This repository contains multiple packages with separate [releases][github-releases]. You can find the assembled Discord API wrapper at [`discord.js`][source]. It is a powerful [Node.js](https://nodejs.org/en) module that allows you to easily interact with the [Discord API](https://discord.com/developers/docs/intro).
discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to easily interact with the
[Discord API](https://discord.com/developers/docs/intro).
## Packages
- Object-oriented
- Predictable abstractions
- Performant
- 100% coverage of the Discord API
- `discord.js` ([source][source]) - A powerful Node.js module for interacting with the Discord API
- `@discordjs/brokers` ([source][brokers-source]) - A collection of brokers for use with discord.js
- `@discordjs/builders` ([source][builders-source]) - A utility package for easily building Discord API payloads
- `@discordjs/collection` ([source][collection-source]) - A powerful utility data structure
- `@discordjs/core` ([source][core-source]) - A thinly abstracted wrapper around the core components of the Discord API
- `@discordjs/formatters` ([source][formatters-source]) - A collection of functions for formatting strings
- `@discordjs/proxy` ([source][proxy-source]) - A wrapper around `@discordjs/rest` for running an HTTP proxy
- `@discordjs/rest` ([source][rest-source]) - A module for interacting with the Discord REST API
- `@discordjs/voice` ([source][voice-source]) - A module for interacting with the Discord Voice API
- `@discordjs/util` ([source][util-source]) - A collection of utility functions
- `@discordjs/ws` ([source][ws-source]) - A wrapper around Discord's gateway
## Installation
**Node.js 16.9.0 or newer is required.**
```sh-session
npm install discord.js
yarn add discord.js
pnpm add discord.js
```
### Optional packages
- [zlib-sync](https://www.npmjs.com/package/zlib-sync) for WebSocket data compression and inflation (`npm install zlib-sync`)
- [erlpack](https://github.com/discord/erlpack) for significantly faster WebSocket data (de)serialisation (`npm install discord/erlpack`)
- [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`)
- [utf-8-validate](https://www.npmjs.com/package/utf-8-validate) in combination with `bufferutil` for much faster WebSocket processing (`npm install utf-8-validate`)
- [@discordjs/voice](https://www.npmjs.com/package/@discordjs/voice) for interacting with the Discord Voice API (`npm install @discordjs/voice`)
## Example usage
Install discord.js:
```sh-session
npm install discord.js
yarn add discord.js
pnpm add discord.js
```
Register a slash command against the Discord API:
```js
const { REST, Routes } = require('discord.js');
const commands = [
{
name: 'ping',
description: 'Replies with Pong!',
},
];
const rest = new REST({ version: '10' }).setToken(TOKEN);
(async () => {
try {
console.log('Started refreshing application (/) commands.');
await rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands });
console.log('Successfully reloaded application (/) commands.');
} catch (error) {
console.error(error);
}
})();
```
Afterwards we can create a quite simple example bot:
```js
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on('interactionCreate', async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
await interaction.reply('Pong!');
}
});
client.login(TOKEN);
```
## Links
- [Website][website] ([source][website-source])
- [Documentation][documentation]
- [Guide][guide] ([source][guide-source])
Also see the v13 to v14 [Update Guide][guide-update], which includes updated and removed items from the library.
See also the [Update Guide][guide-update], including updated and removed items in the library.
- [discord.js Discord server][discord]
- [Discord API Discord server][discord-api]
- [GitHub][source]
@@ -52,15 +120,18 @@ This repository contains multiple packages with separate [releases][github-relea
## Contributing
Please read through our [contribution guidelines][contributing] before starting a pull request. We welcome contributions of all kinds, not just code! If you're stuck for ideas, look for the [good first issue][good-first-issue] label on issues in the repository. If you have any questions about the project, feel free to ask them on [Discord][discord]. Before creating your own issue or pull request, always check to see if one already exists! Don't rush contributions, take your time and ensure you're doing it correctly.
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
[documentation][documentation].
See [the contribution guide][contributing] if you'd like to submit a PR.
## Help
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please join our [Discord server][discord].
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
[website]: https://discord.js.org
[website]: https://discord.js.org/
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
[documentation]: https://discord.js.org/docs
[documentation]: https://discord.js.org/#/docs
[guide]: https://discordjs.guide/
[guide-source]: https://github.com/discordjs/guide
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html
@@ -72,15 +143,3 @@ If you don't understand something in the documentation, you are experiencing pro
[rpc]: https://www.npmjs.com/package/discord-rpc
[rpc-source]: https://github.com/discordjs/RPC
[contributing]: https://github.com/discordjs/discord.js/blob/main/.github/CONTRIBUTING.md
[github-releases]: https://github.com/discordjs/discord.js/releases
[brokers-source]: https://github.com/discordjs/discord.js/tree/main/packages/brokers
[builders-source]: https://github.com/discordjs/discord.js/tree/main/packages/builders
[collection-source]: https://github.com/discordjs/discord.js/tree/main/packages/collection
[core-source]: https://github.com/discordjs/discord.js/tree/main/packages/core
[formatters-source]: https://github.com/discordjs/discord.js/tree/main/packages/formatters
[proxy-source]: https://github.com/discordjs/discord.js/tree/main/packages/proxy
[rest-source]: https://github.com/discordjs/discord.js/tree/main/packages/rest
[voice-source]: https://github.com/discordjs/discord.js/tree/main/packages/voice
[util-source]: https://github.com/discordjs/discord.js/tree/main/packages/util
[ws-source]: https://github.com/discordjs/discord.js/tree/main/packages/ws
[good-first-issue]: https://github.com/discordjs/discord.js/contribute

View File

@@ -45,7 +45,7 @@
*
* SUPPORTED TOKENS: <projectFolder>, <packageName>, <unscopedPackageName>
*/
"mainEntryPointFilePath": "<projectFolder>/dist-docs/index.d.ts",
"mainEntryPointFilePath": "<projectFolder>/dist/index.d.ts",
/**
* A list of NPM package names whose exports should be treated as part of this package.

View File

@@ -1,12 +1,11 @@
{
"extends": ["../../.eslintrc.json", "neon/react", "neon/next", "neon/edge", "@unocss", "neon/prettier"],
"extends": ["../../.eslintrc.json", "neon/react", "neon/astro", "neon/prettier"],
"settings": {
"react": {
"version": "detect"
}
},
"rules": {
"react/react-in-jsx-scope": 0,
"react/jsx-filename-extension": [1, { "extensions": [".tsx"] }]
"react/jsx-filename-extension": [1, { "extensions": [".tsx", ".astro"] }]
}
}

View File

@@ -13,13 +13,13 @@ pids
# Env
.env
.env*.local
# Dist
dist/
typings/
.cache/
build/
api/
src/styles/unocss.css
.next/
@@ -28,6 +28,3 @@ src/styles/unocss.css
coverage/
.vercel
public/searchIndex
.vscode
lighthouse-results/
.contentlayer

View File

@@ -1 +1,8 @@
module.exports = require('../../.prettierrc.json');
module.exports = {
...require('../../.prettierrc.json'),
plugins: [
'prettier-plugin-astro',
'prettier-plugin-tailwindcss', // MUST come last
],
pluginSearchDirs: false,
};

View File

@@ -13,16 +13,12 @@
</p>
</div>
## About
The official guide for discord.js, made to help you get started easily with the library.
## Links
- [Website][website] ([source][website-source])
- [Documentation][documentation]
- [Guide][guide] ([source][guide-source])
Also see the v13 to v14 [Update Guide][guide-update], which includes updated and removed items from the library.
See also the [Update Guide][guide-update], including updated and removed items in the library.
- [discord.js Discord server][discord]
- [Discord API Discord server][discord-api]
- [GitHub][source]
@@ -30,17 +26,16 @@ The official guide for discord.js, made to help you get started easily with the
## Contributing
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
[documentation][documentation].
See [the contribution guide][contributing] if you'd like to submit a PR.
## Help
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
[website]: https://discord.js.org
[website]: https://discord.js.org/
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
[documentation]: https://discord.js.org/docs
[documentation]: https://discord.js.org/
[guide]: https://discordjs.guide/
[guide-source]: https://github.com/discordjs/guide
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html

117
apps/guide/astro.config.ts Normal file
View File

@@ -0,0 +1,117 @@
import { fileURLToPath, URL } from 'node:url';
import image from '@astrojs/image';
import mdx from '@astrojs/mdx';
import prefetch from '@astrojs/prefetch';
import react from '@astrojs/react';
import { remarkCodeHike } from '@code-hike/mdx';
import { defineConfig } from 'astro/config';
import compress from 'astro-compress';
import critters from 'astro-critters';
import { type Node, toString } from 'hast-util-to-string';
import { h } from 'hastscript';
import { escape } from 'html-escaper';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypeSlug from 'rehype-slug';
import shikiThemeDarkPlus from 'shiki/themes/dark-plus.json' assert { type: 'json' };
import Unocss from 'unocss/astro';
const LinkIcon = h(
'svg',
{
width: '1rem',
height: '1rem',
viewBox: '0 0 24 24',
fill: 'none',
stroke: 'currentColor',
strokeWidth: '2',
strokeLinecap: 'round',
strokeLinejoin: 'round',
},
h('path', {
// eslint-disable-next-line id-length
d: 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71',
}),
h('path', {
// eslint-disable-next-line id-length
d: 'M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71',
}),
);
const createSROnlyLabel = (text: string) => {
const node = h('span.sr-only', `Section titled ${escape(text)}`);
node.properties!['is:raw'] = true;
return node;
};
const rootDir = new URL('../../', import.meta.url);
export default defineConfig({
integrations: [
react(),
mdx({
remarkPlugins: [[remarkCodeHike, { autoImport: false, theme: shikiThemeDarkPlus, lineNumbers: true }]],
rehypePlugins: [
rehypeSlug,
[
rehypeAutolinkHeadings,
{
properties: {
class:
'relative inline-flex w-6 h-6 place-items-center place-content-center outline-0 text-black dark:text-white ml-2',
},
behavior: 'after',
group: ({ tagName }: { tagName: string }) =>
h('div', {
class: `[&>*]:inline-block [&>h1]:m-0 [&>h2]:m-0 [&>h3]:m-0 [&>h4]:m-0 level-${tagName}`,
tabIndex: -1,
}),
content: (heading: Node) => [
h(
`span.anchor-icon`,
{
ariaHidden: 'true',
},
LinkIcon,
),
createSROnlyLabel(toString(heading)),
],
},
],
],
}),
image({
serviceEntryPoint: '@astrojs/image/sharp',
}),
prefetch({
throttle: 3,
}),
Unocss({
configFile: fileURLToPath(new URL('unocss.config.ts', rootDir)),
}),
critters(),
compress(),
],
markdown: {
extendDefaultPlugins: true,
syntaxHighlight: false,
},
vite: {
resolve: {
alias: {
'ariakit/button': fileURLToPath(new URL('node_modules/ariakit/esm/button/index.js', rootDir)),
'ariakit/disclosure': fileURLToPath(new URL('node_modules/ariakit/esm/disclosure/index.js', rootDir)),
'ariakit/separator': fileURLToPath(new URL('node_modules/ariakit/esm/separator/index.js', rootDir)),
'ariakit-utils/dom': fileURLToPath(new URL('node_modules/ariakit-utils/esm/dom.js', rootDir)),
'ariakit-utils/events': fileURLToPath(new URL('node_modules/ariakit-utils/esm/events.js', rootDir)),
'ariakit-utils/focus': fileURLToPath(new URL('node_modules/ariakit-utils/esm/focus.js', rootDir)),
'ariakit-utils/hooks': fileURLToPath(new URL('node_modules/ariakit-utils/esm/hooks.js', rootDir)),
'ariakit-utils/misc': fileURLToPath(new URL('node_modules/ariakit-utils/esm/misc.js', rootDir)),
'ariakit-utils/platform': fileURLToPath(new URL('node_modules/ariakit-utils/esm/platform.js', rootDir)),
'ariakit-utils/system': fileURLToPath(new URL('node_modules/ariakit-utils/esm/system.js', rootDir)),
'react-icons/fi': fileURLToPath(new URL('node_modules/react-icons/fi/index.esm.js', rootDir)),
'react-icons/vsc': fileURLToPath(new URL('node_modules/react-icons/vsc/index.esm.js', rootDir)),
'react-use': fileURLToPath(new URL('node_modules/react-use/esm/index.js', rootDir)),
},
},
},
});

View File

@@ -1,101 +0,0 @@
import { remarkCodeHike } from '@code-hike/mdx';
import { defineDocumentType, makeSource } from 'contentlayer/source-files';
// import { type Node, toString } from 'hast-util-to-string';
// import { h } from 'hastscript';
// import { escape } from 'html-escaper';
// import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypeSlug from 'rehype-slug';
import remarkGfm from 'remark-gfm';
import codeHikeThemeDarkPlus from './src/styles/code-hike-theme-dark-plus.json';
export const Content = defineDocumentType(() => ({
name: 'Content',
filePathPattern: `**/*.mdx`,
contentType: 'mdx',
fields: {
title: {
type: 'string',
required: true,
},
category: {
type: 'string',
required: true,
},
},
computedFields: {
slug: {
type: 'string',
// eslint-disable-next-line unicorn/prefer-string-replace-all
resolve: (doc) => doc._raw.flattenedPath.replace(/\d+-/g, ''),
},
url: {
type: 'string',
// eslint-disable-next-line unicorn/prefer-string-replace-all
resolve: (doc) => `/guide/${doc._raw.flattenedPath.replace(/\d+-/g, '')}`,
},
},
}));
// const LinkIcon = h(
// 'svg',
// {
// width: '1rem',
// height: '1rem',
// viewBox: '0 0 24 24',
// fill: 'none',
// stroke: 'currentColor',
// strokeWidth: '2',
// strokeLinecap: 'round',
// strokeLinejoin: 'round',
// },
// h('path', {
// // eslint-disable-next-line id-length
// d: 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71',
// }),
// h('path', {
// // eslint-disable-next-line id-length
// d: 'M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71',
// }),
// );
// const createSROnlyLabel = (text: any) => {
// const node = h('span.sr-only', `Section titled ${escape(text)}`);
// node.properties!['is:raw'] = true;
// return node;
// };
export default makeSource({
contentDirPath: 'src/content',
documentTypes: [Content],
mdx: {
remarkPlugins: [remarkGfm, [remarkCodeHike, { theme: codeHikeThemeDarkPlus, lineNumbers: true }]],
rehypePlugins: [
rehypeSlug,
// [
// rehypeAutolinkHeadings,
// {
// properties: {
// class:
// 'relative inline-flex w-6 h-6 place-items-center place-content-center outline-none text-black dark:text-white ml-2',
// },
// behavior: 'after',
// group: async ({ tagName }: { tagName: string }) =>
// h('div', {
// class: `[&>*]:inline-block [&>h1]:m-0 [&>h2]:m-0 [&>h3]:m-0 [&>h4]:m-0 level-${tagName}`,
// tabIndex: -1,
// }),
// content: (heading: Node) => [
// h(
// `span.anchor-icon`,
// {
// ariaHidden: 'true',
// },
// LinkIcon,
// ),
// createSROnlyLabel(toString(heading)),
// ],
// },
// ],
],
},
});

View File

@@ -1,5 +0,0 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@@ -1,24 +0,0 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable @typescript-eslint/no-require-imports */
// import bundleAnalyzer from '@next/bundle-analyzer';
// import { withContentlayer } from 'next-contentlayer';
const bundleAnalyzer = require('@next/bundle-analyzer');
const { withContentlayer } = require('next-contentlayer');
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer(
withContentlayer({
reactStrictMode: true,
experimental: {
appDir: true,
},
images: {
dangerouslyAllowSVG: true,
contentDispositionType: 'attachment',
contentSecurityPolicy: "default-src 'self'; frame-src 'none'; sandbox;",
},
}),
);

View File

@@ -5,23 +5,15 @@
"private": true,
"scripts": {
"test": "vitest run",
"test:lighthouse": "lighthouse http://localhost:3000 --output-path=./lighthouse-results",
"build:local": "yarn build:prod",
"build:prod": "yarn workspaces foreach -ptR run build && yarn build:css && yarn build:next",
"build:next": "next build",
"build:css": "yarn generate:css",
"build:analyze": "cross-env-shell ANALYZE=true yarn build:prod",
"preview": "next start",
"dev": "concurrently 'yarn dev:contentlayer' 'yarn dev:css' 'yarn dev:next'",
"dev:next": "next dev",
"dev:css": "yarn generate:css --watch",
"dev:contentlayer": "contentlayer dev",
"generate:css": "unocss 'src/**/*.tsx' '../../packages/ui/src/lib/components/**/*.tsx' --out-file ./src/styles/unocss.css --config ../../unocss.config.ts",
"lint": "prettier --check . && cross-env TIMING=1 eslint src --ext .mjs,.js,.cjs,.ts,.tsx --format=pretty",
"format": "prettier --write . && cross-env TIMING=1 eslint src --ext .mjs,.js,.cjs,.ts,.tsx --fix --format=pretty",
"build:prod": "yarn workspaces foreach -ptR run build && astro build",
"dev": "yarn workspaces foreach -ptR run build && astro dev",
"preview": "astro preview",
"lint": "prettier --check . && cross-env TIMING=1 eslint src --ext .mjs,.js,.cjs,.ts,.tsx,.astro --format=pretty",
"format": "prettier --write . && cross-env TIMING=1 eslint src --ext .mjs,.js,.cjs,.ts,.tsx,.astro --fix --format=pretty",
"fmt": "yarn format"
},
"type": "commonjs",
"type": "module",
"contributors": [
"Crawl <icrawltogo@gmail.com>"
],
@@ -44,59 +36,54 @@
},
"homepage": "https://discord.js.org",
"dependencies": {
"@code-hike/mdx": "^0.8.2",
"@code-hike/mdx": "^0.7.4",
"@discordjs/ui": "workspace:^",
"@react-icons/all-files": "^4.1.0",
"@vercel/analytics": "^0.1.11",
"@vercel/edge-config": "^0.1.7",
"@vercel/og": "^0.5.2",
"ariakit": "^2.0.0-next.44",
"cmdk": "^0.2.0",
"contentlayer": "^0.3.1",
"next": "^13.3.0",
"next-contentlayer": "^0.3.1",
"next-themes": "^0.2.1",
"ariakit": "^2.0.0-next.41",
"react": "^18.2.0",
"react-custom-scrollbars-2": "^4.5.0",
"react-dom": "^18.2.0",
"react-use": "^17.4.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-ignore": "^1.0.5",
"rehype-raw": "^6.1.1",
"rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1",
"server-only": "^0.0.1",
"sharp": "^0.32.0"
"react-icons": "^4.7.1",
"react-use": "^17.4.0"
},
"devDependencies": {
"@next/bundle-analyzer": "^13.3.0",
"@testing-library/react": "^14.0.0",
"@astrojs/image": "^0.12.0",
"@astrojs/mdx": "^0.12.0",
"@astrojs/prefetch": "^0.1.1",
"@astrojs/react": "^1.2.2",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@types/node": "18.15.11",
"@types/react": "^18.0.35",
"@types/react-dom": "^18.0.11",
"@unocss/cli": "^0.51.4",
"@unocss/eslint-config": "^0.51.4",
"@unocss/reset": "^0.51.4",
"@vitejs/plugin-react": "^3.1.0",
"@vitest/coverage-c8": "^0.30.1",
"concurrently": "^8.0.1",
"@types/node": "16.18.4",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.9",
"@types/react-syntax-highlighter": "^15.5.5",
"@unocss/cli": "^0.47.5",
"@unocss/reset": "^0.47.5",
"@vitejs/plugin-react": "^2.2.0",
"@vitest/coverage-c8": "^0.25.3",
"astro": "^1.6.12",
"astro-compress": "^1.1.15",
"astro-critters": "^1.1.15",
"cross-env": "^7.0.3",
"eslint": "^8.38.0",
"eslint-config-neon": "^0.1.42",
"eslint-formatter-pretty": "^5.0.0",
"happy-dom": "^9.7.1",
"eslint": "^8.28.0",
"eslint-config-neon": "^0.1.40",
"eslint-formatter-pretty": "^4.1.0",
"happy-dom": "^7.7.0",
"hast-util-to-string": "^2.0.0",
"hastscript": "^7.2.0",
"hastscript": "^7.1.0",
"html-escaper": "^3.0.3",
"lighthouse": "^10.1.1",
"prettier": "^2.8.7",
"typescript": "^5.0.4",
"unocss": "^0.51.4",
"vercel": "^28.18.5",
"vitest": "^0.29.8"
"prettier": "^2.8.0",
"prettier-plugin-astro": "^0.7.0",
"prettier-plugin-tailwindcss": "^0.2.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0",
"sharp": "^0.31.2",
"shiki": "^0.11.1",
"typescript": "^4.9.3",
"unocss": "^0.47.5",
"vercel": "^28.7.0",
"vitest": "^0.25.3"
},
"engines": {
"node": ">=18.13.0"
"node": ">=16.9.0"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,12 +0,0 @@
'use client';
export default function Error({ error }: { error: Error }) {
console.error(error);
return (
<div className="mx-auto max-w-lg min-h-screen flex flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">500</h1>
<h2 className="text-[2rem] md:text-[3rem]">Error.</h2>
</div>
);
}

View File

@@ -1,23 +0,0 @@
'use client';
import { Providers } from './providers';
import { inter } from '~/util/fonts';
export default function GlobalError({ error }: { error: Error }) {
console.error(error);
return (
<html className={inter.variable} lang="en" suppressHydrationWarning>
<body className="bg-light-600 dark:bg-dark-600 dark:text-light-900">
<Providers>
<main className="mx-auto max-w-2xl min-h-screen">
<div className="mx-auto max-w-lg min-h-screen flex flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">500</h1>
<h2 className="text-[2rem] md:text-[3rem]">Error.</h2>
</div>
</main>
</Providers>
</body>
</html>
);
}

View File

@@ -1 +0,0 @@
export { default } from '~/app/not-found';

View File

@@ -1,21 +0,0 @@
import { allContents } from 'contentlayer/generated';
import { notFound } from 'next/navigation';
import { Mdx } from '~/components/Mdx';
export async function generateStaticParams() {
return allContents.map((content) => ({ slug: [content.slug] }));
}
export default function Page({ params }: { params: { slug: string[] } }) {
const content = allContents.find((content) => content.slug === params.slug?.join('/'));
if (!content) {
notFound();
}
return (
<article className="max-w-none prose">
<Mdx code={content?.body.code ?? ''} />
</article>
);
}

View File

@@ -1,25 +0,0 @@
import type { PropsWithChildren } from 'react';
import { Providers } from './providers';
import Footer from '~/components/Footer';
import Header from '~/components/Header';
import { Nav } from '~/components/Nav';
export default function Layout({ children }: PropsWithChildren) {
return (
<Providers>
<main className="mx-auto max-w-7xl px-4 lg:max-w-full">
<Header />
<div className="relative top-6 mx-auto max-w-7xl gap-6 lg:max-w-full lg:flex">
<div className="lg:sticky lg:top-23 lg:h-[calc(100vh_-_105px)]">
<Nav />
</div>
<div className="mx-auto max-w-5xl min-w-xs w-full pb-10">
{children}
<Footer />
</div>
</div>
</main>
</Providers>
);
}

View File

@@ -1,3 +0,0 @@
export default function Page() {
return null;
}

View File

@@ -1,8 +0,0 @@
'use client';
import type { PropsWithChildren } from 'react';
import { NavProvider } from '~/contexts/nav';
export function Providers({ children }: PropsWithChildren) {
return <NavProvider>{children}</NavProvider>;
}

View File

@@ -1,86 +0,0 @@
import { Analytics } from '@vercel/analytics/react';
import type { Metadata } from 'next';
import type { PropsWithChildren } from 'react';
import { Providers } from './providers';
import { DESCRIPTION } from '~/util/constants';
import { inter, jetBrainsMono } from '~/util/fonts';
import '@unocss/reset/tailwind-compat.css';
import '~/styles/unocss.css';
import '~/styles/cmdk.css';
import '@code-hike/mdx/styles.css';
import '~/styles/ch.css';
import '~/styles/main.css';
export const metadata: Metadata = {
title: 'discord.js',
description: DESCRIPTION,
viewport: {
minimumScale: 1,
initialScale: 1,
width: 'device-width',
},
icons: {
other: [
{
url: '/favicon-32x32.png',
sizes: '32x32',
type: 'image/png',
},
{
url: '/favicon-16x16.png',
sizes: '16x16',
type: 'image/png',
},
],
apple: [
'/apple-touch-icon.png',
{
url: '/safari-pinned-tab.svg',
rel: 'mask-icon',
},
],
},
manifest: '/site.webmanifest',
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#f1f3f5' },
{ media: '(prefers-color-scheme: dark)', color: '#181818' },
],
colorScheme: 'light dark',
appleWebApp: {
title: 'discord.js',
},
applicationName: 'discord.js',
openGraph: {
siteName: 'discord.js',
type: 'website',
title: 'discord.js',
description: DESCRIPTION,
images: 'https://discordjs.dev/api/open-graph.png',
},
twitter: {
card: 'summary_large_image',
creator: '@iCrawlToGo',
},
other: {
'msapplication-TileColor': '#090a16',
},
};
export default function RootLayout({ children }: PropsWithChildren) {
return (
<html className={`${inter.variable} ${jetBrainsMono.variable}`} lang="en" suppressHydrationWarning>
<body className="bg-light-600 dark:bg-dark-600 dark:text-light-900">
<Providers>{children}</Providers>
<Analytics />
</body>
</html>
);
}

View File

@@ -1,20 +0,0 @@
export default function Loading() {
return (
<div className="mx-4 min-h-screen flex flex-col items-center justify-center gap-4">
<svg
className="h-9 w-9 animate-spin text-black dark:text-white"
fill="none"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path
className="opacity-75 dark:opacity-100"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
fill="currentColor"
/>
</svg>
<div className="text-lg font-medium">Loading...</div>
</div>
);
}

View File

@@ -1,16 +0,0 @@
import Link from 'next/link';
export default function NotFound() {
return (
<div className="mx-auto max-w-lg min-h-screen flex flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">404</h1>
<h2 className="text-[2rem] md:text-[3rem]">Not found.</h2>
<Link
className="h-11 flex flex-row transform-gpu cursor-pointer select-none appearance-none place-items-center border-0 rounded bg-blurple px-6 text-base font-semibold leading-none text-white no-underline outline-none active:translate-y-px focus:ring focus:ring-width-2 focus:ring-white"
href="/guide"
>
Take me back
</Link>
</div>
);
}

View File

@@ -1,3 +0,0 @@
export default function Page() {
return null;
}

View File

@@ -1,8 +0,0 @@
'use client';
import { ThemeProvider } from 'next-themes';
import type { PropsWithChildren } from 'react';
export function Providers({ children }: PropsWithChildren) {
return <ThemeProvider attribute="class">{children}</ThemeProvider>;
}

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="212" height="44" fill="none"><rect width="212" height="44" fill="#000" rx="8"/><path fill="#fff" d="M60.438 15.227V26.5h1.406v-4.023h2.836c2.117 0 3.625-1.493 3.625-3.602 0-2.148-1.477-3.648-3.61-3.648h-4.257Zm1.406 1.25h2.484c1.633 0 2.531.851 2.531 2.398 0 1.492-.93 2.352-2.53 2.352h-2.485v-4.75Zm11.5 10.171c2.399 0 3.883-1.656 3.883-4.359 0-2.71-1.484-4.36-3.883-4.36-2.398 0-3.883 1.65-3.883 4.36 0 2.703 1.485 4.36 3.883 4.36Zm0-1.21c-1.594 0-2.492-1.157-2.492-3.149 0-2 .898-3.148 2.492-3.148 1.594 0 2.492 1.148 2.492 3.148 0 1.992-.898 3.148-2.492 3.148Zm15.954-7.36h-1.352l-1.656 6.735h-.125l-1.883-6.735h-1.29l-1.882 6.735h-.125l-1.656-6.735h-1.36l2.36 8.422h1.36l1.874-6.516h.125l1.883 6.516h1.367l2.36-8.422Zm4.523 1.04c1.336 0 2.227.984 2.258 2.476h-4.64c.101-1.492 1.039-2.477 2.382-2.477Zm2.219 5.202c-.352.742-1.086 1.14-2.172 1.14-1.43 0-2.36-1.054-2.43-2.718v-.062h6.055v-.516c0-2.617-1.383-4.234-3.656-4.234-2.313 0-3.797 1.718-3.797 4.367 0 2.664 1.46 4.351 3.797 4.351 1.844 0 3.156-.89 3.547-2.328H96.04Zm3.242 2.18h1.344v-5.219c0-1.187.93-2.047 2.211-2.047.266 0 .75.047.86.078V17.97a5.77 5.77 0 0 0-.672-.04c-1.117 0-2.086.579-2.336 1.4h-.125v-1.25h-1.281V26.5Zm8.899-7.383c1.336 0 2.227.985 2.258 2.477h-4.641c.102-1.492 1.04-2.477 2.383-2.477Zm2.219 5.203c-.352.742-1.086 1.14-2.172 1.14-1.43 0-2.359-1.054-2.43-2.718v-.062h6.055v-.516c0-2.617-1.383-4.234-3.656-4.234-2.313 0-3.797 1.718-3.797 4.367 0 2.664 1.461 4.351 3.797 4.351 1.844 0 3.156-.89 3.547-2.328H110.4Zm6.36 2.328c1.164 0 2.164-.554 2.695-1.492h.125V26.5h1.281V14.734h-1.343v4.672h-.118c-.476-.922-1.468-1.476-2.64-1.476-2.141 0-3.539 1.718-3.539 4.36 0 2.648 1.382 4.358 3.539 4.358Zm.312-7.507c1.524 0 2.477 1.218 2.477 3.148 0 1.945-.946 3.148-2.477 3.148-1.539 0-2.461-1.18-2.461-3.148 0-1.96.93-3.148 2.461-3.148Zm14.462 7.507c2.133 0 3.531-1.726 3.531-4.359 0-2.648-1.391-4.36-3.531-4.36-1.156 0-2.18.571-2.641 1.477h-.125v-4.672h-1.344V26.5h1.282v-1.344h.125c.531.938 1.531 1.492 2.703 1.492Zm-.313-7.507c1.539 0 2.453 1.18 2.453 3.148 0 1.969-.914 3.148-2.453 3.148-1.531 0-2.484-1.203-2.484-3.148s.953-3.148 2.484-3.148Zm6.04 10.406c1.492 0 2.164-.578 2.882-2.531l3.29-8.938h-1.43l-2.305 6.93h-.125l-2.312-6.93h-1.453l3.117 8.43-.157.5c-.351 1.015-.773 1.383-1.546 1.383-.188 0-.399-.008-.563-.04V29.5c.188.031.422.047.602.047Zm17.391-3.047 3.898-11.273h-2.148l-2.813 8.921h-.132l-2.836-8.921h-2.227l3.938 11.273h2.32Zm8.016-7.18c1.164 0 1.93.813 1.969 2.078h-4.024c.086-1.25.899-2.078 2.055-2.078Zm1.984 4.828c-.281.633-.945.985-1.906.985-1.273 0-2.094-.89-2.141-2.313v-.101h5.969v-.625c0-2.696-1.461-4.313-3.898-4.313-2.477 0-4.016 1.727-4.016 4.477s1.516 4.414 4.031 4.414c2.016 0 3.446-.969 3.797-2.524h-1.836Zm3.547 2.352h1.938v-4.938c0-1.195.875-1.976 2.133-1.976.328 0 .843.055.992.11v-1.798c-.18-.054-.524-.085-.805-.085-1.101 0-2.023.625-2.258 1.468h-.132v-1.328h-1.868V26.5Zm13.501-5.672c-.203-1.797-1.532-3.047-3.727-3.047-2.57 0-4.078 1.649-4.078 4.422 0 2.813 1.516 4.469 4.086 4.469 2.164 0 3.508-1.203 3.719-2.992h-1.844c-.203.89-.875 1.367-1.883 1.367-1.32 0-2.117-1.047-2.117-2.844 0-1.773.789-2.797 2.117-2.797 1.063 0 1.703.594 1.883 1.422h1.844Zm5.117-1.508c1.164 0 1.93.813 1.969 2.078h-4.024c.086-1.25.899-2.078 2.055-2.078Zm1.985 4.828c-.282.633-.946.985-1.907.985-1.273 0-2.093-.89-2.14-2.313v-.101h5.968v-.625c0-2.696-1.461-4.313-3.898-4.313-2.477 0-4.016 1.727-4.016 4.477s1.516 4.414 4.032 4.414c2.015 0 3.445-.969 3.796-2.524h-1.835Zm3.625 2.352h1.937V14.648h-1.937V26.5ZM23.325 13l9.325 16H14l9.325-16Z"/><path stroke="#5E5E5E" d="M43.5 0v44"/></svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -1,79 +1,3 @@
import { FiExternalLink } from '@react-icons/all-files/fi/FiExternalLink';
import { BASE_URL, BASE_URL_LEGACY, PACKAGES, VERSION } from '~/util/constants';
interface DocsLinkOptions {
/**
* Whether to apply brackets to the end of the symbol to denote a method.
*
* @remarks Functions automatically infer this.
*/
brackets?: boolean;
/**
* The package.
*
* @defaultValue `'discord.js'`
*/
package?: (typeof PACKAGES)[number];
/**
* The initial documentation class, function, interface etc.
*
* @example `'Client'`
*/
parent: string;
/**
* Whether to reference a static property.
*
* @remarks
* This should only be used for the https://discord.js.org domain
* as static properties are not identified in the URL.
*/
static?: boolean;
/**
* The symbol belonging to the parent.
*
* @example '`login'`
*/
symbol?: string;
/**
* The type of the {@link DocsLinkOptions.parent}.
*
* @example `'class'`
* @example `'Function'`
*/
type: string;
}
export function DocsLink({
package: docs = PACKAGES[0],
type,
parent,
symbol,
brackets,
static: staticReference,
}: DocsLinkOptions) {
const bracketText = brackets || type.toUpperCase() === 'FUNCTION' ? '()' : '';
const trimmedSymbol = symbol;
let url;
let text;
if (docs === PACKAGES[0]) {
url = `${BASE_URL_LEGACY}/${VERSION}/${type}/${parent}`;
if (trimmedSymbol) url += `?scrollTo=${trimmedSymbol}`;
text = `${parent}${trimmedSymbol ? (trimmedSymbol.startsWith('s-') ? '.' : '#') : ''}${
// eslint-disable-next-line prefer-named-capture-group
trimmedSymbol ? `${trimmedSymbol.replace(/(e|s)-/, '')}` : ''
}${bracketText}`;
} else {
url = `${BASE_URL}/${docs}/stable/${parent}:${type}`;
if (trimmedSymbol) url += `#${trimmedSymbol}`;
text = `${parent}${trimmedSymbol ? `${staticReference ? '.' : '#'}${trimmedSymbol}` : ''}${bracketText}`;
}
return (
<a className="inline-flex flex-row place-items-center gap-1" href={url} rel="noopener noreferrer" target="_blank">
{text}
<FiExternalLink size={18} />
</a>
);
export function DocsLink() {
return null;
}

View File

@@ -0,0 +1,10 @@
import { FiExternalLink } from 'react-icons/fi';
export function ExternalLink({ href, title }: { href: string; title: string }) {
return (
<a className="text-blurple inline-flex place-items-center gap-2 text-sm font-semibold" href={href}>
<p>{title}</p>
<FiExternalLink size={18} />
</a>
);
}

View File

@@ -1,81 +0,0 @@
import Image from 'next/image';
import vercelLogo from '~/assets/powered-by-vercel.svg';
export default function Footer() {
return (
<footer className="md:pl-12 md:pr-12">
<div className="mx-auto max-w-6xl flex flex-col place-items-center gap-12 pt-12 lg:place-content-center">
<div className="w-full flex flex-col place-content-between place-items-center gap-12 md:flex-row md:gap-0">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"
rel="external noopener noreferrer"
target="_blank"
title="Vercel"
>
<Image
alt="Vercel"
blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAABLCAQAAAA1k5H2AAAAi0lEQVR42u3SMQEAAAgDoC251a3gL2SgmfBYBRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCAgwWEOSWBnYbKggAAAABJRU5ErkJggg=="
height={44}
placeholder="blur"
src={vercelLogo}
width={212}
/>
</a>
<div className="flex flex-row gap-6 md:gap-12">
<div className="flex flex-col gap-2">
<div className="text-lg font-semibold">Community</div>
<div className="flex flex-col gap-1">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord.gg/djs"
rel="external noopener noreferrer"
target="_blank"
>
Discord
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js/discussions"
rel="external noopener noreferrer"
target="_blank"
>
GitHub discussions
</a>
</div>
</div>
<div className="flex flex-col gap-2">
<div className="text-lg font-semibold">Project</div>
<div className="flex flex-col gap-1">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js"
rel="external noopener noreferrer"
target="_blank"
>
discord.js
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord.js.org/docs"
rel="noopener noreferrer"
target="_blank"
>
discord.js documentation
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord-api-types.dev"
rel="external noopener noreferrer"
target="_blank"
>
discord-api-types
</a>
</div>
</div>
</div>
</div>
</div>
</footer>
);
}

View File

@@ -1,91 +0,0 @@
'use client';
import { VscGithubInverted } from '@react-icons/all-files/vsc/VscGithubInverted';
import { VscMenu } from '@react-icons/all-files/vsc/VscMenu';
import { Button } from 'ariakit/button';
import dynamic from 'next/dynamic';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { Fragment, useMemo } from 'react';
import { useNav } from '~/contexts/nav';
const ThemeSwitcher = dynamic(async () => import('./ThemeSwitcher'));
export default function Header() {
const pathname = usePathname();
const { setOpened } = useNav();
const pathElements = useMemo(
() =>
pathname
.split('/')
.slice(1)
.map((path, idx, original) => (
<Link
className="rounded outline-none hover:underline focus:ring focus:ring-width-2 focus:ring-blurple"
href={`/${original.slice(0, idx + 1).join('/')}`}
key={`${path}-${idx}`}
>
{path}
</Link>
)),
[pathname],
);
const breadcrumbs = useMemo(
() =>
pathElements.flatMap((el, idx, array) => {
if (idx === 0) {
return (
<Fragment key={`${el.key}-${idx}`}>
<div className="mx-2">/</div>
<div>{el}</div>
<div className="mx-2">/</div>
</Fragment>
);
}
if (idx !== array.length - 1) {
return (
<Fragment key={`${el.key}-${idx}`}>
<div>{el}</div>
<div className="mx-2">/</div>
</Fragment>
);
}
return <div key={`${el.key}-${idx}`}>{el}</div>;
}),
[pathElements],
);
return (
<header className="sticky top-4 z-20 border border-light-900 rounded-md bg-white/75 shadow backdrop-blur-md dark:border-dark-100 dark:bg-dark-600/75">
<div className="block h-16 px-6">
<div className="h-full flex flex-row place-content-between place-items-center gap-8">
<Button
aria-label="Menu"
className="h-6 w-6 flex flex-row transform-gpu cursor-pointer select-none appearance-none place-items-center border-0 rounded bg-transparent p-0 text-sm font-semibold leading-none no-underline outline-none lg:hidden active:translate-y-px focus:ring focus:ring-width-2 focus:ring-blurple"
onClick={() => setOpened((open) => !open)}
>
<VscMenu size={24} />
</Button>
<div className="hidden lg:flex lg:grow lg:flex-row lg:overflow-hidden">{breadcrumbs}</div>
<div className="flex flex-row place-items-center gap-4">
<Button
aria-label="GitHub"
as="a"
className="h-6 w-6 flex flex-row transform-gpu cursor-pointer select-none appearance-none place-items-center border-0 rounded rounded-full bg-transparent p-0 text-sm font-semibold leading-none no-underline outline-none active:translate-y-px focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js"
rel="external noopener noreferrer"
target="_blank"
>
<VscGithubInverted size={24} />
</Button>
<ThemeSwitcher />
</div>
</div>
</div>
</header>
);
}

View File

@@ -1,16 +0,0 @@
'use client';
import { Alert, Section, DiscordMessages, DiscordMessage, DiscordMessageEmbed } from '@discordjs/ui';
import { useMDXComponent } from 'next-contentlayer/hooks';
import { DocsLink } from '~/components/DocsLink';
import { ResultingCode } from '~/components/ResultingCode';
export function Mdx({ code }: { code: string }) {
const Component = useMDXComponent(code);
return (
<Component
components={{ Alert, Section, DiscordMessages, DiscordMessage, DiscordMessageEmbed, DocsLink, ResultingCode }}
/>
);
}

View File

@@ -1,30 +0,0 @@
'use client';
import { Scrollbars } from 'react-custom-scrollbars-2';
import { Sidebar } from './Sidebar';
import { useNav } from '~/contexts/nav';
export function Nav() {
const { opened } = useNav();
return (
<nav
className={`dark:bg-dark-600/75 dark:border-dark-100 border-light-900 top-22 fixed bottom-4 left-4 right-4 z-20 mx-auto max-w-5xl rounded-md border bg-white/75 shadow backdrop-blur-md ${
opened ? 'block' : 'hidden'
} lg:min-w-xs lg:sticky lg:block lg:h-full lg:w-full lg:max-w-xs`}
>
<Scrollbars
autoHide
className="[&>div]:overscroll-none"
hideTracksWhenNotNeeded
renderThumbVertical={(props) => <div {...props} className="z-30 rounded bg-light-900 dark:bg-dark-100" />}
renderTrackVertical={(props) => (
<div {...props} className="absolute bottom-0.5 right-0.5 top-0.5 z-30 w-1.5 rounded" />
)}
universal
>
<Sidebar />
</Scrollbars>
</nav>
);
}

View File

@@ -0,0 +1,70 @@
import { Button } from 'ariakit/button';
import { useState, useEffect } from 'react';
import { FiCommand } from 'react-icons/fi';
import { VscColorMode, VscGithubInverted, VscMenu, VscSearch } from 'react-icons/vsc';
import { useMedia } from 'react-use';
import { Sidebar } from './Sidebar.jsx';
import type { MDXPage } from './SidebarItems.jsx';
export function Navbar({ pages }: { pages?: MDXPage[] | undefined }) {
const matches = useMedia('(min-width: 992px)', false);
const [opened, setOpened] = useState(false);
useEffect(() => {
if (matches) {
setOpened(false);
}
}, [matches]);
return (
<>
<header className="dark:bg-dark-600 dark:border-dark-100 bg-light-600 border-light-800 fixed top-0 left-0 z-20 w-full border-b">
<div className="h-18 block px-6">
<div className="flex h-full flex-row place-content-between place-items-center">
<Button
aria-label="Menu"
className="focus:ring-width-2 focus:ring-blurple flex h-6 w-6 transform-gpu cursor-pointer select-none appearance-none place-items-center rounded border-0 bg-transparent p-0 text-sm font-semibold leading-none no-underline outline-0 focus:ring active:translate-y-px lg:hidden"
onClick={() => setOpened((open) => !open)}
>
<VscMenu size={24} />
</Button>
<div className="hidden md:flex md:flex-row">Placeholder</div>
<div className="flex flex-row place-items-center gap-4">
<Button
as="div"
className="dark:bg-dark-800 focus:ring-width-2 focus:ring-blurple rounded bg-white px-4 py-2.5 outline-0 focus:ring"
// onClick={() => dialog?.toggle()}
>
<div className="flex flex-row place-items-center gap-4">
<VscSearch size={18} />
<span className="opacity-65">Search...</span>
<div className="opacity-65 flex flex-row place-items-center gap-2">
<FiCommand size={18} /> K
</div>
</div>
</Button>
<Button
aria-label="GitHub"
as="a"
className="focus:ring-width-2 focus:ring-blurple flex h-6 w-6 transform-gpu cursor-pointer select-none appearance-none place-items-center rounded rounded-full border-0 bg-transparent p-0 text-sm font-semibold leading-none no-underline outline-0 focus:ring active:translate-y-px"
href="https://github.com/discordjs/discord.js"
rel="noopener noreferrer"
target="_blank"
>
<VscGithubInverted size={24} />
</Button>
<Button
aria-label="Toggle theme"
className="focus:ring-width-2 focus:ring-blurple flex h-6 w-6 transform-gpu cursor-pointer select-none appearance-none place-items-center rounded-full rounded border-0 bg-transparent p-0 text-sm font-semibold leading-none no-underline outline-0 focus:ring active:translate-y-px"
// onClick={() => toggleTheme()}
>
<VscColorMode size={24} />
</Button>
</div>
</div>
</div>
</header>
<Sidebar opened={opened} pages={pages} />
</>
);
}

View File

@@ -1,19 +1,22 @@
import { useMemo, useState } from 'react';
import type { MarkdownHeading } from 'astro';
import { useEffect, useMemo, useState } from 'react';
import { Scrollbars } from 'react-custom-scrollbars-2';
import { VscListSelection } from 'react-icons/vsc';
import { useLocation } from 'react-use';
const LINK_HEIGHT = 30;
const INDICATOR_SIZE = 10;
const INDICATOR_OFFSET = (LINK_HEIGHT - INDICATOR_SIZE) / 2;
export function Outline({ headings }: { headings: any[] }) {
// eslint-disable-next-line react/hook-use-state
const [active /* setActive */] = useState(0);
export function Outline({ headings }: { headings: MarkdownHeading[] }) {
const state = useLocation();
const [active, setActive] = useState(0);
const headingItems = useMemo(
() =>
headings.map((heading, idx) => (
<a
className={`dark:border-dark-100 border-light-800 pl-6.5 focus:ring-width-2 focus:ring-blurple ml-[10px] border-l p-[5px] text-sm outline-none focus:rounded focus:border-0 focus:ring ${
className={`dark:border-dark-100 border-light-800 pl-6.5 focus:ring-width-2 focus:ring-blurple ml-[10px] border-l p-[5px] text-sm outline-0 focus:rounded focus:border-0 focus:ring ${
idx === active
? 'bg-blurple text-white'
: 'dark:hover:bg-dark-200 dark:active:bg-dark-100 hover:bg-light-700 active:bg-light-800'
@@ -29,32 +32,32 @@ export function Outline({ headings }: { headings: any[] }) {
[headings, active],
);
// useEffect(() => {
// const idx = headings.findIndex((heading) => heading.slug === state.hash?.slice(1));
// if (idx >= 0) {
// setActive(idx);
// }
// }, [state, headings]);
useEffect(() => {
const idx = headings.findIndex((heading) => heading.slug === state.hash?.slice(1));
if (idx >= 0) {
setActive(idx);
}
}, [state, headings]);
return (
<Scrollbars
autoHide
hideTracksWhenNotNeeded
renderThumbVertical={(props) => <div {...props} className="z-30 rounded bg-light-900 dark:bg-dark-100" />}
renderThumbVertical={(props) => <div {...props} className="dark:bg-dark-100 bg-light-900 z-30 rounded" />}
renderTrackVertical={(props) => (
<div {...props} className="absolute bottom-0.5 right-0.5 top-0.5 z-30 w-1.5 rounded" />
<div {...props} className="absolute top-0.5 right-0.5 bottom-0.5 z-30 w-1.5 rounded" />
)}
universal
>
<div className="flex flex-col break-all p-3 pb-8">
<div className="ml-2 mt-4 flex flex-row gap-2">
{/* <VscListSelection size={25} /> */}
<div className="mt-4 ml-2 flex flex-row gap-2">
<VscListSelection size={25} />
<span className="font-semibold">Contents</span>
</div>
<div className="ml-2 mt-4 flex flex-col gap-2">
<div className="mt-4 ml-2 flex flex-col gap-2">
<div className="relative flex flex-col">
<div
className="absolute h-[10px] w-[10px] border-2 border-black rounded-full bg-blurple dark:border-white"
className="bg-blurple absolute h-[10px] w-[10px] rounded-full border-2 border-black dark:border-white"
style={{
left: INDICATOR_SIZE / 2 + 0.5,
transform: `translateY(${active * LINK_HEIGHT + INDICATOR_OFFSET}px)`,

View File

@@ -1,7 +1,7 @@
export function PageButton({ url, title, direction }: { direction: 'next' | 'prev'; title: string; url: string }) {
return (
<a
className="flex flex-row flex-col transform-gpu cursor-pointer select-none appearance-none place-items-center gap-2 rounded bg-light-600 px-4 py-3 leading-none no-underline outline-none active:translate-y-px active:bg-light-800 dark:bg-dark-600 hover:bg-light-700 focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-400 dark:hover:bg-dark-500"
className="bg-light-600 hover:bg-light-700 active:bg-light-800 dark:bg-dark-600 dark:hover:bg-dark-500 dark:active:bg-dark-400 focus:ring-width-2 focus:ring-blurple flex transform-gpu cursor-pointer select-none appearance-none flex-row flex-col place-items-center gap-2 rounded py-3 px-4 leading-none no-underline outline-0 focus:ring active:translate-y-px"
href={url}
>
<h3 className="text-md font-semibold">{title}</h3>

View File

@@ -1,8 +0,0 @@
'use client';
import { Section as DJSSection, type SectionOptions } from '@discordjs/ui';
import type { PropsWithChildren } from 'react';
export function Section(options: PropsWithChildren<SectionOptions>) {
return <DJSSection {...options} />;
}

View File

@@ -1,62 +1,24 @@
'use client';
import { allContents } from 'contentlayer/generated';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { Section } from './Section';
import { useNav } from '~/contexts/nav';
const items = allContents.map((content) => ({
title: content.title,
category: content.category,
slug: content.slug,
href: content.url,
}));
function transformItemsByCategory(allContents: typeof items) {
return allContents.reduce<Record<string, typeof items>>((accumulator: any, content) => {
if (!accumulator[content.category]) {
accumulator[content.category] = [];
}
accumulator[content.category].push(content);
return accumulator;
}, {});
}
const itemsByCategory = transformItemsByCategory(items);
export function Sidebar() {
const pathname = usePathname();
const { setOpened } = useNav();
import { Scrollbars } from 'react-custom-scrollbars-2';
import type { MDXPage } from './SidebarItems.jsx';
export function Sidebar({ pages, opened }: { opened: boolean; pages?: MDXPage[] | undefined }) {
return (
<div className="flex flex-col gap-3 p-3">
{Object.keys(itemsByCategory).map((category, idx) => (
<Section
buttonClassName="bg-light-600 hover:bg-light-700 active:bg-light-800 dark:bg-dark-400 dark:hover:bg-dark-300 dark:active:bg-dark-400 focus:ring-width-2 focus:ring-blurple rounded p-3 outline-none focus:ring"
key={`${category}-${idx}`}
title={category}
>
{itemsByCategory[category]?.map((member, index) => (
<Link
className={`dark:border-dark-100 border-light-800 focus:ring-width-2 focus:ring-blurple ml-5 flex flex-col border-l p-[5px] pl-6 outline-none focus:rounded focus:border-0 focus:ring ${
decodeURIComponent(pathname ?? '') === member.href
? 'bg-blurple text-white'
: 'dark:hover:bg-dark-200 dark:active:bg-dark-100 hover:bg-light-700 active:bg-light-800'
}`}
href={member.href}
key={`${member.title}-${index}`}
onClick={() => setOpened(false)}
title={member.title}
>
<div className="flex flex-row place-items-center gap-2 lg:text-sm">
<span className="truncate">{member.title}</span>
</div>
</Link>
))}
</Section>
))}
</div>
<nav
className={`h-[calc(100vh - 73px)] dark:bg-dark-600 dark:border-dark-100 border-light-800 fixed top-[73px] left-0 bottom-0 z-20 w-full border-r bg-white ${
opened ? 'block' : 'hidden'
} lg:w-76 lg:max-w-76 lg:block`}
>
<Scrollbars
autoHide
hideTracksWhenNotNeeded
renderThumbVertical={(props) => <div {...props} className="dark:bg-dark-100 bg-light-900 z-30 rounded" />}
renderTrackVertical={(props) => (
<div {...props} className="absolute top-0.5 right-0.5 bottom-0.5 z-30 w-1.5 rounded" />
)}
universal
>
{pages ?? null}
</Scrollbars>
</nav>
);
}

View File

@@ -0,0 +1,51 @@
import { Section } from '@discordjs/ui';
import type { MDXInstance } from 'astro';
import { useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-use';
export type MDXPage = MDXInstance<{ category: string; title: string }>;
export function SidebarItems({ pages }: { pages: MDXPage[] }) {
const state = useLocation();
const [active, setActive] = useState<string | undefined>('');
const categories = useMemo(
() =>
pages.reduce<Record<string, MDXPage[]>>((acc, page) => {
if (acc[page.frontmatter.category]) {
acc[page.frontmatter.category]?.push(page);
} else {
acc[page.frontmatter.category] = [page];
}
return acc;
}, {}),
[pages],
);
useEffect(() => {
setActive(state.pathname);
}, [state]);
return Object.keys(categories).map((category, idx) => (
<Section key={idx} title={category}>
{categories[category]?.map((member, index) => (
<a
className={`dark:border-dark-100 border-light-800 focus:ring-width-2 focus:ring-blurple ml-5 flex flex-col border-l p-[5px] pl-6 outline-0 focus:rounded focus:border-0 focus:ring ${
(member.url || '/') === active
? 'bg-blurple text-white'
: 'dark:hover:bg-dark-200 dark:active:bg-dark-100 hover:bg-light-700 active:bg-light-800'
}`}
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
href={member.url || '/'}
key={index}
title={member.frontmatter.title}
>
<div className="flex flex-row place-items-center gap-2 lg:text-sm">
<span className="truncate">{member.frontmatter.title}</span>
</div>
</a>
)) ?? null}
</Section>
));
}

View File

@@ -0,0 +1,180 @@
---
import { Separator } from 'ariakit/separator';
import type { MarkdownLayoutProps } from 'astro';
import { ExternalLink } from './ExternalLink.jsx';
import { Navbar } from './Navbar.jsx';
import { Outline } from './Outline.jsx';
import { PageButton } from './PageButton.jsx';
import { SidebarItems } from './SidebarItems.jsx';
import { generateGithubURL } from '~/util/url.js';
const pages = await Astro.glob<{ category: string; title: string }>('../pages/**/*.mdx');
type Props = MarkdownLayoutProps<{}>;
const { headings, url, frontmatter } = Astro.props;
const groupedPages = pages.reduce<Record<string, typeof pages>>((acc, page) => {
const { category } = page.frontmatter;
acc[category] ??= [];
acc[category]?.push(page);
return acc;
}, {});
// @ts-expect-error props is not typed
const category = frontmatter.category as string;
const curCategoryPages = groupedPages[category];
const curCategoryIndex = curCategoryPages!.findIndex((page) => page.url === url);
const pagePrev = curCategoryPages![curCategoryIndex - 1];
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
const pageNext = curCategoryPages![curCategoryIndex + 1];
---
<script>
window.addEventListener('load', () => {
const headings = document.querySelectorAll(
'div.level-h1 > h1, div.level-h2 > h2, div.level-h3 > h3, div.level-h4 > h4',
);
const headingsObserver = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const location = window.location.toString().split('#')[0];
history.replaceState(null, '', location + '#' + entry.target.id);
}
});
},
{
root: null,
rootMargin: '-100px 0% -66%',
threshold: 1.0,
},
);
headings.forEach((heading) => headingsObserver.observe(heading));
});
</script>
<Navbar client:load>
<div class="flex flex-col gap-3 p-3 pb-32 lg:pb-12" slot="pages">
<SidebarItems client:load pages={pages} />
</div>
</Navbar>
<main class="pt-18 lg:pl-76 xl:pr-64">
<article class="dark:bg-dark-600 bg-light-600">
<div class="dark:bg-dark-800 relative z-10 min-h-[calc(100vh_-_70px)] bg-white p-6 pb-20 shadow">
<div class="prose max-w-full">
<slot />
</div>
<div
class="h-[calc(100vh - 72px)] dark:bg-dark-600 dark:border-dark-100 border-light-800 fixed top-[72px] right-0 bottom-0 z-20 hidden w-64 border-l bg-white pr-2 xl:block"
>
<Outline client:load headings={headings} />
</div>
<Separator className="my-5 border-light-800 dark:border-dark-100" />
<div class="flex flex-col space-y-5">
<div class="flex place-content-end">
<ExternalLink client:load href={generateGithubURL(url!)} title="Edit this page on github" />
</div>
<div class="flex w-full">
{
pagePrev && (
<PageButton
direction="prev"
title={pagePrev.frontmatter.title}
url={pagePrev.url === '' ? '/' : pagePrev.url!}
/>
)
}
<div class="ml-auto self-end justify-self-end">
{
pageNext && (
<PageButton
direction="next"
title={pageNext.frontmatter.title}
url={pageNext.url === '' ? '/' : pageNext.url!}
/>
)
}
</div>
</div>
</div>
</div>
<div class="h-76 md:h-52"></div>
<footer
class="dark:bg-dark-600 h-76 lg:pl-84 bg-light-600 xl:pr-76 fixed bottom-0 left-0 right-0 md:h-52 md:pl-4 md:pr-16"
>
<div class="mx-auto flex max-w-6xl flex-col place-items-center gap-12 pt-12 lg:place-content-center">
<div class="flex w-full flex-col place-content-between place-items-center gap-12 md:flex-row md:gap-0">
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"
rel="noopener noreferrer"
target="_blank"
title="Vercel"
>
<img alt="Vercel" src="/powered-by-vercel.svg" />
</a>
<div class="flex flex-row gap-6 md:gap-12">
<div class="flex flex-col gap-2">
<div class="text-lg font-semibold">Community</div>
<div class="flex flex-col gap-1">
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://discord.gg/djs"
rel="noopener noreferrer"
target="_blank"
>
Discord
</a>
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://github.com/discordjs/discord.js/discussions"
rel="noopener noreferrer"
target="_blank"
>
GitHub discussions
</a>
</div>
</div>
<div class="flex flex-col gap-2">
<div class="text-lg font-semibold">Project</div>
<div class="flex flex-col gap-1">
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://github.com/discordjs/discord.js"
rel="noopener noreferrer"
target="_blank"
>
discord.js
</a>
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://discordjs.guide"
rel="noopener noreferrer"
target="_blank"
>
discord.js guide
</a>
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://discord-api-types.dev"
rel="noopener noreferrer"
target="_blank"
>
discord-api-types
</a>
</div>
</div>
</div>
</div>
</div>
</footer>
</article>
<div>Test</div>
</main>

View File

@@ -1,20 +0,0 @@
'use client';
import { VscColorMode } from '@react-icons/all-files/vsc/VscColorMode';
import { Button } from 'ariakit/button';
import { useTheme } from 'next-themes';
export default function ThemeSwitcher() {
const { resolvedTheme, setTheme } = useTheme();
const toggleTheme = () => setTheme(resolvedTheme === 'light' ? 'dark' : 'light');
return (
<Button
aria-label="Toggle theme"
className="h-6 w-6 flex flex-row transform-gpu cursor-pointer select-none appearance-none place-items-center border-0 rounded rounded-full bg-transparent p-0 text-sm font-semibold leading-none no-underline outline-none active:translate-y-px focus:ring focus:ring-width-2 focus:ring-blurple"
onClick={() => toggleTheme()}
>
<VscColorMode size={24} />
</Button>
);
}

View File

@@ -1,177 +0,0 @@
---
title: How to contribute
category: Home
---
# How to contribute
Since this guide is made specifically for the discord.js community, we want to be sure to provide the most relevant and up-to-date content. We will, of course, make additions to the current pages and add new ones as we see fit, but fulfilling requests is how we know we're providing content you all want the most.
Requests may be as simple as "add an example to the [frequently asked questions](/popular-topics/faq.html) page", or as elaborate as "add a page regarding [sharding](/sharding/)". We'll do our best to fulfill all requests, as long as they're reasonable.
To make a request, simply head over to [the repository's issue tracker](https://github.com/discordjs/discord.js/issues) and [create a new issue](https://github.com/discordjs/discord.js/issues/new)! Title it appropriately, and let us know exactly what you mean inside the issue description. Make sure that you've looked around the site before making a request; what you want to request might already exist!
<Alert title="Tip" type="success">
Remember that you can always [fork the repository](https://github.com/discordjs/discord.js/fork) and [make a pull
request](https://github.com/discordjs/discord.js/pulls) if you want to add anything to the guide yourself!
</Alert>
We'll also get into some of the more advanced features this guide does below.
## Components
Throughout the guide, you'll see some components from the _`@discordjs/ui`_ package:
- _`Alert`_
- _`Section`_
- _`DiscordMessages`_, _`DiscordMessage`_, and _`DiscordMessageEmbed`_
Check the source of this page to see them in action!
### Alert
This component may take a _`title`_ and a _`type`_ of _`'danger' | 'info' | 'success' | 'warning'`_.
This uses _`title="Alert" type="info"`_:
<Alert title="Alert" type="info">
Use these appropriately!
</Alert>
### Section
<Section title="Expand me!" padding defaultClosed background gutter>
Well, hello there!
Whenever some text does not need to be in the main body, you can put it here.
- _`title`_: The title that'll appear.
- _`padding`_: Adds padding.
- _`dense`_: When _`padding`_ is specified, _`dense`_ could make it appear, well, dense.
- _`defaultClosed`_ Whether the section is closed by default. This one was.
- _`background`_ Adds background to the content.
- _`gutter`_: This adds a very small appealing space between the expansion of the section and its content.
</Section>
### DiscordMessages, DiscordMessage, and DiscordMessageEmbed
<DiscordMessages>
<DiscordMessage
author={{
avatar: '/assets/discordjs.png',
bot: true,
time: 'Today at 21:00',
username: 'Guide Bot',
}}
>
A _`DiscordMessage`_ must be within _`DiscordMessages`_.
</DiscordMessage>
<DiscordMessage
author={{
avatar: '/assets/discordjs.png',
bot: true,
time: 'Today at 21:01',
username: 'Guide Bot',
}}
reply={{
author: {
avatar: '/assets/discordjs.png',
bot: true,
username: 'Guide Bot',
},
content: 'A _`DiscordMessage`_ must be within _`DiscordMessages`_.',
}}
time="21:02"
>
It's much better to see the source code of this page to replicate and learn!
</DiscordMessage>
<DiscordMessage
author={{
avatar: '/assets/discordjs.png',
bot: true,
time: 'Today at 21:02',
username: 'Guide Bot',
}}
>
This message depicts the use of embeds.
<>
<DiscordMessageEmbed
author={{
avatar: '/assets/discordjs.png',
username: 'Guide Bot',
}}
footer={{ content: 'Sometimes, titles just have to be.' }}
title={{ title: 'An amazing title' }}
>
This is a description. You can put a description here. It must be descriptive!
</DiscordMessageEmbed>
<DiscordMessageEmbed
author={{
avatar: '/assets/discordjs.png',
username: 'Guide Bot',
}}
footer={{ content: "When one amazing title just wasn't enough." }}
title={{ title: 'Another amazing title' }}
>
Multiple embeds!
</DiscordMessageEmbed>
</>
</DiscordMessage>
<DiscordMessage
author={{
avatar: '/assets/discordjs.png',
bot: true,
time: 'Today at 21:03',
username: 'Guide Bot',
}}
interaction={{
author: {
avatar: '/assets/discordjs.png',
bot: true,
username: 'Guide Bot',
},
command: '/interaction',
}}
>
Interactions are supported! I definitely used a command.
</DiscordMessage>
</DiscordMessages>
## Code blocks
We use [Code Hike](https://codehike.org). Here are some example code blocks, which should be easy to grasp and learn upon reading the source code of this page:
<CH.Code>
```ts
const HELLO = 'hello' as const;
console.log(HELLO);
// "ts" is the language of the code block.
```
</CH.Code>
<CH.Code>
```ts fileName
const FILE_NAME = 'fileName' as const;
if (FILE_NAME.includes(' ')) throw new Error('Spaces cannot be used in file names.');
```
```ts anotherFileName
const FILE_NAME_2 = 'anotherFileName' as const;
// Putting code blocks together makes them appear in tabs, just like in your editor.
```
---
```ts requiredName
const FILE_NAME_3 = 'requiredName' as const;
if (!FILE_NAME) throw new Error('There must be a file name to use panels!');
// The --- divider was used to create a panel.
```
</CH.Code>
For more information, be sure to check out the [documentation](https://codehike.org/docs/ch-code).

View File

@@ -1,805 +0,0 @@
---
title: Updating to v14
category: Additional info
---
# Updating to v14
## Before you start
v14 requires Node 16.9 or higher to use, so make sure you're up to date. To check your Node.js version, use _`node --version`_ in your terminal or command prompt, and if it's not high enough, update it! There are many resources online to help you with this step based on your host system.
### Various packages are now included in v14
If you previously had _`@discordjs/builders`_, _`@discordjs/formatters`_, _`@discordjs/rest`_, or _`discord-api-types`_ manually installed, it's _highly_ recommended that you uninstall the packages to avoid package version conflicts.
<CH.Code>
```sh npm
npm uninstall @discordjs/builders @discordjs/formatters @discordjs/rest discord-api-types
```
```sh yarn
yarn remove @discordjs/builders @discordjs/formatters @discordjs/rest discord-api-types
```
```sh pnpm
pnpm remove @discordjs/builders @discordjs/formatters @discordjs/rest discord-api-types
```
</CH.Code>
## Breaking Changes
### API version
discord.js v14 makes the switch to Discord API v10!
### Common Breakages
### Enum Values
Any areas that used to accept a _`string`_ or _`number`_ type for an enum parameter will now only accept a _`number`_.
In addition, the old enums exported by discord.js v13 and lower are replaced with new enums from [discord-api-types](https://discord-api-types.dev/api/discord-api-types-v10).
#### New enum differences
Most of the difference between enums from discord.js and discord-api-types can be summarized as so:
1. Enums are singular, i.e., _`ApplicationCommandOptionTypes`_ -> _`ApplicationCommandOptionType`_
2. Enums that are prefixed with _`Message`_ no longer have the _`Message`_ prefix, i.e., _`MessageButtonStyles`_ -> _`ButtonStyle`_
3. Enum values are _`PascalCase`_ rather than `SCREAMING_SNAKE_CASE`, i.e., `.CHAT_INPUT` -> `.ChatInput`
<Alert title="Magic Numbers Warning" type="danger">
You might be inclined to a raw _`number`_ (most commonly referred to as [magic
numbers](https://en.wikipedia.org/wiki/Magic_number_(programming))) instead of enum values. This is highly
discouraged. Enums provide more readability and are more resistant to changes in the API. Magic numbers can obscure
the meaning of your code in many ways. Check out this [blog
post](https://blog.webdevsimplified.com/2020-02/magic-numbers) if you want more context on as to why they shouldn't be
used.
</Alert>
#### Common enum breakages
Areas like _`Client`_ initialization, JSON slash commands and JSON message components will likely need to be modified to accommodate these changes:
##### Common Client Initialization Changes
<CH.Code>
```diff
- import { Client, Intents } = from 'discord.js';
+ import { Client, GatewayIntentBits, Partials } = from 'discord.js';
- const client = new Client({ intents: [Intents.FLAGS.GUILDS], partials: ['CHANNEL'] });
+ const client = new Client({ intents: [GatewayIntentBits.Guilds], partials: [Partials.Channel] });
```
</CH.Code>
##### Common Application Command Data changes
<CH.Code>
```diff
+ import { ApplicationCommandType, ApplicationCommandOptionType } = from 'discord.js';
const command = {
name: 'ping',
- type: 'CHAT_INPUT',
+ type: ApplicationCommandType.ChatInput,
options: [{
name: 'option',
description: 'A sample option',
- type: 'STRING',
+ type: ApplicationCommandOptionType.String,
}],
};
```
</CH.Code>
##### Common Button Data changes
<CH.Code>
```diff
+ import { ButtonStyle } = from 'discord.js';
const button = {
label: 'test',
- style: 'PRIMARY',
+ style: ButtonStyle.Primary,
customId: '1234'
}
```
</CH.Code>
### Removal of method-based type guards
#### Channels
Some channel type guard methods that narrowed to one channel type have been removed. Instead compare the _`type`_ property against a [ChannelType](https://discord-api-types.dev/api/discord-api-types-v10/enum/ChannelType) enum member to narrow channels.
<CH.Code>
```diff
- channel.isText();
+ channel.type === ChannelType.GuildText;
- channel.isVoice();
+ channel.type === ChannelType.GuildVoice;
- channel.isDM();
+ channel.type === ChannelType.DM;
```
</CH.Code>
### Builders
Builders are no longer returned by the API like they were previously. For example, you send the API an <DocsLink type="class" parent="EmbedBuilder"/> but you receive an <DocsLink type="class" parent="Embed"/> of the same data. This may affect how your code handles received structures such as components. Refer to [message component changes section](#messagecomponent) for more details.
Added <DocsLink package="builders" type="Function" parent="disableValidators" /> and <DocsLink package="builders" type="Function" parent="enableValidators" /> as top-level exports which disable or enable validation (enabled by default).
### Consolidation of create & edit parameters
Various _`create()`_ and _`edit()`_ methods on managers and objects have had their parameters consolidated. The changes are below:
- <DocsLink type="class" parent="Guild" symbol="edit" brackets /> now takes _`reason`_ in the _`data`_ parameter
- <DocsLink type="class" parent="GuildChannel" symbol="edit" brackets /> now takes _`reason`_ in the _`data`_ parameter
- <DocsLink type="class" parent="GuildEmoji" symbol="edit" brackets /> now takes _`reason`_ in the _`data`_ parameter
- <DocsLink type="class" parent="Role" symbol="edit" brackets /> now takes _`reason`_ in the _`data`_ parameter
- <DocsLink type="class" parent="Sticker" symbol="edit" brackets /> now takes _`reason`_ in the _`data`_ parameter
- <DocsLink type="class" parent="ThreadChannel" symbol="edit" brackets /> now takes _`reason`_ in the _`data`_ parameter
- <DocsLink type="class" parent="GuildChannelManager" symbol="create" brackets /> now takes _`name`_ in the _`options`_ parameter
- <DocsLink type="class" parent="GuildChannelManager" symbol="createWebhook" brackets /> (and other text-based channels)
now takes _`channel`_ and _`name`_ in the _`options`_ parameter
- <DocsLink type="class" parent="GuildChannelManager" symbol="edit" brackets /> now takes _`reason`_ as a part of _`data`_
- <DocsLink type="class" parent="GuildEmojiManager" symbol="edit" brackets /> now takes _`reason`_ as a part of _`data`_
- <DocsLink type="class" parent="GuildManager" symbol="create" brackets /> now takes _`name`_ as a part of _`options`_
- <DocsLink type="class" parent="GuildMemberManager" symbol="edit" brackets /> now takes _`reason`_ as a part of _`data`_
- <DocsLink type="class" parent="GuildMember" symbol="edit" brackets /> now takes _`reason`_ as a part of _`data`_
- <DocsLink type="class" parent="GuildStickerManager" symbol="edit" brackets /> now takes _`reason`_ as a part of _`data`_
- <DocsLink type="class" parent="RoleManager" symbol="edit" brackets /> now takes _`reason`_ as a part of _`options`_
- <DocsLink type="class" parent="Webhook" symbol="edit" brackets /> now takes _`reason`_ as a part of _`options`_
- <DocsLink type="class" parent="GuildEmojiManager" symbol="create" brackets /> now takes _`attachment`_ and _`name`_ as
a part of _`options`_
- <DocsLink type="class" parent="GuildStickerManager" symbol="create" brackets /> now takes _`file`_, _`name`_, and _`tags`_
as a part of _`options`_
### Activity
The following properties have been removed as they are not supported by the API:
- _`Activity#id`_
- _`Activity#platform`_
- _`Activity#sessionId`_
- _`Activity#syncId`_
### Application
_`Application#fetchAssets()`_ has been removed as it is no longer supported by the API.
### BitField
- BitField constituents now have a _`BitField`_ suffix to avoid naming conflicts with the enum names:
```diff
- new Permissions();
+ new PermissionsBitField();
- new MessageFlags();
+ new MessageFlagsBitField();
- new ThreadMemberFlags();
+ new ThreadMemberFlagsBitField();
- new UserFlags();
+ new UserFlagsBitField();
- new SystemChannelFlags();
+ new SystemChannelFlagsBitField();
- new ApplicationFlags();
+ new ApplicationFlagsBitField();
- new Intents();
+ new IntentsBitField();
- new ActivityFlags();
+ new ActivityFlagsBitField();
```
- _`#FLAGS`_ has been renamed to _`#Flags`_
### CDN
The methods that return CDN URLs have changed. Here is an example on a `User`:
<CH.Code>
```diff
- const url = user.displayAvatarURL({ dynamic: true, format: "png", size: 1024 });
+ const url = user.displayAvatarURL({ extension: "png", size: 1024 });
```
</CH.Code>
Dynamic URLs use <DocsLink package="rest" type="Interface" parent="ImageURLOptions"/> and static URLs use <DocsLink package="rest" type="Interface" parent="BaseImageURLOptions"/>. Since dynamic URLs are returned by default, this option has been renamed to _`forceStatic`_ which forces the return of a static URL. Additionally, _`format`_ has been renamed to _`extension`_.
### CategoryChannel
<DocsLink type="class" parent="CategoryChannel" symbol="children" /> is no longer a _`Collection`_ of channels the category
contains. It is now a <DocsLink type="class" parent="CategoryChannelChildManager" />. This also means
_`CategoryChannel#createChannel()`_ has been moved to the <DocsLink type="class" parent="CategoryChannelChildManager" />.
### Channel
The following type guards have been removed:
- _`Channel#isText()`_
- _`Channel#isVoice()`_
- _`Channel#isDirectory()`_
- _`Channel#isDM()`_
- _`Channel#isGroupDM()`_
- _`Channel#isCategory()`_
- _`Channel#isNews()`_
Refer to [this section](#channels) for more context.
The base channel class is now <DocsLink type="class" parent="BaseChannel"/>.
### Client
The _`restWsBridgeTimeout`_ client option has been removed.
### CommandInteractionOptionResolver
<DocsLink type="class" parent="CommandInteractionOptionResolver" symbol="getMember" brackets /> no longer has a parameter
for _`required`_.[^1]
### Constants
- Many constant objects and key arrays are now top-level exports. For example:
<CH.Code>
```diff
- import { Constants } = from 'discord.js';
- const { Colors } = Constants;
+ import { Colors } = from 'discord.js';
```
</CH.Code>
- The refactored constants structures have _`PascalCase`_ member names as opposed to _`SCREAMING_SNAKE_CASE`_ member names.
- Many of the exported constants structures have been replaced and renamed:
<CH.Code>
```diff
- Opcodes
+ GatewayOpcodes
- WSEvents
+ GatewayDispatchEvents
- WSCodes
+ GatewayCloseCodes
- InviteScopes
+ OAuth2Scopes
```
</CH.Code>
### Events
The _`message`_ and _`interaction`_ events are now removed. Use <DocsLink type="class" parent="Client" symbol="e-messageCreate"/> and <DocsLink type="class" parent="Client" symbol="e-interactionCreate"/> instead.
_`Client#applicationCommandCreate`_, _`Client#applicationCommandDelete`_, and _`Client#applicationCommandUpdate`_ have all been removed.[^2]
The <DocsLink type="class" parent="Client" symbol="e-threadMembersUpdate"/> event now emits the users that were added, the users that were removed, and the thread respectively.
### GuildBanManager
Developers should utilise _`deleteMessageSeconds`_ instead of _`days`_ and _`deleteMessageDays`_:
<CH.Code>
```diff
<GuildBanManager>.create('123456789', {
- days: 3
- deleteMessageDays: 3
+ deleteMessageSeconds: 3 * 24 * 60 * 60
});
```
</CH.Code>
_`deleteMessageDays`_ and _`days`_ are both deprecated and will be removed in the future.
### Guild
<DocsLink type="class" parent="Guild" symbol="setRolePositions" brackets /> and <DocsLink
type="class"
parent="Guild"
symbol="setChannelPositions"
brackets
/> have been removed. Use <DocsLink type="class" parent="RoleManager" symbol="setPositions" brackets /> and <DocsLink
type="class"
parent="GuildChannelManager"
symbol="setPositions"
brackets
/> instead respectively.
<DocsLink type="class" parent="Guild" symbol="maximumPresences" /> no longer has a default value of 25,000.
_`Guild#me`_ has been moved to <DocsLink type="class" parent="GuildMemberManager" symbol="me" />.[^3]
### GuildAuditLogs & GuildAuditLogsEntry
_`GuildAuditLogs.build()`_ has been removed as it has been deemed defunct. There is no alternative.
The following properties & methods have been moved to the <DocsLink type="class" parent="GuildAuditLogsEntry" /> class:
- `GuildAuditLogs.Targets`
- `GuildAuditLogs.actionType()`
- `GuildAuditLogs.targetType()`
### GuildMember
<DocsLink type="class" parent="GuildMember" symbol="pending" /> is now nullable to account for partial guild members.[^4]
### IntegrationApplication
_`IntegrationApplication#summary`_ has been removed as it is no longer supported by the API.
### Interaction
Whenever an interaction is replied to and one fetches the reply, it could possibly give an [APIMessage](https://discord-api-types.dev/api/discord-api-types-v10/interface/APIMessage) if the guild was not cached. However, interaction replies now always return a discord.js <DocsLink type="class" parent="Message"/> object with _`fetchReply`_ as _`true`_.
The base interaction class is now <DocsLink type="class" parent="BaseInteraction"/>.
### Invite
<DocsLink type="class" parent="Invite" symbol="inviter" /> is now a getter and resolves structures from the cache.
### MessageAttachment
- _`MessageAttachment`_ has now been renamed to <DocsLink type="class" parent="AttachmentBuilder" />.
<CH.Code>
```diff
- new MessageAttachment(buffer, 'image.png');
+ new AttachmentBuilder(buffer, { name: 'image.png' });
```
</CH.Code>
### MessageComponent
- MessageComponents have been renamed as well. They no longer have the _`Message`_ prefix, and now have a _`Builder`_ suffix:
<CH.Code>
```diff
- const button = new MessageButton();
+ const button = new ButtonBuilder();
- const selectMenu = new MessageSelectMenu();
+ const selectMenu = new StringSelectMenuBuilder();
- const actionRow = new MessageActionRow();
+ const actionRow = new ActionRowBuilder();
- const textInput = new TextInputComponent();
+ const textInput = new TextInputBuilder();
```
</CH.Code>
- Components received from the API are no longer directly mutable. If you wish to mutate a component from the API, use _`ComponentBuilder#from()`_. For example, if you want to make a button mutable:
<CH.Code>
```diff
- const editedButton = receivedButton.setDisabled(true);
+ import { ButtonBuilder } = from 'discord.js';
+ const editedButton = ButtonBuilder.from(receivedButton).setDisabled(true);
```
</CH.Code>
### MessageManager
The second paramter of <DocsLink type="class" parent="MessageManager" symbol="fetch" brackets /> has been removed. The <DocsLink type="class" parent="BaseFetchOptions" /> the second parameter once was is now merged into the first parameter.
<CH.Code>
```diff
- messageManager.fetch('1234567890', { cache: false, force: true });
+ messageManager.fetch({ message: '1234567890', cache: false, force: true });
```
</CH.Code>
### MessageSelectMenu
- _`MessageSelectMenu`_ has been renamed to <DocsLink type="class" parent="StringSelectMenuBuilder" />.
- _`StringSelectMenuBuilder#addOption()`_ has been removed. Use <DocsLink type="class" parent="StringSelectMenuBuilder" symbol="addOptions" brackets /> instead.
### MessageEmbed
- _`MessageEmbed`_ has now been renamed to <DocsLink type="class" parent="EmbedBuilder" />.
- <DocsLink package="builders" type="Class" parent="EmbedBuilder" symbol="setAuthor" brackets /> now accepts a sole <DocsLink
package="builders"
type="TypeAlias"
parent="EmbedAuthorOptions"
/> object.
- <DocsLink package="builders" type="Class" parent="EmbedBuilder" symbol="setFooter" brackets /> now accepts a sole <DocsLink
package="builders"
type="TypeAlias"
parent="EmbedFooterOptions"
/> object.
- _`EmbedBuilder#addField()`_ has been removed. Use <DocsLink package="builders" type="Class" parent="EmbedBuilder" symbol="addFields" brackets/> instead.
<CH.Code>
```diff
- new MessageEmbed().addField('Inline field title', 'Some value here', true);
+ new EmbedBuilder().addFields([
+ { name: 'one', value: 'one', inline: true },
+ { name: 'two', value: 'two', inline: true },
+]);
```
</CH.Code>
### Modal
- _`Modal`_ has been renamed <DocsLink type="class" parent="ModalBuilder" />.
<CH.Code>
```diff
- const modal = new Modal();
+ const modal = new ModalBuilder();
```
</CH.Code>
### PartialTypes
The _`PartialTypes`_ string array has been removed. Use the <DocsLink type="typedef" parent="Partials" /> enum instead.
In addition to this, there is now a new partial: _`Partials.ThreadMember`_.
### Permissions
The thread permissions _`USE_PUBLIC_THREADS`_ and _`USE_PRIVATE_THREADS`_ have been removed as they are deprecated in the API. Use _`CREATE_PUBLIC_THREADS`_ and _`CREATE_PRIVATE_THREADS`_ respectively.
### PermissionOverwritesManager
Overwrites are now keyed by the _`PascalCase`_ permission key rather than the _`SCREAMING_SNAKE_CASE`_ permission key.
### REST Events
#### apiRequest
This REST event has been removed as discord.js now uses [Undici](https://github.com/nodejs/undici) as the underlying request handler. You must now use a [Diagnostics Channel](https://undici.nodejs.org/#/docs/api/DiagnosticsChannel). Here is a simple example:
<CH.Code>
```js JavaScript
import diagnosticsChannel from 'node:diagnostics_channel';
diagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {
const { request } = data;
console.log(request.method); // Log the method
console.log(request.path); // Log the path
console.log(request.headers); // Log the headers
console.log(request); // Or just log everything!
});
```
```ts TypeScript
import diagnosticsChannel from 'node:diagnostics_channel';
import { type DiagnosticsChannel } from 'undici';
diagnosticsChannel.channel('undici:request:create').subscribe((data) => {
const { request } = data as DiagnosticsChannel.RequestCreateMessage;
console.log(request.method); // Log the method
console.log(request.path); // Log the path
console.log(request.headers); // Log the headers
console.log(request); // Or just log everything!
});
```
</CH.Code>
You can find further examples at the [Undici Diagnostics Channel documentation](https://undici.nodejs.org/#/docs/api/DiagnosticsChannel).
#### apiResponse
This REST event has been renamed to _`response`_ and moved to <DocsLink type="class" parent="Client" symbol="rest"/>:
<CH.Code>
```diff
- client.on('apiResponse', ...);
+ client.rest.on('response', ...);
```
</CH.Code>
#### invalidRequestWarning
This REST event has been moved to <DocsLink type="class" parent="Client" symbol="rest"/>:
<CH.Code>
```diff
- client.on('invalidRequestWarning', ...);
+ client.rest.on('invalidRequestWarning', ...);
```
</CH.Code>
#### rateLimit
This REST event has been renamed to _`rateLimited`_ and moved to <DocsLink type="class" parent="Client" symbol="rest"/>:
<CH.Code>
```diff
- client.on('rateLimit', ...);
+ client.rest.on('rateLimited', ...);
```
</CH.Code>
### RoleManager
_`Role.comparePositions()`_ has been removed. Use <DocsLink type="class" parent="RoleManager" symbol="comparePositions" brackets/> instead.
### Sticker
<DocsLink type="class" parent="Sticker" symbol="tags" /> is now a nullable string (_`string | null`_). Previously, it was
a nullable array of strings (_`string[] | null`_).[^5]
### ThreadChannel
The _`MAX`_ helper used in _`ThreadAutoArchiveDuration`_ has been removed. Discord has since allowed any guild to use any auto archive time which makes this helper redundant.
### ThreadMemberManager
The second parameter of <DocsLink type="class" parent="ThreadMemberManager" symbol="fetch" brackets /> has been removed. The <DocsLink type="class" parent="BaseFetchOptions" /> the second parameter once was is now merged into the first parameter. In addition, the boolean helper to specify _`cache`_ has been removed.
Usage is now as follows:
<CH.Code>
```diff
// The second parameter is merged into the first parameter.
- threadMemberManager.fetch('1234567890', { cache: false, force: true });
+ threadMemberManager.fetch({ member: '1234567890', cache: false, force: true });
// The lone boolean has been removed. One must be explicit here.
- threadMemberManager.fetch(false);
+ threadMemberManager.fetch({ cache: false });
```
</CH.Code>
### Util
_`Util.removeMentions()`_ has been removed. To control mentions, you should use _`allowedMentions`_ on <DocsLink type="typedef" parent="BaseMessageOptions" /> instead.
_`Util.splitMessage()`_ has been removed. This utility method is something the developer themselves should do.
_`Util.resolveAutoArchiveMaxLimit()`_ has been removed. Discord has since allowed any guild to use any auto archive time which makes this method redundant.
Other functions in _`Util`_ have been moved to top-level exports so you can directly import them from discord.js.
<CH.Code>
```diff
- import { Util } from 'discord.js';
- Util.escapeMarkdown(message);
+ import { escapeMarkdown } from 'discord.js';
+ escapeMarkdown(message);
```
</CH.Code>
### .deleted fields have been removed
You can no longer use the _`deleted`_ property to check if a structure was deleted.[^6]
### VoiceChannel
_`VoiceChannel#editable`_ has been removed. You should use <DocsLink type="class" parent="GuildChannel" symbol="manageable"/> instead.
### VoiceRegion
_`VoiceRegion#vip`_ has been removed as it is no longer part of the API.
### Webhook
The second parameter of <DocsLink type="class" parent="Webhook" symbol="fetchMessage" brackets/> no longer allows a boolean to be passed. The _`cache`_ option in <DocsLink type="typedef" parent="WebhookFetchMessageOptions"/> should be used instead.
## Features
### ApplicationCommand
NFSW commands are supported.
### AutocompleteInteraction
<DocsLink type="class" parent="AutocompleteInteraction" symbol="commandGuildId" /> has been added which is the id of the
guild the invoked application command is registered to.
### BaseChannel
Added support for <DocsLink type="class" parent="BaseChannel" symbol="flags" />.
Store channels have been removed as they are no longer part of the API.
<DocsLink type="class" parent="BaseChannel" symbol="url" /> has been added which is a link to a channel, just like in the
client.
Additionally, new typeguards have been added:
- <DocsLink type="class" parent="BaseChannel" symbol="isDMBased" brackets />
- <DocsLink type="class" parent="BaseChannel" symbol="isTextBased" brackets />
- <DocsLink type="class" parent="BaseChannel" symbol="isVoiceBased" brackets />
### BaseInteraction
Added <DocsLink type="class" parent="BaseInteraction" symbol="isRepliable" brackets /> to check whether a given interaction can be replied to.
### ClientApplication
Added support for role connection metadata.
### Collection
- Added <DocsLink package="collection" type="Class" parent="Collection" symbol="merge" brackets/> and <DocsLink package="collection" type="Class" parent="Collection" symbol="combineEntries" brackets/>.
- Added <DocsLink package="collection" type="TypeAlias" parent="ReadonlyCollection"/> which indicates an immutable _`Collection`_.
### Collector
A new <DocsLink type="class" parent="Collector" symbol="e-ignore"/> event has been added which is emitted whenever an element is not collected by the collector.
Component collector options now use the [ComponentType](https://discord-api-types.dev/api/discord-api-types-v10/enum/ComponentType) enum values:
<CH.Code>
```diff
+ import { ComponentType } from 'discord.js';
const collector = interaction.channel.createMessageComponentCollector({
filter,
- componentType: 'BUTTON',
+ componentType: ComponentType.Button,
time: 20000
});
```
</CH.Code>
### CommandInteraction
<DocsLink type="class" parent="CommandInteraction" symbol="commandGuildId" /> has been added which is the id of the guild
the invoked application command is registered to.
### CommandInteractionOptionResolver
<DocsLink type="class" parent="CommandInteractionOptionResolver" symbol="getChannel" brackets /> now has a third parameter
which narrows the channel type.
### Events
Added support for <DocsLink type="class" parent="Client" symbol="e-guildAuditLogEntryCreate" /> event.
### ForumChannel
Added support for forum channels.
Added support for <DocsLink type="class" parent="ForumChannel" symbol="defaultForumLayout" />.
### Guild
Added support for <DocsLink type="class" parent="Guild" symbol="setMFALevel" brackets /> which sets the guild's MFA level.
Added support for <DocsLink type="class" parent="Guild" symbol="maxVideoChannelUsers"/>. which indicates the maximum number of video channel users.
Added support for <DocsLink type="class" parent="Guild" symbol="maxStageVideoChannelUsers" />. which indicates the maximum number of video channel users for stage channels.
Added support for <DocsLink type="class" parent="Guild" symbol="disableInvites" brackets />. which disables the guild's invites.
Added support for the _`after`_ parameter in <DocsLink type="class" parent="Guild" symbol="fetchAuditLogs" brackets />.
### GuildChannelManager
_`videoQualityMode`_ may be used whilst creating a channel to initially set the camera video quality mode.
### GuildEmojiManager
Added <DocsLink type="class" parent="GuildEmojiManager" symbol="delete" brackets /> and <DocsLink type="class" parent="GuildEmojiManager" symbol="edit" brackets /> for managing existing guild emojis.
### GuildForumThreadManager
Added <DocsLink type="class" parent="GuildForumThreadManager" /> as manager for threads in forum channels.
### GuildMember
Added support for <DocsLink type="class" parent="GuildMember" symbol="flags"/>.
### GuildMembersChunk
This object now supports the _`notFound`_ property.
### GuildMemberManager
Added <DocsLink type="class" parent="GuildMemberManager" symbol="fetchMe" brackets /> to fetch the client user in the guild.
Added <DocsLink type="class" parent="GuildMemberManager" symbol="addRole" brackets /> and <DocsLink type="class" parent="GuildMemberManager" symbol="removeRole" brackets />. These methods allow a single addition or removal of a role respectively to a guild member, even if uncached.
### GuildTextThreadManager
Added <DocsLink type="class" parent="GuildTextThreadManager" /> as manager for threads in text channels and announcement channels.
### Message
<DocsLink type="class" parent="Message" symbol="position" /> has been added as an approximate position in a thread.
Added support for role subscription data.
### MessageReaction
Added <DocsLink type="class" parent="MessageReaction" symbol="react" brackets /> to make the client user react with the reaction the class belongs to.
### Role
Added support for role subscriptions.
### StageChannel
Stage channels now allow messages to be sent in them, much like voice channels.
### Sticker
Added support for GIF stickers.
### ThreadMemberManager
The new _`withMember`_ options returns the associated guild member with the thread member.
When fetching multiple thread members alongside _`withMember`_, paginated results will be returned. The _`after`_ and _`limit`_ option are supported in this scenario.
### Webhook
Added <DocsLink type="class" parent="Webhook" symbol="applicationId" />.
Added the _`threadName`_ property in <DocsLink type="typedef" parent="WebhookMessageCreateOptions"/> which allows a webhook to create a post in a forum channel.
[^1]: https://github.com/discordjs/discord.js/pull/7188
[^2]: https://github.com/discordjs/discord.js/pull/6492
[^3]: https://github.com/discordjs/discord.js/pull/7669
[^4]: https://github.com/discordjs/discord.js/issues/6546
[^5]: https://github.com/discordjs/discord.js/pull/8010
[^6]: https://github.com/discordjs/discord.js/issues/7091

View File

@@ -1,27 +0,0 @@
'use client';
import {
type PropsWithChildren,
type Dispatch,
type SetStateAction,
createContext,
useContext,
useState,
useMemo,
} from 'react';
export const NavContext = createContext<{ opened: boolean; setOpened: Dispatch<SetStateAction<boolean>> }>({
opened: false,
setOpened: (_) => {},
});
export const NavProvider = ({ children }: PropsWithChildren) => {
const [opened, setOpened] = useState(false);
const value = useMemo(() => ({ opened, setOpened }), [opened]);
return <NavContext.Provider value={value}>{children}</NavContext.Provider>;
};
export function useNav() {
return useContext(NavContext);
}

View File

@@ -0,0 +1,63 @@
---
import '../styles/main.css';
import '@code-hike/mdx/styles.css';
import '../styles/ch.css';
import type { MarkdownLayoutProps } from 'astro';
import SidebarLayout from '../components/SidebarLayout.astro';
import { DESCRIPTION } from '../util/constants.js';
type Props = MarkdownLayoutProps<{}>;
const props = Astro.props;
---
<html lang="en">
<head>
<link href="/apple-touch-icon.png" rel="apple-touch-icon" sizes="180x180" />
<link href="/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png" />
<link href="/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png" />
<link href="/site.webmanifest" rel="manifest" />
<link color="#090a16" href="/safari-pinned-tab.svg" rel="mask-icon" />
<meta content="light dark" name="color-scheme" />
<meta content="discord.js" name="apple-mobile-web-app-title" />
<meta content="discord.js" name="application-name" />
<meta content="#090a16" name="msapplication-TileColor" />
<meta content={DESCRIPTION} name="description" />
<meta content="discord.js" property="og:site_name" />
<meta content="website" property="og:type" />
<meta content="discord.js guide" property="og:title" />
<meta content={DESCRIPTION} name="og:description" />
<meta content="https://discordjs.dev/open-graph.png" property="og:image" />
<meta content="summary_large_image" name="twitter:card" />
<meta content="@iCrawlToGo" name="twitter:creator" />
<title>discord.js</title>
<meta content="minimum-scale=1, initial-scale=1, width=device-width" name="viewport" />
<meta content="#5865f2" name="theme-color" />
</head>
<body class="dark:bg-dark-800 bg-white">
<script is:inline>
function setTheme(prefersDarkMode, persistedColorPreference) {
if (persistedColorPreference === 'dark' || (prefersDarkMode && persistedColorPreference !== 'light')) {
document.documentElement.classList.toggle('dark', true);
} else {
document.documentElement.classList.toggle('dark', false);
}
}
(() => {
const prefersDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
const persistedColorPreference = localStorage.getItem('theme') || 'auto';
setTheme(prefersDarkMode, persistedColorPreference);
const listener =
window.matchMedia &&
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (ev) => setTheme(ev.matches, persistedColorPreference));
})();
</script>
<SidebarLayout {...props}>
<slot />
</SidebarLayout>
</body>
</html>

View File

@@ -1,9 +0,0 @@
import { NextResponse, type NextRequest } from 'next/server';
export default async function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/guide/home/introduction', request.url));
}
export const config = {
matcher: ['/', '/guide'],
};

View File

@@ -1,8 +1,12 @@
---
layout: '../../layouts/SidebarLayout.astro'
title: Understanding async/await
category: Additional info
---
import { CH } from '@code-hike/mdx/components';
import { Alert } from '@discordjs/ui';
# Understanding async/await
If you aren't very familiar with ECMAScript 2017, you may not know about async/await. It's a useful way to handle Promises in a hoisted manner. It's also slightly faster and increases overall readability.
@@ -26,7 +30,7 @@ One important thing to know is that a Promise can only have one state simultaneo
[here](/additional-info/es6-syntax.md).
</Alert>
<CH.Code>
<CH.Code client:load>
```js
function deleteMessages(amount) {
@@ -59,7 +63,7 @@ The following information is essential to know before working with async/await.
A simple example would be:
<CH.Code>
<CH.Code client:load>
```js
async function declaredAsAsync() {
@@ -71,7 +75,7 @@ async function declaredAsAsync() {
or
<CH.Code>
<CH.Code client:load>
```js
const declaredAsAsync = async () => {
@@ -83,7 +87,7 @@ const declaredAsAsync = async () => {
You can use that as well if you use the arrow function as an event listener.
<CH.Code>
<CH.Code client:load>
```js
client.on('event', async (first, last) => {
@@ -99,18 +103,18 @@ An important thing to know is that a function declared as _`async`_ will always
Now that you know how Promises work and what they are used for, let's look at an example that handles multiple Promises. Let's say you want to react with letters (regional indicators) in a specific order. For this example, here's a basic template for a discord.js bot with some ES6 adjustments.
<CH.Code>
<CH.Code client:load>
```js
import { Client, Events, GatewayIntentBits } from 'discord.js';
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.once(Events.ClientReady, () => {
client.once('ready', () => {
console.log('I am ready!');
});
client.on(Events.InteractionCreate, (interaction) => {
client.on('interactionCreate', (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'react') {
@@ -125,7 +129,7 @@ client.login('your-token-goes-here');
If you don't know how Node.js asynchronous execution works, you would probably try something like this:
<CH.Code>
<CH.Code client:load>
```js mark=4:7
client.on('interactionCreate', (interaction) => {
@@ -143,7 +147,7 @@ client.on('interactionCreate', (interaction) => {
But since all of these methods are started at the same time, it would just be a race to which server request finished first, so there would be no guarantee that it would react at all (if the message isn't fetched) or in the order you wanted it to. In order to make sure it reacts after the message is sent and in order (a, b, c), you'd need to use the _`.then()`_ callback from the Promises that these methods return. The code would look like this:
<CH.Code>
<CH.Code client:load>
```js mark=4:12
client.on('interactionCreate', (interaction) => {
@@ -166,7 +170,7 @@ client.on('interactionCreate', (interaction) => {
In this piece of code, the Promises are [chain resolved](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then#Chaining) with each other, and if one of the Promises gets rejected, the function passed to _`.catch()`_ gets called. Here's the same code but with async/await:
<CH.Code>
<CH.Code client:load>
```js mark=1,4:7
client.on('interactionCreate', async (interaction) => {
@@ -184,7 +188,7 @@ client.on('interactionCreate', async (interaction) => {
It's mostly the same code, but how would you catch Promise rejections now since _`.catch()`_ isn't there anymore? That is also a useful feature with async/await; the error will be thrown if you await it so that you can wrap the awaited Promises inside a try/catch, and you're good to go.
<CH.Code>
<CH.Code client:load>
```js mark=1,4:11
client.on('interactionCreate', async (interaction) => {
@@ -209,7 +213,7 @@ So you may be asking, "How would I get the value the Promise resolved with?".
Let's look at an example where you want to delete a sent reply.
<CH.Code>
<CH.Code client:load>
```js mark=3:10
client.on('interactionCreate', (interaction) => {
@@ -229,7 +233,7 @@ client.on('interactionCreate', (interaction) => {
The return value of a _`.reply()`_ with the _`fetchReply`_ option set to _`true`_ is a Promise which resolves with the reply when it has been sent, but how would the same code with async/await look?
<CH.Code>
<CH.Code client:load>
```js mark=1,4:10
client.on('interactionCreate', async (interaction) => {

View File

@@ -1,8 +1,12 @@
---
layout: '../../layouts/SidebarLayout.astro'
title: Collections
category: Additional info
---
import { CH } from '@code-hike/mdx/components';
import { Alert } from '@discordjs/ui';
# Collections
discord.js comes with a utility class known as _`Collection`_.
@@ -24,7 +28,7 @@ This is the point of the _`Collection`_ class!
Many of the methods on _`Collection`_ correspond to their namesake in _`Array`_. One of them is _`find`_:
<CH.Code>
<CH.Code client:load>
```js
// Assume we have an array of users and a collection of the same users.
@@ -54,7 +58,7 @@ Methods that follow this philosophy of staying close to the _`Array`_ interface
Since _`Collection`_ extends _`Map`_, it is an [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols), and can be converted to an _`Array`_ through either _`Array.from()`_ or spread syntax (_`...collection`_).
<CH.Code>
<CH.Code client:load>
```js
// For values.
@@ -82,7 +86,7 @@ Array.from(collection);
Some methods are not from _`Array`_ and are instead entirely new to standard JavaScript.
<CH.Code>
<CH.Code client:load>
```js
// A random value.
@@ -106,9 +110,9 @@ collection.sweep((user) => user.username === 'Bob');
</CH.Code>
A more complicated method is _`partition`_, which splits a single Collection into two new Collections based on the provided function.
You can think of it as two \_`filter`\_ methods, but done at the same time:
You can think of it as two \_`filter`\_s, but done at the same time:
<CH.Code>
<CH.Code client:load>
```js
// `bots` is a Collection of users where their `bot` property was true.

View File

@@ -1,8 +1,14 @@
---
layout: '../../layouts/SidebarLayout.astro'
title: Creating commands
category: Creating your bot
---
import { CH } from '@code-hike/mdx/components';
import { Alert, DiscordMessages, DiscordMessage } from '@discordjs/ui';
import { DocsLink } from '../../components/DocsLink.jsx';
import { ResultingCode } from '../../components/ResultingCode.jsx';
# Creating commands
<Alert title="Tip" type="success">
@@ -56,7 +62,7 @@ Below is a deployment script you can use. Focus on these variables:
user's profile, etc.
</Alert>
<CH.Code>
<CH.Code client:load>
```js deploy-commands.js mark=4,6:10
const { REST, SlashCommandBuilder, Routes } = require('discord.js');
@@ -97,11 +103,11 @@ Once you fill in these values, run _`node deploy-commands.js`_ in your project d
## Replying to commands
Once you've registered your commands, you can listen for interactions via <DocsLink type="class" parent="Client" symbol="e-interactionCreate" /> in your _`index.js`_ file.
Once you've registered your commands, you can listen for interactions via <DocsLink path="class/Client?scrollTo=e-interactionCreate" /> in your _`index.js`_ file.
You should first check if an interaction is a chat input command via <DocsLink type="class" parent="BaseInteraction" symbol="isChatInputCommand" brackets>_`.isChatInputCommand()`_</DocsLink>, and then check the <DocsLink type="class" parent="CommandInteraction" symbol="commandName">_`.commandName`_</DocsLink> property to know which command it is. You can respond to interactions with <DocsLink type="class" parent="CommandInteraction" symbol="reply" brackets>_`.reply()`_</DocsLink>.
You should first check if an interaction is a chat input command via <DocsLink path="class/Interaction?scrollTo=isChatInputCommand" type="method">_`.isChatInputCommand()`_</DocsLink>, and then check the <DocsLink path="class/CommandInteraction?scrollTo=commandName">_`.commandName`_</DocsLink> property to know which command it is. You can respond to interactions with <DocsLink path="class/CommandInteraction?scrollTo=reply">_`.reply()`_</DocsLink>.
<CH.Code>
<CH.Code client:load>
```js mark=5:16
client.once('ready', () => {
@@ -126,9 +132,9 @@ client.login(token);
### Server info command
Note that servers are referred to as "guilds" in the Discord API and discord.js library. _`interaction.guild`_ refers to the guild the interaction was sent in (a <DocsLink type="class" parent="Guild" /> instance), which exposes properties such as _`.name`_ or _`.memberCount`_.
Note that servers are referred to as "guilds" in the Discord API and discord.js library. _`interaction.guild`_ refers to the guild the interaction was sent in (a <DocsLink path="class/Guild" /> instance), which exposes properties such as _`.name`_ or _`.memberCount`_.
<CH.Code>
<CH.Code client:load>
```js focus=7
client.on('interactionCreate', async (interaction) => {
@@ -171,15 +177,14 @@ client.on('interactionCreate', async (interaction) => {
You could also display the date the server was created, or the server's verification level. You would do those in the same manner use _`interaction.guild.createdAt`_ or _`interaction.guild.verificationLevel`_, respectively.
<Alert title="Tip" type="success">
Refer to the <DocsLink type="class" parent="Guild" /> documentation for a list of all the available properties and
methods!
Refer to the <DocsLink path="class/Guild" /> documentation for a list of all the available properties and methods!
</Alert>
### User info command
A "user" refers to a Discord user. _`interaction.user`_ refers to the user the interaction was sent by (a <DocsLink type="class" parent="User" /> instance), which exposes properties such as _`.tag`_ or _`.id`_.
A "user" refers to a Discord user. _`interaction.user`_ refers to the user the interaction was sent by (a <DocsLink path="class/User" /> instance), which exposes properties such as _`.tag`_ or _`.id`_.
<CH.Code>
<CH.Code client:load>
```js focus=9
client.on('interactionCreate', async (interaction) => {
@@ -220,8 +225,7 @@ client.on('interactionCreate', async (interaction) => {
</DiscordMessages>
<Alert title="Tip" type="success">
Refer to the <DocsLink type="class" parent="User" /> documentation for a list of all the available properties and
methods!
Refer to the <DocsLink path="class/User" /> documentation for a list of all the available properties and methods!
</Alert>
And there you have it!

View File

@@ -1,44 +1,29 @@
---
layout: '../../layouts/SidebarLayout.astro'
title: Initial files
category: Creating your bot
---
import { CH } from '@code-hike/mdx/components';
import { Alert, Section } from '@discordjs/ui';
import { DocsLink } from '../../components/DocsLink.jsx';
import { ResultingCode } from '../../components/ResultingCode.jsx';
# Initial files
Once you [add your bot to a server](preparations/adding-your-bot-to-servers.md), the next step is to start coding and get it online! Let's start by initializing your package.json, creating a config file for your client token, and a main file for your bot application.
Once you [add your bot to a server](/preparations/adding-your-bot-to-servers.md), the next step is to start coding and get it online! Let's start by creating a config file for your client token and a main file for your bot application.
## Creating package.json
## Creating configuration files
This command creates a _`package.json`_ file for you, which will keep track of the dependencies your project uses, as well as other information.
<CH.Code>
```sh npm
npm init -y; npm pkg set type="module"
```
```sh yarn
yarn add dotenv
# You must go into your package.json file and add "type": "module"
```
```sh pnpm
pnpm init; pnpm pkg set type="module"
```
</CH.Code>
Once you're done with that, onto the next step!
## Using config.json
As explained in the ["What is a token, anyway?"](preparations/setting-up-a-bot-application.md#what-is-a-token-anyway) section, your token is essentially your bot's password, and you should protect it as best as possible. This can be done through a _`config.json`_ file or by using environment variables.
As explained in the ["What is a token, anyway?"](/preparations/setting-up-a-bot-application.md#what-is-a-token-anyway) section, your token is essentially your bot's password, and you should protect it as best as possible. This can be done through a _`config.json`_ file or by using environment variables.
Open your application in the [Discord Developer Portal](https://discord.com/developers/applications) and go to the "Bot" page to copy your token.
Storing data in a _`config.json`_ file is a common way of keeping your sensitive values safe. Create a _`config.json`_ file in your project directory and paste in your token.
### Using config.json
<CH.Code>
Storing data in a _`config.json`_ file is a common way of keeping your sensitive values safe. Create a _`config.json`_ file in your project directory and paste in your token. You can access your token inside other files by using _`require()`_.
<CH.Code client:load>
```json config.json
{
@@ -46,16 +31,12 @@ Storing data in a _`config.json`_ file is a common way of keeping your sensitive
}
```
</CH.Code>
---
You can then access your token inside other files by using _`import`_.
```js Usage
const { token } = require('./config.json');
<CH.Code>
```ts
import config from './config.json' assert { type: 'json' };
console.log(config.token);
console.log(token);
```
</CH.Code>
@@ -73,7 +54,7 @@ One way to pass in environment variables is via the command line interface. When
You can access the set values in your code via the _`process.env`_ global variable, accessible in any file. Note that values passed this way will always be strings and that you might need to parse them to a number, if using them to do calculations.
<CH.Code>
<CH.Code client:load>
```shellscript Command line
A=123 B=456 DISCORD_TOKEN=your-token-goes-here node index.js
@@ -93,29 +74,23 @@ console.log(process.env.DISCORD_TOKEN);
Another common approach is storing these values in a _`.env`_ file. This spares you from always copying your token into the command line. Each line in a _`.env`_ file should hold a _`KEY=value`_ pair.
You can use the [_`dotenv`_ package](https://www.npmjs.com/package/dotenv) for this. Once installed, preload the package to load your _`.env`_ file and attach the variables to _`process.env`_:
You can use the [_`dotenv`_ package](https://www.npmjs.com/package/dotenv) for this. Once installed, require and use the package to load your _`.env`_ file and attach the variables to _`process.env`_:
##### Installing dotenv
<CH.Code client:load>
<CH.Code>
```sh npm
```shellscript npm
npm install dotenv
```
```sh yarn
```shellscript yarn
yarn add dotenv
```
```sh pnpm
```shellscript pnpm
pnpm add dotenv
```
</CH.Code>
##### Defining your variables
<CH.Code>
---
```text .env
A=123
@@ -123,6 +98,18 @@ B=456
DISCORD_TOKEN=your-token-goes-here
```
---
```js Usage
const dotenv = require('dotenv');
dotenv.config();
console.log(process.env.A);
console.log(process.env.B);
console.log(process.env.DISCORD_TOKEN);
```
</CH.Code>
<Alert title="Caution" type="danger">
@@ -130,29 +117,7 @@ DISCORD_TOKEN=your-token-goes-here
_`.gitignore`_](/creating-your-bot/#git-and-gitignore).
</Alert>
##### Utilizing your variables
<CH.Code>
```sh node
node --require dotenv/config yourFile.js
```
```sh yarn
yarn node --require dotenv/config yourFile.js
```
---
```ts yourFile
console.log(process.env.A); // 123
console.log(process.env.B); // 456
console.log(process.env.DISCORD_TOKEN); // your-token-goes-here
```
</CH.Code>
<Section title="Online editors (Glitch, Heroku, Replit, etc.)" defaultClosed padded background gutter>
<Section client:load title="Online editors (Glitch, Heroku, Replit, etc.)" defaultClosed padded background gutter>
While we generally do not recommend using online editors as hosting solutions, but rather invest in a proper virtual private server, these services do offer ways to keep your credentials safe as well! Please see the respective service's documentation and help articles for more information on how to keep sensitive values safe:
- Glitch: [Storing secrets in .env](https://glitch.happyfox.com/kb/article/18)
@@ -167,7 +132,7 @@ Git is a fantastic tool to keep track of your code changes and allows you to upl
You can specify files that Git should ignore in its versioning systems with a _`.gitignore`_ file. Create a _`.gitignore`_ file in your project directory and add the names of the files and folders you want to ignore:
<CH.Code>
<CH.Code client:load>
```
node_modules
@@ -186,46 +151,44 @@ config.json
## Creating the main file
Open your code editor and create a new file. We suggest that you save the file as _`index.ts`_, or _`index.js`_, depending on whether you use TypeScript. You may name it whatever you wish, however.
Open your code editor and create a new file. We suggest that you save the file as _`index.js`_, but you may name it whatever you wish.
Here's the base code to get you started:
<CH.Code>
<CH.Code client:load>
```ts index.ts
// Import the necessary structures.
import { Client, Events, GatewayIntentBits } from 'discord.js';
import config from './config.json';
```js
// Require the necessary discord.js classes
const { Client, GatewayIntentBits } = require('discord.js');
const { token } = require('./config.json');
// Create a new client instance.
const client = new Client({ intents: GatewayIntentBits.Guilds });
// Create a new client instance
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
// When the client is ready, run this code (only once).
client.once(Events.ClientReady, () => {
// When the client is ready, run this code (only once)
client.once('ready', () => {
console.log('Ready!');
});
// Log in to Discord with your client's token.
client.login(config.token);
// Login to Discord with your client's token
client.login(token);
```
</CH.Code>
This is how you create a client instance for your Discord bot and login to Discord. The _`GatewayIntentBits.Guilds`_ intents option is necessary for your client to work properly, as it ensures that the caches for guilds, channels and roles are populated and available for internal use.
Intents also define which events Discord should send to your bot, and you may wish to enable more than just the minimum. You can read more about the other intents on the [Intents topic](popular-topics/intents).
Intents also define which events Discord should send to your bot, and you may wish to enable more than just the minimum. You can read more about the other intents on the [Intents topic](/popular-topics/intents).
Open your terminal, compile your code (JavaScript users do not do this), and run _`node index.js`_ to start the process. If you see "Ready!" after a few seconds, you're good to go!
Open your terminal and run _`node index.js`_ to start the process. If you see "Ready!" after a few seconds, you're good to go!
<Alert title="Tip" type="success">
You can open your _`package.json`_ file and edit the _`"main": "index.js"`_ field to point to your main file. You can
then run _`node .`_ in your terminal to start the process! After closing the process with <kbd>⌃ Control</kbd>{' '}
<kbd>C</kbd>, you can press <kbd>↑</kbd> on your keyboard to bring up the latest commands you've run. Pressing{' '}
<kbd>↑</kbd> then <kbd>⏎ Enter</kbd> after closing the process is a quick way to start it up again.
then run _`node .`_ in your terminal to start the process! After closing the process with _`Ctrl + C`_, you can press
the up arrow on your keyboard to bring up the latest commands you've run. Pressing up and then enter after closing the
process is a quick way to start it up again.
</Alert>
## Resulting code
<ResultingCode path="creating-your-bot/initial-files" />
Code is indeed a result of code. That being said, it's being worked on. With code. Definitely.

View File

@@ -1,4 +1,5 @@
---
layout: '../layouts/SidebarLayout.astro'
title: Introduction
category: Home
---

View File

@@ -0,0 +1,20 @@
---
layout: '../layouts/SidebarLayout.astro'
title: Requesting more content
category: Home
---
import { Alert } from '@discordjs/ui';
# Requesting more content
Since this guide is made specifically for the discord.js community, we want to be sure to provide the most relevant and up-to-date content. We will, of course, make additions to the current pages and add new ones as we see fit, but fulfilling requests is how we know we're providing content you all want the most.
Requests may be as simple as "add an example to the [frequently asked questions](/popular-topics/faq.html) page", or as elaborate as "add a page regarding [sharding](/sharding/)". We'll do our best to fulfill all requests, as long as they're reasonable.
To make a request, simply head over to [the repo's issue tracker](https://github.com/discordjs/guide/issues) and [create a new issue](https://github.com/discordjs/guide/issues/new)! Title it appropriately, and let us know exactly what you mean inside the issue description. Make sure that you've looked around the site before making a request; what you want to request might already exist!
<Alert title="Tip" type="success">
Remember that you can always [fork the repo](https://github.com/discordjs/guide) and [make a pull
request](https://github.com/discordjs/guide/pulls) if you want to add anything to the guide yourself!
</Alert>

View File

@@ -0,0 +1,102 @@
---
title: Test
category: Test
---
import { DiscordMessages, DiscordMessage, DiscordMessageEmbed } from '@discordjs/ui';
<DiscordMessages>
<DiscordMessage
reply={{
author: {
avatar:
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
username: 'Crawl',
},
content: 'Test',
}}
author={{
avatar:
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
username: 'Crawl',
time: 'Today at 21:00',
}}
>
1234
</DiscordMessage>
<DiscordMessage
author={{
avatar:
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
username: 'Crawl',
time: 'Today at 21:00',
}}
followUp
time="21:02"
>
1234
</DiscordMessage>
</DiscordMessages>
<DiscordMessages>
<DiscordMessage
reply={{
author: {
avatar:
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
username: 'Crawl',
},
content: 'Test',
}}
author={{
avatar:
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
username: 'Crawl',
time: 'Today at 21:00',
}}
>
1234
</DiscordMessage>
</DiscordMessages>
<DiscordMessages>
<DiscordMessage
reply={{
author: {
avatar:
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
username: 'Crawl',
},
content: 'Test',
}}
author={{
avatar:
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
username: 'Crawl',
time: 'Today at 21:00',
}}
>
<>
<DiscordMessageEmbed
author={{
avatar:
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
username: 'Crawl',
}}
/>
<DiscordMessageEmbed title={{ title: 'Title' }} />
<DiscordMessageEmbed footer={{ content: 'Footer' }} />
<DiscordMessageEmbed
author={{
avatar:
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
username: 'Crawl',
}}
title={{ title: 'Title' }}
footer={{ content: 'Footer' }}
>
Test
</DiscordMessageEmbed>
</>
</DiscordMessage>
</DiscordMessages>

View File

@@ -1,21 +1,26 @@
---
layout: '../layouts/SidebarLayout.astro'
title: What's new
category: Home
---
import { CH } from '@code-hike/mdx/components';
import { DiscordMessages, DiscordMessage } from '@discordjs/ui';
# What's new
<DiscordMessages rounded>
<DiscordMessage
interaction={{
author: {
avatar: '/assets/old-guide.png',
username: 'discord.js',
avatar:
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
username: 'Crawl',
},
command: '/upgrade',
command: 'upgrade',
}}
author={{
avatar: '/assets/discordjs.png',
avatar: 'https://cdn.discordapp.com/avatars/474807795183648809/7f239a0776ff928b2182906a2b3743c9.webp?size=160',
bot: true,
username: 'Guide Bot',
time: 'Today at 21:00',
@@ -29,11 +34,14 @@ category: Home
## Site
We have moved from VuePress to [Next.js](https://nextjs.org/)! The source can be found [here](https://github.com/discordjs/discord.js/tree/main/apps/guide).
- Upgraded to [VuePress v2](https://v2.vuepress.vuejs.org/)
- New theme made to match the [discord.js documentation site](https://discord.js.org/)
- Discord message components upgraded to [@discord-message-components/vue](https://github.com/Danktuary/discord-message-components/blob/main/packages/vue/README.md)
- Many fixes in code blocks, grammar, consistency, etc.
## Pages
All content has been updated to use discord.js v14 syntax. The v13 version of the guide can be found at https://v13.discordjs.guide.
All content has been updated to use discord.js v14 syntax. The v13 version of the guide can be found at [https://v13.discordjs.guide/](https://v13.discordjs.guide/).
### New
@@ -50,13 +58,13 @@ All content has been updated to use discord.js v14 syntax. The v13 version of th
- [Voice](/voice/): Rewritten to use the [_`@discordjs/voice`_](https://github.com/discordjs/discord.js/tree/main/packages/voice) package
- [Command handling](/creating-your-bot/command-handling.md/): Updated to use slash commands
- Obsolete sections removed
- _`client.on('message')`_ snippets updated to _`client.on(Events.InteractionCreate)`_
- [Message content became a privileged intent on August 31, 2022](https://support-dev.discord.com/hc/articles/4404772028055)
- _`client.on('message')`_ snippets updated to _`client.on('interactionCreate')`_
- [Message content will become a new privileged intent on August 31, 2022](https://support-dev.discord.com/hc/en-us/articles/4404772028055)
<DiscordMessages rounded>
<DiscordMessage
author={{
avatar: '/assets/discordjs.png',
avatar: 'https://cdn.discordapp.com/avatars/474807795183648809/7f239a0776ff928b2182906a2b3743c9.webp?size=160',
bot: true,
username: 'Guide Bot',
time: 'Today at 21:00',

View File

@@ -0,0 +1,3 @@
.ch-frame-buttons {
display: none;
}

View File

@@ -1,3 +0,0 @@
[data-backdrop] {
background-color: rgb(0 0 0 / 35%);
}

View File

@@ -1,566 +0,0 @@
{
"$schema": "vscode://schemas/color-theme",
"name": "dark-plus",
"tokenColors": [
{
"settings": {
"foreground": "#D4D4D4"
}
},
{
"scope": ["meta.embedded", "source.groovy.embedded", "string meta.image.inline.markdown"],
"settings": {
"foreground": "#D4D4D4"
}
},
{
"scope": "emphasis",
"settings": {
"fontStyle": "italic"
}
},
{
"scope": "strong",
"settings": {
"fontStyle": "bold"
}
},
{
"scope": "header",
"settings": {
"foreground": "#000080"
}
},
{
"scope": "comment",
"settings": {
"foreground": "#6A9955"
}
},
{
"scope": "constant.language",
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": [
"constant.numeric",
"variable.other.enummember",
"keyword.operator.plus.exponent",
"keyword.operator.minus.exponent"
],
"settings": {
"foreground": "#b5cea8"
}
},
{
"scope": "constant.regexp",
"settings": {
"foreground": "#646695"
}
},
{
"scope": "entity.name.tag",
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "entity.name.tag.css",
"settings": {
"foreground": "#d7ba7d"
}
},
{
"scope": "entity.other.attribute-name",
"settings": {
"foreground": "#9cdcfe"
}
},
{
"scope": [
"entity.other.attribute-name.class.css",
"entity.other.attribute-name.class.mixin.css",
"entity.other.attribute-name.id.css",
"entity.other.attribute-name.parent-selector.css",
"entity.other.attribute-name.pseudo-class.css",
"entity.other.attribute-name.pseudo-element.css",
"source.css.less entity.other.attribute-name.id",
"entity.other.attribute-name.scss"
],
"settings": {
"foreground": "#d7ba7d"
}
},
{
"scope": "invalid",
"settings": {
"foreground": "#f44747"
}
},
{
"scope": "markup.underline",
"settings": {
"fontStyle": "underline"
}
},
{
"scope": "markup.bold",
"settings": {
"fontStyle": "bold",
"foreground": "#569cd6"
}
},
{
"scope": "markup.heading",
"settings": {
"fontStyle": "bold",
"foreground": "#569cd6"
}
},
{
"scope": "markup.italic",
"settings": {
"fontStyle": "italic"
}
},
{
"scope": "markup.strikethrough",
"settings": {
"fontStyle": "strikethrough"
}
},
{
"scope": "markup.inserted",
"settings": {
"foreground": "#b5cea8"
}
},
{
"scope": "markup.deleted",
"settings": {
"foreground": "#ce9178"
}
},
{
"scope": "markup.changed",
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "punctuation.definition.quote.begin.markdown",
"settings": {
"foreground": "#6A9955"
}
},
{
"scope": "punctuation.definition.list.begin.markdown",
"settings": {
"foreground": "#6796e6"
}
},
{
"scope": "markup.inline.raw",
"settings": {
"foreground": "#ce9178"
}
},
{
"name": "brackets of XML/HTML tags",
"scope": "punctuation.definition.tag",
"settings": {
"foreground": "#808080"
}
},
{
"scope": ["meta.preprocessor", "entity.name.function.preprocessor"],
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "meta.preprocessor.string",
"settings": {
"foreground": "#ce9178"
}
},
{
"scope": "meta.preprocessor.numeric",
"settings": {
"foreground": "#b5cea8"
}
},
{
"scope": "meta.structure.dictionary.key.python",
"settings": {
"foreground": "#9cdcfe"
}
},
{
"scope": "meta.diff.header",
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "storage",
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "storage.type",
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": ["storage.modifier", "keyword.operator.noexcept"],
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": ["string", "meta.embedded.assembly"],
"settings": {
"foreground": "#ce9178"
}
},
{
"scope": "string.tag",
"settings": {
"foreground": "#ce9178"
}
},
{
"scope": "string.value",
"settings": {
"foreground": "#ce9178"
}
},
{
"scope": "string.regexp",
"settings": {
"foreground": "#d16969"
}
},
{
"name": "String interpolation",
"scope": [
"punctuation.definition.template-expression.begin",
"punctuation.definition.template-expression.end",
"punctuation.section.embedded"
],
"settings": {
"foreground": "#569cd6"
}
},
{
"name": "Reset JavaScript string interpolation expression",
"scope": ["meta.template.expression"],
"settings": {
"foreground": "#d4d4d4"
}
},
{
"scope": [
"support.type.vendored.property-name",
"support.type.property-name",
"variable.css",
"variable.scss",
"variable.other.less",
"source.coffee.embedded"
],
"settings": {
"foreground": "#9cdcfe"
}
},
{
"scope": "keyword",
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "keyword.control",
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "keyword.operator",
"settings": {
"foreground": "#d4d4d4"
}
},
{
"scope": [
"keyword.operator.new",
"keyword.operator.expression",
"keyword.operator.cast",
"keyword.operator.sizeof",
"keyword.operator.alignof",
"keyword.operator.typeid",
"keyword.operator.alignas",
"keyword.operator.instanceof",
"keyword.operator.logical.python",
"keyword.operator.wordlike"
],
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "keyword.other.unit",
"settings": {
"foreground": "#b5cea8"
}
},
{
"scope": ["punctuation.section.embedded.begin.php", "punctuation.section.embedded.end.php"],
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "support.function.git-rebase",
"settings": {
"foreground": "#9cdcfe"
}
},
{
"scope": "constant.sha.git-rebase",
"settings": {
"foreground": "#b5cea8"
}
},
{
"name": "coloring of the Java import and package identifiers",
"scope": ["storage.modifier.import.java", "variable.language.wildcard.java", "storage.modifier.package.java"],
"settings": {
"foreground": "#d4d4d4"
}
},
{
"name": "this.self",
"scope": "variable.language",
"settings": {
"foreground": "#569cd6"
}
},
{
"name": "Function declarations",
"scope": [
"entity.name.function",
"support.function",
"support.constant.handlebars",
"source.powershell variable.other.member",
"entity.name.operator.custom-literal"
],
"settings": {
"foreground": "#DCDCAA"
}
},
{
"name": "Types declaration and references",
"scope": [
"support.class",
"support.type",
"entity.name.type",
"entity.name.namespace",
"entity.other.attribute",
"entity.name.scope-resolution",
"entity.name.class",
"storage.type.numeric.go",
"storage.type.byte.go",
"storage.type.boolean.go",
"storage.type.string.go",
"storage.type.uintptr.go",
"storage.type.error.go",
"storage.type.rune.go",
"storage.type.cs",
"storage.type.generic.cs",
"storage.type.modifier.cs",
"storage.type.variable.cs",
"storage.type.annotation.java",
"storage.type.generic.java",
"storage.type.java",
"storage.type.object.array.java",
"storage.type.primitive.array.java",
"storage.type.primitive.java",
"storage.type.token.java",
"storage.type.groovy",
"storage.type.annotation.groovy",
"storage.type.parameters.groovy",
"storage.type.generic.groovy",
"storage.type.object.array.groovy",
"storage.type.primitive.array.groovy",
"storage.type.primitive.groovy"
],
"settings": {
"foreground": "#4EC9B0"
}
},
{
"name": "Types declaration and references, TS grammar specific",
"scope": [
"meta.type.cast.expr",
"meta.type.new.expr",
"support.constant.math",
"support.constant.dom",
"support.constant.json",
"entity.other.inherited-class"
],
"settings": {
"foreground": "#4EC9B0"
}
},
{
"name": "Control flow / Special keywords",
"scope": [
"keyword.control",
"source.cpp keyword.operator.new",
"keyword.operator.delete",
"keyword.other.using",
"keyword.other.operator",
"entity.name.operator"
],
"settings": {
"foreground": "#C586C0"
}
},
{
"name": "Variable and parameter name",
"scope": [
"variable",
"meta.definition.variable.name",
"support.variable",
"entity.name.variable",
"constant.other.placeholder"
],
"settings": {
"foreground": "#9CDCFE"
}
},
{
"name": "Constants and enums",
"scope": ["variable.other.constant", "variable.other.enummember"],
"settings": {
"foreground": "#4FC1FF"
}
},
{
"name": "Object keys, TS grammar specific",
"scope": ["meta.object-literal.key"],
"settings": {
"foreground": "#9CDCFE"
}
},
{
"name": "CSS property value",
"scope": [
"support.constant.property-value",
"support.constant.font-name",
"support.constant.media-type",
"support.constant.media",
"constant.other.color.rgb-value",
"constant.other.rgb-value",
"support.constant.color"
],
"settings": {
"foreground": "#CE9178"
}
},
{
"name": "Regular expression groups",
"scope": [
"punctuation.definition.group.regexp",
"punctuation.definition.group.assertion.regexp",
"punctuation.definition.character-class.regexp",
"punctuation.character.set.begin.regexp",
"punctuation.character.set.end.regexp",
"keyword.operator.negation.regexp",
"support.other.parenthesis.regexp"
],
"settings": {
"foreground": "#CE9178"
}
},
{
"scope": [
"constant.character.character-class.regexp",
"constant.other.character-class.set.regexp",
"constant.other.character-class.regexp",
"constant.character.set.regexp"
],
"settings": {
"foreground": "#d16969"
}
},
{
"scope": ["keyword.operator.or.regexp", "keyword.control.anchor.regexp"],
"settings": {
"foreground": "#DCDCAA"
}
},
{
"scope": "keyword.operator.quantifier.regexp",
"settings": {
"foreground": "#d7ba7d"
}
},
{
"scope": "constant.character",
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "constant.character.escape",
"settings": {
"foreground": "#d7ba7d"
}
},
{
"scope": "entity.name.label",
"settings": {
"foreground": "#C8C8C8"
}
}
],
"semanticTokenColors": {
"newOperator": "#C586C0",
"stringLiteral": "#ce9178",
"customLiteral": "#DCDCAA",
"numberLiteral": "#b5cea8"
},
"colors": {
"checkbox.border": "#6B6B6B",
"editor.background": "#1E1E1E",
"editor.foreground": "#D4D4D4",
"editor.inactiveSelectionBackground": "#3A3D41",
"editorIndentGuide.background": "#404040",
"editorIndentGuide.activeBackground": "#707070",
"editor.selectionHighlightBackground": "#ADD6FF26",
"list.dropBackground": "#383B3D",
"activityBarBadge.background": "#007ACC",
"sideBarTitle.foreground": "#BBBBBB",
"input.placeholderForeground": "#A6A6A6",
"menu.background": "#252526",
"menu.foreground": "#CCCCCC",
"menu.separatorBackground": "#454545",
"menu.border": "#454545",
"statusBarItem.remoteForeground": "#FFF",
"statusBarItem.remoteBackground": "#16825D",
"ports.iconRunningProcessForeground": "#369432",
"sideBarSectionHeader.background": "#0000",
"sideBarSectionHeader.border": "#ccc3",
"tab.lastPinnedBorder": "#ccc3",
"list.activeSelectionIconForeground": "#FFF",
"terminal.inactiveSelectionBackground": "#3A3D41",
"widget.border": "#303031"
},
"type": "dark"
}

View File

@@ -1,8 +1,16 @@
body {
font-family: var(--font-inter);
min-height: 100vh;
@import url('https://rsms.me/inter/inter.css');
:root {
font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
}
code {
font-family: var(--font-mono);
@supports (font-variation-settings: normal) {
:root {
font-family: 'Inter var', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
}
}

View File

@@ -1,27 +1,3 @@
export const BASE_URL = 'https://discord.js.org/docs/packages' as const;
export const BASE_URL_LEGACY = 'https://old.discordjs.dev/#/docs/discord.js' as const;
export const DESCRIPTION = 'Imagine a guide... that explores the many possibilities for your discord.js bot.';
export const GITHUB_BASE_PAGES_PATH = 'https://github.com/discordjs/discord.js/tree/main/apps/guide/src/pages';
export const PACKAGES = [
'discord.js',
'brokers',
'builders',
'collection',
'core',
'formatters',
'proxy',
'rest',
'next',
'util',
'voice',
'ws',
] as const;
/**
* The stable version of discord.js.
*/
export const VERSION = '14.9.0' as const;

View File

@@ -1,4 +0,0 @@
export const fetcher = async (url: string) => {
const res = await fetch(url);
return res.json();
};

View File

@@ -1,13 +0,0 @@
import { Inter, JetBrains_Mono } from 'next/font/google';
export const inter = Inter({
subsets: ['latin'],
display: 'swap',
variable: '--font-inter',
});
export const jetBrainsMono = JetBrains_Mono({
subsets: ['latin'],
display: 'swap',
variable: '--font-mono',
});

View File

@@ -10,6 +10,7 @@
"**/*.cjs",
"**/*.mjs",
"**/*.jsx",
"**/*.astro",
"**/*.test.ts",
"**/*.test.js",
"**/*.test.mjs",

View File

@@ -9,25 +9,11 @@
"allowJs": false,
"incremental": true,
"skipLibCheck": true,
"sourceMap": true,
"plugins": [
{
"name": "next"
}
],
"types": ["@astrojs/image/client"],
"paths": {
"~/*": ["./src/*"],
"contentlayer/generated": ["./.contentlayer/generated"]
},
"strictNullChecks": true
"~/*": ["./src/*"]
}
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"next-env.d.ts",
"types.d.ts",
".next/types/**/*.ts",
".contentlayer/generated"
],
"include": ["src/**/*.ts", "src/**/*.tsx", "types.d.ts"],
"exclude": ["node_modules"]
}

3
apps/guide/vercel.json Normal file
View File

@@ -0,0 +1,3 @@
{
"cleanUrls": true
}

View File

@@ -1,5 +1,5 @@
{
"extends": ["../../.eslintrc.json", "neon/react", "neon/next", "neon/edge", "@unocss", "neon/prettier"],
"extends": ["../../.eslintrc.json", "neon/react", "neon/next", "neon/edge", "neon/prettier"],
"settings": {
"react": {
"version": "detect"

View File

@@ -13,7 +13,6 @@ pids
# Env
.env
.env*.local
# Dist
dist/
@@ -23,7 +22,6 @@ build/
src/styles/unocss.css
.next/
src/assets/readme/
static/
# Miscellaneous
.tmp/
@@ -31,4 +29,3 @@ coverage/
.vercel
public/searchIndex
.vscode
lighthouse-results/

View File

@@ -1 +1,7 @@
module.exports = require('../../.prettierrc.json');
module.exports = {
...require('../../.prettierrc.json'),
plugins: [
'prettier-plugin-tailwindcss', // MUST come last
],
pluginSearchDirs: false,
};

View File

@@ -18,7 +18,7 @@
- [Website][website] ([source][website-source])
- [Documentation][documentation]
- [Guide][guide] ([source][guide-source])
Also see the v13 to v14 [Update Guide][guide-update], which includes updated and removed items from the library.
See also the [Update Guide][guide-update], including updated and removed items in the library.
- [discord.js Discord server][discord]
- [Discord API Discord server][discord-api]
- [GitHub][source]
@@ -26,17 +26,16 @@
## Contributing
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
[documentation][documentation].
See [the contribution guide][contributing] if you'd like to submit a PR.
## Help
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
[website]: https://discord.js.org
[website]: https://discord.js.org/
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
[documentation]: https://discord.js.org/docs
[documentation]: https://discord.js.org/
[guide]: https://discordjs.guide/
[guide-source]: https://github.com/discordjs/guide
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html

Some files were not shown because too many files have changed in this diff Show More