Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warn deprecated dollar prefix in global directives #70

Merged
merged 17 commits into from
Sep 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"theme": "light"
},
"activationEvents": [
"onLanguage:markdown",
"onCommand:markdown.marp.export",
"onCommand:markdown.marp.showQuickPick",
"onCommand:markdown.marp.toggleMarpPreview"
Expand Down Expand Up @@ -209,18 +210,24 @@
"@marp-team/marpit-svg-polyfill": "^1.1.1",
"@types/cheerio": "^0.22.13",
"@types/jest": "^24.0.18",
"@types/lodash.debounce": "^4.0.6",
"@types/markdown-it": "^0.0.8",
"@types/semver": "^6.0.1",
"@types/vscode": "~1.31.0",
"@types/yaml": "^1.0.2",
"cheerio": "^1.0.0-rc.3",
"codecov": "^3.5.0",
"dedent": "^0.7.0",
"jest": "^24.9.0",
"jest-junit": "^7.0.0",
"markdown-it": "^9.1.0",
"lodash.debounce": "^4.0.8",
"markdown-it": "^10.0.0",
"nanoid": "^2.0.3",
"npm-run-all": "^4.1.5",
"prettier": "^1.18.2",
"rehype-parse": "^6.0.1",
"remark": "^11.0.1",
"remark-parse": "^7.0.1",
"rimraf": "^3.0.0",
"rollup": "^1.20.1",
"rollup-plugin-commonjs": "^10.0.2",
Expand All @@ -236,11 +243,14 @@
"tslint": "^5.19.0",
"tslint-config-airbnb": "^5.11.1",
"tslint-config-prettier": "^1.18.0",
"typescript": "^3.5.3"
"typescript": "^3.5.3",
"unified": "^8.3.2",
"unist-util-visit": "^2.0.0",
"yaml": "^1.6.0"
},
"dependencies": {
"@marp-team/marp-cli": "^0.13.0",
"@marp-team/marp-core": "^0.12.1",
"@marp-team/marp-cli": "^0.14.1",
"@marp-team/marp-core": "^0.13.1",
"axios": "^0.19.0"
}
}
1 change: 1 addition & 0 deletions src/__mocks__/lodash.debounce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = f => (...args) => f(...args)
50 changes: 50 additions & 0 deletions src/__mocks__/vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,44 @@ const uriInstance = (path: string) =>
return uri
})()

export class CodeAction {
// command?: Command
diagnostics?: Diagnostic[]
edit?: WorkspaceEdit
isPreferred?: boolean

constructor(public title: string, public kind?: CodeActionKind) {}
}

export class CodeActionKind {
static readonly QuickFix = new CodeActionKind('QuickFix')

constructor(readonly value: string) {}
}

export class Diagnostic {
code?: string
source?: string

constructor(
public range: Range,
public message: string,
public severity?: DiagnosticSeverity
) {}
}

export enum DiagnosticSeverity {
Error,
Warning,
Information,
Hint,
}

export class Position {
translate(lineDelta: number = 0, characterDelta: number = 0) {
return new Position(this.line + lineDelta, this.character + characterDelta)
}

constructor(readonly line: number, readonly character: number) {}
}

Expand Down Expand Up @@ -49,6 +86,12 @@ export const env = {
}

export const languages = {
createDiagnosticCollection: jest.fn(name => ({
name,
delete: jest.fn(),
set: jest.fn(),
})),
registerCodeActionsProvider: jest.fn(),
setTextDocumentLanguage: jest.fn(),
}

Expand All @@ -59,6 +102,7 @@ export const _setVSCodeVersion = (value: string) => {

export const window = {
activeTextEditor: undefined,
onDidChangeActiveTextEditor: jest.fn(),
showErrorMessage: jest.fn(),
showQuickPick: jest.fn(),
showSaveDialog: jest.fn(),
Expand All @@ -79,12 +123,18 @@ export const workspace = {
})),
getWorkspaceFolder: jest.fn(),
onDidChangeConfiguration: jest.fn(),
onDidChangeTextDocument: jest.fn(),
onDidCloseTextDocument: jest.fn(),

_setConfiguration: (conf: MockedConf = {}) => {
currentConf = { ...defaultConf, ...conf }
},
}

export class WorkspaceEdit {
readonly delete = jest.fn()
}

