Skip to content

Commit

Permalink
Merge pull request #103 from marp-team/workaround-for-theme-resolution
Browse files Browse the repository at this point in the history
Apply messy workaround to broken logic of theme directory resolution
  • Loading branch information
yhatt authored Nov 17, 2019
2 parents 6a4854d + 5fffce4 commit 78ae543
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 51 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

- Add documentation about how to enable HTML into README ([#98](https://github.com/marp-team/marp-vscode/issues/98), [#99](https://github.com/marp-team/marp-vscode/pull/99) by [@eric-burel](https://github.com/eric-burel))

### Fixed

- Apply messy workaround to broken logic of theme directory resolution ([#100](https://github.com/marp-team/marp-vscode/issues/100), [#103](https://github.com/marp-team/marp-vscode/pull/103))

### Changed

- Upgrade dependent packages to the latest version ([#102](https://github.com/marp-team/marp-vscode/pull/102))
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@
"@types/markdown-it": "^0.0.9",
"@types/vscode": "~1.36.0",
"@types/yaml": "^1.2.0",
"builtin-modules": "^3.1.0",
"cheerio": "^1.0.0-rc.3",
"codecov": "^3.6.1",
"dedent": "^0.7.0",
Expand Down
11 changes: 2 additions & 9 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from 'path'
import json from '@rollup/plugin-json'
import builtinModules from 'builtin-modules'
import commonjs from 'rollup-plugin-commonjs'
import nodeResolve from 'rollup-plugin-node-resolve'
import { terser } from 'rollup-plugin-terser'
Expand All @@ -18,15 +19,7 @@ const sourcemap = !!process.env.ROLLUP_WATCH

export default [
{
external: [
...Object.keys(pkg.dependencies),
'crypto',
'fs',
'os',
'path',
'util',
'vscode',
],
external: [...Object.keys(pkg.dependencies), ...builtinModules, 'vscode'],
input: `src/${path.basename(pkg.main, '.js')}.ts`,
output: { exports: 'named', file: pkg.main, format: 'cjs', sourcemap },
plugins,
Expand Down
3 changes: 2 additions & 1 deletion src/__mocks__/vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export const workspace = {
onDidChangeConfiguration: jest.fn(),
onDidChangeTextDocument: jest.fn(),
onDidCloseTextDocument: jest.fn(),
textDocuments: [] as any,

_setConfiguration: (conf: MockedConf = {}) => {
currentConf = { ...defaultConf, ...conf }
Expand All @@ -136,8 +137,8 @@ export class WorkspaceEdit {
}

beforeEach(() => {
currentConf = {}
window.activeTextEditor = undefined
workspace.textDocuments = []
workspace._setConfiguration()
_setVSCodeVersion(defaultVSCodeVersion)
})
12 changes: 10 additions & 2 deletions src/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,15 +217,23 @@ describe('#extendMarkdownIt', () => {
setConfiguration({ 'markdown.marp.themes': ['./test.css'] })

const markdown = md()
markdown.normalizeLink = url => path.resolve(baseDir, url)
const mdBody = marpMd('<!--theme: example-->')
;(workspace as any).textDocuments = [
{
languageId: 'markdown',
getText: () => mdBody,
uri: Uri.parse(baseDir),
fileName: path.resolve(baseDir, 'test.css'),
} as any,
]

await Promise.all(themes.loadStyles(Uri.parse(baseDir)))

expect(fsReadFile).toBeCalledWith(
path.resolve(baseDir, './test.css'),
expect.any(Function)
)
expect(markdown.render(marpMd('<!--theme: example-->'))).toContain(css)
expect(markdown.render(mdBody)).toContain(css)
})

it('cannot traverse theme CSS path to parent directory as same as markdown.styles', async () => {
Expand Down
39 changes: 26 additions & 13 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
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
Expand Down Expand Up @@ -27,28 +28,40 @@ export function extendMarkdownIt(md: any) {
md.parse = (markdown: string, env: any) => {
// Generate tokens by Marp if enabled
if (detectMarpFromMarkdown(markdown)) {
const mdFolder = Uri.parse(md.normalizeLink('.')).with({ scheme: 'file' })
const workspaceFolder = workspace.getWorkspaceFolder(mdFolder)
const baseFolder = workspaceFolder ? workspaceFolder.uri : mdFolder
// 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
let shouldRefresh = false

Promise.all(
themes.loadStyles(baseFolder).map(promise =>
promise
.then(theme => {
if (theme.registered) shouldRefresh = true
})
.catch(e => console.error(e))
themes.loadStyles(baseFolder).map(p =>
p.then(
theme => theme.registered,
e => console.error(e)
)
)
).then(() => {
if (shouldRefresh) commands.executeCommand('markdown.preview.refresh')
).then(registered => {
if (registered.some(f => f === true)) {
commands.executeCommand('markdown.preview.refresh')
}
})

for (const theme of themes.getRegisteredStyles(baseFolder)) {
Expand Down
45 changes: 24 additions & 21 deletions src/option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,30 +63,33 @@ export const marpCoreOptionForCLI = async ({ uri }: TextDocument) => {
const parentFolder = uri.scheme === 'file' && path.dirname(uri.fsPath)
const baseFolder = workspaceFolder ? workspaceFolder.uri.fsPath : parentFolder

if (baseFolder) {
const themeFiles: WorkFile[] = ((await Promise.all(
themes.loadStyles(Uri.parse(`file:${baseFolder}`)).map(promise =>
promise
.then(async theme => {
if (theme.type === ThemeType.File) {
return { path: theme.path, cleanup: () => Promise.resolve() }
}
const themeFiles: WorkFile[] = (
await Promise.all(
themes
.loadStyles(baseFolder ? Uri.parse(`file:${baseFolder}`) : undefined)
.map(promise =>
promise.then(
async theme => {
if (theme.type === ThemeType.File) {
return { path: theme.path, cleanup: () => Promise.resolve() }
}

if (theme.type === ThemeType.Remote) {
const cssName = `.marp-vscode-cli-theme-${nanoid()}.css`
const tmp = path.join(tmpdir(), cssName)
if (theme.type === ThemeType.Remote) {
const cssName = `.marp-vscode-cli-theme-${nanoid()}.css`
const tmp = path.join(tmpdir(), cssName)

await promisify(writeFile)(tmp, theme.css)
return { path: tmp, cleanup: () => promisify(unlink)(tmp) }
}
})
.catch(e => console.error(e))
)
)) as any).filter(w => w)
await promisify(writeFile)(tmp, theme.css)
return { path: tmp, cleanup: () => promisify(unlink)(tmp) }
}
},
e => console.error(e)
)
)
)
).filter((w): w is WorkFile => !!w)

baseOpts.themeSet = themeFiles.map(w => w.path)
baseOpts.vscode.themeFiles = themeFiles
}
baseOpts.themeSet = themeFiles.map(w => w.path)
baseOpts.vscode.themeFiles = themeFiles

return baseOpts
}
Expand Down
13 changes: 8 additions & 5 deletions src/themes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ export class Themes {
this.observedThemes.clear()
}

getRegisteredStyles(rootDirectory: Uri): Theme[] {
getRegisteredStyles(rootDirectory: Uri | undefined): Theme[] {
return this.getPathsFromConf(rootDirectory)
.map(p => this.observedThemes.get(p))
.filter(t => t) as Theme[]
}

loadStyles(rootDirectory: Uri): Promise<Theme>[] {
loadStyles(rootDirectory: Uri | undefined): Promise<Theme>[] {
return this.getPathsFromConf(rootDirectory).map(p => this.registerTheme(p))
}

private getPathsFromConf(rootDirectory: Uri): string[] {
private getPathsFromConf(rootDirectory: Uri | undefined): string[] {
const themes = marpConfiguration().get<string[]>('themes')

if (Array.isArray(themes) && themes.length > 0) {
Expand All @@ -57,15 +57,18 @@ export class Themes {
return []
}

private normalizePaths(paths: string[], rootDirectory: Uri): string[] {
private normalizePaths(
paths: string[],
rootDirectory: Uri | undefined
): string[] {
const normalizedPaths = new Set<string>()

for (const p of paths) {
if (typeof p !== 'string') continue

if (isRemotePath(p)) {
normalizedPaths.add(p)
} else {
} else if (rootDirectory) {
const resolvedPath = path.resolve(rootDirectory.fsPath, p)

if (
Expand Down

0 comments on commit 78ae543

Please sign in to comment.