-
Notifications
You must be signed in to change notification settings - Fork 0
/
gist.ts
158 lines (139 loc) · 4.83 KB
/
gist.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import ansiColors from 'ansi-colors';
import { default as axios } from 'axios';
import Bluebird from 'bluebird';
import path from 'upath';
import * as hexoUtils from 'hexo-util';
import nunjucks from 'nunjucks';
import fs from 'fs-extra';
import { GIST_TEMPLATE, LIB_PATH, ROUTE_NAME, TEMPLATE_PATH } from './env';
const logname = ansiColors.magentaBright('hexo-shortcodes') + ansiColors.blueBright('(gist)');
// hexo-gist
// gist shortcode
// https:/jekyll/jekyll-gist
// https:/jekyll/jekyll-gist/blob/master/lib/jekyll-gist/gist_tag.rb
//
// input {% gist meredrica/088f5a593a2a7184202850c58bcb48d1 %}
// output <script src="https://gist.github.com/meredrica/088f5a593a2a7184202850c58bcb48d1.js"> </script>
//
// You may optionally specify a `filename` after the `id`:
// input {% gist meredrica/c08ee0f2726fd0e3909d test.md %}
const fetch_raw_code = async function (hexo: import('hexo'), id: string, filename: string) {
let url = `https://gist.githubusercontent.com/${id}/raw`;
if (typeof filename === 'string') {
url = `${url}/${filename}`;
}
return new Bluebird(function (resolve: (res: string) => any, reject) {
axios
.get(url)
.then(function (res) {
resolve(res.data);
})
.catch(function (e) {
hexo.log.error(logname, id, `cannot get ${e.message}`, { url });
reject(e);
});
});
};
export const gist = (hexo: import('hexo')) => {
const url_for = hexoUtils.url_for.bind(hexo);
const libFilename = 'gist.css';
const libRoute = `${ROUTE_NAME}/${libFilename}`;
const libFilePath = path.resolve(LIB_PATH, libFilename);
/**
* REGISTER MIDDLEWARE FOR HEXO GENERATE
*/
hexo.extend.generator.register(url_for(libRoute, {}), () => {
return {
path: libRoute,
data: () => fs.createReadStream(libFilePath)
};
});
/**
* REGISTER MIDDLEWARE FOR HEXO SERVER
*/
hexo.extend.filter.register('server_middleware', function (app) {
app.use(libRoute, function (_req, res) {
res.setHeader('content-type', 'text/javascript');
res.end(fs.readFileSync(libFilePath).toString());
});
});
/**
* render using nunjucks
* * useful when username undefined
* @returns
* @example
* {% gist 996818 %}
*/
function _nunjucksMethod() {
const env = nunjucks.configure([LIB_PATH, TEMPLATE_PATH], {
noCache: true,
watch: false
});
return function (args: Parameters<Parameters<typeof hexo.extend.tag.register>[1]>[0]) {
const id = args[0];
hexo.log.d(logname, id);
const filename = args[1];
const payload = {
id,
filename,
raw_code: ''
};
return env.renderString(fs.readFileSync(GIST_TEMPLATE).toString(), payload);
};
}
/**
* smart render using internal hexojs syntax highlighter
* @param args
* @returns
*/
async function _usingHexoSyntaxHighlighter(args: string[]) {
const id = args[0] || '';
// return when id is empty
// if (id.length === 0) return `<pre><code>gist id insufficient</code></pre>`;
const username = id.split('/')[0];
const gist_id = id.split('/')[1];
if (!gist_id) {
try {
return _nunjucksMethod()(args);
} catch (error) {
hexo.log.error(logname, error);
return '';
}
}
hexo.log.d(logname, username, gist_id);
const filename = args[1] || '';
const content = await fetch_raw_code(hexo, id, filename);
const line = args[2] || '';
const lineSplit = line.split('-');
const startLine = (line !== '' && parseInt(lineSplit[0].replace('#L', ''))) || -1;
const endLine = parseInt(
(line !== '' && lineSplit.length > 1 && lineSplit[1].replace('L', '')) || String(startLine)
);
let codeText = '';
let contentSplit = content.split('\n');
if (startLine > 0) {
contentSplit = contentSplit.slice(startLine - 1, endLine);
codeText = contentSplit.join('\n');
// Then add the newline back
codeText = codeText + '\n';
}
// fallback to content
if (codeText.length === 0) codeText = content;
// If neither highlight.js nor prism.js is enabled, return escaped code directly
if (!hexo.extend.highlight.query(hexo.config.syntax_highlighter)) {
return `<pre><code>${hexoUtils.escapeHTML(codeText)}</code></pre>`;
}
const options = {
lines_length: codeText.split('\n').length,
lang: path.extname(filename),
caption: path.extname(filename)
};
// forked from https:/hexojs/hexo/blob/8b95bbc722e5c77a7e8125441ed64d2ea3524ac0/lib/plugins/tag/code.js#L141-L148
const newContent = hexo.extend.highlight.exec(hexo.config.syntax_highlighter, {
context: hexo,
args: [codeText, options]
});
return newContent.replace(/{/g, '{').replace(/}/g, '}');
}
hexo.extend.tag.register('gist', _usingHexoSyntaxHighlighter, { async: true });
};