0

Image Description

荆文征

Zhidu Inc.


你好,再见

给博客文章增加修改历史专栏

  • 小酒馆老板
  • /
  • 2018/4/23 15:11:0

很久没有更新文章了,总想着最近要写点什么。

看着自己的博客,觉的修改历史还是比较帅气的,那么这次我们来谈一下如何实现修改历史吧。

修改历史,其实无非就是git commit历史,那么我们就来一步步的讲一讲我是如何实现,这个修改历史功能的吧。


H2

获取git commit 历史

我目前的博客使用github pages 功能,所以获取git commit 功能是github api 提供的,我们可以这个样子获取到。

发起一个GET请求,请求地址为https://api.github.com/repos/{仓库所有人名称}/{仓库名称}/commits
以我的博客仓库地址为例就是https://api.github.com/repos/aimobier/aimobier.github.io/commits

这个请求需要

我就一展示数据的表格
参数名称 含义
sha 目标分支
path 目标文件路径

这个时候我们可以先尝试一下https://api.github.com/repos/aimobier/aimobier.github.io/commits?sha=master&path=404.html

[
  {
    "sha": "72aa633b57313257e643e5b3d3216b34f22406f1",
    "commit": {
      "author": {
        "name": "aimobier",
        "email": "[email protected]",
        "date": "2018-04-17T06:37:07Z"
      },
      "committer": {
        "name": "aimobier",
        "email": "[email protected]",
        "date": "2018-04-17T06:37:07Z"
      },
      "message": "Site updated: 2018-04-17 06:36:56",
      "tree": {
        "sha": "7eb0a9f414c576382bf0aae5f375829e79383758",
        "url": "https://api.github.com/repos/aimobier/aimobier.github.io/git/trees/7eb0a9f414c576382bf0aae5f375829e79383758"
      },
      "url": "https://api.github.com/repos/aimobier/aimobier.github.io/git/commits/72aa633b57313257e643e5b3d3216b34f22406f1",
      "comment_count": 0,
      "verification": {
        "verified": false,
        "reason": "unsigned",
        "signature": null,
        "payload": null
      }
    },
    "url": "https://api.github.com/repos/aimobier/aimobier.github.io/commits/72aa633b57313257e643e5b3d3216b34f22406f1",
    "html_url": "https://github.com/aimobier/aimobier.github.io/commit/72aa633b57313257e643e5b3d3216b34f22406f1",
    "comments_url": "https://api.github.com/repos/aimobier/aimobier.github.io/commits/72aa633b57313257e643e5b3d3216b34f22406f1/comments",
    "author": {
      "login": "aimobier",
      "id": 6121524,
      "avatar_url": "https://avatars2.githubusercontent.com/u/6121524?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/aimobier",
      "html_url": "https://github.com/aimobier",
      "followers_url": "https://api.github.com/users/aimobier/followers",
      "following_url": "https://api.github.com/users/aimobier/following{/other_user}",
      "gists_url": "https://api.github.com/users/aimobier/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/aimobier/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/aimobier/subscriptions",
      "organizations_url": "https://api.github.com/users/aimobier/orgs",
      "repos_url": "https://api.github.com/users/aimobier/repos",
      "events_url": "https://api.github.com/users/aimobier/events{/privacy}",
      "received_events_url": "https://api.github.com/users/aimobier/received_events",
      "type": "User",
      "site_admin": false
    },
    "committer": {
      "login": "aimobier",
      "id": 6121524,
      "avatar_url": "https://avatars2.githubusercontent.com/u/6121524?v=4",
      "gravatar_id": "",
      "url": "https://api.github.com/users/aimobier",
      "html_url": "https://github.com/aimobier",
      "followers_url": "https://api.github.com/users/aimobier/followers",
      "following_url": "https://api.github.com/users/aimobier/following{/other_user}",
      "gists_url": "https://api.github.com/users/aimobier/gists{/gist_id}",
      "starred_url": "https://api.github.com/users/aimobier/starred{/owner}{/repo}",
      "subscriptions_url": "https://api.github.com/users/aimobier/subscriptions",
      "organizations_url": "https://api.github.com/users/aimobier/orgs",
      "repos_url": "https://api.github.com/users/aimobier/repos",
      "events_url": "https://api.github.com/users/aimobier/events{/privacy}",
      "received_events_url": "https://api.github.com/users/aimobier/received_events",
      "type": "User",
      "site_admin": false
    },
    "parents": [
      {
        "sha": "191f968e43f2685925cba24cfa49fe7465fc99d3",
        "url": "https://api.github.com/repos/aimobier/aimobier.github.io/commits/191f968e43f2685925cba24cfa49fe7465fc99d3",
        "html_url": "https://github.com/aimobier/aimobier.github.io/commit/191f968e43f2685925cba24cfa49fe7465fc99d3"
      }
    ]
  }
]

至此,我们已经可以获取到自己的commit日志了,那么接下来的问题就是,如何知道文件的名称了


H2

获取文件的路径

我们的每一篇文章,文件名称和标题是不一定存在的。当然我们可以将标题和文件名称自己去约束自己完成这个操作,这样子我们直接使用标题拼接字符串就可以完成路径的获取了,但是这种需要人为配置的方式,我不是很喜欢,要是写错了,那还得配置很久呢。

所以我们来试用一下方式来完成该操作。

首先我们创建一个脚本拦截文章配置之后的事件儿after_post_render

我们之前的文章筛选代码如下

/**
 * Created by jingwenzheng on 2018/3/8.
 */
var cheerio;

