From 0b9ff8b1e649de23e8222e0e66718a72f3f083c7 Mon Sep 17 00:00:00 2001 From: Corwin Smith Date: Thu, 1 Dec 2022 01:06:59 +0100 Subject: [PATCH] Create docs navigation sidebar (#40) * crawl files and create directory tree for sidebar * dropdown * Working on dropdown links and styling * setup header nav * Styles * DocumentNav sidebar done * wrap up header sidebar * setup top level nav * update root level data and fix link bug * doc links yaml * nav links for docs * remove character * prettier * fix build error * MDX style * Update src/components/UI/docs/DocsLinks.tsx Co-authored-by: Paul Wackerow <54227730+wackerow@users.noreply.github.com> * Abstract LinksList component into its own file * change requests * AccordionButton styles * AccordionButton styled * fix broken links * prettier * prettier * fix broken default code snippet * fix accordion spacing * fix gap at top of DocsNav lg * fix but of persistent header link * remove test content * setup Notes and prettier * rehype * Note component * Note font styling * convert old notes to use component * Breadcrumb cleanup and prettier * MDXComponents -> MDComponent and documentation Co-authored-by: Paul Wackerow <54227730+wackerow@users.noreply.github.com> --- README.md | 8 + docs/developers/contributing.md | 3 - .../evm-tracing/built-in-tracers.md | 2 - docs/developers/geth-developer/dev-mode.md | 5 - docs/fundamentals/account-management.md | 2 +- docs/fundamentals/les.md | 4 +- docs/fundamentals/mining.md | 2 +- docs/fundamentals/pruning.md | 6 +- docs/getting-started/index.md | 2 +- .../javascript-console.md | 2 +- docs/interacting-with-geth/rpc/index.md | 2 +- docs/interacting-with-geth/rpc/ns-debug.md | 29 ++-- docs/interacting-with-geth/rpc/ns-eth.md | 1 - ...recation.md => ns-personal-deprecation.md} | 0 docs/interacting-with-geth/rpc/ns-personal.md | 2 +- docs/interacting-with-geth/rpc/pubsub.md | 3 - docs/monitoring/dashboards.md | 1 - docs/monitoring/ethstats.md | 6 +- docs/tools/clef/clique-signing.md | 3 + docs/tools/clef/tutorial.md | 3 +- package.json | 1 + src/components/MDXComponents.tsx | 114 ------------- src/components/UI/docs/Breadcrumbs.tsx | 33 ++++ src/components/UI/docs/Code.tsx | 8 +- src/components/UI/docs/DocsLinks.tsx | 81 ++++++++++ src/components/UI/docs/DocsNav.tsx | 59 +++++++ src/components/UI/docs/DocumentNav.tsx | 44 +++++ src/components/UI/docs/LinkList.tsx | 35 ++++ src/components/UI/docs/MDComponents.tsx | 153 ++++++++++++++++++ src/components/UI/docs/Note.tsx | 17 ++ src/components/UI/docs/index.ts | 8 + src/components/UI/docs/index.tsx | 1 - src/components/docs/Breadcrumbs.tsx | 27 ---- src/components/docs/index.ts | 1 - src/components/index.ts | 1 - src/data/documentation-links.yaml | 149 +++++++++++++++++ src/hooks/useActiveHash.ts | 42 +++++ src/pages/[...slug].tsx | 93 +++++++---- src/pages/_app.tsx | 4 +- src/theme/foundations/textStyles.ts | 46 +++++- src/types.ts | 6 + src/utils/getFileList.ts | 16 ++ src/utils/parseHeadingId.ts | 18 +++ yarn.lock | 103 ++++++++++++ 44 files changed, 916 insertions(+), 230 deletions(-) rename docs/interacting-with-geth/rpc/{ns_personal_deprecation.md => ns-personal-deprecation.md} (100%) delete mode 100644 src/components/MDXComponents.tsx create mode 100644 src/components/UI/docs/Breadcrumbs.tsx create mode 100644 src/components/UI/docs/DocsLinks.tsx create mode 100644 src/components/UI/docs/DocsNav.tsx create mode 100644 src/components/UI/docs/DocumentNav.tsx create mode 100644 src/components/UI/docs/LinkList.tsx create mode 100644 src/components/UI/docs/MDComponents.tsx create mode 100644 src/components/UI/docs/Note.tsx create mode 100644 src/components/UI/docs/index.ts delete mode 100644 src/components/UI/docs/index.tsx delete mode 100644 src/components/docs/Breadcrumbs.tsx delete mode 100644 src/components/docs/index.ts delete mode 100644 src/components/index.ts create mode 100644 src/data/documentation-links.yaml create mode 100644 src/hooks/useActiveHash.ts create mode 100644 src/utils/getFileList.ts create mode 100644 src/utils/parseHeadingId.ts diff --git a/README.md b/README.md index 3c633bc383..7043b9cc02 100644 --- a/README.md +++ b/README.md @@ -49,3 +49,11 @@ You can check out [the Next.js GitHub repository](https://github.com/vercel/next The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. + +## Adding a new documentation page + +Documentation pages are located in the `/docs` folder in the root directory of the project. + +When you want to add a new page, add the new file in the appropriate folder in the `/docs` page. `index.md` files will be the default page for a directory, and `{pagename}.md` will define subpages for a directory. + +After adding this page, you will need to add it `/src/data/documentation-links.yaml` which adds documentation structure which you will see on the left sidebar in the documentation pages. diff --git a/docs/developers/contributing.md b/docs/developers/contributing.md index 39eb58bef0..c232f2abfb 100644 --- a/docs/developers/contributing.md +++ b/docs/developers/contributing.md @@ -12,11 +12,8 @@ If you'd like to contribute to the Geth source code, please fork the [Github rep Please make sure your contributions adhere to our coding guidelines: - Code must adhere to the official Go formatting guidelines (i.e. uses gofmt). - - Code must be documented adhering to the official Go commentary guidelines. - - Pull requests need to be based on and opened against the master branch. - - Commit messages should be prefixed with the package(s) they modify. E.g. "eth, rpc: make trace configs optional" diff --git a/docs/developers/evm-tracing/built-in-tracers.md b/docs/developers/evm-tracing/built-in-tracers.md index 1dabc52667..741eafb540 100644 --- a/docs/developers/evm-tracing/built-in-tracers.md +++ b/docs/developers/evm-tracing/built-in-tracers.md @@ -176,7 +176,6 @@ Return: Things to note about the call tracer: - Calls to precompiles are also included in the result - - In case a frame reverts, the field `output` will contain the raw return data - In case the top level frame reverts, its `revertReason` field will contain the parsed reason of revert as returned by the Solidity contract @@ -186,7 +185,6 @@ Things to note about the call tracer: `callTracer` accepts two options: - `onlyTopCall: true` instructs the tracer to only process the main (top-level) call and none of the sub-calls. This avoids extra processing for each call frame if only the top-level call info are required. - - `withLog: true` instructs the tracer to also collect the logs emitted during each call. Example invokation with the `onlyTopCall` flag: diff --git a/docs/developers/geth-developer/dev-mode.md b/docs/developers/geth-developer/dev-mode.md index 29da44f882..ae0bbf44c5 100644 --- a/docs/developers/geth-developer/dev-mode.md +++ b/docs/developers/geth-developer/dev-mode.md @@ -6,15 +6,10 @@ description: Instructions for setting up Geth in developer mode It is often convenient for developers to work in an environment where changes to client or application software can be deployed and tested rapidly and without putting real-world users or assets at risk. For this purpose, Geth has a `--dev` flag that spins up Geth in "developer mode". This creates a single-node Ethereum test network with no connections to any external peers. It exists solely on the local machine. Starting Geth in developer mode does the following: - Initializes the data directory with a testing genesis block - - Sets max peers to 0 (meaning Geth does not search for peers) - - Turns off discovery by other nodes (meaning the node is invisible to other nodes) - - Sets the gas price to 0 (no cost to send transactions) - - Uses the Clique proof-of-authority consensus engine which allows blocks to be mined as-needed without excessive CPU and memory consumption - - Uses on-demand block generation, producing blocks when transactions are waiting to be mined This configuration enables developers to experiment with Geth's source code or develop new applications without having to sync to a pre-existing public network. Blocks are only mined when there are pending transactions. Developers can break things on this network without affecting other users. This page will demonstrate how to spin up a local Geth testnet and a simple smart contract will be deployed to it using the Remix online integrated development environment (IDE). diff --git a/docs/fundamentals/account-management.md b/docs/fundamentals/account-management.md index be91498500..cfb5c6ccfb 100644 --- a/docs/fundamentals/account-management.md +++ b/docs/fundamentals/account-management.md @@ -78,7 +78,7 @@ The console will hang because Clef is waiting for manual approval. Switch to the It is critical to backup the account password safely and securely as it cannot be retrieved or reset. -{% include note.html content=" If the password provided on account creation is lost or forgotten, there is no way to retrive it and the account will simply stay locked forever. The password MUST be backed up safely and securely! **IT IS CRITICAL TO BACKUP THE KEYSTORE AND REMEMBER PASSWORDS**" %} +If the password provided on account creation is lost or forgotten, there is no way to retrive it and the account will simply stay locked forever. The password MUST be backed up safely and securely! **IT IS CRITICAL TO BACKUP THE KEYSTORE AND REMEMBER PASSWORDS** The newly generated key files can be viewed in `/keystore/`. The file naming format is `UTC----
` where `date` is the date and time of key creation formatted according to [UTC 8601](https://www.iso.org/iso-8601-date-and-time-format.html) with zero time offset and seconds precise to eight decimal places. `address` is the 40 hexadecimal characters that make up the account address without a leading `0x`, for example: diff --git a/docs/fundamentals/les.md b/docs/fundamentals/les.md index 81890b183f..c1d607f0bb 100644 --- a/docs/fundamentals/les.md +++ b/docs/fundamentals/les.md @@ -3,13 +3,13 @@ title: Light client description: Introduction to Geth's light sync mode --- -{% include note.html content="Light nodes do not currently work on proof-of-stake Ethereum, but new proof-of-stake light clients are expected to ship soon!" %} +Light nodes do not currently work on proof-of-stake Ethereum, but new proof-of-stake light clients are expected to ship soon! Running a full node is the most trustless, private, decentralized and censorship resistant way to interact with Ethereum. It is also the best choice for the health of the network, because a decentralized network relies on having many individual nodes that independently verify the head of the chain. In a full node a copy of the blockchain is stored locally enabling users to verify incoming data against a local source of truth. However, running a full node requires a lot of disk space and non-negligible CPU allocation and takes hours (for snap sync) or days (for full sync) to sync the blockchain from genesis. Geth also offers a light mode that overcomes these issues and provides some of the benefits of running a node but requires only a fraction of the resources. Read more about the reasons to run nodes on [ethereum.org](https://ethereum.org/en/run-a-node/). -{% include note.html content=" Geth light clients **do not currently work** on proof-of-stake Ethereum. New light clients that work with the proof-of-stake consensus engine are expected to ship soon!" %} +Geth light clients **do not currently work** on proof-of-stake Ethereum. New light clients that work with the proof-of-stake consensus engine are expected to ship soon! ## Light node vs full node {#light-node-vs-full-node} diff --git a/docs/fundamentals/mining.md b/docs/fundamentals/mining.md index c9b03abfa7..31201b3baf 100644 --- a/docs/fundamentals/mining.md +++ b/docs/fundamentals/mining.md @@ -3,7 +3,7 @@ title: Proof-of-work mining with Ethash description: Introduction to proof-of-work mining with Geth --- -{% include note.html content=" Proof-of-work mining is no longer used to secure Ethereum Mainnet. The information below is included because the Ethash code is still part of Geth and it could be used to create a private proof-of-work network or testnet." %} +Proof-of-work mining is no longer used to secure Ethereum Mainnet. The information below is included because the Ethash code is still part of Geth and it could be used to create a private proof-of-work network or testnet. Blockchains grow when individual nodes create valid blocks and distribute them to their peers who check the blocks and add them to their own local databases. Nodes that add blocks are rewarded with ether payouts. On Ethereum Mainnet, the proof-of-stake consensus engine randomly selects a node to produce each block. diff --git a/docs/fundamentals/pruning.md b/docs/fundamentals/pruning.md index ed53205e34..1b286faf4d 100644 --- a/docs/fundamentals/pruning.md +++ b/docs/fundamentals/pruning.md @@ -3,7 +3,7 @@ title: Pruning description: Instructions for pruning a Geth node --- -{% include note.html content="Offline pruning is only for the hash-based state scheme. Soon, we will have a path-based state scheme which enables the pruning by default. Once the hash-based state scheme is no longer supported, offline pruning will be deprecated." %} +Offline pruning is only for the hash-based state scheme. Soon, we will have a path-based state scheme which enables the pruning by default. Once the hash-based state scheme is no longer supported, offline pruning will be deprecated. A snap-sync'd Geth node currently requires more than 650 GB of disk space to store the historic blockchain data. With default cache size the database grows by about 14 GB/week. This means that Geth users will rapidly run out of space on 1TB hard drives. To solve this problem without needing to purchase additional hardware, Geth can be pruned. Pruning is the process of erasing older data to save disk space. Since Geth `v1.10`, users have been able to trigger a snapshot offline prune to bring the total storage back down to the original ~650 GB in about 4-5 hours. This has to be done periodically to keep the total disk storage within the bounds of the local hardware (e.g. every month or so for a 1TB disk). @@ -13,13 +13,9 @@ To prune a Geth node at least 40 GB of free disk space is recommended. This mean ## Pruning rules {#pruning-rules} 1. Do not try to prune an archive node. Archive nodes need to maintain ALL historic data by definition. - 2. Ensure there is at least 40 GB of storage space still available on the disk that will be pruned. Failures have been reported with ~25GB of free space. - 3. Geth is at least `v1.10` ideally > `v1.10.3` - 4. Geth is fully sync'd - 5. Geth has finished creating a snapshot that is at least 128 blocks old. This is true when "state snapshot generation" is no longer reported in the logs. With these rules satisfied, Geth's database can be pruned. diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index d899607b44..74a0d1c04b 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -21,7 +21,7 @@ In order to get the most value from the tutorials on this page, the following sk Users that need to revisit these fundamentals can find helpful resources relating to the command line [here](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line), Ethereum and its testnets [here](https://ethereum.org/en/developers/tutorials/), http [here](https://developer.mozilla.org/en-US/docs/Web/HTTP) and Javascript [here](https://www.javascript.com/learn). Information on node architecture can be found [here](/docs/fundamentals/node-architecture) and our guide for configuring Geth to connect to a consensus client is [here](/docs/getting_started/consensus-clients). -{% include note.html content="If Geth was installed from source on Linux, `make` saves the binaries for Geth and the associated tools in `/build/bin`. To run these programs it is convenient to move them to the top level project directory (e.g. running `mv ./build/bin/* ./`) from `/go-ethereum`. Then `./` must be prepended to the commands in the code snippets in order to execute a particular program, e.g. `./geth` instead of simply `geth`. If the executables are not moved then either navigate to the `bin` directory to run them (e.g. `cd ./build/bin` and `./geth`) or provide their path (e.g. `./build/bin/geth`). These instructions can be ignored for other installations." %} +If Geth was installed from source on Linux, `make` saves the binaries for Geth and the associated tools in `/build/bin`. To run these programs it is convenient to move them to the top level project directory (e.g. running `mv ./build/bin/* ./`) from `/go-ethereum`. Then `./` must be prepended to the commands in the code snippets in order to execute a particular program, e.g. `./geth` instead of simply `geth`. If the executables are not moved then either navigate to the `bin` directory to run them (e.g. `cd ./build/bin` and `./geth`) or provide their path (e.g. `./build/bin/geth`). These instructions can be ignored for other installations. ## Background {#background} diff --git a/docs/interacting-with-geth/javascript-console.md b/docs/interacting-with-geth/javascript-console.md index e81e5a0074..192799bc40 100644 --- a/docs/interacting-with-geth/javascript-console.md +++ b/docs/interacting-with-geth/javascript-console.md @@ -18,7 +18,7 @@ This returns a result which is also a JSON object, with values expressed as hexa This is a low level and rather error-prone way to interact with Geth. Most developers prefer to use convenience libraries that abstract away some of the more tedious and awkward tasks such as converting values from hexadecimal strings into numbers, or converting between denominations of ether (Wei, Gwei, etc). One such library is [Web3.js](https://web3js.readthedocs.io/en/v1.7.3/). The purpose of Geth's Javascript console is to provide a built-in environment to use a subset of the Web3.js libraries to interact with a Geth node. -{% include note.html content="The web3.js version that comes bundled with Geth is not up to date with the official Web3.js documentation. There are several Web3.js libraries that are not available in the Geth Javascript Console. There are also administrative APIs included in the Geth console that are not documented in the Web3.js documentation. The full list of libraries available in the Geth console is available on the [JSON-RPC API page](/docs/interacting-with-geth/rpc/server)." %} +The web3.js version that comes bundled with Geth is not up to date with the official Web3.js documentation. There are several Web3.js libraries that are not available in the Geth Javascript Console. There are also administrative APIs included in the Geth console that are not documented in the Web3.js documentation. The full list of libraries available in the Geth console is available on the [JSON-RPC API page](/docs/interacting-with-geth/rpc/server). ## Starting the console {#starting-the-console} diff --git a/docs/interacting-with-geth/rpc/index.md b/docs/interacting-with-geth/rpc/index.md index 47cea2bd4f..0639935c30 100644 --- a/docs/interacting-with-geth/rpc/index.md +++ b/docs/interacting-with-geth/rpc/index.md @@ -78,7 +78,7 @@ geth --ws --ws.origins http://myapp.example.com As with `--http.corsdomain`, using the wildcard `--ws.origins '*'` allows access from any origin. -{% include note.html content=" By default, **account unlocking is forbidden when HTTP or Websocket access is enabled** (i.e. by passing `--http` or `ws` flag). This is because an attacker that manages to access the node via the externally-exposed HTTP/WS port can then control the unlocked account. It is possible to force account unlock by including the `--allow-insecure-unlock` flag but this is unsafe and **not recommended** except for expert users that completely understand how it can be used safely. This is not a hypothetical risk: **there are bots that continually scan for http-enabled Ethereum nodes to attack**" %} +By default, **account unlocking is forbidden when HTTP or Websocket access is enabled** (i.e. by passing `--http` or `ws` flag). This is because an attacker that manages to access the node via the externally-exposed HTTP/WS port can then control the unlocked account. It is possible to force account unlock by including the `--allow-insecure-unlock` flag but this is unsafe and **not recommended** except for expert users that completely understand how it can be used safely. This is not a hypothetical risk: **there are bots that continually scan for http-enabled Ethereum nodes to attack** ### IPC Server {#ipc-server} diff --git a/docs/interacting-with-geth/rpc/ns-debug.md b/docs/interacting-with-geth/rpc/ns-debug.md index 8ce151439f..1ab4376bc6 100644 --- a/docs/interacting-with-geth/rpc/ns-debug.md +++ b/docs/interacting-with-geth/rpc/ns-debug.md @@ -29,7 +29,7 @@ The location is specified as `:`. Example: -``` js +```js > debug.backtraceAt("server.go:443") ``` @@ -579,13 +579,16 @@ No specific call options: Tracing a call with a destination and specific sender, disabling the storage and memory output (less data returned over RPC) ```js -debug.traceCall({ - "from": "0xdeadbeef29292929192939494959594933929292", - "to": "0xde929f939d939d393f939393f93939f393929023", - "gas": "0x7a120", - "data": "0xf00d4b5d00000000000000000000000001291230982139282304923482304912923823920000000000000000000000001293123098123928310239129839291010293810" - }, - "latest", {"disableStorage": true, "disableMemory": true}) +debug.traceCall( + { + from: '0xdeadbeef29292929192939494959594933929292', + to: '0xde929f939d939d393f939393f93939f393929023', + gas: '0x7a120', + data: '0xf00d4b5d00000000000000000000000001291230982139282304923482304912923823920000000000000000000000001293123098123928310239129839291010293810' + }, + 'latest', + { disableStorage: true, disableMemory: true } +); ``` It is possible to supply 'overrides' for both state-data (accounts/storage) and block data (number, timestamp etc). In the example below, a call which executes `NUMBER` is performed, and the overridden number is placed on the stack: @@ -731,26 +734,26 @@ Sets the logging verbosity pattern. If you want to see messages from a particular Go package (directory) and all subdirectories, use: -``` js +```js > debug.vmodule("eth/*=6") ``` If you want to restrict messages to a particular package (e.g. p2p) but exclude subdirectories, use: -``` js +```js > debug.vmodule("p2p=6") ``` If you want to see log messages from a particular source file, use -``` js +```js > debug.vmodule("server.go=6") ``` You can compose these basic patterns. If you want to see all output from peer.go in a package below eth (eth/peer.go, eth/downloader/peer.go) as well as output from package p2p at level <= 5, use: -``` js -debug.vmodule("eth/*/peer.go=6,p2p=5") +```js +debug.vmodule('eth/*/peer.go=6,p2p=5'); ``` ### debug_writeBlockProfile diff --git a/docs/interacting-with-geth/rpc/ns-eth.md b/docs/interacting-with-geth/rpc/ns-eth.md index 8f9bf247bd..37d5901c8e 100644 --- a/docs/interacting-with-geth/rpc/ns-eth.md +++ b/docs/interacting-with-geth/rpc/ns-eth.md @@ -40,7 +40,6 @@ The _state override set_ is an optional address-to-state mapping, where each ent The goal of the _state override set_ is manyfold: - It can be used by DApps to reduce the amount of contract code needed to be deployed on chain. Code that simply returns internal state or does pre-defined validations can be kept off chain and fed to the node on-demand. - - It can be used for smart contract analysis by extending the code deployed on chain with custom methods and invoking them. This avoids having to download and reconstruct the entire state in a sandbox to run custom code against. - It can be used to debug smart contracts in an already deployed large suite of contracts by selectively overriding some code or state and seeing how execution changes. Specialized tooling will probably be necessary. diff --git a/docs/interacting-with-geth/rpc/ns_personal_deprecation.md b/docs/interacting-with-geth/rpc/ns-personal-deprecation.md similarity index 100% rename from docs/interacting-with-geth/rpc/ns_personal_deprecation.md rename to docs/interacting-with-geth/rpc/ns-personal-deprecation.md diff --git a/docs/interacting-with-geth/rpc/ns-personal.md b/docs/interacting-with-geth/rpc/ns-personal.md index 24ec453aed..ed1ad88a68 100644 --- a/docs/interacting-with-geth/rpc/ns-personal.md +++ b/docs/interacting-with-geth/rpc/ns-personal.md @@ -3,7 +3,7 @@ title: personal Namespace description: Documentation for the JSON-RPC API "personal" namespace --- -{% include note.html content="The personal namespace will be deprecated in the very near future." %} +The personal namespace will be deprecated in the very near future. The personal API managed private keys in the key store. It is deprecated in favour of using [Clef](/docs/tools/clef/Introduction) for interacting with accounts Please refer to the [ns_personal deprecation page](/docs/interacting-with-geth/rpc/ns_personal_deprecation) to see the equivalent methods. The following documentation should be treated as archive information and users should migrate tousing Clef for account interactions. diff --git a/docs/interacting-with-geth/rpc/pubsub.md b/docs/interacting-with-geth/rpc/pubsub.md index e27b3e45bf..7eee1a038b 100644 --- a/docs/interacting-with-geth/rpc/pubsub.md +++ b/docs/interacting-with-geth/rpc/pubsub.md @@ -34,11 +34,8 @@ to cancel the subscription: ## Considerations {#considerations} 1. Notifications are sent for current events and not for past events. For use cases that depend on not to miss any notifications subscriptions are probably not the best option. - 2. Subscriptions require a full duplex connection. Geth offers such connections in the form of WebSocket and IPC (enabled by default). - 3. Subscriptions are coupled to a connection. If the connection is closed all subscriptions that are created over this connection are removed. - 4. Notifications are stored in an internal buffer and sent from this buffer to the client. If the client is unable to keep up and the number of buffered notifications reaches a limit (currently 10k) the connection is closed. Keep in mind that subscribing to some events can cause a flood of notifications, e.g. listening for all logs/blocks when the node starts to synchronize. ## Create subscription {#create-subscriptions} diff --git a/docs/monitoring/dashboards.md b/docs/monitoring/dashboards.md index 7a73e72d8c..fa2153c484 100644 --- a/docs/monitoring/dashboards.md +++ b/docs/monitoring/dashboards.md @@ -10,7 +10,6 @@ There are several ways to monitor the performance of a Geth node. Insights into To follow along with the instructions on this page it will be useful to have: - a running Geth instance. - - basic working knowlegde of bash/terminal. [This video](https://www.youtube.com/watch?v=cOBab8IJMYI) provides an excellent introduction to Geth monitoring. diff --git a/docs/monitoring/ethstats.md b/docs/monitoring/ethstats.md index 22bb2d66c9..0c613f7326 100644 --- a/docs/monitoring/ethstats.md +++ b/docs/monitoring/ethstats.md @@ -50,11 +50,11 @@ each with detailed installation instructions. They all share the common trait th started with a specific URL that can be passed to Geth. [EthNetStats "Classic"](https://github.com/ethereum/eth-netstats) - + [EthNet Intelligence API](https://github.com/ethereum/eth-net-intelligence-api) - + [Goerli Ethstats client](https://github.com/goerli/ethstats-client) - + [Goerli Ethstats server](https://github.com/goerli/ethstats-server) If enabled, Geth spins up a minimal Ethstats reporting daemon that pushes statistics about the diff --git a/docs/tools/clef/clique-signing.md b/docs/tools/clef/clique-signing.md index 0ce79becf3..b47334634d 100644 --- a/docs/tools/clef/clique-signing.md +++ b/docs/tools/clef/clique-signing.md @@ -69,6 +69,7 @@ Initiate Geth: ```sh $ geth --datadir ./ddir init genesis.json ``` + ```terminal ... INFO [06-16|11:14:54.123] Writing custom genesis block @@ -90,6 +91,7 @@ These two things are independent of each other. First of all, however, `clef` mu ```sh $ clef --keystore ./ddir/keystore --configdir ./clef --chainid 15 --suppress-bootwarn init ``` + ```terminal The master seed of clef will be locked with a password. Please specify a password. Do not forget this password! @@ -117,6 +119,7 @@ With that done, `clef` can be made aware of the password. To do this `setpw { - return ( - - {children} - - ); - }, - // links - a: ({ children, href }: any) => { - return ( - - - {children} - - - ); - }, - // headings - h1: ({ children }: any) => { - return ( - - {children} - - ); - }, - h2: ({ children }: any) => { - return ( - - {children} - - ); - }, - h3: ({ children }: any) => { - return ( - - {children} - - ); - }, - h4: ({ children }: any) => { - return ( - - {children} - - ); - }, - // tables - table: ({ children }: any) => ( - - - {children} -
-
- ), - // pre - pre: ({ children }: any) => ( - -
{children}
-
- ), - // code - code: ({ children, ...props }: any) => {children}, - // list - ul: ({ children }: any) => { - return ( - - {children} - - ); - }, - ol: ({ children }: any) => { - return ( - - {children} - - ); - }, - li: ({ children }: any) => { - return {children}; - } -}; - -export default MDXComponents; diff --git a/src/components/UI/docs/Breadcrumbs.tsx b/src/components/UI/docs/Breadcrumbs.tsx new file mode 100644 index 0000000000..e1b6f71304 --- /dev/null +++ b/src/components/UI/docs/Breadcrumbs.tsx @@ -0,0 +1,33 @@ +import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, Stack } from '@chakra-ui/react'; +import NextLink from 'next/link'; +import { useRouter } from 'next/router'; +import { FC } from 'react'; + +export const Breadcrumbs: FC = () => { + const router = useRouter(); + + let pathSplit = router.asPath.split('/'); + pathSplit = pathSplit.splice(1, pathSplit.length); + + return ( + <> + {router.asPath !== '/docs' ? ( + + {pathSplit.map((path: string, idx: number) => { + return ( + + + + {path} + + + + ); + })} + + ) : ( + + )} + + ); +}; diff --git a/src/components/UI/docs/Code.tsx b/src/components/UI/docs/Code.tsx index 67768ab44a..a58c5e1e6d 100644 --- a/src/components/UI/docs/Code.tsx +++ b/src/components/UI/docs/Code.tsx @@ -73,5 +73,11 @@ export const Code: React.FC = ({ className, children, inline }) => { {content} ); - return {content}; + return ( + + + {content} + + + ); }; diff --git a/src/components/UI/docs/DocsLinks.tsx b/src/components/UI/docs/DocsLinks.tsx new file mode 100644 index 0000000000..14beb534ed --- /dev/null +++ b/src/components/UI/docs/DocsLinks.tsx @@ -0,0 +1,81 @@ +import { FC } from 'react'; +import { + Accordion, + AccordionButton, + AccordionItem, + AccordionPanel, + Center, + Link, + Stack, + Text +} from '@chakra-ui/react'; +import { AddIcon, MinusIcon } from '@chakra-ui/icons'; +import NextLink from 'next/link'; + +import { LinksList } from './'; + +import { NavLink } from '../../../types'; + +interface Props { + navLinks: NavLink[]; +} + +export const DocsLinks: FC = ({ navLinks }) => ( + + {navLinks.map(({ id, to, items }, idx) => { + return ( + + + {({ isExpanded }) => ( + <> + + + {to ? ( + + + {id} + + + ) : ( + {id} + )} + + + {items && ( + +
+ {isExpanded ? ( + + ) : ( + + )} +
+
+ )} +
+ {items && ( + + + + )} + + )} +
+
+ ); + })} +
+); diff --git a/src/components/UI/docs/DocsNav.tsx b/src/components/UI/docs/DocsNav.tsx new file mode 100644 index 0000000000..3dcb661d4e --- /dev/null +++ b/src/components/UI/docs/DocsNav.tsx @@ -0,0 +1,59 @@ +import { FC } from 'react'; +import { + Accordion, + AccordionButton, + AccordionIcon, + AccordionItem, + AccordionPanel, + Stack, + Text +} from '@chakra-ui/react'; +import { DocsLinks } from './DocsLinks'; + +import { NavLink } from '../../../types'; + +interface Props { + navLinks: NavLink[]; +} + +export const DocsNav: FC = ({ navLinks }) => { + return ( + + + + + + + + + + + Documentation + + + + + + + + + + + ); +}; diff --git a/src/components/UI/docs/DocumentNav.tsx b/src/components/UI/docs/DocumentNav.tsx new file mode 100644 index 0000000000..25663a720b --- /dev/null +++ b/src/components/UI/docs/DocumentNav.tsx @@ -0,0 +1,44 @@ +import { FC } from 'react'; +import { Divider, Link, Stack, Text } from '@chakra-ui/react'; +import NextLink from 'next/link'; + +import { parseHeadingId } from '../../../utils/parseHeadingId'; +import { useActiveHash } from '../../../hooks/useActiveHash'; + +interface Props { + content: string; +} + +export const DocumentNav: FC = ({ content }) => { + const parsedHeadings = content + .split('\n\n') + .map(item => item.replace(/[\n\r]/g, '')) + .filter(item => item.startsWith('#')) + .map(item => parseHeadingId([item])) + .filter(item => item); + + const activeHash = useActiveHash(parsedHeadings.map(heading => heading!.headingId)); + + return ( + + + on this page + + + {parsedHeadings.map((heading, idx) => { + return ( + + + + {heading?.title} + + + + ); + })} + + ); +}; diff --git a/src/components/UI/docs/LinkList.tsx b/src/components/UI/docs/LinkList.tsx new file mode 100644 index 0000000000..d8c84c72d5 --- /dev/null +++ b/src/components/UI/docs/LinkList.tsx @@ -0,0 +1,35 @@ +import { FC } from 'react'; +import { Link, Stack, Text } from '@chakra-ui/react'; +import NextLink from 'next/link'; + +import { NavLink } from '../../../types'; + +interface LinksListProps { + links: NavLink[]; +} + +export const LinksList: FC = ({ links }) => ( + + {links.map(({ id, to, items }) => { + return to ? ( + + + + + {id} + + + + {items && } + + ) : ( + + + {id} + + {items && } + + ); + })} + +); diff --git a/src/components/UI/docs/MDComponents.tsx b/src/components/UI/docs/MDComponents.tsx new file mode 100644 index 0000000000..09f8b2b71f --- /dev/null +++ b/src/components/UI/docs/MDComponents.tsx @@ -0,0 +1,153 @@ +import { + Flex, + Heading, + Link, + ListItem, + OrderedList, + Stack, + Table, + Text, + UnorderedList +} from '@chakra-ui/react'; +import NextLink from 'next/link'; + +import { Code, Note } from '.'; +import { textStyles } from '../../../theme/foundations'; +import { parseHeadingId } from '../../../utils/parseHeadingId'; + +const { header1, header2, header3, header4 } = textStyles; + +const MDComponents = { + // paragraphs + p: ({ children }: any) => { + return ( + + {children} + + ); + }, + // links + a: ({ children, href }: any) => { + return ( + + + {children} + + + ); + }, + // headings + h1: ({ children }: any) => { + const heading = parseHeadingId(children); + + return heading ? ( + + {heading.children} + + ) : ( + + {children} + + ); + }, + h2: ({ children }: any) => { + const heading = parseHeadingId(children); + + return heading ? ( + + {heading.children} + + ) : ( + + {children} + + ); + }, + h3: ({ children }: any) => { + const heading = parseHeadingId(children); + + return heading ? ( + + {heading.children} + + ) : ( + + {children} + + ); + }, + h4: ({ children }: any) => { + const heading = parseHeadingId(children); + + return heading ? ( + + {heading.children} + + ) : ( + + {children} + + ); + }, + // tables + table: ({ children }: any) => ( + + + {children} +
+
+ ), + // pre + pre: ({ children }: any) => ( + +
{children}
+
+ ), + // code + code: ({ children, ...props }: any) => {children}, + // list + ul: ({ children }: any) => { + return ( + + + {children} + + + ); + }, + ol: ({ children }: any) => { + return ( + + + {children} + + + ); + }, + li: ({ children }: any) => { + return {children}; + }, + note: ({ children }: any) => { + return {children}; + } +}; + +export default MDComponents; diff --git a/src/components/UI/docs/Note.tsx b/src/components/UI/docs/Note.tsx new file mode 100644 index 0000000000..5278fc12ba --- /dev/null +++ b/src/components/UI/docs/Note.tsx @@ -0,0 +1,17 @@ +import { FC } from 'react'; +import { Stack, Text } from '@chakra-ui/react'; + +interface Props { + children: string[]; +} + +export const Note: FC = ({ children }) => { + return ( + + + Note + + {children} + + ); +}; diff --git a/src/components/UI/docs/index.ts b/src/components/UI/docs/index.ts new file mode 100644 index 0000000000..9214774f4c --- /dev/null +++ b/src/components/UI/docs/index.ts @@ -0,0 +1,8 @@ +export * from './Breadcrumbs'; +export * from './Code'; +export * from './DocsLinks'; +export * from './DocsNav'; +export * from './DocumentNav'; +export * from './LinkList'; +export * from './Note'; +export { default } from './MDComponents'; diff --git a/src/components/UI/docs/index.tsx b/src/components/UI/docs/index.tsx deleted file mode 100644 index c3aa9443d1..0000000000 --- a/src/components/UI/docs/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from './Code'; diff --git a/src/components/docs/Breadcrumbs.tsx b/src/components/docs/Breadcrumbs.tsx deleted file mode 100644 index 22dd57527d..0000000000 --- a/src/components/docs/Breadcrumbs.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from '@chakra-ui/react'; -import NextLink from 'next/link'; -import { useRouter } from 'next/router'; -import { FC } from 'react'; - -export const Breadcrumbs: FC = () => { - const router = useRouter(); - - let pathSplit = router.asPath.split('/'); - pathSplit = pathSplit.splice(1, pathSplit.length); - - return ( - - {pathSplit.map((path: string, idx: number) => { - return ( - - - - {path} - - - - ); - })} - - ); -}; diff --git a/src/components/docs/index.ts b/src/components/docs/index.ts deleted file mode 100644 index ce977548b1..0000000000 --- a/src/components/docs/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Breadcrumbs'; diff --git a/src/components/index.ts b/src/components/index.ts deleted file mode 100644 index b7f39642bb..0000000000 --- a/src/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './MDXComponents'; diff --git a/src/data/documentation-links.yaml b/src/data/documentation-links.yaml new file mode 100644 index 0000000000..137b4574d2 --- /dev/null +++ b/src/data/documentation-links.yaml @@ -0,0 +1,149 @@ +- id: Getting started + to: /docs/getting-started + items: + - id: Hardware requirements + to: /docs/getting-started/hardware-requirements + - id: Installing Geth + to: /docs/getting-started/installing-geth + - id: Consensus clients + to: /docs/getting-started/consensus-clients +- id: Fundamentals + to: /docs/fundamentals + items: + - id: Node architecture + to: /docs/fundamentals/node-architecture + - id: Command-line options + to: /docs/fundamentals/command-line-options + - id: Security + to: /docs/fundamentals/security + - id: Sync-modes + to: /docs/fundamentals/sync-modes + - id: Account management + to: /docs/fundamentals/account-management + - id: Backup restore + to: /docs/fundamentals/backup-restore + - id: Logs + to: /docs/fundamentals/logs + - id: Peer-to-peer + to: /docs/fundamentals/peer-to-peer + - id: Pruning + to: /docs/fundamentals/pruning + - id: Light client + to: /docs/fundamentals/les + - id: Mining + to: /docs/fundamentals/mining +- id: Interacting with Geth + items: + - id: JSON-RPC Server + to: /docs/interacting-with-geth/rpc + items: + - id: Batch requests + to: /docs/interacting-with-geth/rpc/batch + - id: GraphQL server + to: /docs/interacting-with-geth/rpc/graphql + - id: admin Namespace + to: /docs/interacting-with-geth/rpc/ns-admin + - id: clique Namespace + to: /docs/interacting-with-geth/rpc/ns-clique + - id: debug Namespace + to: /docs/interacting-with-geth/rpc/ns-debug + - id: eth Namespace + to: /docs/interacting-with-geth/rpc/ns-eth + - id: les Namespace + to: /docs/interacting-with-geth/rpc/ns-les + - id: miner Namespace + to: /docs/interacting-with-geth/rpc/ns-miner + - id: net Namespace + to: /docs/interacting-with-geth/rpc/ns-net + - id: Personal namespace deprecation notes + to: /docs/interacting-with-geth/rpc/ns-personal-deprecation + - id: Personal Namespace + to: /docs/interacting-with-geth/rpc/ns-personal + - id: txpool Namespace + to: /docs/interacting-with-geth/rpc/ns-txpool + - id: Objects + to: /docs/interacting-with-geth/rpc/objects + - id: Real-time Events + to: /docs/interacting-with-geth/rpc/pubsub + - id: JavaScript Console + to: /docs/interacting-with-geth/javascript-console + - id: 'JavaScript Console 2: Contracts' + to: /docs/interacting-with-geth/javascript-console-contracts +- id: Developers + to: /docs/developers + items: + - id: Dapp developers + items: + - id: Go API + to: /docs/developers/dapp-developer/native + - id: Go Account Management + to: /docs/developers/dapp-developer/native-accounts + - id: Go Contract Bindings + to: /docs/developers/dapp-developer/native-bindings + - id: Geth for Mobile + to: /docs/developers/dapp-developer/mobile + - id: EVM tracing + to: /docs/developers/evm-tracing + items: + - id: Basic traces + to: /docs/developers/evm-tracing/basic-traces + - id: Built-in tracers + to: /docs/developers/evm-tracing/built-in-tracers + - id: Custom EVM tracer + to: /docs/developers/evm-tracing/custom-tracer + - id: Tutorial for Javascript tracing + to: /docs/developers/evm-tracing/javascript-tutorial + - id: Geth developer + items: + - id: Developer guide + to: /docs/developers/geth-developer/dev-guide + - id: Developer mode + to: /docs/developers/geth-developer/dev-mode + - id: Disclosures + to: /docs/developers/geth-developer/disclosures + - id: Issue handling workflow + to: /docs/developers/geth-developer/issue-handling-workflow + - id: DNS discovery setup guide + to: /docs/developers/geth-developer/dns-discovery-setup + - id: Code review guidelines + to: /docs/developers/geth-developer/code-review-guidelines + - id: Private networks + to: /docs/developers/geth-developer/private-network + - id: Contributing + to: /docs/developers/contributing +- id: Monitoring + items: + - id: Dashboards + to: /docs/monitoring/dashboards + - id: Ethstats + to: /docs/monitoring/ethstats + - id: Metrics + to: /docs/monitoring/metrics +- id: Tools + items: + - id: Clef + items: + - id: Introduction + to: /docs/tools/clef/introduction + - id: APIs + to: /docs/tools/clef/apis + - id: Rules + to: /docs/tools/clef/rules + - id: Setup + to: /docs/tools/clef/setup + - id: Datatypes + to: /docs/tools/clef/datatypes + - id: Tutorial + to: /docs/tools/clef/tutorial + - id: Clique-signing + to: /docs/tools/clef/clique-signing + - id: puppeth + to: /docs/tools/puppeth + - id: Abigen + to: /docs/tools/abigen + - id: devp2p + to: /docs/tools/devp2p +- id: FAQs + to: /docs/faq +- id: Resources + to: /docs/resources diff --git a/src/hooks/useActiveHash.ts b/src/hooks/useActiveHash.ts new file mode 100644 index 0000000000..70d3944307 --- /dev/null +++ b/src/hooks/useActiveHash.ts @@ -0,0 +1,42 @@ +import { useState, useEffect } from 'react'; + +/** + * A hook to determine which section of the page is currently in the viewport. + * @param {*} itemIds Array of document ids to observe + * @param {*} rootMargin + * @returns id of the element currently in viewport + */ +export const useActiveHash = (itemIds: Array, rootMargin = `0% 0% -80% 0%`): string => { + const [activeHash, setActiveHash] = useState(``); + + useEffect(() => { + const observer = new IntersectionObserver( + entries => { + entries.forEach(entry => { + if (entry.isIntersecting) { + setActiveHash(`${entry.target.id}`); + } + }); + }, + { rootMargin } + ); + + itemIds?.forEach(id => { + const element = document.getElementById(id); + if (element !== null) { + observer.observe(element); + } + }); + + return () => { + itemIds?.forEach(id => { + const element = document.getElementById(id); + if (element !== null) { + observer.unobserve(element); + } + }); + }; + }, [itemIds, rootMargin]); + + return activeHash; +}; diff --git a/src/pages/[...slug].tsx b/src/pages/[...slug].tsx index cb0d69cefc..f16e3fa1dc 100644 --- a/src/pages/[...slug].tsx +++ b/src/pages/[...slug].tsx @@ -1,16 +1,24 @@ import fs from 'fs'; import matter from 'gray-matter'; import yaml from 'js-yaml'; -import { Stack, Heading, Text } from '@chakra-ui/react'; +import { Flex, Stack, Heading, Text } from '@chakra-ui/react'; import ChakraUIRenderer from 'chakra-ui-markdown-renderer'; import ReactMarkdown from 'react-markdown'; +import { useRouter } from 'next/router'; +import { useEffect } from 'react'; import gfm from 'remark-gfm'; +import rehypeRaw from 'rehype-raw'; import { ParsedUrlQuery } from 'querystring'; import type { GetStaticPaths, GetStaticProps, NextPage } from 'next'; -import MDXComponents from '../components/'; -import { Breadcrumbs } from '../components/docs'; +import MDComponents from '../components/UI/docs'; +import { Breadcrumbs, DocsNav, DocumentNav } from '../components/UI/docs'; import { PageMetadata } from '../components/UI'; + +import { NavLink } from '../types'; + +import { getFileList } from '../utils/getFileList'; + import { textStyles } from '../theme/foundations'; import { getParsedDate } from '../utils'; @@ -22,21 +30,6 @@ const MATTER_OPTIONS = { // This method crawls for all valid docs paths export const getStaticPaths: GetStaticPaths = () => { - const getFileList = (dirName: string) => { - let files: string[] = []; - const items = fs.readdirSync(dirName, { withFileTypes: true }); - - for (const item of items) { - if (item.isDirectory()) { - files = [...files, ...getFileList(`${dirName}/${item.name}`)]; - } else { - files.push(`/${dirName}/${item.name}`); - } - } - - return files.map(file => file.replace('.md', '')).map(file => file.replace('/index', '')); - }; - const paths: string[] = getFileList('docs'); // This is folder that get crawled for valid docs paths. Change if this path changes. return { @@ -52,6 +45,8 @@ export const getStaticProps: GetStaticProps = async context => { let file; let lastModified; + const navLinks = yaml.load(fs.readFileSync('src/data/documentation-links.yaml', 'utf8')); + try { file = fs.readFileSync(`${filePath}.md`, 'utf-8'); lastModified = fs.statSync(`${filePath}.md`); @@ -66,6 +61,7 @@ export const getStaticProps: GetStaticProps = async context => { props: { frontmatter, content, + navLinks, lastModified: getParsedDate(lastModified.mtime, { month: 'numeric', day: 'numeric', @@ -80,27 +76,62 @@ interface Props { [key: string]: string; }; content: string; + navLinks: NavLink[]; lastModified: string; } -const DocPage: NextPage = ({ frontmatter, content, lastModified }) => { +const DocPage: NextPage = ({ frontmatter, content, navLinks, lastModified }) => { + const router = useRouter(); + + useEffect(() => { + const id = router.asPath.split('#')[1]; + const element = document.getElementById(id); + + if (!element) { + return; + } + + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + }, [router.asPath]); + return ( <>
- - - - {frontmatter.title} - - - last edited {lastModified} - - - - {content} - + + + + + + + + + + {frontmatter.title} + + + last edited {lastModified} + + + + + + + {content} + + + + + + + + +
); diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index d1f76091e6..c2e8daec60 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -4,7 +4,7 @@ import { MDXProvider } from '@mdx-js/react'; import { Layout } from '../components/layouts'; -import MDXComponents from '../components/'; +import MDComponents from '../components/UI/docs'; import 'focus-visible/dist/focus-visible'; import theme from '../theme'; @@ -12,7 +12,7 @@ import theme from '../theme'; export default function App({ Component, pageProps }: AppProps) { return ( - + diff --git a/src/theme/foundations/textStyles.ts b/src/theme/foundations/textStyles.ts index 2c55908249..df2c9e9d70 100644 --- a/src/theme/foundations/textStyles.ts +++ b/src/theme/foundations/textStyles.ts @@ -107,7 +107,7 @@ export const textStyles = { color: 'body' }, 'footer-link-label': { - fontFamily: '"JetBrains Mono", monospace', + fontFamily: 'heading', fontWeight: 700, textTransform: 'uppercase', lineHeight: '21.12px', @@ -139,13 +139,28 @@ export const textStyles = { textAlign: 'center', fontSize: 'sm' }, + 'docs-nav-dropdown': { + fontFamily: 'heading', + fontWeight: 400, + fontSize: '18px', + lineHeight: 6, + letterSpacing: '4%', + textAlign: 'left' + }, + 'docs-nav-links': { + fontFamily: 'heading', + weight: 400, + fontSize: 'md', + lineHeight: 8, + letterSpacing: '0.01em' + }, 'header-button': { - fontFamily: '"JetBrains Mono", monospace', + fontFamily: 'heading', fontWeight: 700, fontSize: { base: '0.86rem', sm: '1rem' } }, 'header-mobile-button': { - fontFamily: '"JetBrains Mono", monospace', + fontFamily: 'heading', textTransform: 'uppercase', fontSize: '2xl' }, @@ -163,8 +178,25 @@ export const textStyles = { lineHeight: '21.12px', letterSpacing: '0.01rem' }, - // TODO: refactor w/ semantic tokens for light/dark mode - 'link-light': {}, - // TODO: refactor w/ semantic tokens for light/dark mode - 'text-light': {} + 'document-nav-title': { + fontFamily: 'heading', + fontWeight: 400, + fontSize: 'md', + lineHeight: '21.12px', + letterSpacing: '2%' + }, + 'document-nav-link': { + fontFamily: 'body', + fontWeight: 400, + fontSize: '13px', + lineHeight: 5, + letterSpacing: '1%', + mb: 4 + }, + 'note-text': { + fontFamily: 'body', + fontWeight: 400, + fontSize: 'md', + lineHeight: '26px' + } }; diff --git a/src/types.ts b/src/types.ts index 320edd7cb4..5104fe71fd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -35,6 +35,12 @@ export interface ReleaseParams { isStableRelease: boolean; } +export interface NavLink { + id: string; + to?: string; + items?: NavLink[]; +} + export interface OpenPGPSignaturesData { 'build server': string; 'unique id': string; diff --git a/src/utils/getFileList.ts b/src/utils/getFileList.ts new file mode 100644 index 0000000000..4d22edbee6 --- /dev/null +++ b/src/utils/getFileList.ts @@ -0,0 +1,16 @@ +import fs from 'fs'; + +export const getFileList = (dirName: string) => { + let files: string[] = []; + const items = fs.readdirSync(dirName, { withFileTypes: true }); + + for (const item of items) { + if (item.isDirectory()) { + files = [...files, ...getFileList(`${dirName}/${item.name}`)]; + } else { + files.push(`/${dirName}/${item.name}`); + } + } + + return files.map(file => file.replace('.md', '')).map(file => file.replace('/index', '')); +}; diff --git a/src/utils/parseHeadingId.ts b/src/utils/parseHeadingId.ts new file mode 100644 index 0000000000..75d56bf5de --- /dev/null +++ b/src/utils/parseHeadingId.ts @@ -0,0 +1,18 @@ +const check = '{#'; + +export const parseHeadingId = (children: string[]) => { + if (children[children.length - 1].includes(check)) { + const temp = children[children.length - 1].split(check); + const headingId = temp[temp.length - 1].split('}')[0]; + + children[children.length - 1] = temp[0]; + + return { + children, + title: temp[0].replaceAll('#', ''), + headingId + }; + } + + return null; +}; diff --git a/yarn.lock b/yarn.lock index 9cee803ca5..743c2805cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1269,6 +1269,11 @@ resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/parse5@^6.0.0": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.3.tgz#705bb349e789efa06f43f128cef51240753424cb" + integrity sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g== + "@types/prop-types@*", "@types/prop-types@^15.0.0": version "15.7.5" resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz" @@ -2427,11 +2432,62 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hast-to-hyperscript@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-10.0.1.tgz#3decd7cb4654bca8883f6fcbd4fb3695628c4296" + integrity sha512-dhIVGoKCQVewFi+vz3Vt567E4ejMppS1haBRL6TEmeLeJVB1i/FJIIg/e6s1Bwn0g5qtYojHEKvyGA+OZuyifw== + dependencies: + "@types/unist" "^2.0.0" + comma-separated-tokens "^2.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + style-to-object "^0.3.0" + unist-util-is "^5.0.0" + web-namespaces "^2.0.0" + +hast-util-from-parse5@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-7.1.0.tgz#c129dd3a24dd8a867ab8a029ca47e27aa54864b7" + integrity sha512-m8yhANIAccpU4K6+121KpPP55sSl9/samzQSQGpb0mTExcNh2WlvjtMwSWFhg6uqD4Rr6Nfa8N6TMypQM51rzQ== + dependencies: + "@types/hast" "^2.0.0" + "@types/parse5" "^6.0.0" + "@types/unist" "^2.0.0" + hastscript "^7.0.0" + property-information "^6.0.0" + vfile "^5.0.0" + vfile-location "^4.0.0" + web-namespaces "^2.0.0" + hast-util-parse-selector@^2.0.0: version "2.2.5" resolved "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz" integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== +hast-util-parse-selector@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-3.1.0.tgz#a519e27e8b61bd5a98fad494ed06131ce68d9c3f" + integrity sha512-AyjlI2pTAZEOeu7GeBPZhROx0RHBnydkQIXlhnFzDi0qfXTmGUWoCYZtomHbrdrheV4VFUlPcfJ6LMF5T6sQzg== + dependencies: + "@types/hast" "^2.0.0" + +hast-util-raw@^7.2.0: + version "7.2.2" + resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-7.2.2.tgz#1974360b2d7f15b5ce26c2a4bac892d5d8185a18" + integrity sha512-0x3BhhdlBcqRIKyc095lBSDvmQNMY3Eulj2PLsT5XCyKYrxssI5yr3P4Kv/PBo1s/DMkZy2voGkMXECnFCZRLQ== + dependencies: + "@types/hast" "^2.0.0" + "@types/parse5" "^6.0.0" + hast-util-from-parse5 "^7.0.0" + hast-util-to-parse5 "^7.0.0" + html-void-elements "^2.0.0" + parse5 "^6.0.0" + unist-util-position "^4.0.0" + unist-util-visit "^4.0.0" + vfile "^5.0.0" + web-namespaces "^2.0.0" + zwitch "^2.0.0" + hast-util-to-estree@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.1.0.tgz" @@ -2453,6 +2509,18 @@ hast-util-to-estree@^2.0.0: unist-util-position "^4.0.0" zwitch "^2.0.0" +hast-util-to-parse5@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-7.0.0.tgz#a39808e69005d10afeed1866029a1fb137df3f7c" + integrity sha512-YHiS6aTaZ3N0Q3nxaY/Tj98D6kM8QX5Q8xqgg8G45zR7PvWnPGPP0vcKCgb/moIydEJ/QWczVrX0JODCVeoV7A== + dependencies: + "@types/hast" "^2.0.0" + "@types/parse5" "^6.0.0" + hast-to-hyperscript "^10.0.0" + property-information "^6.0.0" + web-namespaces "^2.0.0" + zwitch "^2.0.0" + hast-util-whitespace@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz" @@ -2469,6 +2537,17 @@ hastscript@^6.0.0: property-information "^5.0.0" space-separated-tokens "^1.0.0" +hastscript@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-7.1.0.tgz#e402ed48f46161cf2f093badbff30583a5c3c315" + integrity sha512-uBjaTTLN0MkCZxY/R2fWUOcu7FRtUVzKRO5P/RAfgsu3yFiMB1JWCO4AjeVkgHxAira1f2UecHK5WfS9QurlWA== + dependencies: + "@types/hast" "^2.0.0" + comma-separated-tokens "^2.0.0" + hast-util-parse-selector "^3.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + hey-listen@^1.0.8: version "1.0.8" resolved "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz" @@ -2486,6 +2565,11 @@ hoist-non-react-statics@^3.3.1: dependencies: react-is "^16.7.0" +html-void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-2.0.1.tgz#29459b8b05c200b6c5ee98743c41b979d577549f" + integrity sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A== + ignore@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" @@ -3617,6 +3701,11 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse5@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" @@ -3867,6 +3956,15 @@ regexpp@^3.2.0: resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== +rehype-raw@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/rehype-raw/-/rehype-raw-6.1.1.tgz#81bbef3793bd7abacc6bf8335879d1b6c868c9d4" + integrity sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ== + dependencies: + "@types/hast" "^2.0.0" + hast-util-raw "^7.2.0" + unified "^10.0.0" + remark-gfm@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-3.0.1.tgz#0b180f095e3036545e9dddac0e8df3fa5cfee54f" @@ -4389,6 +4487,11 @@ vfile@^5.0.0: unist-util-stringify-position "^3.0.0" vfile-message "^3.0.0" +web-namespaces@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692" + integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz"