mirror of
https://github.com/discordjs/discord.js.git
synced 2026-05-23 03:50:09 +00:00
Compare commits
110 Commits
@discordjs
...
@discordjs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7aa5ea731f | ||
|
|
f883279ab3 | ||
|
|
f1b2dec8e1 | ||
|
|
0a1701b046 | ||
|
|
5dcc6df224 | ||
|
|
1c35425120 | ||
|
|
cf1f5c0f0c | ||
|
|
a210fc64a2 | ||
|
|
24f17998c8 | ||
|
|
eda118dae9 | ||
|
|
f2fce0a7da | ||
|
|
29389e39f4 | ||
|
|
d5e9e36e8a | ||
|
|
8c0eb56ba5 | ||
|
|
1b74c774c0 | ||
|
|
01949d6e3a | ||
|
|
3ea26cc1a6 | ||
|
|
a516d46f91 | ||
|
|
b35b935679 | ||
|
|
0928c8f6ff | ||
|
|
188d5eea28 | ||
|
|
412e4fffae | ||
|
|
5e2f94c591 | ||
|
|
49627b1f46 | ||
|
|
bcb48fea3e | ||
|
|
c87e826087 | ||
|
|
2dddbe1f32 | ||
|
|
86e5f5a119 | ||
|
|
300059cb26 | ||
|
|
d4c1fecbe2 | ||
|
|
79bcdfa767 | ||
|
|
ca4de2d9c6 | ||
|
|
794abe8450 | ||
|
|
02dfaf1aa2 | ||
|
|
cac3c07729 | ||
|
|
83143178aa | ||
|
|
615752e32b | ||
|
|
2c25639a85 | ||
|
|
a76c1ddacc | ||
|
|
0d0e4d1cb6 | ||
|
|
d35f670d7a | ||
|
|
e4c5f794b0 | ||
|
|
88cab1a0ec | ||
|
|
1c2cc09e05 | ||
|
|
2a684361d4 | ||
|
|
66dc4014fe | ||
|
|
39c6694561 | ||
|
|
70da3746f8 | ||
|
|
0340622f1a | ||
|
|
f36878677c | ||
|
|
e5859b41cf | ||
|
|
8218ffc78d | ||
|
|
7ff3d528d9 | ||
|
|
0b7f296b62 | ||
|
|
85a379fdf8 | ||
|
|
8ffcf77840 | ||
|
|
fcb3a1ab27 | ||
|
|
40be4f80dc | ||
|
|
ee907f32f3 | ||
|
|
731ea5f3cb | ||
|
|
24c462bf6f | ||
|
|
78e02c4b63 | ||
|
|
dcf8757d35 | ||
|
|
a0c57abadd | ||
|
|
1c5a6fa552 | ||
|
|
6a221a9676 | ||
|
|
dcf58d8140 | ||
|
|
676307ff5c | ||
|
|
23e0ac56f4 | ||
|
|
8073561824 | ||
|
|
c0f2dd7131 | ||
|
|
d6905b3b97 | ||
|
|
774e23c572 | ||
|
|
1c8567f147 | ||
|
|
733c96c255 | ||
|
|
69cdeb7296 | ||
|
|
0019700869 | ||
|
|
3ea4d26ee9 | ||
|
|
250eccf118 | ||
|
|
7d3827ebd1 | ||
|
|
d1955f7c9e | ||
|
|
6412da4921 | ||
|
|
79123fb260 | ||
|
|
3d2f4b405e | ||
|
|
bfee6c8d88 | ||
|
|
fbbce3eb4b | ||
|
|
b2eec5f9fc | ||
|
|
b618e215f2 | ||
|
|
d66d113333 | ||
|
|
1b9d07f941 | ||
|
|
f893c6a357 | ||
|
|
687bbd889f | ||
|
|
f195556b64 | ||
|
|
9aafdd6214 | ||
|
|
e3e7d500dc | ||
|
|
3615e2f2d2 | ||
|
|
a7425c29c4 | ||
|
|
c519fe66c9 | ||
|
|
24f280290b | ||
|
|
6912faa9b3 | ||
|
|
0645bf0f7f | ||
|
|
6aba9e99eb | ||
|
|
5efdf57894 | ||
|
|
74059c9d97 | ||
|
|
8d345a041e | ||
|
|
1cbd04e8fd | ||
|
|
8592edba39 | ||
|
|
38f0986000 | ||
|
|
9e077b749c | ||
|
|
b977ba5f4d |
@@ -7,8 +7,5 @@
|
||||
"rules": {
|
||||
"@typescript-eslint/consistent-type-definitions": ["error", "interface"]
|
||||
},
|
||||
"ignorePatterns": ["**/dist/*"],
|
||||
"env": {
|
||||
"jest": true
|
||||
}
|
||||
"ignorePatterns": ["**/dist/*"]
|
||||
}
|
||||
|
||||
27
.github/CODEOWNERS
vendored
Normal file
27
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# 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
|
||||
8
.github/auto_assign.yml
vendored
8
.github/auto_assign.yml
vendored
@@ -1,8 +0,0 @@
|
||||
addReviewers: true
|
||||
reviewers:
|
||||
- iCrawl
|
||||
- SpaceEEC
|
||||
- kyranet
|
||||
- vladfrangu
|
||||
numberOfReviewers: 0
|
||||
runOnDraft: true
|
||||
22
.github/workflows/documentation.yml
vendored
22
.github/workflows/documentation.yml
vendored
@@ -129,6 +129,15 @@ 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:
|
||||
@@ -144,13 +153,12 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Upload documentation to database
|
||||
if: ${{ github.ref_type == 'tag' && matrix.package == steps.extract-tag.outputs.package }}
|
||||
if: ${{ github.ref_type == 'branch' }}
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
uses: ./packages/actions/src/uploadDocumentation
|
||||
with:
|
||||
package: ${{ steps.extract-tag.outputs.package }}
|
||||
version: ${{ steps.extract-tag.outputs.semver }}
|
||||
package: ${{ matrix.package }}
|
||||
|
||||
- name: Move docs to correct directory
|
||||
if: ${{ github.ref_type == 'branch' }}
|
||||
@@ -165,14 +173,6 @@ jobs:
|
||||
mv docs/${PACKAGE}/docs/docs.api.json out/${PACKAGE}/${GITHUB_REF_NAME}.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: Commit and push
|
||||
run: |
|
||||
cd out
|
||||
|
||||
102
.github/workflows/nextjs-bundle-analysis.yml
vendored
102
.github/workflows/nextjs-bundle-analysis.yml
vendored
@@ -1,102 +0,0 @@
|
||||
name: 'Next.js Bundle Analysis'
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
pull_request_target:
|
||||
paths:
|
||||
- 'apps/website/**'
|
||||
workflow_dispatch:
|
||||
defaults:
|
||||
run:
|
||||
working-directory: apps/website
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
pull-requests: write
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- 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: Restore next build
|
||||
uses: actions/cache@v3
|
||||
id: restore-build-cache
|
||||
env:
|
||||
cache-name: cache-next-build
|
||||
with:
|
||||
path: apps/website/.next/cache
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}
|
||||
|
||||
- name: Build packages
|
||||
run: yarn run --top-level build
|
||||
|
||||
- name: Build website
|
||||
run: yarn workspace @discordjs/website run build:local
|
||||
|
||||
- name: Analyze bundle
|
||||
run: npx -yes -p github:hashicorp/nextjs-bundle-analysis report
|
||||
|
||||
- name: Upload bundle
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: bundle
|
||||
path: apps/website/.next/analyze/__bundle_analysis.json
|
||||
|
||||
- name: Download base branch bundle stats
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
if: success() && github.event.number
|
||||
with:
|
||||
workflow: nextjs-bundle-analysis.yml
|
||||
commit: ${{ github.event.pull_request.base.sha }}
|
||||
path: apps/website/.next/analyze/base
|
||||
|
||||
- name: Compare with base branch bundle
|
||||
if: success() && github.event.number
|
||||
run: ls -laR .next/analyze/base && npx -yes -p github:hashicorp/nextjs-bundle-analysis compare
|
||||
|
||||
- name: Get comment body
|
||||
id: get-comment-body
|
||||
if: success() && github.event.number
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
result-encoding: string
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const comment = fs.readFileSync('apps/website/.next/analyze/__bundle_analysis_comment.txt', 'utf8');
|
||||
core.setOutput('body', comment);
|
||||
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
if: success() && github.event.number
|
||||
id: fc
|
||||
with:
|
||||
issue-number: ${{ github.event.number }}
|
||||
body-includes: '<!-- __NEXTJS_BUNDLE -->'
|
||||
|
||||
- name: Create Comment
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
if: success() && github.event.number && steps.fc.outputs.comment-id == 0
|
||||
with:
|
||||
issue-number: ${{ github.event.number }}
|
||||
body: ${{ steps.get-comment-body.outputs.body }}
|
||||
|
||||
- name: Update Comment
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
if: success() && github.event.number && steps.fc.outputs.comment-id != 0
|
||||
with:
|
||||
issue-number: ${{ github.event.number }}
|
||||
body: ${{ steps.get-comment-body.outputs.body }}
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
4
.github/workflows/pr-triage.yml
vendored
4
.github/workflows/pr-triage.yml
vendored
@@ -11,7 +11,3 @@ 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"*": "prettier --ignore-unknown --write",
|
||||
"{src/**,__tests__/**}.{mjs,js,cjs,ts,tsx,astro}": "eslint --ext .mjs,.js,.cjs,.ts,.tsx,.astro --fix",
|
||||
"{src/**,__tests__/**}.{mjs,js,cjs,ts,tsx}": "eslint --ext .mjs,.js,.cjs,.ts,.tsx --fix",
|
||||
"src/**.ts": "vitest related --run --config ../../vitest.config.ts"
|
||||
}
|
||||
|
||||
1
.prettierignore
Normal file
1
.prettierignore
Normal file
@@ -0,0 +1 @@
|
||||
CODEOWNERS
|
||||
1
.vscode/extensions.json
vendored
1
.vscode/extensions.json
vendored
@@ -9,7 +9,6 @@
|
||||
"christian-kohler.npm-intellisense",
|
||||
"christian-kohler.path-intellisense",
|
||||
"antfu.unocss",
|
||||
"astro-build.astro-vscode",
|
||||
"unifiedjs.vscode-mdx"
|
||||
]
|
||||
}
|
||||
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"eslint.workingDirectories": [{ "pattern": "./apps/*" }, { "pattern": "./packages/*" }],
|
||||
"eslint.validate": ["javascript", "javascriptreact", "astro", "typescript", "typescriptreact"],
|
||||
"prettier.documentSelectors": ["**/*.astro"],
|
||||
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
|
||||
@@ -11,3 +11,8 @@ plugins:
|
||||
spec: 'https://github.com/Dcard/yarn-plugins/releases/latest/download/plugin-docker-build.js'
|
||||
|
||||
yarnPath: .yarn/releases/yarn-3.5.0.cjs
|
||||
|
||||
packageExtensions:
|
||||
'@storybook/core-common@*':
|
||||
dependencies:
|
||||
'@storybook/react-vite': '7.0.5'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": ["../../.eslintrc.json", "neon/react", "neon/next", "neon/edge", "neon/prettier"],
|
||||
"extends": ["../../.eslintrc.json", "neon/react", "neon/next", "neon/edge", "@unocss", "neon/prettier"],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
|
||||
@@ -1,7 +1 @@
|
||||
module.exports = {
|
||||
...require('../../.prettierrc.json'),
|
||||
plugins: [
|
||||
'prettier-plugin-tailwindcss', // MUST come last
|
||||
],
|
||||
pluginSearchDirs: false,
|
||||
};
|
||||
module.exports = require('../../.prettierrc.json');
|
||||
|
||||
@@ -6,6 +6,7 @@ import { defineDocumentType, makeSource } from 'contentlayer/source-files';
|
||||
// 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',
|
||||
@@ -16,21 +17,21 @@ export const Content = defineDocumentType(() => ({
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
summary: {
|
||||
type: 'string',
|
||||
},
|
||||
image: {
|
||||
category: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computedFields: {
|
||||
slug: {
|
||||
type: 'string',
|
||||
resolve: (doc) => doc._raw.flattenedPath,
|
||||
// eslint-disable-next-line unicorn/prefer-string-replace-all
|
||||
resolve: (doc) => doc._raw.flattenedPath.replace(/\d+-/g, ''),
|
||||
},
|
||||
url: {
|
||||
type: 'string',
|
||||
resolve: (post) => `/posts/${post._raw.flattenedPath}`,
|
||||
// eslint-disable-next-line unicorn/prefer-string-replace-all
|
||||
resolve: (doc) => `/guide/${doc._raw.flattenedPath.replace(/\d+-/g, '')}`,
|
||||
},
|
||||
},
|
||||
}));
|
||||
@@ -67,7 +68,7 @@ export default makeSource({
|
||||
contentDirPath: 'src/content',
|
||||
documentTypes: [Content],
|
||||
mdx: {
|
||||
remarkPlugins: [remarkGfm, [remarkCodeHike, { theme: 'css-variables', lineNumbers: true }]],
|
||||
remarkPlugins: [remarkGfm, [remarkCodeHike, { theme: codeHikeThemeDarkPlus, lineNumbers: true }]],
|
||||
rehypePlugins: [
|
||||
rehypeSlug,
|
||||
// [
|
||||
@@ -75,7 +76,7 @@ export default makeSource({
|
||||
// {
|
||||
// properties: {
|
||||
// class:
|
||||
// 'relative inline-flex w-6 h-6 place-items-center place-content-center outline-0 text-black dark:text-white ml-2',
|
||||
// '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 }) =>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// import { fileURLToPath } from 'node:url';
|
||||
/* 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 { fileURLToPath } = require('node:url');
|
||||
const bundleAnalyzer = require('@next/bundle-analyzer');
|
||||
const { withContentlayer } = require('next-contentlayer');
|
||||
|
||||
@@ -9,19 +9,11 @@ const withBundleAnalyzer = bundleAnalyzer({
|
||||
enabled: process.env.ANALYZE === 'true',
|
||||
});
|
||||
|
||||
module.exports = withContentlayer(
|
||||
withBundleAnalyzer({
|
||||
module.exports = withBundleAnalyzer(
|
||||
withContentlayer({
|
||||
reactStrictMode: true,
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
// Until Next.js fixes their type issues
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
experimental: {
|
||||
appDir: true,
|
||||
fallbackNodePolyfills: false,
|
||||
},
|
||||
images: {
|
||||
dangerouslyAllowSVG: true,
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
"build:css": "yarn generate:css",
|
||||
"build:analyze": "cross-env-shell ANALYZE=true yarn build:prod",
|
||||
"preview": "next start",
|
||||
"dev": "concurrently 'yarn dev:css' 'yarn dev:next'",
|
||||
"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",
|
||||
@@ -43,57 +44,56 @@
|
||||
},
|
||||
"homepage": "https://discord.js.org",
|
||||
"dependencies": {
|
||||
"@code-hike/mdx": "^0.7.5-next.0",
|
||||
"@code-hike/mdx": "^0.8.2",
|
||||
"@discordjs/ui": "workspace:^",
|
||||
"@react-icons/all-files": "^4.1.0",
|
||||
"@vercel/analytics": "^0.1.11",
|
||||
"@vercel/edge-config": "^0.1.5",
|
||||
"@vercel/og": "^0.5.0",
|
||||
"ariakit": "^2.0.0-next.43",
|
||||
"@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.2.4",
|
||||
"next": "^13.3.0",
|
||||
"next-contentlayer": "^0.3.1",
|
||||
"next-themes": "^0.2.1",
|
||||
"react": "^18.2.0",
|
||||
"react-custom-scrollbars-2": "^4.5.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^4.8.0",
|
||||
"react-use": "^17.4.0",
|
||||
"rehype-autolink-headings": "^6.1.1",
|
||||
"rehype-ignore": "^1.0.4",
|
||||
"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"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "^13.2.4",
|
||||
"@next/bundle-analyzer": "^13.3.0",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/node": "18.15.11",
|
||||
"@types/react": "^18.0.31",
|
||||
"@types/react": "^18.0.35",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@unocss/cli": "^0.50.6",
|
||||
"@unocss/reset": "^0.50.6",
|
||||
"@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.29.8",
|
||||
"@vitest/coverage-c8": "^0.30.1",
|
||||
"concurrently": "^8.0.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.37.0",
|
||||
"eslint-config-neon": "^0.1.41",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-config-neon": "^0.1.42",
|
||||
"eslint-formatter-pretty": "^5.0.0",
|
||||
"happy-dom": "^8.9.0",
|
||||
"happy-dom": "^9.7.1",
|
||||
"hast-util-to-string": "^2.0.0",
|
||||
"hastscript": "^7.2.0",
|
||||
"html-escaper": "^3.0.3",
|
||||
"lighthouse": "^10.1.0",
|
||||
"lighthouse": "^10.1.1",
|
||||
"prettier": "^2.8.7",
|
||||
"prettier-plugin-astro": "^0.8.0",
|
||||
"prettier-plugin-tailwindcss": "^0.2.6",
|
||||
"typescript": "^5.0.3",
|
||||
"unocss": "^0.50.6",
|
||||
"vercel": "^28.18.3",
|
||||
"typescript": "^5.0.4",
|
||||
"unocss": "^0.51.4",
|
||||
"vercel": "^28.18.5",
|
||||
"vitest": "^0.29.8"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
BIN
apps/guide/public/assets/discordjs.png
Normal file
BIN
apps/guide/public/assets/discordjs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
apps/guide/public/assets/old-guide.png
Executable file
BIN
apps/guide/public/assets/old-guide.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
@@ -4,7 +4,7 @@ export default function Error({ error }: { error: Error }) {
|
||||
console.error(error);
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex h-full max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
|
||||
<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>
|
||||
|
||||
@@ -8,10 +8,10 @@ export default function GlobalError({ error }: { error: Error }) {
|
||||
|
||||
return (
|
||||
<html className={inter.variable} lang="en" suppressHydrationWarning>
|
||||
<body className="dark:bg-dark-800 bg-light-600">
|
||||
<body className="bg-light-600 dark:bg-dark-600 dark:text-light-900">
|
||||
<Providers>
|
||||
<main className="mx-auto h-screen max-w-2xl">
|
||||
<div className="mx-auto flex h-screen max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
|
||||
<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>
|
||||
|
||||
1
apps/guide/src/app/guide/[...slug]/not-found.tsx
Normal file
1
apps/guide/src/app/guide/[...slug]/not-found.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from '~/app/not-found';
|
||||
@@ -3,7 +3,7 @@ import { notFound } from 'next/navigation';
|
||||
import { Mdx } from '~/components/Mdx';
|
||||
|
||||
export async function generateStaticParams() {
|
||||
return allContents.map((content) => ({ slug: content.slug }));
|
||||
return allContents.map((content) => ({ slug: [content.slug] }));
|
||||
}
|
||||
|
||||
export default function Page({ params }: { params: { slug: string[] } }) {
|
||||
@@ -14,7 +14,7 @@ export default function Page({ params }: { params: { slug: string[] } }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<article className="prose mx-auto max-w-4xl py-8">
|
||||
<article className="max-w-none prose">
|
||||
<Mdx code={content?.body.code ?? ''} />
|
||||
</article>
|
||||
);
|
||||
25
apps/guide/src/app/guide/layout.tsx
Normal file
25
apps/guide/src/app/guide/layout.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
3
apps/guide/src/app/guide/page.tsx
Normal file
3
apps/guide/src/app/guide/page.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function Page() {
|
||||
return null;
|
||||
}
|
||||
8
apps/guide/src/app/guide/providers.tsx
Normal file
8
apps/guide/src/app/guide/providers.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { NavProvider } from '~/contexts/nav';
|
||||
|
||||
export function Providers({ children }: PropsWithChildren) {
|
||||
return <NavProvider>{children}</NavProvider>;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Analytics } from '@vercel/analytics/react';
|
||||
import type { Metadata } from 'next/types';
|
||||
import type { Metadata } from 'next';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { Providers } from './providers';
|
||||
import { DESCRIPTION } from '~/util/constants';
|
||||
@@ -44,7 +44,10 @@ export const metadata: Metadata = {
|
||||
|
||||
manifest: '/site.webmanifest',
|
||||
|
||||
themeColor: '#5865f2',
|
||||
themeColor: [
|
||||
{ media: '(prefers-color-scheme: light)', color: '#f1f3f5' },
|
||||
{ media: '(prefers-color-scheme: dark)', color: '#181818' },
|
||||
],
|
||||
colorScheme: 'light dark',
|
||||
|
||||
appleWebApp: {
|
||||
@@ -74,7 +77,7 @@ export const metadata: Metadata = {
|
||||
export default function RootLayout({ children }: PropsWithChildren) {
|
||||
return (
|
||||
<html className={`${inter.variable} ${jetBrainsMono.variable}`} lang="en" suppressHydrationWarning>
|
||||
<body className="dark:bg-dark-800 bg-light-600">
|
||||
<body className="bg-light-600 dark:bg-dark-600 dark:text-light-900">
|
||||
<Providers>{children}</Providers>
|
||||
<Analytics />
|
||||
</body>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export default function Loading() {
|
||||
return (
|
||||
<div className="mx-4 flex min-h-screen flex-col items-center justify-center gap-4">
|
||||
<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"
|
||||
|
||||
@@ -2,12 +2,12 @@ import Link from 'next/link';
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<div className="mx-auto flex min-h-screen max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
|
||||
<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="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center rounded border-0 px-6 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
|
||||
href="/docs/packages"
|
||||
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>
|
||||
|
||||
@@ -1,26 +1,3 @@
|
||||
import Image from 'next/image';
|
||||
import vercelLogo from '~/assets/powered-by-vercel.svg';
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="mx-auto flex min-h-screen max-w-6xl flex-col place-items-center gap-12 px-8 py-16 lg:place-content-center lg:px-8 lg:py-0">
|
||||
<div className="flex flex-row place-content-center">
|
||||
<a
|
||||
className="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"
|
||||
>
|
||||
<Image
|
||||
alt="Vercel"
|
||||
blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAABLCAQAAAA1k5H2AAAAi0lEQVR42u3SMQEAAAgDoC251a3gL2SgmfBYBRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCAgwWEOSWBnYbKggAAAABJRU5ErkJggg=="
|
||||
placeholder="blur"
|
||||
priority
|
||||
src={vercelLogo}
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,79 @@
|
||||
export function DocsLink() {
|
||||
return null;
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
81
apps/guide/src/components/Footer.tsx
Normal file
81
apps/guide/src/components/Footer.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
91
apps/guide/src/components/Header.tsx
Normal file
91
apps/guide/src/components/Header.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
'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>
|
||||
);
|
||||
}
|
||||
30
apps/guide/src/components/Nav.tsx
Normal file
30
apps/guide/src/components/Nav.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
'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>
|
||||
);
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
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-400 dark:border-dark-100 bg-light-600 border-light-800 fixed left-0 top-0 z-20 w-full border-b">
|
||||
<div className="block h-16 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 rounded-full 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} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,22 +1,19 @@
|
||||
import type { MarkdownHeading } from 'astro';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { 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: MarkdownHeading[] }) {
|
||||
const state = useLocation();
|
||||
const [active, setActive] = useState(0);
|
||||
export function Outline({ headings }: { headings: any[] }) {
|
||||
// eslint-disable-next-line react/hook-use-state
|
||||
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-0 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-none 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'
|
||||
@@ -32,18 +29,18 @@ export function Outline({ headings }: { headings: MarkdownHeading[] }) {
|
||||
[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="dark:bg-dark-100 bg-light-900 z-30 rounded" />}
|
||||
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" />
|
||||
)}
|
||||
@@ -51,13 +48,13 @@ export function Outline({ headings }: { headings: MarkdownHeading[] }) {
|
||||
>
|
||||
<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} />
|
||||
{/* <VscListSelection size={25} /> */}
|
||||
<span className="font-semibold">Contents</span>
|
||||
</div>
|
||||
<div className="ml-2 mt-4 flex flex-col gap-2">
|
||||
<div className="relative flex flex-col">
|
||||
<div
|
||||
className="bg-blurple absolute h-[10px] w-[10px] rounded-full border-2 border-black dark:border-white"
|
||||
className="absolute h-[10px] w-[10px] border-2 border-black rounded-full bg-blurple dark:border-white"
|
||||
style={{
|
||||
left: INDICATOR_SIZE / 2 + 0.5,
|
||||
transform: `translateY(${active * LINK_HEIGHT + INDICATOR_OFFSET}px)`,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export function PageButton({ url, title, direction }: { direction: 'next' | 'prev'; title: string; url: string }) {
|
||||
return (
|
||||
<a
|
||||
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 px-4 py-3 leading-none no-underline outline-0 focus:ring active:translate-y-px"
|
||||
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"
|
||||
href={url}
|
||||
>
|
||||
<h3 className="text-md font-semibold">{title}</h3>
|
||||
|
||||
8
apps/guide/src/components/Section.tsx
Normal file
8
apps/guide/src/components/Section.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
'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} />;
|
||||
}
|
||||
@@ -1,24 +1,62 @@
|
||||
import { Scrollbars } from 'react-custom-scrollbars-2';
|
||||
import type { MDXPage } from './SidebarItems.jsx';
|
||||
'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();
|
||||
|
||||
export function Sidebar({ pages, opened }: { opened: boolean; pages?: MDXPage[] | undefined }) {
|
||||
return (
|
||||
<nav
|
||||
className={`h-[calc(100vh - 65px)] dark:bg-dark-600 dark:border-dark-100 border-light-800 fixed bottom-0 left-0 top-[65px] 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 bottom-0.5 right-0.5 top-0.5 z-30 w-1.5 rounded" />
|
||||
)}
|
||||
universal
|
||||
>
|
||||
{pages ?? null}
|
||||
</Scrollbars>
|
||||
</nav>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
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={`${category}-${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={`${member.frontmatter.title}-${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>
|
||||
));
|
||||
}
|
||||
20
apps/guide/src/components/ThemeSwitcher.tsx
Normal file
20
apps/guide/src/components/ThemeSwitcher.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
'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>
|
||||
);
|
||||
}
|
||||
@@ -9,14 +9,13 @@ category: Home
|
||||
<DiscordMessage
|
||||
interaction={{
|
||||
author: {
|
||||
avatar:
|
||||
'https://cdn.discordapp.com/guilds/222078108977594368/users/81440962496172032/avatars/c059c5d04d717ea05790f7a6447e4843.webp?size=160',
|
||||
username: 'Crawl',
|
||||
avatar: '/assets/old-guide.png',
|
||||
username: 'discord.js',
|
||||
},
|
||||
command: 'upgrade',
|
||||
command: '/upgrade',
|
||||
}}
|
||||
author={{
|
||||
avatar: 'https://cdn.discordapp.com/avatars/474807795183648809/7f239a0776ff928b2182906a2b3743c9.webp?size=160',
|
||||
avatar: '/assets/discordjs.png',
|
||||
bot: true,
|
||||
username: 'Guide Bot',
|
||||
time: 'Today at 21:00',
|
||||
@@ -30,14 +29,11 @@ category: Home
|
||||
|
||||
## Site
|
||||
|
||||
- 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.
|
||||
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).
|
||||
|
||||
## 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/](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.
|
||||
|
||||
### New
|
||||
|
||||
@@ -54,13 +50,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('interactionCreate')`_
|
||||
- [Message content will become a new privileged intent on August 31, 2022](https://support-dev.discord.com/hc/en-us/articles/4404772028055)
|
||||
- _`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)
|
||||
|
||||
<DiscordMessages rounded>
|
||||
<DiscordMessage
|
||||
author={{
|
||||
avatar: 'https://cdn.discordapp.com/avatars/474807795183648809/7f239a0776ff928b2182906a2b3743c9.webp?size=160',
|
||||
avatar: '/assets/discordjs.png',
|
||||
bot: true,
|
||||
username: 'Guide Bot',
|
||||
time: 'Today at 21:00',
|
||||
177
apps/guide/src/content/01-home/03-how-to-contribute.mdx
Normal file
177
apps/guide/src/content/01-home/03-how-to-contribute.mdx
Normal file
@@ -0,0 +1,177 @@
|
||||
---
|
||||
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).
|
||||
@@ -5,17 +5,38 @@ category: Creating your bot
|
||||
|
||||
# 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 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 initializing your package.json, creating a config file for your client token, and a main file for your bot application.
|
||||
|
||||
## Creating configuration files
|
||||
## Creating package.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.
|
||||
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.
|
||||
|
||||
Open your application in the [Discord Developer Portal](https://discord.com/developers/applications) and go to the "Bot" page to copy your token.
|
||||
|
||||
### Using config.json
|
||||
|
||||
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()`_.
|
||||
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.
|
||||
|
||||
<CH.Code>
|
||||
|
||||
@@ -25,12 +46,16 @@ Storing data in a _`config.json`_ file is a common way of keeping your sensitive
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
</CH.Code>
|
||||
|
||||
```js Usage
|
||||
const { token } = require('./config.json');
|
||||
You can then access your token inside other files by using _`import`_.
|
||||
|
||||
console.log(token);
|
||||
<CH.Code>
|
||||
|
||||
```ts
|
||||
import config from './config.json' assert { type: 'json' };
|
||||
|
||||
console.log(config.token);
|
||||
```
|
||||
|
||||
</CH.Code>
|
||||
@@ -68,7 +93,9 @@ 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, require and use 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, preload the package to load your _`.env`_ file and attach the variables to _`process.env`_:
|
||||
|
||||
##### Installing dotenv
|
||||
|
||||
<CH.Code>
|
||||
|
||||
@@ -84,7 +111,11 @@ yarn add dotenv
|
||||
pnpm add dotenv
|
||||
```
|
||||
|
||||
---
|
||||
</CH.Code>
|
||||
|
||||
##### Defining your variables
|
||||
|
||||
<CH.Code>
|
||||
|
||||
```text .env
|
||||
A=123
|
||||
@@ -92,18 +123,6 @@ 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">
|
||||
@@ -111,6 +130,28 @@ console.log(process.env.DISCORD_TOKEN);
|
||||
_`.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>
|
||||
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:
|
||||
|
||||
@@ -145,44 +186,46 @@ config.json
|
||||
|
||||
## Creating the main file
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Here's the base code to get you started:
|
||||
|
||||
<CH.Code>
|
||||
|
||||
```js
|
||||
// Require the necessary discord.js classes
|
||||
const { Client, GatewayIntentBits } = require('discord.js');
|
||||
const { token } = require('./config.json');
|
||||
```ts index.ts
|
||||
// Import the necessary structures.
|
||||
import { Client, Events, GatewayIntentBits } from 'discord.js';
|
||||
import config from './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('ready', () => {
|
||||
// When the client is ready, run this code (only once).
|
||||
client.once(Events.ClientReady, () => {
|
||||
console.log('Ready!');
|
||||
});
|
||||
|
||||
// Login to Discord with your client's token
|
||||
client.login(token);
|
||||
// Log in to Discord with your client's token.
|
||||
client.login(config.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 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, 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!
|
||||
|
||||
<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 _`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.
|
||||
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.
|
||||
</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.
|
||||
@@ -97,9 +97,9 @@ 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 path="class/Client?scrollTo=e-interactionCreate" /> in your _`index.js`_ file.
|
||||
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.
|
||||
|
||||
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>.
|
||||
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>.
|
||||
|
||||
<CH.Code>
|
||||
|
||||
@@ -126,7 +126,7 @@ 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 path="class/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 type="class" parent="Guild" /> instance), which exposes properties such as _`.name`_ or _`.memberCount`_.
|
||||
|
||||
<CH.Code>
|
||||
|
||||
@@ -171,12 +171,13 @@ 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 path="class/Guild" /> documentation for a list of all the available properties and methods!
|
||||
Refer to the <DocsLink type="class" parent="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 path="class/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 type="class" parent="User" /> instance), which exposes properties such as _`.tag`_ or _`.id`_.
|
||||
|
||||
<CH.Code>
|
||||
|
||||
@@ -219,7 +220,8 @@ client.on('interactionCreate', async (interaction) => {
|
||||
</DiscordMessages>
|
||||
|
||||
<Alert title="Tip" type="success">
|
||||
Refer to the <DocsLink path="class/User" /> documentation for a list of all the available properties and methods!
|
||||
Refer to the <DocsLink type="class" parent="User" /> documentation for a list of all the available properties and
|
||||
methods!
|
||||
</Alert>
|
||||
|
||||
And there you have it!
|
||||
@@ -102,15 +102,15 @@ Now that you know how Promises work and what they are used for, let's look at an
|
||||
<CH.Code>
|
||||
|
||||
```js
|
||||
const { Client, GatewayIntentBits } = require('discord.js');
|
||||
import { Client, Events, GatewayIntentBits } from 'discord.js';
|
||||
|
||||
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
|
||||
|
||||
client.once('ready', () => {
|
||||
client.once(Events.ClientReady, () => {
|
||||
console.log('I am ready!');
|
||||
});
|
||||
|
||||
client.on('interactionCreate', (interaction) => {
|
||||
client.on(Events.InteractionCreate, (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
if (interaction.commandName === 'react') {
|
||||
@@ -106,7 +106,7 @@ 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`\_s, but done at the same time:
|
||||
You can think of it as two \_`filter`\_ methods, but done at the same time:
|
||||
|
||||
<CH.Code>
|
||||
|
||||
805
apps/guide/src/content/03-additional-info/03-updating-to-v14.mdx
Normal file
805
apps/guide/src/content/03-additional-info/03-updating-to-v14.mdx
Normal file
@@ -0,0 +1,805 @@
|
||||
---
|
||||
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
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
title: Requesting more content
|
||||
category: Home
|
||||
---
|
||||
|
||||
# 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>
|
||||
@@ -1,100 +0,0 @@
|
||||
---
|
||||
title: Test
|
||||
category: Test
|
||||
---
|
||||
|
||||
<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>
|
||||
27
apps/guide/src/contexts/nav.tsx
Normal file
27
apps/guide/src/contexts/nav.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
'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);
|
||||
}
|
||||
9
apps/guide/src/middleware.ts
Normal file
9
apps/guide/src/middleware.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
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'],
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
:root {
|
||||
--shiki-color-text: #24292eff;
|
||||
--shiki-color-background: #ffffff;
|
||||
--shiki-token-constant: #1976d2;
|
||||
--shiki-token-string: #6f42c1;
|
||||
--shiki-token-comment: #c2c3c5;
|
||||
--shiki-token-keyword: #d32f2f;
|
||||
--shiki-token-parameter: #ff9800;
|
||||
--shiki-token-function: #6f42c1;
|
||||
--shiki-token-string-expression: #22863a;
|
||||
--shiki-token-punctuation: #212121;
|
||||
--shiki-token-link: #22863a;
|
||||
|
||||
--ch-tabs-bg: #f6f6f6;
|
||||
--ch-tab-border: #f6f6f6;
|
||||
--ch-tab-active-border: #fff;
|
||||
--ch-tab-active-bg: #24292eff;
|
||||
--ch-tab-inactive-color: #bdbdbd;
|
||||
--ch-tab-inactive-bg: #f6f6f6;
|
||||
--ch-icon-text: #24292eff;
|
||||
}
|
||||
|
||||
.ch-code,
|
||||
.ch-inline-code > code {
|
||||
background: var(--shiki-color-background) !important;
|
||||
}
|
||||
|
||||
.ch-code {
|
||||
color-scheme: light !important;
|
||||
}
|
||||
|
||||
.ch-code-multiline-mark {
|
||||
background: rgba(253, 255, 0, 0.2) !important;
|
||||
}
|
||||
|
||||
.ch-codegroup .ch-editor-button,
|
||||
.ch-codeblock .ch-code-button {
|
||||
color: var(--ch-icon-text) !important;
|
||||
}
|
||||
|
||||
div.ch-editor-tab-active {
|
||||
color: var(--ch-tab-active-color) !important;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--shiki-color-text: #adbac7;
|
||||
--shiki-color-background: #22272e;
|
||||
--shiki-token-constant: #f47067;
|
||||
--shiki-token-string: #96d0ff;
|
||||
--shiki-token-comment: #768390;
|
||||
--shiki-token-keyword: #f47067;
|
||||
--shiki-token-parameter: #adbac7;
|
||||
--shiki-token-function: #dcbdfb;
|
||||
--shiki-token-string-expression: #8ddb8c;
|
||||
--shiki-token-punctuation: #adbac7;
|
||||
--shiki-token-link: #adbac7;
|
||||
|
||||
--ch-tabs-bg: #1c2128;
|
||||
--ch-tab-border: #444c56;
|
||||
--ch-tab-active-border: #22272e;
|
||||
--ch-tab-active-bg: #22272e;
|
||||
--ch-tab-inactive-color: #768390;
|
||||
--ch-tab-inactive-bg: #1c2128;
|
||||
--ch-icon-text: #768390;
|
||||
}
|
||||
|
||||
.dark .ch-codegroup .ch-editor-button,
|
||||
.ch-codeblock .ch-code-button {
|
||||
color: var(--ch-icon-text) !important;
|
||||
}
|
||||
|
||||
.dark div.ch-editor-tab-active {
|
||||
color: var(--ch-tab-active-color) !important;
|
||||
}
|
||||
|
||||
.dark .ch-code {
|
||||
color-scheme: dark !important;
|
||||
}
|
||||
|
||||
.dark .ch-code-multiline-mark {
|
||||
background: rgba(255, 255, 255, 0.043) !important;
|
||||
}
|
||||
|
||||
566
apps/guide/src/styles/code-hike-theme-dark-plus.json
Normal file
566
apps/guide/src/styles/code-hike-theme-dark-plus.json
Normal file
@@ -0,0 +1,566 @@
|
||||
{
|
||||
"$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"
|
||||
}
|
||||
@@ -1,3 +1,27 @@
|
||||
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;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": ["../../.eslintrc.json", "neon/react", "neon/next", "neon/edge", "neon/prettier"],
|
||||
"extends": ["../../.eslintrc.json", "neon/react", "neon/next", "neon/edge", "@unocss", "neon/prettier"],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
|
||||
1
apps/website/.gitignore
vendored
1
apps/website/.gitignore
vendored
@@ -23,6 +23,7 @@ build/
|
||||
src/styles/unocss.css
|
||||
.next/
|
||||
src/assets/readme/
|
||||
static/
|
||||
|
||||
# Miscellaneous
|
||||
.tmp/
|
||||
|
||||
@@ -1,7 +1 @@
|
||||
module.exports = {
|
||||
...require('../../.prettierrc.json'),
|
||||
plugins: [
|
||||
'prettier-plugin-tailwindcss', // MUST come last
|
||||
],
|
||||
pluginSearchDirs: false,
|
||||
};
|
||||
module.exports = require('../../.prettierrc.json');
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import bundleAnalyzer from '@next/bundle-analyzer';
|
||||
|
||||
const withBundleAnalyzer = bundleAnalyzer({
|
||||
@@ -7,18 +6,8 @@ const withBundleAnalyzer = bundleAnalyzer({
|
||||
|
||||
export default withBundleAnalyzer({
|
||||
reactStrictMode: true,
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
// Until Next.js fixes their type issues
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
outputFileTracing: true,
|
||||
experimental: {
|
||||
appDir: true,
|
||||
outputFileTracingRoot: fileURLToPath(new URL('../../', import.meta.url)),
|
||||
fallbackNodePolyfills: false,
|
||||
serverComponentsExternalPackages: ['@microsoft/api-extractor-model', 'jju'],
|
||||
},
|
||||
images: {
|
||||
@@ -33,6 +22,11 @@ export default withBundleAnalyzer({
|
||||
destination: '/logo.svg',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: '/guide/:path*',
|
||||
destination: 'https://next.discordjs.guide/guide/:path*',
|
||||
permanent: true,
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
@@ -50,62 +50,58 @@
|
||||
"@discordjs/ui": "workspace:^",
|
||||
"@microsoft/api-extractor-model": "7.26.4",
|
||||
"@microsoft/tsdoc": "0.14.2",
|
||||
"@planetscale/database": "^1.6.0",
|
||||
"@planetscale/database": "1.7.0",
|
||||
"@react-icons/all-files": "^4.1.0",
|
||||
"@vercel/analytics": "^0.1.11",
|
||||
"@vercel/edge-config": "^0.1.5",
|
||||
"@vercel/og": "^0.5.0",
|
||||
"@vercel/edge-config": "^0.1.7",
|
||||
"@vercel/og": "^0.5.2",
|
||||
"@vscode/codicons": "^0.0.32",
|
||||
"ariakit": "^2.0.0-next.43",
|
||||
"bright": "^0.7.0",
|
||||
"ariakit": "^2.0.0-next.44",
|
||||
"bright": "^0.7.1",
|
||||
"cmdk": "^0.2.0",
|
||||
"meilisearch": "^0.32.0",
|
||||
"next": "^13.2.5-canary.23",
|
||||
"meilisearch": "^0.32.3",
|
||||
"next": "^13.3.1-canary.8",
|
||||
"next-mdx-remote": "^4.4.1",
|
||||
"next-themes": "^0.2.1",
|
||||
"react": "^18.2.0",
|
||||
"react-custom-scrollbars-2": "^4.5.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-use": "^17.4.0",
|
||||
"rehype-ignore": "^1.0.4",
|
||||
"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",
|
||||
"swr": "^2.1.1"
|
||||
"swr": "^2.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "^13.2.4",
|
||||
"@next/bundle-analyzer": "^13.3.0",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/node": "18.15.11",
|
||||
"@types/react": "^18.0.31",
|
||||
"@types/react": "^18.0.35",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@unocss/cli": "^0.50.6",
|
||||
"@unocss/reset": "^0.50.6",
|
||||
"@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.29.8",
|
||||
"@vitest/coverage-c8": "^0.30.1",
|
||||
"concurrently": "^8.0.1",
|
||||
"cpy-cli": "^4.2.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.37.0",
|
||||
"eslint-config-neon": "^0.1.41",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-config-neon": "^0.1.42",
|
||||
"eslint-formatter-pretty": "^5.0.0",
|
||||
"happy-dom": "^8.9.0",
|
||||
"lighthouse": "^10.1.0",
|
||||
"happy-dom": "^9.7.1",
|
||||
"lighthouse": "^10.1.1",
|
||||
"prettier": "^2.8.7",
|
||||
"prettier-plugin-tailwindcss": "^0.2.6",
|
||||
"typescript": "^5.0.3",
|
||||
"unocss": "^0.50.6",
|
||||
"vercel": "^28.18.3",
|
||||
"typescript": "^5.0.4",
|
||||
"unocss": "^0.51.4",
|
||||
"vercel": "^28.18.5",
|
||||
"vitest": "^0.29.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.13.0"
|
||||
},
|
||||
"nextBundleAnalysis": {
|
||||
"budget": 358400,
|
||||
"budgetPercentIncreaseRed": 20,
|
||||
"showDetails": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
import { get } from '@vercel/edge-config';
|
||||
import { NextResponse } from 'next/server';
|
||||
import type { ServerRuntime } from 'next/types';
|
||||
|
||||
export const runtime: ServerRuntime = 'edge';
|
||||
export const runtime = 'edge';
|
||||
|
||||
export async function GET() {
|
||||
const url = await get<string>('DISCORD_WEBHOOK_URL');
|
||||
const imageUrl = await get<string>('IT_IS_WEDNESDAY_MY_DUDES');
|
||||
if (url && imageUrl) {
|
||||
await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
username: 'It is wednesday, my dudes',
|
||||
embeds: [
|
||||
{
|
||||
image: {
|
||||
url: imageUrl,
|
||||
try {
|
||||
const url = await get<string>('DISCORD_WEBHOOK_URL');
|
||||
const imageUrl = await get<string>('IT_IS_WEDNESDAY_MY_DUDES');
|
||||
if (url && imageUrl) {
|
||||
await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
username: 'It is wednesday, my dudes',
|
||||
embeds: [
|
||||
{
|
||||
image: {
|
||||
url: imageUrl,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
}
|
||||
],
|
||||
}),
|
||||
});
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return NextResponse.json({ message: 'It is wednesday, my dudes' });
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
import type { ApiItemKind } from '@microsoft/api-extractor-model';
|
||||
import { ImageResponse } from '@vercel/og';
|
||||
import type { NextRequest } from 'next/server';
|
||||
import type { ServerRuntime } from 'next/types';
|
||||
|
||||
export const runtime: ServerRuntime = 'edge';
|
||||
export const runtime = 'edge';
|
||||
|
||||
const fonts = Promise.all([
|
||||
fetch(new URL('../../../assets/fonts/Inter-Regular.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()),
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/* eslint-disable react/no-unknown-property */
|
||||
|
||||
import { ImageResponse } from '@vercel/og';
|
||||
import type { ServerRuntime } from 'next/types';
|
||||
|
||||
export const runtime: ServerRuntime = 'edge';
|
||||
export const runtime = 'edge';
|
||||
|
||||
const fonts = fetch(new URL('../../../assets/fonts/Inter-Black.ttf', import.meta.url)).then(async (res) =>
|
||||
res.arrayBuffer(),
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import 'server-only';
|
||||
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import { connect } from '@planetscale/database';
|
||||
import { cache } from 'react';
|
||||
|
||||
const sql = connect({ url: process.env.DATABASE_URL! });
|
||||
const sql = connect({
|
||||
async fetch(input, init) {
|
||||
// @ts-expect-error: Deleting cache or setting as undefined, same thing
|
||||
return fetch(input, { ...init, cache: undefined, next: { revalidate: 3_600 } });
|
||||
},
|
||||
url: process.env.DATABASE_URL!,
|
||||
});
|
||||
|
||||
export async function fetchVersions(packageName: string): Promise<string[]> {
|
||||
const response = await fetch(`https://docs.discordjs.dev/api/info?package=${packageName}`, {
|
||||
@@ -13,7 +20,7 @@ export async function fetchVersions(packageName: string): Promise<string[]> {
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export const fetchModelJSON = cache(async (packageName: string, version: string): Promise<unknown> => {
|
||||
export async function fetchModelJSON(packageName: string, version: string): Promise<unknown> {
|
||||
if (process.env.NEXT_PUBLIC_LOCAL_DEV) {
|
||||
const res = await readFile(
|
||||
join(process.cwd(), '..', '..', 'packages', packageName, 'docs', 'docs.api.json'),
|
||||
@@ -35,4 +42,4 @@ export const fetchModelJSON = cache(async (packageName: string, version: string)
|
||||
|
||||
// @ts-expect-error: https://github.com/planetscale/database-js/issues/71
|
||||
return rows[0].data;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from '~/app/loading';
|
||||
@@ -0,0 +1,22 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
|
||||
export default function NotFound() {
|
||||
const pathname = usePathname();
|
||||
const href = pathname.split('/').slice(0, -1).join('/');
|
||||
|
||||
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={href}
|
||||
>
|
||||
Take me back
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -12,10 +12,11 @@ import type {
|
||||
ApiPropertySignature,
|
||||
ApiTypeAlias,
|
||||
ApiVariable,
|
||||
ApiFunction,
|
||||
} from '@microsoft/api-extractor-model';
|
||||
import { ApiItemKind, ApiModel, ApiFunction } from '@microsoft/api-extractor-model';
|
||||
import { ApiItemKind, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import type { Metadata } from 'next';
|
||||
import { notFound } from 'next/navigation';
|
||||
import type { Metadata } from 'next/types';
|
||||
import { fetchModelJSON } from '~/app/docAPI';
|
||||
import { Class } from '~/components/model/Class';
|
||||
import { Interface } from '~/components/model/Interface';
|
||||
@@ -23,35 +24,29 @@ import { TypeAlias } from '~/components/model/TypeAlias';
|
||||
import { Variable } from '~/components/model/Variable';
|
||||
import { Enum } from '~/components/model/enum/Enum';
|
||||
import { Function } from '~/components/model/function/Function';
|
||||
import { OVERLOAD_SEPARATOR, PACKAGES } from '~/util/constants';
|
||||
import { findMember, findMemberByKey } from '~/util/model.server';
|
||||
import { OVERLOAD_SEPARATOR } from '~/util/constants';
|
||||
import type { ItemRouteParams } from '~/util/fetchMember';
|
||||
import { fetchMember } from '~/util/fetchMember';
|
||||
import { findMember } from '~/util/model';
|
||||
|
||||
export interface ItemRouteParams {
|
||||
item: string;
|
||||
package: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
async function fetchHeadMember({ package: packageName, version, item }: ItemRouteParams): Promise<ApiItem | undefined> {
|
||||
async function fetchHeadMember({ package: packageName, version, item }: ItemRouteParams) {
|
||||
const modelJSON = await fetchModelJSON(packageName, version);
|
||||
const model = addPackageToModel(new ApiModel(), modelJSON);
|
||||
const pkg = model.tryGetPackageByName(packageName);
|
||||
const entry = pkg?.entryPoints[0];
|
||||
|
||||
if (!entry) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const [memberName] = decodeURIComponent(item).split(OVERLOAD_SEPARATOR);
|
||||
|
||||
return findMember(model, packageName, memberName);
|
||||
}
|
||||
|
||||
function resolveMemberSearchParams(packageName: string, member: ApiItem): URLSearchParams {
|
||||
function resolveMemberSearchParams(packageName: string, member?: ApiItem) {
|
||||
const params = new URLSearchParams({
|
||||
pkg: packageName,
|
||||
kind: member?.kind,
|
||||
name: member?.displayName,
|
||||
kind: member?.kind ?? '',
|
||||
name: member?.displayName ?? '',
|
||||
});
|
||||
|
||||
switch (member?.kind) {
|
||||
@@ -84,11 +79,8 @@ function resolveMemberSearchParams(packageName: string, member: ApiItem): URLSea
|
||||
return params;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line unicorn/numeric-separators-style
|
||||
export const revalidate = 3600;
|
||||
|
||||
export async function generateMetadata({ params }: { params: ItemRouteParams }) {
|
||||
const member = (await fetchHeadMember(params))!;
|
||||
const member = await fetchHeadMember(params);
|
||||
const name = `discord.js${member?.displayName ? ` | ${member.displayName}` : ''}`;
|
||||
const ogTitle = `${params.package ?? 'discord.js'}${member?.displayName ? ` | ${member.displayName}` : ''}`;
|
||||
const url = new URL('https://discordjs.dev/api/dynamic-open-graph.png');
|
||||
@@ -120,39 +112,10 @@ export async function generateStaticParams({ params: { package: packageName, ver
|
||||
}
|
||||
|
||||
return entry.members.map((member: ApiItem) => ({
|
||||
item: member.displayName,
|
||||
item: `${member.displayName}${OVERLOAD_SEPARATOR}${member.kind}`,
|
||||
}));
|
||||
}
|
||||
|
||||
async function fetchMember({ package: packageName, version: branchName = 'main', item }: ItemRouteParams) {
|
||||
if (!PACKAGES.includes(packageName)) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const model = new ApiModel();
|
||||
|
||||
if (branchName === 'main') {
|
||||
const modelJSONFiles = await Promise.all(PACKAGES.map(async (pkg) => fetchModelJSON(pkg, branchName)));
|
||||
|
||||
for (const modelJSONFile of modelJSONFiles) {
|
||||
addPackageToModel(model, modelJSONFile);
|
||||
}
|
||||
} else {
|
||||
const modelJSON = await fetchModelJSON(packageName, branchName);
|
||||
addPackageToModel(model, modelJSON);
|
||||
}
|
||||
|
||||
const [memberName, overloadIndex] = decodeURIComponent(item).split(OVERLOAD_SEPARATOR);
|
||||
|
||||
// eslint-disable-next-line prefer-const
|
||||
let { containerKey, displayName: name } = findMember(model, packageName, memberName) ?? {};
|
||||
if (name && overloadIndex && !Number.isNaN(Number.parseInt(overloadIndex, 10))) {
|
||||
containerKey = ApiFunction.getContainerKey(name, Number.parseInt(overloadIndex, 10));
|
||||
}
|
||||
|
||||
return memberName && containerKey ? findMemberByKey(model, packageName, containerKey) ?? null : null;
|
||||
}
|
||||
|
||||
function Member({ member }: { member?: ApiItem }) {
|
||||
switch (member?.kind) {
|
||||
case 'Class':
|
||||
@@ -175,5 +138,13 @@ function Member({ member }: { member?: ApiItem }) {
|
||||
export default async function Page({ params }: { params: ItemRouteParams }) {
|
||||
const member = await fetchMember(params);
|
||||
|
||||
return <div className="relative top-6">{member ? <Member member={member} /> : null}</div>;
|
||||
if (!member) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative top-6">
|
||||
<Member member={member} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ export default function Error({ error }: { error: Error }) {
|
||||
console.error(error);
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex h-full max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
|
||||
<div className="mx-auto h-full max-w-lg 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>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { notFound } from 'next/navigation';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { Providers } from './providers';
|
||||
import { fetchModelJSON, fetchVersions } from '~/app/docAPI';
|
||||
import { Banner } from '~/components/Banner';
|
||||
import { CmdKDialog } from '~/components/CmdK';
|
||||
import { Nav } from '~/components/Nav';
|
||||
import type { SidebarSectionItemData } from '~/components/Sidebar';
|
||||
@@ -20,9 +21,6 @@ export interface VersionRouteParams {
|
||||
version: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line unicorn/numeric-separators-style
|
||||
export const revalidate = 3600;
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const params: VersionRouteParams[] = [];
|
||||
|
||||
@@ -72,14 +70,15 @@ export default async function PackageLayout({ children, params }: PropsWithChild
|
||||
|
||||
return (
|
||||
<Providers>
|
||||
<Banner className="mb-6" />
|
||||
<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:flex lg:max-w-full">
|
||||
<div className="lg:top-23 lg:sticky lg:h-[calc(100vh_-_100px)]">
|
||||
<div className="relative top-2.5 mx-auto max-w-7xl gap-6 lg:max-w-full lg:flex">
|
||||
<div className="lg:sticky lg:top-23 lg:h-[calc(100vh_-_145px)]">
|
||||
<Nav members={members.map((member) => serializeIntoSidebarItemData(member))} />
|
||||
</div>
|
||||
|
||||
<div className="min-w-xs mx-auto w-full max-w-5xl pb-10">
|
||||
<div className="mx-auto max-w-5xl min-w-xs w-full pb-10">
|
||||
{children}
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from '~/app/loading';
|
||||
@@ -27,7 +27,7 @@ export default async function Page({ params }: { params: VersionRouteParams }) {
|
||||
const readmeSource = await loadREADME(packageName);
|
||||
|
||||
return (
|
||||
<div className="prose max-w-none">
|
||||
<div className="max-w-none prose">
|
||||
{/* @ts-expect-error async component */}
|
||||
<MDXRemote components={{ pre: SyntaxHighlighter }} options={mdxOptions} source={readmeSource} />
|
||||
</div>
|
||||
|
||||
@@ -3,10 +3,9 @@ import { VscArrowRight } from '@react-icons/all-files/vsc/VscArrowRight';
|
||||
import { VscVersions } from '@react-icons/all-files/vsc/VscVersions';
|
||||
import Link from 'next/link';
|
||||
import { notFound } from 'next/navigation';
|
||||
import type { ServerRuntime } from 'next/types';
|
||||
import { PACKAGES } from '~/util/constants';
|
||||
|
||||
export const runtime: ServerRuntime = 'edge';
|
||||
export const runtime = 'edge';
|
||||
|
||||
async function getData(pkg: string) {
|
||||
if (!PACKAGES.includes(pkg)) {
|
||||
@@ -27,12 +26,12 @@ export default async function Page({ params }: { params: { package: string } })
|
||||
const data = await getData(params.package);
|
||||
|
||||
return (
|
||||
<div className="min-w-xs sm:w-md mx-auto flex min-h-screen flex-col gap-8 px-4 py-6 lg:px-6 lg:py-6">
|
||||
<div className="mx-auto min-h-screen min-w-xs flex flex-col gap-8 px-4 py-6 sm:w-md lg:px-6 lg:py-6">
|
||||
<h1 className="text-2xl font-semibold">Select a version:</h1>
|
||||
<div className="flex flex-col gap-4">
|
||||
{data.map((version, idx) => (
|
||||
<Link
|
||||
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-col place-content-center rounded border border-neutral-300 bg-white p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
|
||||
className="h-11 flex flex-col transform-gpu cursor-pointer select-none appearance-none place-content-center border border-neutral-300 rounded bg-white p-4 text-base font-semibold leading-none text-black outline-none active:translate-y-px dark:border-dark-100 active:bg-neutral-200 dark:bg-dark-400 hover:bg-neutral-100 dark:text-white focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-200 dark:hover:bg-dark-300"
|
||||
href={`/docs/packages/${params.package}/${version}`}
|
||||
key={`${version}-${idx}`}
|
||||
>
|
||||
@@ -47,7 +46,7 @@ export default async function Page({ params }: { params: { package: string } })
|
||||
)) ?? null}
|
||||
</div>
|
||||
<Link
|
||||
className="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center gap-2 place-self-center rounded border-0 px-4 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
|
||||
className="h-11 flex flex-row transform-gpu cursor-pointer select-none appearance-none place-items-center place-self-center gap-2 border-0 rounded bg-blurple px-4 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="/docs/packages"
|
||||
>
|
||||
<VscArrowLeft size={20} /> Go back
|
||||
|
||||
@@ -3,18 +3,17 @@ import { VscArrowLeft } from '@react-icons/all-files/vsc/VscArrowLeft';
|
||||
import { VscArrowRight } from '@react-icons/all-files/vsc/VscArrowRight';
|
||||
import { VscPackage } from '@react-icons/all-files/vsc/VscPackage';
|
||||
import Link from 'next/link';
|
||||
import type { ServerRuntime } from 'next/types';
|
||||
import { PACKAGES } from '~/util/constants';
|
||||
|
||||
export const runtime: ServerRuntime = 'edge';
|
||||
export const runtime = 'edge';
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="min-w-xs sm:w-md mx-auto flex min-h-screen flex-col gap-8 px-4 py-6 lg:px-6 lg:py-6">
|
||||
<div className="mx-auto min-h-screen min-w-xs flex flex-col gap-8 px-4 py-6 sm:w-md lg:px-6 lg:py-6">
|
||||
<h1 className="text-2xl font-semibold">Select a package:</h1>
|
||||
<div className="flex flex-col gap-4">
|
||||
<a
|
||||
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none place-content-between rounded border border-neutral-300 bg-white p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
|
||||
className="h-11 flex transform-gpu cursor-pointer select-none appearance-none place-content-between border border-neutral-300 rounded bg-white p-4 text-base font-semibold leading-none text-black outline-none active:translate-y-px dark:border-dark-100 active:bg-neutral-200 dark:bg-dark-400 hover:bg-neutral-100 dark:text-white focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-200 dark:hover:bg-dark-300"
|
||||
href="https://old.discordjs.dev/#/docs/discord.js"
|
||||
>
|
||||
<div className="flex grow flex-row place-content-between place-items-center gap-4">
|
||||
@@ -29,7 +28,7 @@ export default function Page() {
|
||||
</a>
|
||||
{PACKAGES.map((pkg, idx) => (
|
||||
<Link
|
||||
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-content-between rounded border border-neutral-300 bg-white p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
|
||||
className="h-11 flex flex-row transform-gpu cursor-pointer select-none appearance-none place-content-between border border-neutral-300 rounded bg-white p-4 text-base font-semibold leading-none text-black outline-none active:translate-y-px dark:border-dark-100 active:bg-neutral-200 dark:bg-dark-400 hover:bg-neutral-100 dark:text-white focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-200 dark:hover:bg-dark-300"
|
||||
href={`/docs/packages/${pkg}`}
|
||||
key={`${pkg}-${idx}`}
|
||||
>
|
||||
@@ -41,7 +40,7 @@ export default function Page() {
|
||||
</div>
|
||||
{/* <Link href={`/docs/packages/${pkg}`}>
|
||||
<div
|
||||
className="bg-blurple focus:ring-width-2 flex h-6 transform-gpu cursor-pointer select-none appearance-none flex-row place-content-center place-items-center rounded border-0 px-2 text-xs font-semibold leading-none text-white outline-0 focus:ring focus:ring-white active:translate-y-px"
|
||||
className="bg-blurple focus:ring-width-2 flex h-6 transform-gpu cursor-pointer select-none appearance-none flex-row place-content-center place-items-center rounded border-0 px-2 text-xs font-semibold leading-none text-white outline-none focus:ring focus:ring-white active:translate-y-px"
|
||||
role="link"
|
||||
>
|
||||
Select version
|
||||
@@ -53,7 +52,7 @@ export default function Page() {
|
||||
</Link>
|
||||
))}
|
||||
<a
|
||||
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none place-content-between rounded border border-neutral-300 bg-white p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
|
||||
className="h-11 flex transform-gpu cursor-pointer select-none appearance-none place-content-between border border-neutral-300 rounded bg-white p-4 text-base font-semibold leading-none text-black outline-none active:translate-y-px dark:border-dark-100 active:bg-neutral-200 dark:bg-dark-400 hover:bg-neutral-100 dark:text-white focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-200 dark:hover:bg-dark-300"
|
||||
href="https://discord-api-types.dev/"
|
||||
>
|
||||
<div className="flex grow flex-row place-content-between place-items-center gap-4">
|
||||
@@ -68,7 +67,7 @@ export default function Page() {
|
||||
</a>
|
||||
</div>
|
||||
<Link
|
||||
className="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center gap-2 place-self-center rounded border-0 px-4 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
|
||||
className="h-11 flex flex-row transform-gpu cursor-pointer select-none appearance-none place-items-center place-self-center gap-2 border-0 rounded bg-blurple px-4 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="/"
|
||||
>
|
||||
<VscArrowLeft size={20} /> Go back
|
||||
|
||||
@@ -4,7 +4,7 @@ export default function Error({ error }: { error: Error }) {
|
||||
console.error(error);
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex min-h-screen max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
|
||||
<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>
|
||||
|
||||
@@ -8,10 +8,10 @@ export default function GlobalError({ error }: { error: Error }) {
|
||||
|
||||
return (
|
||||
<html className={inter.variable} lang="en" suppressHydrationWarning>
|
||||
<body className="dark:bg-dark-800 bg-light-600">
|
||||
<body className="bg-light-600 dark:bg-dark-600 dark:text-light-900">
|
||||
<Providers>
|
||||
<main className="mx-auto min-h-screen max-w-2xl">
|
||||
<div className="mx-auto flex min-h-screen max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
|
||||
<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>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Analytics } from '@vercel/analytics/react';
|
||||
import type { Metadata } from 'next/types';
|
||||
import type { Metadata } from 'next';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { Providers } from './providers';
|
||||
import { DESCRIPTION } from '~/util/constants';
|
||||
@@ -44,7 +44,7 @@ export const metadata: Metadata = {
|
||||
|
||||
themeColor: [
|
||||
{ media: '(prefers-color-scheme: light)', color: '#f1f3f5' },
|
||||
{ media: '(prefers-color-scheme: dark)', color: '#181818' },
|
||||
{ media: '(prefers-color-scheme: dark)', color: '#1c1c1e' },
|
||||
],
|
||||
colorScheme: 'light dark',
|
||||
|
||||
@@ -68,14 +68,14 @@ export const metadata: Metadata = {
|
||||
},
|
||||
|
||||
other: {
|
||||
'msapplication-TileColor': '#090a16',
|
||||
'msapplication-TileColor': '#1c1c1e',
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }: PropsWithChildren) {
|
||||
return (
|
||||
<html className={`${inter.variable} ${jetBrainsMono.variable}`} lang="en" suppressHydrationWarning>
|
||||
<body className="dark:bg-dark-800 bg-light-600">
|
||||
<body className="bg-light-600 dark:bg-dark-600 dark:text-light-900">
|
||||
<Providers>{children}</Providers>
|
||||
<Analytics />
|
||||
</body>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export default function Loading() {
|
||||
return (
|
||||
<div className="mx-4 flex min-h-screen flex-col items-center justify-center gap-4">
|
||||
<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"
|
||||
|
||||
@@ -2,12 +2,12 @@ import Link from 'next/link';
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<div className="mx-auto flex min-h-screen max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
|
||||
<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="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center rounded border-0 px-6 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
|
||||
href="/docs/packages"
|
||||
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="/docs"
|
||||
>
|
||||
Take me back
|
||||
</Link>
|
||||
|
||||
@@ -2,67 +2,70 @@ import { FiExternalLink } from '@react-icons/all-files/fi/FiExternalLink';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import vercelLogo from '~/assets/powered-by-vercel.svg';
|
||||
import { SyntaxHighlighter } from '~/components/SyntaxHighlighter';
|
||||
import { CODE_EXAMPLE } from '~/util/constants';
|
||||
import { Banner } from '~/components/Banner';
|
||||
import { InstallButton } from '~/components/InstallButton';
|
||||
import { DESCRIPTION } from '~/util/constants';
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="mx-auto flex min-h-screen max-w-6xl flex-col place-items-center gap-12 px-8 py-16 lg:place-content-center lg:px-8 lg:py-0">
|
||||
<div className="flex flex-col place-items-center gap-10 lg:flex-row lg:gap-6">
|
||||
<div className="flex max-w-lg flex-col gap-3 lg:mr-8">
|
||||
<h1 className="text-3xl font-black leading-tight sm:text-5xl sm:leading-tight">
|
||||
The <span className="bg-blurple relative rounded px-3 py-1 text-white">most popular</span> way to build
|
||||
Discord <br /> bots.
|
||||
</h1>
|
||||
<p className="my-6 leading-normal text-neutral-700 dark:text-neutral-300">
|
||||
discord.js is a powerful node.js module that allows you to interact with the Discord API very easily. It
|
||||
takes a much more object-oriented approach than most other JS Discord libraries, making your bot's code
|
||||
significantly tidier and easier to comprehend.
|
||||
</p>
|
||||
<div className="flex flex-row gap-4">
|
||||
<Link
|
||||
className="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center rounded border-0 px-6 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
|
||||
href="/docs"
|
||||
>
|
||||
Docs
|
||||
</Link>
|
||||
<a
|
||||
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 border-light-900 hover:bg-light-200 active:bg-light-300 focus:ring-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center gap-2 rounded border bg-white px-4 text-base font-semibold leading-none text-black no-underline outline-0 focus:ring active:translate-y-px dark:text-white"
|
||||
href="https://discordjs.guide"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Guide <FiExternalLink />
|
||||
</a>
|
||||
<a
|
||||
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 border-light-900 hover:bg-light-200 active:bg-light-300 focus:ring-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none appearance-none flex-row place-items-center gap-2 rounded border bg-white px-4 text-base font-semibold leading-none text-black no-underline outline-0 focus:ring active:translate-y-px dark:text-white"
|
||||
href="https://github.com/discordjs/discord.js"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
GitHub <FiExternalLink />
|
||||
</a>
|
||||
<div className="min-h-screen">
|
||||
<Banner />
|
||||
<div className="mx-auto max-w-6xl flex flex-col place-items-center gap-24 px-8 pb-16 pt-12 lg:min-h-[calc(100vh_-_40px)] lg:place-content-center lg:py-10">
|
||||
<div className="flex flex-col place-items-center gap-10 lg:flex-row lg:gap-6">
|
||||
<div className="flex flex-col place-items-center gap-8 text-center">
|
||||
<h1 className="text-3xl font-black leading-tight sm:text-7xl sm:leading-tight">
|
||||
The <span className="relative rounded bg-blurple px-3 py-1 text-white">most popular</span> way to build
|
||||
Discord bots.
|
||||
</h1>
|
||||
<p className="my-6 leading-normal text-neutral-700 dark:text-neutral-300">{DESCRIPTION}</p>
|
||||
<div className="flex flex-row gap-4">
|
||||
<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="/docs"
|
||||
>
|
||||
Docs
|
||||
</Link>
|
||||
{/* <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"
|
||||
>
|
||||
Guide
|
||||
</Link> */}
|
||||
<a
|
||||
className="h-11 flex flex-row transform-gpu cursor-pointer select-none appearance-none place-items-center gap-2 border border-light-900 rounded bg-white px-4 text-base font-semibold leading-none text-black no-underline outline-none transition duration-200 active:translate-y-px dark:border-dark-100 hover:border-black active:bg-light-300 dark:bg-dark-400 hover:bg-light-200 dark:text-white focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-200 dark:hover:bg-dark-300"
|
||||
href="https://discordjs.guide"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Guide <FiExternalLink />
|
||||
</a>
|
||||
<a
|
||||
className="h-11 flex flex-row transform-gpu cursor-pointer select-none appearance-none appearance-none place-items-center gap-2 border border-light-900 rounded bg-white px-4 text-base font-semibold leading-none text-black no-underline outline-none transition duration-200 active:translate-y-px dark:border-dark-100 hover:border-black active:bg-light-300 dark:bg-dark-400 hover:bg-light-200 dark:text-white focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-200 dark:hover:bg-dark-300"
|
||||
href="https://github.com/discordjs/discord.js"
|
||||
rel="external noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
GitHub <FiExternalLink />
|
||||
</a>
|
||||
</div>
|
||||
<InstallButton />
|
||||
</div>
|
||||
</div>
|
||||
<div className="max-w-xs sm:max-w-6xl">
|
||||
{/* @ts-expect-error async component */}
|
||||
<SyntaxHighlighter code={CODE_EXAMPLE} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row place-content-center">
|
||||
<a
|
||||
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
|
||||
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"
|
||||
rel="noopener noreferrer"
|
||||
rel="external noopener noreferrer"
|
||||
target="_blank"
|
||||
title="Vercel"
|
||||
>
|
||||
<Image
|
||||
alt="Vercel"
|
||||
blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAABLCAQAAAA1k5H2AAAAi0lEQVR42u3SMQEAAAgDoC251a3gL2SgmfBYBRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCAgwWEOSWBnYbKggAAAABJRU5ErkJggg=="
|
||||
height={44}
|
||||
placeholder="blur"
|
||||
priority
|
||||
src={vercelLogo}
|
||||
width={212}
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -2,15 +2,12 @@
|
||||
|
||||
import { ThemeProvider } from 'next-themes';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { ServiceWorker } from '~/components/ServiceWorker';
|
||||
import { SystemThemeFallback } from '~/components/SystemThemeFallback';
|
||||
import { useSystemThemeFallback } from '~/hooks/useSystemThemeFallback';
|
||||
import { useUnregisterServiceWorker } from '~/hooks/useUnregisterServiceWorker';
|
||||
|
||||
export function Providers({ children }: PropsWithChildren) {
|
||||
return (
|
||||
<>
|
||||
<ThemeProvider attribute="class">{children}</ThemeProvider>
|
||||
<ServiceWorker />
|
||||
<SystemThemeFallback />
|
||||
</>
|
||||
);
|
||||
useUnregisterServiceWorker();
|
||||
useSystemThemeFallback();
|
||||
|
||||
return <ThemeProvider attribute="class">{children}</ThemeProvider>;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FiLink } from '@react-icons/all-files/fi/FiLink';
|
||||
|
||||
export function Anchor({ href }: { href: string }) {
|
||||
return (
|
||||
<a className="focus:ring-width-2 focus:ring-blurple mr-1 inline-block rounded outline-0 focus:ring" href={href}>
|
||||
<a className="mr-1 inline-block rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple" href={href}>
|
||||
<FiLink size={20} />
|
||||
</a>
|
||||
);
|
||||
|
||||
15
apps/website/src/components/Banner.tsx
Normal file
15
apps/website/src/components/Banner.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { HTMLAttributes } from 'react';
|
||||
|
||||
export function Banner({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
|
||||
return (
|
||||
<div className={`bg-blurple px-4 py-2 text-center text-sm text-white ${className}`} {...props}>
|
||||
You are reading the documentation for the <strong>next</strong> version of discord.js. Documentation for v13/v14+
|
||||
has been moved to{' '}
|
||||
<strong>
|
||||
<a href="https://old.discordjs.dev/#/docs" rel="external noopener noreferrer" target="_blank">
|
||||
old.discordjs.dev
|
||||
</a>
|
||||
</strong>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ export function CmdKDialog() {
|
||||
() =>
|
||||
searchResults?.map((item, idx) => (
|
||||
<Command.Item
|
||||
className="dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 [&[aria-selected]]:ring-blurple [&[aria-selected]]:ring-width-2 my-1 flex transform-gpu cursor-pointer select-none appearance-none flex-row place-content-center rounded bg-transparent px-4 py-2 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 active:translate-y-px active:bg-neutral-200 dark:text-white [&[aria-selected]]:ring"
|
||||
className="my-1 flex flex-row transform-gpu cursor-pointer select-none appearance-none place-content-center rounded bg-transparent px-4 py-2 text-base font-semibold leading-none text-black outline-none active:translate-y-px dark:border-dark-100 active:bg-neutral-200 hover:bg-neutral-100 dark:text-white [&[aria-selected]]:ring [&[aria-selected]]:ring-width-2 [&[aria-selected]]:ring-blurple dark:active:bg-dark-200 dark:hover:bg-dark-300"
|
||||
key={`${item.id}-${idx}`}
|
||||
onSelect={() => {
|
||||
router.push(item.path);
|
||||
@@ -60,10 +60,10 @@ export function CmdKDialog() {
|
||||
<div className="flex grow flex-row place-content-between place-items-center gap-4">
|
||||
<div className="flex flex-row place-items-center gap-4">
|
||||
{resolveIcon(item.kind)}
|
||||
<div className="w-50 sm:w-100 flex flex-col">
|
||||
<div className="w-50 flex flex-col sm:w-100">
|
||||
<h2 className="font-semibold">{item.name}</h2>
|
||||
<div className="line-clamp-1 text-sm font-normal">{item.summary}</div>
|
||||
<div className="line-clamp-1 hidden text-xs font-light opacity-75 dark:opacity-50 sm:block">
|
||||
<div className="line-clamp-1 hidden text-xs font-light opacity-75 sm:block dark:opacity-50">
|
||||
{item.path}
|
||||
</div>
|
||||
</div>
|
||||
@@ -114,12 +114,12 @@ export function CmdKDialog() {
|
||||
return (
|
||||
<Dialog className="fixed left-1/2 top-1/4 z-50 -translate-x-1/2" state={dialog!}>
|
||||
<Command
|
||||
className="dark:bg-dark/50 min-w-xs sm:min-w-lg dark:border-dark-100 border-light-900 max-w-xs rounded border bg-white/50 shadow backdrop-blur-md sm:max-w-lg"
|
||||
className="max-w-xs min-w-xs border border-light-900 rounded bg-white/50 shadow backdrop-blur-md sm:max-w-lg sm:min-w-lg dark:border-dark-100 dark:bg-dark/50"
|
||||
label="Command Menu"
|
||||
shouldFilter={false}
|
||||
>
|
||||
<Command.Input
|
||||
className="dark:bg-dark/50 caret-blurple placeholder:text-dark-300/75 dark:border-dark-100 border-light-900 rounded-b-0 w-full rounded border-0 border-b bg-white/50 p-4 text-lg outline-0 dark:placeholder:text-white/75"
|
||||
className="w-full border-0 border-b border-light-900 rounded rounded-b-0 bg-white/50 p-4 text-lg caret-blurple outline-none dark:border-dark-100 dark:bg-dark/50 placeholder:text-dark-300/75 dark:placeholder:text-white/75"
|
||||
onValueChange={setSearch}
|
||||
placeholder="Quick search..."
|
||||
value={search}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { ApiModel, Excerpt } from '@microsoft/api-extractor-model';
|
||||
import { ExcerptTokenKind } from '@microsoft/api-extractor-model';
|
||||
import { ItemLink } from './ItemLink';
|
||||
import { resolveItemURI } from './documentation/util';
|
||||
import { DISCORD_API_TYPES_DOCS_URL } from '~/util/constants';
|
||||
|
||||
export interface ExcerptTextProps {
|
||||
/**
|
||||
@@ -19,8 +21,24 @@ export interface ExcerptTextProps {
|
||||
export function ExcerptText({ model, excerpt }: ExcerptTextProps) {
|
||||
return (
|
||||
<>
|
||||
{excerpt.spannedTokens.map((token) => {
|
||||
{excerpt.spannedTokens.map((token, idx) => {
|
||||
if (token.kind === ExcerptTokenKind.Reference) {
|
||||
const source = token.canonicalReference?.source;
|
||||
|
||||
if (source && 'packageName' in source && source.packageName === 'discord-api-types') {
|
||||
const meaning = token.canonicalReference.symbol?.meaning;
|
||||
const href =
|
||||
meaning === 'type'
|
||||
? `${DISCORD_API_TYPES_DOCS_URL}#${token.text}`
|
||||
: `${DISCORD_API_TYPES_DOCS_URL}/${meaning}/${token.text}`;
|
||||
|
||||
return (
|
||||
<a className="text-blurple" href={href} key={idx} rel="external noreferrer noopener" target="_blank">
|
||||
{token.text}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
const item = model.resolveDeclarationReference(token.canonicalReference!, model).resolvedApiItem;
|
||||
|
||||
if (!item) {
|
||||
@@ -30,7 +48,7 @@ export function ExcerptText({ model, excerpt }: ExcerptTextProps) {
|
||||
return (
|
||||
<ItemLink
|
||||
className="text-blurple"
|
||||
itemURI={`${item.displayName}:${item.kind}`}
|
||||
itemURI={resolveItemURI(item)}
|
||||
key={`${item.displayName}-${item.containerKey}`}
|
||||
packageName={item.getAssociatedPackage()?.displayName.replace('@discordjs/', '')}
|
||||
>
|
||||
|
||||
@@ -3,21 +3,23 @@ import vercelLogo from '~/assets/powered-by-vercel.svg';
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="dark:bg-dark-800 bg-light-600 md:pl-12 md:pr-12">
|
||||
<div className="mx-auto flex max-w-6xl flex-col place-items-center gap-12 pt-12 lg:place-content-center">
|
||||
<div className="flex w-full flex-col place-content-between place-items-center gap-12 md:flex-row md:gap-0">
|
||||
<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="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
|
||||
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"
|
||||
rel="noopener noreferrer"
|
||||
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">
|
||||
@@ -25,17 +27,17 @@ export default function Footer() {
|
||||
<div className="text-lg font-semibold">Community</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<a
|
||||
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
|
||||
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
href="https://discord.gg/djs"
|
||||
rel="noopener noreferrer"
|
||||
rel="external noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Discord
|
||||
</a>
|
||||
<a
|
||||
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
|
||||
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
href="https://github.com/discordjs/discord.js/discussions"
|
||||
rel="noopener noreferrer"
|
||||
rel="external noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
GitHub discussions
|
||||
@@ -46,15 +48,15 @@ export default function Footer() {
|
||||
<div className="text-lg font-semibold">Project</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<a
|
||||
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
|
||||
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
href="https://github.com/discordjs/discord.js"
|
||||
rel="noopener noreferrer"
|
||||
rel="external noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
discord.js
|
||||
</a>
|
||||
<a
|
||||
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
|
||||
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
href="https://discordjs.guide"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
@@ -62,9 +64,9 @@ export default function Footer() {
|
||||
discord.js guide
|
||||
</a>
|
||||
<a
|
||||
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
|
||||
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
href="https://discord-api-types.dev"
|
||||
rel="noopener noreferrer"
|
||||
rel="external noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
discord-api-types
|
||||
|
||||
@@ -26,7 +26,7 @@ export default function Header() {
|
||||
.slice(1)
|
||||
.map((path, idx, original) => (
|
||||
<Link
|
||||
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 hover:underline focus:ring"
|
||||
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}`}
|
||||
>
|
||||
@@ -43,7 +43,7 @@ export default function Header() {
|
||||
return (
|
||||
<Fragment key={`${el.key}-${idx}`}>
|
||||
<div className="mx-2">/</div>
|
||||
{el}
|
||||
<div>{el}</div>
|
||||
<div className="mx-2">/</div>
|
||||
</Fragment>
|
||||
);
|
||||
@@ -52,49 +52,56 @@ export default function Header() {
|
||||
if (idx !== array.length - 1) {
|
||||
return (
|
||||
<Fragment key={`${el.key}-${idx}`}>
|
||||
{el}
|
||||
<div>{el}</div>
|
||||
<div className="mx-2">/</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
return <Fragment key={`${el.key}-${idx}`}>{el}</Fragment>;
|
||||
return <div key={`${el.key}-${idx}`}>{el}</div>;
|
||||
}),
|
||||
[pathElements],
|
||||
);
|
||||
|
||||
return (
|
||||
<header className="dark:bg-dark/50 dark:border-dark-100 border-light-900 sticky top-4 z-20 rounded-md border bg-white/50 shadow backdrop-blur-md">
|
||||
<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="flex h-full flex-row place-content-between place-items-center gap-8">
|
||||
<div className="h-full flex flex-row place-content-between place-items-center gap-8">
|
||||
<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 flex-row 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"
|
||||
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:flex-row lg:overflow-hidden">{breadcrumbs}</div>
|
||||
<div className="hidden lg:flex lg:grow lg:flex-row lg:overflow-hidden">{breadcrumbs}</div>
|
||||
<Button
|
||||
as="div"
|
||||
className="dark:bg-dark-800 focus:ring-width-2 focus:ring-blurple w-56 grow rounded bg-white px-4 py-2.5 outline-0 focus:ring sm:grow-0"
|
||||
className="hidden w-56 grow rounded bg-white px-4 py-2.5 outline-none md:block sm:grow-0 dark:bg-dark-800 focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
onClick={() => dialog?.toggle()}
|
||||
>
|
||||
<div className="flex flex-row place-items-center gap-4 md:justify-between">
|
||||
<VscSearch size={18} />
|
||||
<span className="opacity-65">Search...</span>
|
||||
<div className="md:opacity-65 hidden md:flex md:flex-row md:place-items-center md:gap-2">
|
||||
<div className="hidden md:flex md:flex-row md:place-items-center md:gap-2 md:opacity-65">
|
||||
<FiCommand size={18} /> K
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
<div className="flex flex-row place-items-center gap-4">
|
||||
<Button
|
||||
as="div"
|
||||
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 md:hidden active:translate-y-px focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
onClick={() => dialog?.toggle()}
|
||||
>
|
||||
<VscSearch size={24} />
|
||||
</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 flex-row 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"
|
||||
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="noopener noreferrer"
|
||||
rel="external noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<VscGithubInverted size={24} />
|
||||
|
||||
@@ -7,7 +7,7 @@ export function InheritanceText({ parent }: { parent: ApiDeclaredItem }) {
|
||||
<span className="font-semibold">
|
||||
Inherited from{' '}
|
||||
<ItemLink
|
||||
className="text-blurple focus:ring-width-2 focus:ring-blurple rounded font-mono outline-0 focus:ring"
|
||||
className="rounded font-mono text-blurple outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
itemURI={resolveItemURI(parent)}
|
||||
>
|
||||
{parent.displayName}
|
||||
|
||||
34
apps/website/src/components/InstallButton.tsx
Normal file
34
apps/website/src/components/InstallButton.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
'use client';
|
||||
|
||||
import { FiCheck } from '@react-icons/all-files/fi/FiCheck';
|
||||
import { FiCopy } from '@react-icons/all-files/fi/FiCopy';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
|
||||
export function InstallButton() {
|
||||
const [interacted, setInteracted] = useState(false);
|
||||
const [state, copyToClipboard] = useCopyToClipboard();
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setInteracted(false), 2_000);
|
||||
return () => clearTimeout(timer);
|
||||
}, [interacted]);
|
||||
|
||||
return (
|
||||
<button
|
||||
className="cursor-copy select-none bg-transparent px-4 py-2 text-sm text-dark-50 dark:text-light-900"
|
||||
onClick={() => {
|
||||
setInteracted(true);
|
||||
copyToClipboard('npm install discord.js');
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<span className="font-semibold text-blurple">{'>'}</span> npm install discord.js{' '}
|
||||
{state.value && interacted ? (
|
||||
<FiCheck className="ml-1 inline-block text-green-500" />
|
||||
) : (
|
||||
<FiCopy className="ml-1 inline-block" />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -3,13 +3,13 @@
|
||||
import type { LinkProps } from 'next/link';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import type { AnchorHTMLAttributes, PropsWithChildren, RefAttributes } from 'react';
|
||||
import { useCurrentPathMeta } from '~/hooks/useCurrentPathMeta';
|
||||
|
||||
export interface ItemLinkProps
|
||||
extends Omit<LinkProps, 'href'>,
|
||||
React.RefAttributes<HTMLAnchorElement>,
|
||||
Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> {
|
||||
RefAttributes<HTMLAnchorElement>,
|
||||
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> {
|
||||
className?: string;
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,7 @@ export function Nav({ members }: { members: SidebarSectionItemData[] }) {
|
||||
|
||||
return (
|
||||
<nav
|
||||
className={`dark:bg-dark/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 ${
|
||||
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`}
|
||||
>
|
||||
@@ -22,7 +22,7 @@ export function Nav({ members }: { members: SidebarSectionItemData[] }) {
|
||||
autoHide
|
||||
className="[&>div]:overscroll-none"
|
||||
hideTracksWhenNotNeeded
|
||||
renderThumbVertical={(props) => <div {...props} className="dark:bg-dark-100 bg-light-900 z-30 rounded" />}
|
||||
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" />
|
||||
)}
|
||||
|
||||
@@ -6,11 +6,11 @@ import { TableOfContentItems } from './TableOfContentItems';
|
||||
|
||||
export function Outline({ members }: { members: TableOfContentsSerialized[] }) {
|
||||
return (
|
||||
<aside className="dark:bg-dark-600 dark:border-dark-100 border-light-800 fixed bottom-0 right-0 top-[50px] z-20 hidden h-[calc(100vh_-_65px)] w-64 border-l bg-white pr-2 xl:block">
|
||||
<aside className="fixed bottom-0 right-0 top-[50px] z-20 hidden h-[calc(100vh_-_65px)] w-64 border-l border-light-800 bg-white pr-2 xl:block dark:border-dark-100 dark:bg-dark-600">
|
||||
<Scrollbars
|
||||
autoHide
|
||||
hideTracksWhenNotNeeded
|
||||
renderThumbVertical={(props) => <div {...props} className="dark:bg-dark-100 bg-light-900 z-30 rounded" />}
|
||||
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" />
|
||||
)}
|
||||
|
||||
@@ -19,7 +19,7 @@ export default function OverloadSwitcher({ overloads, children }: PropsWithChild
|
||||
() =>
|
||||
overloads.map((_, idx) => (
|
||||
<MenuItem
|
||||
className="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 my-0.5 cursor-pointer rounded bg-white p-3 text-sm outline-0 focus:ring"
|
||||
className="my-0.5 cursor-pointer rounded bg-white p-3 text-sm outline-none 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"
|
||||
key={idx}
|
||||
onClick={() => setOverloadIndex(idx + 1)}
|
||||
>
|
||||
@@ -32,7 +32,7 @@ export default function OverloadSwitcher({ overloads, children }: PropsWithChild
|
||||
return (
|
||||
<div className="flex flex-col place-items-start gap-2">
|
||||
<MenuButton
|
||||
className="bg-light-700 hover:bg-light-800 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 rounded p-3 outline-0 focus:ring"
|
||||
className="mb-2 rounded bg-white p-3 outline-none active:bg-light-900 dark:bg-dark-400 hover:bg-light-800 focus:ring focus:ring-width-2 focus:ring-blurple md:-ml-2 dark:active:bg-dark-200 dark:hover:bg-dark-300"
|
||||
state={menu}
|
||||
>
|
||||
<div className="flex flex-row place-content-between place-items-center gap-2">
|
||||
@@ -48,7 +48,7 @@ export default function OverloadSwitcher({ overloads, children }: PropsWithChild
|
||||
</div>
|
||||
</MenuButton>
|
||||
<Menu
|
||||
className="dark:bg-dark-600 border-light-800 dark:border-dark-100 focus:ring-width-2 focus:ring-blurple z-20 flex flex-col rounded border bg-white p-1 outline-0 focus:ring"
|
||||
className="z-20 flex flex-col border border-light-800 rounded bg-white p-1 outline-none dark:border-dark-100 dark:bg-dark-600 focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
state={menu}
|
||||
>
|
||||
{menuItems}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import { VscChevronDown } from '@react-icons/all-files/vsc/VscChevronDown';
|
||||
import { VscPackage } from '@react-icons/all-files/vsc/VscPackage';
|
||||
import { Menu, MenuButton, MenuItem, useMenuState } from 'ariakit/menu';
|
||||
@@ -16,7 +18,7 @@ export default function PackageSelect() {
|
||||
() => [
|
||||
<a href="https://old.discordjs.dev/#/docs/discord.js" key="discord.js">
|
||||
<MenuItem
|
||||
className="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 my-0.5 rounded bg-white p-3 text-sm outline-0 focus:ring"
|
||||
className="my-0.5 rounded bg-white p-3 text-sm outline-none 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"
|
||||
id="discord-js"
|
||||
onClick={() => packageMenu.setOpen(false)}
|
||||
state={packageMenu}
|
||||
@@ -27,7 +29,7 @@ export default function PackageSelect() {
|
||||
...PACKAGES.map((pkg, idx) => (
|
||||
<Link href={`/docs/packages/${pkg}/main`} key={`${pkg}-${idx}`}>
|
||||
<MenuItem
|
||||
className="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 my-0.5 rounded bg-white p-3 text-sm outline-0 focus:ring"
|
||||
className="my-0.5 rounded bg-white p-3 text-sm outline-none 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"
|
||||
id={pkg}
|
||||
onClick={() => packageMenu.setOpen(false)}
|
||||
state={packageMenu}
|
||||
@@ -43,7 +45,7 @@ export default function PackageSelect() {
|
||||
return (
|
||||
<>
|
||||
<MenuButton
|
||||
className="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-0 focus:ring"
|
||||
className="rounded bg-light-600 p-3 outline-none active:bg-light-800 dark:bg-dark-400 hover:bg-light-700 focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-400 dark:hover:bg-dark-300"
|
||||
state={packageMenu}
|
||||
>
|
||||
<div className="flex flex-row place-content-between place-items-center">
|
||||
@@ -58,7 +60,7 @@ export default function PackageSelect() {
|
||||
</div>
|
||||
</MenuButton>
|
||||
<Menu
|
||||
className="dark:bg-dark-600 border-light-800 dark:border-dark-100 focus:ring-width-2 focus:ring-blurple z-20 flex flex-col rounded border bg-white p-1 outline-0 focus:ring"
|
||||
className="z-20 flex flex-col border border-light-800 rounded bg-white p-1 outline-none dark:border-dark-100 dark:bg-dark-600 focus:ring focus:ring-width-2 focus:ring-blurple"
|
||||
state={packageMenu}
|
||||
>
|
||||
{packageMenuItems}
|
||||
|
||||
@@ -4,7 +4,7 @@ export function Panel({ children }: PropsWithChildren) {
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
<div className="border-light-900 dark:border-dark-100 border-t-2" />
|
||||
<div className="border-t-2 border-light-900 dark:border-dark-100" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import type { ApiDeclaredItem, ApiItemContainerMixin, ApiPropertyItem } from '@microsoft/api-extractor-model';
|
||||
import type {
|
||||
ApiDeclaredItem,
|
||||
ApiItemContainerMixin,
|
||||
ApiProperty,
|
||||
ApiPropertySignature,
|
||||
} from '@microsoft/api-extractor-model';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { Anchor } from './Anchor';
|
||||
import { ExcerptText } from './ExcerptText';
|
||||
@@ -17,29 +22,34 @@ export function Property({
|
||||
inheritedFrom,
|
||||
}: PropsWithChildren<{
|
||||
inheritedFrom?: (ApiDeclaredItem & ApiItemContainerMixin) | undefined;
|
||||
item: ApiPropertyItem;
|
||||
item: ApiProperty | ApiPropertySignature;
|
||||
separator?: PropertySeparatorType;
|
||||
}>) {
|
||||
const isDeprecated = Boolean(item.tsdocComment?.deprecatedBlock);
|
||||
const hasSummary = Boolean(item.tsdocComment?.summarySection);
|
||||
|
||||
return (
|
||||
<div className="scroll-mt-30 flex flex-col gap-4" id={item.displayName}>
|
||||
<div className="flex flex-col scroll-mt-30 gap-4" id={item.displayName}>
|
||||
<div className="flex flex-col gap-2 md:-ml-9">
|
||||
{isDeprecated || item.isReadonly || item.isOptional ? (
|
||||
{isDeprecated || item.isReadonly || item.isOptional || (item as ApiProperty).isStatic ? (
|
||||
<div className="flex flex-row gap-1 md:ml-7">
|
||||
{isDeprecated ? (
|
||||
<div className="flex h-5 flex-row place-content-center place-items-center rounded-full bg-red-500 px-3 text-center text-xs font-semibold uppercase text-white">
|
||||
<div className="h-5 flex flex-row place-content-center place-items-center rounded-full bg-red-500 px-3 text-center text-xs font-semibold uppercase text-white">
|
||||
Deprecated
|
||||
</div>
|
||||
) : null}
|
||||
{(item as ApiProperty).isStatic ? (
|
||||
<div className="h-5 flex flex-row place-content-center place-items-center rounded-full bg-blurple px-3 text-center text-xs font-semibold uppercase text-white">
|
||||
Static
|
||||
</div>
|
||||
) : null}
|
||||
{item.isReadonly ? (
|
||||
<div className="bg-blurple flex h-5 flex-row place-content-center place-items-center rounded-full px-3 text-center text-xs font-semibold uppercase text-white">
|
||||
<div className="h-5 flex flex-row place-content-center place-items-center rounded-full bg-blurple px-3 text-center text-xs font-semibold uppercase text-white">
|
||||
Readonly
|
||||
</div>
|
||||
) : null}
|
||||
{item.isOptional ? (
|
||||
<div className="bg-blurple flex h-5 flex-row place-content-center place-items-center rounded-full px-3 text-center text-xs font-semibold uppercase text-white">
|
||||
<div className="h-5 flex flex-row place-content-center place-items-center rounded-full bg-blurple px-3 text-center text-xs font-semibold uppercase text-white">
|
||||
Optional
|
||||
</div>
|
||||
) : null}
|
||||
@@ -51,10 +61,14 @@ export function Property({
|
||||
{item.displayName}
|
||||
{item.isOptional ? '?' : ''}
|
||||
</h4>
|
||||
<h4 className="font-mono text-lg font-bold">{separator}</h4>
|
||||
<h4 className="break-all font-mono text-lg font-bold">
|
||||
<ExcerptText excerpt={item.propertyTypeExcerpt} model={item.getAssociatedModel()!} />
|
||||
</h4>
|
||||
{item.propertyTypeExcerpt.text ? (
|
||||
<>
|
||||
<h4 className="font-mono text-lg font-bold">{separator}</h4>
|
||||
<h4 className="break-all font-mono text-lg font-bold">
|
||||
<ExcerptText excerpt={item.propertyTypeExcerpt} model={item.getAssociatedModel()!} />
|
||||
</h4>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
{hasSummary || inheritedFrom ? (
|
||||
|
||||
@@ -3,7 +3,6 @@ import type {
|
||||
ApiItem,
|
||||
ApiItemContainerMixin,
|
||||
ApiProperty,
|
||||
ApiPropertyItem,
|
||||
ApiPropertySignature,
|
||||
} from '@microsoft/api-extractor-model';
|
||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
||||
@@ -25,10 +24,10 @@ export function PropertyList({ item }: { item: ApiItemContainerMixin }) {
|
||||
<Fragment key={`${prop.item.displayName}-${idx}`}>
|
||||
<Property
|
||||
inheritedFrom={prop.inherited as ApiDeclaredItem & ApiItemContainerMixin}
|
||||
item={prop.item as ApiPropertyItem}
|
||||
item={prop.item as ApiProperty}
|
||||
separator={PropertySeparatorType.Type}
|
||||
/>
|
||||
<div className="border-light-900 dark:border-dark-100 border-t-2" />
|
||||
<div className="border-t-2 border-light-900 dark:border-dark-100" />
|
||||
</Fragment>
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -2,15 +2,7 @@
|
||||
|
||||
import { Section as DJSSection, type SectionOptions } from '@discordjs/ui';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { useMedia } from 'react-use';
|
||||
|
||||
// This is wrapper around the Section component from @discordjs/ui,
|
||||
// it simply automatically sets the dense prop to true if the screen
|
||||
// width is less than 768px. This is done to separate client-side logic
|
||||
// from server-side rendering.
|
||||
export function Section(options: PropsWithChildren<SectionOptions>) {
|
||||
const matches = useMedia('(max-width: 768px)', true);
|
||||
const modifiedOptions = { ...options, dense: matches };
|
||||
|
||||
return <DJSSection {...modifiedOptions} />;
|
||||
return <DJSSection {...options} />;
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { useUnregisterServiceWorker } from '~/hooks/useUnregisterServiceWorker';
|
||||
|
||||
export function ServiceWorker() {
|
||||
useUnregisterServiceWorker();
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import { VscSymbolField } from '@react-icons/all-files/vsc/VscSymbolField';
|
||||
import { VscSymbolInterface } from '@react-icons/all-files/vsc/VscSymbolInterface';
|
||||
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
||||
import { VscSymbolVariable } from '@react-icons/all-files/vsc/VscSymbolVariable';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useSelectedLayoutSegment } from 'next/navigation';
|
||||
import { useMemo } from 'react';
|
||||
import { ItemLink } from './ItemLink';
|
||||
import { Section } from './Section';
|
||||
@@ -83,7 +83,7 @@ function resolveIcon(item: string) {
|
||||
}
|
||||
|
||||
export function Sidebar({ members }: { members: SidebarSectionItemData[] }) {
|
||||
const pathname = usePathname();
|
||||
const segment = useSelectedLayoutSegment();
|
||||
const { setOpened } = useNav();
|
||||
|
||||
const groupItems = useMemo(() => groupMembers(members), [members]);
|
||||
@@ -93,11 +93,16 @@ export function Sidebar({ members }: { members: SidebarSectionItemData[] }) {
|
||||
{(Object.keys(groupItems) as (keyof GroupedMembers)[])
|
||||
.filter((group) => groupItems[group].length)
|
||||
.map((group, idx) => (
|
||||
<Section icon={resolveIcon(group)} key={`${group}-${idx}`} title={group}>
|
||||
<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"
|
||||
icon={resolveIcon(group)}
|
||||
key={`${group}-${idx}`}
|
||||
title={group}
|
||||
>
|
||||
{groupItems[group].map((member, index) => (
|
||||
<ItemLink
|
||||
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 ${
|
||||
pathname === member.href
|
||||
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(segment ?? '') === member.href
|
||||
? 'bg-blurple text-white'
|
||||
: 'dark:hover:bg-dark-200 dark:active:bg-dark-100 hover:bg-light-700 active:bg-light-800'
|
||||
}`}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user