-
-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathflavor-container.js
executable file
·161 lines (161 loc) · 4.27 KB
/
flavor-container.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
'use strict'
var __importDefault =
(this && this.__importDefault) ||
function (mod) {
return mod && mod.__esModule ? mod : { default: mod }
}
Object.defineProperty(exports, '__esModule', { value: true })
exports.wrapFlavorContainersInTabs =
exports.markFlavorHeadings =
exports.createFlavorContainer =
void 0
const token_1 = __importDefault(require('markdown-it/lib/token'))
/**
* Adds flavor containers
*
* For example:
* /// flavor vue
* ...vue specific content...
* ///
*/
const container = require('markdown-it-container')
const klass = 'flavor'
function createFlavorContainer() {
return [
container,
klass,
{
marker: '/',
render(tokens, idx) {
const token = tokens[idx]
const info = token.info.trim().slice(klass.length).trim()
if (token.nesting === 1) {
return `<div class="${klass} ${info}" data-tab-title="${info}">\n`
} else {
return `</div>\n`
}
},
},
]
}
exports.createFlavorContainer = createFlavorContainer
/**
* Adds flavor classes to headings
*
* Adds flavor to headings array used in sidebars
*/
function markFlavorHeadings(md) {
const renderHeadingOpen = md.renderer.rules['heading_open']
const renderContainerFlavorOpen = md.renderer.rules['container_flavor_open']
const renderContainerFlavorClose = md.renderer.rules['container_flavor_close']
let currentFlavor = null
md.renderer.rules['container_flavor_open'] = function (
tokens,
idx,
options,
env,
renderer
) {
const info = tokens[idx].info.trim().slice(klass.length).trim()
currentFlavor = info
return renderContainerFlavorOpen(tokens, idx, options, env, renderer)
}
md.renderer.rules['container_flavor_close'] = function (
tokens,
idx,
options,
env,
renderer
) {
currentFlavor = null
return renderContainerFlavorClose(tokens, idx, options, env, renderer)
}
md.renderer.rules['heading_open'] = function (
tokens,
idx,
options,
env,
renderer
) {
if (currentFlavor) {
const token = tokens[idx]
token.attrJoin('class', currentFlavor)
// render now to apply other plugins like vitepress headings
const rendered = renderHeadingOpen(tokens, idx, options, env, renderer)
// update headings data afterwards
const idAttr = token.attrs.find(([name]) => name === 'id')
const slug = idAttr && idAttr[1]
const headers = md.__data.headers
if (headers) {
const header = headers.find((h) => h.slug === slug)
if (header) {
header.flavor = currentFlavor
}
}
return rendered
}
return renderHeadingOpen(tokens, idx, options, env, renderer)
}
}
exports.markFlavorHeadings = markFlavorHeadings
function wrapFlavorContainersInTabs(md) {
const process = md.core.process.bind(md.core)
md.core.process = function (state) {
process(state)
processFlavorContainers(state)
return state
}
}
exports.wrapFlavorContainersInTabs = wrapFlavorContainersInTabs
function processFlavorContainers(state) {
const OPEN_TYPE = 'container_flavor_open'
const CLOSE_TYPE = 'container_flavor_close'
const DEBUG = false
const tokens = state.tokens
let lastTokenType
let groupStart
let groups = []
for (let idx = 0; idx < tokens.length; idx++) {
const token = tokens[idx]
DEBUG &&
console.log(`${idx} | ${token.type} (LAST TYPE = ${lastTokenType})`)
if (lastTokenType === CLOSE_TYPE && token.type !== OPEN_TYPE) {
// close group
groups.push({ start: groupStart, end: idx - 1 })
groupStart = undefined
lastTokenType = undefined
DEBUG && console.log(`CLOSE GROUP | `, groups[groups.length - 1])
}
if (!(token.type === OPEN_TYPE || token.type === CLOSE_TYPE)) {
DEBUG && console.log('SKIP')
continue
}
if (token.type === OPEN_TYPE) {
DEBUG && console.log('OPEN')
if (groupStart === undefined) {
DEBUG && console.log('OPEN GROUP')
groupStart = idx
}
}
if (token.type === CLOSE_TYPE) {
DEBUG && console.log('CLOSE')
}
lastTokenType = token.type
}
// insert wrapping tokens
let idxOffset = 0
groups.forEach((group) => {
const start = group.start + idxOffset
const start_token = new token_1.default(
'flavor_group_start',
'FlavorTabs',
1
)
state.tokens.splice(start, 0, start_token)
idxOffset++
const end = group.end + 1 + idxOffset
const end_token = new token_1.default('flavor_group_end', 'FlavorTabs', -1)
state.tokens.splice(end, 0, end_token)
idxOffset++
})
}