Skip to content

Commit

Permalink
Merge pull request #64 from marp-team/support-enhanced-marpit-plugin
Browse files Browse the repository at this point in the history
Support an enhanced Marpit enable state
  • Loading branch information
yhatt authored Jan 31, 2019
2 parents a7b6f6e + e5b060d commit 6a6b7df
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 61 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Changed

- Upgrade dependent packages to latest version, includes [Marpit v0.7.0](https://github.com/marp-team/marpit/releases/tag/v0.7.0) ([#63](https://github.com/marp-team/marp-core/pull/63))
- Support an enhanced Marpit enable state ([#64](https://github.com/marp-team/marp-core/pull/64))

## v0.5.1 - 2019-01-26

Expand Down
39 changes: 22 additions & 17 deletions src/emoji/emoji.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import emojiRegex from 'emoji-regex'
import Token from 'markdown-it/lib/token'
import markdownItEmoji from 'markdown-it-emoji'
import twemoji from 'twemoji'
import { marpEnabledSymbol } from '../marp'
import twemojiCSS from './twemoji.scss'

export interface EmojiOptions {
Expand Down Expand Up @@ -56,7 +57,7 @@ export function markdown(md, opts: EmojiOptions): void {
Object.assign(new Token(), {
...t,
content: text,
type: idx % 2 ? 'unicode_emoji' : 'text',
type: idx % 2 ? 'marp_unicode_emoji' : 'text',
}),
],
[]
Expand All @@ -72,28 +73,32 @@ export function markdown(md, opts: EmojiOptions): void {
}
})

md.renderer.rules.unicode_emoji = (token: any[], idx: number): string =>
token[idx].content
md.renderer.rules.marp_unicode_emoji = (
token: any[],
idx: number
): string => token[idx].content

const { code_block, code_inline, fence } = md.renderer.rules

if (opts.unicode === 'twemoji') {
const wrap = text =>
text
.split(/(<[^>]*>)/g)
.reduce(
(ret, part, idx) =>
`${ret}${
idx % 2
? part
: part.replace(regexForSplit, ([emoji]) =>
twemojiParse(emoji)
)
}`,
''
)
md[marpEnabledSymbol]
? text
.split(/(<[^>]*>)/g)
.reduce(
(ret, part, idx) =>
`${ret}${
idx % 2
? part
: part.replace(regexForSplit, ([emoji]) =>
twemojiParse(emoji)
)
}`,
''
)
: text

md.renderer.rules.unicode_emoji = twemojiRenderer
md.renderer.rules.marp_unicode_emoji = twemojiRenderer

md.renderer.rules.code_inline = (...args) => wrap(code_inline(...args))
md.renderer.rules.code_block = (...args) => wrap(code_block(...args))
Expand Down
32 changes: 17 additions & 15 deletions src/fitting/fitting.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Token from 'markdown-it/lib/token'
import fittingCSS from './fitting.scss'
import { Marp } from '../marp'
import { Marp, marpEnabledSymbol } from '../marp'

export const css = fittingCSS
export const attr = 'data-marp-fitting'
Expand All @@ -26,8 +26,9 @@ function fittingCode(md, marp: Marp, themeResolver: ThemeResolver): void {

const replacedRenderer = func => (...args) => {
const rendered: string = func(...args)
const { fittingCode } = marp.themeSet.getThemeProp(themeResolver()!, 'meta')
if (!md[marpEnabledSymbol]) return rendered

const { fittingCode } = marp.themeSet.getThemeProp(themeResolver()!, 'meta')
if (fittingCode === 'false') return rendered

return rendered.replace(codeMatcher, (_, start, content, end) => {
Expand All @@ -48,7 +49,7 @@ function fittingCode(md, marp: Marp, themeResolver: ThemeResolver): void {
}

// Detect `<!-- fit -->` comment keyword in headings.
function fittingHeader(md): void {
function fittingHeader(md, marp: Marp): void {
md.core.ruler.after('inline', 'marp_fitting_header', state => {
let target = undefined

Expand Down Expand Up @@ -76,14 +77,23 @@ function fittingHeader(md): void {
}
}
})

if (marp.options.inlineSVG) {
Object.assign(md.renderer.rules, {
marp_fitting_open: () =>
`<svg ${attr}="svg"><foreignObject><span ${svgContentAttr}>`,
marp_fitting_close: () => '</span></foreignObject></svg>',
})
}
}

function fittingMathBlock(md, marp: Marp): void {
const { math_block } = md.renderer.rules
if (!math_block) return
const { marp_math_block } = md.renderer.rules
if (!marp_math_block) return

const replacedRenderer = func => (...args) => {
const rendered: string = func(...args)
if (!md[marpEnabledSymbol]) return rendered

// Rendered math block is wrapped by `<p>` tag in math plugin
const katex = rendered.slice(3, -4)
Expand All @@ -99,19 +109,11 @@ function fittingMathBlock(md, marp: Marp): void {
return `<p><span ${attr}="plain">${katex}</span></p>`
}

md.renderer.rules.math_block = replacedRenderer(math_block)
md.renderer.rules.marp_math_block = replacedRenderer(marp_math_block)
}

export function markdown(md, marp: Marp, themeResolver: ThemeResolver): void {
md.use(fittingHeader)
md.use(fittingHeader, marp)
md.use(fittingCode, marp, themeResolver)
md.use(fittingMathBlock, marp)

if (marp.options.inlineSVG) {
Object.assign(md.renderer.rules, {
marp_fitting_open: () =>
`<svg ${attr}="svg"><foreignObject><span ${svgContentAttr}>`,
marp_fitting_close: () => '</span></foreignObject></svg>',
})
}
}
9 changes: 6 additions & 3 deletions src/html/html.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { FilterXSS } from 'xss'
import { MarpOptions } from '../marp'
import { MarpOptions, marpEnabledSymbol } from '../marp'

export function markdown(md, opts: MarpOptions['html']): void {
if (typeof opts === 'object') {
const { html_inline, html_block } = md.renderer.rules
const filter = new FilterXSS({ whiteList: opts })

const sanitizedRenderer = original => (...args) =>
filter.process(original(...args))
const sanitizedRenderer = (original: Function) => (...args) => {
const ret = original(...args)

return md[marpEnabledSymbol] ? filter.process(ret) : ret
}

md.renderer.rules.html_inline = sanitizedRenderer(html_inline)
md.renderer.rules.html_block = sanitizedRenderer(html_block)
Expand Down
57 changes: 40 additions & 17 deletions src/marp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import defaultTheme from '../themes/default.scss'
import gaiaTheme from '../themes/gaia.scss'
import uncoverTheme from '../themes/uncover.scss'

const marpObservedSymbol = Symbol('marpObserved')

export interface MarpOptions extends MarpitOptions {
emoji?: emojiPlugin.EmojiOptions
html?: boolean | { [tag: string]: string[] }
Expand All @@ -24,8 +22,12 @@ export interface MarpOptions extends MarpitOptions {
}
}

const marpObservedSymbol = Symbol('marpObserved')

export const marpEnabledSymbol = Symbol('marpEnabled')

export class Marp extends Marpit {
readonly options!: MarpOptions
readonly options!: Required<MarpOptions>

private renderedMath: boolean = false

Expand All @@ -45,9 +47,9 @@ export class Marp extends Marpit {
{
breaks: true,
linkify: true,
...(typeof opts.markdown === 'object' ? opts.markdown : {}),
highlight: (code: string, lang: string) =>
this.highlighter(code, lang),
...(typeof opts.markdown === 'object' ? opts.markdown : {}),
html: !!(opts.html !== undefined ? opts.html : Marp.html),
},
],
Expand All @@ -73,11 +75,18 @@ export class Marp extends Marpit {

const { emoji, html, math } = this.options

const useMarpitPlugin = (() => {
const tmp = new Marpit()
tmp.markdown = md

return tmp.use.bind(tmp)
})()

// HTML sanitizer
md.use(htmlPlugin.markdown, html)
useMarpitPlugin(htmlPlugin.markdown, html)

// Emoji support
md.use(emojiPlugin.markdown, emoji)
useMarpitPlugin(emojiPlugin.markdown, emoji)

// Math typesetting
if (math) {
Expand All @@ -86,14 +95,30 @@ export class Marp extends Marpit {
? math.katexOption
: {}

md.use(mathPlugin.markdown, opts, flag => (this.renderedMath = flag))
useMarpitPlugin(
mathPlugin.markdown,
opts,
flag => (this.renderedMath = flag)
)
}

// Fitting
const themeResolver: fittingPlugin.ThemeResolver = () =>
(this.lastGlobalDirectives || {}).theme

md.use(fittingPlugin.markdown, this, themeResolver)
useMarpitPlugin(
fittingPlugin.markdown,
this,
() => (this.lastGlobalDirectives || {}).theme
)

// Track usage of Marpit features (for renderer)
md.core.ruler.push('marp_enabled', () => (md[marpEnabledSymbol] = false))

useMarpitPlugin(() =>
md.core.ruler.after(
'marp_enabled',
'marp_enabled_tracker',
() => (md[marpEnabledSymbol] = true)
)
)
}

highlighter(code: string, lang: string): string {
Expand All @@ -107,13 +132,11 @@ export class Marp extends Marpit {

protected themeSetPackOptions(): ThemeSetPackOptions {
const base = { ...super.themeSetPackOptions() }
const prependCSS = css => {
if (css) base.before = `${css}\n${base.before || ''}`
}
const prepend = css => css && (base.before = `${css}\n${base.before || ''}`)
const { emoji, math } = this.options

prependCSS(emojiPlugin.css(emoji!))
prependCSS(fittingPlugin.css)
prepend(emojiPlugin.css(emoji!))
prepend(fittingPlugin.css)

if (math && this.renderedMath) {
// By default, we use KaTeX web fonts through CDN.
Expand All @@ -126,7 +149,7 @@ export class Marp extends Marpit {
}

// Add KaTeX css
prependCSS(mathPlugin.css(path))
prepend(mathPlugin.css(path))
}

return base
Expand Down
8 changes: 4 additions & 4 deletions src/math/math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function markdown(
return false
})

md.renderer.rules.math_inline = (tokens, idx) => {
md.renderer.rules.marp_math_inline = (tokens, idx) => {
const { content } = tokens[idx]

try {
Expand All @@ -64,7 +64,7 @@ export function markdown(
}
)

md.renderer.rules.math_block = (tokens, idx) => {
md.renderer.rules.marp_math_block = (tokens, idx) => {
const { content } = tokens[idx]

try {
Expand Down Expand Up @@ -137,7 +137,7 @@ function parseInlineMath(state, silent) {
}

return found(() => {
const token = state.push('math_inline', 'math', 0)
const token = state.push('marp_math_inline', 'math', 0)
token.markup = '$'
token.content = src.slice(start, match)
}, match + 1)
Expand Down Expand Up @@ -178,7 +178,7 @@ function parseMathBlock(state, start, end, silent) {

state.line = next + 1

const token = state.push('math_block', 'math', 0)
const token = state.push('marp_math_block', 'math', 0)
token.block = true
token.content = ''
token.map = [start, state.line]
Expand Down
Loading

0 comments on commit 6a6b7df

Please sign in to comment.