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

原文連接:https://ssshooter.com/2019-01...javascript

偶然看到經過語雀 webhook 發佈文章到 Hexo 靜態博客,很方便,實現過程也頗有意思。一樣的原理能夠運用到 Gatsby.js 博客上。java

由於使用了 netlify,自動部署的事情就不用本身擔憂了,本文講述的有一下兩點:node

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

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

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

語雀 webhook

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

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

clipboard.png

本地測試

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

個人配置:npm

clipboard.png

express 接收 webhook 推送

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

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

GitHub api 更新倉庫

原理

使用 api 更新 GitHub 倉庫的方法能夠參考:使用 Github API 更新倉庫axios

主要代碼

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 代碼,總以爲對格式有種不能徹底控制源碼的束縛感。

相關文章
相關標籤/搜索