-
-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from marp-team/marp-cli-integration
Add command to export PDF, HTML, and images via Marp CLI integration
- Loading branch information
Showing
16 changed files
with
1,282 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
v10.2.0 | ||
v10.15.3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = new Proxy(require.requireActual('../option'), { | ||
get: (target, prop) => { | ||
target.clearMarpCoreOptionCache() // Disable option cache while running test | ||
return target[prop] | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,55 @@ | ||
/* tslint:disable: variable-name */ | ||
type MockedConf = Record<string, any> | ||
|
||
const defaultConf: MockedConf = { | ||
'markdown.marp.breaks': 'on', | ||
'markdown.marp.enableHtml': false, | ||
'window.zoomLevel': 0, | ||
} | ||
|
||
let currentConf: MockedConf = {} | ||
|
||
export const ProgressLocation = { | ||
Notification: 'notification', | ||
} | ||
|
||
export const Uri = { | ||
file: (path: string) => ({ fsPath: path }), | ||
} | ||
|
||
export const commands = { | ||
executeCommand: jest.fn(), | ||
registerCommand: jest.fn(), | ||
} | ||
|
||
export const env = { | ||
openExternal: jest.fn(), | ||
} | ||
|
||
export const window = { | ||
activeTextEditor: undefined, | ||
showErrorMessage: jest.fn(), | ||
showSaveDialog: jest.fn(), | ||
showWarningMessage: jest.fn(), | ||
withProgress: jest.fn(), | ||
} | ||
|
||
export const workspace = { | ||
getConfiguration: jest.fn(() => new Map()), | ||
getConfiguration: jest.fn((section?: string) => ({ | ||
get: jest.fn( | ||
(subSection?: string) => | ||
currentConf[[section, subSection].filter(s => s).join('.')] | ||
), | ||
})), | ||
getWorkspaceFolder: jest.fn(), | ||
onDidChangeConfiguration: jest.fn(), | ||
|
||
_setConfiguration: (conf: MockedConf = {}) => { | ||
currentConf = { ...defaultConf, ...conf } | ||
}, | ||
} | ||
|
||
beforeEach(() => { | ||
window.activeTextEditor = undefined | ||
workspace._setConfiguration() | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import { env, window } from 'vscode' | ||
import * as exportModule from './export' | ||
import * as marpCli from '../marp-cli' | ||
|
||
const exportCommand = exportModule.default | ||
|
||
jest.mock('vscode') | ||
|
||
describe('Export command', () => { | ||
let saveDialog: jest.Mock | ||
|
||
beforeEach(() => { | ||
saveDialog = jest.spyOn(exportModule, 'saveDialog').mockImplementation() | ||
}) | ||
|
||
it('has no ops when active text editor is undefined', async () => { | ||
window.activeTextEditor = undefined | ||
|
||
await exportCommand() | ||
expect(saveDialog).not.toBeCalled() | ||
}) | ||
|
||
it('opens save dialog when active text editor is Markdown', async () => { | ||
window.activeTextEditor = { document: { languageId: 'markdown' } } as any | ||
|
||
await exportCommand() | ||
expect(saveDialog).toBeCalledWith(window.activeTextEditor!.document) | ||
}) | ||
|
||
describe('when active text editor is not Markdown', () => { | ||
beforeEach(() => { | ||
window.activeTextEditor = { document: { languageId: 'plaintext' } } as any | ||
}) | ||
|
||
it('shows warning notification', async () => { | ||
await exportCommand() | ||
expect(saveDialog).not.toBeCalled() | ||
expect(window.showWarningMessage).toBeCalled() | ||
}) | ||
|
||
it('continues exporting when reacted on the notification to continue', async () => { | ||
const { showWarningMessage }: any = window | ||
showWarningMessage.mockResolvedValue(exportModule.ITEM_CONTINUE_TO_EXPORT) | ||
|
||
await exportCommand() | ||
expect(saveDialog).toBeCalledWith(window.activeTextEditor!.document) | ||
}) | ||
}) | ||
}) | ||
|
||
describe('#saveDialog', () => { | ||
const document: any = { uri: { fsPath: '/tmp/test.md' } } | ||
|
||
it('opens save dialog with default URI', async () => { | ||
await exportModule.saveDialog(document) | ||
|
||
expect(window.showSaveDialog).toBeCalledWith( | ||
expect.objectContaining({ | ||
defaultUri: expect.objectContaining({ fsPath: '/tmp/test' }), | ||
}) | ||
) | ||
}) | ||
|
||
it('runs exporting with notification when file path is specified', async () => { | ||
const saveURI: any = { path: 'PATH', fsPath: '/tmp/saveTo.pdf' } | ||
jest.spyOn(window, 'showSaveDialog').mockImplementation(() => saveURI) | ||
|
||
const doExportMock: jest.Mock = jest | ||
.spyOn(exportModule, 'doExport') | ||
.mockImplementation() | ||
|
||
await exportModule.saveDialog(document) | ||
expect(window.withProgress).toBeCalledWith( | ||
expect.objectContaining({ title: expect.stringContaining('PATH') }), | ||
expect.any(Function) | ||
) | ||
;(window.withProgress as any).mock.calls[0][1]() | ||
expect(doExportMock).toBeCalledWith(saveURI, document) | ||
}) | ||
}) | ||
|
||
describe('#doExport', () => { | ||
const saveURI: any = { fsPath: '/tmp/to.pdf' } | ||
const document: any = { uri: { scheme: 'file', fsPath: '/tmp/md.md' } } | ||
|
||
it('exports passed document via Marp CLI and opens it', async () => { | ||
const runMarpCLI = jest.spyOn(marpCli, 'default').mockImplementation() | ||
|
||
await exportModule.doExport(saveURI, document) | ||
expect(runMarpCLI).toBeCalled() | ||
expect(env.openExternal).toBeCalledWith(saveURI) | ||
}) | ||
|
||
it('shows warning when Marp CLI throws error', async () => { | ||
jest.spyOn(marpCli, 'default').mockRejectedValue(new Error('ERROR')) | ||
|
||
await exportModule.doExport(saveURI, document) | ||
expect(window.showErrorMessage).toBeCalledWith( | ||
expect.stringContaining('Error: ERROR') | ||
) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import path from 'path' | ||
import { env, ProgressLocation, TextDocument, Uri, window } from 'vscode' | ||
import marpCli, { | ||
createConfigFile, | ||
createWorkFile, | ||
MarpCLIError, | ||
} from '../marp-cli' | ||
|
||
export const ITEM_CONTINUE_TO_EXPORT = 'Continue to export...' | ||
|
||
export const doExport = async (uri: Uri, document: TextDocument) => { | ||
const input = await createWorkFile(document) | ||
|
||
try { | ||
const conf = await createConfigFile(document) | ||
|
||
try { | ||
await marpCli('-c', conf.path, input.path, '-o', uri.fsPath) | ||
env.openExternal(uri) | ||
} finally { | ||
conf.cleanup() | ||
} | ||
} catch (e) { | ||
window.showErrorMessage( | ||
`Failure to export. ${ | ||
e instanceof MarpCLIError ? e.message : e.toString() | ||
}` | ||
) | ||
} finally { | ||
input.cleanup() | ||
} | ||
} | ||
|
||
export const saveDialog = async (document: TextDocument) => { | ||
const { fsPath } = document.uri | ||
|
||
const saveURI = await window.showSaveDialog({ | ||
defaultUri: Uri.file(fsPath.slice(0, -path.extname(fsPath).length)), | ||
filters: { | ||
'PDF slide deck': ['pdf'], | ||
'HTML slide deck': ['html'], | ||
'PNG image (first slide only)': ['png'], | ||
'JPEG image (first slide only)': ['jpg', 'jpeg'], | ||
}, | ||
saveLabel: 'Export', | ||
}) | ||
|
||
if (saveURI) { | ||
await window.withProgress( | ||
{ | ||
location: ProgressLocation.Notification, | ||
title: `Exporting Marp slide deck to ${saveURI.path}...`, | ||
}, | ||
() => doExport(saveURI, document) | ||
) | ||
} | ||
} | ||
|
||
export default async function exportCommand() { | ||
const activeEditor = window.activeTextEditor | ||
|
||
if (activeEditor) { | ||
if (activeEditor.document.languageId === 'markdown') { | ||
await saveDialog(activeEditor.document) | ||
} else { | ||
const acted = await window.showWarningMessage( | ||
'A current document is not Markdown document.', | ||
ITEM_CONTINUE_TO_EXPORT | ||
) | ||
|
||
if (acted === ITEM_CONTINUE_TO_EXPORT) { | ||
await saveDialog(activeEditor.document) | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.