First deployed version
12
.gitignore
vendored
@@ -1,3 +1,13 @@
|
||||
# Deployment utilities
|
||||
bin/priv/
|
||||
|
||||
# Files generated during the build process
|
||||
src/md/pages/
|
||||
src/md/annotated.md
|
||||
index.json
|
||||
|
||||
# Junk
|
||||
node_modules/
|
||||
.cache/
|
||||
public
|
||||
public/
|
||||
tmp/
|
||||
|
||||
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "plugins/gatsby-remark-mathjax3"]
|
||||
path = plugins/gatsby-remark-mathjax3
|
||||
url = https://gitlab.com/public-repositories/gatsby-remark-mathjax3.git
|
||||
111
README.md
@@ -1,54 +1,97 @@
|
||||
<p align="center">
|
||||
<a href="https://www.gatsbyjs.com/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter">
|
||||
<img alt="Gatsby" src="https://www.gatsbyjs.com/Gatsby-Monogram.svg" width="60" />
|
||||
</a>
|
||||
</p>
|
||||
<h1 align="center">
|
||||
Gatsby minimal starter
|
||||
</h1>
|
||||
# Upgrading Ethereum
|
||||
|
||||
## 🚀 Quick start
|
||||
## Intro
|
||||
|
||||
1. **Create a Gatsby site.**
|
||||
This is my book about Ethereum 2.0: Ethereum on proof of stake and beyond.
|
||||
|
||||
Use the Gatsby CLI to create a new site, specifying the minimal starter.
|
||||
You can read it at [upgrading-ethereum.info](https://upgrading-ethereum.info/altair) or at [eth2book.info](https://eth2book.info/altair).
|
||||
|
||||
```shell
|
||||
# create a new Gatsby site using the minimal starter
|
||||
npm init gatsby
|
||||
```
|
||||
It is a work in progress. Currently, the only reasonably complete section is the annotated specification (Part 3). But I thought you might like a glimpse at where it's going. I say more about the plan in the [preface](https://upgrading-ethereum.info/altair/preface).
|
||||
|
||||
2. **Start developing.**
|
||||
I am not looking for contributions. That may change in future, but for now I will not be accepting any PRs to _src/book.md_. Please feel free, however, to raise issues for typos, inaccuracies, omissions, and suggestions. And I'll happily consider PRs for improvements to the CSS or JavaScript.
|
||||
|
||||
Navigate into your new site’s directory and start it up.
|
||||
## Licence
|
||||
|
||||
```shell
|
||||
cd my-gatsby-site/
|
||||
npm run develop
|
||||
```
|
||||
The copyright on the original parts of this work belongs to ConsenSys. We are currently deciding what licence to apply.
|
||||
|
||||
3. **Open the code and start customizing!**
|
||||
## Installing
|
||||
|
||||
Your site is now running at http://localhost:8000!
|
||||
### Pre-requisites
|
||||
|
||||
Edit `src/pages/index.js` to see your site update in real-time!
|
||||
Install `node`, `npm`, and `gatsby-cli`. These are my versions:
|
||||
|
||||
4. **Learn more**
|
||||
```
|
||||
> node --version
|
||||
v16.11.1
|
||||
> npm --version
|
||||
8.1.3
|
||||
> npm list -g gatsby-cli
|
||||
/home/ben/.config/nvm/versions/node/v16.11.1/lib
|
||||
└── gatsby-cli@4.2.0
|
||||
```
|
||||
|
||||
- [Documentation](https://www.gatsbyjs.com/docs/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter)
|
||||
`gatsby-cli` can be installed with,
|
||||
|
||||
- [Tutorials](https://www.gatsbyjs.com/tutorial/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter)
|
||||
```
|
||||
npm install -g gatsby-cli
|
||||
```
|
||||
|
||||
- [Guides](https://www.gatsbyjs.com/tutorial/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter)
|
||||
You'll also need a working `gawk` (GNU awk) installed at _/usr/bin/gawk_ so that the build can preprocess the book document.
|
||||
|
||||
- [API Reference](https://www.gatsbyjs.com/docs/api-reference/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter)
|
||||
### Building
|
||||
|
||||
- [Plugin Library](https://www.gatsbyjs.com/plugins?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter)
|
||||
Clone this repo. `cd` into it, then:
|
||||
|
||||
- [Cheat Sheet](https://www.gatsbyjs.com/docs/cheat-sheet/?utm_source=starter&utm_medium=readme&utm_campaign=minimal-starter)
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
npm install
|
||||
gatsby build
|
||||
```
|
||||
|
||||
## 🚀 Quick start (Gatsby Cloud)
|
||||
### Viewing
|
||||
|
||||
Deploy this starter with one click on [Gatsby Cloud](https://www.gatsbyjs.com/cloud/):
|
||||
After building as above, do
|
||||
|
||||
[<img src="https://www.gatsbyjs.com/deploynow.svg" alt="Deploy to Gatsby Cloud">](https://www.gatsbyjs.com/dashboard/deploynow?url=https://github.com/gatsbyjs/gatsby-starter-minimal)
|
||||
```
|
||||
gatsby serve
|
||||
```
|
||||
|
||||
and visit `http://localhost:9000` in a web browser.
|
||||
|
||||
Instead of building and serving, you can run `gatsby develop` and point your browser at port 8000. This will not pick up real-time changes to _src/book.md_ and will need to be restarted to pick up changes. It is useful, though, for checking CSS and React changes interactively.
|
||||
|
||||
## Editing
|
||||
|
||||
The entire text for the book is in the _src/book.md_ file. Everything under _src/md/pages_ is auto-generated and any changes there will be lost.
|
||||
|
||||
## How to
|
||||
|
||||
### Create a new page
|
||||
|
||||
New pages are created by appending HTML comments to headings (first three levels only):
|
||||
|
||||
```
|
||||
## Heading <!-- /new/page/path -->
|
||||
```
|
||||
|
||||
Take care to get the white space correct.
|
||||
|
||||
### Make a page unlinkable
|
||||
|
||||
Do this if a page has no content yet. It will appear in the index, but not linkable.
|
||||
|
||||
Append a `*` to the path:
|
||||
|
||||
```
|
||||
## Heading <!-- /unlinked/page/path* -->
|
||||
```
|
||||
|
||||
### Insert an image
|
||||
|
||||
Insert SVG images with
|
||||
```
|
||||
<div class="image">
|
||||
<img src="images/image_0.svg" /><br />
|
||||
<span>Image caption, centred and italic.</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
50
bin/build/annotated.awk
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/gawk -f
|
||||
|
||||
# Split out the annotated spec chapter as a single page doc and update links
|
||||
#
|
||||
# Sends output to stdout
|
||||
|
||||
BEGIN {
|
||||
in_part_3 = 0
|
||||
|
||||
print "---"
|
||||
print "path: /annotated-spec"
|
||||
print "titles: [\"One Page Annotated Spec\",\"\",\"\"]"
|
||||
print "index: [999]"
|
||||
print "---"
|
||||
}
|
||||
|
||||
/<!-- \/part3 -->/ {
|
||||
in_part_3 = 1
|
||||
}
|
||||
|
||||
/<!-- \/part4 -->/ {
|
||||
in_part_3 = 0
|
||||
}
|
||||
|
||||
in_part_3 {
|
||||
|
||||
# Change the chapter title
|
||||
if (in_part_3 == 1) {
|
||||
print "# One Page Annotated Spec"
|
||||
print ""
|
||||
print "**Note:** This page is automatically generated from the chapters in [Part 3](/part3). You may find that some internal links are broken."
|
||||
in_part_3 = 2
|
||||
next
|
||||
}
|
||||
|
||||
# Rewrite links to images
|
||||
if ($0 ~ /<img src="md.*"/) {
|
||||
sub(/src="md\//, "src=\"", $0)
|
||||
}
|
||||
|
||||
# Rewrite urls that are internal to the chapter
|
||||
gsub(/]\(\/part3\/[^#)]*/, "](", $0)
|
||||
|
||||
# Remove page path comments from titles
|
||||
if ($0 ~ /^#.*<!--/) {
|
||||
sub(/ <!--.*-->/, "", $0)
|
||||
}
|
||||
|
||||
print
|
||||
}
|
||||
96
bin/build/links.awk
Executable file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/gawk -f
|
||||
|
||||
# Finds internal links that do not point to existing anchors.
|
||||
#
|
||||
# Anchors may be
|
||||
# 1. Full page paths: /part3/introduction
|
||||
# 2. Headings or <a id="..."></a> elements: #introduction
|
||||
# 3. A combination: /part3/introduction#introduction
|
||||
#
|
||||
# Relative page paths are not supported.
|
||||
#
|
||||
# Anchors generated from headings have some rules (imposed by Gatsby):
|
||||
# - Converted to lower case
|
||||
# - Spaces become "-"
|
||||
# - Special characters are omitted: ".,?:'`/[]()" and probably others
|
||||
# - Underscores and dashes are retained.
|
||||
#
|
||||
# Remember to pass the target file twice:
|
||||
#
|
||||
# ../bin/build/links.awk book.md book.md
|
||||
#
|
||||
|
||||
BEGIN {
|
||||
# /contents is OK as a page, but will not be picked up automatically
|
||||
anchors["/contents"] = 1
|
||||
# Ditto /annotated-spec
|
||||
anchors["/annotated-spec"] = 1
|
||||
}
|
||||
|
||||
# Path needs to be set on both passes
|
||||
/(^# |^## |^### ).* <!-- .* -->$/ {
|
||||
path = gensub(/^#+ .* <!-- ([^*]+).? -->$/, "\\1", "1")
|
||||
|
||||
# We can link to the page directly, without the anchor
|
||||
if (FNR == NR ) anchors[path] = 1
|
||||
}
|
||||
|
||||
# First pass: build list of anchors
|
||||
FNR == NR {
|
||||
|
||||
# Headings
|
||||
if ($0 ~ /^#/) {
|
||||
name = ""
|
||||
if ($0 ~ / <!-- .* -->$/) {
|
||||
name = gensub(/^#+ (.*) <!-- .* -->$/, "\\1", "1")
|
||||
} else {
|
||||
name = gensub(/^#+ (.*)$/, "\\1", "1")
|
||||
}
|
||||
name = tolower(name)
|
||||
gsub(/ /, "-", name)
|
||||
gsub(/[^a-z0-9_-]/, "", name)
|
||||
|
||||
anchors[path "#" name] = 1
|
||||
# print path "#" name
|
||||
}
|
||||
|
||||
# Explicit anchors - only one per line allowed, at the start of the line
|
||||
if ($0 ~ /^<a id=".*"><\/a>$/) {
|
||||
name = gensub(/^<a id="(.*)"><\/a>$/, "\\1", "1")
|
||||
|
||||
anchors[path "#" name] = 1
|
||||
# print path "#" name
|
||||
}
|
||||
|
||||
next
|
||||
}
|
||||
|
||||
# Second pass: check anchors exist
|
||||
{
|
||||
# There may be multiple anchors on the line
|
||||
# This mess matches non-greedy [foo](#bar) and [foo](/a/b/c#xyz) etc.
|
||||
while (match($0, /\[[^]]+\]\([#/][^)]+\)/)) {
|
||||
|
||||
# Workaround awk's greediness, otherwise we just get the last match per line.
|
||||
partial = substr($0, RSTART, RLENGTH)
|
||||
name = gensub(/\[[^]]+\]\(([#/][^)]+)\)/, "\\1", "1", partial)
|
||||
|
||||
# Full paths start with "/", paths to the same page with "#". We do not use relative ".." paths.
|
||||
if (name ~ /^#/) {
|
||||
anchor = path name
|
||||
} else {
|
||||
anchor = name
|
||||
}
|
||||
|
||||
if (anchors[anchor] != 1) {
|
||||
print("Anchor not found, line " FNR ": " name)
|
||||
}
|
||||
|
||||
$0 = substr($0, RSTART + RLENGTH)
|
||||
}
|
||||
}
|
||||
|
||||
# Any empty links
|
||||
/\[[^]]+\]\(\)/ {
|
||||
print("Empty link, line " FNR)
|
||||
}
|
||||
113
bin/build/split.awk
Executable file
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/gawk -f
|
||||
|
||||
# Note: run this via "update.sh" rather than directly.
|
||||
#
|
||||
# Split the master markdown file into separate files for each page.
|
||||
#
|
||||
# - Creates a directory structure reflecting the path hierarchy of the
|
||||
# pages.
|
||||
# - Prepends Gatsby frontmatter to each file.
|
||||
# - Rewrites links for image files so that the origial file can use
|
||||
# one path and the split files another.
|
||||
#
|
||||
# Rules:
|
||||
# - New pages can start at markdown heading levels 1, 2, or 3.
|
||||
# - To start a new page, append " <!-- /path/to/page -->" to the heading.
|
||||
# - The file containing the page will end up in "./md/pages/path/to/page.md"
|
||||
# - For the page to be marked "hidden", append a "*" to the path.
|
||||
# - Images matching /<img src="md.*"/ will have their paths naively rewritten.
|
||||
|
||||
BEGIN{
|
||||
n = 0
|
||||
filename_prefix = "md/pages"
|
||||
filename = filename_prefix "/error.md"
|
||||
h_part = ""
|
||||
h_chapter = ""
|
||||
h_part_no = -1 # Number parts from 0
|
||||
h_chapter_no = 0
|
||||
h_section_no = 0
|
||||
}
|
||||
|
||||
# Headings with an HTML comment at the end trigger a new page
|
||||
/^(# |## |### ).* <!-- .* -->$/ {
|
||||
|
||||
# Start a new page
|
||||
if (n > 0) {
|
||||
close (filename)
|
||||
}
|
||||
n++
|
||||
|
||||
# Generate frontmatter contents
|
||||
name = gensub(/^#+ (.*) <!-- .* -->$/, "\\1", "1")
|
||||
h_path = gensub(/^#+ .* <!-- (.*) -->$/, "\\1", "1")
|
||||
heading = gensub (/^(#+ .*) <!-- .* -->$/, "\\1", "1")
|
||||
|
||||
# Is this page hidden?
|
||||
if (h_path ~ /\*$/) {
|
||||
h_path = substr(h_path, 1, length(h_path) - 1)
|
||||
h_hide = "true"
|
||||
} else {
|
||||
h_hide = "false"
|
||||
}
|
||||
|
||||
# Make filesystem path for writing the file
|
||||
file_path = h_path
|
||||
sub(/\/[^/]+$/, "", file_path)
|
||||
system("mkdir -p " filename_prefix file_path " 2>/dev/null")
|
||||
filename = filename_prefix h_path ".md"
|
||||
|
||||
print filename
|
||||
|
||||
switch ($0) {
|
||||
case /^# /:
|
||||
h_part = name
|
||||
h_chapter = ""
|
||||
h_section = ""
|
||||
h_part_no++
|
||||
h_chapter_no = 0
|
||||
idx = h_part_no
|
||||
break
|
||||
case /^## /:
|
||||
h_chapter = name
|
||||
h_section = ""
|
||||
h_chapter_no++
|
||||
h_section_no = 0
|
||||
idx = h_part_no "," h_chapter_no
|
||||
break
|
||||
case /^### /:
|
||||
h_section = name
|
||||
h_section_no++
|
||||
idx = h_part_no "," h_chapter_no "," h_section_no
|
||||
break
|
||||
default:
|
||||
print "Internal error"
|
||||
exit (1)
|
||||
}
|
||||
print "---" > filename
|
||||
print "hide: " h_hide > filename
|
||||
print "path: " h_path > filename
|
||||
print "titles: [\"" h_part "\",\"" h_chapter "\",\"" h_section "\"]" > filename
|
||||
print "index: [" idx "]" > filename
|
||||
print "sequence: " n > filename
|
||||
print "---" > filename
|
||||
print "\n# " h_part > filename
|
||||
if (h_chapter != "") print "\n## " h_chapter > filename
|
||||
if (h_section != "") print "\n### " h_section > filename
|
||||
|
||||
next
|
||||
}
|
||||
|
||||
# Rewrite image paths to reflect the directory hierarchy
|
||||
/<img src="md.*"/ {
|
||||
prefix = substr(h_path, 2)
|
||||
gsub(/[^/]*/, "..", prefix)
|
||||
sub(/src="md/, "src=\"" prefix, $0)
|
||||
print > filename
|
||||
|
||||
next
|
||||
}
|
||||
|
||||
# Pass through everything else as-is
|
||||
{
|
||||
print > filename
|
||||
}
|
||||
14
bin/build/update.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Recreate the individual page markdown files from the master document
|
||||
# in src/book.md
|
||||
|
||||
cd "$(dirname "$0")/../../src"
|
||||
|
||||
# Build the markdown pages
|
||||
rm -rf md/pages/
|
||||
../bin/build/split.awk book.md
|
||||
|
||||
# Build the one page annotated spec
|
||||
rm -f md/annotated.md
|
||||
../bin/build/annotated.awk book.md > md/annotated.md
|
||||
35
bin/util/anchors.awk
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/gawk -f
|
||||
|
||||
# Output all eligible anchors in the document
|
||||
|
||||
BEGIN {
|
||||
# /contents is OK as a page, but will not be picked up automatically
|
||||
print "/contents"
|
||||
name = ""
|
||||
}
|
||||
|
||||
/(^# |^## |^### ).* <!-- .* -->$/ {
|
||||
path = gensub(/^#+ .* <!-- ([^*]+).? -->$/, "\\1", "1")
|
||||
print path
|
||||
}
|
||||
|
||||
# Headings
|
||||
/^#/ {
|
||||
if ($0 ~ / <!-- .* -->$/) {
|
||||
name = gensub(/^#+ (.*) <!-- .* -->$/, "\\1", "1")
|
||||
} else {
|
||||
name = gensub(/^#+ (.*)$/, "\\1", "1")
|
||||
}
|
||||
name = tolower(name)
|
||||
gsub(/ /, "-", name)
|
||||
gsub(/[^a-z0-9_-]/, "", name)
|
||||
|
||||
print path "#" name
|
||||
}
|
||||
|
||||
# Explicit anchors - only one per line allowed, at the start of the line
|
||||
/^<a id=".*"><\/a>$/ {
|
||||
name = gensub(/^<a id="(.*)"><\/a>$/, "\\1", "1")
|
||||
print path "#" name
|
||||
}
|
||||
|
||||
26
bin/util/functions.awk
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/gawk -f
|
||||
|
||||
# Insert an anchor for each function defined in the document, 2 lines ahead.
|
||||
|
||||
NR == 1 {
|
||||
lm2 = $0
|
||||
}
|
||||
|
||||
NR == 2 {
|
||||
lm1 = $0
|
||||
}
|
||||
|
||||
NR > 2 {
|
||||
if ($0 ~ /^def /) {
|
||||
f = gensub(/^def ([^(]+).+$/, "\\1", "1")
|
||||
print "\n<a id=\"def_" f "\"></a>"
|
||||
}
|
||||
print lm2
|
||||
lm2 = lm1
|
||||
lm1 = $0
|
||||
}
|
||||
|
||||
END {
|
||||
print lm2
|
||||
print lm1
|
||||
}
|
||||
78
bin/util/index.awk
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/gawk -f
|
||||
|
||||
# Builds a JSON index from a file of keywords
|
||||
#
|
||||
# ./index.awk words.txt ../../src/book.md
|
||||
#
|
||||
# Should probably escape quotation marks in page_name and heading
|
||||
|
||||
BEGIN {
|
||||
ORS=""
|
||||
}
|
||||
|
||||
# First pass: build list of things to index
|
||||
FNR == NR {
|
||||
refs[$0] = ""
|
||||
next
|
||||
}
|
||||
|
||||
# Record the current page
|
||||
/(^# |^## |^### ).* <!-- .* -->$/ {
|
||||
page_name = gensub(/^#+ (.*) <!-- .* -->$/, "\\1", "1")
|
||||
page_path = gensub(/^#+ .* <!-- ([^*]+).? -->$/, "\\1", "1")
|
||||
}
|
||||
|
||||
# Record the most recent anchor heading
|
||||
/^#/ {
|
||||
heading = ""
|
||||
if ($0 ~ / <!-- .* -->$/) {
|
||||
heading = gensub(/^#+ (.*) <!-- .* -->$/, "\\1", "1")
|
||||
} else {
|
||||
heading = gensub(/^#+ (.*)$/, "\\1", "1")
|
||||
}
|
||||
gsub(/`/, "", heading)
|
||||
anchor = tolower(heading)
|
||||
gsub(/ /, "-", anchor)
|
||||
gsub(/[^a-z0-9_-]/, "", anchor)
|
||||
|
||||
for (word in refs) {
|
||||
done[word] = 0
|
||||
}
|
||||
}
|
||||
|
||||
# Skipping empty lines gives a nice speed-up
|
||||
length() {
|
||||
for (word in refs) {
|
||||
if (!done[word] && index($0, word)) {
|
||||
refs[word] = refs[word] "\"" page_path "#" anchor "\","
|
||||
heads[page_path "#" anchor] = "[\"" page_name "\",\"" heading "\"]"
|
||||
done[word] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
print "{\"refs\":{"
|
||||
count = length(refs)
|
||||
for (word in refs) {
|
||||
count--
|
||||
references = refs[word]
|
||||
if (references) {
|
||||
#remove trailing commas
|
||||
sub(/,$/, "", references)
|
||||
print "\"" word "\":[" references "]"
|
||||
if (count) print ","
|
||||
}
|
||||
}
|
||||
print "},\"heads\":{"
|
||||
count = length(heads)
|
||||
for (anchor in heads) {
|
||||
count--
|
||||
headings = heads[anchor]
|
||||
if (headings) {
|
||||
print "\"" anchor "\":" headings
|
||||
if (count) print ","
|
||||
}
|
||||
}
|
||||
print "}}"
|
||||
}
|
||||
207
bin/util/words.txt
Normal file
@@ -0,0 +1,207 @@
|
||||
`Slot`
|
||||
`Epoch`
|
||||
`CommitteeIndex`
|
||||
`ValidatorIndex`
|
||||
`Gwei`
|
||||
`Root`
|
||||
`Hash32`
|
||||
`Version`
|
||||
`DomainType`
|
||||
`ForkDigest`
|
||||
`Domain`
|
||||
`BLSPubkey`
|
||||
`BLSSignature`
|
||||
`ParticipationFlags`
|
||||
`Fork`
|
||||
`ForkData`
|
||||
`Checkpoint`
|
||||
`Validator`
|
||||
`AttestationData`
|
||||
`IndexedAttestation`
|
||||
`PendingAttestation`
|
||||
`Eth1Data`
|
||||
`HistoricalBatch`
|
||||
`DepositMessage`
|
||||
`DepositData`
|
||||
`BeaconBlockHeader`
|
||||
`SigningData`
|
||||
`ProposerSlashing`
|
||||
`AttesterSlashing`
|
||||
`Attestation`
|
||||
`Deposit`
|
||||
`VoluntaryExit`
|
||||
`BeaconBlockBody`
|
||||
`BeaconBlock`
|
||||
`BeaconState`
|
||||
`SignedVoluntaryExit`
|
||||
`SignedBeaconBlock`
|
||||
`SignedBeaconBlockHeader`
|
||||
`SyncAggregate`
|
||||
`SyncCommittee`
|
||||
`GENESIS_SLOT`
|
||||
`GENESIS_EPOCH`
|
||||
`FAR_FUTURE_EPOCH`
|
||||
`DEPOSIT_CONTRACT_TREE_DEPTH`
|
||||
`JUSTIFICATION_BITS_LENGTH`
|
||||
`PARTICIPATION_FLAG_WEIGHTS`
|
||||
`ENDIANNESS`
|
||||
`TIMELY_SOURCE_FLAG_INDEX`
|
||||
`TIMELY_TARGET_FLAG_INDEX`
|
||||
`TIMELY_HEAD_FLAG_INDEX`
|
||||
`TIMELY_SOURCE_WEIGHT`
|
||||
`TIMELY_TARGET_WEIGHT`
|
||||
`TIMELY_HEAD_WEIGHT`
|
||||
`SYNC_REWARD_WEIGHT`
|
||||
`PROPOSER_WEIGHT`
|
||||
`WEIGHT_DENOMINATOR`
|
||||
`BLS_WITHDRAWAL_PREFIX`
|
||||
`ETH1_ADDRESS_WITHDRAWAL_PREFIX`
|
||||
`DOMAIN_BEACON_PROPOSER`
|
||||
`DOMAIN_BEACON_ATTESTER`
|
||||
`DOMAIN_RANDAO`
|
||||
`DOMAIN_DEPOSIT`
|
||||
`DOMAIN_VOLUNTARY_EXIT`
|
||||
`DOMAIN_SELECTION_PROOF`
|
||||
`DOMAIN_AGGREGATE_AND_PROOF`
|
||||
`DOMAIN_SYNC_COMMITTEE`
|
||||
`DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF`
|
||||
`DOMAIN_CONTRIBUTION_AND_PROOF`
|
||||
`G2_POINT_AT_INFINITY`
|
||||
`MAX_COMMITTEES_PER_SLOT`
|
||||
`TARGET_COMMITTEE_SIZE`
|
||||
`MAX_VALIDATORS_PER_COMMITTEE`
|
||||
`SHUFFLE_ROUND_COUNT`
|
||||
`HYSTERESIS_QUOTIENT`
|
||||
`HYSTERESIS_DOWNWARD_MULTIPLIER`
|
||||
`HYSTERESIS_UPWARD_MULTIPLIER`
|
||||
`MIN_DEPOSIT_AMOUNT`
|
||||
`MAX_EFFECTIVE_BALANCE`
|
||||
`EFFECTIVE_BALANCE_INCREMENT`
|
||||
`MIN_ATTESTATION_INCLUSION_DELAY`
|
||||
`SLOTS_PER_EPOCH`
|
||||
`MIN_SEED_LOOKAHEAD`
|
||||
`MAX_SEED_LOOKAHEAD`
|
||||
`MIN_EPOCHS_TO_INACTIVITY_PENALTY`
|
||||
`EPOCHS_PER_ETH1_VOTING_PERIOD`
|
||||
`SLOTS_PER_HISTORICAL_ROOT`
|
||||
`EPOCHS_PER_HISTORICAL_VECTOR`
|
||||
`EPOCHS_PER_SLASHINGS_VECTOR`
|
||||
`HISTORICAL_ROOTS_LIMIT`
|
||||
`VALIDATOR_REGISTRY_LIMIT`
|
||||
`BASE_REWARD_FACTOR`
|
||||
`WHISTLEBLOWER_REWARD_QUOTIENT`
|
||||
`PROPOSER_REWARD_QUOTIENT`
|
||||
`INACTIVITY_PENALTY_QUOTIENT`
|
||||
`MIN_SLASHING_PENALTY_QUOTIENT`
|
||||
`PROPORTIONAL_SLASHING_MULTIPLIER`
|
||||
`INACTIVITY_PENALTY_QUOTIENT_ALTAIR`
|
||||
`MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR`
|
||||
`PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR`
|
||||
`MAX_PROPOSER_SLASHINGS`
|
||||
`MAX_ATTESTER_SLASHINGS`
|
||||
`MAX_ATTESTATIONS`
|
||||
`MAX_DEPOSITS`
|
||||
`MAX_VOLUNTARY_EXITS`
|
||||
`SYNC_COMMITTEE_SIZE`
|
||||
`EPOCHS_PER_SYNC_COMMITTEE_PERIOD`
|
||||
`GENESIS_FORK_VERSION`
|
||||
`GENESIS_DELAY`
|
||||
`SECONDS_PER_SLOT`
|
||||
`SECONDS_PER_ETH1_BLOCK`
|
||||
`MIN_VALIDATOR_WITHDRAWABILITY_DELAY`
|
||||
`SHARD_COMMITTEE_PERIOD`
|
||||
`ETH1_FOLLOW_DISTANCE`
|
||||
`EJECTION_BALANCE`
|
||||
`MIN_PER_EPOCH_CHURN_LIMIT`
|
||||
`CHURN_LIMIT_QUOTIENT`
|
||||
`INACTIVITY_SCORE_BIAS`
|
||||
`INACTIVITY_SCORE_RECOVERY_RATE`
|
||||
`integer_squareroot`
|
||||
`xor`
|
||||
`bytes_to_uint64`
|
||||
`eth_aggregate_pubkeys`
|
||||
`eth_fast_aggregate_verify`
|
||||
`is_active_validator`
|
||||
`is_eligible_for_activation_queue`
|
||||
`is_eligible_for_activation`
|
||||
`is_slashable_validator`
|
||||
`is_slashable_attestation_data`
|
||||
`is_valid_indexed_attestation`
|
||||
`is_valid_merkle_branch`
|
||||
`compute_shuffled_index`
|
||||
`compute_proposer_index`
|
||||
`compute_committee`
|
||||
`compute_epoch_at_slot`
|
||||
`compute_start_slot_at_epoch`
|
||||
`compute_activation_exit_epoch`
|
||||
`compute_fork_data_root`
|
||||
`compute_fork_digest`
|
||||
`compute_domain`
|
||||
`compute_signing_root`
|
||||
`add_flag`
|
||||
`has_flag`
|
||||
`get_current_epoch`
|
||||
`get_previous_epoch`
|
||||
`get_block_root`
|
||||
`get_block_root_at_slot`
|
||||
`get_randao_mix`
|
||||
`get_active_validator_indices`
|
||||
`get_validator_churn_limit`
|
||||
`get_seed`
|
||||
`get_committee_count_per_slot`
|
||||
`get_beacon_committee`
|
||||
`get_beacon_proposer_index`
|
||||
`get_total_balance`
|
||||
`get_total_active_balance`
|
||||
`get_domain`
|
||||
`get_indexed_attestation`
|
||||
`get_attesting_indices`
|
||||
`get_next_sync_committee_indices`
|
||||
`get_next_sync_committee`
|
||||
`get_unslashed_participating_indices`
|
||||
`get_attestation_participation_flag_indices`
|
||||
`get_flag_index_deltas`
|
||||
`increase_balance`
|
||||
`decrease_balance`
|
||||
`initiate_validator_exit`
|
||||
`slash_validator`
|
||||
`state_transition`
|
||||
`verify_block_signature`
|
||||
`process_slots`
|
||||
`process_slot`
|
||||
`process_epoch`
|
||||
`process_justification_and_finalization`
|
||||
`weigh_justification_and_finalization`
|
||||
`process_inactivity_updates`
|
||||
`get_base_reward_per_increment`
|
||||
`get_base_reward`
|
||||
`get_finality_delay`
|
||||
`is_in_inactivity_leak`
|
||||
`get_eligible_validator_indices`
|
||||
`get_inactivity_penalty_deltas`
|
||||
`process_rewards_and_penalties`
|
||||
`process_registry_updates`
|
||||
`process_slashings`
|
||||
`process_eth1_data_reset`
|
||||
`process_effective_balance_updates`
|
||||
`process_slashings_reset`
|
||||
`process_randao_mixes_reset`
|
||||
`process_historical_roots_update`
|
||||
`process_participation_flag_updates`
|
||||
`process_sync_committee_updates`
|
||||
`process_block`
|
||||
`process_block_header`
|
||||
`process_randao`
|
||||
`process_eth1_data`
|
||||
`process_operations`
|
||||
`process_proposer_slashing`
|
||||
`process_attester_slashing`
|
||||
`process_attestation`
|
||||
`get_validator_from_deposit`
|
||||
`process_deposit`
|
||||
`process_voluntary_exit`
|
||||
`process_sync_aggregate`
|
||||
`initialize_beacon_state_from_eth1`
|
||||
`is_valid_genesis_state`
|
||||
`translate_participation`
|
||||
`upgrade_to_altair`
|
||||
1
gatsby-browser.js
Normal file
@@ -0,0 +1 @@
|
||||
require("prismjs/themes/prism-tomorrow.css")
|
||||
@@ -1,7 +1,55 @@
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
siteUrl: "https://www.yourdomain.tld",
|
||||
title: "Ethereum 2.0 Explained",
|
||||
title: "Upgrading Ethereum",
|
||||
description: `A technical handbook on Ethereum's move to proof of stake and beyond`,
|
||||
author: `Ben Edgington (@benjaminion)`,
|
||||
},
|
||||
plugins: [],
|
||||
pathPrefix: `/altair`,
|
||||
plugins: [
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
name: `markdown-pages`,
|
||||
path: `${__dirname}/src/md`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-transformer-remark`,
|
||||
options: {
|
||||
gfm: true,
|
||||
plugins: [
|
||||
`gatsby-remark-autolink-headers`,
|
||||
'gatsby-remark-numbered-footnotes',
|
||||
`gatsby-remark-mathjax3`,
|
||||
{
|
||||
resolve: "gatsby-remark-external-links",
|
||||
options: {
|
||||
target: "_blank",
|
||||
rel: "external noopener"
|
||||
}
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-remark-prismjs`,
|
||||
options: {
|
||||
noInlineHighlight: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-remark-copy-linked-files`,
|
||||
options: {
|
||||
destinationDir: `images`,
|
||||
ignoreFileExtensions: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-catch-links`,
|
||||
{
|
||||
resolve: 'gatsby-plugin-htaccess',
|
||||
options: {
|
||||
ErrorDocument: `ErrorDocument 404 /altair/404.html`,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
54
gatsby-node.js
Normal file
@@ -0,0 +1,54 @@
|
||||
const path = require(`path`)
|
||||
const execSync = require('child_process').execSync;
|
||||
|
||||
exports.onPreInit = ({reporter}) => {
|
||||
|
||||
reporter.info("Checking internal links...")
|
||||
try {
|
||||
const out = execSync('bin/build/links.awk src/book.md src/book.md', {encoding: 'utf8'})
|
||||
if (out !== "") {
|
||||
reporter.warn("Found some bad internal links:")
|
||||
out.split(/\r?\n/).forEach((line, i) => reporter.warn(line))
|
||||
}
|
||||
} catch (err) {
|
||||
reporter.warn("Unable to check internal links:")
|
||||
err.toString().split(/\r?\n/).forEach((line, i) => reporter.warn(line))
|
||||
}
|
||||
|
||||
reporter.info("Unpacking book source...")
|
||||
try {
|
||||
execSync('bin/build/update.sh')
|
||||
} catch (err) {
|
||||
reporter.panic("Failed to unpack book source.", err)
|
||||
}
|
||||
}
|
||||
|
||||
exports.createPages = async ({ actions, graphql }) => {
|
||||
const { createPage } = actions
|
||||
const pageTemplate = path.resolve(`src/templates/pageTemplate.js`)
|
||||
|
||||
const result = await graphql(`
|
||||
{
|
||||
allMarkdownRemark {
|
||||
edges {
|
||||
node {
|
||||
frontmatter {
|
||||
path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
if (result.errors) {
|
||||
reporter.panicOnBuild(`Error while running GraphQL query.`)
|
||||
}
|
||||
|
||||
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
|
||||
createPage({
|
||||
path: node.frontmatter.path,
|
||||
component: pageTemplate,
|
||||
})
|
||||
})
|
||||
}
|
||||
12175
package-lock.json
generated
27
package.json
@@ -1,12 +1,10 @@
|
||||
{
|
||||
"name": "ethereum-2.0-explained",
|
||||
"name": "upgrading-ethereum-book",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Ethereum 2.0 Explained",
|
||||
"description": "A technical handbook on Ethereum's move to proof of stake and beyond",
|
||||
"author": "Ben Edgington",
|
||||
"keywords": [
|
||||
"gatsby"
|
||||
],
|
||||
"keywords": [],
|
||||
"scripts": {
|
||||
"develop": "gatsby develop",
|
||||
"start": "gatsby develop",
|
||||
@@ -15,8 +13,23 @@
|
||||
"clean": "gatsby clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"gatsby": "^3.14.2",
|
||||
"gatsby": "^4.1.3",
|
||||
"gatsby-plugin-catch-links": "^4.0.0",
|
||||
"gatsby-plugin-htaccess": "^1.4.0",
|
||||
"gatsby-plugin-sharp": "^4.0.0",
|
||||
"gatsby-remark-autolink-headers": "^5.0.0",
|
||||
"gatsby-remark-copy-linked-files": "^5.0.0",
|
||||
"gatsby-remark-external-links": "^0.0.4",
|
||||
"gatsby-remark-images": "^6.0.0",
|
||||
"gatsby-remark-numbered-footnotes": "^1.0.1",
|
||||
"gatsby-remark-prismjs": "^6.1.0",
|
||||
"gatsby-source-filesystem": "^4.0.0",
|
||||
"gatsby-transformer-remark": "^5.0.0",
|
||||
"gatsby-transformer-sharp": "^4.0.0",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1"
|
||||
"react-dom": "^17.0.1",
|
||||
"rehype-mathjax": "^3.1.0",
|
||||
"remark-math": "^4.0.0",
|
||||
"remark-rehype": "^8.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
1
plugins/gatsby-remark-mathjax3
Submodule
5251
src/book.md
Normal file
8
src/components/custom.css
Normal file
@@ -0,0 +1,8 @@
|
||||
:root {
|
||||
--sidebar-width: 20vw;
|
||||
--sidebar-max-width: 400px;
|
||||
--sidebar-min-width: 240px;
|
||||
--main-width: 50vw;
|
||||
--main-max-width: 1200px;
|
||||
--main-min-width: 800px;
|
||||
}
|
||||
5
src/components/footer.css
Normal file
@@ -0,0 +1,5 @@
|
||||
footer {
|
||||
border-top: solid 1px #999;
|
||||
padding-top: 1ex;
|
||||
margin-top: 10ex;
|
||||
}
|
||||
17
src/components/footer.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import React from "react"
|
||||
|
||||
import "./footer.css"
|
||||
|
||||
const Footer = () => {
|
||||
return (
|
||||
<footer>
|
||||
<p>Created by Ben Edgington. © Copyright 2021 ConsenSys. License TBD.</p>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
||||
// <footer>
|
||||
// <p>Created by Ben Edgington. © Copyright 2021 ConsenSys. Licensed under <a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license noreferrer" target="_blank">CC BY-SA 4.0</a>.</p>
|
||||
// </footer>
|
||||
|
||||
export default Footer
|
||||
33
src/components/nestedlist.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import React from "react"
|
||||
import { Link } from "gatsby"
|
||||
|
||||
function ConditionalLink({to, children, nolink}) {
|
||||
const ret = nolink
|
||||
? <>{children}</>
|
||||
: <Link to={to} activeClassName="index-active">{children}</Link>
|
||||
return (ret)
|
||||
}
|
||||
|
||||
export default function NestedList({idx, items, level}) {
|
||||
var ret = []
|
||||
var i = idx
|
||||
while (i < items.length) {
|
||||
const item = items[i]
|
||||
const labelSpan = item.label.length === 0 ? <></ > : <span className="label-string">{item.label}</span>
|
||||
if (item.level === level) {
|
||||
var foo = ""
|
||||
if (i + 1 < items.length && items[i + 1].level > level) {
|
||||
foo = <NestedList key={i + 1} items={items} level={level + 1} idx={i + 1} />
|
||||
}
|
||||
ret.push(
|
||||
<li key={i}><ConditionalLink to={item.link} nolink={item.hide}>{labelSpan} {item.title}</ConditionalLink>{foo}</li>
|
||||
)
|
||||
i++
|
||||
while (i < items.length && items[i].level > level)
|
||||
i++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return (<ul>{ret}</ul>)
|
||||
}
|
||||
215
src/components/page.css
Normal file
@@ -0,0 +1,215 @@
|
||||
@import "custom.css";
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #24292e;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
|
||||
}
|
||||
|
||||
/* A fix for PgUp/PgDn not working to scroll */
|
||||
#gatsby-focus-wrapper {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
flex-direction: row;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
div.main-content {
|
||||
box-sizing: border-box;
|
||||
margin: 0px;
|
||||
margin-left: calc(50vw - min(var(--sidebar-width), var(--sidebar-max-width)) - min(var(--main-max-width), var(--main-width)) / 2);
|
||||
/* margin-left: calc(50vw - min(var(--sidebar-width), var(--sidebar-max-width)) - min(700px,30vw));*/
|
||||
width: var(--main-width);
|
||||
max-width: var(--main-max-width);
|
||||
min-width: var(--main-min-width);
|
||||
padding: 0px 64px 0 96px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
code, pre, tt {
|
||||
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0366d6;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a[rel*="external"]::after {
|
||||
content: "↗";
|
||||
font-size: 10px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 95%;
|
||||
}
|
||||
|
||||
h3 {
|
||||
padding-bottom: 6px;
|
||||
border-bottom: 1px solid #cccccc;
|
||||
margin-bottom: 3ex;
|
||||
}
|
||||
|
||||
h4, h5, h6 {
|
||||
margin-top: 4ex;
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
h1 + p,
|
||||
h2 + p,
|
||||
h3 + p,
|
||||
h4 + p,
|
||||
h5 + p,
|
||||
h6 + p {
|
||||
margin-top: 1ex;
|
||||
}
|
||||
|
||||
h4 code {font-size: inherit; }
|
||||
|
||||
h5 code {
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
div.image {
|
||||
text-align: center;
|
||||
padding: 3ex 0;
|
||||
}
|
||||
|
||||
div.image img {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
div.image span {
|
||||
display: inline;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
table {
|
||||
border: solid #999999 1px;
|
||||
border-collapse: collapse;
|
||||
margin: 3ex 0;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: solid #999999 1px;
|
||||
padding: 4px 8px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th {
|
||||
color: white;
|
||||
background-color: #999999;
|
||||
border: solid #cccccc 1px;
|
||||
border-top-style: inherit;
|
||||
}
|
||||
|
||||
th:first-child {
|
||||
border-left-style: inherit;
|
||||
}
|
||||
|
||||
th:last-child {
|
||||
border-right-style: inherit;
|
||||
}
|
||||
|
||||
th:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.section li {
|
||||
line-height: 1.5;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-left: 0;
|
||||
padding-left: 2em;
|
||||
border-left: solid #ccc 4px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/*** Title page format ***/
|
||||
|
||||
div.title-page {
|
||||
display: flex;
|
||||
margin:6ex 20%;
|
||||
height: 80vh;
|
||||
text-align:center;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
div.title-page h1, div.title-page h2, div.title-page h3, div.title-page h4 {
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.title-page img {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/*** Code prettifier ***/
|
||||
|
||||
pre.language-text {
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
code.language-text {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
div.gatsby-highlight {
|
||||
margin: 1ex 0 3ex 0;
|
||||
}
|
||||
|
||||
pre[class^="language-"] {
|
||||
border-radius: 1ex;
|
||||
}
|
||||
|
||||
pre[class^="language-"] code {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
/*** Displyed equations ***/
|
||||
|
||||
/* Make larger than the default size */
|
||||
div.math-display {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
/*** Footnotes ***/
|
||||
|
||||
div.footnotes hr {
|
||||
margin-top: 6ex;
|
||||
border: 0;
|
||||
border-top: solid 1px #ccc;
|
||||
}
|
||||
|
||||
div.footnotes {
|
||||
font-size: 85%;
|
||||
}
|
||||
13
src/components/page.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import React from "react"
|
||||
|
||||
import "./page.css"
|
||||
|
||||
const Layout = ({ children }) => {
|
||||
return (
|
||||
<>
|
||||
<main>{children}</main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Layout
|
||||
24
src/components/pagelist.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import React from "react"
|
||||
import NestedList from "./nestedlist"
|
||||
|
||||
// Format pages as a list according to their index data.
|
||||
// Depth is the length of prefix to ignore
|
||||
// We assume the pages are given to us in sorted order
|
||||
const PageList = ({pages, depth}) => {
|
||||
|
||||
const filteredPages = pages.filter(p => p.node.frontmatter.index !== null)
|
||||
if (filteredPages.length === 0) return null
|
||||
|
||||
// Make a flat array of list level and the list info
|
||||
const layout = filteredPages.map(p => {return ({
|
||||
level: p.node.frontmatter.index.length,
|
||||
label: p.node.frontmatter.index.join("."),
|
||||
title: p.node.frontmatter.titles[p.node.frontmatter.index.length - 1],
|
||||
link: p.node.frontmatter.path,
|
||||
hide: p.node.frontmatter.hide === true
|
||||
})})
|
||||
|
||||
return (<NestedList items={layout} level={depth + 1} idx={0} />)
|
||||
}
|
||||
|
||||
export default PageList
|
||||
33
src/components/pagenavi.css
Normal file
@@ -0,0 +1,33 @@
|
||||
div.page-navi {
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
padding: 0 1em 0 2em;
|
||||
margin: 0px;
|
||||
overflow-y: auto;
|
||||
color: #999999;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
div.page-navi a {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
div.page-navi a:hover {
|
||||
text-decoration: none;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
div.page-navi ul {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
div.page-navi li {
|
||||
list-style-type: none;
|
||||
padding-bottom: 3px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
div.page-navi > ul > li {
|
||||
padding-top: 1ex;
|
||||
font-weight: bold;
|
||||
}
|
||||
47
src/components/pagenavi.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import React from "react"
|
||||
import { useStaticQuery, graphql } from "gatsby"
|
||||
import NestedList from "./nestedlist"
|
||||
|
||||
import "./pagenavi.css"
|
||||
|
||||
const PageNavi = ({path}) => {
|
||||
const data = useStaticQuery(graphql`
|
||||
{
|
||||
allMarkdownRemark {
|
||||
edges {
|
||||
node {
|
||||
headings {
|
||||
value
|
||||
depth
|
||||
id
|
||||
}
|
||||
frontmatter {
|
||||
path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
const pages = data.allMarkdownRemark.edges
|
||||
const headings = pages.filter(page => page.node.frontmatter.path === path)[0].node.headings
|
||||
|
||||
if (headings.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
// console.log(JSON.stringify(thisPage.node.headings, undefined, 2))
|
||||
|
||||
const items = headings.filter(h => h.depth >= 2).map(h => {return ({
|
||||
level: h.depth,
|
||||
label: "",
|
||||
title: h.value,
|
||||
link: "#" + h.id,
|
||||
hide: false
|
||||
})})
|
||||
|
||||
return (<NestedList items={items} level={2} idx={0} />)
|
||||
}
|
||||
|
||||
export default PageNavi
|
||||
28
src/components/prevnext.css
Normal file
@@ -0,0 +1,28 @@
|
||||
div.prevnext {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 6px 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
div.prevnext span {
|
||||
width: 40%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
div.prevnext span.prev {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
div.prevnext span.prev a {
|
||||
padding-right: 100%;
|
||||
}
|
||||
|
||||
div.prevnext span.next {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
div.prevnext span.next a {
|
||||
padding-left: 100%;
|
||||
}
|
||||
58
src/components/prevnext.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import React from "react"
|
||||
import { Link } from "gatsby"
|
||||
import { useStaticQuery, graphql } from "gatsby"
|
||||
|
||||
import "./prevnext.css"
|
||||
|
||||
function PrevNextLink(props) {
|
||||
if (props.page === null || props.page === undefined) return null
|
||||
|
||||
const f = props.page.node.frontmatter
|
||||
var title = f.titles[0]
|
||||
if (f.titles[1] !== "") title += " > " + f.titles[1]
|
||||
if (f.titles[2] !== "") title += " > " + f.titles[2]
|
||||
|
||||
return(
|
||||
<Link to={f.path} title={title} rel={props.rel}>{props.children}</Link>
|
||||
)
|
||||
}
|
||||
|
||||
const PrevNext = (props) => {
|
||||
const data = useStaticQuery(graphql`
|
||||
{
|
||||
allMarkdownRemark {
|
||||
edges {
|
||||
node {
|
||||
frontmatter {
|
||||
path
|
||||
titles
|
||||
sequence
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
if (props.seq === null) return null
|
||||
|
||||
const pages = data.allMarkdownRemark.edges
|
||||
|
||||
// console.log(JSON.stringify(pages, undefined, 2))
|
||||
|
||||
const prevPage = pages.filter(p => p.node.frontmatter.sequence === (props.seq - 1))[0]
|
||||
const nextPage = pages.filter(p => p.node.frontmatter.sequence === (props.seq + 1))[0]
|
||||
|
||||
return (
|
||||
<div className="prevnext">
|
||||
<span className="prev">
|
||||
<PrevNextLink page={prevPage} rel="prev">Back</PrevNextLink>
|
||||
</span>
|
||||
<span className="next">
|
||||
<PrevNextLink page={nextPage} rel="next">Next</PrevNextLink>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PrevNext
|
||||
59
src/components/sidebar.css
Normal file
@@ -0,0 +1,59 @@
|
||||
@import "custom.css";
|
||||
|
||||
nav.sidebar {
|
||||
box-sizing: border-box;
|
||||
width: var(--sidebar-width);
|
||||
max-width: var(--sidebar-max-width);
|
||||
min-width: var(--sidebar-min-width);
|
||||
height: 100%;
|
||||
padding: 0 1em 0 2em;
|
||||
margin: 0px;
|
||||
overflow-y: auto;
|
||||
border-right: 1px solid rgb(230, 236, 241);
|
||||
text-align: center;
|
||||
background-color: rgb(243, 245, 246);
|
||||
}
|
||||
|
||||
#index {
|
||||
margin: 0 1em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#index,
|
||||
#index a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#index li {
|
||||
text-indent: -1em;
|
||||
list-style-type: none;
|
||||
line-height: 1.4;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#index ul {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
#index > ul > li {
|
||||
padding-top: 1ex;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#index > ul > li > a > span.label-string {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#index a.index-active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
nav.sidebar div.sidebar-title {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
nav.sidebar div.sidebar-title a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
66
src/components/sidebar.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import React from "react"
|
||||
import { Link } from "gatsby"
|
||||
import { useStaticQuery, graphql } from "gatsby"
|
||||
|
||||
import PageList from "./pagelist"
|
||||
import "./sidebar.css"
|
||||
|
||||
const Sidebar = (props) => {
|
||||
const data = useStaticQuery(graphql`
|
||||
{
|
||||
allMarkdownRemark(
|
||||
sort: {fields: [frontmatter___sequence]}
|
||||
filter: {frontmatter: {index: {ne: null}}}
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
frontmatter {
|
||||
hide
|
||||
path
|
||||
titles
|
||||
index
|
||||
sequence
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
const pages = data.allMarkdownRemark.edges
|
||||
|
||||
// List only parts and chapters and immediate children in the sidebar
|
||||
const index = props.index !== null ? props.index : []
|
||||
const filteredPages = index.length < 2
|
||||
? pages.filter(p => p.node.frontmatter.index.length <= 2)
|
||||
: pages.filter(p => p.node.frontmatter.index.length <= 2
|
||||
|| (p.node.frontmatter.index.length === 3
|
||||
&& p.node.frontmatter.index[0] === index[0]
|
||||
&& p.node.frontmatter.index[1] === index[1]
|
||||
)
|
||||
)
|
||||
|
||||
// console.log(JSON.stringify(filteredPages, undefined, 2))
|
||||
|
||||
return (
|
||||
<nav className="sidebar">
|
||||
<div className="sidebar-title">
|
||||
<Link
|
||||
to="/"
|
||||
>
|
||||
{data.site.siteMetadata.title}
|
||||
</Link>
|
||||
</div>
|
||||
<div id="index">
|
||||
<PageList pages={filteredPages} depth={0} />
|
||||
</div>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
export default Sidebar
|
||||
3
src/components/subsections.css
Normal file
@@ -0,0 +1,3 @@
|
||||
.subsection-list .label-string {
|
||||
display: none;
|
||||
}
|
||||
50
src/components/subsections.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import React from "react"
|
||||
import { useStaticQuery, graphql } from "gatsby"
|
||||
|
||||
import PageList from "./pagelist"
|
||||
import "./subsections.css"
|
||||
|
||||
// Format subsections of the page with index indexArray as a nested list
|
||||
const Subsections = ({indexArray}) => {
|
||||
|
||||
const data = useStaticQuery(graphql`
|
||||
{
|
||||
allMarkdownRemark(
|
||||
sort: {fields: [frontmatter___sequence]}
|
||||
filter: {frontmatter: {index: {ne: null}}}
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
frontmatter {
|
||||
hide
|
||||
path
|
||||
titles
|
||||
index
|
||||
sequence
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
// Only add the auto index for Parts, not any deeper structure
|
||||
if (indexArray === null || indexArray.length > 1) return null
|
||||
|
||||
// Find pages that are subsections of the page we are on
|
||||
const pages = data.allMarkdownRemark.edges
|
||||
const indexFilterString = indexArray.length === 0 ? "" : indexArray.join() + ","
|
||||
const filteredPages = pages.filter(p => p.node.frontmatter.index.join().startsWith(indexFilterString))
|
||||
|
||||
if (filteredPages.length > 0) {
|
||||
return (
|
||||
<div className="subsection-list">
|
||||
<PageList pages={filteredPages} depth={indexArray.length} />
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export default Subsections
|
||||
63
src/html.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
|
||||
export default function HTML(props) {
|
||||
return (
|
||||
<html lang="en-GB" {...props.htmlAttributes}>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||
/>
|
||||
<title>Upgrading Ethereum</title>
|
||||
<meta name="twitter:card" content="summary"/>
|
||||
<meta name="twitter:site" content="eth2book.info"/>
|
||||
<meta name="twitter:creator" content="@benjaminion_xyz"/>
|
||||
<meta name="twitter:image" content="https://benjaminion.xyz/f/henohenomoheji.svg"/>
|
||||
<meta property="og:image" content="https://benjaminion.xyz/f/android-icon-192x192.png"/>
|
||||
<meta name="description" content="A technical handbook on Ethereum's move to proof of stake and beyond." />
|
||||
<meta property="og:image" content="https://benjaminion.xyz/android-icon-192x192.png" />
|
||||
<meta property="og:title" content="Upgrading Ethereum" />
|
||||
<meta property="og:description" content="A technical handbook on Ethereum's move to proof of stake and beyond." />
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://benjaminion.xyz/f/apple-icon-57x57.png" />
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="https://benjaminion.xyz/f/apple-icon-60x60.png" />
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="https://benjaminion.xyz/f/apple-icon-72x72.png" />
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="https://benjaminion.xyz/f/apple-icon-76x76.png" />
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="https://benjaminion.xyz/f/apple-icon-114x114.png" />
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="https://benjaminion.xyz/f/apple-icon-120x120.png" />
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="https://benjaminion.xyz/f/apple-icon-144x144.png" />
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="https://benjaminion.xyz/f/apple-icon-152x152.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="https://benjaminion.xyz/f/apple-icon-180x180.png" />
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="https://benjaminion.xyz/f/android-icon-192x192.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="https://benjaminion.xyz/f/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="https://benjaminion.xyz/f/favicon-96x96.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="https://benjaminion.xyz/f/favicon-16x16.png" />
|
||||
<link rel="manifest" href="https://benjaminion.xyz/f/manifest.json" />
|
||||
<meta name="msapplication-TileColor" content="#ffffff" />
|
||||
<meta name="msapplication-TileImage" content="https://benjaminion.xyz/f/ms-icon-144x144.png" />
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
{props.headComponents}
|
||||
</head>
|
||||
<body {...props.bodyAttributes}>
|
||||
{props.preBodyComponents}
|
||||
<div
|
||||
key={`body`}
|
||||
id="___gatsby"
|
||||
dangerouslySetInnerHTML={{ __html: props.body }}
|
||||
/>
|
||||
{props.postBodyComponents}
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
|
||||
HTML.propTypes = {
|
||||
htmlAttributes: PropTypes.object,
|
||||
headComponents: PropTypes.array,
|
||||
bodyAttributes: PropTypes.object,
|
||||
preBodyComponents: PropTypes.array,
|
||||
body: PropTypes.string,
|
||||
postBodyComponents: PropTypes.array,
|
||||
}
|
||||
|
Before Width: | Height: | Size: 11 KiB |
9
src/md/404.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
path: /404.html
|
||||
---
|
||||
|
||||
# Not Found
|
||||
|
||||
Sorry, that page does not exist.
|
||||
|
||||
Try the [contents](/contents) page.
|
||||
9
src/md/contents.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
path: /contents
|
||||
titles: ["Contents","",""]
|
||||
index: [-1]
|
||||
sequence: 0
|
||||
---
|
||||
|
||||
# Contents
|
||||
|
||||
1
src/md/images/benjaminion.svg
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
4
src/md/images/inactivity-scores-flow.svg
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
src/md/images/inactivity_0.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
src/md/images/inactivity_1.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
4
src/md/images/k-finality.svg
Normal file
|
After Width: | Height: | Size: 112 KiB |
4
src/md/images/shuffling_0.svg
Normal file
|
After Width: | Height: | Size: 218 KiB |
4
src/md/images/shuffling_1.svg
Normal file
|
After Width: | Height: | Size: 229 KiB |
4
src/md/images/shuffling_2.svg
Normal file
|
After Width: | Height: | Size: 226 KiB |
4
src/md/images/shuffling_3.svg
Normal file
|
After Width: | Height: | Size: 228 KiB |
4
src/md/images/shuffling_4.svg
Normal file
|
After Width: | Height: | Size: 242 KiB |
4
src/md/images/weights.svg
Normal file
|
After Width: | Height: | Size: 40 KiB |
12
src/md/title_page.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
path: /
|
||||
---
|
||||
|
||||
<div class="title-page">
|
||||
<h1>Upgrading Ethereum</h1>
|
||||
<h2>A technical handbook on Ethereum's move to proof of stake and beyond</h2>
|
||||
<h3>Edition 0.1: Altair [WIP]</h3>
|
||||
<h4>by Ben Edgington</h4>
|
||||
<img src="images/benjaminion.svg" width="120" alt="" />
|
||||
<h4><a href="contents">Contents</a></h4>
|
||||
</div>
|
||||
@@ -1,54 +0,0 @@
|
||||
import * as React from "react"
|
||||
import { Link } from "gatsby"
|
||||
|
||||
// styles
|
||||
const pageStyles = {
|
||||
color: "#232129",
|
||||
padding: "96px",
|
||||
fontFamily: "-apple-system, Roboto, sans-serif, serif",
|
||||
}
|
||||
const headingStyles = {
|
||||
marginTop: 0,
|
||||
marginBottom: 64,
|
||||
maxWidth: 320,
|
||||
}
|
||||
|
||||
const paragraphStyles = {
|
||||
marginBottom: 48,
|
||||
}
|
||||
const codeStyles = {
|
||||
color: "#8A6534",
|
||||
padding: 4,
|
||||
backgroundColor: "#FFF4DB",
|
||||
fontSize: "1.25rem",
|
||||
borderRadius: 4,
|
||||
}
|
||||
|
||||
// markup
|
||||
const NotFoundPage = () => {
|
||||
return (
|
||||
<main style={pageStyles}>
|
||||
<title>Not found</title>
|
||||
<h1 style={headingStyles}>Page not found</h1>
|
||||
<p style={paragraphStyles}>
|
||||
Sorry{" "}
|
||||
<span role="img" aria-label="Pensive emoji">
|
||||
😔
|
||||
</span>{" "}
|
||||
we couldn’t find what you were looking for.
|
||||
<br />
|
||||
{process.env.NODE_ENV === "development" ? (
|
||||
<>
|
||||
<br />
|
||||
Try creating a page in <code style={codeStyles}>src/pages/</code>.
|
||||
<br />
|
||||
</>
|
||||
) : null}
|
||||
<br />
|
||||
<Link to="/">Go home</Link>.
|
||||
</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
export default NotFoundPage
|
||||
@@ -1,184 +0,0 @@
|
||||
import * as React from "react"
|
||||
|
||||
// styles
|
||||
const pageStyles = {
|
||||
color: "#232129",
|
||||
padding: 96,
|
||||
fontFamily: "-apple-system, Roboto, sans-serif, serif",
|
||||
}
|
||||
const headingStyles = {
|
||||
marginTop: 0,
|
||||
marginBottom: 64,
|
||||
maxWidth: 320,
|
||||
}
|
||||
const headingAccentStyles = {
|
||||
color: "#663399",
|
||||
}
|
||||
const paragraphStyles = {
|
||||
marginBottom: 48,
|
||||
}
|
||||
const codeStyles = {
|
||||
color: "#8A6534",
|
||||
padding: 4,
|
||||
backgroundColor: "#FFF4DB",
|
||||
fontSize: "1.25rem",
|
||||
borderRadius: 4,
|
||||
}
|
||||
const listStyles = {
|
||||
marginBottom: 96,
|
||||
paddingLeft: 0,
|
||||
}
|
||||
const listItemStyles = {
|
||||
fontWeight: 300,
|
||||
fontSize: 24,
|
||||
maxWidth: 560,
|
||||
marginBottom: 30,
|
||||
}
|
||||
|
||||
const linkStyle = {
|
||||
color: "#8954A8",
|
||||
fontWeight: "bold",
|
||||
fontSize: 16,
|
||||
verticalAlign: "5%",
|
||||
}
|
||||
|
||||
const docLinkStyle = {
|
||||
...linkStyle,
|
||||
listStyleType: "none",
|
||||
marginBottom: 24,
|
||||
}
|
||||
|
||||
const descriptionStyle = {
|
||||
color: "#232129",
|
||||
fontSize: 14,
|
||||
marginTop: 10,
|
||||
marginBottom: 0,
|
||||
lineHeight: 1.25,
|
||||
}
|
||||
|
||||
const docLink = {
|
||||
text: "Documentation",
|
||||
url: "https://www.gatsbyjs.com/docs/",
|
||||
color: "#8954A8",
|
||||
}
|
||||
|
||||
const badgeStyle = {
|
||||
color: "#fff",
|
||||
backgroundColor: "#088413",
|
||||
border: "1px solid #088413",
|
||||
fontSize: 11,
|
||||
fontWeight: "bold",
|
||||
letterSpacing: 1,
|
||||
borderRadius: 4,
|
||||
padding: "4px 6px",
|
||||
display: "inline-block",
|
||||
position: "relative",
|
||||
top: -2,
|
||||
marginLeft: 10,
|
||||
lineHeight: 1,
|
||||
}
|
||||
|
||||
// data
|
||||
const links = [
|
||||
{
|
||||
text: "Tutorial",
|
||||
url: "https://www.gatsbyjs.com/docs/tutorial/",
|
||||
description:
|
||||
"A great place to get started if you're new to web development. Designed to guide you through setting up your first Gatsby site.",
|
||||
color: "#E95800",
|
||||
},
|
||||
{
|
||||
text: "How to Guides",
|
||||
url: "https://www.gatsbyjs.com/docs/how-to/",
|
||||
description:
|
||||
"Practical step-by-step guides to help you achieve a specific goal. Most useful when you're trying to get something done.",
|
||||
color: "#1099A8",
|
||||
},
|
||||
{
|
||||
text: "Reference Guides",
|
||||
url: "https://www.gatsbyjs.com/docs/reference/",
|
||||
description:
|
||||
"Nitty-gritty technical descriptions of how Gatsby works. Most useful when you need detailed information about Gatsby's APIs.",
|
||||
color: "#BC027F",
|
||||
},
|
||||
{
|
||||
text: "Conceptual Guides",
|
||||
url: "https://www.gatsbyjs.com/docs/conceptual/",
|
||||
description:
|
||||
"Big-picture explanations of higher-level Gatsby concepts. Most useful for building understanding of a particular topic.",
|
||||
color: "#0D96F2",
|
||||
},
|
||||
{
|
||||
text: "Plugin Library",
|
||||
url: "https://www.gatsbyjs.com/plugins",
|
||||
description:
|
||||
"Add functionality and customize your Gatsby site or app with thousands of plugins built by our amazing developer community.",
|
||||
color: "#8EB814",
|
||||
},
|
||||
{
|
||||
text: "Build and Host",
|
||||
url: "https://www.gatsbyjs.com/cloud",
|
||||
badge: true,
|
||||
description:
|
||||
"Now you’re ready to show the world! Give your Gatsby site superpowers: Build and host on Gatsby Cloud. Get started for free!",
|
||||
color: "#663399",
|
||||
},
|
||||
]
|
||||
|
||||
// markup
|
||||
const IndexPage = () => {
|
||||
return (
|
||||
<main style={pageStyles}>
|
||||
<title>Home Page</title>
|
||||
<h1 style={headingStyles}>
|
||||
Congratulations
|
||||
<br />
|
||||
<span style={headingAccentStyles}>— you just made a Gatsby site! </span>
|
||||
<span role="img" aria-label="Party popper emojis">
|
||||
🎉🎉🎉
|
||||
</span>
|
||||
</h1>
|
||||
<p style={paragraphStyles}>
|
||||
Edit <code style={codeStyles}>src/pages/index.js</code> to see this page
|
||||
update in real-time.{" "}
|
||||
<span role="img" aria-label="Sunglasses smiley emoji">
|
||||
😎
|
||||
</span>
|
||||
</p>
|
||||
<ul style={listStyles}>
|
||||
<li style={docLinkStyle}>
|
||||
<a
|
||||
style={linkStyle}
|
||||
href={`${docLink.url}?utm_source=starter&utm_medium=start-page&utm_campaign=minimal-starter`}
|
||||
>
|
||||
{docLink.text}
|
||||
</a>
|
||||
</li>
|
||||
{links.map(link => (
|
||||
<li key={link.url} style={{ ...listItemStyles, color: link.color }}>
|
||||
<span>
|
||||
<a
|
||||
style={linkStyle}
|
||||
href={`${link.url}?utm_source=starter&utm_medium=start-page&utm_campaign=minimal-starter`}
|
||||
>
|
||||
{link.text}
|
||||
</a>
|
||||
{link.badge && (
|
||||
<span style={badgeStyle} aria-label="New Badge">
|
||||
NEW!
|
||||
</span>
|
||||
)}
|
||||
<p style={descriptionStyle}>{link.description}</p>
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<img
|
||||
alt="Gatsby G Logo"
|
||||
src="data:image/svg+xml,%3Csvg width='24' height='24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 2a10 10 0 110 20 10 10 0 010-20zm0 2c-3.73 0-6.86 2.55-7.75 6L14 19.75c3.45-.89 6-4.02 6-7.75h-5.25v1.5h3.45a6.37 6.37 0 01-3.89 4.44L6.06 9.69C7 7.31 9.3 5.63 12 5.63c2.13 0 4 1.04 5.18 2.65l1.23-1.06A7.959 7.959 0 0012 4zm-8 8a8 8 0 008 8c.04 0 .09 0-8-8z' fill='%23639'/%3E%3C/svg%3E"
|
||||
/>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
export default IndexPage
|
||||
58
src/templates/pageTemplate.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import React from "react"
|
||||
import { graphql } from "gatsby"
|
||||
|
||||
import Layout from "../components/page"
|
||||
import Sidebar from "../components/sidebar"
|
||||
import Subsections from "../components/subsections"
|
||||
import PrevNext from "../components/prevnext"
|
||||
import Footer from "../components/footer"
|
||||
import PageNavi from "../components/pagenavi"
|
||||
|
||||
export default function Template({
|
||||
data,
|
||||
}) {
|
||||
const { markdownRemark } = data
|
||||
const { html } = markdownRemark
|
||||
|
||||
//console.log(JSON.stringify(markdownRemark, undefined, 2))
|
||||
|
||||
const index_array = markdownRemark.frontmatter.path !== "/contents"
|
||||
? markdownRemark.frontmatter.index
|
||||
: []
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Sidebar index={markdownRemark.frontmatter.index} />
|
||||
<div className="main-content">
|
||||
<PrevNext seq={markdownRemark.frontmatter.sequence} />
|
||||
<div className="container">
|
||||
<div className="section">
|
||||
<div
|
||||
className="section-content"
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
/>
|
||||
<Subsections indexArray={index_array} />
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
<PrevNext seq={markdownRemark.frontmatter.sequence} />
|
||||
</div>
|
||||
<div className="page-navi">
|
||||
<PageNavi path={markdownRemark.frontmatter.path} />
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
export const pageQuery = graphql`
|
||||
query($path: String!) {
|
||||
markdownRemark(frontmatter: { path: { eq: $path } }) {
|
||||
frontmatter {
|
||||
index
|
||||
path
|
||||
sequence
|
||||
}
|
||||
html
|
||||
}
|
||||
}
|
||||
`
|
||||