Skip to content

Commit

Permalink
Merge pull request #240 from marp-team/directive-parser-crlf
Browse files Browse the repository at this point in the history
Fix wrong highlight in CRLF
  • Loading branch information
yhatt authored May 18, 2021
2 parents d42d9c2 + d935fa2 commit 0e0e0ba
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 45 deletions.
20 changes: 0 additions & 20 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,6 @@ jobs:
steps:
- audit

unit-electron9:
executor:
name: node
version: '12.14.1'
steps:
- test

unit-electron11:
executor:
name: node
version: '12.18.3'
steps:
- test

unit-electron12:
executor:
name: node
Expand All @@ -108,12 +94,6 @@ workflows:
test:
jobs:
- audit
- unit-electron9:
requires:
- audit
- unit-electron11:
requires:
- audit
- unit-electron12:
requires:
- audit
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

### Fixed

- Wrong highlight in CRLF ([#239](https://github.com/marp-team/marp-vscode/issues/239), [#240](https://github.com/marp-team/marp-vscode/pull/240))

## v1.0.0 - 2021-05-17

### Breaking
Expand Down
33 changes: 25 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@
"unist-util-visit": "^3.1.0",
"utf-8-validate": "^5.0.5",
"vsce": "^1.88.0",
"yaml": "^1.10.2"
"yaml": "^2.0.0-5"
},
"dependencies": {
"@marp-team/marp-cli": "^1.1.1",
Expand Down
2 changes: 1 addition & 1 deletion src/diagnostics/deprecated-dollar-prefix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function register(
diagnostics: Diagnostic[]
) {
directiveParser.on('directive', ({ item, offset }) => {
if (warnDirectives.includes(item.key.value)) {
if (warnDirectives.includes(item.key.value) && item.key.range) {
const name = item.key.value.slice(1)
const [start, end] = item.key.range

Expand Down
4 changes: 2 additions & 2 deletions src/diagnostics/overloading-global-directive.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Diagnostic, DiagnosticSeverity, Range, TextDocument } from 'vscode'
import { Pair } from 'yaml/types'
import { DirectiveParser, DirectiveType } from '../directives/parser'
import type { Pair } from 'yaml'

interface ParsedGlobalDirective {
item: Pair
Expand All @@ -21,7 +21,7 @@ export function register(
})

directiveParser.on('directive', ({ item, offset, info }) => {
if (info?.type === DirectiveType.Global) {
if (info?.type === DirectiveType.Global && item.key.range) {
const [start] = item.key.range
const [, end] = item.value?.range ?? item.key.range

Expand Down
2 changes: 1 addition & 1 deletion src/diagnostics/unknown-theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function register(
})

directiveParser.on('directive', ({ item, offset, info }) => {
if (info?.name === 'theme' && item.value) {
if (info?.name === 'theme' && item.value?.range) {
const [start, end] = item.value.range

parsed = {
Expand Down
25 changes: 16 additions & 9 deletions src/directives/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import TypedEmitter from 'typed-emitter'
import unified from 'unified'
import { visit } from 'unist-util-visit'
import { Range, TextDocument } from 'vscode'
import yaml from 'yaml'
import { Pair, YAMLMap } from 'yaml/types'
import yaml, { Pair, Scalar, YAMLMap } from 'yaml'
import { frontMatterRegex } from '../utils'
import {
builtinDirectives,
Expand All @@ -30,7 +29,7 @@ const parseYaml = (yamlBody: string) =>

export interface DirectiveEventHandler {
info?: DirectiveInfo
item: Pair
item: Pair<Scalar<string>, Scalar<any>>
offset: number
}

Expand Down Expand Up @@ -63,11 +62,12 @@ export class DirectiveParser extends (EventEmitter as new () => TypedEmitter<Dir
offset: number,
definedIn = DirectiveDefinedIn.Comment
) => {
const { contents, errors } = parseYaml(text)
const { contents, errors } = parseYaml(text.replace(/\r$/, ''))

if (errors.length === 0 && contents?.['items']) {
for (const item of (contents as YAMLMap).items) {
if (item.type === 'PAIR') {
for (const item of (contents as YAMLMap<Scalar<string>, Scalar<any>>)
.items) {
if (item.key && item.value) {
let scoped: boolean | undefined = undefined

const directiveInfo = this.directives.find((d) => {
Expand Down Expand Up @@ -116,23 +116,30 @@ export class DirectiveParser extends (EventEmitter as new () => TypedEmitter<Dir
// HTML comments
visit(parseMd(markdown), 'html', (n: any) => {
visit(parseHtml(n.value), 'comment', (c: any) => {
const rawBody = n.value.slice(
c.position.start.offset,
c.position.end.offset
)

this.emit('comment', {
body: `<!--${c.value}-->`,
body: rawBody,
range: new Range(
doc.positionAt(index + n.position.start.offset),
doc.positionAt(index + n.position.end.offset)
),
})

const trimmedLeft = c.value.replace(/^-*\s*/, '')
// c.value should not use because it has normalized CRLF to LF
const value = rawBody.slice(4, -3)
const trimmedLeft = value.replace(/^-*\s*/, '')

detectDirectives(
trimmedLeft.replace(/\s*-*$/, ''),
index +
n.position.start.offset +
c.position.start.offset +
4 +
(c.value.length - trimmedLeft.length)
(value.length - trimmedLeft.length)
)
})
})
Expand Down
111 changes: 109 additions & 2 deletions src/language/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,17 @@ describe('Language parser', () => {
test: test
---
<!-- paginate: true -->
<!--
paginate: true
-->
<!-- _paginate: false -->
`),
positionAt: (idx: number) => new Position(0, idx),
positionAt(offset: number) {
const lines = this.getText().slice(0, offset).split('\n')

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return new Position(lines.length - 1, lines.pop()!.length)
},
}
window.activeTextEditor = { document } as any

Expand All @@ -82,6 +89,106 @@ describe('Language parser', () => {
expect(data?.commentRanges).toHaveLength(2)
expect(data?.frontMatterRange).toBeInstanceOf(Range)
expect(data?.directvies).toHaveLength(4)

// Range data
expect(data?.directvies[0].range.start).toMatchObject({
line: 1,
character: 0,
})
expect(data?.directvies[0].range.end).toMatchObject({
line: 1,
character: 10,
})
expect(data?.directvies[1].range.start).toMatchObject({
line: 2,
character: 0,
})
expect(data?.directvies[1].range.end).toMatchObject({
line: 2,
character: 14,
})
expect(data?.directvies[2].range.start).toMatchObject({
line: 7,
character: 0,
})
expect(data?.directvies[2].range.end).toMatchObject({
line: 7,
character: 14,
})
expect(data?.directvies[3].range.start).toMatchObject({
line: 9,
character: 5,
})
expect(data?.directvies[3].range.end).toMatchObject({
line: 9,
character: 21,
})
})

it('has correct source map even if used CR+LF newline', async () => {
const document = {
languageId: 'markdown',
getText: () => {
const baseDoc = dedent(`
---
marp: true
theme: default
test: test
---
<!--
paginate: true
-->
<!-- _paginate: false -->
`)

return baseDoc.split('\n').join('\r\n')
},
positionAt(offset: number) {
const lines = this.getText().slice(0, offset).split('\n')

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return new Position(lines.length - 1, lines.pop()!.length)
},
}
window.activeTextEditor = { document } as any

const parser = new LanguageParser([])
const data = await parser.getParseData(document as any)

expect(data).toBeTruthy()
expect(data?.directvies[0].range.start).toMatchObject({
line: 1,
character: 0,
})
expect(data?.directvies[0].range.end).toMatchObject({
line: 1,
character: 10,
})
expect(data?.directvies[1].range.start).toMatchObject({
line: 2,
character: 0,
})
expect(data?.directvies[1].range.end).toMatchObject({
line: 2,
character: 14,
})
expect(data?.directvies[2].range.start).toMatchObject({
line: 7,
character: 0,
})
expect(data?.directvies[2].range.end).toMatchObject({
line: 7,
character: 14,
})
expect(data?.directvies[3].range.start).toMatchObject({
line: 9,
character: 5,
})
expect(data?.directvies[3].range.end).toMatchObject({
line: 9,
character: 21,
})
})

it('does not parse Markdown when it is not Marp Markdown', async () => {
Expand Down
2 changes: 1 addition & 1 deletion src/language/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export class LanguageParser
})
.on('comment', ({ range }) => commentRanges.push(range))
.on('directive', ({ item, info, offset }) => {
if (info) {
if (info && item.key.range) {
const [start, end] = item.key.range
const [, vEnd] = item.value?.range ?? item.key.range

Expand Down

0 comments on commit 0e0e0ba

Please sign in to comment.