├── .prettierrc
├── public
├── favicon.ico
├── fonts
│ └── inter
│ │ ├── Inter-Black.woff
│ │ ├── Inter-Black.woff2
│ │ ├── Inter-Bold.woff
│ │ ├── Inter-Bold.woff2
│ │ ├── Inter-Italic.woff
│ │ ├── Inter-Light.woff
│ │ ├── Inter-Light.woff2
│ │ ├── Inter-Medium.woff
│ │ ├── Inter-Thin.woff
│ │ ├── Inter-Thin.woff2
│ │ ├── Inter.var.woff2
│ │ ├── Inter-Italic.woff2
│ │ ├── Inter-Medium.woff2
│ │ ├── Inter-Regular.woff
│ │ ├── Inter-Regular.woff2
│ │ ├── Inter-SemiBold.woff
│ │ ├── Inter-BlackItalic.woff
│ │ ├── Inter-BoldItalic.woff
│ │ ├── Inter-BoldItalic.woff2
│ │ ├── Inter-ExtraBold.woff
│ │ ├── Inter-ExtraBold.woff2
│ │ ├── Inter-ExtraLight.woff
│ │ ├── Inter-ExtraLight.woff2
│ │ ├── Inter-LightItalic.woff
│ │ ├── Inter-SemiBold.woff2
│ │ ├── Inter-ThinItalic.woff
│ │ ├── Inter-ThinItalic.woff2
│ │ ├── Inter-italic.var.woff2
│ │ ├── Inter-roman.var.woff2
│ │ ├── Inter-BlackItalic.woff2
│ │ ├── Inter-LightItalic.woff2
│ │ ├── Inter-MediumItalic.woff
│ │ ├── Inter-MediumItalic.woff2
│ │ ├── Inter-ExtraBoldItalic.woff
│ │ ├── Inter-ExtraBoldItalic.woff2
│ │ ├── Inter-ExtraLightItalic.woff
│ │ ├── Inter-SemiBoldItalic.woff
│ │ ├── Inter-SemiBoldItalic.woff2
│ │ ├── Inter-ExtraLightItalic.woff2
│ │ └── inter.css
├── badge.svg
├── styles
│ └── hljs
│ │ ├── atom-one-dark.min.css
│ │ └── atom-one-light.min.css
├── logo.svg
└── favicon.svg
├── postcss.config.js
├── worker
├── yarn.lock
├── .gitignore
├── package.json
├── wrangler.toml
└── index.js
├── next.config.js
├── next-env.d.ts
├── deploy
├── README.md
└── main.ts
├── vercel.json
├── .gitignore
├── components
├── TypeAlias.tsx
├── Namespace.tsx
├── app.css
├── Enum.tsx
├── Variable.tsx
├── Sidebar.tsx
├── JSDoc.tsx
├── Documentation.tsx
├── Function.tsx
├── Transition.tsx
├── Interface.tsx
├── Footer.tsx
├── Loading.tsx
├── Header.tsx
├── Class.tsx
├── TsType.tsx
├── Wrapper.tsx
└── SinglePage.tsx
├── tsconfig.json
├── pages
├── 404.tsx
├── _app.tsx
├── builtin
│ └── [version].tsx
├── https
│ └── [...url].tsx
├── _document.tsx
├── index.tsx
└── about.tsx
├── README.md
├── .github
└── workflows
│ └── ci.yml
├── LICENSE
├── package.json
├── tailwind.config.js
├── api
└── docs.ts
└── util
├── data.ts
└── docs.ts
/.prettierrc:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/favicon.ico
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: ["tailwindcss", "autoprefixer"],
3 | };
4 |
--------------------------------------------------------------------------------
/worker/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 |
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Black.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Black.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Black.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Black.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Bold.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Bold.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Italic.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Light.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Light.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Medium.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Medium.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Thin.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Thin.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Thin.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Thin.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter.var.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter.var.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Italic.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Medium.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Regular.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-Regular.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-SemiBold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-SemiBold.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-BlackItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-BlackItalic.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-BoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-BoldItalic.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-BoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-ExtraBold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-ExtraBold.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-ExtraBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-ExtraBold.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-ExtraLight.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-ExtraLight.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-ExtraLight.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-ExtraLight.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-LightItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-LightItalic.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-SemiBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-SemiBold.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-ThinItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-ThinItalic.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-ThinItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-ThinItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-italic.var.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-italic.var.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-roman.var.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-roman.var.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-BlackItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-BlackItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-LightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-LightItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-MediumItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-MediumItalic.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-MediumItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-MediumItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-ExtraBoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-ExtraBoldItalic.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-ExtraBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-ExtraBoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-ExtraLightItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-ExtraLightItalic.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-SemiBoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-SemiBoldItalic.woff
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-SemiBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-SemiBoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/inter/Inter-ExtraLightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/denoland/doc_website/main/public/fonts/inter/Inter-ExtraLightItalic.woff2
--------------------------------------------------------------------------------
/worker/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /dist
3 | **/*.rs.bk
4 | Cargo.lock
5 | bin/
6 | pkg/
7 | wasm-pack.log
8 | worker/
9 | node_modules/
10 | .cargo-ok
11 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | const withPreact = require("next-plugin-preact");
2 |
3 | module.exports = withPreact({
4 | experimental: {
5 | modern: true,
6 | polyfillsOptimization: true,
7 | },
8 | });
9 |
--------------------------------------------------------------------------------
/worker/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "worker",
4 | "version": "1.0.0",
5 | "description": "Cloudflare Worker for doc.deno.land",
6 | "main": "index.js",
7 | "license": "MIT"
8 | }
9 |
--------------------------------------------------------------------------------
/worker/wrangler.toml:
--------------------------------------------------------------------------------
1 | name = "deno_doc_cache"
2 | type = "javascript"
3 | account_id = "895762025d37fc687ecd72d7cc80204a"
4 | workers_dev = false
5 | route = "https://doc.deno.land/api/docs*"
6 | zone_id = "c192cf8ac042c681023493c52edd44c8"
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
5 | // NOTE: This file should not be edited
6 | // see https://nextjs.org/docs/basic-features/typescript for more information.
7 |
--------------------------------------------------------------------------------
/deploy/README.md:
--------------------------------------------------------------------------------
1 | # Proxy of lib.deno.d.ts as Deno Deploy script
2 |
3 | Deno publishes `lib.deno.d.ts` for each release in the url
4 | `https://github.com/denoland/deno/releases/download/${version}/lib.deno.d.ts`,
5 | but it doesn't return correct content-type header. This Deno Deploy script
6 | proxies that file with corrected content-type headers.
7 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "functions": {
3 | "api/**/*.ts": {
4 | "runtime": "vercel-deno@0.8.0",
5 | "maxDuration": 60
6 | }
7 | },
8 | "regions": ["sfo"],
9 | "build": {
10 | "env": {
11 | "DENO_VERSION": "1.12.2",
12 | "DENO_UNSTABLE": "true"
13 | }
14 | },
15 | "env": {
16 | "DENO_VERSION": "1.12.2",
17 | "DENO_UNSTABLE": "true"
18 | },
19 | "github": {
20 | "silent": true
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 |
21 | # debug
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
26 | # local env files
27 | .env.local
28 | .env.development.local
29 | .env.test.local
30 | .env.production.local
31 |
32 | .now
33 | .vercel
34 |
--------------------------------------------------------------------------------
/components/TypeAlias.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import { DocNodeTypeAlias } from "../util/docs";
5 | import { SimpleCard } from "./SinglePage";
6 |
7 | export function TypeAliasCard({
8 | node,
9 | nested,
10 | }: {
11 | node: DocNodeTypeAlias;
12 | nested: boolean;
13 | }) {
14 | return (
15 |
21 | );
22 | }
23 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true
17 | },
18 | "exclude": ["node_modules", "api", "deploy"],
19 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
20 | }
21 |
--------------------------------------------------------------------------------
/pages/404.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import Link from "next/link";
5 |
6 | function NotFound() {
7 | return (
8 | <>
9 |
10 | 404 not found - deno doc
11 |
12 |
18 | >
19 | );
20 | }
21 |
22 | export default NotFound;
23 |
--------------------------------------------------------------------------------
/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import App from "next/app";
5 | import "../components/app.css";
6 | import Head from "next/head";
7 |
8 | export default class DenoDocApp extends App {
9 | render() {
10 | const { Component, pageProps } = this.props;
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | );
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/pages/builtin/[version].tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import { useRouter } from "next/router";
4 | import { Documentation } from "../../components/Documentation";
5 |
6 | const Page = () => {
7 | const { query } = useRouter();
8 | const version = query.version ?? "stable";
9 | return (
10 |
18 | );
19 | };
20 |
21 | export default Page;
22 |
--------------------------------------------------------------------------------
/pages/https/[...url].tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import { Documentation } from "../../components/Documentation";
4 | import { NextPage } from "next";
5 |
6 | const Page: NextPage<{ entrypoint: string; name: string }> = (props) => (
7 |
8 | );
9 |
10 | Page.getInitialProps = async (ctx) => {
11 | const url =
12 | typeof ctx.query.url === "string"
13 | ? ctx.query.url
14 | : ctx.query.url === undefined
15 | ? ""
16 | : ctx.query.url.join("/");
17 | return {
18 | entrypoint: "https://" + decodeURIComponent(url),
19 | name: decodeURIComponent(url),
20 | };
21 | };
22 |
23 | export default Page;
24 |
--------------------------------------------------------------------------------
/components/Namespace.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import { DocNodeNamespace, groupNodes, sortByAlphabet } from "../util/docs";
5 | import { SimpleCard, CardList } from "./SinglePage";
6 |
7 | export function NamespaceCard({
8 | node,
9 | nested,
10 | }: {
11 | node: DocNodeNamespace;
12 | nested: boolean;
13 | }) {
14 | return (
15 |
24 | }
25 | />
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # deno_doc frontend
2 |
3 | This website is built with [Next.js](https://nextjs.org) and automatically deploys to [Vercel](https://vercel.com).
4 |
5 | ### Contributing
6 |
7 | Install [Vercel CLI](https://vercel.com/download) and run `vercel dev`. Currently not supported on Windows, see (https://github.com/lucacasonato/now-deno/issues/12)
8 |
9 | For this to run succesfully you will need to change the `functions` object of the `vercel.json` file to:
10 |
11 | ```json
12 | {
13 | "functions": {
14 | "api/**/*.ts": {
15 | "runtime": "vercel-deno@0.8.0",
16 | "maxDuration": 10
17 | }
18 | },
19 | ```
20 |
21 | To install dependencies via npm, you must run `npm install` with the `--legacy-peer-deps` flag.
22 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v1
10 | - uses: actions/setup-node@v1
11 | with:
12 | node-version: 12
13 | # TODO(ry) check lint, tests
14 | - run: yarn --frozen-lockfile
15 | # - run: yarn run lint
16 | - run: yarn format --check
17 | # - run: CI=true yarn test
18 | - name: Publish CF Worker
19 | if: github.ref == 'refs/heads/main' && github.event_name == 'push' && github.repository == 'denoland/doc_website'
20 | uses: cloudflare/wrangler-action@1.1.0
21 | with:
22 | apiToken: ${{ secrets.cloudflareKey }}
23 | workingDirectory: worker
24 |
--------------------------------------------------------------------------------
/components/app.css:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 the Deno authors. All rights reserved. MIT license. */
2 |
3 | /* purgecss start ignore */
4 | @import "tailwindcss/base";
5 | @import "tailwindcss/components";
6 | /* purgecss end ignore */
7 |
8 | @import "tailwindcss/utilities";
9 |
10 | html {
11 | scroll-behavior: smooth;
12 | }
13 |
14 | .link {
15 | @apply text-blue-500;
16 | @apply transition;
17 | @apply duration-75;
18 | @apply ease-in-out;
19 | }
20 |
21 | .link:hover {
22 | @apply text-blue-400;
23 | }
24 |
25 | .keyword {
26 | @apply text-pink-800;
27 | }
28 |
29 | @media (prefers-color-scheme: dark) {
30 | .link {
31 | @apply text-blue-500;
32 | }
33 |
34 | .link:hover {
35 | @apply text-blue-400;
36 | }
37 |
38 | .keyword {
39 | color: #ff3885;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/public/badge.svg:
--------------------------------------------------------------------------------
1 | deno deno doc doc
--------------------------------------------------------------------------------
/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import Document, {
4 | Html,
5 | Head,
6 | Main,
7 | NextScript,
8 | DocumentContext,
9 | } from "next/document";
10 |
11 | export default class DenoDocDocument extends Document {
12 | static async getInitialProps(ctx: DocumentContext) {
13 | const initialProps = await Document.getInitialProps(ctx);
14 | return { ...initialProps };
15 | }
16 |
17 | render() {
18 | return (
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/components/Enum.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import { DocNodeEnum } from "../util/docs";
5 | import { SimpleCard, SimpleSubCard } from "./SinglePage";
6 |
7 | export function EnumCard({
8 | node,
9 | nested,
10 | }: {
11 | node: DocNodeEnum;
12 | nested: boolean;
13 | }) {
14 | return (
15 |
21 |
22 |
23 | Members
24 |
25 | {node.enumDef.members.length > 0 ? (
26 | node.enumDef.members.map((member) => {
27 | return
;
28 | })
29 | ) : (
30 |
31 | This enum has no members.
32 |
33 | )}
34 |
35 | >
36 | }
37 | />
38 | );
39 | }
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 the Deno authors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/public/styles/hljs/atom-one-dark.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Minified by jsDelivr using clean-css v4.2.3.
3 | * Original file: /npm/highlight.js@10.7.2/styles/atom-one-dark.css
4 | *
5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
6 | */
7 | .hljs{display:block;overflow-x:auto;padding:.5em;color:#abb2bf;background:#282c34}.hljs-comment,.hljs-quote{color:#5c6370;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-built_in,.hljs-class .hljs-title{color:#e6c07b}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
8 | /*# sourceMappingURL=/sm/f7543874fd85ac54022e92bff1f3e54326ad7a136685439729114cd42b44ed2c.map */
--------------------------------------------------------------------------------
/public/styles/hljs/atom-one-light.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Minified by jsDelivr using clean-css v4.2.3.
3 | * Original file: /npm/highlight.js@10.7.2/styles/atom-one-light.css
4 | *
5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
6 | */
7 | .hljs{display:block;overflow-x:auto;padding:.5em;color:#383a42;background:#fafafa}.hljs-comment,.hljs-quote{color:#a0a1a7;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#a626a4}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e45649}.hljs-literal{color:#0184bb}.hljs-addition,.hljs-attribute,.hljs-meta-string,.hljs-regexp,.hljs-string{color:#50a14f}.hljs-built_in,.hljs-class .hljs-title{color:#c18401}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#986801}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#4078f2}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
8 | /*# sourceMappingURL=/sm/d76652e02644cc28bcf6e449c522da2442dcd1b6da7571da0fe4c284282c557e.map */
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "deno-doc",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "format": "prettier --write **.tsx **.ts **.js **.json"
10 | },
11 | "dependencies": {
12 | "@tailwindcss/ui": "^0.4.0",
13 | "isomorphic-unfetch": "^3.0.0",
14 | "next": "^12.0.4",
15 | "next-plugin-preact": "^3.0.6",
16 | "preact": "^10.5.15",
17 | "preact-render-to-string": "^5.1.19",
18 | "react": "npm:@preact/compat",
19 | "react-dom": "npm:@preact/compat",
20 | "react-markdown": "^4.3.1",
21 | "react-syntax-highlighter": "^13.0.0",
22 | "react-transition-group": "^4.4.1",
23 | "swr": "^0.2.3",
24 | "tailwindcss": "^1.5.2",
25 | "tailwindcss-prefers-dark-mode": "^1.2.0"
26 | },
27 | "devDependencies": {
28 | "@types/node": "^14.0.26",
29 | "@types/react": "^16.9.43",
30 | "@types/react-syntax-highlighter": "^11.0.4",
31 | "@types/react-transition-group": "^4.4.0",
32 | "autoprefixer": "^9.8.5",
33 | "prettier": "^2.0.5",
34 | "scheduler": "^0.20.2",
35 | "typescript": "^4.4.4",
36 | "webpack": "^5.64.1"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/deploy/main.ts:
--------------------------------------------------------------------------------
1 | import { serve } from "https://deno.land/x/sift@0.2.0/mod.ts";
2 |
3 | const EXAMPLE_VERSION = "v1.9.0";
4 |
5 | serve({
6 | "/": () =>
7 | new Response(
8 | `
9 | serving lib.deno.d.ts
10 | visit
11 | /builtin/stable ,
12 | /builtin/${EXAMPLE_VERSION} , for example
13 |
14 | GitHub
15 | `,
16 | { status: 200, headers: { "content-type": "text/html" } },
17 | ),
18 | "/builtin/:version": async (request, params) => {
19 | if (!params) {
20 | return notFound();
21 | }
22 | const { version } = params;
23 | if (!version) {
24 | return notFound();
25 | }
26 | // Handles "stable" version differently
27 | const dtsUrl = version === "stable"
28 | ? "https://github.com/denoland/deno/releases/latest/download/lib.deno.d.ts"
29 | : `https://github.com/denoland/deno/releases/download/${version}/lib.deno.d.ts`;
30 | const resp = await fetch(dtsUrl);
31 | if (resp.status !== 200) {
32 | return notFound();
33 | }
34 | const isBrowser = request.headers.get("accept")?.includes("text/html");
35 | // The headers on a `Response` are immutable
36 | const headers = new Headers(resp.headers);
37 | // Responses as plain text to browsers
38 | headers.set(
39 | "content-type",
40 | isBrowser ? "text/plain" : "application/typescript; charset=utf-8",
41 | );
42 | // Prevents downloading the file
43 | headers.delete("content-disposition");
44 | return new Response(resp.body, { ...resp, headers });
45 | },
46 | 404: () => notFound(),
47 | });
48 |
49 | function notFound(): Response {
50 | return new Response(`not foundBack to Top `, {
51 | status: 404,
52 | headers: { "content-type": "text/html" },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/components/Variable.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import {
5 | DocNodeVariable,
6 | TsTypeDefKind,
7 | TsTypeDefTypeLiteral,
8 | } from "../util/docs";
9 | import { SimpleCard, SimpleSubCard } from "./SinglePage";
10 |
11 | export function VariableCard({
12 | node,
13 | nested,
14 | }: {
15 | node: DocNodeVariable;
16 | nested: boolean;
17 | }) {
18 | const type = node.variableDef.tsType;
19 | const isNamespace =
20 | node.variableDef.kind === "const" &&
21 | type &&
22 | type.kind === TsTypeDefKind.TypeLiteral &&
23 | type.typeLiteral.properties.length > 0 &&
24 | type.typeLiteral.methods.length === 0 &&
25 | type.typeLiteral.callSignatures.length === 0;
26 |
27 | return isNamespace ? (
28 |
29 | ) : (
30 |
36 | );
37 | }
38 |
39 | export function VariableNamespaceCard({
40 | node,
41 | nested,
42 | }: {
43 | node: DocNodeVariable;
44 | nested: boolean;
45 | }) {
46 | const type = node.variableDef.tsType as TsTypeDefTypeLiteral;
47 | const parent = node;
48 | return (
49 |
55 |
56 | Properties
57 |
58 | {type.typeLiteral.properties.map((node) => {
59 | return (
60 |
64 | );
65 | })}
66 |
67 | }
68 | />
69 | );
70 | }
71 |
--------------------------------------------------------------------------------
/worker/index.js:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | const origin = "https://doc-website-git-main.denoland.vercel.app/api/docs";
4 |
5 | async function handleRequest(event) {
6 | let request = event.request;
7 | let url = new URL(request.url);
8 | const entrypoint = url.searchParams.get("entrypoint");
9 | if (!entrypoint) {
10 | return new Response(`{"error": "No entrypoint URL specified."}`, {
11 | status: 400,
12 | });
13 | }
14 |
15 | const remoteURL = new URL(
16 | `${origin}?entrypoint=${encodeURIComponent(entrypoint)}`,
17 | );
18 |
19 | let cacheKey = new Request(remoteURL, {
20 | method: request.method,
21 | headers: request.headers,
22 | });
23 | let cache = caches.default;
24 |
25 | const forceReload = url.searchParams.get("force_reload");
26 |
27 | // Get this request from this zone's cache
28 | let response = await cache.match(cacheKey);
29 | if (!response || forceReload) {
30 | //if not in cache, grab it from the origin
31 | response = await fetch(cacheKey);
32 | if (!response.ok) {
33 | return response;
34 | }
35 | // must use Response constructor to inherit all of response's fields
36 | response = new Response(response.body, response);
37 | // Cache API respects Cache-Control headers, so by setting max-age to 86400
38 | // the response will only live in cache for max of 24 * 60 * 60 seconds
39 | response.headers.append("Cache-Control", "max-age=86400");
40 | // store the fetched response as cacheKey
41 | // use waitUntil so computational expensive tasks don't delay the response
42 | event.waitUntil(cache.put(cacheKey, response.clone()));
43 | }
44 | response = new Response(response.body, response);
45 | response.headers.set("Cache-Control", "max-age=0");
46 | return response;
47 | }
48 |
49 | addEventListener("fetch", (event) => {
50 | try {
51 | return event.respondWith(handleRequest(event));
52 | } catch (e) {
53 | return event.respondWith(
54 | new Response(`{"error": "${e.message}"}`, {
55 | status: 500,
56 | }),
57 | );
58 | }
59 | });
60 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const defaultTheme = require("tailwindcss/defaultTheme"); // eslint-disable-line
2 |
3 | module.exports = {
4 | purge: ["./components/**/*.tsx", "./pages/**/*.tsx"],
5 | theme: {
6 | fontFamily: {
7 | mono: [
8 | "Menlo",
9 | "Monaco",
10 | '"Lucida Console"',
11 | "Consolas",
12 | '"Liberation Mono"',
13 | '"Courier New"',
14 | "monospace",
15 | ],
16 | },
17 | inset: {
18 | "0": 0,
19 | auto: "auto",
20 | "16": "4rem",
21 | "20": "5rem",
22 | xs: "20rem",
23 | },
24 | extend: {
25 | fontFamily: {
26 | sans: ["Inter var", ...defaultTheme.fontFamily.sans],
27 | },
28 | padding: {
29 | xs: "20rem",
30 | },
31 | width: {
32 | xs: "20rem",
33 | },
34 | colors: {
35 | "light-black-950": "#141414",
36 | "light-black-900": "#1a1a1a",
37 | "light-black-800": "#202020",
38 | "light-black-700": "#2a2a2a",
39 | "light-black-600": "#323232",
40 | },
41 | },
42 | },
43 | variants: {
44 | backgroundColor: [
45 | "responsive",
46 | "hover",
47 | "focus",
48 | "active",
49 | "dark",
50 | "dark:hover",
51 | "dark:focus",
52 | "dark:active",
53 | ],
54 | borderColor: [
55 | "responsive",
56 | "hover",
57 | "focus",
58 | "dark",
59 | "dark:hover",
60 | "dark:focus",
61 | ],
62 | placeholderColor: [
63 | "responsive",
64 | "hover",
65 | "focus",
66 | "dark",
67 | "dark:hover",
68 | "dark:focus",
69 | ],
70 | textColor: [
71 | "responsive",
72 | "hover",
73 | "focus",
74 | "group-hover",
75 | "dark",
76 | "dark:hover",
77 | "dark:focus",
78 | "dark:group-hover",
79 | "focus-within",
80 | "dark:focus-within",
81 | "dark:odd",
82 | "dark:even",
83 | "dark:active",
84 | "dark:disabled",
85 | ],
86 | borderStyle: ["responsive", "dark"],
87 | },
88 | plugins: [
89 | require("@tailwindcss/ui"),
90 | require("tailwindcss-prefers-dark-mode")(),
91 | ],
92 | };
93 |
--------------------------------------------------------------------------------
/api/docs.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.
2 |
3 | import { ServerRequest } from "https://deno.land/std@0.84.0/http/server.ts";
4 |
5 | const decoder = new TextDecoder();
6 |
7 | export default async (req: ServerRequest) => {
8 | const url = new URL(req.url, "https://example.com");
9 |
10 | const entrypoint = url.searchParams.get("entrypoint");
11 |
12 | if (!entrypoint) {
13 | return await req.respond(error("missing entrypoint query parameter", 400));
14 | }
15 |
16 | const isRemote = entrypoint.startsWith("https://");
17 |
18 | let sourceFile: string;
19 | if (isRemote) {
20 | sourceFile = entrypoint;
21 | } else {
22 | return await req.respond(
23 | error("entrypoint must be a remote https:// module", 400),
24 | );
25 | }
26 |
27 | const proc = Deno.run({
28 | cmd: ["deno", "doc", sourceFile, "--json", "--reload"],
29 | stdout: "piped",
30 | stderr: "piped",
31 | env: { "DENO_DIR": "/tmp/denodir" },
32 | });
33 |
34 | let killed = false;
35 |
36 | // Zeit timeout is 60 seconds for pro tier: https://zeit.co/docs/v2/platform/limits
37 | const timer = setTimeout(() => {
38 | killed = true;
39 | proc.kill(Deno.Signal.SIGKILL);
40 | }, 58000);
41 |
42 | const [out, errOut] = await Promise.all([proc.output(), proc.stderrOutput()]);
43 | const status = await proc.status();
44 | clearTimeout(timer);
45 | proc.close();
46 | if (!status.success) {
47 | if (killed) return await req.respond(error("timed out", 500));
48 | return await req.respond(error(decoder.decode(errOut), 500));
49 | }
50 |
51 | return await req.respond({
52 | status: 200,
53 | body: JSON.stringify({
54 | timestamp: new Date().toISOString(),
55 | nodes: JSON.parse(decoder.decode(out)),
56 | }),
57 | headers: new Headers({
58 | "content-type": "application/json; charset=utf-8",
59 | }),
60 | });
61 | };
62 |
63 | function error(message: string, code: number) {
64 | return {
65 | status: code,
66 | body: JSON.stringify({
67 | error: message,
68 | }),
69 | headers: new Headers({
70 | "content-type": "application/json; charset=utf-8",
71 | }),
72 | };
73 | }
74 |
--------------------------------------------------------------------------------
/components/Sidebar.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import { DocNodeShared, GroupedNodes } from "../util/docs";
5 |
6 | const SidebarSection = (props: {
7 | title: string;
8 | type: string;
9 | nodes: DocNodeShared[];
10 | }) => {
11 | return props.nodes.length > 0 ? (
12 |
13 |
14 | {props.title}
15 |
16 |
17 | {props.nodes.map((node, i) => {
18 | const scope = node.scope ? node.scope.join(".") + "." : "";
19 | return (
20 |
24 | {scope}
25 |
26 | {node.name}
27 |
28 |
29 | );
30 | })}
31 |
32 |
33 | ) : null;
34 | };
35 |
36 | export const Sidebar = ({ groups }: { groups: GroupedNodes }) => {
37 | return (
38 |
39 |
40 | <>
41 |
46 |
51 |
52 |
53 |
58 |
63 | >
64 |
69 |
70 |
71 | );
72 | };
73 |
--------------------------------------------------------------------------------
/components/JSDoc.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import ReactMarkdown from "react-markdown";
5 | import { Light as SyntaxHighlighter } from "react-syntax-highlighter";
6 | import javascript from "react-syntax-highlighter/dist/cjs/languages/hljs/javascript";
7 | import typescript from "react-syntax-highlighter/dist/cjs/languages/hljs/typescript";
8 | SyntaxHighlighter.registerLanguage("js", javascript);
9 | SyntaxHighlighter.registerLanguage("ts", typescript);
10 |
11 | export function JSDoc(props: { jsdoc: string }) {
12 | let jsdoc = props.jsdoc
13 | .replace(/\n@param/g, "\n\n __param__")
14 | .replace(/\n@return/g, "\n\n __return__")
15 | // [link text]{@link https://www.link.com}
16 | .replace(/\[(.*?)\]{@link (.*?)}/g, (match, text, link): string => {
17 | return `[${text}](${link})`;
18 | })
19 | // {@link https://www.link.com|link text}
20 | .replace(/{@link (.*?)\|(.*?)}/g, (match, link, text): string => {
21 | return `[${text}](${link})`;
22 | })
23 | // {@link https://www.link.com link text}
24 | .replace(/{@link ([^}]*?) ([^}]*?)}/g, (match, link, text): string => {
25 | return `[${text}](${link})`
26 | })
27 | // {@link https://www.link.com}
28 | .replace(/{@link (.*?)}/g, (match, link): string => {
29 | return `[${link}](${link})`
30 | })
31 | // @deprecated reason
32 | .replace(/@deprecated/g, "__deprecated__");
33 |
34 | return (
35 | (
39 |
40 | {props.children}
41 |
42 | ),
43 | inlineCode: InlineCode,
44 | code: CodeBlock,
45 | table: (props) => (
46 |
52 | ),
53 | tableCell: (props) => (
54 |
61 | ),
62 | }}
63 | />
64 | );
65 | }
66 |
67 | export function InlineCode(props: { children: React.ReactNode }) {
68 | return (
69 |
70 | {props.children}
71 |
72 | );
73 | }
74 |
75 | export function CodeBlock(props: { value: string; language: string }) {
76 | return (
77 |
78 |
92 | {props.value}
93 |
94 |
95 | );
96 | }
97 |
--------------------------------------------------------------------------------
/components/Documentation.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React, { useReducer, useEffect } from "react";
4 | import Link from "next/link";
5 | import Head from "next/head";
6 | import useSWR from "swr";
7 | import { getData, DocsData } from "../util/data";
8 | import { SinglePage } from "./SinglePage";
9 |
10 | export const Documentation = ({
11 | entrypoint,
12 | name,
13 | }: {
14 | entrypoint: string;
15 | name: string;
16 | }) => {
17 | const [loadCount, forceReload] = useReducer((i) => ++i, 0);
18 | const { data, error } = useSWR(
19 | [entrypoint, loadCount],
20 | () =>
21 | getData(entrypoint, "", loadCount > 0).catch((err) => {
22 | throw err?.message ?? err.toString();
23 | }),
24 | {
25 | revalidateOnFocus: false,
26 | revalidateOnReconnect: false,
27 | refreshWhenHidden: false,
28 | refreshWhenOffline: false,
29 | }
30 | );
31 |
32 | const { data: runtimeBuiltinsData } = useSWR(
33 | [loadCount],
34 | () =>
35 | getData(
36 | "https://doc-proxy.deno.dev/builtin/stable",
37 | "",
38 | loadCount > 0
39 | ).catch((err) => {
40 | throw err?.message ?? err.toString();
41 | }),
42 | {
43 | revalidateOnFocus: false,
44 | revalidateOnReconnect: false,
45 | refreshWhenHidden: false,
46 | refreshWhenOffline: false,
47 | }
48 | );
49 |
50 | useEffect(() => {
51 | let { hash } = location;
52 | hash = hash && hash.substring(1);
53 | if (!hash) return;
54 |
55 | const el = document.getElementById(hash);
56 | if (!el) return;
57 |
58 | setTimeout(() => el.scrollIntoView(), 0);
59 | }, [data]);
60 |
61 | if (error) {
62 | let title =
63 | "A internal server error occured while generating the documentation.";
64 | let details = error;
65 |
66 | if (error && (error.includes("404") || error.includes("dns"))) {
67 | const file = (error.match(/Import '(.*)' failed/) ?? [])[1] ?? "";
68 | title = "404 - A source file could not be found.";
69 | details = `Please check that the ${
70 | file ? `file '${file}'` : "entrypoint and its dependents are"
71 | } available on the public internet.`;
72 | }
73 |
74 | return (
75 |
90 | );
91 | }
92 |
93 | return (
94 | <>
95 |
96 | {name} - deno doc
97 |
101 |
102 |
108 | >
109 | );
110 | };
111 |
--------------------------------------------------------------------------------
/components/Function.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import { DocNodeFunction, ParamDef, ObjectPatPropDef } from "../util/docs";
5 | import { SimpleCard } from "./SinglePage";
6 | import { TsType } from "./TsType";
7 |
8 | export function FunctionCard({
9 | node,
10 | nested,
11 | }: {
12 | node: DocNodeFunction;
13 | nested: boolean;
14 | }) {
15 | return (
16 |
23 | );
24 | }
25 |
26 | export function ObjectPatProp({
27 | prop,
28 | scope,
29 | }: {
30 | prop: ObjectPatPropDef;
31 | scope: string[];
32 | }) {
33 | switch (prop.kind) {
34 | case "assign":
35 | case "keyValue":
36 | return <>{prop.key}>;
37 | case "rest":
38 | return (
39 | <>
40 | ...
41 |
42 | >
43 | );
44 | }
45 | }
46 |
47 | export function Param({
48 | param: p,
49 | scope,
50 | }: {
51 | param: ParamDef;
52 | scope: string[];
53 | }) {
54 | switch (p.kind) {
55 | case "array": {
56 | return (
57 | <>
58 | [ ]{p.optional && "?"}
59 | {p.tsType && (
60 |
61 | :
62 |
63 | )}
64 | >
65 | );
66 | }
67 | case "assign": {
68 | return (
69 | <>
70 |
71 | {p.tsType && (
72 |
73 | :
74 |
75 | )}
76 | >
77 | );
78 | }
79 | case "identifier": {
80 | return (
81 | <>
82 | {p.name}
83 | {p.optional && "?"}
84 | {p.tsType && (
85 |
86 | :
87 |
88 | )}
89 | >
90 | );
91 | }
92 | case "object": {
93 | return (
94 | <>
95 | {"{ "}
96 | {p.props
97 | .map((prop) => )
98 | .reduce((r, a) => (
99 | <>
100 | {r}, {a}
101 | >
102 | ))}
103 | {" }"}
104 | {p.optional && "?"}
105 | {p.tsType && (
106 |
107 | :
108 |
109 | )}
110 | >
111 | );
112 | }
113 | case "rest": {
114 | return (
115 | <>
116 | ...
117 |
118 | {p.tsType && (
119 |
120 | :
121 |
122 | )}
123 | >
124 | );
125 | }
126 | }
127 | }
128 |
129 | export function Params({
130 | params,
131 | scope,
132 | }: {
133 | params: (ParamDef | null)[];
134 | scope: string[];
135 | }) {
136 | if (params.length === 0) return <>>;
137 | return (
138 | <>
139 | {params
140 | .map((p) => {
141 | if (p === null) return <>>;
142 | return ;
143 | })
144 | .reduce((r, a) => (
145 | <>
146 | {r}, {a}
147 | >
148 | ))}
149 | >
150 | );
151 | }
152 |
--------------------------------------------------------------------------------
/util/data.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import { createContext, useContext } from "react";
4 | import fetch from "isomorphic-unfetch";
5 | import { DocNode } from "./docs";
6 |
7 | const flattendContext = createContext([]);
8 |
9 | export function useFlattend() {
10 | return useContext(flattendContext);
11 | }
12 |
13 | export const FlattendProvider = flattendContext.Provider;
14 |
15 | const runtimeBuiltinsContext = createContext([]);
16 |
17 | export function useRuntimeBuiltins() {
18 | return useContext(runtimeBuiltinsContext);
19 | }
20 |
21 | export const RuntimeBuiltinsProvider = runtimeBuiltinsContext.Provider;
22 |
23 | export interface DocsData {
24 | timestamp: string;
25 | nodes: DocNode[];
26 | }
27 |
28 | // A regex to determine if a provided url has a version and thus can be cached.
29 | const HAS_VERSION_REGEX = /https:\/\/deno\.land\/(x\/[a-z0-9][a-z0-9_]+[a-z0-9]|std)@\d*\.\d*\.\d*\/.+/g;
30 |
31 | export async function getData(
32 | entrypoint: string,
33 | hostname: string,
34 | forceReload?: boolean
35 | ): Promise {
36 | // TODO: Use a smarter way to ensure that the entrypoint is tagged with a version, currently we
37 | // will get occasional cache misses for version-tagged entrypoints.
38 | const canBeCached = HAS_VERSION_REGEX.test(entrypoint);
39 | const cacheKey = `cached-entrypoint-${entrypoint}`;
40 | // Looks for the data cached in the local storage if we know that the entrypoint is tagged with a
41 | // version and we aren't forcing a reload.
42 | const cachedData =
43 | canBeCached && !forceReload ? window.localStorage.getItem(cacheKey) : null;
44 |
45 | if (cachedData) {
46 | return JSON.parse(cachedData);
47 | } else {
48 | const req = await fetch(
49 | `${hostname}/api/docs?entrypoint=${encodeURIComponent(entrypoint)}${
50 | forceReload ? "&force_reload=true" : ""
51 | }`
52 | );
53 | if (!req.ok) throw new Error((await req.json()).error);
54 | const resp = await req.json();
55 | const data = {
56 | timestamp: resp.timestamp,
57 | nodes: resp.nodes,
58 | };
59 |
60 | const dataStringified = JSON.stringify(data);
61 |
62 | if (canBeCached) {
63 | try {
64 | window.localStorage.setItem(cacheKey, dataStringified);
65 | } catch (error) {
66 | // The local storage is either full or the user has disabled it's usage. We'll try to evict
67 | // some of the oldest items in the cache to make space.
68 |
69 | // Reads all of the cached items in the local storage and pairs them with the data and the
70 | // size of the entry.
71 | const cacheTuples = [...new Array(window.localStorage.length)]
72 | .map((_, i) => window.localStorage.key(i))
73 | .filter(
74 | (key): key is string =>
75 | key?.startsWith("cached-entrypoint-") ?? false
76 | )
77 | .map((key): [string, DocsData, number] => {
78 | const data = window.localStorage.getItem(key)!;
79 | return [key, JSON.parse(data) as DocsData, data.length];
80 | })
81 | .sort(
82 | ([_aKey, a], [_bKey, b]) =>
83 | Date.parse(a.timestamp) - Date.parse(b.timestamp)
84 | );
85 |
86 | let deletedData = 0;
87 |
88 | // Removes items from the local storage until we have enough to store the new data.
89 | for (const [key, _, sizeInStorage] of cacheTuples) {
90 | if (deletedData >= dataStringified.length) {
91 | break;
92 | }
93 |
94 | window.localStorage.removeItem(key);
95 | deletedData += sizeInStorage;
96 | }
97 |
98 | // Tries to cache the key again, after clearing enough space for it.
99 | window.localStorage.setItem(cacheKey, dataStringified);
100 | }
101 | }
102 |
103 | return data;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/components/Transition.tsx:
--------------------------------------------------------------------------------
1 | // From https://gist.githubusercontent.com/stevecastaneda/e71a8465c3f290b98982e5d160260de2/raw/68a48d6b5e0ef60ec5894a0cf6b171bb48681f23/Transition.tsx
2 | // JSX Version by Adam Wathan: https://gist.github.com/adamwathan/e0a791aa0419098a7ece70028b2e641e
3 |
4 | import React, { ReactNode, useRef, useEffect, useContext } from "react";
5 | import { CSSTransition as ReactCSSTransition } from "react-transition-group";
6 |
7 | interface TransitionProps {
8 | show?: boolean;
9 | enter?: string;
10 | enterFrom?: string;
11 | enterTo?: string;
12 | leave?: string;
13 | leaveFrom?: string;
14 | leaveTo?: string;
15 | appear?: string | boolean;
16 | children: ReactNode;
17 | }
18 |
19 | interface ParentContextProps {
20 | parent: {
21 | show?: boolean;
22 | appear?: string | boolean;
23 | isInitialRender?: boolean;
24 | };
25 | }
26 |
27 | const TransitionContext = React.createContext({
28 | parent: {},
29 | });
30 |
31 | function useIsInitialRender() {
32 | const isInitialRender = useRef(true);
33 | useEffect(() => {
34 | isInitialRender.current = false;
35 | }, []);
36 | return isInitialRender.current;
37 | }
38 |
39 | function CSSTransition({
40 | show,
41 | enter = "",
42 | enterFrom = "",
43 | enterTo = "",
44 | leave = "",
45 | leaveFrom = "",
46 | leaveTo = "",
47 | appear,
48 | children,
49 | }: TransitionProps) {
50 | const enterClasses = enter.split(" ").filter((s) => s.length);
51 | const enterFromClasses = enterFrom.split(" ").filter((s) => s.length);
52 | const enterToClasses = enterTo.split(" ").filter((s) => s.length);
53 | const leaveClasses = leave.split(" ").filter((s) => s.length);
54 | const leaveFromClasses = leaveFrom.split(" ").filter((s) => s.length);
55 | const leaveToClasses = leaveTo.split(" ").filter((s) => s.length);
56 |
57 | function addClasses(node: HTMLElement, classes: string[]) {
58 | classes.length && node.classList.add(...classes);
59 | }
60 |
61 | function removeClasses(node: HTMLElement, classes: string[]) {
62 | classes.length && node.classList.remove(...classes);
63 | }
64 |
65 | return (
66 | {
71 | node.addEventListener("transitionend", done, false);
72 | }}
73 | onEnter={(node, _) => {
74 | addClasses(node, [...enterClasses, ...enterFromClasses]);
75 | }}
76 | onEntering={(node, _) => {
77 | removeClasses(node, enterFromClasses);
78 | addClasses(node, enterToClasses);
79 | }}
80 | onEntered={(node, _) => {
81 | removeClasses(node, [...enterToClasses, ...enterClasses]);
82 | }}
83 | onExit={(node) => {
84 | addClasses(node, [...leaveClasses, ...leaveFromClasses]);
85 | }}
86 | onExiting={(node) => {
87 | removeClasses(node, leaveFromClasses);
88 | addClasses(node, leaveToClasses);
89 | }}
90 | onExited={(node) => {
91 | removeClasses(node, [...leaveToClasses, ...leaveClasses]);
92 | }}
93 | >
94 | {children}
95 |
96 | );
97 | }
98 |
99 | function Transition({ show, appear, ...rest }: TransitionProps) {
100 | const { parent } = useContext(TransitionContext);
101 | const isInitialRender = useIsInitialRender();
102 | const isChild = show === undefined;
103 |
104 | if (isChild) {
105 | return (
106 |
111 | );
112 | }
113 |
114 | return (
115 |
124 |
125 |
126 | );
127 | }
128 |
129 | export default Transition;
130 |
--------------------------------------------------------------------------------
/components/Interface.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import { DocNodeInterface } from "../util/docs";
5 | import { SimpleCard, SimpleSubCard } from "./SinglePage";
6 | import { TypeParams } from "./Class";
7 | import { TsType } from "./TsType";
8 |
9 | export function InterfaceCard({
10 | node,
11 | nested,
12 | }: {
13 | node: DocNodeInterface;
14 | nested: boolean;
15 | }) {
16 | const parent = node;
17 | const extendsItems = node.interfaceDef.extends.flatMap((tsType) => {
18 | return [ , ", "];
19 | });
20 | extendsItems.pop();
21 | return (
22 |
28 | {node.interfaceDef.typeParams.length > 0 ? (
29 |
30 | {"<"}
31 |
35 | {">"}
36 |
37 | ) : null}
38 | {extendsItems.length > 0 ? (
39 | <>
40 | {" "}
41 | extends {extendsItems}
42 | >
43 | ) : null}
44 | >
45 | }
46 | details={
47 | <>
48 | {node.interfaceDef.callSignatures.length > 0 ? (
49 |
50 |
51 | Call Signatures
52 |
53 | {node.interfaceDef.callSignatures.map((node) => {
54 | return (
55 |
60 | );
61 | })}
62 |
63 | ) : null}
64 | {node.interfaceDef.properties.length > 0 ? (
65 |
66 |
67 | Properties
68 |
69 | {node.interfaceDef.properties.map((node) => {
70 | return (
71 |
76 | );
77 | })}
78 |
79 | ) : null}
80 | {node.interfaceDef.methods.length > 0 ? (
81 |
82 |
83 | Methods
84 |
85 | {node.interfaceDef.methods.map((node) => {
86 | return (
87 |
93 | );
94 | })}
95 |
96 | ) : null}
97 | {node.interfaceDef.indexSignatures.length > 0 ? (
98 |
99 |
100 | Index Signatures
101 |
102 | {node.interfaceDef.indexSignatures.map((node) => {
103 | return (
104 |
111 | );
112 | })}
113 |
114 | ) : null}
115 | >
116 | }
117 | />
118 | );
119 | }
120 |
--------------------------------------------------------------------------------
/public/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/favicon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/fonts/inter/inter.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Inter';
3 | font-style: normal;
4 | font-weight: 100;
5 | font-display: swap;
6 | src: url("Inter-Thin.woff2?v=3.13") format("woff2"),
7 | url("Inter-Thin.woff?v=3.13") format("woff");
8 | }
9 | @font-face {
10 | font-family: 'Inter';
11 | font-style: italic;
12 | font-weight: 100;
13 | font-display: swap;
14 | src: url("Inter-ThinItalic.woff2?v=3.13") format("woff2"),
15 | url("Inter-ThinItalic.woff?v=3.13") format("woff");
16 | }
17 |
18 | @font-face {
19 | font-family: 'Inter';
20 | font-style: normal;
21 | font-weight: 200;
22 | font-display: swap;
23 | src: url("Inter-ExtraLight.woff2?v=3.13") format("woff2"),
24 | url("Inter-ExtraLight.woff?v=3.13") format("woff");
25 | }
26 | @font-face {
27 | font-family: 'Inter';
28 | font-style: italic;
29 | font-weight: 200;
30 | font-display: swap;
31 | src: url("Inter-ExtraLightItalic.woff2?v=3.13") format("woff2"),
32 | url("Inter-ExtraLightItalic.woff?v=3.13") format("woff");
33 | }
34 |
35 | @font-face {
36 | font-family: 'Inter';
37 | font-style: normal;
38 | font-weight: 300;
39 | font-display: swap;
40 | src: url("Inter-Light.woff2?v=3.13") format("woff2"),
41 | url("Inter-Light.woff?v=3.13") format("woff");
42 | }
43 | @font-face {
44 | font-family: 'Inter';
45 | font-style: italic;
46 | font-weight: 300;
47 | font-display: swap;
48 | src: url("Inter-LightItalic.woff2?v=3.13") format("woff2"),
49 | url("Inter-LightItalic.woff?v=3.13") format("woff");
50 | }
51 |
52 | @font-face {
53 | font-family: 'Inter';
54 | font-style: normal;
55 | font-weight: 400;
56 | font-display: swap;
57 | src: url("Inter-Regular.woff2?v=3.13") format("woff2"),
58 | url("Inter-Regular.woff?v=3.13") format("woff");
59 | }
60 | @font-face {
61 | font-family: 'Inter';
62 | font-style: italic;
63 | font-weight: 400;
64 | font-display: swap;
65 | src: url("Inter-Italic.woff2?v=3.13") format("woff2"),
66 | url("Inter-Italic.woff?v=3.13") format("woff");
67 | }
68 |
69 | @font-face {
70 | font-family: 'Inter';
71 | font-style: normal;
72 | font-weight: 500;
73 | font-display: swap;
74 | src: url("Inter-Medium.woff2?v=3.13") format("woff2"),
75 | url("Inter-Medium.woff?v=3.13") format("woff");
76 | }
77 | @font-face {
78 | font-family: 'Inter';
79 | font-style: italic;
80 | font-weight: 500;
81 | font-display: swap;
82 | src: url("Inter-MediumItalic.woff2?v=3.13") format("woff2"),
83 | url("Inter-MediumItalic.woff?v=3.13") format("woff");
84 | }
85 |
86 | @font-face {
87 | font-family: 'Inter';
88 | font-style: normal;
89 | font-weight: 600;
90 | font-display: swap;
91 | src: url("Inter-SemiBold.woff2?v=3.13") format("woff2"),
92 | url("Inter-SemiBold.woff?v=3.13") format("woff");
93 | }
94 | @font-face {
95 | font-family: 'Inter';
96 | font-style: italic;
97 | font-weight: 600;
98 | font-display: swap;
99 | src: url("Inter-SemiBoldItalic.woff2?v=3.13") format("woff2"),
100 | url("Inter-SemiBoldItalic.woff?v=3.13") format("woff");
101 | }
102 |
103 | @font-face {
104 | font-family: 'Inter';
105 | font-style: normal;
106 | font-weight: 700;
107 | font-display: swap;
108 | src: url("Inter-Bold.woff2?v=3.13") format("woff2"),
109 | url("Inter-Bold.woff?v=3.13") format("woff");
110 | }
111 | @font-face {
112 | font-family: 'Inter';
113 | font-style: italic;
114 | font-weight: 700;
115 | font-display: swap;
116 | src: url("Inter-BoldItalic.woff2?v=3.13") format("woff2"),
117 | url("Inter-BoldItalic.woff?v=3.13") format("woff");
118 | }
119 |
120 | @font-face {
121 | font-family: 'Inter';
122 | font-style: normal;
123 | font-weight: 800;
124 | font-display: swap;
125 | src: url("Inter-ExtraBold.woff2?v=3.13") format("woff2"),
126 | url("Inter-ExtraBold.woff?v=3.13") format("woff");
127 | }
128 | @font-face {
129 | font-family: 'Inter';
130 | font-style: italic;
131 | font-weight: 800;
132 | font-display: swap;
133 | src: url("Inter-ExtraBoldItalic.woff2?v=3.13") format("woff2"),
134 | url("Inter-ExtraBoldItalic.woff?v=3.13") format("woff");
135 | }
136 |
137 | @font-face {
138 | font-family: 'Inter';
139 | font-style: normal;
140 | font-weight: 900;
141 | font-display: swap;
142 | src: url("Inter-Black.woff2?v=3.13") format("woff2"),
143 | url("Inter-Black.woff?v=3.13") format("woff");
144 | }
145 | @font-face {
146 | font-family: 'Inter';
147 | font-style: italic;
148 | font-weight: 900;
149 | font-display: swap;
150 | src: url("Inter-BlackItalic.woff2?v=3.13") format("woff2"),
151 | url("Inter-BlackItalic.woff?v=3.13") format("woff");
152 | }
153 |
154 | /* -------------------------------------------------------
155 | Variable font.
156 | Usage:
157 |
158 | html { font-family: 'Inter', sans-serif; }
159 | @supports (font-variation-settings: normal) {
160 | html { font-family: 'Inter var', sans-serif; }
161 | }
162 | */
163 | @font-face {
164 | font-family: 'Inter var';
165 | font-weight: 100 900;
166 | font-display: swap;
167 | font-style: normal;
168 | font-named-instance: 'Regular';
169 | src: url("Inter-roman.var.woff2?v=3.13") format("woff2");
170 | }
171 | @font-face {
172 | font-family: 'Inter var';
173 | font-weight: 100 900;
174 | font-display: swap;
175 | font-style: italic;
176 | font-named-instance: 'Italic';
177 | src: url("Inter-italic.var.woff2?v=3.13") format("woff2");
178 | }
179 |
180 |
181 | /* --------------------------------------------------------------------------
182 | [EXPERIMENTAL] Multi-axis, single variable font.
183 |
184 | Slant axis is not yet widely supported (as of February 2019) and thus this
185 | multi-axis single variable font is opt-in rather than the default.
186 |
187 | When using this, you will probably need to set font-variation-settings
188 | explicitly, e.g.
189 |
190 | * { font-variation-settings: "slnt" 0deg }
191 | .italic { font-variation-settings: "slnt" 10deg }
192 |
193 | */
194 | @font-face {
195 | font-family: 'Inter var experimental';
196 | font-weight: 100 900;
197 | font-display: swap;
198 | font-style: oblique 0deg 10deg;
199 | src: url("Inter.var.woff2?v=3.13") format("woff2");
200 | }
201 |
--------------------------------------------------------------------------------
/pages/index.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import Head from "next/head";
4 | import { useRouter } from "next/router";
5 | import Link from "next/link";
6 | import { useState } from "react";
7 | import Header from "../components/Header";
8 | import Footer from "../components/Footer";
9 |
10 | const examples = [
11 | "deno.land/std/http/mod.ts",
12 | "deno.land/std/fs/mod.ts",
13 | "deno.land/x/oak/mod.ts",
14 | "deno.land/x/redis/mod.ts",
15 | "deno.land/x/amqp/mod.ts",
16 | "cdn.pika.dev/lodash-es",
17 | "deno.land/std/archive/tar.ts",
18 | "deno.land/std/node/module.ts",
19 | ];
20 |
21 | function Home() {
22 | const router = useRouter();
23 | const [url, setUrl] = useState("");
24 | function navigate() {
25 | router.push(
26 | "/https/[...url]",
27 | "/https/" +
28 | encodeURIComponent(url.replace("https://", "").replace("http://", ""))
29 | );
30 | }
31 | return (
32 | <>
33 |
34 | deno doc
35 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
51 | Deno runtime documentation
52 |
53 |
54 |
55 |
56 | or view documentation for
57 |
58 |
59 |
60 |
61 | Source link
62 |
63 | setUrl(e.target.value)}
70 | onKeyDown={(e) => {
71 | if (e.key === "Enter" && url.length > 0) navigate();
72 | }}
73 | />
74 |
75 |
{
78 | if (url.length > 0) navigate();
79 | }}
80 | >
81 | View {" "}
82 |
87 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | View{" "}
100 |
101 | --unstable
102 | {" "}
103 | runtime documentation{" "}
104 |
105 |
here
106 |
107 | .
108 |
109 |
Some examples:
110 |
111 | {examples.map((example) => (
112 |
113 |
114 | https://{example}
115 |
116 |
117 | ))}
118 |
119 |
120 |
121 |
122 | >
123 | );
124 | }
125 |
126 | export default Home;
127 |
--------------------------------------------------------------------------------
/pages/about.tsx:
--------------------------------------------------------------------------------
1 | import Head from "next/head";
2 | import Link from "next/link";
3 | import { CodeBlock, InlineCode } from "../components/JSDoc";
4 | import Header from "../components/Header";
5 | import Footer from "../components/Footer";
6 |
7 | function About() {
8 | return (
9 |
10 |
11 |
About deno doc
12 |
16 |
17 |
18 |
19 |
About
20 |
21 |
22 | doc.deno.land hosts documentation for TypeScript and ES module files
23 | available on the public internet that use ES module import syntax
24 | with URLs.
25 |
26 |
27 | The source code is available on{" "}
28 |
29 | GitHub
30 |
31 | .
32 |
33 |
34 |
35 |
39 | Adding a module to deno doc
40 |
41 |
42 | doc.deno.land dynamically pulls a module from the specified URL and
43 | generates documentation for it when it is first viewed. You do not
44 | need to manually register a module on doc.deno.land to make it
45 | available.
46 |
47 |
48 | doc.deno.land caches generated documentation for 24 hours. After
49 | this time the generated documentation is removed from the cache and
50 | the module is treated as if it had never been requested before.
51 |
52 |
53 |
54 |
58 | Removing a module from deno doc
59 |
60 |
61 | You can not manually remove modules from doc.deno.land as they
62 | expire automatically after 24 hours. If there is an urgent reason to
63 | remove a module from the cache, please reach out to one of the Deno
64 | maintainers on the{" "}
65 |
66 | Deno discord
67 |
68 | .
69 |
70 |
71 |
72 |
73 | Badges
74 |
75 |
76 | Below are examples of some snippets that you can use to link to
77 | doc.deno.land from your project website or README.{" "}
78 |
79 | Don't forget to replace the doc.deno.land url with the one for
80 | your module.
81 |
82 |
83 |
84 |
85 |
HTML
86 |
`}
89 | />
90 |
91 |
92 | Markdown
93 |
97 |
98 |
99 |
100 |
104 | Limitations
105 |
106 |
107 |
108 | doc.deno.land currently has some limitations that you should be
109 | aware of:
110 |
111 |
112 |
113 | The time to pull source files and generate documentation from
114 | these may not exceed 58 seconds. If you are running into a
115 | timeout issue because of this, please open an issue on{" "}
116 |
120 | GitHub
121 | {" "}
122 | with a link to the module that is timing out.
123 |
124 |
125 |
126 |
127 |
128 |
129 | Feedback
130 |
131 |
132 | On our{" "}
133 |
134 | GitHub
135 | {" "}
136 | you can open an issue to share any ideas, feature requests,
137 | questions, or issues you are having. For general discussion about
138 | Deno or doc.deno.land, please use our{" "}
139 |
140 | Discord server
141 |
142 | .
143 |
144 |
145 |
146 |
147 |
148 | );
149 | }
150 |
151 | export default About;
152 |
--------------------------------------------------------------------------------
/components/Footer.tsx:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 the Deno authors. All rights reserved. MIT license. */
2 |
3 | import React from "react";
4 | import Link from "next/link";
5 |
6 | const Footer = (props: { simple?: boolean }) => (
7 |
14 |
15 |
16 | {" "}
24 |
32 |
39 |
40 |
73 |
110 |
111 |
112 | );
113 |
114 | export default Footer;
115 |
--------------------------------------------------------------------------------
/components/Loading.tsx:
--------------------------------------------------------------------------------
1 | export const Loading = () => (
2 |
8 |
9 |
12 |
13 |
14 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
37 |
38 |
39 |
45 |
46 |
47 |
52 |
53 |
54 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
81 |
86 |
91 |
96 |
101 |
106 |
111 |
112 |
209 |
210 | );
211 |
--------------------------------------------------------------------------------
/components/Header.tsx:
--------------------------------------------------------------------------------
1 | /* Copyright 2020 the Deno authors. All rights reserved. MIT license. */
2 |
3 | import React, { useState } from "react";
4 | import Link from "next/link";
5 | import Transition from "./Transition";
6 |
7 | const Header = () => {
8 | const [menuOpen, setMenuOpen] = useState(false);
9 |
10 | return (
11 |
167 | );
168 | };
169 |
170 | export default Header;
171 |
--------------------------------------------------------------------------------
/components/Class.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React from "react";
4 | import {
5 | DocNodeClass,
6 | getLinkByScopedName,
7 | getFieldsForClassRecursive,
8 | TsTypeParamDef,
9 | } from "../util/docs";
10 | import { SimpleCard, SimpleSubCard } from "./SinglePage";
11 | import { useFlattend, useRuntimeBuiltins } from "../util/data";
12 | import Link from "next/link";
13 | import { TsType, LinkRef } from "./TsType";
14 |
15 | export function ClassCard({
16 | node,
17 | nested,
18 | }: {
19 | node: DocNodeClass;
20 | nested: boolean;
21 | }) {
22 | const constructors = node.classDef.constructors;
23 | const indexSignatures = node.classDef.indexSignatures;
24 |
25 | const flattend = useFlattend();
26 | const fullClass = getFieldsForClassRecursive(flattend, node);
27 |
28 | const properties = fullClass.properties.filter(
29 | (node) => node.accessibility !== "private"
30 | );
31 | const realProperties = properties.filter((node) => !node.isStatic);
32 | const staticProperties = properties.filter((node) => node.isStatic);
33 | const methods = fullClass.methods.filter(
34 | (node) => node.accessibility !== "private"
35 | );
36 | const realMethods = methods.filter((node) => !node.isStatic);
37 | const staticMethods = methods.filter((node) => node.isStatic);
38 |
39 | const parent = node;
40 |
41 | const { extends: extends_ } = node.classDef;
42 | const runtimeBuiltins = useRuntimeBuiltins();
43 | const extendsLink = extends_
44 | ? getLinkByScopedName(flattend, runtimeBuiltins, extends_, node.scope ?? [])
45 | : undefined;
46 |
47 | return (
48 |
54 | {node.classDef.typeParams.length > 0 ? (
55 |
56 | {"<"}
57 |
61 | {">"}
62 |
63 | ) : null}
64 | {node.classDef.extends ? (
65 | <>
66 | {" "}
67 | extends {" "}
68 |
69 | {node.classDef.superTypeParams.length > 0 ? (
70 |
71 | {"<"}
72 | {node.classDef.superTypeParams
73 | .map((tsType) => (
74 |
75 | ))
76 | .reduce((r, a) => (
77 | <>
78 | {r}, {a}
79 | >
80 | ))}
81 | {">"}
82 |
83 | ) : null}
84 | >
85 | ) : null}
86 | {node.classDef.implements.length ? (
87 | <>
88 | {" "}
89 | implements {" "}
90 | {node.classDef.implements
91 | .map((_implements) => (
92 |
93 | ))
94 | .reduce((r, a) => (
95 | <>
96 | {r}, {a}
97 | >
98 | ))}
99 | >
100 | ) : null}
101 | >
102 | }
103 | details={
104 | <>
105 | {constructors.length > 0 ? (
106 |
107 |
108 | Constructors
109 |
110 | {constructors.map((node) => {
111 | return (
112 |
116 | );
117 | })}
118 |
119 | ) : null}
120 | {realProperties.length > 0 ? (
121 |
122 |
123 | Properties
124 |
125 | {realProperties.map((node) => {
126 | return (
127 |
137 | );
138 | })}
139 |
140 | ) : null}
141 | {realMethods.length > 0 ? (
142 |
143 |
144 | Methods
145 |
146 | {realMethods.map((node) => {
147 | return (
148 |
163 | );
164 | })}
165 |
166 | ) : null}
167 | {indexSignatures.length > 0 ? (
168 |
169 |
170 | Index Signatures
171 |
172 | {indexSignatures.map((node) => {
173 | return (
174 |
180 | );
181 | })}
182 |
183 | ) : null}
184 | {staticProperties.length > 0 ? (
185 |
186 |
187 | Static Properties
188 |
189 | {staticProperties.map((node) => {
190 | return (
191 |
201 | );
202 | })}
203 |
204 | ) : null}
205 | {staticMethods.length > 0 ? (
206 |
207 |
208 | Static Methods
209 |
210 | {staticMethods.map((node) => {
211 | return (
212 |
227 | );
228 | })}
229 |
230 | ) : null}
231 | >
232 | }
233 | />
234 | );
235 | }
236 |
237 | export function TypeParams({
238 | params,
239 | scope,
240 | }: {
241 | params: TsTypeParamDef[];
242 | scope: string[];
243 | }) {
244 | return (
245 | <>
246 | {params
247 | .map((p) => {
248 | return (
249 | <>
250 | {p.name}
251 | {p.constraint ? (
252 | <>
253 | {" "}
254 | extends
255 | >
256 | ) : null}
257 | {p.default ? (
258 | <>
259 | {" "}
260 | =
261 | >
262 | ) : null}
263 | >
264 | );
265 | })
266 | .reduce((r, a) => (
267 | <>
268 | {r}, {a}
269 | >
270 | ))}
271 | >
272 | );
273 | }
274 |
--------------------------------------------------------------------------------
/components/TsType.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React, { memo } from "react";
4 | import Link from "next/link";
5 | import {
6 | TsTypeDef,
7 | TsTypeDefKind,
8 | LiteralDefKind,
9 | getLinkByScopedName,
10 | } from "../util/docs";
11 | import { useFlattend, useRuntimeBuiltins } from "../util/data";
12 | import { Params } from "./Function";
13 |
14 | export const TsType = memo(
15 | ({ tsType, scope }: { tsType: TsTypeDef; scope: string[] }) => {
16 | switch (tsType.kind) {
17 | case TsTypeDefKind.Array:
18 | return (
19 | <>
20 |
21 | []
22 | >
23 | );
24 | case TsTypeDefKind.Conditional:
25 | return (
26 | <>
27 | {" "}
28 | extends{" "}
29 | {" "}
30 | ? {" "}
31 | :
32 | >
33 | );
34 | case TsTypeDefKind.FnOrConstructor: {
35 | return (
36 | <>
37 | {tsType.fnOrConstructor.constructor ? "new " : null} (
38 | ) {"=> "}
42 |
43 | >
44 | );
45 | }
46 | case TsTypeDefKind.IndexedAccess:
47 | return (
48 | <>
49 | [
50 | ]
51 | >
52 | );
53 | case TsTypeDefKind.Intersection: {
54 | const elements: React.ReactNode[] = [];
55 | tsType.intersection.forEach((tsType) =>
56 | elements.push( , " & ")
57 | );
58 | elements.pop();
59 | return <>{elements}>;
60 | }
61 | case TsTypeDefKind.Keyword:
62 | return <>{tsType.keyword}>;
63 | case TsTypeDefKind.Literal:
64 | switch (tsType.literal.kind) {
65 | case LiteralDefKind.Number:
66 | return <>{tsType.literal.number}>;
67 | case LiteralDefKind.String:
68 | return <>"{tsType.literal.string}">;
69 | case LiteralDefKind.Boolean:
70 | return <>{tsType.literal.boolean ? "true" : "false"}>;
71 | }
72 | case TsTypeDefKind.Optional:
73 | return (
74 | <>
75 | ?
76 | >
77 | );
78 | case TsTypeDefKind.Parenthesized:
79 | return (
80 | <>
81 | ( )
82 | >
83 | );
84 | case TsTypeDefKind.Rest:
85 | return (
86 | <>
87 | ...
88 |
89 | >
90 | );
91 | case TsTypeDefKind.This:
92 | return <>this>;
93 | case TsTypeDefKind.Tuple:
94 | const elements: React.ReactNode[] = [];
95 | tsType.tuple.forEach((tsType) =>
96 | elements.push( , ", ")
97 | );
98 | elements.pop();
99 | return <>[{elements}]>;
100 | case TsTypeDefKind.TypeLiteral: {
101 | const final: React.ReactNode[] = [];
102 | tsType.typeLiteral.callSignatures.forEach((callSignature) => {
103 | final.push(
104 | <>
105 | ( )
106 | {callSignature.tsType ? (
107 | <>
108 | :{" "}
109 |
110 | >
111 | ) : null}
112 | >,
113 | ", "
114 | );
115 | });
116 | tsType.typeLiteral.methods.forEach((method) => {
117 | final.push(
118 | <>
119 | {method.name}( )
120 | {method.returnType ? (
121 | <>
122 | :
123 | >
124 | ) : null}
125 | >,
126 | ", "
127 | );
128 | });
129 | tsType.typeLiteral.properties.forEach((property) => {
130 | final.push(
131 | <>
132 | {property.name}
133 | {property.tsType ? (
134 | <>
135 | :
136 | >
137 | ) : null}
138 | >,
139 | ", "
140 | );
141 | });
142 | tsType.typeLiteral.indexSignatures.forEach((indexSignature) => {
143 | final.push(
144 | <>
145 | {indexSignature.readonly && (
146 |
147 | readonly{" "}
148 |
149 | )}
150 |
151 | {indexSignature.tsType ? (
152 | <>
153 | :{" "}
154 |
155 | >
156 | ) : null}
157 | >,
158 | ", "
159 | );
160 | });
161 |
162 | final.pop();
163 | return (
164 | <>
165 | {"{ "}
166 | {final}
167 | {" }"}
168 | >
169 | );
170 | }
171 | case TsTypeDefKind.TypeOperator:
172 | return (
173 | <>
174 | {tsType.typeOperator.operator}{" "}
175 |
176 | >
177 | );
178 | case TsTypeDefKind.TypePredicate: {
179 | const predicate = tsType.typePredicate;
180 | const paramRepr = predicate.param.type === "this"
181 | ? "this"
182 | : predicate.param.name;
183 | if (predicate.type === null) {
184 | if (predicate.asserts) {
185 | return (
186 | <>
187 | asserts {paramRepr}
188 | >
189 | );
190 | } else {
191 | // unreachable - type predicate must have either `asserts` or `is`
192 | return null;
193 | }
194 | }
195 | return (
196 | <>
197 | {predicate.asserts ? "asserts " : ""}
198 | {paramRepr} is
199 | >
200 | );
201 | }
202 | case TsTypeDefKind.TypeQuery: {
203 | const flattend = useFlattend();
204 | const runtimeBuiltins = useRuntimeBuiltins();
205 | const link = getLinkByScopedName(
206 | flattend,
207 | runtimeBuiltins,
208 | tsType.typeQuery,
209 | scope ?? []
210 | );
211 | return (
212 | <>
213 | typeof
214 | >
215 | );
216 | }
217 | case TsTypeDefKind.TypeRef: {
218 | const flattend = useFlattend();
219 | const runtimeBuiltins = useRuntimeBuiltins();
220 | const link = getLinkByScopedName(
221 | flattend,
222 | runtimeBuiltins,
223 | tsType.typeRef.typeName,
224 | scope ?? [],
225 | "type"
226 | );
227 | const paramElements: React.ReactNode[] = [];
228 | (tsType.typeRef.typeParams ?? []).forEach((tsType) =>
229 | paramElements.push( , ", ")
230 | );
231 | paramElements.pop();
232 | return (
233 | <>
234 |
235 | {tsType.typeRef.typeParams ? (
236 |
237 | {"<"}
238 | {paramElements}
239 | {">"}
240 |
241 | ) : null}
242 | >
243 | );
244 | }
245 | case TsTypeDefKind.Union: {
246 | const elements: React.ReactNode[] = [];
247 | tsType.union.forEach((tsType, i) =>
248 | elements.push( , " | ")
249 | );
250 | elements.pop();
251 | return <>{elements}>;
252 | }
253 | default:
254 | return <>_notimpl_>;
255 | }
256 | }
257 | );
258 |
259 | export function LinkRef(props: {
260 | link: ReturnType;
261 | name: string;
262 | }) {
263 | switch (props.link?.type) {
264 | case "local":
265 | case "external":
266 | return (
267 |
268 | {props.name}
269 |
270 | );
271 | case "builtin":
272 | return (
273 |
274 | {props.name}
275 |
276 | );
277 | case "remote":
278 | const url = props.link.remote;
279 | if (url.startsWith("https://")) {
280 | return (
281 |
287 | {props.name}
288 |
289 | );
290 | }
291 | default:
292 | return <>{props.name}>;
293 | }
294 | }
295 |
--------------------------------------------------------------------------------
/components/Wrapper.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React, { useState } from "react";
4 | import Link from "next/link";
5 | import { Sidebar } from "./Sidebar";
6 | import Transition from "./Transition";
7 | import { GroupedNodes } from "../util/docs";
8 |
9 | // TODO(lucacasonato): not have this use absolute positioning - make this less terrible CSS
10 | export function Wrapper(props: {
11 | children: React.ReactNode;
12 | forceReload: () => void;
13 | entrypoint: string;
14 | timestamp: string;
15 | groups: GroupedNodes | undefined;
16 | }) {
17 | const [showSidebar, setShowSidebar] = useState(false);
18 | const hideSidebar = () => setShowSidebar(false);
19 |
20 | return (
21 |
22 |
23 |
24 |
25 |
33 |
39 |
40 |
48 |
49 |
50 |
56 |
62 |
68 |
69 |
70 |
71 |
108 | {props.groups ?
: null}
109 |
110 |
111 |
112 | {/**/}
113 |
114 |
115 |
116 |
117 |
118 |
119 |
151 | {props.groups ?
: null}
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 | {/*
164 |
165 | Search
166 |
167 |
188 |
*/}
189 |
190 |
191 |
setShowSidebar(true)}
195 | >
196 |
202 |
208 |
209 |
210 |
211 |
212 |
216 | {props.children}
217 |
218 |
219 |
220 | );
221 | }
222 |
--------------------------------------------------------------------------------
/components/SinglePage.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import React, { useMemo, memo } from "react";
4 | import {
5 | DocsData,
6 | FlattendProvider,
7 | RuntimeBuiltinsProvider,
8 | } from "../util/data";
9 | import {
10 | DocNodeShared,
11 | ParamDef,
12 | TsTypeDef,
13 | DocNodeLocation,
14 | expandNamespaces,
15 | flattenNamespaces,
16 | GroupedNodes,
17 | groupNodes,
18 | sortByAlphabet,
19 | normalizeFilename,
20 | } from "../util/docs";
21 | import { JSDoc } from "./JSDoc";
22 | import { ClassCard } from "./Class";
23 | import { TsType } from "./TsType";
24 | import { FunctionCard, Params } from "./Function";
25 | import { EnumCard } from "./Enum";
26 | import { InterfaceCard } from "./Interface";
27 | import { VariableCard } from "./Variable";
28 | import { TypeAliasCard } from "./TypeAlias";
29 | import { Wrapper } from "./Wrapper";
30 | import { NamespaceCard } from "./Namespace";
31 | import { Loading } from "./Loading";
32 |
33 | export const SinglePage = memo(
34 | (props: {
35 | forceReload: () => void;
36 | entrypoint: string;
37 | data: DocsData | undefined;
38 | runtimeBuiltinsData: DocsData | undefined;
39 | }) => {
40 | if (!props.data) {
41 | return (
42 |
48 |
49 |
50 |
51 | It can take a few seconds for documentation to be generated.
52 |
53 |
54 |
55 | );
56 | }
57 |
58 | const nodes = expandNamespaces(props.data.nodes ?? []);
59 | const runtimeBuiltinsNodes = props.runtimeBuiltinsData
60 | ? expandNamespaces(props.runtimeBuiltinsData.nodes)
61 | : undefined;
62 |
63 | const hasNone = nodes.length === 0;
64 |
65 | const flattend = flattenNamespaces(nodes);
66 | const flattendRuntimeBuiltins = runtimeBuiltinsNodes
67 | ? flattenNamespaces(runtimeBuiltinsNodes)
68 | : undefined;
69 |
70 | const groups = useMemo(() => groupNodes(sortByAlphabet(flattend)), [
71 | flattend,
72 | ]);
73 |
74 | return (
75 |
76 |
77 |
83 |
84 |
85 |
89 | {props.entrypoint}
90 |
91 | {hasNone ? (
92 |
93 | This module has no exports that are recognized by deno doc.
94 |
95 | ) : (
96 |
97 | )}
98 |
99 |
100 |
101 |
102 |
103 | );
104 | }
105 | );
106 |
107 | export const CardList = memo(
108 | ({ groups, nested }: { groups: GroupedNodes; nested?: boolean }) => {
109 | return (
110 | <>
111 | {groups.functions.length > 0 ? (
112 |
113 | {!nested && (
114 |
115 | Functions
116 |
117 | )}
118 |
119 | {groups.functions.map((node, i) => (
120 |
125 | ))}
126 |
127 |
128 | ) : null}
129 | {groups.variables.length > 0 ? (
130 |
131 | {!nested && (
132 |
133 | Variables
134 |
135 | )}
136 |
137 | {groups.variables.map((node, i) => (
138 |
143 | ))}
144 |
145 |
146 | ) : null}
147 | {groups.classes.length > 0 ? (
148 |
149 | {!nested && (
150 |
151 | Classes
152 |
153 | )}
154 |
155 | {groups.classes.map((node, i) => (
156 |
161 | ))}
162 |
163 |
164 | ) : null}
165 | {groups.enums.length > 0 ? (
166 |
167 | {!nested && (
168 |
169 | Enums
170 |
171 | )}
172 |
173 | {groups.enums.map((node, i) => (
174 |
179 | ))}
180 |
181 |
182 | ) : null}
183 | {groups.interfaces.length > 0 ? (
184 |
185 | {!nested && (
186 |
187 | Interfaces
188 |
189 | )}
190 |
191 | {groups.interfaces.map((node, i) => (
192 |
197 | ))}
198 |
199 |
200 | ) : null}
201 | {groups.typeAliases.length > 0 ? (
202 |
203 | {!nested && (
204 |
205 | Type Aliases
206 |
207 | )}
208 |
209 | {groups.typeAliases.map((node, i) => (
210 |
215 | ))}
216 |
217 |
218 | ) : null}
219 | {groups.namespaces.length > 0 ? (
220 |
221 | {!nested && (
222 |
223 | Namespaces
224 |
225 | )}
226 |
227 | {groups.namespaces.map((node, i) => (
228 |
233 | ))}
234 |
235 |
236 | ) : null}
237 | >
238 | );
239 | }
240 | );
241 |
242 | export function SimpleCard({
243 | node,
244 | prefix,
245 | details,
246 | suffix,
247 | params,
248 | returnType,
249 | nested,
250 | }: {
251 | node: DocNodeShared & { kind?: string };
252 | prefix?: string;
253 | details?: React.ReactNode;
254 | suffix?: React.ReactNode;
255 | params?: ParamDef[];
256 | returnType?: TsTypeDef;
257 | nested: boolean;
258 | }) {
259 | const id = (node.scope ?? []).concat(node.name).join(".");
260 | return (
261 |
268 |
269 |
270 | {prefix ?
{prefix} : null}
271 | {node.scope?.map((s, i) => (
272 | <>
273 |
277 | {s}
278 |
279 | .
280 | >
281 | ))}
282 |
283 | {node.name}
284 |
285 | {params ? (
286 |
287 | ( )
288 |
289 | ) : null}
290 | {returnType ? (
291 |
292 | {": "}
293 |
294 |
295 | ) : null}
296 | {suffix}
297 |
298 |
306 | [src]
307 |
308 |
309 |
310 | {node.jsDoc ? (
311 |
312 |
313 |
314 | ) : null}
315 |
316 | {details}
317 |
318 | );
319 | }
320 |
321 | export function SimpleSubCard({
322 | node,
323 | prefix,
324 | optional,
325 | computedParams,
326 | params,
327 | returnType,
328 | }: {
329 | node: Omit & {
330 | kind?: string;
331 | location?: DocNodeLocation;
332 | inherited?: boolean;
333 | };
334 | prefix?: string;
335 | optional?: boolean;
336 | computedParams?: ParamDef[];
337 | params?: ParamDef[];
338 | returnType?: TsTypeDef;
339 | }) {
340 | return (
341 |
344 |
345 |
351 | {node.inherited ? (
352 |
inherited
353 | ) : null}
354 | {prefix ?
{prefix} : null}
355 | {node.name}
356 | {optional ? "?" : ""}
357 | {computedParams ? (
358 | <>
359 | [
]
360 | >
361 | ) : null}
362 | {params ? (
363 |
364 | ( )
365 |
366 | ) : null}
367 | {returnType ? (
368 |
369 | {": "}
370 |
371 |
372 | ) : null}
373 |
374 | {node.location ? (
375 |
383 | [src]
384 |
385 | ) : null}
386 |
387 | {node.jsDoc ? (
388 |
389 |
390 |
391 | ) : null}
392 |
393 | );
394 | }
395 |
--------------------------------------------------------------------------------
/util/docs.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020 the Deno authors. All rights reserved. MIT license.
2 |
3 | import { schoolBook } from "react-syntax-highlighter/dist/esm/styles/hljs";
4 |
5 | export enum DocNodeKind {
6 | Function = "function",
7 | Variable = "variable",
8 | Class = "class",
9 | Enum = "enum",
10 | Interface = "interface",
11 | TypeAlias = "typeAlias",
12 | Namespace = "namespace",
13 | Import = "import",
14 | }
15 | export interface DocNodeLocation {
16 | filename: string;
17 | line: number;
18 | col: number;
19 | }
20 | export interface DocNodeShared {
21 | name: string;
22 | scope?: string[];
23 | location: DocNodeLocation;
24 | jsDoc?: string;
25 | }
26 | export interface TsTypeParamDef {
27 | name: string;
28 | constraint?: TsTypeDef;
29 | default?: TsTypeDef;
30 | }
31 | export interface TsTypeRefDef {
32 | typeName: string;
33 | typeParams?: TsTypeDef[];
34 | }
35 | export interface TsTypeOperatorDef {
36 | operator: string;
37 | tsType: TsTypeDef;
38 | }
39 | export interface TsFnOrConstructorDef {
40 | constructor: boolean;
41 | tsType: TsTypeDef;
42 | params: ParamDef[];
43 | }
44 | export interface TsConditionalDef {
45 | checkType: TsTypeDef;
46 | extendsType: TsTypeDef;
47 | trueType: TsTypeDef;
48 | falseType: TsTypeDef;
49 | }
50 | export interface TsIndexedAccessDef {
51 | readonly: boolean;
52 | objType: TsTypeDef;
53 | indexType: TsTypeDef;
54 | }
55 | export interface TsTypeLiteralDef {
56 | methods: LiteralMethodDef[];
57 | properties: LiteralPropertyDef[];
58 | callSignatures: LiteralCallSignatureDef[];
59 | indexSignatures: LiteralIndexSignatureDef[];
60 | }
61 | export interface TsTypePredicateDef {
62 | asserts: boolean;
63 | param: {
64 | type: "this";
65 | } | {
66 | type: "identifier";
67 | name: string;
68 | };
69 | type: TsTypeDef | null;
70 | }
71 | export interface LiteralMethodDef {
72 | name: string;
73 | params: ParamDef[];
74 | returnType?: TsTypeDef;
75 | }
76 | export interface LiteralPropertyDef {
77 | name: string;
78 | computed: boolean;
79 | optional: boolean;
80 | tsType?: TsTypeDef;
81 | }
82 | export interface LiteralCallSignatureDef {
83 | params: ParamDef[];
84 | tsType?: TsTypeDef;
85 | }
86 | export interface LiteralIndexSignatureDef {
87 | readonly: boolean;
88 | params: ParamDef[];
89 | tsType?: TsTypeDef;
90 | }
91 | export interface LiteralMethodDef {
92 | params: ParamDef[];
93 | returnType?: TsTypeDef;
94 | }
95 | export enum LiteralDefKind {
96 | Number = "number",
97 | String = "string",
98 | Boolean = "boolean",
99 | }
100 | export type LiteralDef =
101 | | {
102 | kind: LiteralDefKind.Number;
103 | number: number;
104 | }
105 | | {
106 | kind: LiteralDefKind.String;
107 | string: string;
108 | }
109 | | {
110 | kind: LiteralDefKind.Boolean;
111 | boolean: boolean;
112 | };
113 | export enum TsTypeDefKind {
114 | Keyword = "keyword",
115 | Literal = "literal",
116 | TypeRef = "typeRef",
117 | Union = "union",
118 | Intersection = "intersection",
119 | Array = "array",
120 | Tuple = "tuple",
121 | TypeOperator = "typeOperator",
122 | Parenthesized = "parenthesized",
123 | Rest = "rest",
124 | Optional = "optional",
125 | TypeQuery = "typeQuery",
126 | This = "this",
127 | FnOrConstructor = "fnOrConstructor",
128 | Conditional = "conditional",
129 | IndexedAccess = "indexedAccess",
130 | TypeLiteral = "typeLiteral",
131 | TypePredicate = "typePredicate",
132 | }
133 | export interface TsTypeDefShared {
134 | repr: string;
135 | }
136 | export interface TsTypeDefArray extends TsTypeDefShared {
137 | kind: TsTypeDefKind.Array;
138 | array: TsTypeDef;
139 | }
140 | export interface TsTypeDefConditional extends TsTypeDefShared {
141 | kind: TsTypeDefKind.Conditional;
142 | conditionalType: TsConditionalDef;
143 | }
144 | export interface TsTypeDefFnOrConstructor extends TsTypeDefShared {
145 | kind: TsTypeDefKind.FnOrConstructor;
146 | fnOrConstructor: TsFnOrConstructorDef;
147 | }
148 | export interface TsTypeDefIndexedAccess extends TsTypeDefShared {
149 | kind: TsTypeDefKind.IndexedAccess;
150 | indexedAccess: TsIndexedAccessDef;
151 | }
152 | export interface TsTypeDefIntersection extends TsTypeDefShared {
153 | kind: TsTypeDefKind.Intersection;
154 | intersection: TsTypeDef[];
155 | }
156 | export interface TsTypeDefKeyword extends TsTypeDefShared {
157 | kind: TsTypeDefKind.Keyword;
158 | keyword: string;
159 | }
160 | export interface TsTypeDefLiteral extends TsTypeDefShared {
161 | kind: TsTypeDefKind.Literal;
162 | literal: LiteralDef;
163 | }
164 | export interface TsTypeDefOptional extends TsTypeDefShared {
165 | kind: TsTypeDefKind.Optional;
166 | optional: TsTypeDef;
167 | }
168 | export interface TsTypeDefParenthesized extends TsTypeDefShared {
169 | kind: TsTypeDefKind.Parenthesized;
170 | parenthesized: TsTypeDef;
171 | }
172 | export interface TsTypeDefTypePredicate extends TsTypeDefShared {
173 | kind: TsTypeDefKind.TypePredicate;
174 | typePredicate: TsTypePredicateDef;
175 | }
176 | export interface TsTypeDefRest extends TsTypeDefShared {
177 | kind: TsTypeDefKind.Rest;
178 | rest: TsTypeDef;
179 | }
180 | export interface TsTypeDefThis extends TsTypeDefShared {
181 | kind: TsTypeDefKind.This;
182 | this: boolean;
183 | }
184 | export interface TsTypeDefTuple extends TsTypeDefShared {
185 | kind: TsTypeDefKind.Tuple;
186 | tuple: TsTypeDef[];
187 | }
188 | export interface TsTypeDefTypeLiteral extends TsTypeDefShared {
189 | kind: TsTypeDefKind.TypeLiteral;
190 | typeLiteral: TsTypeLiteralDef;
191 | }
192 | export interface TsTypeDefTypeOperator extends TsTypeDefShared {
193 | kind: TsTypeDefKind.TypeOperator;
194 | typeOperator: TsTypeOperatorDef;
195 | }
196 | export interface TsTypeDefTypeQuery extends TsTypeDefShared {
197 | kind: TsTypeDefKind.TypeQuery;
198 | typeQuery: string;
199 | }
200 | export interface TsTypeDefTypeRef extends TsTypeDefShared {
201 | kind: TsTypeDefKind.TypeRef;
202 | typeRef: TsTypeRefDef;
203 | }
204 | export interface TsTypeDefUnion extends TsTypeDefShared {
205 | kind: TsTypeDefKind.Union;
206 | union: TsTypeDef[];
207 | }
208 | export type TsTypeDef =
209 | | TsTypeDefArray
210 | | TsTypeDefConditional
211 | | TsTypeDefFnOrConstructor
212 | | TsTypeDefIndexedAccess
213 | | TsTypeDefIntersection
214 | | TsTypeDefKeyword
215 | | TsTypeDefLiteral
216 | | TsTypeDefOptional
217 | | TsTypeDefParenthesized
218 | | TsTypeDefRest
219 | | TsTypeDefThis
220 | | TsTypeDefTuple
221 | | TsTypeDefTypeLiteral
222 | | TsTypeDefTypeOperator
223 | | TsTypeDefTypePredicate
224 | | TsTypeDefTypeQuery
225 | | TsTypeDefTypeRef
226 | | TsTypeDefUnion;
227 |
228 | export type ParamDef =
229 | | {
230 | kind: "array";
231 | elements: (ParamDef | null)[];
232 | optional: boolean;
233 | tsType?: TsTypeDef;
234 | }
235 | | {
236 | kind: "assign";
237 | left: ParamDef;
238 | right: string;
239 | tsType?: TsTypeDef;
240 | }
241 | | {
242 | kind: "identifier";
243 | name: string;
244 | optional: boolean;
245 | tsType?: TsTypeDef;
246 | }
247 | | {
248 | kind: "object";
249 | props: ObjectPatPropDef[];
250 | optional: boolean;
251 | tsType?: TsTypeDef;
252 | }
253 | | {
254 | kind: "rest";
255 | arg: ParamDef;
256 | tsType?: TsTypeDef;
257 | };
258 | export type ObjectPatPropDef =
259 | | {
260 | kind: "assign";
261 | key: string;
262 | value?: string;
263 | }
264 | | {
265 | kind: "keyValue";
266 | key: string;
267 | value: ParamDef;
268 | }
269 | | {
270 | kind: "rest";
271 | arg: ParamDef;
272 | };
273 | export interface FunctionDef {
274 | params: ParamDef[];
275 | returnType?: TsTypeDef;
276 | isAsync: boolean;
277 | isGenerator: boolean;
278 | }
279 | export interface VariableDef {
280 | tsType: TsTypeDef;
281 | kind: "var" | "let" | "const";
282 | }
283 | export type Accessibility = "public" | "protected" | "private";
284 | export interface ClassConstructorDef extends DocNodeShared {
285 | accessibility?: Accessibility;
286 | params: ParamDef[];
287 | }
288 | export interface ClassPropertyDef extends DocNodeShared {
289 | tsType: TsTypeDef;
290 | readonly: boolean;
291 | accessibility?: Accessibility;
292 | optional: boolean;
293 | isAbstract: boolean;
294 | isStatic: boolean;
295 | }
296 | export interface ClassMethodDef extends DocNodeShared {
297 | accessibility?: Accessibility;
298 | optional: boolean;
299 | isAbstract: boolean;
300 | isStatic: boolean;
301 | kind: "method" | "getter" | "setter";
302 | functionDef: FunctionDef;
303 | }
304 | export interface ClassDef {
305 | isAbstract: boolean;
306 | constructors: ClassConstructorDef[];
307 | properties: ClassPropertyDef[];
308 | indexSignatures: ClassIndexSignatureDef[];
309 | methods: ClassMethodDef[];
310 | extends?: string;
311 | implements: TsTypeDef[];
312 | typeParams: TsTypeParamDef[];
313 | superTypeParams: TsTypeDef[];
314 | }
315 | export interface ClassIndexSignatureDef {
316 | readonly: boolean;
317 | params: ParamDef[];
318 | tsType?: TsTypeDef;
319 | }
320 | export interface EnumMemberDef {
321 | name: string;
322 | }
323 | export interface EnumDef {
324 | members: EnumMemberDef[];
325 | }
326 |
327 | export interface InterfaceMethodDef extends DocNodeShared {
328 | params: ParamDef[];
329 | optional: boolean;
330 | returnType?: TsTypeDef;
331 | }
332 |
333 | export interface InterfacePropertyDef extends DocNodeShared {
334 | computed: boolean;
335 | optional: boolean;
336 | tsType?: TsTypeDef;
337 | }
338 |
339 | export interface InterfaceCallSignatureDef extends Omit {
340 | params: ParamDef[];
341 | tsType?: TsTypeDef;
342 | }
343 |
344 | export interface InterfaceDef {
345 | extends: TsTypeDef[];
346 | methods: InterfaceMethodDef[];
347 | properties: InterfacePropertyDef[];
348 | callSignatures: InterfaceCallSignatureDef[];
349 | indexSignatures: InterfaceIndexSignatureDef[];
350 | typeParams: TsTypeParamDef[];
351 | }
352 | export interface InterfaceIndexSignatureDef {
353 | readonly: boolean;
354 | params: ParamDef[];
355 | tsType?: TsTypeDef;
356 | }
357 | export interface TypeAliasDef {
358 | tsType: TsTypeDef;
359 | }
360 | export interface NamespaceDef {
361 | elements: DocNode[];
362 | }
363 | export interface ImportDef {
364 | src: string;
365 | local: string;
366 | imported?: string;
367 | }
368 |
369 | export type DocNodeFunction = DocNodeShared & {
370 | kind: DocNodeKind.Function;
371 | functionDef: FunctionDef;
372 | };
373 | export type DocNodeVariable = DocNodeShared & {
374 | kind: DocNodeKind.Variable;
375 | variableDef: VariableDef;
376 | };
377 | export type DocNodeClass = DocNodeShared & {
378 | kind: DocNodeKind.Class;
379 | classDef: ClassDef;
380 | };
381 | export type DocNodeEnum = DocNodeShared & {
382 | kind: DocNodeKind.Enum;
383 | enumDef: EnumDef;
384 | };
385 | export type DocNodeInterface = DocNodeShared & {
386 | kind: DocNodeKind.Interface;
387 | interfaceDef: InterfaceDef;
388 | };
389 | export type DocNodeTypeAlias = DocNodeShared & {
390 | kind: DocNodeKind.TypeAlias;
391 | typeAliasDef: TypeAliasDef;
392 | };
393 | export type DocNodeNamespace = DocNodeShared & {
394 | kind: DocNodeKind.Namespace;
395 | namespaceDef: NamespaceDef;
396 | };
397 | export type DocNodeImport = DocNodeShared & {
398 | kind: DocNodeKind.Import;
399 | importDef: ImportDef;
400 | };
401 |
402 | export type DocNode =
403 | | DocNodeFunction
404 | | DocNodeVariable
405 | | DocNodeClass
406 | | DocNodeEnum
407 | | DocNodeInterface
408 | | DocNodeTypeAlias
409 | | DocNodeNamespace
410 | | DocNodeImport;
411 |
412 | export interface GroupedNodes {
413 | functions: DocNodeFunction[];
414 | variables: DocNodeVariable[];
415 | classes: DocNodeClass[];
416 | enums: DocNodeEnum[];
417 | interfaces: DocNodeInterface[];
418 | typeAliases: DocNodeTypeAlias[];
419 | namespaces: DocNodeNamespace[];
420 | }
421 |
422 | export function expandNamespaces(docs: DocNode[]): DocNode[] {
423 | return docs.flatMap((parent): any => {
424 | if (parent.kind === DocNodeKind.Namespace) {
425 | const scope = Array.isArray(parent.scope)
426 | ? [...parent.scope, parent.name]
427 | : [parent.name];
428 | return [
429 | {
430 | ...parent,
431 | namespaceDef: {
432 | elements: expandNamespaces(
433 | parent.namespaceDef.elements.map((el) => ({
434 | ...el,
435 | scope: scope,
436 | })),
437 | ),
438 | },
439 | },
440 | ];
441 | } else {
442 | return [parent];
443 | }
444 | });
445 | }
446 |
447 | export function flattenNamespaces(docs: DocNode[]): DocNode[] {
448 | return docs.flatMap((parent): any => {
449 | if (parent.kind === DocNodeKind.Namespace) {
450 | return [parent, ...flattenNamespaces(parent.namespaceDef.elements)];
451 | } else {
452 | return [parent];
453 | }
454 | });
455 | }
456 |
457 | function nodeName(a: DocNode): string {
458 | return (a.scope ? a.scope.join(".") + "." : "") + a.name;
459 | }
460 |
461 | export function sortByAlphabet(docs: DocNode[]): DocNode[] {
462 | return docs.sort((a, b) => {
463 | const scopeCountA = a.scope?.length ?? 0;
464 | const scopeCountB = b.scope?.length ?? 0;
465 | if (scopeCountA !== scopeCountB) {
466 | return scopeCountA - scopeCountB;
467 | }
468 | return (nodeName(a) < nodeName(b) ? -1 : 1);
469 | });
470 | }
471 |
472 | export function groupNodes(docs: DocNode[]): GroupedNodes {
473 | const groupedNodes: GroupedNodes = {
474 | functions: [],
475 | variables: [],
476 | classes: [],
477 | enums: [],
478 | interfaces: [],
479 | typeAliases: [],
480 | namespaces: [],
481 | };
482 |
483 | docs.forEach((node) => {
484 | switch (node.kind) {
485 | case DocNodeKind.Function:
486 | groupedNodes.functions.push(node);
487 | break;
488 | case DocNodeKind.Variable:
489 | groupedNodes.variables.push(node);
490 | break;
491 | case DocNodeKind.Class:
492 | groupedNodes.classes.push(node);
493 | break;
494 | case DocNodeKind.Enum:
495 | groupedNodes.enums.push(node);
496 | break;
497 | case DocNodeKind.Interface:
498 | groupedNodes.interfaces.push(node);
499 | break;
500 | case DocNodeKind.TypeAlias:
501 | groupedNodes.typeAliases.push(node);
502 | break;
503 | case DocNodeKind.Namespace:
504 | groupedNodes.namespaces.push(node);
505 | break;
506 | case DocNodeKind.Import:
507 | break;
508 | }
509 | });
510 |
511 | return groupedNodes;
512 | }
513 |
514 | function findNodeByScopedName(
515 | flattend: DocNode[],
516 | name: string,
517 | initialScope: string[],
518 | mustBe?: "type" | "class",
519 | ): DocNode | undefined {
520 | const scope = [...initialScope];
521 | let done = false;
522 | while (!done) {
523 | const node = flattend.find(
524 | (node) =>
525 | // Name + scope must match (if not import)
526 | node.kind !== DocNodeKind.Import &&
527 | (node.scope && node.scope?.length > 0
528 | ? node.scope.join(".") + "."
529 | : "") +
530 | node.name ===
531 | (scope.length > 0 ? scope.join(".") + "." : "") + name &&
532 | // Must be a type, or class, or any. Dependant on settings
533 | ((mustBe === "type" &&
534 | (node.kind === DocNodeKind.Class ||
535 | node.kind === DocNodeKind.Enum ||
536 | node.kind === DocNodeKind.Interface ||
537 | node.kind === DocNodeKind.TypeAlias ||
538 | node.kind === DocNodeKind.Namespace)) ||
539 | (mustBe === "class" && node.kind === DocNodeKind.Class) ||
540 | mustBe === undefined),
541 | );
542 | if (node) return node;
543 | if (scope.length === 0) {
544 | const import_ = flattend.find(
545 | (node) =>
546 | node.kind === DocNodeKind.Import &&
547 | (name + ".").startsWith(node.name + "."),
548 | );
549 | if (import_) return import_;
550 | done = true;
551 | }
552 | scope.pop();
553 | }
554 | return undefined;
555 | }
556 |
557 | function globalObjectMDN(name: string): { [name: string]: string } {
558 | return {
559 | [name]:
560 | `https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/${name}`,
561 | };
562 | }
563 |
564 | const MDN_BUILTINS: { [builtin: string]: string } = {
565 | ...globalObjectMDN("Object"),
566 | ...globalObjectMDN("Function"),
567 | ...globalObjectMDN("Boolean"),
568 | ...globalObjectMDN("Error"),
569 | ...globalObjectMDN("TypeError"),
570 | ...globalObjectMDN("Number"),
571 | ...globalObjectMDN("BigInt"),
572 | ...globalObjectMDN("Math"),
573 | ...globalObjectMDN("Date"),
574 | ...globalObjectMDN("String"),
575 | ...globalObjectMDN("RegExp"),
576 | ...globalObjectMDN("Array"),
577 | ...globalObjectMDN("Int8Array"),
578 | ...globalObjectMDN("Uint8Array"),
579 | ...globalObjectMDN("Uint8ClampedArray"),
580 | ...globalObjectMDN("Int16Array"),
581 | ...globalObjectMDN("Uint16Array"),
582 | ...globalObjectMDN("Int32Array"),
583 | ...globalObjectMDN("Uint32Array"),
584 | ...globalObjectMDN("Float32Array"),
585 | ...globalObjectMDN("Float64Array"),
586 | ...globalObjectMDN("BigInt64Array"),
587 | ...globalObjectMDN("BigUint64Array"),
588 | ...globalObjectMDN("Map"),
589 | ...globalObjectMDN("Set"),
590 | ...globalObjectMDN("WeakMap"),
591 | ...globalObjectMDN("WeakSet"),
592 | ...globalObjectMDN("ArrayBuffer"),
593 | ...globalObjectMDN("SharedArrayBuffer"),
594 | ...globalObjectMDN("Atomics"),
595 | ...globalObjectMDN("DataView"),
596 | ...globalObjectMDN("JSON"),
597 | ...globalObjectMDN("Promise"),
598 | ...globalObjectMDN("Generator"),
599 | ...globalObjectMDN("GeneratorFunction"),
600 | ...globalObjectMDN("AsyncFunction"),
601 | ...globalObjectMDN("Reflect"),
602 | ...globalObjectMDN("Proxy"),
603 | ...globalObjectMDN("Intl"),
604 | };
605 |
606 | export function getLinkByScopedName(
607 | flattend: DocNode[],
608 | runtimeBuiltins: DocNode[] | undefined,
609 | name: string,
610 | initialScope: string[],
611 | mustBe?: "type" | "class",
612 | ):
613 | | { type: "local"; href: string }
614 | | { type: "remote"; remote: string; node: string }
615 | | { type: "builtin"; href: string }
616 | | { type: "external"; href: string }
617 | | undefined {
618 | const node = findNodeByScopedName(flattend, name, initialScope, mustBe);
619 | if (node) {
620 | if (node.kind === DocNodeKind.Import) {
621 | if (node.importDef.imported) {
622 | return {
623 | type: "remote",
624 | remote: node.importDef.src,
625 | node: node.importDef.imported ?? node.name,
626 | };
627 | } else {
628 | return {
629 | type: "remote",
630 | remote: node.importDef.src,
631 | node: name.substring(node.name.length),
632 | };
633 | }
634 | }
635 | return {
636 | type: "local",
637 | href: `#${node.scope ? node.scope.join(".") + "." : ""}${node.name}`,
638 | };
639 | }
640 | if (runtimeBuiltins) {
641 | const node = findNodeByScopedName(
642 | runtimeBuiltins,
643 | name,
644 | [],
645 | mustBe,
646 | );
647 | if (node) {
648 | return {
649 | type: "builtin",
650 | href: `#${node.scope ? node.scope.join(".") + "." : ""}${node.name}`,
651 | };
652 | }
653 | }
654 | const builtin = MDN_BUILTINS[name];
655 | if (builtin) {
656 | return {
657 | type: "external",
658 | href: builtin,
659 | };
660 | }
661 | return undefined;
662 | }
663 |
664 | export function getFieldsForClassRecursive(
665 | flattend: DocNode[],
666 | parent: DocNodeClass,
667 | ): {
668 | methods: (ClassMethodDef & { inherited: boolean })[];
669 | properties: (ClassPropertyDef & { inherited: boolean })[];
670 | } {
671 | if (parent.classDef.extends) {
672 | const node = findNodeByScopedName(
673 | flattend,
674 | parent.classDef.extends,
675 | parent.scope ?? [],
676 | "class",
677 | ) as DocNodeClass;
678 | if (node) {
679 | const r = getFieldsForClassRecursive(flattend, node);
680 | return {
681 | methods: [
682 | ...parent.classDef.methods.map((method) => ({
683 | ...method,
684 | inherited: false,
685 | })),
686 | ...r.methods.map((method) => ({
687 | ...method,
688 | inherited: true,
689 | })),
690 | ],
691 | properties: [
692 | ...parent.classDef.properties.map((property) => ({
693 | ...property,
694 | inherited: false,
695 | })),
696 | ...r.properties.map((property) => ({
697 | ...property,
698 | inherited: true,
699 | })),
700 | ],
701 | };
702 | }
703 | }
704 |
705 | return {
706 | methods: parent.classDef.methods.map((method) => ({
707 | ...method,
708 | inherited: false,
709 | })),
710 | properties: parent.classDef.properties.map((property) => ({
711 | ...property,
712 | inherited: false,
713 | })),
714 | };
715 | }
716 |
717 | export function normalizeFilename(filename: string): string {
718 | const rawRegex = /(github\.com\/.+\/.+\/|gitlab\.com\/.+\/.+\/-\/)raw/
719 | const usercontentRegex = /raw\.githubusercontent\.com\/([^\/]+\/[^\/]+)/
720 | if (filename.match(rawRegex)) {
721 | return filename.replace(rawRegex, "$1blob")
722 | }
723 |
724 | if (filename.match(usercontentRegex)) {
725 | return filename.replace(usercontentRegex, "github.com/$1/blob")
726 | }
727 |
728 | return filename
729 | }
730 |
731 |
--------------------------------------------------------------------------------