一开始,我在博客上使用了 Halo。我发现有很多问题。时不时会报各种莫名其妙、莫名其妙的主题的错误。有时我不得不升级。
这两天,我抽空来来回回。不小心把镜像给尼玛删了,发的文章都没了。想了想,我需要做出改变!
众所周知,我很懒而且很有名。我想你不要让我担心这种事情。一年内最好不要搬家。和原来的一样。
研究了一阵子,最后还是决定用docsify+github来搞定。最初的想法是把MD文件写在本地,直接push到github,然后触发github的webhook,触发脚本拉取代码到服务器。
在这种情况下,还有想象的空间。以后同步文章的大部分工作都可以省了,可以通过API回调同步。不过,我们还没有调查这些平台是否可以支持它,但这应该不是问题。
是否可以尝试解决方案,我觉得很好。
docsify 构建安装
先安装 docsify-cli 工具
npm i docsify-cli -g
然后进入自己的目录并初始化
docsify init ./
这几乎是一样的。还有几个文件。只需修改index.html,配置名称和代码仓库信息,打开左侧边栏即可。
同时添加一些插件,全部来自互联网。
Document
window.$docsify = {
name: '艾小仙',
repo: 'https://github.com/irwinai/JavaInterview.git',
loadSidebar: true,
autoHeader: true,
subMaxLevel: 3,
sidebarDisplayLevel: 1, // set sidebar display level
count:{
countable:true,
fontsize:'0.9em',
color:'rgb(90,90,90)',
language:'chinese'
},
search: {
maxAge: 86400000, // Expiration time, the default one day
paths: [], // or 'auto'
placeholder: '开始搜索',
noData: '啥也没有!'
},
copyCode: {
buttonText : '点击复制',
errorText : '错误',
successText: '复制成功'
},
footer: {
copy: '艾小仙 © 2022',
auth: '赣ICP备2021008029号-1',
pre: '
',
style: 'text-align: right;',
class: 'className'
}
}
然后运行,本地会启动:3000,直接看效果
docsify serve
就是这样
目前还没有侧边栏,使用命令生成,它会根据目录自动帮我们创建一个_sidebar.md文件,就是我们的侧边栏。
docsify generate .
然后看看效果。这几乎是一样的。需要注意的是文件名不能有空格,否则生成的侧边栏目录会有问题。您需要修改文件名并将其替换为破折号或下划线。空格(我不明白为什么不能使用空格)。
多级目录生成问题
还有一个问题是不能生成多级目录,即不能超过二级目录。我随意更改了这个。
去docsify-cli的官方git仓库下载源码,然后把这个放进去,执行目录下的node generate.js,把最下面的test目录改成自己的目录。
'use strict'
const fs = require('fs')
const os = require('os')
const {cwd, exists} = require('../util')
const path = require('path')
const logger = require('../util/logger')
const ignoreFiles = ['_navbar', '_coverpage', '_sidebar']
// eslint-disable-next-line
function test (path = '', sidebar) {
// 获取当前目录
const cwdPath = cwd(path || '.')
// console.log('cwdPath', cwdPath, !!exists(cwdPath));
// console.log('///////', cwdPath, path, cwd(path || '.'))
if (exists(cwdPath)) {
if (sidebar) {
const sidebarPath = cwdPath + '/' + sidebar || '_sidebar.md';
if (!exists(sidebarPath)) {
genSidebar(cwdPath, sidebarPath)
logger.success(`Successfully generated the sidebar file '${sidebar}'.`)
return true
}
logger.error(`The sidebar file '${sidebar}' already exists.`)
process.exitCode = 1
return false
}
return false;
}
logger.error(`${cwdPath} directory does not exist.`)
}
let tree = '';
function genSidebar(cwdPath, sidebarPath) {
// let tree = '';
let lastPath = ''
let nodeName = ''
let blankspace = '';
let test = 0;
const files = getFiles(cwdPath);
console.log(JSON.stringify(files));
getTree(files);
fs.writeFile(sidebarPath, tree, 'utf8', err => {
if (err) {
logger.error(`Couldn't generate the sidebar file, error: ${err.message}`)
}
})
return;
getDirFiles(cwdPath, function (pathname) {
path.relative(pathname, cwdPath) // 找cwdPath的相对路径
pathname = pathname.replace(cwdPath + '/', '')
let filename = path.basename(pathname, '.md') // 文件名
let splitPath = pathname.split(path.sep) // 路径分割成数组
let blankspace = '';
if (ignoreFiles.indexOf(filename) !== -1) {
return true
}
nodeName = '- [' + toCamelCase(filename) + '](' + pathname + ')' + os.EOL
if (splitPath.length > 1) {
if (splitPath[0] !== lastPath) {
lastPath = splitPath[0]
tree += os.EOL + '- ' + toCamelCase(splitPath[0]) + os.EOL
}
tree += ' ' + nodeName
// console.error('tree=====', tree, splitPath, splitPath.length);
} else {
if (lastPath !== '') {
lastPath = ''
tree += os.EOL
}
tree += nodeName
}
})
fs.writeFile(sidebarPath, tree, 'utf8', err => {
if (err) {
logger.error(`Couldn't generate the sidebar file, error: ${err.message}`)
}
})
}
function getFiles (dir) {
// let path = require('path');
// let fs = require('fs');
let rootDir = dir;
var filesNameArr = []
let cur = 0
// 用个hash队列保存每个目录的深度
var mapDeep = {}
mapDeep[dir] = 0
// 先遍历一遍给其建立深度索引
function getMap(dir, curIndex) {
var files = fs.readdirSync(dir) //同步拿到文件目录下的所有文件名
files.map(function (file) {
//var subPath = path.resolve(dir, file) //拼接为绝对路径
var subPath = path.join(dir, file) //拼接为相对路径
var stats = fs.statSync(subPath) //拿到文件信息对象
// 必须过滤掉node_modules文件夹
if (file != 'node_modules') {
mapDeep[file] = curIndex + 1
if (stats.isDirectory()) { //判断是否为文件夹类型
return getMap(subPath, mapDeep[file]) //递归读取文件夹
}
}
})
}
getMap(dir, mapDeep[dir])
function readdirs(dir, folderName, myroot) {
var result = { //构造文件夹数据
path: dir,
title: path.basename(dir),
type: 'directory',
deep: mapDeep[folderName]
}
var files = fs.readdirSync(dir) //同步拿到文件目录下的所有文件名
result.children = files.map(function (file) {
//var subPath = path.resolve(dir, file) //拼接为绝对路径
var subPath = path.join(dir, file) //拼接为相对路径
var stats = fs.statSync(subPath) //拿到文件信息对象
if (stats.isDirectory()) { //判断是否为文件夹类型
return readdirs(subPath, file, file) //递归读取文件夹
}
if (path.extname(file) === '.md') {
const path = subPath.replace(rootDir + '/', '');
// console.log(subPath, rootDir, '========', path);
return { //构造文件数据
path: path,
name: file,
type: 'file',
deep: mapDeep[folderName] + 1,
}
}
})
return result //返回数据
}
filesNameArr.push(readdirs(dir, dir))
return filesNameArr
}
function getTree(files) {
for (let i=0; i<files.length;i++) {
const item = files[i];
if (item) {
if (item.deep === 0) {
if (item.children) {
getTree(item.children)
}
} else {
let blankspace = ''
for (let i = 1; i < item.deep; i++) {
blankspace += ' '
}
// console.log('-' + blankspace + '-', item.deep)
if (item.type === 'directory') {
tree += os.EOL + blankspace + '- ' + toCamelCase(item.title) + os.EOL
} else if (item.type === 'file') {
tree += os.EOL + blankspace + '- [' + item.name + '](' + item.path + ')' + os.EOL
// console.log('tree', tree);
}
if (item.children) {
getTree(item.children)
}
}
}
}
}
function getDirFiles(dir, callback) {
fs.readdirSync(dir).forEach(function (file) {
let pathname = path.join(dir, file)
if (fs.statSync(pathname).isDirectory()) {
getDirFiles(pathname, callback)
} else if (path.extname(file) === '.md') {
callback(pathname)
}
})
}
function toCamelCase(str) {
return str.replace(/b(w)/g, function (match, capture) {
return capture.toUpperCase()
}).replace(/-|_/g, ' ')
}
test("/Users/user/Documents/JavaInterview/", "sidebar.md");
那岂不是万事大吉?看看最终效果。
nginx 配置
webhook 尚未完成。先手动push,然后上传文件到服务器,再设置nginx。
server {
listen 80;
listen [::]:80;
server_name aixiaoxian.vip;
client_max_body_size 1024m;
location / {
root /你的目录;
index index.html;
}
}
server {
listen 443 ssl;
server_name aixiaoxian.vip;
root /usr/share/nginx/html;
ssl_certificate cert/aixiaoxian.pem;
ssl_certificate_key cert/aixiaoxian.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #表示使用的TLS协议的类型。
include /etc/nginx/default.d/*.conf;
location / {
root /你的目录;
index index.html;
}
}
这时候你去reload nginx,你会发现网站可能是403。把你的ng文件的第一行改一下,不管后面是什么,改成root就大功告成了。
user root;
就是这样。
内网渗透
然后,你需要创建一个webhook程序,但是在此之前,为了在本地测试webhook的效果,你需要配置一个内网穿透程序,我们使用ngrok。
先安装。
brew install ngrok/ngrok/ngrok
然后你需要注册一个账号,这里没关系,直接用google登录,然后进入个人页面会提示使用步骤。
按照步骤添加令牌,然后映射端口 80。
如果以后发现找不到ngrok命令,可以去官网手动下载一个文件,放到/usr/local/bin目录下。
成功后可以看到ngrok的页面,使用他提供给我们的Forwarding地址,也就是我们的公网地址。
我做了一个随机的80端口,这里可以用自己项目的端口号来映射。我们稍后将其更改为 9000。
网络钩子
配置完成后,到我们的github项目中设置一个webhook,使用上面得到的地址。
设置OK,然后创建一个Java程序,监听9000端口,随便写个Controller。
@PostMapping("/webhook")
public void webhook(@RequestBody JsonNode jsonNode) {
System.out.println("json===" + jsonNode);
}
暂无评论内容