beforeEach(() => {
currentConf = {}
window.activeTextEditor = undefined
Expand Down
199 changes: 199 additions & 0 deletions src/diagnostics/deprecated-dollar-prefix.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import dedent from 'dedent'
import {
CancellationToken,
CodeAction,
CodeActionKind,
Diagnostic,
DiagnosticSeverity,
languages,
Position,
Range,
TextDocument,
WorkspaceEdit,
} from 'vscode'
import * as rule from './deprecated-dollar-prefix'

jest.mock('vscode')

const doc = (text: string): TextDocument =>
({
getText: () => text,
positionAt: (offset: number) => {
const lines = text.slice(0, offset).split('\n')
return new Position(lines.length - 1, lines.pop()!.length)
},
uri: '/test/document',
} as any)

describe('[Diagnostics rule] Deprecated dollar prefix', () => {
const register = (doc: TextDocument): Diagnostic[] => {
const diagnostics: Diagnostic[] = []
rule.register(doc, diagnostics)

return diagnostics
}

describe('#register', () => {
it('does not add diagnostics when passed pure markdown', () =>
expect(register(doc('# Hello'))).toHaveLength(0))

it('does not add diagnostics when passed only marp directive', () =>
expect(register(doc('---\nmarp: true\n---\n\n# Hello'))).toHaveLength(0))

it('does not add diagnostics when passed valid directives', () =>
expect(
register(doc('---\nmarp: true\ntheme: default\n---'))
).toHaveLength(0))

it('adds diagnostics to warn deprecated directives when passed outdated directives', () => {
const [$theme] = register(doc('---\nmarp: true\n$theme: default\n---'))

expect($theme).toBeInstanceOf(Diagnostic)
expect($theme.code).toBe(rule.code)
expect($theme.source).toBe('marp-vscode')
expect($theme.severity).toBe(DiagnosticSeverity.Warning)
expect($theme.range).toStrictEqual(
new Range(new Position(2, 0), new Position(2, 6))
)

// Multiple deprecated directives
const document = doc(dedent`
---
$size: 4:3
theme: default

$headingDivider: 2
$style: |
section { background: #eee; }

marp: true
---
`)

const diagnostics = register(document)
expect(diagnostics).toHaveLength(3)
expect(diagnostics.every(d => d instanceof Diagnostic)).toBe(true)
expect(diagnostics.every(d => d.source === 'marp-vscode')).toBe(true)
expect(diagnostics.every(d => d.code === rule.code)).toBe(true)

const [$size, $headingDivider, $style] = diagnostics
expect($size.range).toStrictEqual(
new Range(new Position(1, 0), new Position(1, 5))
)
expect($headingDivider.range).toStrictEqual(
new Range(new Position(4, 0), new Position(4, 15))
)
expect($style.range).toStrictEqual(
new Range(new Position(5, 0), new Position(5, 6))
)
})

it('adds diagnostics when passed outdated directives as HTML comment', () => {
const document = doc(dedent`
---
marp: true
---

<!-- $theme: default -->

<!---
class: foobar
$size: 16:9
--->

\`\`\`
<!-- $theme: gaia -->
\`\`\`

<!-- $theme: uncover -->

<!-- $style: "" -->

# Hello! <!--fit-->

xxxxx <!-- $headingDivider: 1 --> xxxxx
`)

const diagnostics = register(document)
expect(diagnostics).toHaveLength(4)
expect(diagnostics.every(d => d instanceof Diagnostic)).toBe(true)
expect(diagnostics.every(d => d.source === 'marp-vscode')).toBe(true)
expect(diagnostics.every(d => d.code === rule.code)).toBe(true)

const [$theme, $size, $style, $headingDivider] = diagnostics
expect($theme.range).toStrictEqual(
new Range(new Position(4, 5), new Position(4, 11))
)
expect($size.range).toStrictEqual(
new Range(new Position(8, 0), new Position(8, 5))
)
expect($style.range).toStrictEqual(
new Range(new Position(17, 7), new Position(17, 13))
)
expect($headingDivider.range).toStrictEqual(
new Range(new Position(21, 11), new Position(21, 26))
)
})
})

describe('#subscribe', () => {
it('subscribes registered RemoveDollarPrefix code action provider', () => {
const subscriptions: any[] = []
rule.subscribe(subscriptions)

expect(languages.registerCodeActionsProvider).toBeCalledWith(
'markdown',
expect.any(rule.RemoveDollarPrefix),
{ providedCodeActionKinds: [CodeActionKind.QuickFix] }
)
})
})

describe('RemoveDollarPrefix code action', () => {
describe('#provideCodeActions', () => {
const dummyRange = new Range(new Position(0, 0), new Position(0, 0))
const dummyToken = {} as CancellationToken

it('returns created code actions for corresponding diagnostics', () => {
const document = doc('---\nmarp: true\n$theme: default\n---')
const diagnostics = register(document)
const codeActions = new rule.RemoveDollarPrefix().provideCodeActions(
document,
dummyRange,
{ diagnostics },
dummyToken
)

expect(codeActions).toHaveLength(1)
expect(codeActions![0]).toBeInstanceOf(CodeAction)

// Quick fix action
const action: CodeAction = codeActions![0]
expect(action.kind).toBe(CodeActionKind.QuickFix)
expect(action.diagnostics).toStrictEqual(diagnostics)
expect(action.edit).toBeInstanceOf(WorkspaceEdit)

// Edit
const edit: WorkspaceEdit = action.edit!
expect(edit.delete).toBeCalledTimes(1)
expect(edit.delete).toBeCalledWith(
document.uri,
new Range(new Position(2, 0), new Position(2, 1)) // "$"
)
})

it('does not create code actions when dorresponding diagnostics have not passed', () => {
const document = doc('---\nmarp: true\n---')
const diagnostics = register(document)
const codeActions = new rule.RemoveDollarPrefix().provideCodeActions(
document,
dummyRange,
{ diagnostics },
dummyToken
)

expect(codeActions).toHaveLength(0)
})
})
})
})
Loading