From 51dc8d4c01f90d22d958d2778aa3152a5094055c Mon Sep 17 00:00:00 2001 From: Abdulbasit sadiq <76534194+Dramoka@users.noreply.github.com> Date: Wed, 30 Dec 2020 03:23:51 +0100 Subject: [PATCH] Initial commit --- .devcontainer.json | 12 + .gitattributes | 2 + .github/ISSUE_TEMPLATE/bug.md | 20 + .github/ISSUE_TEMPLATE/feature_request.md | 20 + .github/ISSUE_TEMPLATE/upgrade.md | 10 + .github/workflows/chatops.yaml | 195 +++ .github/workflows/check_cdns.yaml | 13 + .github/workflows/check_config.yaml | 78 + .github/workflows/ci.yaml | 58 + .github/workflows/docker-nbdev.yaml | 8 + .github/workflows/docker.yaml | 33 + .github/workflows/gh-page.yaml | 17 + .github/workflows/issue_reminder.yaml | 26 + .github/workflows/setup.yaml | 105 ++ .github/workflows/upgrade.yaml | 275 ++++ .gitignore | 14 + CNAME | 1 + Gemfile | 43 + Gemfile.lock | 154 ++ LICENSE | 201 +++ Makefile | 53 + README.md | 553 +++++++ _action_files/Dockerfile | 9 + _action_files/__init__.py | 0 _action_files/action.yml | 17 + _action_files/action_entrypoint.sh | 48 + _action_files/check_js.sh | 25 + _action_files/fast_template.py | 29 + _action_files/fastpages-jekyll.Dockerfile | 7 + _action_files/fastpages.tpl | 22 + _action_files/hide.tpl | 44 + _action_files/nb2post.py | 22 + _action_files/parse_netlify.py | 7 + _action_files/pr_comment.sh | 39 + _action_files/settings.ini | 43 + _action_files/word2post.py | 8 + _action_files/word2post.sh | 33 + _action_files/word_front_matter.txt | 3 + _config.yml | 122 ++ _fastpages_docs/CONTRIBUTING.md | 63 + _fastpages_docs/DEVELOPMENT.md | 102 ++ _fastpages_docs/NOTEBOOK_FOOTNOTES.md | 30 + _fastpages_docs/README_TEMPLATE.md | 29 + _fastpages_docs/TROUBLESHOOTING.md | 66 + _fastpages_docs/UPGRADE.md | 71 + _fastpages_docs/_checkbox.png | Bin 0 -> 21148 bytes _fastpages_docs/_manual_setup.md | 41 + _fastpages_docs/_paginate.png | Bin 0 -> 6990 bytes _fastpages_docs/_post_tags.png | Bin 0 -> 21294 bytes _fastpages_docs/_setup_pr_template.md | 41 + _fastpages_docs/_show_image_true.png | Bin 0 -> 82874 bytes _fastpages_docs/_upgrade_pr.md | 14 + _fastpages_docs/annotate.png | Bin 0 -> 26346 bytes _fastpages_docs/enable_actions.png | Bin 0 -> 42110 bytes _fastpages_docs/fastapges-setup.gif | Bin 0 -> 5927801 bytes _fastpages_docs/highlight_dracula.png | Bin 0 -> 74027 bytes _fastpages_docs/highlight_original.png | Bin 0 -> 66383 bytes _fastpages_docs/upgrade_step1.png | Bin 0 -> 34335 bytes _fastpages_docs/upgrade_step2.png | Bin 0 -> 182730 bytes _fastpages_docs/upgrade_step3.png | Bin 0 -> 158877 bytes _fastpages_docs/version.txt | 1 + _includes/alert.html | 4 + _includes/custom-head.html | 63 + _includes/favicons.html | 1 + _includes/google-analytics.html | 6 + _includes/head.html | 15 + _includes/image-r | 11 + _includes/image.html | 8 + _includes/important.html | 4 + _includes/info.html | 4 + _includes/note.html | 4 + _includes/notebook_binder_link.html | 5 + _includes/notebook_colab_link.html | 5 + _includes/notebook_github_link.html | 9 + _includes/post_list.html | 9 + _includes/post_list_image_card.html | 16 + _includes/reading_time.html | 8 + _includes/screenshot | 7 + _includes/tip.html | 4 + _includes/toc.html | 20 + _includes/twitter.html | 8 + _includes/utterances.html | 9 + _includes/video.html | 3 + _includes/warning.html | 4 + _includes/youtube.html | 9 + _layouts/categories.html | 9 + _layouts/home.html | 82 + _layouts/notebook.html | 5 + _layouts/post.html | 67 + _notebooks/2020-02-20-test.ipynb | 847 ++++++++++ .../2020-02-21-introducing-fastpages.ipynb | 573 +++++++ _notebooks/2020-09-01-fastcore.ipynb | 1366 +++++++++++++++++ _notebooks/2020-11-17-linkcheck.ipynb | 470 ++++++ _notebooks/README.md | 14 + _notebooks/fastcore_imgs/bwtm.jpg | Bin 0 -> 16710 bytes _notebooks/fastcore_imgs/td.png | Bin 0 -> 148691 bytes .../fastlinkcheck_images/fastlinkcheck.png | Bin 0 -> 55088 bytes _notebooks/my_icons/fastai_logo.png | Bin 0 -> 7125 bytes _pages/404.html | 25 + _pages/about.md | 11 + _pages/search.html | 18 + _pages/tags.html | 36 + _plugins/footnote-detail.rb | 9 + _plugins/footnote.rb | 15 + _posts/2020-01-14-test-markdown-post.md | 103 ++ _posts/2020-03-06-fastpages-actions.md | 282 ++++ _posts/2020-12-10-codespaces.md | 114 ++ _posts/README.md | 15 + _sass/minima/custom-styles.scss | 11 + _sass/minima/custom-variables.scss | 9 + _sass/minima/fastpages-dracula-highlight.scss | 222 +++ _sass/minima/fastpages-styles.scss | 258 ++++ ...020-01-01-Microsoft-Word-Example-Post.docx | Bin 0 -> 407563 bytes _word/README.md | 21 + action.yml | 17 + assets/badges/binder.svg | 1 + assets/badges/colab.svg | 1 + assets/badges/github.svg | 1 + assets/js/search-data.json | 32 + assets/js/search.js | 300 ++++ assets/js/vendor/lunr.min.js | 6 + docker-compose.yml | 44 + images/chart-preview.png | Bin 0 -> 198493 bytes images/copied_from_nb/README.md | 3 + images/diagram.png | Bin 0 -> 42576 bytes .../fastpages_posts/actions/actions_logo.png | Bin 0 -> 17486 bytes images/fastpages_posts/actions/pr_1.png | Bin 0 -> 367199 bytes images/fastpages_posts/actions/pr_2.png | Bin 0 -> 249181 bytes .../fastpages_posts/codespaces/codespaces.png | Bin 0 -> 47373 bytes images/favicon.ico | Bin 0 -> 2807 bytes images/logo.png | Bin 0 -> 7125 bytes index.html | 15 + 132 files changed, 8065 insertions(+) create mode 100644 .devcontainer.json create mode 100644 .gitattributes create mode 100644 .github/ISSUE_TEMPLATE/bug.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/upgrade.md create mode 100755 .github/workflows/chatops.yaml create mode 100644 .github/workflows/check_cdns.yaml create mode 100644 .github/workflows/check_config.yaml create mode 100755 .github/workflows/ci.yaml create mode 100644 .github/workflows/docker-nbdev.yaml create mode 100755 .github/workflows/docker.yaml create mode 100644 .github/workflows/gh-page.yaml create mode 100644 .github/workflows/issue_reminder.yaml create mode 100755 .github/workflows/setup.yaml create mode 100755 .github/workflows/upgrade.yaml create mode 100644 .gitignore create mode 100644 CNAME create mode 100755 Gemfile create mode 100755 Gemfile.lock create mode 100644 LICENSE create mode 100755 Makefile create mode 100755 README.md create mode 100755 _action_files/Dockerfile create mode 100755 _action_files/__init__.py create mode 100644 _action_files/action.yml create mode 100755 _action_files/action_entrypoint.sh create mode 100755 _action_files/check_js.sh create mode 100755 _action_files/fast_template.py create mode 100755 _action_files/fastpages-jekyll.Dockerfile create mode 100644 _action_files/fastpages.tpl create mode 100644 _action_files/hide.tpl create mode 100755 _action_files/nb2post.py create mode 100644 _action_files/parse_netlify.py create mode 100755 _action_files/pr_comment.sh create mode 100644 _action_files/settings.ini create mode 100755 _action_files/word2post.py create mode 100755 _action_files/word2post.sh create mode 100644 _action_files/word_front_matter.txt create mode 100644 _config.yml create mode 100644 _fastpages_docs/CONTRIBUTING.md create mode 100644 _fastpages_docs/DEVELOPMENT.md create mode 100644 _fastpages_docs/NOTEBOOK_FOOTNOTES.md create mode 100644 _fastpages_docs/README_TEMPLATE.md create mode 100644 _fastpages_docs/TROUBLESHOOTING.md create mode 100644 _fastpages_docs/UPGRADE.md create mode 100644 _fastpages_docs/_checkbox.png create mode 100644 _fastpages_docs/_manual_setup.md create mode 100644 _fastpages_docs/_paginate.png create mode 100644 _fastpages_docs/_post_tags.png create mode 100644 _fastpages_docs/_setup_pr_template.md create mode 100644 _fastpages_docs/_show_image_true.png create mode 100644 _fastpages_docs/_upgrade_pr.md create mode 100644 _fastpages_docs/annotate.png create mode 100644 _fastpages_docs/enable_actions.png create mode 100644 _fastpages_docs/fastapges-setup.gif create mode 100644 _fastpages_docs/highlight_dracula.png create mode 100644 _fastpages_docs/highlight_original.png create mode 100644 _fastpages_docs/upgrade_step1.png create mode 100644 _fastpages_docs/upgrade_step2.png create mode 100644 _fastpages_docs/upgrade_step3.png create mode 100755 _fastpages_docs/version.txt create mode 100644 _includes/alert.html create mode 100755 _includes/custom-head.html create mode 100644 _includes/favicons.html create mode 100644 _includes/google-analytics.html create mode 100755 _includes/head.html create mode 100644 _includes/image-r create mode 100644 _includes/image.html create mode 100644 _includes/important.html create mode 100644 _includes/info.html create mode 100644 _includes/note.html create mode 100644 _includes/notebook_binder_link.html create mode 100644 _includes/notebook_colab_link.html create mode 100644 _includes/notebook_github_link.html create mode 100644 _includes/post_list.html create mode 100644 _includes/post_list_image_card.html create mode 100644 _includes/reading_time.html create mode 100644 _includes/screenshot create mode 100644 _includes/tip.html create mode 100644 _includes/toc.html create mode 100644 _includes/twitter.html create mode 100644 _includes/utterances.html create mode 100644 _includes/video.html create mode 100644 _includes/warning.html create mode 100644 _includes/youtube.html create mode 100644 _layouts/categories.html create mode 100644 _layouts/home.html create mode 100644 _layouts/notebook.html create mode 100644 _layouts/post.html create mode 100644 _notebooks/2020-02-20-test.ipynb create mode 100644 _notebooks/2020-02-21-introducing-fastpages.ipynb create mode 100755 _notebooks/2020-09-01-fastcore.ipynb create mode 100755 _notebooks/2020-11-17-linkcheck.ipynb create mode 100644 _notebooks/README.md create mode 100644 _notebooks/fastcore_imgs/bwtm.jpg create mode 100644 _notebooks/fastcore_imgs/td.png create mode 100755 _notebooks/fastlinkcheck_images/fastlinkcheck.png create mode 100644 _notebooks/my_icons/fastai_logo.png create mode 100644 _pages/404.html create mode 100644 _pages/about.md create mode 100644 _pages/search.html create mode 100644 _pages/tags.html create mode 100644 _plugins/footnote-detail.rb create mode 100644 _plugins/footnote.rb create mode 100755 _posts/2020-01-14-test-markdown-post.md create mode 100755 _posts/2020-03-06-fastpages-actions.md create mode 100755 _posts/2020-12-10-codespaces.md create mode 100644 _posts/README.md create mode 100644 _sass/minima/custom-styles.scss create mode 100644 _sass/minima/custom-variables.scss create mode 100755 _sass/minima/fastpages-dracula-highlight.scss create mode 100755 _sass/minima/fastpages-styles.scss create mode 100644 _word/2020-01-01-Microsoft-Word-Example-Post.docx create mode 100644 _word/README.md create mode 100644 action.yml create mode 100644 assets/badges/binder.svg create mode 100644 assets/badges/colab.svg create mode 100644 assets/badges/github.svg create mode 100644 assets/js/search-data.json create mode 100644 assets/js/search.js create mode 100644 assets/js/vendor/lunr.min.js create mode 100755 docker-compose.yml create mode 100644 images/chart-preview.png create mode 100644 images/copied_from_nb/README.md create mode 100644 images/diagram.png create mode 100755 images/fastpages_posts/actions/actions_logo.png create mode 100755 images/fastpages_posts/actions/pr_1.png create mode 100755 images/fastpages_posts/actions/pr_2.png create mode 100755 images/fastpages_posts/codespaces/codespaces.png create mode 100644 images/favicon.ico create mode 100644 images/logo.png create mode 100644 index.html diff --git a/.devcontainer.json b/.devcontainer.json new file mode 100644 index 0000000..4c0bf09 --- /dev/null +++ b/.devcontainer.json @@ -0,0 +1,12 @@ +{ + "name": "fastpages-codespaces", + "dockerComposeFile": "docker-compose.yml", + "service": "watcher", + "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ], + "forwardPorts": [4000, 8080], + "appPort": [4000, 8080], + "extensions": ["ms-python.python", + "ms-azuretools.vscode-docker"], + "runServices": ["converter", "notebook", "jekyll", "watcher"] +} + diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..09bc62c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 0000000..cacde65 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,20 @@ +--- +name: Bug +about: Use this template for filing bugs +title: "" +labels: bug +assignees: '' + +--- + +## Required Prerequisites for filing a bug + +### You must follow ALL the steps in the [troubleshooting guide](https://github.com/fastai/fastpages/blob/master/_fastpages_docs/TROUBLESHOOTING.md). Not doing so may result in automatic closure of the issue. + + +## Required information + +1. Steps to reproduce the problem +2. A link to the notebook or markdown file where the error is occurring +3. If the error is happening in GitHub Actions, a link to the specific error along with how you are able to reproduce this error. You must provide this **in addition to the link to the notebook or markdown file**. +4. A screenshot / dump of relevant logs or error messages you are receiving from your local development environment. Instructions of running a local development server is provided in the [development guide](https://github.com/fastai/fastpages/blob/master/_fastpages_docs/DEVELOPMENT.md). diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..11fc491 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/upgrade.md b/.github/ISSUE_TEMPLATE/upgrade.md new file mode 100644 index 0000000..6e59c30 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/upgrade.md @@ -0,0 +1,10 @@ +--- +name: "[fastpages] Automated Upgrade" +about: "Trigger a PR for upgrading fastpages" +title: "[fastpages] Automated Upgrade" +labels: fastpages-automation +assignees: '' + +--- + +Opening this issue will trigger GitHub Actions to fetch the lastest version of [fastpages](https://github.com/fastai/fastpages). More information will be provided in forthcoming comments below. diff --git a/.github/workflows/chatops.yaml b/.github/workflows/chatops.yaml new file mode 100755 index 0000000..4974b2e --- /dev/null +++ b/.github/workflows/chatops.yaml @@ -0,0 +1,195 @@ +name: Chatops +on: [issue_comment] + +jobs: + trigger-chatops: + if: (github.event.issue.pull_request != null) && contains(github.event.comment.body, '/preview') && (github.repository == 'fastai/fastpages') + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + CHECK_RUN_NAME: "Draft-Site-Build" + runs-on: ubuntu-latest + steps: + + - name: see payload + run: | + echo "FULL PAYLOAD:\n${PAYLOAD}\n" + echo "PR_PAYLOAD PAYLOAD:\n${PR_PAYLOAD}" + env: + PAYLOAD: ${{ toJSON(github.event) }} + PR_PAYLOAD: ${{ github.event.pull_request }} + + - name: verify env exists + id: get_status + run: | + if [ -z ${NETLIFY_AUTH_TOKEN} ]; then echo "::set-output name=status::public"; else echo "::set-output name=status::private"; fi + + - name: make comment on PR if env does not exist + if: steps.get_status.outputs.status == 'public' + run: | + ./_action_files/pr_comment.sh "Was not able to generate site preview due to absent credentials." + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + + - name: Fetch context about the PR that has been commented on + id: chatops + uses: machine-learning-apps/actions-chatops@master + with: + TRIGGER_PHRASE: "/preview" + env: # you must supply GITHUB_TOKEN + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: 3.6 + + - name: install requests + run: pip3 install requests + + - name: add check run + id: create_check + if: steps.get_status.outputs.status == 'private' + shell: python + run: | + import os, requests + + sha = os.getenv('SHA') + token = os.getenv('GITHUB_TOKEN') + nwo = os.getenv('GITHUB_REPOSITORY') + name = os.getenv('CHECK_RUN_NAME') + + url = f'https://api.github.com/repos/{nwo}/check-runs' + + headers = {'authorization': f'token {token}', + 'accept': 'application/vnd.github.antiope-preview+json'} + + payload = { + 'name': f'{name}', + 'head_sha': f'{sha}', + 'status': 'in_progress', + 'output':{ + 'title': f'Building preview of site for {sha}.', + 'summary': ' ', + 'text': ' ' + }, + } + response = requests.post(url=url, headers=headers, json=payload) + print(response) + id = response.json()['id'] + print(f"::set-output name=id::{id}") + env: + SHA: ${{ steps.chatops.outputs.SHA }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: add label + if: steps.get_status.outputs.status == 'private' + run: | + import os, requests + nwo = os.getenv('GITHUB_REPOSITORY') + token = os.getenv('GITHUB_TOKEN') + pr_num = os.getenv('PR_NUM') + headers = {'Accept': 'application/vnd.github.symmetra-preview+json', + 'Authorization': f'token {token}'} + url = f"https://api.github.com/repos/{nwo}/issues/{pr_num}/labels" + data = {"labels": ["draft build pending"]} + result = requests.post(url=url, headers=headers, json=data) + # assert response.status_code == 201, f"Received status code of {response.status_code}" + print(result) + shell: python + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUM: ${{ steps.chatops.outputs.PULL_REQUEST_NUMBER }} + GITHUB_REPOSITORY: $GITHUB_REPOSITORY + + - name: Copy The PR's Branch Repository Contents + uses: actions/checkout@main + if: steps.get_status.outputs.status == 'private' + with: + ref: ${{ steps.chatops.outputs.SHA }} + + - name: convert notebooks and word docs to posts + uses: ./ # use the code in this repo to instead of fastai/fastpages@master + + - name: setup directories for Jekyll build + if: steps.get_status.outputs.status == 'private' + run: | + rm -rf _site + sudo chmod -R 777 . + + - name: Jekyll build with baseurl as root for netifly + if: steps.get_status.outputs.status == 'private' + uses: docker://fastai/fastpages-jekyll + with: + args: bash -c "jekyll build" + + - name: deploy to netlify + if: steps.get_status.outputs.status == 'private' + id: py + run: | + sudo npm install netlify-cli -g + netlify deploy --dir _site | tee _netlify_logs.txt + cat _netlify_logs.txt | python _action_files/parse_netlify.py + + - name: make comment on PR + if: steps.get_status.outputs.status == 'private' + run: | + MSG="A preview build of this branch has been generated for SHA: $SHA and can be viewed **live** at: ${URL}\n\nThe current fastpages site built from master can be viewed for comparison [here](https://fastpages.fast.ai/)" + echo "$MSG" + ./_action_files/pr_comment.sh "${MSG}" + env: + URL: ${{ steps.py.outputs.draft_url }} + SHA: ${{ steps.chatops.outputs.SHA }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + + - name: remove label + if: always() + run: | + import os, requests + nwo = os.getenv('GITHUB_REPOSITORY') + token = os.getenv('GITHUB_TOKEN') + pr_num = os.getenv('PR_NUM') + headers = {'Accept': 'application/vnd.github.symmetra-preview+json', + 'Authorization': f'token {token}'} + url = f"https://api.github.com/repos/{nwo}/issues/{pr_num}/labels/draft%20build%20pending" + result = requests.delete(url=url, headers=headers) + print(result) + shell: python + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUM: ${{ steps.chatops.outputs.PULL_REQUEST_NUMBER }} + GITHUB_REPOSITORY: $GITHUB_REPOSITORY + + # defensively clear check run each time + - name: clear check run + if: always() + continue-on-error: true + shell: python + run: | + import os, requests + + sha = os.getenv('SHA') + conclusion = os.getenv('WORKFLOW_CONCLUSION').lower() + token = os.getenv('GITHUB_TOKEN') + nwo = os.getenv('GITHUB_REPOSITORY') + check_run_id = os.getenv('CHECK_RUN_ID') + if not check_run_id: + quit() + + url = f'https://api.github.com/repos/{nwo}/check-runs/{check_run_id}' + headers = {'authorization': f'token {token}', + 'accept': 'application/vnd.github.antiope-preview+json'} + + data = { + 'conclusion': f'{conclusion}', + } + response = requests.patch(url=url, headers=headers, json=data) + print(response) + env: + SHA: ${{ steps.chatops.outputs.SHA }} + WORKFLOW_CONCLUSION: ${{ job.status }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CHECK_RUN_ID: ${{ steps.create_check.outputs.id }} + diff --git a/.github/workflows/check_cdns.yaml b/.github/workflows/check_cdns.yaml new file mode 100644 index 0000000..f1c954a --- /dev/null +++ b/.github/workflows/check_cdns.yaml @@ -0,0 +1,13 @@ +name: Check CDN +on: +# push: +# schedule: +# - cron: '1 7,14,21 * * *' + workflow_dispatch: + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - run: ./_action_files/check_js.sh diff --git a/.github/workflows/check_config.yaml b/.github/workflows/check_config.yaml new file mode 100644 index 0000000..f889409 --- /dev/null +++ b/.github/workflows/check_config.yaml @@ -0,0 +1,78 @@ +name: Check Configurations +on: push + +jobs: + check-config: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: 3.7 + + - name: install dependencies + run: pip3 install pyyaml + + - name: check baseurl + id: baseurl + run: | + import yaml + from pathlib import Path + from configparser import ConfigParser + settings = ConfigParser() + + config_path = Path('_config.yml') + settings_path = Path('_action_files/settings.ini') + + assert config_path.exists(), 'Did not find _config.yml in the current directory!' + assert settings_path.exists(), 'Did not find _action_files/settings.ini in the current directory!' + + settings.read(settings_path) + with open('_config.yml') as f: + config = yaml.safe_load(f) + + errmsg = f"The value set for baseurl in _action_files/settings.ini and _config.yml are not identical. Please fix and try again." + assert config['baseurl'] == settings['DEFAULT']['baseurl'], errmsg + shell: python + + - name: Create issue if baseurl rule is violated + if: steps.baseurl.outcome == 'failure' + uses: actions/github-script@0.6.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + var err = process.env.ERROR_STRING; + var run_id = process.env.RUN_ID; + github.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: "Error with repository configuration: baseurl", + body: `${err}\n See run [${run_id}](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${run_id}) for more details.` + }) + env: + ERROR_STRING: "You have not configured your baseurl correctly, please read the instructions in _config.yml carefully." + RUN_ID: ${{ github.run_id }} + + - name: check for User Pages + id: userpage + run: | + import os + nwo = os.getenv('GITHUB_REPOSITORY') + errmsg = "fastpages does not support User Pages or repo names that end with github.io, please see https://forums.fast.ai/t/fastpages-replacing-main-username-github-io-page-w-fastpages/64316/3 for more details." + assert ".github.io" not in nwo, errmsg + shell: python + + - name: Create Issue if User Pages rule is violated + if: steps.userpage.outcome == 'failure' + uses: actions/github-script@0.6.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + github.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: "Error with repository configuration: repo name", + body: 'fastpages does not support User Pages or repo names that end with github.io, please see https://forums.fast.ai/t/fastpages-replacing-main-username-github-io-page-w-fastpages/64316/3 for more details.' + }) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100755 index 0000000..5eb953b --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,58 @@ +name: CI +on: + push: + branches: + - master # need to filter here so we only deploy when there is a push to master + # no filters on pull requests, so intentionally left blank + pull_request: + workflow_dispatch: + +jobs: + build-site: + if: ( github.event.commits[0].message != 'Initial commit' ) || github.run_number > 1 + runs-on: ubuntu-latest + steps: + + - name: Check if secret exists + if: github.event_name == 'push' + run: | + if [ -z "$deploy_key" ] + then + echo "You do not have a secret named SSH_DEPLOY_KEY. This means you did not follow the setup instructions carefully. Please try setting up your repo again with the right secrets." + exit 1; + fi + env: + deploy_key: ${{ secrets.SSH_DEPLOY_KEY }} + + + - name: Copy Repository Contents + uses: actions/checkout@main + with: + persist-credentials: false + + - name: convert notebooks and word docs to posts + uses: ./_action_files + + - name: setup directories for Jekyll build + run: | + rm -rf _site + sudo chmod -R 777 . + + - name: Jekyll build + uses: docker://fastai/fastpages-jekyll + with: + args: bash -c "jekyll build -V --strict_front_matter --trace" + env: + JEKYLL_ENV: 'production' + + - name: copy CNAME file into _site if CNAME exists + run: | + sudo chmod -R 777 _site/ + cp CNAME _site/ 2>/dev/null || : + + - name: Deploy + if: github.event_name == 'push' + uses: peaceiris/actions-gh-pages@v3 + with: + deploy_key: ${{ secrets.SSH_DEPLOY_KEY }} + publish_dir: ./_site diff --git a/.github/workflows/docker-nbdev.yaml b/.github/workflows/docker-nbdev.yaml new file mode 100644 index 0000000..9849cb3 --- /dev/null +++ b/.github/workflows/docker-nbdev.yaml @@ -0,0 +1,8 @@ +name: deprecated +on: workflow_dispatch + +jobs: + nothing: + runs-on: ubuntu-latest + steps: + - run: exit 1; diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100755 index 0000000..a2b2075 --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,33 @@ +name: Build-Docker +on: + push: + paths: + - Gemfile* + branches: + - master + pull_request: + paths: + - Gemfile* + +jobs: + jekyll-fastpages: + if: github.repository == 'fastai/fastpages' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + + - name: setup directories for Jekyll build + run: sudo chmod -R 777 . + + - name: build container + run: | + docker build -t fastai/fastpages-jekyll -f _action_files/fastpages-jekyll.Dockerfile . + + - name: push container + if: github.event == 'push' + run: | + echo ${PASSWORD} | docker login -u $USERNAME --password-stdin + docker push fastai/fastpages-jekyll + env: + USERNAME: ${{ secrets.DOCKER_USERNAME }} + PASSWORD: ${{ secrets.DOCKER_PASSWORD }} diff --git a/.github/workflows/gh-page.yaml b/.github/workflows/gh-page.yaml new file mode 100644 index 0000000..3fe4340 --- /dev/null +++ b/.github/workflows/gh-page.yaml @@ -0,0 +1,17 @@ +name: GH-Pages Status +on: + page_build + +jobs: + see-page-build-payload: + runs-on: ubuntu-latest + steps: + - name: check status + run: | + import os + status, errormsg = os.getenv('STATUS'), os.getenv('ERROR') + assert status == 'built', 'There was an error building the page on GitHub pages.\n\nStatus: {}\n\nError messsage: {}'.format(status, errormsg) + shell: python + env: + STATUS: ${{ github.event.build.status }} + ERROR: ${{ github.event.build.error.message }} diff --git a/.github/workflows/issue_reminder.yaml b/.github/workflows/issue_reminder.yaml new file mode 100644 index 0000000..4d3683a --- /dev/null +++ b/.github/workflows/issue_reminder.yaml @@ -0,0 +1,26 @@ + +name: Issue Reminder +on: + issues: + types: [opened] + +jobs: + issue_comment: + if: | + (github.repository == 'fastai/fastpages') + runs-on: ubuntu-latest + steps: + + - name: Comment on issue + uses: actions/github-script@0.6.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + var url = 'https://github.com/fastai/fastpages/blob/master/_fastpages_docs/TROUBLESHOOTING.md' + var msg = `Thank you for opening an issue. If this issue is related to a bug, please follow the steps and provide the information outlined in the [Troubleshooting Guide](${url}). Failure to follow these instructions may result in automatic closing of this issue.` + github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: msg + }) diff --git a/.github/workflows/setup.yaml b/.github/workflows/setup.yaml new file mode 100755 index 0000000..230c83c --- /dev/null +++ b/.github/workflows/setup.yaml @@ -0,0 +1,105 @@ +name: Setup +on: push + +jobs: + setup: + if: (github.event.commits[0].message == 'Initial commit') && (github.run_number == 1) + runs-on: ubuntu-latest + steps: + + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: 3.6 + + - name: Copy Repository Contents + uses: actions/checkout@v2 + + - name: modify files + run: | + import re, os + from pathlib import Path + from configparser import ConfigParser + config = ConfigParser() + + nwo = os.getenv('GITHUB_REPOSITORY') + username, repo_name = nwo.split('/') + readme_template_path = Path('_fastpages_docs/README_TEMPLATE.md') + readme_path = Path('README.md') + config_path = Path('_config.yml') + pr_msg_path = Path('_fastpages_docs/_setup_pr_template.md') + settings = Path('_action_files/settings.ini') + + assert readme_template_path.exists(), 'Did not find _fastpages_docs/README_TEMPLATE.md in the current directory!' + assert readme_path.exists(), 'Did not find README.md in the current directory!' + assert config_path.exists(), 'Did not find _config.yml in the current directory!' + assert pr_msg_path.exists(), 'Did not find _fastpages_docs/_setup_pr_template.md in the current directory!' + assert settings.exists(), 'Did not find _action_files/settings.ini in the current directory!' + + # edit settings.ini file to inject baseurl + config.read(settings) + config['DEFAULT']['baseurl'] = f'/{repo_name}' + with open('_action_files/settings.ini', 'w') as configfile: + config.write(configfile) + + # replace content of README with template + readme = readme_template_path.read_text().replace('{_username_}', username).replace('{_repo_name_}', repo_name) + readme_path.write_text(readme) + + # update _config.yml + cfg = config_path.read_text() + cfg = re.sub(r'^(github_username: )(fastai)', fr'\g<1>{username}', cfg, flags=re.MULTILINE) + cfg = re.sub(r'^(baseurl: )("")', r'\1"/{}"'.format(repo_name), cfg, flags=re.MULTILINE) + cfg = re.sub(r'^(github_repo: ")(fastpages)', r'\1{}'.format(repo_name), cfg, flags=re.MULTILINE) + cfg = re.sub(r'^(url: "https://)(fastpages.fast.ai)(")', fr'\g<1>{username}.github.io\3', cfg, flags=re.MULTILINE) + cfg = re.sub('UA-57531313-5', '', cfg, flags=re.MULTILINE) + config_path.write_text(cfg) + + # prepare the pr message + pr = pr_msg_path.read_text().replace('{_username_}', username).replace('{_repo_name_}', repo_name) + pr_msg_path.write_text(pr) + shell: python + + - name: commit changes + run: | + git config --global user.email "${GH_EMAIL}" + git config --global user.name "${GH_USERNAME}" + git checkout -B fastpages-automated-setup + git rm CNAME action.yml + git rm _notebooks/2020-02-21-introducing-fastpages.ipynb + git rm _notebooks/2020-09-01-fastcore.ipynb || true + git rm _notebooks/2020-11-17-linkcheck.ipynb || true + git rm -rf _notebooks/fastcore_imgs + git rm -rf _notebooks/fastlinkcheck_images + git rm _posts/2020-03-06-fastpages-actions.md + git rm _posts/*codespaces.md || true + git rm -rf images/fastpages_posts + git rm .github/workflows/chatops.yaml + git rm .github/workflows/docker.yaml + git rm .github/workflows/issue_reminder.yaml + git rm .github/workflows/setup.yaml + git rm .github/ISSUE_TEMPLATE/bug.md + git rm .github/ISSUE_TEMPLATE/feature_request.md + git rm _word/*.docx + git add _config.yml README.md _fastpages_docs/ _action_files/settings.ini + git commit -m'setup repo' + git push -f --set-upstream origin fastpages-automated-setup + env: + GH_EMAIL: ${{ github.event.commits[0].author.email }} + GH_USERNAME: ${{ github.event.commits[0].author.username }} + + - name: Open a PR + uses: actions/github-script@0.5.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + var fs = require('fs'); + var contents = fs.readFileSync('_fastpages_docs/_setup_pr_template.md', 'utf8'); + github.pulls.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: 'Initial Setup', + head: 'fastpages-automated-setup', + base: 'master', + body: `${contents}` + }) diff --git a/.github/workflows/upgrade.yaml b/.github/workflows/upgrade.yaml new file mode 100755 index 0000000..a2a1cd3 --- /dev/null +++ b/.github/workflows/upgrade.yaml @@ -0,0 +1,275 @@ +name: Upgrade fastpages +on: + issues: + types: [opened] + +jobs: + check_credentials: + if: | + (github.repository != 'fastai/fastpages') && + (github.event.issue.title == '[fastpages] Automated Upgrade') + runs-on: ubuntu-latest + steps: + + - name: see payload + run: | + echo "FULL PAYLOAD:\n${PAYLOAD}\n" + echo "PR_PAYLOAD PAYLOAD:\n${PR_PAYLOAD}" + env: + PAYLOAD: ${{ toJSON(github.event) }} + PR_PAYLOAD: ${{ github.event.pull_request }} + + - name: Comment on issue if sufficient access does not exist + if: | + (github.event.issue.author_association != 'OWNER') && + (github.event.issue.author_association != 'COLLABORATOR') && + (github.event.issue.author_association != 'MEMBER') + uses: actions/github-script@0.6.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + var permission_level = process.env.permission_level; + var url = 'https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/permission-levels-for-a-user-account-repository#collaborator-access-on-a-repository-owned-by-a-user-account' + var msg = `You must have the [permission level](${url}) of either an **OWNER**, **COLLABORATOR** or **MEMBER** to instantiate an upgrade request. Your permission level is ${permission_level}` + github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: msg + }) + github.issues.update({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + state: 'closed' + }) + throw msg; + env: + permission_level: ${{ github.event.issue.author_association }} + + upgrade: + needs: [check_credentials] + if: | + (github.repository != 'fastai/fastpages') && + (github.event.issue.title == '[fastpages] Automated Upgrade') && + (github.event.issue.author_association == 'OWNER' || github.event.issue.author_association == 'COLLABORATOR' || github.event.issue.author_association == 'MEMBER') + runs-on: ubuntu-latest + steps: + + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: 3.7 + + - name: checkout latest fastpages + uses: actions/checkout@v2 + with: + repository: 'fastai/fastpages' + path: 'new_files' + persist-credentials: false + + - name: copy this repo's contents + uses: actions/checkout@v2 + with: + path: 'current_files' + persist-credentials: false + + - name: compare versions + id: check_version + run: | + from pathlib import Path + new_version = Path('new_files/_fastpages_docs/version.txt') + old_version = Path('current_files/_fastpages_docs/version.txt') + + if old_version.exists(): + old_num = old_version.read_text().strip() + new_num = new_version.read_text().strip() + print(f'Old version: {old_num}') + print(f'New version: {new_num}') + if old_num == new_num: + print('::set-output name=vbump::false') + else: + print('::set-output name=vbump::true') + else: + print('::set-output name=vbump::true') + shell: python + + - name: copy new files + if: steps.check_version.outputs.vbump == 'true' + run: | + # remove files you don't want to copy from current version of fastpages + cd new_files + rm -rf _posts _notebooks _word images + rm *.md CNAME action.yml _config.yml index.html LICENSE + rm _pages/*.md + rm .github/workflows/chatops.yaml + rm .github/workflows/docker.yaml + rm .github/ISSUE_TEMPLATE/bug.md .github/ISSUE_TEMPLATE/feature_request.md + + # copy new files from fastpages into your repo + for file in $(ls | egrep -v "(assets|_sass)"); do + if [[ -f "$file" ]] || [[ -d "$file" ]] + then + echo "copying $file"; + cp -r $file ../current_files; + fi + done + + # copy custom-variables.scss if doesn't exist + if [ ! -f "../current_files/_sass/minima/custom-variables.scss" ]; then + cp _sass/minima/custom-variables.scss ../current_files/_sass/minima/ + fi + + # copy select files in assets and _sass + cp -r assets/js ../current_files/assets + cp -r assets/badges ../current_files/assets + cp _sass/minima/fastpages-styles.scss ../current_files/_sass/minima/ + cp _sass/minima/fastpages-dracula-highlight.scss ../current_files/_sass/minima/ + + # copy action workflows + cp -r .github ../current_files + + # install dependencies + pip3 install pyyaml + + - name: sync baseurl + if: steps.check_version.outputs.vbump == 'true' + run: | + import re, os, yaml + from pathlib import Path + from configparser import ConfigParser + settings = ConfigParser() + + # specify location of config files + nwo = os.getenv('GITHUB_REPOSITORY') + username, repo_name = nwo.split('/') + settings_path = Path('current_files/_action_files/settings.ini') + config_path = Path('current_files/_config.yml') + setup_pr_path = Path('current_files/_fastpages_docs/_setup_pr_template.md') + upgrade_pr_path = Path('current_files/_fastpages_docs/_upgrade_pr.md') + + assert settings_path.exists(), 'Did not find _action_files/settings.ini in your repository!' + assert config_path.exists(), 'Did not find _config.yml in your repository!' + assert setup_pr_path.exists(), 'Did not find_fastpages_docs/_setup_pr_template.md in the current directory!' + assert upgrade_pr_path.exists(), 'Did not find _fastpages_docs/_upgrade_pr.md in your repository!' + + # read data from config files + settings.read(settings_path) + with open(config_path, 'r') as cfg: + config = yaml.load(cfg) + + # sync value for baseurl b/w config.yml and settings.ini + settings['DEFAULT']['baseurl'] = config['baseurl'] + with open(settings_path, 'w') as stg: + settings.write(stg) + + # update PR templates + setup_pr = setup_pr_path.read_text().replace('{_username_}', username).replace('{_repo_name_}', repo_name) + setup_pr_path.write_text(setup_pr) + upgrade_pr = upgrade_pr_path.read_text().replace('{_username_}', username).replace('{_repo_name_}', repo_name) + upgrade_pr_path.write_text(upgrade_pr) + shell: python + + - uses: webfactory/ssh-agent@v0.4.1 + if: steps.check_version.outputs.vbump == 'true' + with: + ssh-private-key: ${{ secrets.SSH_DEPLOY_KEY }} + + - name: push changes to branch + if: steps.check_version.outputs.vbump == 'true' + run: | + # commit changes + cd current_files + git config --global user.email "${GH_USERNAME}@users.noreply.github.com" + git config --global user.name "${GH_USERNAME}" + git remote remove origin + git remote add origin "git@github.com:${GITHUB_REPOSITORY}.git" + + git add _action_files/settings.ini + git checkout -b fastpages-automated-upgrade + git add -A + git commit -m'upgrade fastpages' + git push -f --set-upstream origin fastpages-automated-upgrade master + env: + GH_USERNAME: ${{ github.event.issue.user.login }} + + - name: Open a PR + if: steps.check_version.outputs.vbump == 'true' + id: pr + uses: actions/github-script@0.6.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + var fs = require('fs'); + var contents = fs.readFileSync('current_files/_fastpages_docs/_upgrade_pr.md', 'utf8'); + github.pulls.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: '[fastpages] Update repo with changes from fastpages', + head: 'fastpages-automated-upgrade', + base: 'master', + body: `${contents}` + }) + .then(result => console.log(`::set-output name=pr_num::${result.data.number}`)) + + - name: Comment on issue if failure + if: failure() && (steps.check_version.outputs.vbump == 'true') + uses: actions/github-script@0.6.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + var pr_num = process.env.PR_NUM; + var repo = process.env.REPO + github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `An error occurred when attempting to open a PR to update fastpages. See the [Actions tab of your repo](https://github.com/${repo}/actions) for more details.` + }) + env: + PR_NUM: ${{ steps.pr.outputs.pr_num }} + REPO: ${{ github.repository }} + + - name: Comment on issue + if: steps.check_version.outputs.vbump == 'true' + uses: actions/github-script@0.6.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + var pr_num = process.env.PR_NUM; + var repo = process.env.REPO + github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `Opened PR https://github.com/${repo}/pull/${pr_num} to assist with updating fastpages.` + }) + env: + PR_NUM: ${{ steps.pr.outputs.pr_num }} + REPO: ${{ github.repository }} + + - name: Comment on issue if version has not changed + if: steps.check_version.outputs.vbump == 'false' + uses: actions/github-script@0.6.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `Your version of fastpages is up to date. There is nothing to change.` + }) + + - name: Close Issue + if: always() + uses: actions/github-script@0.6.0 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + github.issues.update({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + state: 'closed' + }) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6cdd784 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.swp +~* +*~ +_site +.sass-cache +.jekyll-cache +.jekyll-metadata +*.xml +vendor +_notebooks/.ipynb_checkpoints +# Local Netlify folder +.netlify +.tweet-cache +__pycache__ diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..18a648f --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +fastpages.fast.ai diff --git a/Gemfile b/Gemfile new file mode 100755 index 0000000..e3aacc5 --- /dev/null +++ b/Gemfile @@ -0,0 +1,43 @@ +source "https://rubygems.org" +# Hello! This is where you manage which Jekyll version is used to run. +# When you want to use a different version, change it below, save the +# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: +# +# bundle exec jekyll serve +# +# This will help ensure the proper Jekyll version is running. +# Happy Jekylling! +gem "jekyll", "~> 4.1.0" +# This is the default theme for new Jekyll sites. You may change this to anything you like. +gem "minima" +# To upgrade, run `bundle update github-pages`. +# gem "github-pages", group: :jekyll_plugins +# If you have any plugins, put them here! +group :jekyll_plugins do + gem "jekyll-feed", "~> 0.12" + gem 'jekyll-octicons' + gem 'jekyll-remote-theme' + gem "jekyll-twitter-plugin" + gem 'jekyll-relative-links' + gem 'jekyll-seo-tag' + gem 'jekyll-toc' + gem 'jekyll-gist' + gem 'jekyll-paginate' + gem 'jekyll-sitemap' +end + +gem "kramdown-math-katex" +gem "jemoji" + +# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem +# and associated library. +install_if -> { RUBY_PLATFORM =~ %r!mingw|mswin|java! } do + gem "tzinfo", "~> 1.2" + gem "tzinfo-data" +end + +# Performance-booster for watching directories on Windows +gem "wdm", "~> 0.1.1", :install_if => Gem.win_platform? + +gem "faraday", "< 1.0" + diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100755 index 0000000..b8aa71f --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,154 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (6.0.3.3) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + colorator (1.1.0) + concurrent-ruby (1.1.7) + em-websocket (0.5.1) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0.6.0) + eventmachine (1.2.7) + execjs (2.7.0) + faraday (0.17.3) + multipart-post (>= 1.2, < 3) + ffi (1.13.1) + forwardable-extended (2.6.0) + gemoji (3.0.1) + html-pipeline (2.14.0) + activesupport (>= 2) + nokogiri (>= 1.4) + http_parser.rb (0.6.0) + i18n (1.8.5) + concurrent-ruby (~> 1.0) + jekyll (4.1.1) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (~> 2.0) + jekyll-watch (~> 2.0) + kramdown (~> 2.1) + kramdown-parser-gfm (~> 1.0) + liquid (~> 4.0) + mercenary (~> 0.4.0) + pathutil (~> 0.9) + rouge (~> 3.0) + safe_yaml (~> 1.0) + terminal-table (~> 1.8) + jekyll-feed (0.15.0) + jekyll (>= 3.7, < 5.0) + jekyll-gist (1.5.0) + octokit (~> 4.2) + jekyll-octicons (11.0.0) + jekyll (>= 3.6, < 5.0) + octicons (= 11.0.0) + jekyll-paginate (1.1.0) + jekyll-relative-links (0.6.1) + jekyll (>= 3.3, < 5.0) + jekyll-remote-theme (0.4.2) + addressable (~> 2.0) + jekyll (>= 3.5, < 5.0) + jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) + rubyzip (>= 1.3.0, < 3.0) + jekyll-sass-converter (2.1.0) + sassc (> 2.0.1, < 3.0) + jekyll-seo-tag (2.6.1) + jekyll (>= 3.3, < 5.0) + jekyll-sitemap (1.4.0) + jekyll (>= 3.7, < 5.0) + jekyll-toc (0.14.0) + jekyll (>= 3.8) + nokogiri (~> 1.10) + jekyll-twitter-plugin (2.1.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + jemoji (0.12.0) + gemoji (~> 3.0) + html-pipeline (~> 2.2) + jekyll (>= 3.0, < 5.0) + katex (0.6.0) + execjs (~> 2.7) + kramdown (2.3.0) + rexml + kramdown-math-katex (1.0.1) + katex (~> 0.4) + kramdown (~> 2.0) + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.3) + listen (3.2.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.4.0) + mini_portile2 (2.4.0) + minima (2.5.1) + jekyll (>= 3.5, < 5.0) + jekyll-feed (~> 0.9) + jekyll-seo-tag (~> 2.1) + minitest (5.14.2) + multipart-post (2.1.1) + nokogiri (1.10.10) + mini_portile2 (~> 2.4.0) + octicons (11.0.0) + nokogiri (>= 1.6.3.1) + octokit (4.18.0) + faraday (>= 0.9) + sawyer (~> 0.8.0, >= 0.5.3) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (4.0.6) + rb-fsevent (0.10.4) + rb-inotify (0.10.1) + ffi (~> 1.0) + rexml (3.2.4) + rouge (3.23.0) + rubyzip (2.3.0) + safe_yaml (1.0.5) + sassc (2.4.0) + ffi (~> 1.9) + sawyer (0.8.2) + addressable (>= 2.3.5) + faraday (> 0.8, < 2.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + thread_safe (0.3.6) + tzinfo (1.2.7) + thread_safe (~> 0.1) + tzinfo-data (1.2020.1) + tzinfo (>= 1.0.0) + unicode-display_width (1.7.0) + wdm (0.1.1) + zeitwerk (2.4.0) + +PLATFORMS + ruby + +DEPENDENCIES + faraday (< 1.0) + jekyll (~> 4.1.0) + jekyll-feed (~> 0.12) + jekyll-gist + jekyll-octicons + jekyll-paginate + jekyll-relative-links + jekyll-remote-theme + jekyll-seo-tag + jekyll-sitemap + jekyll-toc + jekyll-twitter-plugin + jemoji + kramdown-math-katex + minima + tzinfo (~> 1.2) + tzinfo-data + wdm (~> 0.1.1) + +BUNDLED WITH + 2.1.4 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5c1d0d4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 onwards, fast.ai, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..60f5db9 --- /dev/null +++ b/Makefile @@ -0,0 +1,53 @@ +help: + cat Makefile + +# start (or restart) the services +server: .FORCE + docker-compose down --remove-orphans || true; + docker-compose up + +# start (or restart) the services in detached mode +server-detached: .FORCE + docker-compose down || true; + docker-compose up -d + +# build or rebuild the services WITHOUT cache +build: .FORCE + chmod 777 Gemfile.lock + docker-compose stop || true; docker-compose rm || true; + docker build --no-cache -t fastai/fastpages-jekyll -f _action_files/fastpages-jekyll.Dockerfile . + docker-compose build --force-rm --no-cache + +# rebuild the services WITH cache +quick-build: .FORCE + docker-compose stop || true; + docker build -t fastai/fastpages-jekyll -f _action_files/fastpages-jekyll.Dockerfile . + docker-compose build + +# convert word & nb without Jekyll services +convert: .FORCE + docker-compose up converter + +# stop all containers +stop: .FORCE + docker-compose stop + docker ps | grep fastpages | awk '{print $1}' | xargs docker stop + +# remove all containers +remove: .FORCE + docker-compose stop || true; docker-compose rm || true; + +# get shell inside the notebook converter service (Must already be running) +bash-nb: .FORCE + docker-compose exec watcher /bin/bash + +# get shell inside jekyll service (Must already be running) +bash-jekyll: .FORCE + docker-compose exec jekyll /bin/bash + +# restart just the Jekyll server +restart-jekyll: .FORCE + docker-compose restart jekyll + +.FORCE: + chmod -R u+rw . diff --git a/README.md b/README.md new file mode 100755 index 0000000..303c834 --- /dev/null +++ b/README.md @@ -0,0 +1,553 @@ +[//]: # (BADGES SECTION: change `fastai` with your GitHub username and `fastpages` with the name of your repo) + +![](https://github.com/fastai/fastpages/workflows/CI/badge.svg) +![](https://github.com/fastai/fastpages/workflows/GH-Pages%20Status/badge.svg) +[![](https://img.shields.io/static/v1?label=fastai&message=nbdev&color=57aeac&labelColor=black&style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAjCAYAAABhCKGoAAAGMklEQVR42q1Xa0xTVxyfKExlui9blszoB12yDzPGzJhtyT5s+zBxUxELBQSHm2ZzU5epBF/LclXae29pCxR5VEGgLQUuIOKDuClhm8oUK7S9ve19tLTl/fA5p9MNc/Y/hRYEzGLxJL/87zk9Ob/zf5++NGHMALzYgdDYmWh0Qly3Lybtwi6lXdpN2cWN5A0+hrQKe5R2PoN2uD+OKcn/UF5ZsVduMmyXVRi+jzebdmI5/juhwrgj3mTI2GA0vvsUIcMwM7GkOD42t7Mf6bqHkFry2yk7X5PXcxMVDN5DGtFf9NkJfe6W5iaUyFShjfV1KPlk7VPAa0k11WjzL+eRvMJ4IKQO0dw8SydJL+Op0u5cn+3tQTn+fqTivTbQpiavF0iG7iGt6NevKjpKpTbUo3hj+QO47XB8hfHfIGAelA+T6mqQzFi+e0oTKm3iexQnXaU56ZrK5SlVsq70LMF7TuX0XNTyvi1rThzLST3TgOCgxwD0DPwDGoE07QkcSl/m5ynbHWmZVm6b0sp9o2DZN8aTZtqk9w9b2G2HLbbvsjlx+fry0vwU0OS5SH68Ylmilny3c3x9SOvpRuQN7hO8vqulZQ6WJMuXFAzcRfkDd5BG8B1bpc+nU0+fQtgkYLIngOEJwGt/J9UxCIJg1whJ05Ul4IMejbsLqUUfOjJKQnCDr4ySHMeO1/UMIa3UmR9TUpj7ZdMFJK8yo6RaZjLAF/JqM/rifCO+yP4AycGmlgUaT9cZ0OYP2um5prjBLhtvLhy68Fs7RFqbRvSlf15ybGdyLcPJmcpfIcIuT4nqqt+Sa2vaZaby1FB+JGi1c9INhuiv9fpIysItIh3CVgVAzXfEE1evzse/bwr8bolcAXs+zcqKXksQc5+FD2D/svT06I8IYtaUeZLZzsVm+3oRDmON1Ok/2NKyIJSs0xnj84RknXG6zgGEE1It+rsPtrYuDOxBKAJLrO1qnW7+OpqeNxF4HWv6v4Rql3uFRvL/DATnc/29x4lmy2t4fXVjY+ASGwylm8DBvkSm2gpgx1Bpg4hyyysqVoUuFRw0z8+jXe40yiFsp1lpC9navlJpE9JIh7RVwfJywmKZO4Hkh02NZ1FilfkJLi1B4GhLPduAZGazHO9LGDX/WAj7+npzwUQqvuOBoo1Va91dj3Tdgyinc0Dae+HyIrxvc2npbCxlxrJvcW3CeSKDMhKCoexRYnUlSqg0xU0iIS5dXwzm6c/x9iKKEx8q2lkV5RARJCcm9We2sgsZhGZmgMYjJOU7UhpOIqhRwwlmEwrBZHgCBRKkKX4ySVvbmzQnXoSDHWCyS6SV20Ha+VaSFTiSE8/ttVheDe4NarLxVB1kdE0fYAgjGaOWGYD1vxKrqmInkSBchRkmiuC4KILhonAo4+9gWVHYnElQMEsAxbRDSHtp7dq5CRWly2VlZe/EFRcvDcBQvBTPZeXly1JMpvlThzBBRASBoDsSBIpgOBQV6C+sUJzffwflQX8BTevCTZMZeoslUo9QJJZYTZDw3RuIKtIhlhXdfhDoJ7TTXY/XdBBpgUshwFMSRYTVwim7FJvt6aFyOnoVKqc7MZQDzzNwsmnd3UegCudl8R2qzHZ7bJbQoYGyn692+zMULCfXenoOacTOTBUnJYRFsq+5+a3sjp5BXM6hEz7ObHNoVEIHyocekiX6WIiykwWDd1HhzT8RzY2YqxnK0HNQBJtW500ddiwrDgdIeCABZ4MPnKQdk9xDhUP3wfHSqbBI9v/e9jo0Iy30cCOgAMyVgMMVCMwql/cQxfKp2R1dWWrRm0PzUkrIXC9ykDY+hnJ5DqkE709guriwSRgGzWTQCPABWJZ6vbNHQlgo099+CCEMPnF6xnwynYETEWd8ls0WPUpSWnTrfuAhAWacPslUiQRNLBGXFSA7TrL8V3gNhesTnLFY0jb+bYWVp0i7SClY184jVtcayi7so2yuA0r4npbjsV8CJHZhPQ7no323cJ5w8FqpLwR/YJNRnHs0hNGs6ZFw/Lpsb+9oj/dZSbuL0XUNojx4d9Gch5mOT0ImINsdKyHzT9Muz1lcXhRWbo9a8J3B72H8Lg6+bKb1hyWMPeERBXMGRxEBCM7Ddfh/1jDuWhb5+QkAAAAASUVORK5CYII=)](https://github.com/fastai/nbdev) +[![](https://img.shields.io/static/v1?label=View%20Demo%20Site&message=link&labelColor=2f363d&color=blue&style=flat&logo=github&logoColor=959da5)](https://fastpages.fast.ai/) + +[//]: # (END OF BADGES SECTION) + +# Welcome To `fastpages` + +> An easy to use blogging platform, with support for Jupyter notebooks, Word docs, and Markdown. + +![](images/diagram.png) + +`fastpages` uses [GitHub Actions](https://github.com/features/actions) to simplify the process of creating [Jekyll blog posts](https://jekyllrb.com/) on [GitHub Pages](https://pages.github.com/) from a variety of input formats. + +### `fastpages` provides the following features: + +- Create posts containing code, outputs of code (which can be interactive), formatted text, etc directly from [Jupyter Notebooks](https://jupyter.org/); Notebook posts support features such as: + - Interactive visualizations made with [Altair](https://altair-viz.github.io/) remain interactive. + - Hide or show cell input and output. + - Collapsable code cells that are either open or closed by default. + - Define the Title, Summary and other metadata via a special markdown cells + - Ability to add links to [Colab](https://colab.research.google.com/) and GitHub automatically. +- Support for comments, supported natively through GitHub Issues. +- Built-in search. +- Support for customizing the styling of your site. +- Embed Twitter cards and YouTube videos. +- Categorization of blog posts by user-supplied tags for discoverability. +- Create and edit [Markdown](https://guides.github.com/features/mastering-markdown/) posts. +- Create posts, including formatting and images, directly from Microsoft Word documents. +- Write posts on your local machine and [preview them with live reload](#running-the-blog-on-your-local-machine). + +See below for a more detailed list of features. + + +**[See the demo site](https://fastpages.fast.ai/)** + +--- + + + +- [Welcome To `fastpages`](#welcome-to-fastpages) + - [`fastpages` provides the following features:](#fastpages-provides-the-following-features) + - [Setup Instructions](#setup-instructions) + - [Customizing Blog Posts With Front Matter](#customizing-blog-posts-with-front-matter) + - [Configure Title & Summary](#configure-title--summary) + - [Table of Contents](#table-of-contents) + - [Colab, Binder and GitHub Badges](#colab-binder-and-github-badges) + - [Categories](#categories) + - [Enabling Comments](#enabling-comments) + - [Setting an Image For Social Media](#setting-an-image-for-social-media) + - [Hiding A Blog Post](#hiding-a-blog-post) + - [Pinning A Blog Post](#pinning-a-blog-post) + - [Toggle Search Visibility](#toggle-search-visibility) + - [Site Wide Configuration Options](#site-wide-configuration-options) + - [Adjusting Page Width](#adjusting-page-width) + - [Annotations and Highlighting With hypothes.is](#annotations-and-highlighting-with-hypothes.is) + - [Subscribing with RSS](#subscribing-with-rss) + - [Syntax Highlighting](#syntax-highlighting) + - [Dark Mode](#dark-mode) + - [Adding Citations via BibTeX](#adding-citations-via-bibtex) + - [Writing Blog Posts With Jupyter](#writing-blog-posts-with-jupyter) + - [Hide Input/Output Cells](#hide-inputoutput-cells) + - [Collapsable Code Cells](#collapsable-code-cells) + - [Embedded Twitter and YouTube Content](#embedded-twitter-and-youtube-content) + - [Adding Footnotes](#adding-footnotes) + - [Automatically Convert Notebooks To Blog Posts](#automatically-convert-notebooks-to-blog-posts) + - [Writing Blog Posts With Markdown](#writing-blog-posts-with-markdown) + - [Writing Blog Posts With Microsoft Word](#writing-blog-posts-with-microsoft-word) + - [Specifying front-matter for Word documents](#specifying-front-matter-for-word-documents) +- [Running the blog on your local machine](#running-the-blog-on-your-local-machine) +- [Using The GitHub Action & Your Own Custom Blog](#using-the-github-action--your-own-custom-blog) + - [Optional Inputs](#optional-inputs) +- [Contributing To Fastpages](#contributing-to-fastpages) +- [Upgrading Fastpages](#upgrading-fastpages) +- [FAQ](#faq) +- [Customizing Fastpages](#customizing-fastpages) +- [Troubleshooting fastpages](#troubleshooting-fastpages) + + + + +## Setup Instructions + +1. Generate a copy of this repo by clicking [on this link](https://github.com/fastai/fastpages/generate). Make sure to sign in to your account, or you will see a 404 error. Name your repo anything you like **except** {your-username}.github.io. + +2. **GitHub Actions will automatically open a PR** on your new repository ~ 30 seconds after the copy is created. Follow the instructions in that PR to continue. + +>If you are not seeing a PR, please make sure you have third party actions enabled in your organization: **Settings -> Actions -> Actions Permissions -> Enable local and third party Actions for this repository** + +For a live walk-through of the setup steps (with some additional tips) see this [video tutorial of setting up a fastpages blog](https://youtu.be/L0boq3zqazI) by Abdul Majed. + +## Customizing Blog Posts With Front Matter + +[Front matter](https://jekyllrb.com/docs/front-matter/) allows you to toggle various options on/off for each blog post, as well as pass metadata to various features of fastpages. + +In a notebook, front matter is defined as a markdown cell at the beginning of the notebook with the following contents: + + ```markdown + # "Title" + > "Awesome summary" + + - toc: false + - branch: master + - badges: true + - comments: true + - categories: [fastpages, jupyter] + - image: images/some_folder/your_image.png + - hide: false + - search_exclude: true + - metadata_key1: metadata_value1 + - metadata_key2: metadata_value2 + ``` + +Similarly, in a markdown document the same front matter would be defined like this at the beginning of the document: + + ```yaml + --- + title: "My Title" + description: "Awesome description" + layout: post + toc: false + comments: true + image: images/some_folder/your_image.png + hide: false + search_exclude: true + categories: [fastpages, jupyter] + metadata_key1: metadata_value1 + metadata_key2: metadata_value2 + --- + ``` + +Additional metadata is optional and allows you to set custom [front matter](https://jekyllrb.com/docs/front-matter/). + +Note that anything defined in front matter must be valid YAML. **Failure to provide valid YAML could result in your page not rendering** in your blog. For example, if you want a colon in your title you must escape it with double quotes like this: + +` - title: "Deep learning: A tutorial"` + +See this [tutorial on YAML](https://rollout.io/blog/yaml-tutorial-everything-you-need-get-started/) for more information. + +### Configure Title & Summary + - Replace `Title`, with your desired title, and `Awesome summary` with your desired summary. + +**Note:** It is recommended to enclose these values in double quotes, so that you can escape colons and other characters that may break the YAML parser. + +### Table of Contents + - `fast_template` will automatically generate a table of contents for you based on [markdown headers](https://guides.github.com/features/mastering-markdown/)! You can toggle this feature on or off by setting `toc:` to either `true` or `false`. + +### Colab, Binder and GitHub Badges + +This option works for **notebooks only** + + - The `branch` field is used to optionally render a link your notebook to Colab and GitHub in your blog post post. It'll default to `master` if you don't specify it in the notebook. + - If you do not want to show Colab / GitHub badges on your blog post (perhaps because your repo is private and the links would be broken) set `badges` to `false`. This defaults to `true` + - By default, when you omit this parameter from your front matter, or you set `badges: true`, **all three badges (GitHub, Binder, Colab)** will appear by default. You can adjust these defaults in with the `default_badges` parameter in [Site Wide Configuration Options](#site-wide-configuration-options). + - If only want to hide a badge on an individual post, you can set the front matter `hide_{github,colab,binder}_badge: true`. For example, if you wanted to hide the Binder badge for an individual notebook but you want the other badges to show up, you can set this in your front matter: + + ```yaml + - badges: true + - hide_binder_badge: true + ``` + - **Note about Binder**: Binder allows you to customize the dependencies and other aspects of the Jupyter Notebook environment for your readers. The easiest way is to add a `requirements.txt` file with common packages you use for all your notebooks at the root of your repository, you can learn more [on the official Binder docs](https://mybinder.readthedocs.io/en/latest/introduction.html). + +### Categories + - You can have a comma seperated list inside square brackets of categories for a blog post, which will make the post visible on the tags page of your blog's site. For example: + + In a notebook: + + ``` + # "My Title" + - categories: [fastpages, jupyter] + ``` + + In a markdown document: + + ``` + --- + title: "My Title" + categories: [fastpages, jupyter] + --- + ``` + + You can see a preview of what this looks like [here](https://fastpages.fast.ai/categories/). + + + - You can toggle the display of tags on/off by setting `show_tags` to `true` or `false` in `_config.yml`: + +```yaml +# Set this to true to display tags on each post +show_tags: true +``` + +### Enabling Comments + +Commenting on blog posts is powered by [Utterances](https://github.com/utterance/utterances), an open-source and ad-free way of implementing comments. All comments are stored in issues on your blog's GitHub repo. You can turn this on setting `comments` to `true`. This defaults to `false`. + +To enable comments with [Utterances](https://github.com/utterance/utterances) you will need to do the following: + + - Make sure the repo is public, otherwise your readers will not be able to view the issues/comments. + - Make sure the [utterances app](https://github.com/apps/utterances) is installed on the repo, otherwise users will not be able to post comments. + - If your repo is a fork, navigate to it's settings tab and confirm the issues feature is turned on. + +### Setting an Image For Social Media + +On social media sites like Twitter, an image preview can be automatically shown with your URL. Specifying the front matter `image` provides this metadata to social media sites to render this image for you. You can set this value as follows: + +`- image: images/diagram.png` + +Note: for this setting **you can only reference image files and folders in the `/images` folder of your repo.** + +### Hiding A Blog Post + +You may want to prevent a blog post from being listed on the home page, but still have a public url that you can preview or share discreetly. You can hide a blog post from the home page by setting the front matter `hide` to `true`. This is set to `false` by default. + +It is recommended that you use [permalinks](https://jekyllrb.com/docs/permalinks/) in order to generate a predictable url for hidden blog posts. You can also set the front matter `search_exclude` to `false` if you don't want users to find your hidden post in a search. + +### Pinning A Blog Post + +By default, posts are sorted by date on your homepage. However, you may want one or more blog posts to always appear at the very top of your homepage. In other words, you may want certain posts to be "pinned" or "sticky". To accomplish this, specify the `sticky_rank` front matter in the order you would like your sticky posts to appear. Blog posts that do not set this parameter are sorted in the default way by date after the sticky posts. + +For example, consider these three markdown posts (also works for notebooks). + +`2020-01-01-Post-One.md` +```yaml +--- +title: Post One +sticky_rank: 1 +--- +``` + +`2020-02-01-Post-Two.md` +```yaml +--- +title: Post Two +sticky_rank: 2 +--- +``` + +`2020-04-01-Post-Three.md` +```yaml +--- +title: Post Three +--- +``` + +However, since `sticky_rank` is specified, blog posts will **first be sorted by sticky_rank in ascending order, then by date in descending order**, so the order of these posts will appear like so: + +- Post One +- Post Two +- Post Three + +_Without `sticky_rank` the above posts would actually be sorted in reverse order due to the dates associated with each post._ + +_Note: pinning also works for notebooks:_ + +``` +# "My cool blog post" +> "Description of blog post" + +- sticky_rank: 2 +``` + +### Toggle Search Visibility + +fastpages comes with built in keyword search powered by [lunr.js](https://lunrjs.com/). You can prevent a blog post or page from appearing in search results by setting the front matter `search_exclude` to `false`. This is set to `true` by default. + + +## Site Wide Configuration Options + +**It is recommended that everyone personalizes their blogging site by setting site-wide configration options**. These options can be found in `/_config.yml`. Below is a description of various options that are available. + +- `title`: this is the title that appears on the upper left hand corner on the header of all your pages. +- `description`: this description will show up in various places when a preview for your site is generated (for example, on social media). +- `github_username`: this allows your site to display a link to your GitHub page in the footer. +- `github_repo`: this allows your site to render links back to your repository for various features such as links to GitHub and Colab for notebooks. +- `url`: This does not need to be changed unless you have a custom domain. **Note: leave out the trailing / from this value.** +- `baseurl`: See the comments in `/_config.yml` for instructions ( "Special Instructions for baseurl" on setting this value properly. If you do not have a custom domain, then you can likely ignore this option. +- `email`: this is currently unused. Ignore. +- `twitter_username`: creates a link in your footer to your twitter page. +- `use_math`: Set this to `true` to get LaTeX math equation support. This is off by default as it otherwhise loads javascript into each page that may not be used. +- `show_description`: This shows a description under the title of your blog posts on your homepage that contains a list of your blog posts. Set to `true` by default. +- `google_analytics`: Optionally use a [Google Analytics](http://www.google.com/analytics/) ID for tracking if desired. +- `show_image`: If set to true, this uses the `image` parameter in the front matter of your blog posts to render a preview of your blogs as shown below. This is set to `false` by default. + When show_image is set to `true` your homepage will look like this: + + ![home page](/_fastpages_docs/_show_image_true.png) + +- `show_tags`: You can toggle the display of tags on your blog posts on or off by setting this value to `false`. This is set to `true` by default, which which renders the following links for tags on your blog posts like this: + + ![tags](_fastpages_docs/_post_tags.png) + +- `pagination`: This is the maximum number of posts to show on each page of your home page. Any posts exceeding this amount will be paginated onto another page. This is set to `15` by default. When this is triggered, you will see pagination at the bottom of your home page appear like this: + + ![paginate](_fastpages_docs/_paginate.png) + + Note: if you are using an older version of fastpages, **you cannot use the automated upgrade process** to get pagination. Instead you must follow these steps: + + 1. Rename your index.md file to index.html + > mv index.md index.html + 2. Replace the `Gemfile` and `Gemfile.lock` in the root of your repo with the files in this repo. + 3. Edit your `_config.yml` as follows (look at [_config.yml](_config.yml) for an example): + ```yaml + gems: + - jekyll-paginate + + paginate: 10 + paginate_path: /page:num/ + ``` + + _Alternatively, you can copy all of your posts over to a newly created repository created from the fastpages template._ + +- `default_badges`: By default GitHub, Binder, and Colab badges will show up on notebook blog posts. You can adjust these defaults by setting the appropriate value in `default_badges` to false. For example, if you wanted to turn Binder badges off by default, you would change `default_badges` to this: + + ```yaml + default_badges: + github: true + binder: false + colab: true + ``` + +- `html_escape`: this allows you to toggle escaping of HTML in various components of blog posts on or off. At this moment, you can only toggle this for the `description` field in your posts. +This is set to `false` by default. + +## Adjusting Page Width + +You can adjust the page width of fastpages on various devices by editing [/_sass/minima/custom-variables.scss](_sass/minima/custom-variables.scss). + +These are the default values, which can be adjusted to suit your preferences: + +```scss +// width of the content area +// can be set as "px" or "%" +$content-width: 1000px; +$on-palm: 800px; +$on-laptop: 1000px; +$on-medium: 1000px; +$on-large: 1200px; +``` + +## Annotations and Highlighting With hypothes.is + +[hypothes.is](https://web.hypothes.is/) is an open platform that provides a way to annotate and higlight pages, which can be either public or private. When this feature is enabled, readers of your blog will be presented with the following tooltip when highlighting text: + +![annotation](_fastpages_docs/annotate.png) + +**This is disabled by default in fastpages.** You can enable or disable this in your [_config.yml](_config.yml) file by setting `annotations` to `true` or `false`: + +```yaml +# Set this to true to turn on annotations with hypothes.is +annotations: false +``` + +> You can customize hypothes.is by reading [these configuration options](http://h.readthedocs.io/projects/client/en/latest/publishers/config/). It is also a good idea to read [these docs](https://web.hypothes.is/for-publishers/#embedding) if you want to do more with hypothes.is. However, before trying to customize this feature you should read the [customizing fastpages](#customizing-fastpages) section for important caveats. + +## Subscribing with RSS + +You can direct your readers to subscribe with [RSS feeds](https://en.wikipedia.org/wiki/RSS). There are many RSS subscription services available on the internet. Some examples include: + +1. [Feedrabbit](https://feedrabbit.com/) +2. [Blogtrottr](https://blogtrottr.com/) + +## Syntax Highlighting + +`fastpages` overrides the default syntax highlighting of minima with the [Dracula theme](https://draculatheme.com/). + +- The default highlighting in fastpages looks like this: + + ![default-highlighting](_fastpages_docs/highlight_dracula.png) + +- However, you can make the syntax highlighting to look like this, if you choose: + + ![default-highlighting](_fastpages_docs/highlight_original.png) + + If you wish to revert to the light theme above, you can remove the below line in [_sass/minima/custom-styles.scss](_sass/minima/custom-styles.scss) + + ```scss + @import "minima/fastpages-dracula-highlight"; + ``` +- If you don't like either of these themes, you can add your own CSS in [`_sass/minima/custom-styles.scss`](_sass/minima/custom-styles.scss). See [customizing fastpages](#customizing-fastpages) for more details. + +## Dark Mode + +[This blog post](https://prudhvirampey.com/blog/colours/jekyll/css/fastpages/2020/10/30/hello-dark-mode.html) describes how to enable Dark Mode for fastpages. + +## Adding Citations via BibTeX + +Users who prefer to use the citation system BibTeX may do so; it requires enabling the [jekyll-scholar](https://github.com/inukshuk/jekyll-scholar) plugin. Please see [Citations in Fastpages via BibTeX and jekyll-scholar](https://drscotthawley.github.io/devblog4/2020/07/01/Citations-Via-Bibtex.html) for instructions on implementing this. + +## Writing Blog Posts With Jupyter + +### Hide Input/Output Cells + +Place the comment `#hide` at the beginning of a code cell and it wil **hide both the input and the output** of that cell. + +A `#hide_input` comment at the top of any cell will **only hide the input**. + +Furthermore, the `hide input` [Jupyter Extension](https://jupyter-contrib-nbextensions.readthedocs.io/en/latest/nbextensions/hide_input/readme.html) can be used to hide cell inputs or outputs, which will be respected by fastpages. + +### Collapsable Code Cells + +You may want some code to be hidden in a collapsed element that the user can expand, rather than completely hiding the code from the reader. + +- To include code in a collapsable cell that **is collapsed by default**, place the comment `#collapse` at the top of the code cell. +- To include code in a collapsable cell that **is open by default**, place the comment `#collapse_show` or `#collapse-show` at the top of the code cell. +- To include the output under a collapsable element that is closed by default, place the comment `#collapse_output` or `#collapse-output` at the top of the code cell. + +### Embedded Twitter and YouTube Content +In a markdown cell in your notebook, use the following markdown shortcuts to embed Twitter cards and YouTube Videos. + + + ```markdown + > youtube: https://youtu.be/your-link + > twitter: https://twitter.com/some-link + ``` +### Adding Footnotes + +Adding footnotes in notebooks is a bit different than markdown. Please see the [Detailed Guide To Footnotes in Notebooks](https://github.com/fastai/fastpages/blob/master/_fastpages_docs/NOTEBOOK_FOOTNOTES.md). + +### Automatically Convert Notebooks To Blog Posts + +1. Save your notebook with the naming convention `YYYY-MM-DD-*.` into the `/_notebooks` or `/_word` folder of this repo, respectively. For example `2020-01-28-My-First-Post.ipynb`. This [naming convention is required by Jekyll](https://jekyllrb.com/docs/posts/) to render your blog post. + - Be careful to name your file correctly! It is easy to forget the last dash in `YYYY-MM-DD-`. Furthermore, the character immediately following the dash should only be an alphabetical letter. Examples of valid filenames are: + + ```shell + 2020-01-28-My-First-Post.ipynb + 2012-09-12-how-to-write-a-blog.ipynb + ``` + + - If you fail to name your file correctly, `fastpages` will automatically attempt to fix the problem by prepending the last modified date of your file to your generated blog post, however, it is recommended that you name your files properly yourself for more transparency. + + +2. [Commit and push](https://help.github.com/en/github/managing-files-in-a-repository/adding-a-file-to-a-repository-using-the-command-line) your file(s) to GitHub in your repository's master branch. + +3. GitHub will automatically convert your files to blog posts. **It will take ~5 minutes for the conversion process to take place**. You can click on the Actions tab of your repo to view the logs of this process. There will be two workflows that are triggered with each push you make to your master branch: (1) "CI" and (2) "GH Pages Status". Both workflows must complete with a green checkmark for your latest commit before your site is updated. + +4. If you wish, you can preview how your blog will look locally before commiting to GitHub. See [this section](#running-the-blog-on-your-local-machine) for a detailed guide on running the preview locally. + + +## Writing Blog Posts With Markdown + +If you are writing your blog post in markdown, save your `.md` file into the `/_posts` folder with the same naming convention (`YYYY-MM-DD-*.md`) specified for notebooks. + +## Writing Blog Posts With Microsoft Word + +Save your Microsoft Word documents into the `/_word` folder with the same naming convention (`YYYY-MM-DD-*.docx`) specified for notebooks. + +_Note:_ [alt text](https://support.office.com/en-us/article/add-alternative-text-to-a-shape-picture-chart-smartart-graphic-or-other-object-44989b2a-903c-4d9a-b742-6a75b451c669) in Word documents are not yet supported by fastpages, and will break links to images. + +### Specifying front-matter for Word documents + +`fastpages` does not have a robust way to specify [front matter](https://jekyllrb.com/docs/front-matter/) for Word documents. At the moment, you can only specify front matter globally for all Word documents by editing [_action_files/word_front_matter.txt](_action_files/word_front_matter.txt). + +To specify unique front matter per Word document, you will need to convert Word to markdown files manually. You can follow the steps in this [blog post](https://www.fast.ai/2020/01/18/gitblog/), which walk you through how to use [pandoc](https://pandoc.org/installing.html) to do the conversion. Note: If you wish to customize your Word generated blog post in markdown, make sure you delete your Word document from the _word directory so your markdown file doesn’t get overwritten! + +_If your primary method of writing blog posts is Word documents, and you plan on always manually editing markdown files converted from Word, you are probably better off using [fast_template](https://github.com/fastai/fast_template) instead of fastpages._ + +# Running the blog on your local machine + +See the [development guide](_fastpages_docs/DEVELOPMENT.md). + + +# Using The GitHub Action & Your Own Custom Blog + +The `fastpages` action allows you to convert notebooks from `/_notebooks` and word documents from `/_word` directories in your repo into [Jekyll](https://jekyllrb.com/) compliant blog post markdown files located in `/_posts`. **Note: This directory structure is currently inflexible** for this Action, as it is designed to be used with Jekyll. + +If you already have sufficient familiarity with [Jekyll](https://jekyllrb.com/) and wish to use this automation in your own theme, you can use this GitHub Action by referencing `fastai/fastpages@master` as follows: + +```yaml +... + +uses: fastai/fastpages@master + +... +``` +An illustrative example of what a complete workflow may look like: + + + +```yaml +jobs: + build-site: + runs-on: ubuntu-latest + ... + + - name: convert notebooks and word docs to posts + uses: fastai/fastpages@master + + ... + + - name: Jekyll build + uses: docker://jekyll/jekyll + with: + args: jekyll build + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + if: github.event_name == 'push' + with: + deploy_key: ${{ secrets.SSH_DEPLOY_KEY }} + publish_branch: gh-pages + publish_dir: ./_site +``` + +Note that this Action **does not have any required inputs, and has no output variables**. + +### Optional Inputs + + - `BOOL_SAVE_MARKDOWN`: Either 'true' or 'false'. Whether or not to commit converted markdown files from notebooks and word documents into the _posts directory in your repo. This is useful for debugging. _default: false_ + - `SSH_DEPLOY_KEY`: a ssh deploy key is required if BOOL_SAVE_MARKDOWN = 'true' + +See the API spec for this action in [action.yml](action.yml) + +Detailed instructions on how to customize this blog are beyond the scope of this README. ( We invite someone from the community to contribute a blog post on how to do this in this repo! ) + +# Contributing To Fastpages + +Please see the [contributing guide](_fastpages_docs/CONTRIBUTING.md). + +# Upgrading Fastpages + +Please see the [upgrading guide](_fastpages_docs/UPGRADE.md). + +# FAQ + +- **Q:** Where are the markdown files in `_posts/` that are generated from my Jupyter notebooks or word documents? **A:** The GitHub Actions workflow in this repo converts your notebook and word documents to markdown on the fly before building your site, but never commits these intermediate markdown files to this repo. This is in order to save you from the annoyance of your local environment being constantly out of sync with your repository. You can optionally see these intermediate markdown files by setting the `BOOL_SAVE_MARKDOWN` and `SSH_DEPLOY_KEY` inputs to the fastpages action in your `.github/workflows/ci.yaml` file as follows: + +```yaml + ... + + - name: convert notebooks and word docs to posts + uses: fastai/fastpages@master + with: + BOOL_SAVE_MARKDOWN: true + SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} + + ... +``` + +- **Q:** Can I use `fastpages` for Jekyll docs sites or for things that are not Jekyll blog posts? **A:** At the moment, `fastpages` is a highly opinionated solution that works only for Jekyll blog posts. If you want to write documentation for your module or library with Jupyter notebooks, we suggest you use [fastai/nbdev](https://github.com/fastai/nbdev) which is expressly built for this purpose. + +- **Q:** What is the difference between [fast_template](https://github.com/fastai/fast_template) and fastpages? Which one should I use? **A:** Because `fastpages` is more flexible and extensible, we recommend using it where possible. `fast_template` may be a better option for getting folks blogging who have no technical expertise at all, and will only be creating posts using Github's integrated online editor. + +# Customizing Fastpages + +fastpages builds upon the [minima theme](https://github.com/jekyll/minima). If you want to customize the styling or layout of fastpages, you can find instructions [in minima's README](https://github.com/jekyll/minima/blob/master/README.md). It is a good idea to read the full contents of the README to understand the directory structure. Furthermore, it is a good idea to have a basic understanding of Jekyll before customizing your theme. For those new to Jekyll, [the official docs](https://jekyllrb.com/docs/) are a good place to start. Concretely, you can override css in fastpages in `_sass/minima/custom-styles.scss`. *NOTE that minima's "skins" feature is currently incompatible with fastpages' css settings.* + +**If you choose to make customizations to fastpages** It is possible that customizations you make could collide with current or future versions of fastpages and we recommend doing so only if you feel sufficiently comfortable with HTML and CSS. + +# Troubleshooting fastpages + +Please see the [troubleshooting guide](https://github.com/fastai/fastpages/blob/master/_fastpages_docs/TROUBLESHOOTING.md). diff --git a/_action_files/Dockerfile b/_action_files/Dockerfile new file mode 100755 index 0000000..b5bcf32 --- /dev/null +++ b/_action_files/Dockerfile @@ -0,0 +1,9 @@ +FROM fastai/jekyll:2020-09-12 + +WORKDIR /fastpages +COPY . . +RUN chmod u+x action_entrypoint.sh +RUN chmod u+x word2post.sh +RUN dos2unix /fastpages/*.sh + +CMD [ "/fastpages/action_entrypoint.sh" ] diff --git a/_action_files/__init__.py b/_action_files/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/_action_files/action.yml b/_action_files/action.yml new file mode 100644 index 0000000..9f240fe --- /dev/null +++ b/_action_files/action.yml @@ -0,0 +1,17 @@ +name: 'fastpages: An easy to use blogging platform with support for Jupyter Notebooks.' +description: Converts Jupyter notebooks and Word docs into Jekyll blog posts. +author: Hamel Husain +inputs: + BOOL_SAVE_MARKDOWN: + description: Either 'true' or 'false'. Whether or not to commit converted markdown files from notebooks and word documents into the _posts directory in your repo. This is useful for debugging. + required: false + default: false + SSH_DEPLOY_KEY: + description: a ssh deploy key is required if BOOL_SAVE_MARKDOWN = 'true' + required: false +branding: + color: 'blue' + icon: 'book' +runs: + using: 'docker' + image: 'Dockerfile' diff --git a/_action_files/action_entrypoint.sh b/_action_files/action_entrypoint.sh new file mode 100755 index 0000000..4850484 --- /dev/null +++ b/_action_files/action_entrypoint.sh @@ -0,0 +1,48 @@ +#!/bin/bash +set -e + +# setup ssh: allow key to be used without a prompt and start ssh agent +export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" +eval "$(ssh-agent -s)" + +######## Run notebook/word converter ######## +# word converter using pandoc +/fastpages/word2post.sh +# notebook converter using nbdev +cp /fastpages/settings.ini . +python /fastpages/nb2post.py + + +######## Optionally save files and build GitHub Pages ######## +if [[ "$INPUT_BOOL_SAVE_MARKDOWN" == "true" ]];then + + if [ -z "$INPUT_SSH_DEPLOY_KEY" ];then + echo "You must set the SSH_DEPLOY_KEY input if BOOL_SAVE_MARKDOWN is set to true."; + exit 1; + fi + + # Get user's email from commit history + if [[ "$GITHUB_EVENT_NAME" == "push" ]];then + USER_EMAIL=$(jq '.commits | .[0] | .author.email' < "$GITHUB_EVENT_PATH") + else + USER_EMAIL="actions@github.com" + fi + + # Setup Git credentials if we are planning to change the data in the repo + git config --global user.name "$GITHUB_ACTOR" + git config --global user.email "$USER_EMAIL" + git remote add fastpages-origin "git@github.com:$GITHUB_REPOSITORY.git" + echo "${INPUT_SSH_DEPLOY_KEY}" > _mykey + chmod 400 _mykey + ssh-add _mykey + + # Optionally save intermediate markdown + if [[ "$INPUT_BOOL_SAVE_MARKDOWN" == "true" ]]; then + git pull fastpages-origin "${GITHUB_REF}" --ff-only + git add _posts + git commit -m "[Bot] Update $INPUT_FORMAT blog posts" --allow-empty + git push fastpages-origin HEAD:"$GITHUB_REF" + fi +fi + + diff --git a/_action_files/check_js.sh b/_action_files/check_js.sh new file mode 100755 index 0000000..61c9936 --- /dev/null +++ b/_action_files/check_js.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# The purpose of this script is to check parity between official hosted third party js libraries, and alternative CDNs used on this site. + +function compare { + printf "=================\ncomparing:\n%s vs. %s\n" "$1" "$2" + wget "$1" -O f1 &> /dev/null + wget "$2" -O f2 &> /dev/null + if ! cmp f1 f2; + then + printf "Files are NOT the same!\n" + exit 1; + else + printf "Files are the same.\n" + fi + } + +compare "https://unpkg.com/@primer/css/dist/primer.css" "https://cdnjs.cloudflare.com/ajax/libs/Primer/15.2.0/primer.css" +#compare "https://hypothes.is/embed.js" "https://cdn.jsdelivr.net/npm/hypothesis/build/boot.js" +compare "https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js" "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.12.0/contrib/auto-render.min.js" +compare "https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css" "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.12.0/katex.min.css" +compare "https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js" "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.12.0/katex.min.js" +compare "https://cdn.jsdelivr.net/npm/mathjax@2.7.5/MathJax.js" "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js" + +# Remove files created for comparison +rm f1 f2 diff --git a/_action_files/fast_template.py b/_action_files/fast_template.py new file mode 100755 index 0000000..935e2ff --- /dev/null +++ b/_action_files/fast_template.py @@ -0,0 +1,29 @@ +from datetime import datetime +import re, os +from pathlib import Path +from typing import Tuple, Set + +# Check for YYYY-MM-DD +_re_blog_date = re.compile(r'([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])-)') +# Check for leading dashses or numbers +_re_numdash = re.compile(r'(^[-\d]+)') + +def rename_for_jekyll(nb_path: Path, warnings: Set[Tuple[str, str]]=None) -> str: + """ + Return a Path's filename string appended with its modified time in YYYY-MM-DD format. + """ + assert nb_path.exists(), f'{nb_path} could not be found.' + + # Checks if filename is compliant with Jekyll blog posts + if _re_blog_date.match(nb_path.name): return nb_path.with_suffix('.md').name.replace(' ', '-') + + else: + clean_name = _re_numdash.sub('', nb_path.with_suffix('.md').name).replace(' ', '-') + + # Gets the file's last modified time and and append YYYY-MM-DD- to the beginning of the filename + mdate = os.path.getmtime(nb_path) - 86400 # subtract one day b/c dates in the future break Jekyll + dtnm = datetime.fromtimestamp(mdate).strftime("%Y-%m-%d-") + clean_name + assert _re_blog_date.match(dtnm), f'{dtnm} is not a valid name, filename must be pre-pended with YYYY-MM-DD-' + # push this into a set b/c _nb2htmlfname gets called multiple times per conversion + if warnings: warnings.add((nb_path, dtnm)) + return dtnm diff --git a/_action_files/fastpages-jekyll.Dockerfile b/_action_files/fastpages-jekyll.Dockerfile new file mode 100755 index 0000000..3e10794 --- /dev/null +++ b/_action_files/fastpages-jekyll.Dockerfile @@ -0,0 +1,7 @@ +# Defines https://hub.docker.com/repository/docker/fastai/fastpages-jekyll +FROM jekyll/jekyll:4.1.0 + +COPY . . +RUN chmod -R 777 . +RUN gem install bundler +RUN jekyll build diff --git a/_action_files/fastpages.tpl b/_action_files/fastpages.tpl new file mode 100644 index 0000000..14077e5 --- /dev/null +++ b/_action_files/fastpages.tpl @@ -0,0 +1,22 @@ +{%- extends 'hide.tpl' -%} +{%- block body -%} +{%- set internals = ["metadata", "output_extension", "inlining", + "raw_mimetypes", "global_content_filter"] -%} +--- +{%- for k in resources |reject("in", internals) %} +{% if k == "summary" and "description" not in resources %}description{% else %}{{ k }}{% endif %}: {{ resources[k] }} +{%- endfor %} +layout: notebook +--- + + + +
{{ super() }}
+{{ super() }}
+{{ super() }}
+%&WU4-CdssSGVHlZ)r3-kcm^*uago`DH2fs`Q@4GhhUysad|86b*$w9?&Pdu
z(tVKO^FY3<)&mzzN?Pr#aJEM8_Bt7HnCrpsFULjvCto5+1W%@65vCS`6VNC>BGN-on09W$-sdIJ(g(W@6NDS$@X3}$}&{1{koZvEnc&$DhSNU>`NNG?6v
zMjT2BixxnsJ|%Ms2-e{p0zIDbW
8qcvrSw$-NpH&JbvhOW&lX;}^bMjz&eV
z`~j0l_a=>%#d{6S4T;1-G_GBZ$uPh`O5CMPXQ{M#lZLhNXLF+^A^rXD8s+PsNWxVp
zfS!w)wyQdq3KSJ=(>-b+sOJGY>!#}pO_>*)!=(!-O^u|ux1P3qQP|(F&Od#Y5l%bo
zbJIz_oRekI&ySUh-*)o3e~c?0K)6yt9JW;M+pxRAE5#lj+*eoe>Fd!vjCr&?o@>S3
zGRzrQM{U=w#~nvCp)Y@IG26>V9-e1CKP>4TIVBYcuWMuFa;C4LFEQIWhS6q+u%&Nv
z6