├── .editorconfig ├── .github ├── assets │ └── example.png ├── dependabot.yml └── workflows │ ├── publish.yml │ ├── test.yml │ └── update.yml ├── .gitignore ├── .npmignore ├── .nvmrc ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── example ├── .gitignore ├── README.md ├── babel.config.cjs ├── blog │ ├── 2019-05-28-hola.md │ ├── 2019-05-29-hello-world.md │ └── 2019-05-30-welcome.md ├── docs │ ├── doc1.md │ ├── doc2.md │ ├── doc3.md │ └── mdx.md ├── docusaurus.config.js ├── package-lock.json ├── package.json ├── sidebars.js ├── src │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.js │ │ └── styles.module.css └── static │ ├── .nojekyll │ └── img │ ├── favicon.ico │ ├── logo.svg │ ├── undraw_docusaurus_mountain.svg │ ├── undraw_docusaurus_react.svg │ └── undraw_docusaurus_tree.svg ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── cjs │ ├── index.ts │ └── package.json ├── client │ ├── index.ts │ └── useCodeblockThemeConfig.ts ├── index.ts ├── theme-github-codeblock.d.ts ├── theme │ ├── CodeBlock │ │ └── index.tsx │ ├── ReferenceCodeBlock │ │ ├── RunmeLink.tsx │ │ ├── constants.ts │ │ ├── index.tsx │ │ └── utils.ts │ └── types.ts ├── types.d.ts └── types │ └── @theme-init.d.ts ├── tests ├── ReferenceCodeBlock.test.ts ├── __mocks__ │ ├── @docusaurus │ │ ├── BrowserOnly.ts │ │ └── useDocusaurusContext.ts │ ├── @theme-init │ │ └── CodeBlock.ts │ ├── docusaurus-theme-github-codeblock │ │ └── client.ts │ └── react.ts └── __snapshots__ │ └── ReferenceCodeBlock.test.ts.snap ├── tsconfig.cjs.json └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | indent_style = space 10 | indent_size = 4 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | 17 | [{*.json,.eslintrc.js,*.yml}] 18 | indent_size = 2 19 | -------------------------------------------------------------------------------- /.github/assets/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christian-bromann/docusaurus-theme-github-codeblock/5d12bbcf912981c3253cb8d97395c36023124649/.github/assets/example.png -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Manual NPM Publish 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | releaseType: 7 | description: "Release Type" 8 | required: true 9 | type: choice 10 | default: "patch" 11 | options: 12 | - patch 13 | - minor 14 | - major 15 | 16 | env: 17 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 18 | GITHUB_TOKEN: ${{ secrets.PAT }} 19 | 20 | jobs: 21 | publish: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Clone Repository 25 | uses: actions/checkout@v3 26 | - name: Setup Node version 27 | uses: actions/setup-node@v3 28 | with: 29 | node-version: 18 30 | - name: Install dependencies 31 | run: npm ci 32 | - name: Run tests 33 | run: npm test 34 | - name: Build package 35 | run: npm run build 36 | - name: NPM Setup 37 | run: | 38 | npm set registry "https://registry.npmjs.org/" 39 | npm set //registry.npmjs.org/:_authToken $NPM_TOKEN 40 | npm whoami 41 | - name: Release 42 | run: | 43 | git config --global user.name "christian-bromann" 44 | git config --global user.email "git@bromann.dev" 45 | npm run release -- ${{github.event.inputs.releaseType}} 46 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test Changes 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Clone Repository 10 | uses: actions/checkout@v3 11 | - name: Setup Node version 12 | uses: actions/setup-node@v3 13 | with: 14 | node-version: 18 15 | - name: Install dependencies 16 | run: npm ci 17 | - run: npm run build 18 | - name: Run tests 19 | run: npm test 20 | -------------------------------------------------------------------------------- /.github/workflows/update.yml: -------------------------------------------------------------------------------- 1 | # this workflow merges requests from Dependabot if tests are passing 2 | # ref https://docs.github.com/en/code-security/dependabot/working-with-dependabot/automating-dependabot-with-github-actions 3 | # and https://github.com/dependabot/fetch-metadata 4 | name: Auto-merge 5 | 6 | # `pull_request_target` means this uses code in the base branch, not the PR. 7 | on: pull_request_target 8 | 9 | # Dependabot PRs' tokens have read permissions by default and thus we must enable write permissions. 10 | permissions: 11 | contents: write 12 | pull-requests: write 13 | 14 | jobs: 15 | dependencies: 16 | runs-on: ubuntu-latest 17 | if: github.actor == 'dependabot[bot]' 18 | 19 | steps: 20 | - name: Fetch PR metadata 21 | id: metadata 22 | uses: dependabot/fetch-metadata@v1.3.5 23 | with: 24 | github-token: ${{ secrets.GITHUB_TOKEN }} 25 | 26 | - name: Wait for PR CI 27 | # Don't merge updates to GitHub Actions versions automatically. 28 | # (Some repos may wish to limit by version range (major/minor/patch), or scope (dep vs dev-dep), too.) 29 | if: contains(steps.metadata.outputs.package-ecosystem, 'npm') 30 | uses: lewagon/wait-on-check-action@v1.2.0 31 | with: 32 | ref: ${{ github.event.pull_request.head.sha }} 33 | repo-token: ${{ secrets.GITHUB_TOKEN }} 34 | wait-interval: 30 # seconds 35 | running-workflow-name: dependencies # wait for all checks except this one 36 | allowed-conclusions: success # all other checks must pass, being skipped or cancelled is not sufficient 37 | 38 | - name: Auto-merge dependabot PRs 39 | # Don't merge updates to GitHub Actions versions automatically. 40 | # (Some repos may wish to limit by version range (major/minor/patch), or scope (dep vs dev-dep), too.) 41 | if: contains(steps.metadata.outputs.package-ecosystem, 'npm') 42 | env: 43 | PR_URL: ${{ github.event.pull_request.html_url }} 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | # The "auto" flag will only merge once all of the target branch's required checks 46 | # are met. Configure those in the "branch protection" settings for each repo. 47 | run: gh pr merge --auto --squash "$PR_URL" 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | build 107 | cjs 108 | !src/cjs 109 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | coverage 3 | node_modules 4 | src 5 | tests 6 | tsconfig.json 7 | tsconfig.cjs.json 8 | .github 9 | .editorconfig 10 | *.tgz 11 | /*.js 12 | CONTRIBUTING.md 13 | .nvmrc 14 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v18.12.1 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to `docusaurus-theme-github-codeblock` 2 | 3 | **Thank you for your interest in `docusaurus-theme-github-codeblock`. Your contributions are highly welcome.** 4 | 5 | There are multiple ways of getting involved: 6 | 7 | - [Report a bug](#report-a-bug) 8 | - [Suggest a feature](#suggest-a-feature) 9 | - [Contribute code](#contribute-code) 10 | 11 | Below are a few guidelines we would like you to follow. 12 | If you need help, please reach out to us by opening an issue. 13 | 14 | ## Report a bug 15 | Reporting bugs is one of the best ways to contribute. Before creating a bug report, please check that an [issue](/issues) reporting the same problem does not already exist. If there is such an issue, you may add your information as a comment. 16 | 17 | To report a new bug you should open an issue that summarizes the bug and set the label to "bug". 18 | 19 | If you want to provide a fix along with your bug report: That is great! In this case please send us a pull request as described in section [Contribute Code](#contribute-code). 20 | 21 | ## Suggest a feature 22 | To request a new feature you should open an [issue](../../issues/new) and summarize the desired functionality and its use case. Set the issue label to "feature". 23 | 24 | ## Contribute code 25 | This is an outline of what the workflow for code contributions looks like 26 | 27 | - Check the list of open [issues](../../issues). Either assign an existing issue to yourself, or 28 | create a new one that you would like work on and discuss your ideas and use cases. 29 | 30 | It is always best to discuss your plans beforehand, to ensure that your contribution is in line with our goals. 31 | 32 | - Fork the repository on GitHub 33 | - Create a topic branch from where you want to base your work. This is usually master. 34 | - Open a new pull request, label it `work in progress` and outline what you will be contributing 35 | - Make commits of logical units. 36 | - Make sure you sign-off on your commits `git commit -s -m "adding X to change Y"` 37 | - Write good commit messages (see below). 38 | - Push your changes to a topic branch in your fork of the repository. 39 | - As you push your changes, update the pull request with new infomation and tasks as you complete them 40 | - Project maintainers might comment on your work as you progress 41 | - When you are done, remove the `work in progess` label and ping the maintainers for a review 42 | - Your pull request must receive a :thumbsup: from two [maintainers](MAINTAINERS) 43 | 44 | Thanks for your contributions! 45 | 46 | ### Commit messages 47 | Your commit messages ideally can answer two questions: what changed and why. The subject line should feature the “what” and the body of the commit should describe the “why”. 48 | 49 | When creating a pull request, its description should reference the corresponding issue id. 50 | 51 | ### Sign your work / Developer certificate of origin 52 | All contributions (including pull requests) must agree to the Developer Certificate of Origin (DCO) version 1.1. This is exactly the same one created and used by the Linux kernel developers and posted on http://developercertificate.org/. This is a developer's certification that he or she has the right to submit the patch for inclusion into the project. Simply submitting a contribution implies this agreement, however, please include a "Signed-off-by" tag in every patch (this tag is a conventional way to confirm that you agree to the DCO) - you can automate this with a [Git hook](https://stackoverflow.com/questions/15015894/git-add-signed-off-by-line-using-format-signoff-not-working) 53 | 54 | ``` 55 | git commit -s -m "adding X to change Y" 56 | ``` 57 | 58 | **Have fun, and happy hacking!** 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Christian Bromann 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Docusaurus Theme GitHub Codeblock ![Test Changes](https://github.com/christian-bromann/docusaurus-theme-github-codeblock/workflows/Test%20Changes/badge.svg?branch=main) 2 | ================================= 3 | 4 | A Docusaurus plugin that supports referencing code examples from public GitHub repositories. 5 | 6 | > Note: this theme plugin supports Docusaurus [v2](https://docusaurus.io/docs/2.x) and [v3](https://docusaurus.io/docs). 7 | 8 | ## Install 9 | 10 | First, add the theme plugin to your dependencies: 11 | 12 | ```sh 13 | npm install docusaurus-theme-github-codeblock 14 | ``` 15 | 16 | ## Usage 17 | 18 | Add the theme plugin to your list of themes in the `docusaurus.config.js`: 19 | 20 | ```js 21 | // ... 22 | themes: [ 23 | 'docusaurus-theme-github-codeblock' 24 | ], 25 | // ... 26 | themeConfig: { 27 | // github codeblock theme configuration 28 | codeblock: { 29 | showGithubLink: true, 30 | githubLinkLabel: 'View on GitHub', 31 | showRunmeLink: false, 32 | runmeLinkLabel: 'Checkout via Runme' 33 | }, 34 | // ... 35 | } 36 | // ... 37 | ``` 38 | 39 | To reference GitHub snippets in your markdown, create code blocks with a `reference` attached to the language meta string and put the link to your GitHub reference in the code block, e.g.: 40 | 41 | ```js reference 42 | https://github.com/christian-bromann/docusaurus-theme-github-codeblock/blob/main/src/theme/ReferenceCodeBlock/index.tsx#L105-L108 43 | ``` 44 | 45 | You can also set a custom title: 46 | 47 | ```js reference title="Example" 48 | https://github.com/christian-bromann/docusaurus-theme-github-codeblock/blob/main/src/theme/ReferenceCodeBlock/index.tsx#L105-L108 49 | ``` 50 | 51 | The plugin will download the code and display the desired lines: 52 | 53 | ![Plugin Example](https://github.com/christian-bromann/docusaurus-theme-github-codeblock/raw/main/.github/assets/example.png 'Plugin Example') 54 | 55 | ### Runme Support 56 | 57 | In addition to providing a link to the GitHub source, you can also enable a [Runme](https://runme.dev) link to allow users to easily check-out the example markdown file with [VS Code](https://code.visualstudio.com/) and run the code reference locally. To enable support, set `showRunmeLink` to `true` in your Docusaurus `themeConfig`. 58 | 59 | By default the Runme link is generated based on the repository and it will checkout a `README.md` in the same directory as the file. For example using the example above, Runme will checkout the repository `christian-bromann/docusaurus-theme-github-codeblock` and the file `src/theme/ReferenceCodeBlock/README.md`. 60 | 61 | If the markdown file you like the user to check-out is located in a different repository or path, you can define the `repository` and `fileToOpen` param of [Runme link](https://stateful.com/blog/runme-blog-launcher) manually via, e.g.: 62 | 63 | ```js reference runmeRepository="git@github.com:christian-bromann/docusaurus-theme-github-codeblock.git" runmeFileToOpen="CONTRIBUTING.md" 64 | https://github.com/christian-bromann/docusaurus-theme-github-codeblock/blob/main/src/theme/ReferenceCodeBlock/index.tsx#L105-L115 65 | ``` 66 | 67 | In case you have `showRunmeLink` set for all code references, if you prefer to clone the reference using a Git HTTPS url, add `useHTTPS` to the frontmatter: 68 | 69 | ```js reference useHTTPS 70 | https://github.com/christian-bromann/docusaurus-theme-github-codeblock/blob/main/src/theme/ReferenceCodeBlock/index.tsx#L105-L108 71 | ``` 72 | 73 | Learn more about Runme in the [project docs](https://runme.dev/docs/intro). 74 | 75 | ## Options 76 | 77 | This Docusaurus theme has the following options: 78 | 79 | ### `showGithubLink` 80 | 81 | If set to `true` the link to the GitHub source of the reference is provided. 82 | 83 | __Type:__ `boolean`
84 | __Default:__ `true` 85 | 86 | ### `githubLinkLabel` 87 | 88 | Link text for GitHub link. 89 | 90 | __Type:__ `string`
91 | __Default:__ `View on GitHub` 92 | 93 | ### `showRunmeLink` 94 | 95 | If set to `true`, a [Runme](https://runme.dev) link is provided. This property will be automatically set to `false` if a mobile environment is detected given these environment don't support the `vscode://` url schema. 96 | 97 | __Type:__ `boolean`
98 | __Default:__ `true` 99 | 100 | ### `runmeLinkLabel` 101 | 102 | Link text for [Runme](https://runme.dev) link. 103 | 104 | __Type:__ `string`
105 | __Default:__ `Checkout via Runme` 106 | 107 | --- 108 | 109 | If you are interested in contributing to this project, see [CONTRIBUTING.md](CONTRIBUTING.md). 110 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 4 | 5 | ## Installation 6 | 7 | ```console 8 | yarn install 9 | ``` 10 | 11 | ## Local Development 12 | 13 | ```console 14 | yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ## Build 20 | 21 | ```console 22 | yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ## Deployment 28 | 29 | ```console 30 | GIT_USER= USE_SSH=true yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /example/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /example/blog/2019-05-28-hola.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: hola 3 | title: Hola 4 | author: Gao Wei 5 | author_title: Docusaurus Core Team 6 | author_url: https://github.com/wgao19 7 | author_image_url: https://avatars1.githubusercontent.com/u/2055384?v=4 8 | tags: [hola, docusaurus] 9 | --- 10 | 11 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 12 | -------------------------------------------------------------------------------- /example/blog/2019-05-29-hello-world.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: hello-world 3 | title: Hello 4 | author: Endilie Yacop Sucipto 5 | author_title: Maintainer of Docusaurus 6 | author_url: https://github.com/endiliey 7 | author_image_url: https://avatars1.githubusercontent.com/u/17883920?s=460&v=4 8 | tags: [hello, docusaurus] 9 | --- 10 | 11 | Welcome to this blog. This blog is created with [**Docusaurus 2 alpha**](https://v2.docusaurus.io/). 12 | 13 | 14 | 15 | This is a test post. 16 | 17 | A whole bunch of other information. 18 | -------------------------------------------------------------------------------- /example/blog/2019-05-30-welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: welcome 3 | title: Welcome 4 | author: Yangshun Tay 5 | author_title: Front End Engineer @ Facebook 6 | author_url: https://github.com/yangshun 7 | author_image_url: https://avatars0.githubusercontent.com/u/1315101?s=400&v=4 8 | tags: [facebook, hello, docusaurus] 9 | --- 10 | 11 | Blog features are powered by the blog plugin. Simply add files to the `blog` directory. It supports tags as well! 12 | 13 | Delete the whole directory if you don't want the blog features. As simple as that! 14 | -------------------------------------------------------------------------------- /example/docs/doc1.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: doc1 3 | title: Style Guide 4 | sidebar_label: Style Guide 5 | slug: / 6 | --- 7 | 8 | This theme provides the following: 9 | 10 | ```js reference runmeRepository="git@github.com:christian-bromann/docusaurus-theme-github-codeblock.git" runmeFileToOpen="CONTRIBUTING.md" 11 | https://github.com/webdriverio/example-recipes/blob/main/click/example.js#L14-L18 12 | ``` 13 | 14 | ```js reference runmeFileToOpen="https://gist.githubusercontent.com/christian-bromann/df97ce3dace21564ffdf1900400ec099/raw/0a9b29c979d61e17032c855b04dbc4f5b962f847/ThankYou.md" title="Custom Title" 15 | https://github.com/webdriverio/example-recipes/blob/main/click/example.js#L114-L182 16 | ``` 17 | 18 | ```js reference 19 | https://github.com/webdriverio/example-recipes/blob/main/click/example.js#L14-L18 20 | ``` 21 | 22 | You can write content using [GitHub-flavored Markdown syntax](https://github.github.com/gfm/). 23 | 24 | ## Markdown Syntax 25 | 26 | To serve as an example page when styling markdown based Docusaurus sites. 27 | 28 | ## Headers 29 | 30 | # H1 - Create the best documentation 31 | 32 | ## H2 - Create the best documentation 33 | 34 | ### H3 - Create the best documentation 35 | 36 | #### H4 - Create the best documentation 37 | 38 | ##### H5 - Create the best documentation 39 | 40 | ###### H6 - Create the best documentation 41 | 42 | --- 43 | 44 | ## Emphasis 45 | 46 | Emphasis, aka italics, with *asterisks* or _underscores_. 47 | 48 | Strong emphasis, aka bold, with **asterisks** or __underscores__. 49 | 50 | Combined emphasis with **asterisks and _underscores_**. 51 | 52 | Strikethrough uses two tildes. ~~Scratch this.~~ 53 | 54 | --- 55 | 56 | ## Lists 57 | 58 | 1. First ordered list item 59 | 1. Another item 60 | - Unordered sub-list. 61 | 1. Actual numbers don't matter, just that it's a number 62 | 1. Ordered sub-list 63 | 1. And another item. 64 | 65 | * Unordered list can use asterisks 66 | 67 | - Or minuses 68 | 69 | + Or pluses 70 | 71 | --- 72 | 73 | ## Links 74 | 75 | [I'm an inline-style link](https://www.google.com/) 76 | 77 | [I'm an inline-style link with title](https://www.google.com/ "Google's Homepage") 78 | 79 | [I'm a reference-style link][arbitrary case-insensitive reference text] 80 | 81 | [You can use numbers for reference-style link definitions][1] 82 | 83 | Or leave it empty and use the [link text itself]. 84 | 85 | URLs and URLs in angle brackets will automatically get turned into links. http://www.example.com/ and sometimes example.com (but not on GitHub, for example). 86 | 87 | Some text to show that the reference links can follow later. 88 | 89 | [arbitrary case-insensitive reference text]: https://www.mozilla.org/ 90 | [1]: http://slashdot.org/ 91 | [link text itself]: http://www.reddit.com/ 92 | 93 | --- 94 | 95 | ## Images 96 | 97 | Here's our logo (hover to see the title text): 98 | 99 | Inline-style: ![alt text](https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png 'Logo Title Text 1') 100 | 101 | Reference-style: ![alt text][logo] 102 | 103 | [logo]: https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png 'Logo Title Text 2' 104 | 105 | Images from any folder can be used by providing path to file. Path should be relative to markdown file. 106 | 107 | ![img](../static/img/logo.svg) 108 | 109 | --- 110 | 111 | ## Code 112 | 113 | ```javascript 114 | var s = 'JavaScript syntax highlighting'; 115 | alert(s); 116 | ``` 117 | 118 | ```python 119 | s = "Python syntax highlighting" 120 | print(s) 121 | ``` 122 | 123 | ``` 124 | No language indicated, so no syntax highlighting. 125 | But let's throw in a tag. 126 | ``` 127 | 128 | ```js {2} 129 | function highlightMe() { 130 | console.log('This line can be highlighted!'); 131 | } 132 | ``` 133 | 134 | --- 135 | 136 | ## Tables 137 | 138 | Colons can be used to align columns. 139 | 140 | | Tables | Are | Cool | 141 | | ------------- | :-----------: | -----: | 142 | | col 3 is | right-aligned | \$1600 | 143 | | col 2 is | centered | \$12 | 144 | | zebra stripes | are neat | \$1 | 145 | 146 | There must be at least 3 dashes separating each header cell. The outer pipes (|) are optional, and you don't need to make the raw Markdown line up prettily. You can also use inline Markdown. 147 | 148 | | Markdown | Less | Pretty | 149 | | -------- | --------- | ---------- | 150 | | _Still_ | `renders` | **nicely** | 151 | | 1 | 2 | 3 | 152 | 153 | --- 154 | 155 | ## Blockquotes 156 | 157 | > Blockquotes are very handy in email to emulate reply text. This line is part of the same quote. 158 | 159 | Quote break. 160 | 161 | > This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can _put_ **Markdown** into a blockquote. 162 | 163 | --- 164 | 165 | ## Inline HTML 166 | 167 |
168 |
Definition list
169 |
Is something people use sometimes.
170 | 171 |
Markdown in HTML
172 |
Does *not* work **very** well. Use HTML tags.
173 |
174 | 175 | --- 176 | 177 | ## Line Breaks 178 | 179 | Here's a line for us to start with. 180 | 181 | This line is separated from the one above by two newlines, so it will be a _separate paragraph_. 182 | 183 | This line is also a separate paragraph, but... This line is only separated by a single newline, so it's a separate line in the _same paragraph_. 184 | 185 | --- 186 | 187 | ## Admonitions 188 | 189 | :::note 190 | 191 | This is a note 192 | 193 | ::: 194 | 195 | :::tip 196 | 197 | This is a tip 198 | 199 | ::: 200 | 201 | :::important 202 | 203 | This is important 204 | 205 | ::: 206 | 207 | :::caution 208 | 209 | This is a caution 210 | 211 | ::: 212 | 213 | :::warning 214 | 215 | This is a warning 216 | 217 | ::: 218 | -------------------------------------------------------------------------------- /example/docs/doc2.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: doc2 3 | title: Document Number 2 4 | --- 5 | 6 | This is a link to [another document.](doc3.md) This is a link to an [external page.](http://www.example.com/) 7 | -------------------------------------------------------------------------------- /example/docs/doc3.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: doc3 3 | title: This is Document Number 3 4 | --- 5 | 6 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac euismod odio, eu consequat dui. Nullam molestie consectetur risus id imperdiet. Proin sodales ornare turpis, non mollis massa ultricies id. Nam at nibh scelerisque, feugiat ante non, dapibus tortor. Vivamus volutpat diam quis tellus elementum bibendum. Praesent semper gravida velit quis aliquam. Etiam in cursus neque. Nam lectus ligula, malesuada et mauris a, bibendum faucibus mi. Phasellus ut interdum felis. Phasellus in odio pulvinar, porttitor urna eget, fringilla lectus. Aliquam sollicitudin est eros. Mauris consectetur quam vitae mauris interdum hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 7 | 8 | Duis et egestas libero, imperdiet faucibus ipsum. Sed posuere eget urna vel feugiat. Vivamus a arcu sagittis, fermentum urna dapibus, congue lectus. Fusce vulputate porttitor nisl, ac cursus elit volutpat vitae. Nullam vitae ipsum egestas, convallis quam non, porta nibh. Morbi gravida erat nec neque bibendum, eu pellentesque velit posuere. Fusce aliquam erat eu massa eleifend tristique. 9 | 10 | Sed consequat sollicitudin ipsum eget tempus. Integer a aliquet velit. In justo nibh, pellentesque non suscipit eget, gravida vel lacus. Donec odio ante, malesuada in massa quis, pharetra tristique ligula. Donec eros est, tristique eget finibus quis, semper non nisl. Vivamus et elit nec enim ornare placerat. Sed posuere odio a elit cursus sagittis. 11 | 12 | Phasellus feugiat purus eu tortor ultrices finibus. Ut libero nibh, lobortis et libero nec, dapibus posuere eros. Sed sagittis euismod justo at consectetur. Nulla finibus libero placerat, cursus sapien at, eleifend ligula. Vivamus elit nisl, hendrerit ac nibh eu, ultrices tempus dui. Nam tellus neque, commodo non rhoncus eu, gravida in risus. Nullam id iaculis tortor. 13 | 14 | Nullam at odio in sem varius tempor sit amet vel lorem. Etiam eu hendrerit nisl. Fusce nibh mauris, vulputate sit amet ex vitae, congue rhoncus nisl. Sed eget tellus purus. Nullam tempus commodo erat ut tristique. Cras accumsan massa sit amet justo consequat eleifend. Integer scelerisque vitae tellus id consectetur. 15 | -------------------------------------------------------------------------------- /example/docs/mdx.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: mdx 3 | title: Powered by MDX 4 | --- 5 | 6 | You can write JSX and use React components within your Markdown thanks to [MDX](https://mdxjs.com/). 7 | 8 | export const Highlight = ({children, color}) => ( {children} ); 14 | 15 | Docusaurus green and Facebook blue are my favorite colors. 16 | 17 | I can write **Markdown** alongside my _JSX_! 18 | -------------------------------------------------------------------------------- /example/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | import path from 'node:path'; 2 | import { themes as prismThemes } from 'prism-react-renderer'; 3 | 4 | /** @type {import('@docusaurus/types').Config} */ 5 | const config = { 6 | title: 'My Site', 7 | tagline: 'The tagline of my site', 8 | url: 'https://your-docusaurus-test-site.com', 9 | baseUrl: '/', 10 | onBrokenLinks: 'throw', 11 | favicon: 'img/favicon.ico', 12 | organizationName: 'facebook', // Usually your GitHub org/user name. 13 | projectName: 'docusaurus', // Usually your repo name. 14 | themes: [ 15 | path.resolve(__dirname, '..', 'build', 'index.js') 16 | ], 17 | // Even if you don't use internationalization, you can use this field to set 18 | // useful metadata like html lang. For example, if your site is Chinese, you 19 | // may want to replace "en" with "zh-Hans". 20 | i18n: { 21 | defaultLocale: 'en', 22 | locales: ['en'], 23 | }, 24 | themeConfig: { 25 | codeblock: { 26 | showRunmeLink: true 27 | }, 28 | prism: { 29 | theme: prismThemes.github, 30 | darkTheme: prismThemes.dracula, 31 | }, 32 | navbar: { 33 | title: 'My Site', 34 | logo: { 35 | alt: 'My Site Logo', 36 | src: 'img/logo.svg', 37 | }, 38 | items: [ 39 | { 40 | to: 'docs/', 41 | activeBasePath: 'docs', 42 | label: 'Docs', 43 | position: 'left', 44 | }, 45 | {to: 'blog', label: 'Blog', position: 'left'}, 46 | { 47 | href: 'https://github.com/facebook/docusaurus', 48 | label: 'GitHub', 49 | position: 'right', 50 | }, 51 | ], 52 | }, 53 | footer: { 54 | style: 'dark', 55 | links: [ 56 | { 57 | title: 'Docs', 58 | items: [ 59 | { 60 | label: 'Style Guide', 61 | to: 'docs/', 62 | }, 63 | { 64 | label: 'Second Doc', 65 | to: 'docs/doc2/', 66 | }, 67 | ], 68 | }, 69 | { 70 | title: 'Community', 71 | items: [ 72 | { 73 | label: 'Stack Overflow', 74 | href: 'https://stackoverflow.com/questions/tagged/docusaurus', 75 | }, 76 | { 77 | label: 'Discord', 78 | href: 'https://discordapp.com/invite/docusaurus', 79 | }, 80 | { 81 | label: 'Twitter', 82 | href: 'https://twitter.com/docusaurus', 83 | }, 84 | ], 85 | }, 86 | { 87 | title: 'More', 88 | items: [ 89 | { 90 | label: 'Blog', 91 | to: 'blog', 92 | }, 93 | { 94 | label: 'GitHub', 95 | href: 'https://github.com/facebook/docusaurus', 96 | }, 97 | ], 98 | }, 99 | ], 100 | copyright: `Copyright © ${new Date().getFullYear()} My Project, Inc. Built with Docusaurus.`, 101 | }, 102 | }, 103 | presets: [ 104 | [ 105 | 'classic', 106 | { 107 | docs: { 108 | sidebarPath: './sidebars.js', 109 | // Please change this to your repo. 110 | editUrl: 111 | 'https://github.com/facebook/docusaurus/edit/master/website/', 112 | }, 113 | blog: { 114 | showReadingTime: true, 115 | // Please change this to your repo. 116 | editUrl: 117 | 'https://github.com/facebook/docusaurus/edit/master/website/blog/', 118 | }, 119 | theme: { 120 | customCss: './src/css/custom.css', 121 | }, 122 | }, 123 | ], 124 | ], 125 | }; 126 | 127 | export default config; 128 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "serve": "docusaurus serve" 12 | }, 13 | "dependencies": { 14 | "@docusaurus/core": "^3.0.0", 15 | "@docusaurus/preset-classic": "^3.0.0", 16 | "@mdx-js/react": "^3.0.0", 17 | "clsx": "^2.0.0" 18 | }, 19 | "browserslist": { 20 | "production": [ 21 | ">0.2%", 22 | "not dead", 23 | "not op_mini all" 24 | ], 25 | "development": [ 26 | "last 1 chrome version", 27 | "last 1 firefox version", 28 | "last 1 safari version" 29 | ] 30 | }, 31 | "devDependencies": { 32 | "@docusaurus/module-type-aliases": "^3.0.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /example/sidebars.js: -------------------------------------------------------------------------------- 1 | export default { 2 | someSidebar: { 3 | Docusaurus: ['doc1', 'doc2', 'doc3'], 4 | Features: ['mdx'], 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /example/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * Any CSS included here will be global. The classic template 4 | * bundles Infima by default. Infima is a CSS framework designed to 5 | * work well for content-centric websites. 6 | */ 7 | 8 | /* You can override the default Infima variables here. */ 9 | :root { 10 | --ifm-color-primary: #25c2a0; 11 | --ifm-color-primary-dark: rgb(33, 175, 144); 12 | --ifm-color-primary-darker: rgb(31, 165, 136); 13 | --ifm-color-primary-darkest: rgb(26, 136, 112); 14 | --ifm-color-primary-light: rgb(70, 203, 174); 15 | --ifm-color-primary-lighter: rgb(102, 212, 189); 16 | --ifm-color-primary-lightest: rgb(146, 224, 208); 17 | --ifm-code-font-size: 95%; 18 | } 19 | 20 | .docusaurus-highlight-code-line { 21 | background-color: rgb(72, 77, 91); 22 | display: block; 23 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 24 | padding: 0 var(--ifm-pre-padding); 25 | } 26 | -------------------------------------------------------------------------------- /example/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import clsx from 'clsx'; 3 | import Layout from '@theme/Layout'; 4 | import Link from '@docusaurus/Link'; 5 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 6 | import useBaseUrl from '@docusaurus/useBaseUrl'; 7 | import styles from './styles.module.css'; 8 | 9 | const features = [ 10 | { 11 | title: 'Easy to Use', 12 | imageUrl: 'img/undraw_docusaurus_mountain.svg', 13 | description: ( 14 | <> 15 | Docusaurus was designed from the ground up to be easily installed and 16 | used to get your website up and running quickly. 17 | 18 | ), 19 | }, 20 | { 21 | title: 'Focus on What Matters', 22 | imageUrl: 'img/undraw_docusaurus_tree.svg', 23 | description: ( 24 | <> 25 | Docusaurus lets you focus on your docs, and we'll do the chores. Go 26 | ahead and move your docs into the docs directory. 27 | 28 | ), 29 | }, 30 | { 31 | title: 'Powered by React', 32 | imageUrl: 'img/undraw_docusaurus_react.svg', 33 | description: ( 34 | <> 35 | Extend or customize your website layout by reusing React. Docusaurus can 36 | be extended while reusing the same header and footer. 37 | 38 | ), 39 | }, 40 | ]; 41 | 42 | function Feature({imageUrl, title, description}) { 43 | const imgUrl = useBaseUrl(imageUrl); 44 | return ( 45 |
46 | {imgUrl && ( 47 |
48 | {title} 49 |
50 | )} 51 |

