-
Notifications
You must be signed in to change notification settings - Fork 26
/
index.js
184 lines (150 loc) · 4.75 KB
/
index.js
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
var Prism = require('prismjs');
var languages = require('prismjs').languages;
var path = require('path');
var fs = require('fs');
var cheerio = require('cheerio');
var mkdirp = require('mkdirp');
var DEFAULT_LANGUAGE = 'markup';
var MAP_LANGUAGES = {
'py': 'python',
'js': 'javascript',
'rb': 'ruby',
'cs': 'csharp',
'sh': 'bash',
'html': 'markup'
};
// Base languages syntaxes (as of [email protected]), extended by other syntaxes.
// They need to be required before the others.
var PRELUDE = [
'markup-templating', 'clike', 'javascript', 'markup', 'c', 'ruby', 'css',
// The following depends on previous ones
'java', 'php'
];
PRELUDE.map(requireSyntax);
/**
* Load the syntax definition for a language id
*/
function requireSyntax(lang) {
require('prismjs/components/prism-' + lang + '.js');
}
function getConfig(context, property, defaultValue) {
var config = context.config ? /* 3.x */ context.config : /* 2.x */ context.book.config;
return config.get(property, defaultValue);
}
function isEbook(book) {
// 2.x
if (book.options && book.options.generator) {
return book.options.generator === 'ebook';
}
// 3.x
return book.output.name === 'ebook';
}
function getAssets() {
var cssFiles = getConfig(this, 'pluginsConfig.prism.css', []);
var cssFolder = null;
var cssNames = [];
var cssName = null;
if (cssFiles.length === 0) {
cssFiles.push('prismjs/themes/prism.css');
}
cssFiles.forEach(function(cssFile) {
var cssPath = require.resolve(cssFile);
cssFolder = path.dirname(cssPath);
cssName = path.basename(cssPath);
cssNames.push(cssName);
});
return {
assets: cssFolder,
css: cssNames
};
}
module.exports = {
book: getAssets,
ebook: function() {
// Adding prism-ebook.css to the CSS collection forces Gitbook
// reference to it in the html markup that is converted into a PDF.
var assets = getAssets.call(this);
assets.css.push('prism-ebook.css');
return assets;
},
blocks: {
code: function(block) {
var highlighted = '';
var userDefined = getConfig(this, 'pluginsConfig.prism.lang', {});
var userIgnored = getConfig(this, 'pluginsConfig.prism.ignore', []);
// Normalize language id
var lang = block.kwargs.language || DEFAULT_LANGUAGE;
lang = userDefined[lang] || MAP_LANGUAGES[lang] || lang;
// Check to see if the lang is ignored
if (userIgnored.indexOf(lang) > -1) {
return block.body;
}
// Try and find the language definition in components folder
if (!languages[lang]) {
try {
requireSyntax(lang);
} catch (e) {
console.warn('Failed to load prism syntax: ' + lang);
console.warn(e);
}
}
if (!languages[lang]) lang = DEFAULT_LANGUAGE;
// Check against html, prism "markup" works for this
if (lang === 'html') {
lang = 'markup';
}
try {
// The process can fail (failed to parse)
highlighted = Prism.highlight(block.body, languages[lang]);
} catch (e) {
console.warn('Failed to highlight:');
console.warn(e);
highlighted = block.body;
}
return highlighted;
}
},
hooks: {
// Manually copy prism-ebook.css into the temporary directory that Gitbook uses for inlining
// styles from this plugin. The getAssets() (above) function can't be leveraged because
// ebook-prism.css lives outside the folder referenced by this plugin's config.
//
// @Inspiration https://github.com/GitbookIO/plugin-styles-less/blob/master/index.js#L8
init: function() {
var book = this;
if (!isEbook(book)) {
return;
}
var outputDirectory = path.join(book.output.root(), '/gitbook/gitbook-plugin-prism');
var outputFile = path.resolve(outputDirectory, 'prism-ebook.css');
var inputFile = path.resolve(__dirname, './prism-ebook.css');
mkdirp.sync(outputDirectory);
try {
fs.writeFileSync(outputFile, fs.readFileSync(inputFile));
} catch (e) {
console.warn('Failed to write prism-ebook.css. See https://git.io/v1LHY for side effects.');
console.warn(e);
}
},
page: function(page) {
var highlighted = false;
var $ = cheerio.load(page.content);
// Prism css styles target the <code> and <pre> blocks using
// a substring CSS selector:
//
// code[class*="language-"], pre[class*="language-"]
//
// Adding "language-" to <pre> element should be sufficient to trigger
// correct color theme.
$('pre').each(function() {
highlighted = true;
const $this = $(this);
$this.addClass('language-');
});
if (highlighted) {
page.content = $.html();
}
return page;
}
}
};