使用 Gatsby.js 搭建靜態博客 EX 使用語雀發佈到博客

偶然看到通過語雀 webhook 發佈文章到 Hexo 靜態博客,很方便,實現過程也很有意思。同樣的原理可以運用到 Gatsby.js 博客上。

因爲使用了 netlify,自動部署的事情就不用自己擔心了,本文講述的有一下兩點:

  1. 熟悉語雀 webhook
  2. 使用 GitHub api 更新 GitHub 倉庫(更新倉庫後 netlify 自動部署)

除了以上兩個重點,整個流程是:

在語雀發佈文章 -> 觸發語雀 webhook -> express(node.js)接收到文章推送 -> 請求信息中抽取文章內容和必要信息 -> 調用 GitHub api 更新倉庫 -> netlify 自動部署 -> 文章在博客發佈

語雀 webhook

語雀webhook文檔 自帶完整指引,以下講講關鍵步驟。

在知識庫頁面配置訂閱地址

clipboard.png

本地測試

官方推薦使用 ngrok,ngrok 能讓你的本地服務暴露到外網,方便測試。

我的配置:

clipboard.png

express 接收 webhook 推送

app.post('/yuque/webhook', function(req, res) {
    console.log(req.body.data)
})

此時在語雀發佈文章,接口就會收到推送的文章信息。

GitHub api 更新倉庫

原理

使用 api 更新 GitHub 倉庫的方法可以參考:使用 Github API 更新倉庫

主要代碼

var updateGitHubRes = function(blob, path) {
  var commitSha
  var commitTreeSha
  return getRef()
    .then(({ data }) => {
      commitSha = data.object.sha
      return getCommit(commitSha)
    })
    .then(({ data }) => {
      commitTreeSha = data.tree.sha
      return createBlob(blob)
    })
    .then(({ data }) => {
      var blobSha = data.sha
      return createTree(commitTreeSha, path, blobSha)
    })
    .then(({ data }) => {
      var treeSha = data.sha
      return createCommit(commitSha, treeSha)
    })
    .then(({ data }) => {
      var newCommitSha = data.sha
      return updataRef(newCommitSha)
    })
    .catch(err => {
      console.log(err)
    })
}

var getRef = function() {
  return axios.get(`/${owner}/${repo}/git/refs/heads/master`)
}

var getCommit = function(commitSha) {
  return axios.get(`/${owner}/${repo}/git/commits/${commitSha}`)
}

var createBlob = function(content) {
  return axios.post(`/${owner}/${repo}/git/blobs`, {
    content,
    encoding: 'utf-8'
  })
}

var createTree = function(base_tree, path, sha) {
  return axios.post(`/${owner}/${repo}/git/trees`, {
    base_tree, // commit tree 的 sha
    tree: [
      {
        path, // 文件路徑
        mode: '100644', // 類型,詳情看文檔
        type: 'blob',
        sha // 剛纔生成的 blob 的 sha
      }
    ]
  })
}

var createCommit = function(
  parentCommitSha,
  tree,
  message = ':memo: update post'
) {
  return axios.post(`/${owner}/${repo}/git/commits`, {
    message,
    parents: [parentCommitSha],
    tree
  })
}

var updataRef = function(newCommitSha) {
  return axios.post(`/${owner}/${repo}/git/refs/heads/master`, {
    sha: newCommitSha,
    force: true
  })
}

組合

把接受 webhook 請求的功能和 GitHub 更新流程組合起來,有如下代碼:

app.post('/yuque/webhook', function(req, res) {
  console.log('web hook')
  var postData = req.body.data
  if (!postData) {
    console.log('nothing append')
    return res.json({
      msg: 'nothing append'
    })
  }
  var title = postData.title
  var date = postData.created_at
  var content = postData.body

  var tagsReg = new RegExp(/(?<=<tags>).*(?=<\/tags>)/)
  var removeTagsReg = new RegExp(/<tags>.*<\/tags>/)
  var pathReg = new RegExp(/(?<=<path>).*(?=<\/path>)/)
  var removePathReg = new RegExp(/<path>.*<\/path>/)
  var replaceBrReg = new RegExp(/<br \/>/g)

  var tags = content.match(tagsReg)
  content = content.replace(removeTagsReg, '')
  var postPath = content.match(pathReg)
  content = content.replace(removePathReg, '')
  content = content.replace(replaceBrReg, '\n')

  tags = tags && tags[0]
  postPath = postPath && postPath[0]
  var tagsString = JSON.stringify(tags.split(','))

  var contentHeader = `---
path: "${postPath}"
date: "${date}"
title: "${title}"
tags: ${tagsString}
---
`
  updateGitHubRes(
    contentHeader + content,
    `src/pages/${date.substring(0, 10)}-${postPath.substring(1)}/index.md`
  ).then(({ data }) => {
    console.log('finish')
    return res.json({
      msg: 'finish'
    })
  })
})

因爲語雀沒有 tag 之類的選項,只能自己用特定標記寫到文章裏再在後端提取,並且添加信息頭部。內容組合好調用更新 api 即可完成整個流程。

功能部署

如果你自己有服務器,正常部署即可,若沒有,可以使用 Heroku。Heroku 可以爲你提供免費的程序部署服務。你可以先把上面寫好的功能上傳到 GitHub,然後從選擇從 GitHub 拉取倉庫。拉取倉庫後 Heroku 會自動運行 npm start

npm start 映射到 node index.js 就可以了。

值得注意的是,heroku 的端口是系統分配的,所以需要使用環境變量提供的端口:

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Our app is running on port ${ PORT }`);
});

大功告成

在語雀發佈文章即可在博客同時發佈,這確實比手寫 md 再 push 發佈只方便了一點,但是更讓人期待的是語雀移動端的上線!那麼之後就能直接在手機更新靜態博客了!不過有點地方還是想吐槽,語雀的 md 編輯器有時候會語法失效,而且不能直接看到 md 代碼,總覺得對格式有種不能完全控制源碼的束縛感。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章