hexo.extend.filter.register('after_post_render', function(data){

    if (!cheerio) cheerio = require('cheerio');

    var $ = cheerio.load(data.content);

    ulliHandle($);
    codeHandle($);
    imageHandle($);
    blockquoteHandle($);
    handleTable($);

    data.content = $.html();

    return data;
});

我们接下来需要增加一个 hidden 标签,让它来存储我们需要的路径字段


/**
 * Created by jingwenzheng on 2018/3/8.
 */
var cheerio;

hexo.extend.filter.register('after_post_render', function(data){

  const appendHtmlString = '\
  <p hidden id="CurrentFileName">'+data.full_source.split("/").slice(-1)[0]+'</p>\
  ';

  data.content += appendHtmlString;

    if (!cheerio) cheerio = require('cheerio');

    var $ = cheerio.load(data.content);

    ulliHandle($);
    codeHandle($);
    imageHandle($);
    blockquoteHandle($);
    handleTable($);

    data.content = $.html();

    return data;
});

这样子我们就可以使用 $("#CurrentFileName")获取到我们的额路径地址了


H2

最终完成

好了,现在我们万事俱备让我们来书写我们的最终代码吧。

const GitHubHistoryReq = {
  requestBodyParams: {
    sha: "make-blog", // 分支名称
    path: "source/_posts/", // 文章存储路径
    paramF: function(fn) { // 返回请求的参数对象
      return {
        sha: "make-blog",
        path: "source/_posts/" + fn,
      }
    }
  },
  requestUrlParams: {
    user: "aimobier", // 用户名称
    repos: "aimobier.github.io", // 仓库名称
    urlF: function() { // 返回完整的请求链接地址
      return "https://api.github.com/repos/" + this.user + "/" + this.repos + "/commits";
    }
  },
  Request: function() {
    const fileName = $("#CurrentFileName").text();
    if (fileName !== null || fileName !== undefined || fileName !== '') {
      $.getJSON(this.requestUrlParams.urlF(), this.requestBodyParams.paramF(fileName), this.requestSuccess.bind(this));
    };
  },
  timeSince: function(date) {

    var seconds = Math.floor((new Date() - date) / 1000);

    var interval = Math.floor(seconds / 31536000);

    if (interval > 1) {
      return interval + " years ago";
    }
    interval = Math.floor(seconds / 2592000);
    if (interval > 1) {
      return interval + " months ago";
    }
    interval = Math.floor(seconds / 86400);
    if (interval > 1) {
      return interval + " days ago";
    }
    interval = Math.floor(seconds / 3600);
    if (interval > 1) {
      return interval + " hours ago";
    }
    interval = Math.floor(seconds / 60);
    if (interval > 1) {
      return interval + " minutes ago";
    }
    return Math.floor(seconds) + " seconds ago";
  },
  returnHtmlElment: function(commit) {

    const date = new Date(commit.commit.committer.date);

    commit.commit.message = commit.commit.message.replace(/\n/g,"<br>");

    return '\
    <li class="media g-brd-around g-brd-gray-light-v4 g-pa-20 g-mb-minus-1">\
      <div class="d-flex g-mt-2 g-mr-15">\
        <a target="_blank" href="' + commit.author.html_url + '"><img class="g-width-30 g-height-30 rounded-circle" src="' + commit.author.avatar_url + '" alt="Image Description"></a>\
      </div>\
      <div class="media-body">\
        <div class="d-flex justify-content-between">\
          <a target="_blank" href="' + commit.author.html_url + '"><strong class="g-font-size-9">' + commit.author.login + '</strong></a>\
          <a target="_blank" href="' + commit.html_url + '"><span class="align-self-center g-font-size-9 text-nowrap">' + (commit.sha.slice(0, 5) + '..') + '</span></a>\
        </div>\
        <span class="align-self-center g-font-size-9 text-nowrap g-color-gray-dark-v4">'+timeago(null, 'zh_CN').format(date)+'</span>\
        <span class="d-block g-font-size-11">' + commit.commit.message + '</span>\
      </div>\
    </li>\
    ';
  },
  requestSuccess: function(body) {

    var liRes = body.map(function(item, index, input) {
      return this.returnHtmlElment(item);
    }.bind(this));

    $("#commit-history").html(liRes.join(""));
  },
  editHtmlMethod:function(){

    const fileName = $("#CurrentFileName").text();
    const urlString = "https://github.com/aimobier/aimobier.github.io/tree/make-blog/source/_posts/"+fileName;

    const editHtml = '\
    <li class="list-inline-item g-mx-10">/</li>\
    <li class="list-inline-item g-mr-10">\
      <a target="_blank" class="u-link-v5 g-color-deeporange g-color-orange--hover" href="'+urlString+'">\
              <i class="align-middle mr-2 fa fa-edit u-line-icon-pro"></i>发现错误,编辑本页\
            </a>\
    </li>\
    ';

    $("#editHtmlElement").append(editHtml);
  }
}

$(function() {

  GitHubHistoryReq.Request();

  GitHubHistoryReq.editHtmlMethod();
});

我们最终在 editHtmlMethod 方法中,完成了历史的植入。另外的布局不在这里展开了。

可以查阅 c7b07a2a730b77620e012e22d7e6d5daec25fdd4 来具体查看我的代码。


H2

增加编辑本页

其实我们已经做到这一步了,这个就很简单了,无非就是增加一个链接的事儿了。增加链接的目的就是让用户点击可以到用户所查看的文章的源文件。

把我们的本篇文章的链接,贴到页面,用户可以提交修改内容,我们只需要进行审批就好了。

专栏: Hexo
标签: 博客美化 hexo