├── .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 |
13 |
404 - Page not found
14 | 15 | Go back home 16 | 17 |
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 | denodenodocdoc -------------------------------------------------------------------------------- /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 found
Back 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 | 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 |
47 | 51 | 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 |
76 |
{title}
77 |
 78 |           {details}
 79 |         
80 | 81 | Go back home 82 | 83 | 87 | Report Issue 88 | 89 |
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 | 53 | 54 | 55 | 58 |
59 |
60 | 63 | setUrl(e.target.value)} 70 | onKeyDown={(e) => { 71 | if (e.key === "Enter" && url.length > 0) navigate(); 72 | }} 73 | /> 74 |
75 | 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 | deno doc badge 84 |
85 | HTML 86 | deno doc`} 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 | 112 | ); 113 | 114 | export default Footer; 115 | -------------------------------------------------------------------------------- /components/Loading.tsx: -------------------------------------------------------------------------------- 1 | export const Loading = () => ( 2 | 8 | 9 | 10 | 11 | 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 |
12 | 90 | 91 | 100 |
101 |
102 |
103 |
104 | 105 | 106 | 111 |
112 |
113 | deno doc 114 |
115 |
116 | Documentation Generator 117 |
118 |
119 |
120 | {" "} 121 |
122 | 141 |
142 |
143 | 162 |
163 |
164 |
165 |
166 |
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 |
34 |
38 |
39 |
40 | 48 |
49 |
50 | 70 |
71 |
72 | 73 | 74 | logo 79 |
80 |
81 | deno doc 82 |
83 |
84 |
85 | 86 | {props.groups ? ( 87 |
88 | {props.timestamp ? ( 89 |
90 | Last refreshed{" "} 91 | {new Date(props.timestamp).toLocaleString()}.{" "} 92 | 96 | Refresh now 97 | 98 |
99 | ) : null} 100 |

101 | 102 | About doc.deno.land 103 | 104 |

105 |
106 | ) : null} 107 |
108 | {props.groups ? : null} 109 |
110 |
111 |
112 | {/**/} 113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | 121 | 122 | logo 123 |
124 |
125 | deno doc 126 |
127 |
128 |
129 | 130 | {props.groups ? ( 131 |
132 | {props.timestamp ? ( 133 |
134 | Last refreshed {new Date(props.timestamp).toLocaleString()}.{" "} 135 | 139 | Refresh now 140 | 141 |
142 | ) : null} 143 |

144 | 145 | About doc.deno.land 146 | 147 |

148 |
149 | ) : null} 150 |
151 | {props.groups ? : null} 152 |
153 |
154 |
155 |
156 | 157 | 158 | logo 159 | 160 | 161 |
162 |
163 | {/*
164 | 167 |
168 |
169 | 174 | 179 | 180 |
181 | 187 |
188 |
*/} 189 |
190 |
191 | 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 | --------------------------------------------------------------------------------