-
-
Notifications
You must be signed in to change notification settings - Fork 75
/
extension.ts
131 lines (111 loc) · 4.21 KB
/
extension.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
import path from 'path'
import { Marp } from '@marp-team/marp-core'
import { ExtensionContext, Uri, commands, workspace } from 'vscode'
import exportCommand from './commands/export' // tslint:disable-line: import-name
import showQuickPick from './commands/show-quick-pick'
import toggleMarpPreview from './commands/toggle-marp-preview'
import customTheme from './plugins/custom-theme'
import lineNumber from './plugins/line-number'
import outline from './plugins/outline'
import diagnostics from './diagnostics/' // tslint:disable-line: import-name
import { marpCoreOptionForPreview, clearMarpCoreOptionCache } from './option'
import themes from './themes'
import { detectMarpFromMarkdown } from './utils'
const shouldRefreshConfs = [
'markdown.marp.breaks',
'markdown.marp.enableHtml',
'markdown.marp.themes',
'markdown.preview.breaks',
]
export const marpVscode = Symbol('marp-vscode')
export function extendMarkdownIt(md: any) {
const { parse, renderer } = md
const { render } = renderer
md.parse = (markdown: string, env: any) => {
// Generate tokens by Marp if enabled
if (detectMarpFromMarkdown(markdown)) {
// A messy resolution by finding matched document to resolve workspace or directory of Markdown
// https://github.com/microsoft/vscode/issues/84846
const baseFolder: Uri | undefined = (() => {
for (const document of workspace.textDocuments) {
if (
document.languageId === 'markdown' &&
document.getText().replace(/\u2028|\u2029/g, '') === markdown
) {
const workspaceFolder = workspace.getWorkspaceFolder(document.uri)
if (workspaceFolder) return workspaceFolder.uri
return document.uri.with({ path: path.dirname(document.fileName) })
}
}
return undefined
})()
const marp = new Marp(marpCoreOptionForPreview(md.options))
.use(customTheme)
.use(outline)
.use(lineNumber)
// Load custom themes
Promise.all(
themes.loadStyles(baseFolder).map(p =>
p.then(
theme => theme.registered,
e => console.error(e)
)
)
).then(registered => {
if (registered.some(f => f === true)) {
commands.executeCommand('markdown.preview.refresh')
}
})
for (const theme of themes.getRegisteredStyles(baseFolder)) {
try {
marp.themeSet.add(theme.css)
} catch (e) {
console.error(
`Failed to register custom theme from "${theme.path}". (${e.message})`
)
}
}
// Use image stabilizer and link normalizer from VS Code
marp.markdown.renderer.rules.image = md.renderer.rules.image
marp.markdown.normalizeLink = md.normalizeLink
// validateLink prefers Marp's default. If overridden by VS Code's it,
// does not return compatible result with the other Marp tools.
// marp.markdown.validateLink = md.validateLink
md[marpVscode] = marp
return marp.markdown.parse(markdown, env)
}
// Fallback to original instance if Marp was not enabled
md[marpVscode] = false
return parse.call(md, markdown, env)
}
renderer.render = (tokens: any[], options: any, env: any) => {
const marp = md[marpVscode]
if (marp) {
const { markdown } = marp
const style = marp.renderStyle(marp.lastGlobalDirectives.theme)
const html = markdown.renderer.render(tokens, markdown.options, env)
return `<style id="marp-vscode-style">${style}</style>${html}`
}
return render.call(renderer, tokens, options, env)
}
return md
}
export const activate = ({ subscriptions }: ExtensionContext) => {
diagnostics(subscriptions)
subscriptions.push(
commands.registerCommand('markdown.marp.export', exportCommand),
commands.registerCommand('markdown.marp.showQuickPick', showQuickPick),
commands.registerCommand(
'markdown.marp.toggleMarpPreview',
toggleMarpPreview
),
themes,
workspace.onDidChangeConfiguration(e => {
if (shouldRefreshConfs.some(c => e.affectsConfiguration(c))) {
clearMarpCoreOptionCache()
commands.executeCommand('markdown.preview.refresh')
}
})
)
return { extendMarkdownIt }
}