Introduce RFC mdBook web page (#60)

- Closes https://github.com/polkadot-fellows/RFCs/issues/53
- Preview available [here](https://paritytech.github.io/RFCs/).

![Screenshot 2023-12-19 at 13 55
05](https://github.com/polkadot-fellows/RFCs/assets/12039224/ee06a7ad-231e-4077-a773-c6319661dfb6)


---

### What it does

- The workflow gathers the source markdown files of RFCs - approved
ones, and proposed ones (from open PRs).
- The proposed RFCs are separated into new (<7 days since PR created)
and stale (>30 days since PR updated).
- The RFCs are extended with a table of contents, and a link to the
source.
- The RFCs are build into a web page using
[mdBook](https://github.com/rust-lang/mdBook).
- The built web page gets pushed to `gh-pages` branch - to be published
in Github Pages.
- The workflow is triggered on merge to `main`, and periodically once a
day.
This commit is contained in:
Przemek Rzad
2024-01-03 11:05:00 -08:00
committed by GitHub
parent 6b4262b55c
commit f94ab697e5
18 changed files with 679 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
/**
* mdBook relies on the creation of a special SUMMARY.md file
* https://rust-lang.github.io/mdBook/format/summary.html
* This script constructs the summary out of the available source files.
*/
const fs = require('fs');
const summaryPath = "mdbook/src/SUMMARY.md"
module.exports = async ({github, context}) => {
fs.writeFileSync(summaryPath, "# Summary\n\n[Introduction](introduction.md)\n") // Starting point.
const appendRfcsToSummary = (dirPath) => {
for (const filename of fs.readdirSync(dirPath)) {
if (!filename.endsWith(".md")) continue;
const filePath = dirPath + filename
const text = fs.readFileSync(filePath)
const title = text.toString().split(/\n/)
.find(line => line.startsWith("# ") || line.startsWith(" # "))
.replace("# ", "")
// Relative path, without the src prefix (format required by mdbook)
const relativePath = filePath.replace("mdbook/src/", "")
fs.appendFileSync(summaryPath, `- [${title}](${relativePath})\n`)
}
}
fs.appendFileSync(summaryPath, "\n---\n\n# Approved\n\n")
appendRfcsToSummary("mdbook/src/approved/")
fs.appendFileSync(summaryPath, "\n---\n\n# Newly Proposed\n\n")
appendRfcsToSummary("mdbook/src/new/")
fs.appendFileSync(summaryPath, "\n---\n\n# Proposed\n\n")
appendRfcsToSummary("mdbook/src/proposed/")
fs.appendFileSync(summaryPath, "\n---\n\n# Stale\n\n")
appendRfcsToSummary("mdbook/src/stale/")
}
+74
View File
@@ -0,0 +1,74 @@
/**
* This scripts gathers source markdown files of approved and proposed RFCS into the mdbook/src directory.
*/
const fs = require('fs');
// The amount of days that an RFC is considered "new".
// Counted from the creation of a given PR.
const NEW_RFC_PERIOD_DAYS = 7
// The amount of days that an RFC is considered "stale".
// Counted from the last update on a PR.
const STALE_RFC_PERIOD_DAYS = 30
const dateDaysBefore = (daysBefore) => {
const result = new Date()
result.setDate(result.getDate() - daysBefore)
return result
}
[
"mdbook/src/approved",
"mdbook/src/new",
"mdbook/src/stale",
"mdbook/src/proposed"
].forEach(path => fs.mkdirSync(path, {resursive: true}))
const TOC = "**Table of Contents**\n\n<\!-- toc -->\n"
module.exports = async ({github, context}) => {
const owner = 'polkadot-fellows'
const repo = 'RFCs'
const prs = await github.paginate(github.rest.pulls.list, {owner, repo, state: 'open'})
/*
The open PRs are potential proposed RFCs.
We iterate over them and filter those that include a new RFC markdown file.
*/
for (const pr of prs) {
const addedMarkdownFiles = (
await github.rest.pulls.listFiles({
owner, repo,
pull_number: pr.number,
})
).data.filter(
(file) => file.status === "added" && file.filename.startsWith("text/") && file.filename.includes(".md"),
);
if (addedMarkdownFiles.length !== 1) continue;
const [rfcFile] = addedMarkdownFiles;
const rawText = await (await fetch(rfcFile.raw_url)).text();
const isNew = new Date(pr.created_at) > dateDaysBefore(NEW_RFC_PERIOD_DAYS)
const isStale = new Date(pr.updated_at) < dateDaysBefore(STALE_RFC_PERIOD_DAYS)
const status = isNew ? 'new' : (isStale ? 'stale' : 'proposed')
const filename = rfcFile.filename.replace("text/", "")
fs.writeFileSync(
`mdbook/src/${status}/${filename}`,
`[(source)](${pr.html_url})\n\n`
+ TOC
+ rawText
)
}
// Copy the approved (already-merged) RFCs markdown files, first adding a source link at the top and a TOC.
for (const file of fs.readdirSync("text/")) {
if (!file.endsWith(".md")) continue;
const text = `[(source)](https://github.com/polkadot-fellows/RFCs/blob/main/text/${file})\n\n`
+ TOC
+ fs.readFileSync(`text/${file}`)
fs.writeFileSync(`mdbook/src/approved/${file}`, text)
}
}
+49
View File
@@ -0,0 +1,49 @@
name: mdBook
on:
push:
branches:
- main
schedule:
- cron: "0 0 * * *" # Once a day
jobs:
mdbook:
runs-on: ubuntu-latest
permissions:
# For writing to gh-pages branch.
contents: write
steps:
- name: Checkout this repo
uses: actions/checkout@v3
# Gather mdbook source files - approved (merged) files, and open PRs.
- name: Gather mdbook sources
uses: actions/github-script@v7
with:
script: |
const script = require('.github/scripts/gather-mdbook-sources.js')
await script({github, context})
- name: Build the mdbook SUMMARY.md
uses: actions/github-script@v7
with:
script: |
const script = require('.github/scripts/build-mdbook-summary.js')
await script({github, context})
- name: Setup mdBook binary
uses: peaceiris/actions-mdbook@adeb05db28a0c0004681db83893d56c0388ea9ea # v1.2.0
with:
mdbook-version: '0.4.36'
- name: Install dependencies
run: |
cargo install mdbook-toc@0.14.1
- name: Generate the mdbook
run: |
cd mdbook
rm -rf ./book/
mdbook build --dest-dir ./book/
- name: Deploy to github pages
uses: peaceiris/actions-gh-pages@373f7f263a76c20808c831209c920827a82a2847 # v3.9.3
with:
publish_dir: ./mdbook/book
github_token: ${{ secrets.GITHUB_TOKEN }}
+11
View File
@@ -0,0 +1,11 @@
# Autogenerated
book/
# Generated by the `build-mdbook-summary` script
SUMMARY.md
# Generated by the `gather-mdbook-sources` script
src/approved/
src/new/
src/proposed/
src/stale/
+8
View File
@@ -0,0 +1,8 @@
# RFCs book
An mdbook-based web page for presenting approved and proposed RFCs.
## Prerequisites
- [mdbook](https://github.com/rust-lang/mdBook)
- [mdbook-toc](https://github.com/badboy/mdbook-toc)
+23
View File
@@ -0,0 +1,23 @@
[book]
title = "Polkadot Fellowship RFCs"
description = "An online book of RFCs approved or proposed within the Polkadot Fellowship."
src = "src"
[build]
create-missing = false
[output.html]
additional-css = ["theme/polkadot.css"]
default-theme = "polkadot"
preferred-dark-theme = "polkadot"
copy-fonts = true
no-section-label = true
[output.html.font]
enable = true
woff = true
[preprocessor.toc]
command = "mdbook-toc"
renderer = ["html"]
max-level = 3
@@ -0,0 +1 @@
<svg id="Content" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 7277.19 2000"><defs><style>.cls-1{fill:#e6007a;}</style></defs><path d="M2384.74,504.19c-77.17,0-151.58,9.65-181.9,17.92-44.09,12.4-55.12,31.69-63.39,71.65l-175,807.52c-2.76,16.54-5.52,30.32-5.52,44.1,0,40,26.19,66.14,68.9,66.14,46.86,0,66.15-30.31,75.8-77.16l49.6-230.13c34.45,4.13,79.93,8.26,144.7,8.26,285.25,0,463-154.33,463-387.22C2760.94,621.32,2619,504.19,2384.74,504.19Zm-93.7,576c-44.1,0-78.55-1.37-110.25-5.51l92.33-428.56c28.94-4.14,71.66-9.65,115.76-9.65,151.58,0,228.75,71.66,228.75,190.17C2617.63,978.23,2507.39,1080.2,2291,1080.2Z"/><path d="M6874.28,1245.57c-23.42,0-38.58,13.78-67.52,45.47-51,52.37-82.68,81.3-122.64,81.3-35.83,0-55.13-28.93-55.13-75.79,0-26.18,5.52-57.87,12.41-92.32l51-239.78h153c48.23,0,77.17-27.56,77.17-77.17,0-27.56-17.91-48.23-59.25-48.23H6719.94l24.81-111.62c2.75-16.53,5.51-31.69,5.51-45.47,0-38.59-26.18-66.15-68.9-66.15-45.48,0-66.15,30.32-75.79,77.17l-31.7,146.07h-64.76c-49.61,0-78.55,27.56-78.55,77.17,0,27.56,19.29,48.23,60.63,48.23h56.5l-51,237c-5.51,26.18-12.4,68.9-12.4,113,0,111.62,57.88,192.92,181.9,192.92,71.66,0,135.05-35.83,183.28-78.55,46.85-41.34,81.3-92.32,81.3-125.4C6930.78,1271.75,6906,1245.57,6874.28,1245.57Z"/><path d="M3704.86,585.5c0-40-27.56-66.15-70.28-66.15-45.47,0-66.14,30.32-75.79,77.17l-172.25,800.63c-4.14,16.54-6.89,30.32-6.89,44.1,0,40,27.56,66.14,68.9,66.14,46.85,0,67.52-30.32,77.17-77.17L3698,629.59C3700.73,613.06,3704.86,599.28,3704.86,585.5Z"/><path d="M6164.6,825.27c-220.48,0-370.69,219.11-370.69,427.19,0,3.9.1,7.75.22,11.59-34.58,52.5-78.76,106.92-109.08,106.92-22.05,0-30.32-20.67-30.32-52.37,0-38.58,11-103.35,23.43-159.85l114.38-529.16c2.75-16.53,5.51-30.31,5.51-44.09,0-40-26.18-66.15-68.9-66.15-46.85,0-66.15,30.32-75.79,77.17l-62,286.63C5558.27,848.7,5510,825.27,5437,825.27c-146.43,0-293.7,112.73-351.1,285.6-63.21,163.42-119.7,260.1-164.27,260.1-16.53,0-26.18-13.78-26.18-37.21,0-68.9,38.58-237,55.12-318.32,5.51-30.32,8.27-42.72,8.27-60.64,0-60.63-100.6-132.29-231.51-132.29-151.37,0-288.48,95.86-357.24,238.35C4268,1241.28,4174.3,1371,4127.91,1371c-20.67,0-27.56-26.19-33.07-51l-34.45-190.17,210.84-172.25c19.29-16.54,44.09-40,44.09-70.28,0-37.2-24.8-62-62-62-27.56,0-51,16.54-74.41,35.83L3862,1122.92l106.11-493.33c2.76-16.53,6.89-30.31,6.89-44.09,0-40-27.56-66.15-70.28-66.15-45.47,0-66.14,30.32-75.79,77.17l-172.25,800.63c-4.13,16.54-6.89,30.32-6.89,44.1,0,40,27.56,66.14,68.9,66.14,46.85,0,67.52-30.32,77.17-77.17l22.05-103.35,129.53-104.73,31.7,159.85c12.4,63.39,45.47,125.4,130.91,125.4,85,0,151.86-77.63,218.85-182.52,20.33,109.86,98.48,182.52,206.95,182.52,108.86,0,183.27-64.77,231.5-151.58v2.75c0,89.58,45.48,148.83,125.4,148.83,72.26,0,132.29-43.57,185.91-136.21,30.41,80.73,98.38,136.21,193,136.21,111.62,0,191.54-67.52,242.53-161.23v8.27c0,99.22,49.61,153,130.91,153,71.78,0,132.82-41.66,184.86-109.53,39.61,67.8,110.59,109.53,206.5,109.53,220.48,0,370.68-219.1,370.68-428.56C6407.13,931.38,6317.56,825.27,6164.6,825.27ZM4790.73,1105c-40,172.25-125.4,270.09-221.86,270.09-64.77,0-100.6-49.61-100.6-124,0-146.07,106.11-303.17,248-303.17,42.71,0,75.79,12.41,104.73,30.32Zm767.54-73c-44.09,202.57-144.69,343.13-254.93,343.13-60.63,0-96.46-46.85-96.46-124,0-147.45,102-300.41,238.4-300.41,52.36,0,92.32,17.91,121.26,41.34ZM6053,1375.1c-79.92,0-113-57.88-113-130.91,0-133.67,92.32-286.63,208.08-286.63,79.92,0,113,57.88,113,130.91C6261.06,1223.52,6168.74,1375.1,6053,1375.1Z"/><path d="M3104.06,825.27c-220.49,0-370.69,219.11-370.69,427.19,0,148.82,89.57,254.93,242.53,254.93,220.48,0,370.69-219.1,370.69-428.56C3346.59,931.38,3257,825.27,3104.06,825.27ZM2992.44,1375.1c-79.93,0-113-57.88-113-130.91,0-133.67,92.33-286.63,208.08-286.63,79.93,0,113,57.88,113,130.91C3200.52,1223.52,3108.19,1375.1,2992.44,1375.1Z"/><ellipse class="cls-1" cx="1000" cy="441.78" rx="254.27" ry="147.95"/><ellipse class="cls-1" cx="1000" cy="1556.15" rx="254.27" ry="147.95"/><ellipse class="cls-1" cx="517.47" cy="720.38" rx="254.27" ry="147.95" transform="translate(-365.13 808.33) rotate(-60)"/><ellipse class="cls-1" cx="1482.53" cy="1277.56" rx="254.27" ry="147.95" transform="translate(-365.13 1922.69) rotate(-60)"/><ellipse class="cls-1" cx="517.47" cy="1277.56" rx="147.95" ry="254.27" transform="translate(-569.45 429.89) rotate(-30)"/><ellipse class="cls-1" cx="1482.53" cy="720.38" rx="147.95" ry="254.27" transform="translate(-161.57 837.78) rotate(-30)"/></svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

+1
View File
@@ -0,0 +1 @@
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg>

After

Width:  |  Height:  |  Size: 963 B

+8
View File
@@ -0,0 +1,8 @@
<p><img width="30%" src="images/Polkadot_Logo_Horizontal_Pink_Black.svg" alt="Polkadot logo" /></p>
# Introduction
This book contains the Polkadot Fellowship Requests for Comments (RFCs)
detailing proposed changes to the technical implementation of the Polkadot network.
<p><img width="2%" src="images/github-mark.svg" alt="GitHub logo" />&nbsp;<a href="https://github.com/polkadot-fellows/RFCs/">polkadot-fellows/RFCs</a></p>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
@font-face {
font-family:Unbounded;
src:url(./Unbounded-ExtraLight.woff2) format("woff2");
font-weight:200;
font-style:normal;
font-display:block
}
@font-face {
font-family:Unbounded;
src:url(./Unbounded-Light.woff2) format("woff2");
font-weight:300;
font-style:normal;
font-display:block
}
@font-face {
font-family:Unbounded;
src:url(./Unbounded-Regular.woff2) format("woff2");
font-weight:400;
font-style:normal;
font-display:block
}
@font-face {
font-family:Unbounded;
src:url(./Unbounded-Medium.woff2) format("woff2");
font-weight:500;
font-style:normal;
font-display:block
}
@font-face {
font-family:Unbounded;
src:url(./Unbounded-Bold.woff2) format("woff2");
font-weight:700;
font-style:normal;
font-display:block
}
@font-face {
font-family:Unbounded;
src:url(./Unbounded-Black.woff2) format("woff2");
font-weight:900;
font-style:normal;
font-display:block
}
+354
View File
@@ -0,0 +1,354 @@
{{!--
README:
As instructed by the docs (https://rust-lang.github.io/mdBook/format/theme/index.html),
this file is copied from the source repository and modified as need.
This file was taken from here: https://github.com/rust-lang/mdBook/blob/208d5ea7abc19ca47b22032ba2a4a4046ffe0902/src/theme/index.hbs,
and modified in one place to add Polkadot theme to the theme selection widget.
--}}
<!DOCTYPE HTML>
<html lang="{{ language }}" class="{{ default_theme }}" dir="{{ text_direction }}">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>{{ title }}</title>
{{#if is_print }}
<meta name="robots" content="noindex">
{{/if}}
{{#if base_url}}
<base href="{{ base_url }}">
{{/if}}
<!-- Custom HTML head -->
{{> head}}
<meta name="description" content="{{ description }}">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
{{#if favicon_svg}}
<link rel="icon" href="{{ path_to_root }}favicon.svg">
{{/if}}
{{#if favicon_png}}
<link rel="shortcut icon" href="{{ path_to_root }}favicon.png">
{{/if}}
<link rel="stylesheet" href="{{ path_to_root }}css/variables.css">
<link rel="stylesheet" href="{{ path_to_root }}css/general.css">
<link rel="stylesheet" href="{{ path_to_root }}css/chrome.css">
{{#if print_enable}}
<link rel="stylesheet" href="{{ path_to_root }}css/print.css" media="print">
{{/if}}
<!-- Fonts -->
<link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
{{#if copy_fonts}}
<link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css">
{{/if}}
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="{{ path_to_root }}highlight.css">
<link rel="stylesheet" href="{{ path_to_root }}tomorrow-night.css">
<link rel="stylesheet" href="{{ path_to_root }}ayu-highlight.css">
<!-- Custom theme stylesheets -->
{{#each additional_css}}
<link rel="stylesheet" href="{{ ../path_to_root }}{{ this }}">
{{/each}}
{{#if mathjax_support}}
<!-- MathJax -->
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
{{/if}}
</head>
<body class="sidebar-visible no-js">
<div id="body-container">
<!-- Provide site root to javascript -->
<script>
var path_to_root = "{{ path_to_root }}";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "{{ preferred_dark_theme }}" : "{{ default_theme }}";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('{{ default_theme }}')
html.classList.add(theme);
var body = document.querySelector('body');
body.classList.remove('no-js')
body.classList.add('js');
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
var body = document.querySelector('body');
var sidebar = null;
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
body.classList.remove('sidebar-visible');
body.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
{{#toc}}{{/toc}}
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<!-- Track and set sidebar scroll position -->
<script>
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
sidebarScrollbox.addEventListener('click', function(e) {
if (e.target.tagName === 'A') {
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
}
}, { passive: true });
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
sessionStorage.removeItem('sidebar-scroll');
if (sidebarScrollTop) {
// preserve sidebar scroll position when navigating via links within sidebar
sidebarScrollbox.scrollTop = sidebarScrollTop;
} else {
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
var activeSection = document.querySelector('#sidebar .active');
if (activeSection) {
activeSection.scrollIntoView({ block: 'center' });
}
}
</script>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
{{> header}}
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="polkadot">Polkadot</button></li>
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
{{#if search_enabled}}
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
{{/if}}
</div>
<h1 class="menu-title">{{ book_title }}</h1>
<div class="right-buttons">
{{#if print_enable}}
<a href="{{ path_to_root }}print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
{{/if}}
{{#if git_repository_url}}
<a href="{{git_repository_url}}" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa {{git_repository_icon}}"></i>
</a>
{{/if}}
{{#if git_repository_edit_url}}
<a href="{{git_repository_edit_url}}" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
{{/if}}
</div>
</div>
{{#if search_enabled}}
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
{{/if}}
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
{{{ content }}}
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
{{#previous}}
<a rel="prev" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
{{/previous}}
{{#next}}
<a rel="next prefetch" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
{{/next}}
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
{{#previous}}
<a rel="prev" href="{{ path_to_root }}{{link}}" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
{{/previous}}
{{#next}}
<a rel="next prefetch" href="{{ path_to_root }}{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
{{/next}}
</nav>
</div>
{{#if live_reload_endpoint}}
<!-- Livereload script (if served using the cli tool) -->
<script>
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "{{{live_reload_endpoint}}}";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload();
}
};
window.onbeforeunload = function() {
socket.close();
}
</script>
{{/if}}
{{#if google_analytics}}
<!-- Google Analytics Tag -->
<script>
var localAddrs = ["localhost", "127.0.0.1", ""];
// make sure we don't activate google analytics if the developer is
// inspecting the book locally...
if (localAddrs.indexOf(document.location.hostname) === -1) {
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', '{{google_analytics}}', 'auto');
ga('send', 'pageview');
}
</script>
{{/if}}
{{#if playground_line_numbers}}
<script>
window.playground_line_numbers = true;
</script>
{{/if}}
{{#if playground_copyable}}
<script>
window.playground_copyable = true;
</script>
{{/if}}
{{#if playground_js}}
<script src="{{ path_to_root }}ace.js"></script>
<script src="{{ path_to_root }}editor.js"></script>
<script src="{{ path_to_root }}mode-rust.js"></script>
<script src="{{ path_to_root }}theme-dawn.js"></script>
<script src="{{ path_to_root }}theme-tomorrow_night.js"></script>
{{/if}}
{{#if search_js}}
<script src="{{ path_to_root }}elasticlunr.min.js"></script>
<script src="{{ path_to_root }}mark.min.js"></script>
<script src="{{ path_to_root }}searcher.js"></script>
{{/if}}
<script src="{{ path_to_root }}clipboard.min.js"></script>
<script src="{{ path_to_root }}highlight.js"></script>
<script src="{{ path_to_root }}book.js"></script>
<!-- Custom JS scripts -->
{{#each additional_js}}
<script src="{{ ../path_to_root }}{{this}}"></script>
{{/each}}
{{#if is_print}}
{{#if mathjax_support}}
<script>
window.addEventListener('load', function() {
MathJax.Hub.Register.StartupHook('End', function() {
window.setTimeout(window.print, 100);
});
});
</script>
{{else}}
<script>
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
</script>
{{/if}}
{{/if}}
</div>
</body>
</html>
+70
View File
@@ -0,0 +1,70 @@
html.polkadot {
font-family: "Open Sans", sans-serif;
}
.polkadot {
--pink500: #E6007A;
--purple600: #442299;
--purple500: #552BBF;
--purple400: #6D3AEE;
--cyan700: #0094D4;
--cyan600: #00A6ED;
--cyan500: #00B2FF;
--green700: #48CC81;
--green600: #51E591;
--green500: #56F39A;
--lime700: #A9CC29;
--lime600: #BEE52E;
--lime500: #D3FF33;
--purple700: #321D47;
--purple800: #28123E;
--purple900: #1C0533;
--purple300: #DAE0F2;
--purple200: #E6EAF6;
--purple100: #F3F5FB;
--bg: var(--purple100);
--fg: #262625;
--sidebar-bg: var(--purple800);
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #505254;
--sidebar-active: var(--pink500);
--sidebar-spacer: var(--purple700);
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #262625;
--links: #2b79a2;
--inline-code-color: #6e6b5e;
--theme-popup-bg: var(--purple200);
--theme-popup-border: var(--purple300);
--theme-hover: var(--purple200);
--quote-bg: var(--purple200);
--quote-border: var(--purple300);
--warning-border: #ff8e00;
--table-border-color: var(--purple200);
--table-header-bg: var(--purple300);
--table-alternate-bg: var(--purple200);
--searchbar-border-color: #aaa;
--searchbar-bg: #fafafa;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #888;
--searchresults-li-bg: #dec2a2;
--search-mark-bg: var(--cyan500);
--color-scheme: light;
}