diff --git a/.github/scripts/build-mdbook-summary.js b/.github/scripts/build-mdbook-summary.js new file mode 100644 index 000000000..4b0a456a6 --- /dev/null +++ b/.github/scripts/build-mdbook-summary.js @@ -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/") +} diff --git a/.github/scripts/gather-mdbook-sources.js b/.github/scripts/gather-mdbook-sources.js new file mode 100644 index 000000000..50e48dfc2 --- /dev/null +++ b/.github/scripts/gather-mdbook-sources.js @@ -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) + } +} diff --git a/.github/workflows/mdbook.yml b/.github/workflows/mdbook.yml new file mode 100644 index 000000000..19508039e --- /dev/null +++ b/.github/workflows/mdbook.yml @@ -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 }} diff --git a/mdbook/.gitignore b/mdbook/.gitignore new file mode 100644 index 000000000..831de81c9 --- /dev/null +++ b/mdbook/.gitignore @@ -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/ diff --git a/mdbook/README.md b/mdbook/README.md new file mode 100644 index 000000000..46f3a29b5 --- /dev/null +++ b/mdbook/README.md @@ -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) diff --git a/mdbook/book.toml b/mdbook/book.toml new file mode 100644 index 000000000..2eab700e4 --- /dev/null +++ b/mdbook/book.toml @@ -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 diff --git a/mdbook/src/images/Polkadot_Logo_Horizontal_Pink_Black.svg b/mdbook/src/images/Polkadot_Logo_Horizontal_Pink_Black.svg new file mode 100644 index 000000000..909415405 --- /dev/null +++ b/mdbook/src/images/Polkadot_Logo_Horizontal_Pink_Black.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mdbook/src/images/github-mark.svg b/mdbook/src/images/github-mark.svg new file mode 100644 index 000000000..37fa923df --- /dev/null +++ b/mdbook/src/images/github-mark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mdbook/src/introduction.md b/mdbook/src/introduction.md new file mode 100644 index 000000000..31f4cc119 --- /dev/null +++ b/mdbook/src/introduction.md @@ -0,0 +1,8 @@ +

Polkadot logo

+ +# Introduction + +This book contains the Polkadot Fellowship Requests for Comments (RFCs) +detailing proposed changes to the technical implementation of the Polkadot network. + +

GitHub logo polkadot-fellows/RFCs

diff --git a/mdbook/theme/fonts/Unbounded-Black.woff2 b/mdbook/theme/fonts/Unbounded-Black.woff2 new file mode 100644 index 000000000..6bf337eee Binary files /dev/null and b/mdbook/theme/fonts/Unbounded-Black.woff2 differ diff --git a/mdbook/theme/fonts/Unbounded-Bold.woff2 b/mdbook/theme/fonts/Unbounded-Bold.woff2 new file mode 100644 index 000000000..add77ee4f Binary files /dev/null and b/mdbook/theme/fonts/Unbounded-Bold.woff2 differ diff --git a/mdbook/theme/fonts/Unbounded-ExtraLight.woff2 b/mdbook/theme/fonts/Unbounded-ExtraLight.woff2 new file mode 100644 index 000000000..7ee20a6bf Binary files /dev/null and b/mdbook/theme/fonts/Unbounded-ExtraLight.woff2 differ diff --git a/mdbook/theme/fonts/Unbounded-Light.woff2 b/mdbook/theme/fonts/Unbounded-Light.woff2 new file mode 100644 index 000000000..f99890344 Binary files /dev/null and b/mdbook/theme/fonts/Unbounded-Light.woff2 differ diff --git a/mdbook/theme/fonts/Unbounded-Medium.woff2 b/mdbook/theme/fonts/Unbounded-Medium.woff2 new file mode 100644 index 000000000..b16d92b11 Binary files /dev/null and b/mdbook/theme/fonts/Unbounded-Medium.woff2 differ diff --git a/mdbook/theme/fonts/Unbounded-Regular.woff2 b/mdbook/theme/fonts/Unbounded-Regular.woff2 new file mode 100644 index 000000000..5db9542d0 Binary files /dev/null and b/mdbook/theme/fonts/Unbounded-Regular.woff2 differ diff --git a/mdbook/theme/fonts/fonts.css b/mdbook/theme/fonts/fonts.css new file mode 100644 index 000000000..f976c9d7e --- /dev/null +++ b/mdbook/theme/fonts/fonts.css @@ -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 +} \ No newline at end of file diff --git a/mdbook/theme/index.hbs b/mdbook/theme/index.hbs new file mode 100644 index 000000000..a88a989be --- /dev/null +++ b/mdbook/theme/index.hbs @@ -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. +--}} + + + + + + + {{ title }} + {{#if is_print }} + + {{/if}} + {{#if base_url}} + + {{/if}} + + + + {{> head}} + + + + + + {{#if favicon_svg}} + + {{/if}} + {{#if favicon_png}} + + {{/if}} + + + + {{#if print_enable}} + + {{/if}} + + + + {{#if copy_fonts}} + + {{/if}} + + + + + + + + {{#each additional_css}} + + {{/each}} + + {{#if mathjax_support}} + + + {{/if}} + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ {{> header}} + + + + {{#if search_enabled}} + + {{/if}} + + + + +
+
+ {{{ content }}} +
+ + +
+
+ + + +
+ + {{#if live_reload_endpoint}} + + + {{/if}} + + {{#if google_analytics}} + + + {{/if}} + + {{#if playground_line_numbers}} + + {{/if}} + + {{#if playground_copyable}} + + {{/if}} + + {{#if playground_js}} + + + + + + {{/if}} + + {{#if search_js}} + + + + {{/if}} + + + + + + + {{#each additional_js}} + + {{/each}} + + {{#if is_print}} + {{#if mathjax_support}} + + {{else}} + + {{/if}} + {{/if}} + +
+ + diff --git a/mdbook/theme/polkadot.css b/mdbook/theme/polkadot.css new file mode 100644 index 000000000..4fb84c56e --- /dev/null +++ b/mdbook/theme/polkadot.css @@ -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; +}