-
-
Notifications
You must be signed in to change notification settings - Fork 80
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 #63 from marp-team/toggle-marp-preview
Add markdown.marp.toggleMarpPreview command
- Loading branch information
Showing
13 changed files
with
255 additions
and
16 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
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,127 @@ | ||
import { Position, Range, languages, window } from 'vscode' | ||
import * as toggleMarpPreview from './toggle-marp-preview' | ||
|
||
const toggleMarpPreviewCommand = toggleMarpPreview.default | ||
|
||
jest.mock('vscode') | ||
|
||
describe('toggleMarpPreview command', () => { | ||
let toggleFunc: jest.SpyInstance | ||
|
||
beforeEach(() => { | ||
toggleFunc = jest.spyOn(toggleMarpPreview, 'toggle').mockImplementation() | ||
}) | ||
|
||
it('has no ops when active text editor is undefined', async () => { | ||
window.activeTextEditor = undefined | ||
|
||
await toggleMarpPreviewCommand() | ||
expect(toggleFunc).not.toBeCalled() | ||
}) | ||
|
||
it('runs toggle function when active text editor is Markdown', async () => { | ||
window.activeTextEditor = { document: { languageId: 'markdown' } } as any | ||
|
||
await toggleMarpPreviewCommand() | ||
expect(toggleFunc).toBeCalledWith(window.activeTextEditor) | ||
}) | ||
|
||
describe('when active text editor is not Markdown', () => { | ||
beforeEach(() => { | ||
window.activeTextEditor = { document: { languageId: 'plaintext' } } as any | ||
}) | ||
|
||
it('shows warning notification', async () => { | ||
await toggleMarpPreviewCommand() | ||
expect(toggleFunc).not.toBeCalled() | ||
expect(window.showWarningMessage).toBeCalled() | ||
}) | ||
|
||
it('changes editor language and continues process when reacted on the notification', async () => { | ||
const { showWarningMessage }: any = window | ||
showWarningMessage.mockResolvedValue( | ||
toggleMarpPreview.ITEM_CONTINUE_BY_CHANGING_LANGUAGE | ||
) | ||
|
||
await toggleMarpPreviewCommand() | ||
expect(languages.setTextDocumentLanguage).toBeCalledWith( | ||
window.activeTextEditor!.document, | ||
'markdown' | ||
) | ||
expect(toggleFunc).toBeCalledWith(window.activeTextEditor) | ||
}) | ||
}) | ||
}) | ||
|
||
describe('#toggle', () => { | ||
const editBuilder = () => ({ | ||
replace: jest.fn(), | ||
insert: jest.fn(), | ||
delete: jest.fn(), | ||
}) | ||
|
||
const textEditor = (text: string): any => { | ||
const textEditorMock: any = { | ||
_editBuilders: [], | ||
document: { getText: () => text }, | ||
} | ||
|
||
textEditorMock.edit = jest.fn(callback => { | ||
const builder = editBuilder() | ||
textEditorMock._editBuilders.push(builder) | ||
|
||
return Promise.resolve(callback(builder)) | ||
}) | ||
|
||
return textEditorMock | ||
} | ||
|
||
it('inserts frontmatter to the top when frontmatter was not detected', async () => { | ||
const editor = textEditor('') | ||
await toggleMarpPreview.toggle(editor) | ||
|
||
expect(editor._editBuilders[0].insert).toBeCalledWith( | ||
new Position(0, 0), | ||
'---\nmarp: true\n---\n\n' | ||
) | ||
}) | ||
|
||
it('inserts `marp: true` to the last line of frontmatter when frontmatter without marp key was detected', async () => { | ||
const editor = textEditor('---\ntest: abc\nfoo: bar\n---') | ||
await toggleMarpPreview.toggle(editor) | ||
|
||
expect(editor._editBuilders[0].insert).toBeCalledWith( | ||
new Position(3, 0), | ||
'marp: true\n' | ||
) | ||
|
||
// Empty frontmatter | ||
const editorEmptyFm = textEditor('---\n---') | ||
await toggleMarpPreview.toggle(editorEmptyFm) | ||
|
||
expect(editorEmptyFm._editBuilders[0].insert).toBeCalledWith( | ||
new Position(1, 0), | ||
'marp: true\n' | ||
) | ||
}) | ||
|
||
it('toggles the value of marp key in frontmatter when frontmatter with marp key was detected', async () => { | ||
// true => false | ||
const editorEnabled = textEditor('---\nmarp: true\n---') | ||
await toggleMarpPreview.toggle(editorEnabled) | ||
|
||
expect(editorEnabled._editBuilders[0].replace).toBeCalledWith( | ||
new Range(new Position(1, 6), new Position(1, 10)), | ||
'false' | ||
) | ||
|
||
// false => true | ||
const editorDisabled = textEditor('---\nfoo: bar\nmarp: false\n---') | ||
await toggleMarpPreview.toggle(editorDisabled) | ||
|
||
expect(editorDisabled._editBuilders[0].replace).toBeCalledWith( | ||
new Range(new Position(2, 8), new Position(2, 13)), | ||
'true' | ||
) | ||
}) | ||
}) |
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,65 @@ | ||
import { Position, Range, TextEditor, languages, window } from 'vscode' | ||
import { detectFrontMatter, marpDirectiveRegex } from '../utils' | ||
|
||
export const ITEM_CONTINUE_BY_CHANGING_LANGUAGE = | ||
'Continue by changing language to Markdown' | ||
|
||
export const toggle = async (editor: TextEditor) => { | ||
const originalText = editor.document.getText() | ||
const frontmatter = detectFrontMatter(originalText) | ||
|
||
if (frontmatter !== undefined) { | ||
let line = 1 | ||
let targetRange: Range | undefined | ||
let toggleValue: string | undefined | ||
|
||
for (const lText of frontmatter.split('\n')) { | ||
const matched = marpDirectiveRegex.exec(lText) | ||
|
||
if (matched) { | ||
targetRange = new Range( | ||
new Position(line, matched[1].length), | ||
new Position(line, matched[1].length + matched[2].length) | ||
) | ||
toggleValue = matched[2] === 'true' ? 'false' : 'true' | ||
} | ||
|
||
line += 1 | ||
} | ||
|
||
if (targetRange && toggleValue) { | ||
await editor.edit(e => e.replace(targetRange!, toggleValue!)) | ||
} else { | ||
await editor.edit(e => | ||
e.insert(new Position(line - 1, 0), 'marp: true\n') | ||
) | ||
} | ||
} else { | ||
await editor.edit(e => | ||
e.insert(new Position(0, 0), '---\nmarp: true\n---\n\n') | ||
) | ||
} | ||
} | ||
|
||
export default async function toggleMarpPreview() { | ||
const activeEditor = window.activeTextEditor | ||
|
||
if (activeEditor) { | ||
if (activeEditor.document.languageId === 'markdown') { | ||
await toggle(activeEditor) | ||
} else { | ||
const acted = await window.showWarningMessage( | ||
'A current document is not Markdown document. Do you want to continue by changing language?', | ||
ITEM_CONTINUE_BY_CHANGING_LANGUAGE | ||
) | ||
|
||
if (acted === ITEM_CONTINUE_BY_CHANGING_LANGUAGE) { | ||
await languages.setTextDocumentLanguage( | ||
activeEditor.document, | ||
'markdown' | ||
) | ||
await toggle(activeEditor) | ||
} | ||
} | ||
} | ||
} |
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,21 @@ | ||
import { workspace } from 'vscode' | ||
|
||
const frontMatterRegex = /^-{3,}\s*$\n([\s\S]*?)^\s*-{3}/m | ||
|
||
export const marpDirectiveRegex = /^(marp\s*: +)(.*)\s*$/m | ||
|
||
export const detectFrontMatter = (markdown: string): string | undefined => { | ||
const m = markdown.match(frontMatterRegex) | ||
return m && m.index === 0 ? m[1] : undefined | ||
} | ||
|
||
export const detectMarpFromMarkdown = (markdown: string): boolean => { | ||
const frontmatter = detectFrontMatter(markdown) | ||
if (!frontmatter) return false | ||
|
||
const matched = marpDirectiveRegex.exec(frontmatter) | ||
return matched ? matched[2] === 'true' : false | ||
} | ||
|
||
export const marpConfiguration = () => | ||
workspace.getConfiguration('markdown.marp') |