refactor(website,guide): cloudflare workers support (#11204)
2
apps/guide/.gitignore
vendored
@@ -16,7 +16,9 @@ pids
|
||||
.env*.local
|
||||
|
||||
# Dist
|
||||
.open-next
|
||||
.next
|
||||
.wrangler
|
||||
.source
|
||||
|
||||
# Miscellaneous
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
import { GithubInfo } from 'fumadocs-ui/components/github-info';
|
||||
import { GithubInfo } from '@/components/GitHubInfo';
|
||||
|
||||
<GithubInfo owner="discordjs" repo="discord.js" />
|
||||
|
||||
|
||||
@@ -23,14 +23,6 @@ export default withMDX({
|
||||
fullUrl: true,
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
ppr: true,
|
||||
useCache: true,
|
||||
dynamicOnHover: true,
|
||||
},
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
reactCompiler: true,
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
|
||||
3
apps/guide/open-next.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { defineCloudflareConfig } from '@opennextjs/cloudflare';
|
||||
|
||||
export default defineCloudflareConfig();
|
||||
@@ -5,11 +5,15 @@
|
||||
"description": "Imagine a bot... the most popular way to build discord bots",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts",
|
||||
"build:check": "tsc --noEmit",
|
||||
"build:local": "cross-env NEXT_PUBLIC_LOCAL_DEV=true pnpm run build:prod",
|
||||
"build:prod": "pnpm run build:next",
|
||||
"build:next": "next build",
|
||||
"build": "next build --webpack",
|
||||
"preview": "next start",
|
||||
"preview:cf": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
|
||||
"deploy:cf": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
|
||||
"dev": "next dev -p 3001 --turbopack",
|
||||
"lint": "pnpm run build:check && prettier --check . && cross-env TIMING=1 eslint --format=pretty src ",
|
||||
"format": "pnpm run build:check && prettier --write . && cross-env TIMING=1 eslint --fix --format=pretty src ",
|
||||
@@ -44,30 +48,32 @@
|
||||
"homepage": "https://discord.js.org",
|
||||
"funding": "https://github.com/discordjs/discord.js?sponsor",
|
||||
"dependencies": {
|
||||
"@opennextjs/cloudflare": "^1.11.0",
|
||||
"@react-icons/all-files": "^4.1.0",
|
||||
"@vercel/analytics": "^1.5.0",
|
||||
"cmdk": "^1.1.1",
|
||||
"cva": "1.0.0-beta.3",
|
||||
"fumadocs-core": "^15.8.4",
|
||||
"fumadocs-mdx": "^12.0.3",
|
||||
"fumadocs-twoslash": "^3.1.8",
|
||||
"fumadocs-ui": "^15.8.4",
|
||||
"fumadocs-core": "^16.0.2",
|
||||
"fumadocs-mdx": "^13.0.0",
|
||||
"fumadocs-twoslash": "^3.1.9",
|
||||
"fumadocs-ui": "^16.0.2",
|
||||
"geist": "^1.5.1",
|
||||
"immer": "^10.1.3",
|
||||
"jotai": "^2.15.0",
|
||||
"jotai-immer": "^0.4.1",
|
||||
"lucide-react": "^0.545.0",
|
||||
"lucide-react": "^0.548.0",
|
||||
"mermaid": "^11.12.0",
|
||||
"motion": "^12.23.22",
|
||||
"next": "15.6.0-canary.45",
|
||||
"next-mdx-remote-client": "^2.1.6",
|
||||
"motion": "^12.23.24",
|
||||
"next": "^16.0.0",
|
||||
"next-mdx-remote-client": "^2.1.7",
|
||||
"next-themes": "^0.4.6",
|
||||
"nuqs": "^2.7.1",
|
||||
"nuqs": "^2.7.2",
|
||||
"react": "^19.2.0",
|
||||
"react-aria": "^3.44.0",
|
||||
"react-aria-components": "^1.13.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-error-boundary": "^6.0.0",
|
||||
"safe-mdx": "^1.3.8",
|
||||
"sharp": "^0.34.4",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
@@ -75,15 +81,15 @@
|
||||
"usehooks-ts": "^3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/env": "^15.5.4",
|
||||
"@next/env": "^16.0.0",
|
||||
"@shikijs/rehype": "^3.13.0",
|
||||
"@tailwindcss/postcss": "^4.1.14",
|
||||
"@tailwindcss/postcss": "^4.1.16",
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"@tailwindcss/vite": "^4.1.14",
|
||||
"@tailwindcss/vite": "^4.1.16",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "^22.18.8",
|
||||
"@types/react": "^19.2.0",
|
||||
"@types/react-dom": "^19.2.0",
|
||||
"@types/node": "^24.9.1",
|
||||
"@types/react": "^19.2.2",
|
||||
"@types/react-dom": "^19.2.2",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
||||
"cpy-cli": "^6.0.0",
|
||||
@@ -94,15 +100,16 @@
|
||||
"git-describe": "^4.1.1",
|
||||
"postcss": "^8.5.6",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-tailwindcss": "^0.6.14",
|
||||
"prettier-plugin-tailwindcss": "^0.7.1",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"remark-rehype": "^11.1.2",
|
||||
"shiki": "^3.13.0",
|
||||
"tailwindcss": "^4.1.14",
|
||||
"tailwindcss": "^4.1.16",
|
||||
"tailwindcss-react-aria-components": "^2.0.1",
|
||||
"turbo": "^2.5.8",
|
||||
"typescript": "^5.9.3",
|
||||
"vercel": "^48.2.1"
|
||||
"vercel": "^48.2.1",
|
||||
"wrangler": "^4.45.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
|
||||
2
apps/guide/public/_headers
Normal file
@@ -0,0 +1,2 @@
|
||||
/_next/static/*
|
||||
Cache-Control: public,max-age=31536000,immutable
|
||||
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 8.9 KiB |
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square70x70logo src="/mstile-70x70.png"/>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<square310x310logo src="/mstile-310x310.png"/>
|
||||
<wide310x150logo src="/mstile-310x150.png"/>
|
||||
<TileColor>#090a16</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
|
Before Width: | Height: | Size: 561 B |
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
apps/guide/public/favicon-96x96.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
3
apps/guide/public/favicon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="180" height="180" viewBox="0 0 180 180"><image width="180" height="180" xlink:href="data:image/png;base64,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"></image><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
|
||||
@media (prefers-color-scheme: dark) { :root { filter: none; } }
|
||||
</style></svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="400.000000pt" height="400.000000pt" viewBox="0 0 400.000000 400.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,400.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M0 2000 l0 -2000 2000 0 2000 0 0 2000 0 2000 -2000 0 -2000 0 0
|
||||
-2000z m1305 795 c219 -47 373 -197 421 -411 24 -109 16 -315 -16 -399 l-23
|
||||
-61 -59 -11 c-110 -21 -182 -92 -203 -202 -11 -56 -11 -56 -68 -79 -76 -30
|
||||
-201 -42 -464 -42 l-223 0 0 610 0 610 283 0 c210 0 300 -4 352 -15z m890
|
||||
-585 c0 -543 -2 -601 -18 -659 -56 -198 -190 -334 -365 -370 -176 -37 -349 5
|
||||
-471 115 -48 44 -111 134 -111 161 0 6 19 14 43 18 23 4 73 18 110 32 l68 24
|
||||
50 -45 c56 -50 98 -66 175 -66 100 0 207 81 234 178 6 23 10 251 10 625 l0
|
||||
588 138 -3 137 -3 0 -595z m930 570 c93 -29 197 -84 252 -134 l44 -41 -61 -75
|
||||
c-34 -41 -67 -81 -74 -88 -10 -10 -25 -4 -78 32 -95 63 -154 81 -268 81 -79 0
|
||||
-103 -4 -142 -23 -62 -31 -90 -71 -96 -137 -8 -94 28 -137 168 -202 157 -73
|
||||
172 -80 240 -108 236 -97 341 -215 356 -400 16 -193 -82 -363 -258 -449 -91
|
||||
-45 -187 -66 -303 -66 -191 0 -390 74 -524 195 l-40 37 80 93 80 94 73 -53
|
||||
c168 -121 353 -155 491 -92 72 33 108 82 113 155 9 122 -37 162 -323 286 -258
|
||||
111 -350 179 -407 300 -69 148 -37 343 75 463 61 65 195 133 300 152 79 14
|
||||
222 4 302 -20z m-1367 -977 c45 -34 65 -69 70 -125 4 -61 -19 -106 -77 -145
|
||||
-90 -60 -226 3 -238 111 -3 24 -3 56 1 70 8 34 54 86 91 102 40 19 120 12 153
|
||||
-13z"/>
|
||||
<path d="M967 2543 c-4 -3 -7 -159 -7 -346 l0 -339 128 4 c101 3 136 8 172 24
|
||||
106 48 162 145 168 292 10 214 -69 334 -238 361 -73 12 -213 15 -223 4z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -3,14 +3,16 @@
|
||||
"short_name": "discord.js",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"src": "/web-app-manifest-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png"
|
||||
"src": "/web-app-manifest-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
],
|
||||
"theme_color": "#1a1b1e",
|
||||
|
||||
BIN
apps/guide/public/web-app-manifest-192x192.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
apps/guide/public/web-app-manifest-512x512.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
@@ -1,6 +1,6 @@
|
||||
import { Analytics } from '@vercel/analytics/react';
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||
import { RootProvider } from 'fumadocs-ui/provider';
|
||||
import { RootProvider } from 'fumadocs-ui/provider/next';
|
||||
import { GeistMono } from 'geist/font/mono';
|
||||
import { GeistSans } from 'geist/font/sans';
|
||||
import type { Metadata, Viewport } from 'next';
|
||||
@@ -29,33 +29,16 @@ export const metadata: Metadata = {
|
||||
icons: {
|
||||
other: [
|
||||
{
|
||||
url: '/favicon-32x32.png',
|
||||
sizes: '32x32',
|
||||
type: 'image/png',
|
||||
},
|
||||
{
|
||||
url: '/favicon-16x16.png',
|
||||
sizes: '16x16',
|
||||
url: '/favicon-96x96.png',
|
||||
sizes: '96x96',
|
||||
type: 'image/png',
|
||||
},
|
||||
],
|
||||
apple: [
|
||||
'/apple-touch-icon.png',
|
||||
{
|
||||
url: '/safari-pinned-tab.svg',
|
||||
rel: 'mask-icon',
|
||||
},
|
||||
],
|
||||
apple: ['/apple-touch-icon.png'],
|
||||
},
|
||||
|
||||
manifest: '/site.webmanifest',
|
||||
|
||||
appleWebApp: {
|
||||
title: 'discord.js',
|
||||
},
|
||||
|
||||
applicationName: 'discord.js',
|
||||
|
||||
openGraph: {
|
||||
siteName: 'discord.js',
|
||||
type: 'website',
|
||||
@@ -67,10 +50,6 @@ export const metadata: Metadata = {
|
||||
card: 'summary_large_image',
|
||||
creator: '@iCrawlToGo',
|
||||
},
|
||||
|
||||
other: {
|
||||
'msapplication-TileColor': '#1a1a1e',
|
||||
},
|
||||
};
|
||||
|
||||
export default async function RootLayout({ children }: PropsWithChildren) {
|
||||
|
||||
@@ -9,12 +9,25 @@ export function generateStaticParams() {
|
||||
}));
|
||||
}
|
||||
|
||||
async function loadGoogleFont(font: string, text: string) {
|
||||
const url = `https://fonts.googleapis.com/css2?family=${font}&text=${encodeURIComponent(text)}`;
|
||||
const css = await (await fetch(url)).text();
|
||||
// eslint-disable-next-line prefer-named-capture-group
|
||||
const resource = /src: url\((.+)\) format\('(opentype|truetype)'\)/.exec(css);
|
||||
|
||||
if (resource) {
|
||||
const response = await fetch(resource[1]!);
|
||||
if (response.status === 200) {
|
||||
return response.arrayBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('failed to load font data');
|
||||
}
|
||||
|
||||
export async function GET(_req: Request, { params }: { params: Promise<{ slug: string[] }> }) {
|
||||
const { slug } = await params;
|
||||
const page = source.getPage(slug.slice(0, -1));
|
||||
// const fontData = await fetch(new URL('../../assets/Geist-Regular.ttf', import.meta.url), {
|
||||
// next: { revalidate: 604_800 },
|
||||
// }).then(async (res) => res.arrayBuffer());
|
||||
|
||||
if (!page) {
|
||||
notFound();
|
||||
@@ -24,13 +37,13 @@ export async function GET(_req: Request, { params }: { params: Promise<{ slug: s
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
site: 'discord.js Guide',
|
||||
// fonts: [
|
||||
// {
|
||||
// name: 'Geist',
|
||||
// data: fontData,
|
||||
// weight: 900,
|
||||
// style: 'normal',
|
||||
// },
|
||||
// ],
|
||||
fonts: [
|
||||
{
|
||||
name: 'Geist',
|
||||
data: await loadGoogleFont('Geist:wght@400', page.data.title),
|
||||
weight: 400,
|
||||
style: 'normal',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
109
apps/guide/src/components/GitHubInfo.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
// https://github.com/fuma-nama/fumadocs/blob/dev/packages/ui/src/components/github-info.tsx
|
||||
// https://github.com/fuma-nama/fumadocs/blob/dev/LICENSE
|
||||
|
||||
import { Star } from 'lucide-react';
|
||||
import { type AnchorHTMLAttributes } from 'react';
|
||||
import { twMerge as cn } from 'tailwind-merge';
|
||||
|
||||
async function getRepoStarsAndForks(
|
||||
owner: string,
|
||||
repo: string,
|
||||
token?: string,
|
||||
): Promise<{
|
||||
forks: number;
|
||||
stars: number;
|
||||
}> {
|
||||
const endpoint = `https://api.github.com/repos/${owner}/${repo}`;
|
||||
const headers = new Headers({
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'discordjs-guide',
|
||||
});
|
||||
|
||||
if (token) headers.set('Authorization', `Bearer ${token}`);
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
headers,
|
||||
next: {
|
||||
revalidate: 60,
|
||||
},
|
||||
} as RequestInit);
|
||||
|
||||
if (!response.ok) {
|
||||
const message = await response.text();
|
||||
|
||||
throw new Error(`Failed to fetch repository data: ${message}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return {
|
||||
stars: data.stargazers_count,
|
||||
forks: data.forks_count,
|
||||
};
|
||||
}
|
||||
|
||||
export async function GithubInfo({
|
||||
repo,
|
||||
owner,
|
||||
token,
|
||||
...props
|
||||
}: AnchorHTMLAttributes<HTMLAnchorElement> & {
|
||||
readonly owner: string;
|
||||
readonly repo: string;
|
||||
readonly token?: string;
|
||||
}) {
|
||||
const { stars } = await getRepoStarsAndForks(owner, repo, token);
|
||||
const humanizedStars = humanizeNumber(stars);
|
||||
|
||||
return (
|
||||
<a
|
||||
href={`https://github.com/${owner}/${repo}`}
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
{...props}
|
||||
className={cn(
|
||||
'text-fd-foreground/80 hover:text-fd-accent-foreground hover:bg-fd-accent flex flex-col gap-1.5 rounded-lg p-2 text-sm transition-colors lg:flex-row lg:items-center',
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
<p className="flex items-center gap-2 truncate">
|
||||
<svg className="size-3.5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<title>GitHub</title>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||
</svg>
|
||||
{owner}/{repo}
|
||||
</p>
|
||||
<p className="text-fd-muted-foreground flex items-center gap-1 text-xs">
|
||||
<Star className="size-3" />
|
||||
{humanizedStars}
|
||||
</p>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a number to a human-readable string with K suffix for thousands
|
||||
*
|
||||
* @example 1500 -> "1.5K", 1000000 -> "1000000"
|
||||
*/
|
||||
function humanizeNumber(num: number): string {
|
||||
if (num < 1_000) {
|
||||
return num.toString();
|
||||
}
|
||||
|
||||
if (num < 100_000) {
|
||||
// For numbers between 1,000 and 99,999, show with one decimal (e.g., 1.5K)
|
||||
const value = (num / 1_000).toFixed(1);
|
||||
// Remove trailing .0 if present
|
||||
const formattedValue = value.endsWith('.0') ? value.slice(0, -2) : value;
|
||||
|
||||
return `${formattedValue}K`;
|
||||
}
|
||||
|
||||
if (num < 1_000_000) {
|
||||
// For numbers between 10,000 and 999,999, show as whole K (e.g., 10K, 999K)
|
||||
return `${Math.floor(num / 1_000)}K`;
|
||||
}
|
||||
|
||||
// For 1,000,000 and above, just return the number
|
||||
return num.toString();
|
||||
}
|
||||
19
apps/guide/wrangler.jsonc
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "node_modules/wrangler/config-schema.json",
|
||||
"main": ".open-next/worker.js",
|
||||
"name": "discordjs-guide",
|
||||
"keep_names": false,
|
||||
"compatibility_date": "2025-10-04",
|
||||
"compatibility_flags": ["nodejs_compat"],
|
||||
"assets": {
|
||||
"directory": ".open-next/assets",
|
||||
"binding": "ASSETS",
|
||||
},
|
||||
"observability": {
|
||||
"logs": {
|
||||
"enabled": true,
|
||||
"head_sampling_rate": 1,
|
||||
"invocation_logs": true,
|
||||
},
|
||||
},
|
||||
}
|
||||