Skip to content

Commit

Permalink
Merge pull request #199 from marp-team/magic-comment
Browse files Browse the repository at this point in the history
Mark well-known magic comments in linter and formatter as parsed
  • Loading branch information
yhatt authored Oct 10, 2019
2 parents 410d2aa + 7b69eb7 commit 11557b6
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 55 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Changed

- Ignore well-known magic comments in collected comments ([#191](https://github.com/marp-team/marpit/issues/191), [#199](https://github.com/marp-team/marpit/pull/199))
- Upgrade dependent packages to the latest version ([#196](https://github.com/marp-team/marpit/pull/196))

## v1.4.0 - 2019-09-12
Expand Down
28 changes: 25 additions & 3 deletions src/markdown/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ const commentMatcher = /<!--+\s*([\s\S]*?)\s*--+>/
const commentMatcherOpening = /^<!--/
const commentMatcherClosing = /-->/

const magicCommentMatchers = [
// Prettier
/^prettier-ignore(-(start|end))?$/,

// markdownlint
/^markdownlint-((disable|enable).*|capture|restore)$/,

// remark-lint (remark-message-control)
/^lint (disable|enable|ignore).*$/,
]

export function markAsParsed(token, kind) {
token.meta = token.meta || {}
token.meta.marpitCommentParsed = kind
}

/**
* Marpit comment plugin.
*
Expand All @@ -19,9 +35,15 @@ function comment(md) {
const parse = (token, content) => {
const parsed = yaml(content, !!md.marpit.options.looseYAML)

token.meta = {
...(token.meta || {}),
marpitParsedDirectives: parsed === false ? {} : parsed,
token.meta = token.meta || {}
token.meta.marpitParsedDirectives = parsed === false ? {} : parsed

// Mark well-known magic comments as parsed comment
for (const magicCommentMatcher of magicCommentMatchers) {
if (magicCommentMatcher.test(content.trim())) {
markAsParsed(token, 'well-known-magic-comment')
break
}
}
}

Expand Down
30 changes: 16 additions & 14 deletions src/markdown/directives/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@
import MarkdownItFrontMatter from 'markdown-it-front-matter'
import yaml from './yaml'
import * as directives from './directives'
import { markAsParsed } from '../comment'
import marpitPlugin from '../marpit_plugin'

const isComment = token =>
const isDirectiveComment = token =>
token.type === 'marpit_comment' && token.meta.marpitParsedDirectives

const markAsParsed = token => {
token.meta = token.meta || {}
token.meta.marpitCommentParsed = 'directive'
}

/**
* Parse Marpit directives and store result to the slide token meta.
*
Expand Down Expand Up @@ -101,14 +97,17 @@ function parse(md, opts = {}) {

for (const token of state.tokens) {
if (
isComment(token) &&
isDirectiveComment(token) &&
applyDirectives(token.meta.marpitParsedDirectives)
) {
markAsParsed(token)
markAsParsed(token, 'directive')
} else if (token.type === 'inline') {
for (const t of token.children) {
if (isComment(t) && applyDirectives(t.meta.marpitParsedDirectives))
markAsParsed(t)
if (
isDirectiveComment(t) &&
applyDirectives(t.meta.marpitParsedDirectives)
)
markAsParsed(t, 'directive')
}
}
}
Expand Down Expand Up @@ -190,14 +189,17 @@ function parse(md, opts = {}) {

cursor.spot = {}
} else if (
isComment(token) &&
isDirectiveComment(token) &&
applyDirectives(token.meta.marpitParsedDirectives)
) {
markAsParsed(token)
markAsParsed(token, 'directive')
} else if (token.type === 'inline') {
for (const t of token.children) {
if (isComment(t) && applyDirectives(t.meta.marpitParsedDirectives))
markAsParsed(t)
if (
isDirectiveComment(t) &&
applyDirectives(t.meta.marpitParsedDirectives)
)
markAsParsed(t, 'directive')
}
}
}
Expand Down
127 changes: 89 additions & 38 deletions test/markdown/collect.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import dedent from 'dedent'
import MarkdownIt from 'markdown-it'
import applyDirectives from '../../src/markdown/directives/apply'
import collect from '../../src/markdown/collect'
import comment from '../../src/markdown/comment'
import comment, { markAsParsed } from '../../src/markdown/comment'
import inlineSVG from '../../src/markdown/inline_svg'
import parseDirectives from '../../src/markdown/directives/parse'
import slide from '../../src/markdown/slide'
Expand Down Expand Up @@ -109,46 +109,97 @@ describe('Marpit collect plugin', () => {
expect(lastComments[3]).toStrictEqual(['inline comment'])
})

context(
'when comment token is marked marpitCommentParsed meta in other plugin',
() => {
it('ignores collecting comment', () => {
const marpit = marpitStub()

md(marpit)
.use(mdIt => {
mdIt.core.ruler.before(
'marpit_slide',
'marpit_test_inject',
state => {
const markParsed = token => {
token.meta = {
...(token.meta || {}),
marpitCommentParsed: 'test',
}
}
context('when comment token is marked as parsed by #markAsParsed', () => {
it('ignores collecting comment', () => {
const marpit = marpitStub()

for (const token of state.tokens) {
if (token.content === 'This is comment') {
markParsed(token)
} else if (token.type === 'inline') {
for (const t of token.children)
if (t.content === 'inline comment') markParsed(t)
}
md(marpit)
.use(mdIt => {
mdIt.core.ruler.before(
'marpit_slide',
'marpit_test_inject',
state => {
for (const token of state.tokens) {
if (token.content === 'This is comment') {
markAsParsed(token, 'test')
} else if (token.type === 'inline') {
for (const t of token.children)
if (t.content === 'inline comment') markAsParsed(t, 'test')
}
}
)
})
.render(text)

const { lastComments } = marpit

expect(lastComments[0]).toHaveLength(1)
expect(lastComments[0]).not.toContain('This is comment')
expect(lastComments[3]).toHaveLength(0)
})
}
)
}
)
})
.render(text)

const { lastComments } = marpit

expect(lastComments[0]).toHaveLength(1)
expect(lastComments[0]).not.toContain('This is comment')
expect(lastComments[3]).toHaveLength(0)
})

it('ignores comments for well-known linters and formatters by default', () => {
const comments = markdown => {
const marpit = marpitStub()
md(marpit).render(markdown)

return marpit.lastComments[0]
}

expect(comments('<!-- regular comment -->')).toHaveLength(1)

// Prettier
expect(comments('<!-- prettier-ignore -->')).toHaveLength(0)
expect(
comments(dedent`
<!-- prettier-ignore-start -->
<!-- test -->
<!--prettier-ignore-end-->
`)
).toHaveLength(1)

// markdownlint
expect(
comments(dedent`
<!-- markdownlint-disable no-space-in-emphasis -->
deliberate space * in * emphasis
<!-- markdownlint-enable no-space-in-emphasis -->
`)
).toHaveLength(0)
expect(
comments(dedent`
<!-- markdownlint-capture -->
<!-- markdownlint-disable -->
any violations you want
<!-- markdownlint-restore -->
`)
).toHaveLength(0)

// remark-lint (remark-message-control)
expect(comments('<!--lint disable-->')).toHaveLength(0)
expect(comments('<!--lint enable-->')).toHaveLength(0)
expect(
comments(dedent`
# Hello
<!--lint disable no-duplicate-headings-->
## Hello
<!-- lint enable no-duplicate-headings -->
`)
).toHaveLength(0)
expect(
comments(dedent`
<!--lint ignore list-item-bullet-indent strong-marker-->
* **foo**
* __bar__
`)
).toHaveLength(0)
})
})

context('with inline SVG mode', () => {
it('includes inline SVG tokens in collected result', () => {
Expand Down

0 comments on commit 11557b6

Please sign in to comment.