{title}

52 |

{description}

53 |
54 | ); 55 | } 56 | 57 | function Home() { 58 | const context = useDocusaurusContext(); 59 | const {siteConfig = {}} = context; 60 | return ( 61 | 64 |
65 |
66 |

{siteConfig.title}

67 |

{siteConfig.tagline}

68 |
69 | 75 | Get Started 76 | 77 |
78 |
79 |
80 |
81 | {features && features.length > 0 && ( 82 |
83 |
84 |
85 | {features.map((props, idx) => ( 86 | 87 | ))} 88 |
89 |
90 |
91 | )} 92 |
93 |
94 | ); 95 | } 96 | 97 | export default Home; 98 | -------------------------------------------------------------------------------- /example/src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | 3 | /** 4 | * CSS files with the .module.css suffix will be treated as CSS modules 5 | * and scoped locally. 6 | */ 7 | 8 | .heroBanner { 9 | padding: 4rem 0; 10 | text-align: center; 11 | position: relative; 12 | overflow: hidden; 13 | } 14 | 15 | @media screen and (max-width: 966px) { 16 | .heroBanner { 17 | padding: 2rem; 18 | } 19 | } 20 | 21 | .buttons { 22 | display: flex; 23 | align-items: center; 24 | justify-content: center; 25 | } 26 | 27 | .features { 28 | display: flex; 29 | align-items: center; 30 | padding: 2rem 0; 31 | width: 100%; 32 | } 33 | 34 | .featureImage { 35 | height: 200px; 36 | width: 200px; 37 | } 38 | -------------------------------------------------------------------------------- /example/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christian-bromann/docusaurus-theme-github-codeblock/5d12bbcf912981c3253cb8d97395c36023124649/example/static/.nojekyll -------------------------------------------------------------------------------- /example/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christian-bromann/docusaurus-theme-github-codeblock/5d12bbcf912981c3253cb8d97395c36023124649/example/static/img/favicon.ico -------------------------------------------------------------------------------- /example/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/static/img/undraw_docusaurus_mountain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /example/static/img/undraw_docusaurus_react.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /example/static/img/undraw_docusaurus_tree.svg: -------------------------------------------------------------------------------- 1 | docu_tree -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | collectCoverage: true, 4 | testMatch: ['/tests/**/*.test.ts'], 5 | transform: { 6 | '^.+\\.(ts|js|tsx)$': 'ts-jest' 7 | }, 8 | coverageThreshold: { 9 | global: { 10 | branches: 50, 11 | functions: 36, 12 | lines: 59, 13 | statements: 59 14 | } 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docusaurus-theme-github-codeblock", 3 | "version": "2.0.2", 4 | "author": "Christian Bromann ", 5 | "description": "A Docusaurus v2 plugin that supports referencing code examples from public GitHub repositories.", 6 | "license": "MIT", 7 | "directories": { 8 | "example": "example" 9 | }, 10 | "main": "cjs/index.js", 11 | "exports": { 12 | "./client": { 13 | "types": "./build/client/index.d.ts", 14 | "require": "./cjs/client/index.js", 15 | "default": "./build/client/index.js" 16 | }, 17 | ".": { 18 | "types": "./src/theme-github-codeblock.d.ts", 19 | "require": "./cjs/cjs/index.js", 20 | "default": "./build/index.js" 21 | } 22 | }, 23 | "types": "src/theme-github-codeblock.d.ts", 24 | "scripts": { 25 | "build": "run-s clean && run-p build:*", 26 | "build:esm": "tsc", 27 | "build:cjs": "run-s build:cjs:*", 28 | "build:cjs:tsc": "tsc -p ./tsconfig.cjs.json", 29 | "build:cjs:pkg": "cp src/cjs/package.json ./cjs/package.json", 30 | "clean": "rimraf ./build ./cjs ./coverage example/.docusaurus example/build", 31 | "release": "release-it --github.release --ci --npm.skipChecks --no-git.requireCleanWorkingDir", 32 | "test": "jest", 33 | "watch": "tsc --watch" 34 | }, 35 | "repository": { 36 | "type": "git", 37 | "url": "git+https://github.com/christian-bromann/docusaurus-theme-github-codeblock.git" 38 | }, 39 | "keywords": [ 40 | "docusarus" 41 | ], 42 | "bugs": { 43 | "url": "https://github.com/christian-bromann/docusaurus-theme-github-codeblock/issues" 44 | }, 45 | "homepage": "https://github.com/christian-bromann/docusaurus-theme-github-codeblock#readme", 46 | "devDependencies": { 47 | "@types/jest": "^29.5.10", 48 | "@types/node": "^20.10.1", 49 | "@types/react": "^18.2.39", 50 | "jest": "^29.7.0", 51 | "jest-environment-jsdom": "^29.7.0", 52 | "npm-run-all": "^4.1.5", 53 | "release-it": "^17.0.0", 54 | "rimraf": "^5.0.5", 55 | "ts-jest": "^29.1.1", 56 | "typescript": "^5.3.2" 57 | }, 58 | "dependencies": { 59 | "@docusaurus/types": "^3.0.0" 60 | }, 61 | "publishConfig": { 62 | "access": "public" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/cjs/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Christian Bromann 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import path from 'node:path' 9 | 10 | export default () => ({ 11 | name: 'docusaurus-theme-github-codeblock', 12 | 13 | getThemePath() { 14 | return path.resolve(__dirname, '..', './theme') 15 | } 16 | }) 17 | -------------------------------------------------------------------------------- /src/cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "commonjs" 3 | } 4 | -------------------------------------------------------------------------------- /src/client/index.ts: -------------------------------------------------------------------------------- 1 | export { useCodeblockThemeConfig } from './useCodeblockThemeConfig.js' 2 | -------------------------------------------------------------------------------- /src/client/useCodeblockThemeConfig.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 3 | import type { ThemeConfig } from 'docusaurus-theme-github-codeblock'; 4 | 5 | const DEFAULT_THEME_CONFIG: ThemeConfig['codeblock'] = { 6 | showGithubLink: true, 7 | githubLinkLabel: 'View on GitHub', 8 | showRunmeLink: false, 9 | runmeLinkLabel: 'Checkout via Runme' 10 | } 11 | 12 | const THEME_CONFIG_KEY = 'codeblock' 13 | 14 | export function useCodeblockThemeConfig(): ThemeConfig['codeblock'] { 15 | const { 16 | siteConfig: {themeConfig}, 17 | } = useDocusaurusContext(); 18 | return Object.assign(DEFAULT_THEME_CONFIG, themeConfig[THEME_CONFIG_KEY] || {}); 19 | } 20 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Christian Bromann 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import url from 'node:url' 9 | import path from 'node:path' 10 | 11 | const __dirname = path.dirname(url.fileURLToPath(import.meta.url)) 12 | 13 | export default () => ({ 14 | name: 'docusaurus-theme-github-codeblock', 15 | 16 | getThemePath() { 17 | return path.resolve(__dirname, './theme') 18 | } 19 | }) 20 | -------------------------------------------------------------------------------- /src/theme-github-codeblock.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | declare module 'docusaurus-theme-github-codeblock' { 9 | export type ThemeConfig = { 10 | codeblock: { 11 | showGithubLink: boolean 12 | githubLinkLabel: string 13 | showRunmeLink: boolean 14 | runmeLinkLabel: string 15 | } 16 | } 17 | } 18 | 19 | declare module 'docusaurus-theme-github-codeblock/client' { 20 | import type { ThemeConfig } from 'docusaurus-theme-github-codeblock'; 21 | export function useCodeblockThemeConfig(): ThemeConfig['codeblock']; 22 | } 23 | -------------------------------------------------------------------------------- /src/theme/CodeBlock/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | import React from 'react' 9 | import ReferenceCodeBlock from '../ReferenceCodeBlock/index.js' 10 | import CodeBlock from '@theme-init/CodeBlock' 11 | 12 | import type { ReferenceCodeBlockProps } from '../types' 13 | 14 | function hasReferenceMeta(props: ReferenceCodeBlockProps) { 15 | return (props.reference || props.metastring?.split(' ').includes('reference')) 16 | } 17 | 18 | const componentWrapper = (Component: typeof CodeBlock) => { 19 | const WrappedComponent = (props: ReferenceCodeBlockProps) => { 20 | if (hasReferenceMeta(props)) { 21 | return ( 22 | 23 | ); 24 | } 25 | 26 | return 27 | }; 28 | 29 | return WrappedComponent; 30 | }; 31 | 32 | export default componentWrapper(CodeBlock) 33 | -------------------------------------------------------------------------------- /src/theme/ReferenceCodeBlock/RunmeLink.tsx: -------------------------------------------------------------------------------- 1 | import React, { PropsWithChildren } from 'react' 2 | import BrowserOnly from '@docusaurus/BrowserOnly' 3 | import { useCodeblockThemeConfig } from 'docusaurus-theme-github-codeblock/client' 4 | 5 | import { parseReference } from './utils' 6 | import { buttonStyles } from './constants' 7 | 8 | const REGEX_MOBILE_DEVICE = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i 9 | const REGEX_VENDOR = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i 10 | function detectMobile (userAgent: string) { 11 | return REGEX_MOBILE_DEVICE.test(userAgent) || REGEX_VENDOR.test(userAgent.substr(0, 4)) 12 | } 13 | 14 | export interface RunmeLinkProps extends PropsWithChildren { 15 | reference: string 16 | metastring?: string 17 | } 18 | 19 | export function RunmeLink (props: RunmeLinkProps) { 20 | return 21 | {() => } 22 | 23 | } 24 | 25 | function RunmeLinkComponent({ reference, metastring }: RunmeLinkProps) { 26 | const userAgent = ( 27 | navigator.userAgent || 28 | navigator.vendor || 29 | // @ts-expect-error 30 | window.opera 31 | ) 32 | const codeblockConfig = useCodeblockThemeConfig() 33 | const showRunmeButton = !detectMobile(userAgent) && codeblockConfig.showRunmeLink && metastring 34 | 35 | if (!showRunmeButton) { 36 | return null 37 | } 38 | 39 | return ( 40 | 46 | {codeblockConfig.runmeLinkLabel} 47 | 48 | ) 49 | } 50 | 51 | export function getRunmeLink (snippetUrl: string, metastring: string) { 52 | const params = new URLSearchParams({ command: 'setup' }); 53 | const runmeRepositoryMatch = metastring.match(/runmeRepository="(?[^"]*)"/) 54 | const runmeFileToOpenMatch = metastring.match(/runmeFileToOpen="(?[^"]*)"/) 55 | const useHTTPS = metastring.match(/useHTTPS|useHTTPS=(false|true)/) 56 | 57 | if (snippetUrl.endsWith('.md')) { 58 | params.set('fileToOpen', parseReference(snippetUrl).url) 59 | return params.toString() 60 | } 61 | 62 | if (runmeFileToOpenMatch?.groups?.fileToOpen) { 63 | params.set('fileToOpen', runmeFileToOpenMatch.groups.fileToOpen) 64 | 65 | if (runmeRepositoryMatch?.groups?.repository) { 66 | params.set('repository', runmeRepositoryMatch.groups.repository) 67 | } 68 | 69 | return params.toString() 70 | } 71 | 72 | const { org, repo, title } = parseReference(snippetUrl) 73 | const cloneHost = useHTTPS && useHTTPS.input && (useHTTPS.input.includes('useHTTPS=true') || useHTTPS.input.includes(' useHTTPS ') || useHTTPS.input.endsWith('useHTTPS')) 74 | ? 'https://github.com/' 75 | : 'git@github.com:' 76 | params.set('repository', `${cloneHost}${org}/${repo}.git`) 77 | params.set('fileToOpen', title.split('/').slice(0, -1).join('/') + '/README.md') 78 | return params.toString() 79 | } 80 | -------------------------------------------------------------------------------- /src/theme/ReferenceCodeBlock/constants.ts: -------------------------------------------------------------------------------- 1 | export const initialFetchResultState = { 2 | code: 'loading...', 3 | error: null, 4 | loading: null, 5 | } 6 | 7 | export const buttonStyles: React.CSSProperties = { 8 | margin: '0 10px' 9 | } 10 | -------------------------------------------------------------------------------- /src/theme/ReferenceCodeBlock/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useReducer } from 'react' 2 | import CodeBlock from '@theme-init/CodeBlock' 3 | import { useCodeblockThemeConfig } from 'docusaurus-theme-github-codeblock/client' 4 | 5 | import { RunmeLink } from './RunmeLink.js' 6 | import { parseReference, fetchCode, codeReducer } from './utils.js' 7 | import { initialFetchResultState, buttonStyles } from './constants.js' 8 | import type { ReferenceCodeBlockProps } from '../types' 9 | 10 | const buttonBarStyles: React.CSSProperties = { 11 | fontSize: '.9em', 12 | fontWeight: 600, 13 | color: '#0E75DD', 14 | textAlign: 'right', 15 | paddingBottom: '13px', 16 | textDecoration: 'underline' 17 | } 18 | 19 | function ReferenceCode(props: ReferenceCodeBlockProps) { 20 | const [fetchResultState, fetchResultStateDispatcher] = useReducer( 21 | codeReducer, 22 | initialFetchResultState, 23 | ) 24 | 25 | const codeSnippetDetails = parseReference(props.children) 26 | if (fetchResultState.loading !== false) { 27 | fetchCode(codeSnippetDetails, fetchResultStateDispatcher) 28 | } 29 | 30 | const titleMatch = props.metastring?.match(/title="(?[^"]*)"/); 31 | const customProps = { 32 | ...props, 33 | metastring: titleMatch?.groups?.title 34 | ? `${props.metastring} title="${titleMatch?.groups?.title}"` 35 | : `${props.metastring} title="${codeSnippetDetails.title}"`, 36 | children: initialFetchResultState.code, 37 | }; 38 | 39 | const codeblockConfig = useCodeblockThemeConfig() 40 | const showButtons = codeblockConfig.showGithubLink || codeblockConfig.showRunmeLink 41 | return ( 42 | <div className='docusaurus-theme-github-codeblock'> 43 | <CodeBlock {...customProps}>{fetchResultState.code}</CodeBlock> 44 | {showButtons && ( 45 | <div style={buttonBarStyles}> 46 | <RunmeLink 47 | reference={props.children} 48 | metastring={props.metastring} 49 | /> 50 | {codeblockConfig.showGithubLink && ( 51 | <a 52 | href={props.children} 53 | className='githubLink' 54 | style={buttonStyles} 55 | target="_blank" 56 | > 57 | {codeblockConfig.githubLinkLabel} 58 | </a> 59 | )} 60 | </div> 61 | )} 62 | </div> 63 | ); 64 | } 65 | 66 | export default ReferenceCode; 67 | -------------------------------------------------------------------------------- /src/theme/ReferenceCodeBlock/utils.ts: -------------------------------------------------------------------------------- 1 | import { initialFetchResultState } from './constants' 2 | import type { GitHubReference, DispatchMessage } from '../types' 3 | 4 | /** 5 | * parses GitHub reference 6 | * @param {string} ref url to github file 7 | */ 8 | export function parseReference(ref: string): GitHubReference { 9 | const fullUrl = ref.slice(ref.indexOf('https')) 10 | const [url, loc] = fullUrl.split('#') 11 | 12 | /** 13 | * webpack causes failures when it tries to render this page 14 | */ 15 | const [org, repo, blob, branch, ...pathSeg] = new global.URL(url).pathname.split('/').slice(1) 16 | const [fromLine, toLine] = loc 17 | ? loc.split('-').map((lineNr) => parseInt(lineNr.slice(1), 10) - 1) 18 | : [0, Infinity] 19 | 20 | return { 21 | url: `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${pathSeg.join('/')}`, 22 | fromLine, 23 | toLine, 24 | title: pathSeg.join('/'), 25 | org, 26 | repo 27 | } 28 | } 29 | 30 | export async function fetchCode({ url, fromLine, toLine }: GitHubReference, fetchResultStateDispatcher: React.Dispatch<DispatchMessage>) { 31 | let res: Response 32 | 33 | try { 34 | res = await fetch(url) 35 | } catch (err) { 36 | return fetchResultStateDispatcher({ type: 'error', value: err as Error }) 37 | } 38 | 39 | if (res.status !== 200) { 40 | const error = await res.text() 41 | return fetchResultStateDispatcher({ type: 'error', value: error }) 42 | } 43 | 44 | const body = (await res.text()).split('\n').slice(fromLine, (toLine || fromLine) + 1) 45 | const preceedingSpace = body.reduce((prev: number, line: string) => { 46 | if (line.length === 0) { 47 | return prev 48 | } 49 | 50 | const spaces = line.match(/^\s+/) 51 | if (spaces) { 52 | return Math.min(prev, spaces[0].length) 53 | } 54 | 55 | return 0 56 | }, Infinity) 57 | 58 | if (body.length === 0) { 59 | return fetchResultStateDispatcher({ 60 | type: 'error', 61 | value: `Error: No code found at ${url} from line ${fromLine} to line ${toLine}` 62 | }) 63 | } 64 | 65 | return fetchResultStateDispatcher({ 66 | type: 'loaded', 67 | value: body.map((line) => line.slice(preceedingSpace)).join('\n') 68 | }) 69 | } 70 | 71 | export function codeReducer(prevState: any, { type, value }: DispatchMessage) { 72 | switch (type) { 73 | case 'reset': { 74 | return initialFetchResultState; 75 | } 76 | case 'loading': { 77 | return { ...prevState, loading: true }; 78 | } 79 | case 'loaded': { 80 | return { ...prevState, code: value, loading: false }; 81 | } 82 | case 'error': { 83 | return { ...prevState, code: value, loading: false }; 84 | } 85 | default: 86 | return prevState; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/theme/types.ts: -------------------------------------------------------------------------------- 1 | import type { Props } from '@theme-init/CodeBlock' 2 | 3 | export interface GitHubReference { 4 | url: string 5 | fromLine: number 6 | toLine: number 7 | title: string, 8 | org: string, 9 | repo: string 10 | } 11 | 12 | export interface ReferenceCodeBlockProps extends Props { 13 | reference: string 14 | } 15 | 16 | export type DispatchTypes = 'reset' | 'loading' | 'loaded' | 'error' 17 | 18 | export interface DispatchMessage { 19 | type: DispatchTypes 20 | value: string | Error 21 | } 22 | -------------------------------------------------------------------------------- /src/types.d.ts: -------------------------------------------------------------------------------- 1 | /// <reference types="@docusaurus/module-type-aliases" /> 2 | /// <reference types="@docusaurus/theme-common" /> 3 | /// <reference types="@docusaurus/theme-classic" /> 4 | 5 | declare module '@docusaurus/BrowserOnly' { 6 | const FC: React.FC & PropsWithChildren 7 | export default FC 8 | } 9 | -------------------------------------------------------------------------------- /src/types/@theme-init.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@theme-init/CodeBlock' { 2 | export type Props = { 3 | readonly children: string; 4 | readonly className?: string; 5 | readonly metastring?: string; 6 | }; 7 | 8 | const CodeBlock: (props: Props) => JSX.Element; 9 | export default CodeBlock; 10 | } 11 | -------------------------------------------------------------------------------- /tests/ReferenceCodeBlock.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | import { getRunmeLink } from '../src/theme/ReferenceCodeBlock/RunmeLink' 5 | import { parseReference, codeReducer } from '../src/theme/ReferenceCodeBlock/utils' 6 | 7 | const exampleLink = 'https://github.com/christian-bromann/docusaurus-theme-github-codeblock/blob/main/src/theme/ReferenceCodeBlock/index.tsx' 8 | 9 | test('should parse GitHub reference properly', () => { 10 | expect(parseReference(exampleLink)).toMatchSnapshot() 11 | expect(parseReference(`${exampleLink}#L105-L108`)).toMatchSnapshot() 12 | }) 13 | 14 | test('codeReducer', () => { 15 | const prevState = { foo: 'bar' } 16 | expect(codeReducer(prevState, { type: 'reset', value: '' })).toMatchSnapshot() 17 | expect(codeReducer(prevState, { type: 'loading', value: '' })).toMatchSnapshot() 18 | expect(codeReducer(prevState, { type: 'loaded', value: 'foobar' })).toMatchSnapshot() 19 | expect(codeReducer(prevState, { type: 'error', value: 'ups' })).toMatchSnapshot() 20 | // @ts-expect-error 21 | expect(codeReducer(prevState, { type: 'unknown', value: '' })).toEqual(prevState) 22 | }) 23 | 24 | test('getRunmeLink', () => { 25 | expect(getRunmeLink(exampleLink, '')).toMatchSnapshot() 26 | expect(getRunmeLink(exampleLink, 'reference useHTTPS')).toMatchSnapshot() 27 | expect(getRunmeLink(exampleLink, 'reference useHTTPS=true')).toMatchSnapshot() 28 | expect(getRunmeLink(exampleLink, 'reference useHTTPS=false')).toMatchSnapshot() 29 | expect(getRunmeLink(exampleLink, 'runmeFileToOpen="foobar" title="barfoo"')).toMatchSnapshot() 30 | expect(getRunmeLink(exampleLink, 'runmeRepository="foobar" title="barfoo" runmeFileToOpen="foofoo"')).toMatchSnapshot() 31 | }) 32 | -------------------------------------------------------------------------------- /tests/__mocks__/@docusaurus/BrowserOnly.ts: -------------------------------------------------------------------------------- 1 | export default jest.fn() 2 | -------------------------------------------------------------------------------- /tests/__mocks__/@docusaurus/useDocusaurusContext.ts: -------------------------------------------------------------------------------- 1 | export default jest.fn().mockReturnValue({}) 2 | -------------------------------------------------------------------------------- /tests/__mocks__/@theme-init/CodeBlock.ts: -------------------------------------------------------------------------------- 1 | export default {} 2 | -------------------------------------------------------------------------------- /tests/__mocks__/docusaurus-theme-github-codeblock/client.ts: -------------------------------------------------------------------------------- 1 | export const useCodeblockThemeConfig = jest.fn().mockReturnValue({}) 2 | -------------------------------------------------------------------------------- /tests/__mocks__/react.ts: -------------------------------------------------------------------------------- 1 | export default {} 2 | -------------------------------------------------------------------------------- /tests/__snapshots__/ReferenceCodeBlock.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`codeReducer 1`] = ` 4 | { 5 | "code": "loading...", 6 | "error": null, 7 | "loading": null, 8 | } 9 | `; 10 | 11 | exports[`codeReducer 2`] = ` 12 | { 13 | "foo": "bar", 14 | "loading": true, 15 | } 16 | `; 17 | 18 | exports[`codeReducer 3`] = ` 19 | { 20 | "code": "foobar", 21 | "foo": "bar", 22 | "loading": false, 23 | } 24 | `; 25 | 26 | exports[`codeReducer 4`] = ` 27 | { 28 | "code": "ups", 29 | "foo": "bar", 30 | "loading": false, 31 | } 32 | `; 33 | 34 | exports[`getRunmeLink 1`] = `"command=setup&repository=git%40github.com%3Achristian-bromann%2Fdocusaurus-theme-github-codeblock.git&fileToOpen=src%2Ftheme%2FReferenceCodeBlock%2FREADME.md"`; 35 | 36 | exports[`getRunmeLink 2`] = `"command=setup&repository=https%3A%2F%2Fgithub.com%2Fchristian-bromann%2Fdocusaurus-theme-github-codeblock.git&fileToOpen=src%2Ftheme%2FReferenceCodeBlock%2FREADME.md"`; 37 | 38 | exports[`getRunmeLink 3`] = `"command=setup&repository=https%3A%2F%2Fgithub.com%2Fchristian-bromann%2Fdocusaurus-theme-github-codeblock.git&fileToOpen=src%2Ftheme%2FReferenceCodeBlock%2FREADME.md"`; 39 | 40 | exports[`getRunmeLink 4`] = `"command=setup&repository=git%40github.com%3Achristian-bromann%2Fdocusaurus-theme-github-codeblock.git&fileToOpen=src%2Ftheme%2FReferenceCodeBlock%2FREADME.md"`; 41 | 42 | exports[`getRunmeLink 5`] = `"command=setup&fileToOpen=foobar"`; 43 | 44 | exports[`getRunmeLink 6`] = `"command=setup&fileToOpen=foofoo&repository=foobar"`; 45 | 46 | exports[`should parse GitHub reference properly 1`] = ` 47 | { 48 | "fromLine": 0, 49 | "org": "christian-bromann", 50 | "repo": "docusaurus-theme-github-codeblock", 51 | "title": "src/theme/ReferenceCodeBlock/index.tsx", 52 | "toLine": Infinity, 53 | "url": "https://raw.githubusercontent.com/christian-bromann/docusaurus-theme-github-codeblock/main/src/theme/ReferenceCodeBlock/index.tsx", 54 | } 55 | `; 56 | 57 | exports[`should parse GitHub reference properly 2`] = ` 58 | { 59 | "fromLine": 104, 60 | "org": "christian-bromann", 61 | "repo": "docusaurus-theme-github-codeblock", 62 | "title": "src/theme/ReferenceCodeBlock/index.tsx", 63 | "toLine": 107, 64 | "url": "https://raw.githubusercontent.com/christian-bromann/docusaurus-theme-github-codeblock/main/src/theme/ReferenceCodeBlock/index.tsx", 65 | } 66 | `; 67 | -------------------------------------------------------------------------------- /tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "CommonJS", 5 | "outDir": "./cjs", 6 | "esModuleInterop": true 7 | }, 8 | "exclude": ["src/index.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "ES2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 8 | "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | "lib": ["es2020", "DOM"], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | "outDir": "./build", /* Redirect output structure to the directory. */ 18 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | 43 | /* Module Resolution Options */ 44 | // "moduleResolution": "NodeNext", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 45 | "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 46 | "paths": { 47 | "react": ["./examples/node_modules/react"] 48 | }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 49 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 50 | // "typeRoots": [], /* List of folders to include type definitions from. */ 51 | "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 52 | // "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 53 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 54 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 55 | 56 | /* Source Map Options */ 57 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 58 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 59 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 60 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 61 | 62 | /* Experimental Options */ 63 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 64 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 65 | 66 | /* Advanced Options */ 67 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 68 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 69 | }, 70 | "include": ["src"], 71 | "exclude": [ 72 | "tests", 73 | "build", 74 | "src/cjs" 75 | ] 76 | } 77 | --------------------------------------------------------------------------------