如何将文档与 Github Pages 同步?
Posted
技术标签:
【中文标题】如何将文档与 Github Pages 同步?【英文标题】:How can I sync documentation with Github Pages? 【发布时间】:2013-02-19 07:41:34 【问题描述】:我和几个人一起有一个项目,我们有一个README.md
文件,其中包含一堆 GitHub 风格的 Markdown,呈现在我们的 GitHub 页面上。我们还建立了一个 GitHub Pages 分支,它托管在我们的 GitHub 组织的子域下,并在创建页面时使用 Automatic Page Generator 简单地加载到我们的 README.md
文件中。但是,我注意到当我更新我们的README.md
文件时,它并没有更新项目页面。相反,我们必须转到 GitHub 设置选项卡并重新创建项目页面,并在执行此操作时重新加载 README.md
文件。
此外,在阅读了有关 relative linking 在 GitHub 项目目录页面上的文档文件之间工作的信息之后。我非常喜欢 Markdown,因为它节省了大量时间,无需为我们的文档手动编写所有 html。然而,我想要的是能够拥有一个README.md
文件,该文件能够包含指向位于docs/*.md
的其他文档文件的相对链接。我希望有一个简单的解决方案,以便我的其他文档文件也可以包含在我的 gh-pages 分支中,并托管在我的 GitHub Pages 子域下并进行渲染和/或主题化。
换句话说,我的问题是:
有没有办法让我的 README.md 文件在我的 Github 页面子域上自动更新? [ EDIT ] : 如果使用自动页面生成器,答案似乎不是。您必须转到存储库的设置页面并在每次发生更改时重新加载它才能更新它。 有没有办法让我的 README.md 文件上的文档的相对链接在我的 Github 页面上工作,也许我以某种方式将我的/docs/*.md
同步到我的 Github 页面并以某种方式呈现和/或主题化它们?
[ EDIT ] : 从我写这个问题以来所学到的,这似乎只能在 GitHub 页面上通过使用 static site generator 像 ruby gem Jekyll 和可能的一些用途在下面的 cmets 中提到的 webhooks supported by GitHub 中。我目前正在尝试寻找最佳解决方案。
更好的是,有没有一种更简单的方法可以做到这一点,并且可能只有一份我的 README.md 和文档的副本,用于 gh-pages 和我的主分支并使一切变得简单?
[ EDIT ] : 看来这个几乎肯定是否定的。我正在考虑在 GitHub 中内置一些东西来实现这一点的可能性。看来将来可能会在 GitHub Pages 中内置对这种东西的更好支持,或者至少我绝对希望它会这样。
【问题讨论】:
GitHub 支持 post-receive webhook。你有没有想过添加一个钩子来调用一些远程脚本,将新的README.md
版本推送到 GitHub 页面?
感谢您的出色发现和编辑。在这个网站上没有足够的人这样做。
对于第一个问题,这里是manual approach,不是自动的,但它简单且有效。对于 HTML 生成部分,可以使用dillinger.io。我也找到了this automatic method,虽然我试了一下,但没有成功。
GitHub 刚刚启用了使用any branch and directory as the source for the docs。您不再需要使用gh-pages
。
【参考方案1】:
我将发布一个我设置的解决方案,该解决方案利用了 GitHub Pages 使用 Jekyll 已经使用自动页面生成器这一事实。
git checkout gh-pages
mkdir _layouts
mv index.html _layouts
git checkout master -- README.md
mv README.md index.md
在index.md
前添加以下文本
---
layout: index
---
您还需要打开index.html
文件并进行以下更改:
从 README.md
文件中的标记中删除呈现的 HTML。这通常在<section>
或<article>
标签之间。将此 HTML 替换为文本 content
这将允许我们将此文件用作 jekyll。我们应用布局的文件将放置在内容标签所在的位置。
找到项目页面主题的 CSS。对我来说,这是如下一行:
<link rel='stylesheet' href='stylesheets/stylesheet.css' />
这需要改成
<link rel='stylesheet' href=' site.path /stylesheets/stylesheet.css' />
site.path
为前缀。
通过这样做,Jekyll 会将 markdown 文件呈现为 _layouts
目录中 index.html
布局的内容。为了使这个过程自动化,不仅是 README.md 文件,还有你的 master 分支中可能拥有的其他文档,我采取了以下步骤:
创建了名为 post-commit
的文件,其中包含以下内容:
#!/bin/bash
###
### The following block runs after commit to "master" branch
###
if [ `git rev-parse --abbrev-ref HEAD` == "master" ]; then
# Layout prefix is prepended to each markdown file synced
###################################################################
LAYOUT_PREFIX='---\r\nlayout: index\r\n---\r\n\r\n'
# Switch to gh-pages branch to sync it with master
###################################################################
git checkout gh-pages
# Sync the README.md in master to index.md adding jekyll header
###################################################################
git checkout master -- README.md
echo -e $LAYOUT_PREFIX > index.md
cat README.md >> index.md
rm README.md
git add index.md
git commit -a -m "Sync README.md in master branch to index.md in gh-pages"
# Sync the markdown files in the docs/* directory
###################################################################
git checkout master -- docs
FILES=docs/*
for file in $FILES
do
echo -e $LAYOUT_PREFIX | cat - "$file" > temp && mv temp "$file"
done
git add docs
git commit -a -m "Sync docs from master branch to docs gh-pages directory"
# Uncomment the following push if you want to auto push to
# the gh-pages branch whenever you commit to master locally.
# This is a little extreme. Use with care!
###################################################################
# git push origin gh-pages
# Finally, switch back to the master branch and exit block
git checkout master
fi
编辑:我为README.md
文件和docs/*
中的markdown 更新了上述脚本,以使用相同的布局文件。这是一个比我以前更好的设置。该脚本位于您的.git/hooks/
目录中。 bash 必须在您的路径中。
使用以下内容创建文件_config.yml
markdown: redcarpet
path: http://username.github.io/reponame
上述脚本还同步在master
分支的docs/*
目录中找到的markdown 文件,以便它们也可以在GitHub Pages 站点上查看。如果您包含以下 jQuery 函数以从 gh-pages
分支上的锚点中删除 .md
扩展名,则到这些文档的相对链接有效。可以在_layouts
目录下的index.html
添加如下脚本:
$(document).on('ready', function ()
$('a').each(function (i, e)
var href = e.href;
if (href.search('.md') > 0)
$(this).attr('href', href.split('.md')[0]);
);
);
编辑:我在我的存储库中更改了上面的代码,这是一种快速而肮脏的方法,但如果你知道我的意思,它不会在所有情况下都正常工作..例如,markdown 文件company.mdata.md
将无法正确处理。为了解决这个问题,我将其更新为以下脚本,该脚本更仔细地检查了 href 并在找到时删除扩展名。我还使脚本更通用,允许通过更改ext
变量来删除其他扩展。代码如下:
$(function ()
$('a').each(function ()
var ext = '.md';
var href = $(this).attr('href');
var position = href.length - ext.length;
if (href.substring(position) === ext)
$(this).attr('href', href.substring(0, position));
);
);
我在 CoryG89/docsync 设置了一个示例 repo,它有一个 project page here,如果你想看看这一切是如何协同工作的。
【讨论】:
我奖励你我的赏金,因为你给出了如此彻底的答案,但我仍然希望有人提出一个更直接的解决方案。 我很欣赏马特。我将继续使用 50 rep 来提供另一个赏金,希望有另一个更简单/更简单的解决方案来做到这一点。这个解决方案很好,因为它允许相对链接在您的 README 和您网站上以及您的 repo 中的其他降价文档之间继续按预期工作。 在提交后挂钩中去除 .md 扩展名不是更容易吗?或者甚至有一种方法可以使用 Jenkins 本身? 我认为您必须使用 .md 扩展名将文件保存在存储中,否则它不会呈现为 Markdown。虽然不是 100%。 2016年还有更简单的事情吗?【参考方案2】:我对将 README 与 Github 页面同步的问题的解决方案与上述略有不同。可以使用 Github API 返回呈现为 HTML 的 Markdown 文件,而不是使用单独的 javascript Markdown 引擎。
-
从
https://api.github.com/repos/<owner>/<repo>/contents/README.md
获取README.md
。
解码 Base64 响应:window.atob( JSON.parse( blob ).content );
将解码后的README
发布到 JSON 正文中的https://api.github.com/markdown
"text": "<README>",
"mode": "markdown",
"context": "<owner>/<repo>"
将呈现的 HTML 插入 DOM 元素,如 Brad Rhodes 所做的那样。
对这种方法的两个注意事项:
-
执行两个串行请求会减慢页面加载速度。
访问 Github API 时可能会遇到速率限制。
对于加载时间不重要(约 1-2 秒)的低流量页面,上述方法就足够了。
【讨论】:
atob() 在 Chrome 和 FF 中工作正常,但在 IE 11 中不能正常工作。说无效字符。网站位于joymon.github.io/joyful-visualstudio【参考方案3】:您可以使用DocumentUp 来呈现您的 README.md。
【讨论】:
【参考方案4】:对于在您的文档站点和主 github 存储库之间共享一个自述文件,我有几个想法:
您只能使用一个包含您的代码和 jekyll 文档站点的 gh-pages 分支。您的存储库可能会有点混乱,您需要在自述文件的顶部放置一个 YAML 标头。它几乎支持相对链接。问题是,如果你想让 jekyll 渲染你的 markdown,它会给它一个 .html 扩展名。也许有一种方法可以配置它。 Here's an example I threw together to see if it works.
您可以在文档站点中使用 AJAX 调用从主分支读取自述文件,然后使用 Javascript Markdown renderer 呈现它。这将需要更长的时间来加载,并且如果您不编写一些聪明的 Javascript,它将不支持相对链接。实施起来也比想法 1 需要更多的工作。
【讨论】:
【参考方案5】:另一个需要考虑的方法是设置一个pre-commit hook 来构建相关页面。我在one of my repositories 中执行此操作。不过,您可能不得不放弃自动页面生成器,只需要自己推送到 gh-pages
分支,以及将您的文档转换为 HTML 或 Jekyll 网站,如 Nathan suggests。
在该存储库中 I push like this 以保持 gh-pages
与 master
相同。也有很多other ways 可以做到这一点。不过,这可能不适合您的情况(您可能不希望它们相同)。
无论如何,我在这个问题上提供赏金的原因是因为我希望有人有更好的工作流程。这种方法有点复杂和不灵活,它要求每个人都保持他们的钩子同步。
【讨论】:
【参考方案6】:另一种我已经非常成功地工作的方法是使用 Ajax 来获取文档,使用 Github API 和 Javascript 降价引擎来呈现 HTML(正如 Nathan 所建议的那样)。
-
使用 Github API 和 JSONP 从 Github 获取文档
解码来自 Github API 的响应中的 base64 内容
使用 javascript 降价引擎呈现降价
显示渲染的html
Nathan 对性能表示了一些担忧,但根据我的经验,它似乎是立即加载的,所以我认为这实际上不是问题。
优点是它易于设置,即使您只是直接在 github 上的浏览器中编辑 markdown,它也会始终更新您的文档。
我在 Github 页面上的 http://bradrhodes.github.io/GithubDocSync/ 上设置了一个示例来展示它的工作原理。
【讨论】:
我将该方法与 cloning 结合起来,将我的project.wiki 显示为GitHub pages。【参考方案7】:Nathan 和 Brand Rhodes 描述的方法的另一种可能性是使用一个很棒的工具:Rico Sta 创建的FlatDoc。克鲁兹。
FlatDoc 将通过 ajax 加载文档(README.md 或任何其他降价文件),对其进行解析并显示所有好东西,甚至是用于导航的侧边栏菜单!
它在其 api 中构建了一个辅助方法来从 GitHub repo master 加载文件(但也可以从 web 的其他任何地方加载)。
说明
首先将以下 html template 复制到 gh-pages 分支的 index.html 中。继续:
将“USER”替换为您的 GitHub 用户名 将“REPO”替换为您的 GitHub 存储库名称 将“Your Project”替换为您的项目名称在文件中。在浏览器中本地试用。然后提交并推送更改。现在,您的 github 页面将始终使用您的主分支中的 README.md 文件进行更新。
如果您不满意默认主题,您可以使用自己的 css 重新设置样式。
【讨论】:
【参考方案8】:我还想在 master 中编辑文档并在 gh-pages 中发布 - 我喜欢使文档与源代码保持同步,这似乎是最好的方法。这对我来说正在进行中,但我以Cory's script 为起点并对其进行了一些扩展以使其开箱即用,只要有一个带有_layouts
的gh-pages 分支(即jekyll 站点) )。它转换了反引号样式围栏(用于代码块),在 github 源代码浏览中工作得很好,但在 gh-pages 中却不行。我使用index.md
和项目README.md
的包含,所以我可以添加标题和其他一些装饰。此版本还处理任何称为“docs”的嵌套目录中的文档,我发现它在具有多个模块(不是 git 子模块,只是子目录)的项目中很有用:
.git/hooks/post-commit
#!/bin/bash
###
### The following block runs after commit to "master" branch
###
if [ `git rev-parse --abbrev-ref HEAD` == "master" ]; then
# function to convert a plain .md file to one that renders nicely in gh-pages
function convert
# sed - convert links with *.md to *.html (assumed relative links in local pages)
# awk - convert backtick fencing to highlights (script from bottom of file)
sed -e 's/(\(.*\)\.md)/(\1.html)/g' "$1" | awk -f <(sed -e '0,/^#!.*awk/d' $0) > _temp && mv _temp "$1"
if ! git show-ref --verify --quiet refs/heads/gh-pages; then
echo "No gh-pages, so not syncing"
exit 0
fi
# Switch to gh-pages branch to sync it with master
###################################################################
git checkout gh-pages
mkdir -p _includes
# Sync the README.md in master to index.md adding jekyll header
###################################################################
git checkout master -- README.md
if [ -f README.md ]; then
cp README.md _includes/
convert _includes/README.md
git add README.md
git add _includes/README.md
fi
# Generate index if there isn't one already
###################################################################
if [ ! -f index.md ]; then
echo -e '---\ntitle: Docs\nlayout: default\n---\n\n% include README.md %' > index.md
git add index.md
fi
# Generate a header if there isn't one already
###################################################################
if [ ! -f _includes/header.txt ]; then
echo -e '---\ntitle: Docs\nlayout: default\nhome: \n---\n\n' > _includes/header.txt
git add _includes/header.txt
fi
# Sync the markdown files in all docs/* directories
###################################################################
for file in `git ls-tree -r --name-only master | grep 'docs/.*\.md'`
do
git checkout master -- "$file"
dir=`echo $file%/* | sed -e "s,[^/]*,..,g"`
cat _includes/header.txt | sed -e "s,^home: .*$,home: $dir/," > _temp
cat "$file" >> _temp && mv _temp "$file"
convert "$file"
git add "$file"
done
git commit -a -m "Sync docs from master branch to docs gh-pages directory"
# Uncomment the following push if you want to auto push to
# the gh-pages branch whenever you commit to master locally.
# This is a little extreme. Use with care!
###################################################################
# git push origin gh-pages
# Finally, switch back to the master branch and exit block
git checkout master
fi
exit $?
#!/usr/bin/awk
# Replace backtick fencing (renders well when browsing github) with jekyll directives
if (/```/)
IN = IN?0:1 # Are we already in a fenced section? Toggle.
if (IN) # If we are starting a fenced section
if (/```\s*$/)
$0 = $0"text" # empty language is OK for backticks but not for jekyll
gsub(/```/, "% highlight ")
print $0" %"
else # ending a fenced section
print "% endhighlight %"
else # not a fencing line
if (IN) # but in a fenced section, so add indent to make sure code is rendered with <pre>
print " "$0
else
print
与原始版本不同的是,它在所有页面中设置了一个变量page.home
。这个可以用来定位根目录的相对路径,所以可以用来定位css之类的静态资源。在_layouts/.default.html
我有:
<link rel="stylesheet" href=" page.home css/main.css">
这样我可以编辑 css,在本地构建 jekyll 站点,并在浏览器中查看结果,而无需等待 github 在服务器上构建它。
【讨论】:
【参考方案9】:我最近制作了一个包gh-pages-generator 来解决这个问题 - 它使用多个 MD 文件和一个配置文件生成多页站点。
它会正确更新页面之间的所有链接。将更改提交回 gh-pages 分支相对容易使其成为 CI 的一部分。
我正在使用它here 和here。
【讨论】:
【参考方案10】:不难,两次复制粘贴到终端就大功告成了。
Jekyll
允许您导入 Markdown 文件,然后它会负责将它们转换为 HTML。诀窍是使用% include_relative README.md %
将README.md
导入到index.md
文件中。我们可以这样做:
值得一试how to setup a super barebones Jekyll
site on github(它只是两个文件!)
设置
您可以复制这两个文件,只需运行此一次性设置(复制整个代码块并粘贴到终端中,即可让您的页面与当前的自述文件一致) :
# Copy our two files to the gh-pages branch
git checkout -b gh-pages &&
wget https://raw.githubusercontent.com/lazamar/barebones-jekyll-project-readme/master/_config.yml &&
wget https://raw.githubusercontent.com/lazamar/barebones-jekyll-project-readme/master/index.md &&
#
# Commit and publish our page on github
git add -A && git commit -m "Create project github page" &&
git push --set-upstream origin gh-pages |
#
git checkout master # go back to master branch
自动化
然后我们只需要在每次推送之前自动将所有更改从 master
复制到 gh-pages
分支的任务。我们可以通过运行此脚本来做到这一点(您可以将其复制并粘贴到终端中)
$(cat > .git/hooks/pre-push << EOF
#!/bin/sh
we_are_in_gh_pages="\$(git branch | grep -G "* gh-pages")"
if [ ! "\$we_are_in_gh_pages" ];
then
git checkout gh-pages &&
git rebase master &&
git push -f &&
git checkout master # go back to master branch
fi
EOF
) && chmod 775 .git/hooks/pre-push
它将创建一个推送挂钩,每次运行git push
时,都会将所有更改从master
分支复制到gh-pages
。
就是这样。完成。
【讨论】:
以上是关于如何将文档与 Github Pages 同步?的主要内容,如果未能解决你的问题,请参考以下文章
Git与GitHub学习笔记使用 Github Pages 管理项目文档
如何将 GitHub Actions 与多个存储库一起使用并部署到 GitHub Pages?