Skip to content

Commit

Permalink
Merge pull request #148 from marp-team/fragmented-list
Browse files Browse the repository at this point in the history
Add fragment plugin and parse fragmented list
  • Loading branch information
yhatt authored Apr 3, 2019
2 parents 8767170 + ee204ca commit a766742
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 1 deletion.
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]

### Added

- Parse lists in `*` and `1)` marker as fragmented list ([#145](https://github.com/marp-team/marpit/issues/145), [#148](https://github.com/marp-team/marpit/pull/148))

### Changed

- Upgrade dependent packages to the latest version ([#143](https://github.com/marp-team/marpit/pull/143))
Expand Down
52 changes: 52 additions & 0 deletions src/markdown/fragment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/** @module */
import marpitPlugin from './marpit_plugin'

const fragmentedListMarkups = ['*', ')']

/**
* Marpit fragment plugin.
*
* @alias module:markdown/fragment
* @param {MarkdownIt} md markdown-it instance.
*/
function fragment(md) {
// Fragmented list
md.core.ruler.after('marpit_directives_parse', 'marpit_fragment', state => {
if (state.inlineMode) return

for (const token of state.tokens) {
if (
token.type === 'list_item_open' &&
fragmentedListMarkups.includes(token.markup)
) {
token.meta = token.meta || {}
token.meta.marpitFragment = true
}
}
})

// Add data-marpit-fragment(s) attributes to token
md.core.ruler.after('marpit_fragment', 'marpit_apply_fragment', state => {
if (state.inlineMode) return

const fragments = { slide: undefined, count: 0 }

for (const token of state.tokens) {
if (token.meta && token.meta.marpitSlideElement === 1) {
fragments.slide = token
fragments.count = 0
} else if (token.meta && token.meta.marpitSlideElement === -1) {
if (fragments.slide && fragments.count > 0) {
fragments.slide.attrSet('data-marpit-fragments', fragments.count)
}
} else if (token.meta && token.meta.marpitFragment) {
fragments.count += 1

token.meta.marpitFragment = fragments.count
token.attrSet('data-marpit-fragment', fragments.count)
}
}
})
}

export default marpitPlugin(fragment)
4 changes: 3 additions & 1 deletion src/marpit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import marpitBackgroundImage from './markdown/background_image'
import marpitCollect from './markdown/collect'
import marpitComment from './markdown/comment'
import marpitContainerPlugin from './markdown/container'
import marpitFragment from './markdown/fragment'
import marpitHeaderAndFooter from './markdown/header_and_footer'
import marpitHeadingDivider from './markdown/heading_divider'
import marpitInlineSVG from './markdown/inline_svg'
Expand Down Expand Up @@ -179,8 +180,9 @@ class Marpit {
.use(marpitSweep)
.use(marpitInlineSVG)
.use(marpitStyleAssign)
.use(marpitCollect)
.use(marpitBackgroundImage)
.use(marpitFragment)
.use(marpitCollect)
}

/**
Expand Down
84 changes: 84 additions & 0 deletions test/markdown/fragment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import cheerio from 'cheerio'
import MarkdownIt from 'markdown-it'
import fragment from '../../src/markdown/fragment'
import slide from '../../src/markdown/slide'

describe('Marpit fragment plugin', () => {
const md = () => {
const instance = new MarkdownIt('commonmark')
instance.marpit = {}

return instance
.use(slide)
.use(m => m.core.ruler.push('marpit_directives_parse', () => {}))
.use(fragment)
}

describe('Fragmented unordered list', () => {
context('when using "*" markup', () => {
const markdown = '* A\n* B\n* C'
const $ = cheerio.load(md().render(markdown))

it('adds data-marpit-fragment attribute to <li> with index', () => {
const li = $('ul > li[data-marpit-fragment]')
expect(li).toHaveLength(3)

const indexes = li.map((_, el) => $(el).data('marpit-fragment')).get()
expect(indexes).toStrictEqual([1, 2, 3])
})

it('adds data-marpit-fragments attribute to <section> with count of fragments', () => {
const section = $('section[data-marpit-fragments]')

expect(section).toHaveLength(1)
expect(section.data('marpit-fragments')).toBe(3)
})
})

for (const char of ['-', '+']) {
context(`when using "${char}" markup`, () => {
const markdown = `${char} A\n${char} B\n${char} C`
const $ = cheerio.load(md().render(markdown))

it('does not add data-marpit-fragment attribute', () =>
expect($('[data-marpit-fragment]')).toHaveLength(0))

it('does not add data-marpit-fragments attribute', () =>
expect($('[data-marpit-fragments]')).toHaveLength(0))
})
}
})

describe('Fragmented ordered list', () => {
context('when using "1)" markup', () => {
const markdown = '1) A\n1) B\n1) C'
const $ = cheerio.load(md().render(markdown))

it('adds data-marpit-fragment attribute to <li> with index', () => {
const li = $('ol > li[data-marpit-fragment]')
expect(li).toHaveLength(3)

const indexes = li.map((_, el) => $(el).data('marpit-fragment')).get()
expect(indexes).toStrictEqual([1, 2, 3])
})

it('adds data-marpit-fragments attribute to <section> with count of fragments', () => {
const section = $('section[data-marpit-fragments]')

expect(section).toHaveLength(1)
expect(section.data('marpit-fragments')).toBe(3)
})
})

context(`when using "1." markup`, () => {
const markdown = `1. A\n1. B\n1. C`
const $ = cheerio.load(md().render(markdown))

it('does not add data-marpit-fragment attribute', () =>
expect($('[data-marpit-fragment]')).toHaveLength(0))

it('does not add data-marpit-fragments attribute', () =>
expect($('[data-marpit-fragments]')).toHaveLength(0))
})
})
})

0 comments on commit a766742

Please sign in to comment.