forked from GitbookIO/plugin-codetabs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
100 lines (86 loc) · 3.1 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
var escape = require('escape-html');
function alphanumeric(input) {
return input.replace(/[^a-zA-Z0-9\-@]/g, '');
}
function wrapInTab(isActive, block, contents) {
const safeName = alphanumeric(block.kwargs.name),
safeOptionSet = alphanumeric(block.kwargs.optionSet);
return '<div class="tab' + (isActive ? ' active' : '') + '" ' +
'tab-name="' + safeName + '" ' +
'option-set="' + safeOptionSet + '"' +
'>' + contents + '</div>';
}
function createTabHeader(block, isActive) {
return wrapInTab(isActive, block, block.kwargs.name);
}
async function createTabBody(block, isActive, book) {
if (block.kwargs.type == "markdown") {
return wrapInTab(
isActive,
block,
await book.renderBlock('markdown', block.body
));
}
else {
const content =
'<pre>' +
'<code class="lang-' + block.kwargs.name + '">' +
escape(block.body) +
'</code>' +
'</pre>';
return wrapInTab(isActive, block, content);
}
}
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
module.exports = {
book: {
assets: './assets',
css: [
'tabs.css'
],
js: [
'tabs.js'
]
},
blocks: {
tabs: {
blocks: ['tab'],
process: async function (parentBlock) {
const book = this;
// optionSet is used to sort tab groups that use the same set of options.
// This will let us change the active tab for all of the tab groups using
// the same optionSet by clicking any of them.
// If an optionSet is not provided for this group of tabs, then create a GUID to
// ensure that no other optionSet will alter the active tab for this tab group
const optionSet = parentBlock.kwargs.optionSet || '@' + guid();
const blocks = [parentBlock].concat(parentBlock.blocks);
let tabsContent = "",
tabsHeader = "",
active = true;
for (let block of blocks) {
block.kwargs.optionSet = optionSet;
if (!block.kwargs.name) {
throw new Error('Tab requires a "name" property');
}
if (!block.kwargs.type) {
block.kwargs.type = block.kwargs.name;
}
tabsHeader += createTabHeader(block, active);
tabsContent += await createTabBody(block, active, book);
active = false;
};
return '<div class="tabs">' +
'<div class="tabs-header">' + tabsHeader + '</div>' +
'<div class="tabs-body">' + tabsContent + '</div>' +
'</div>';
}
}
}
};