Skip to content

Instantly share code, notes, and snippets.

@buzztaiki
Last active February 12, 2024 22:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save buzztaiki/0b26bed948ea5d925635a0fbe6d772b2 to your computer and use it in GitHub Desktop.
Save buzztaiki/0b26bed948ea5d925635a0fbe6d772b2 to your computer and use it in GitHub Desktop.
GitHub の README をそのまま静的 HTML にするあれこれ

GitHub の README をそのまま静的 HTML にするあれこれ

リポジトリに README.md とか *.md* とか置いて読めるようにしてるやつを、そのまま静的HTMLにしてみてみるあれこれ。

一番お手軽。Jekyll のプラグインセットといった感じ。gh-pages で公開するなら自分で生成する必要もない。ただ、オワコンになりつつある気もする。

そのままだと details の中に markdown が書けないので、jekyll-commonmark-ghpages を使うようにしておく。

markdown: CommonMarkGhPages
commonmark:
  options: ["UNSAFE", "SMART", "FOOTNOTES"]
  extensions: ["strikethrough", "autolink", "table", "tagfilter"]

あとは 生成するだけ。

gem exec github-pages build --source <source> --destination <dest>

これもお手軽。こんな HTML を書いて配備するだけで動く。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="description" content="Description">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
</head>
<body>
  <div id="app"></div>
  <script>
    window.$docsify = {
      // ...
    }
  </script>
  <!-- Docsify v4 -->
  <script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
</body>
</html>

サイドバーが欲しければ window.$docsifyloadSidebar: true を足して _sidebar.md を書いておけばよい。

がんばればいけるけど、そのままだと厳しい。

使う場合はこのへんケアしないといけない (Jekyll はプラグインで何とかしてるけど、hugo にそういうのはない)

  • README.mdcontent/_index.md に変える
  • Web 向けのテーマを使う (Book とか)
  • path/to/markdown.mdpath/to/markdown/index.html になって画像が参照できなくなるのを何かする

具体的には

hugo.toml をこうして:

[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true

[module]

[[module.imports]]
path = 'github.com/alex-shpak/hugo-book'

[params]
BookToC = false
BookSection = "/"

以下のように前処理してあげる

preprocess.sh
#!/bin/bash

set -e -o pipefail

preprocess_md() {
  local file=$1 relname=$2
  local frontmatter=("title: $(md_title <"$file")")
  if [[ $file == */README.md ]]; then
    frontmatter+=("bookCollapseSection: true")
  else
    frontmatter+=("url: ${relname/.md/.html}")
  fi

  echo '---'
  join $'\n' "${frontmatter[@]}"
  echo '---'
  sed -E -e 's/README\.md//g' <"$file"
    
}

md_title() {
  awk '/^# +/{sub(/^# +/, ""); print; exit}'
}

join() {
  local IFS=$1; shift
  echo "$*"
}

main() {
  if [[ $# -ne 2 ]]; then
    echo "usage: $0 <src> <dest>" 1>&2
    exit 1
  fi

  local src=$1
  local dest=$2

  rm -rf "$dest"
  local file
  find "$src" -type f | while read -r file; do
    local relname=${file#"$src"}
    local relname=${relname#/}
    local reldir=$(dirname "$relname")
    mkdir -p "$dest/$reldir"

    if [[ $file == */README.md ]]; then
      preprocess_md "$file" "$relname" >"$dest/$reldir/_index.md"
    elif [[ $file == */*.md ]]; then
      preprocess_md "$file" "$relname" >"$dest/$relname"
    else
      cp "$file" "$dest/$relname"
    fi
  done
}

main "$@"

がんばればいけるけど、そのままだと厳しい。

  • 画像を assets に置く必要がある
  • README.mdindex.md に変えないといけない
  • frontmatter で title 付けないといけない
  • 画像は content に置けないから assets に移動する

astro.confg.mjs:

import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';

// https://astro.build/config
export default defineConfig({
  integrations: [
    starlight({
      title: 'docs',
      sidebar: [
        {
          label: 'my-collecion',
          collapsed: true,
          autogenerate: { directory: 'my-collection' },
        },
      ],
    }),
  ],
});

tsconfig.json:

{
  "extends": "astro/tsconfigs/strict",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@assets/*": ["src/assets/*"]
    }
  }
}
preprocess.sh
#!/bin/bash

set -e -o pipefail

preprocess_md() {
  local file=$1 relname=$2 collection=$3
  local title=$(md_title <"$file")
  local reldir=$(dirname "$relname")

  echo '---'
  echo "title: $title"
  echo '---'

  local sed_ops=(
    -e '/^# +/d'
    -e 's/README\.md//g'
    -e 's/\.md//g'
    -e "s;([a-zA-Z0-9_-]+.svg);@assets/$collection/$reldir/\1;g"
  )
  sed -E "${sed_ops[@]}" <"$file"
}

md_title() {
  awk '/^# +/{sub(/^# +/, ""); print; exit}'
}

join() {
  local IFS=$1; shift
  echo "$*"
}

main() {
  if [[ $# -ne 3 ]]; then
    echo "usage: $0 <src> <dest> <collection>" 1>&2
    exit 1
  fi

  local src=$1
  local dest=$2
  local collection=$3

  local docs="$dest/src/content/docs/$collection"
  local assets="$dest/src/assets/$collection"

  rm -rf "$docs" "$assets"

  local file
  find "$src" -type f | while read -r file; do
    local relname=${file#"$src"}
    local relname=${relname#/}
    local reldir=$(dirname "$relname")

    mkdir -p "$docs/$reldir"
    mkdir -p "$assets/$reldir"

    if [[ $file == */README.md ]]; then
      preprocess_md "$file" "$relname" "$collection" >"$docs/$reldir/index.md"
    elif [[ $file == */*.md ]]; then
      preprocess_md "$file" "$relname" "$collection" >"$docs/$relname"
    else
      cp "$file" "$assets/$relname"
    fi
  done
}

main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment