@marp-team/marpit
Advanced tools
Comparing version 0.0.4 to 0.0.5
@@ -5,2 +5,8 @@ # Change Log | ||
## v0.0.5 - 2018-05-12 | ||
* Add `paginate` local directive ([#17](https://github.com/marp-team/marpit/pull/17)) | ||
* Make Unicode emoji printable ([#18](https://github.com/marp-team/marpit/pull/18)) | ||
* Prevent style injections ([#19](https://github.com/marp-team/marpit/pull/19)) | ||
## v0.0.4 - 2018-05-05 | ||
@@ -7,0 +13,0 @@ |
@@ -7,6 +7,2 @@ 'use strict'; | ||
var _split = require('../helpers/split'); | ||
var _split2 = _interopRequireDefault(_split); | ||
var _wrap_tokens = require('../helpers/wrap_tokens'); | ||
@@ -18,3 +14,2 @@ | ||
/** @module */ | ||
const bgSizeKeywords = { | ||
@@ -42,3 +37,4 @@ auto: 'auto', | ||
*/ | ||
};function backgroundImage(md) { | ||
}; /** @module */ | ||
function backgroundImage(md) { | ||
md.inline.ruler2.after('marpit_parse_image', 'marpit_background_image', ({ tokens }) => { | ||
@@ -125,26 +121,22 @@ tokens.forEach(t => { | ||
md.core.ruler.after('marpit_directives_apply', 'marpit_advanced_background', state => { | ||
state.tokens = (0, _split2.default)(state.tokens, t => t.type === 'marpit_inline_svg_content_open' && t.meta && t.meta.marpitBackground, true).reduce((arr, tokens) => { | ||
const [foreignObject] = tokens; | ||
let advancedBgs = []; | ||
let current; | ||
if (foreignObject.type === 'marpit_inline_svg_content_open') { | ||
const { | ||
height, | ||
images, | ||
open, | ||
width | ||
} = foreignObject.meta.marpitBackground; | ||
state.tokens = state.tokens.reduce((ret, t) => { | ||
let tokens = [t]; | ||
if (t.type === 'marpit_inline_svg_content_open' && t.meta && t.meta.marpitBackground) { | ||
current = t; | ||
const { height, images, open, width } = t.meta.marpitBackground; | ||
open.attrSet('data-marpit-advanced-background', 'content'); | ||
const splitSide = foreignObject.meta.marpitBackground.split; | ||
const splitSide = t.meta.marpitBackground.split; | ||
if (splitSide) { | ||
open.attrSet('data-marpit-advanced-background-split', splitSide); | ||
foreignObject.attrSet('width', '50%'); | ||
t.attrSet('width', '50%'); | ||
if (splitSide === 'left') foreignObject.attrSet('x', '50%'); | ||
if (splitSide === 'left') t.attrSet('x', '50%'); | ||
} | ||
advancedBgs = (0, _wrap_tokens2.default)('marpit_advanced_background_foreign_object', { tag: 'foreignObject', width, height }, (0, _wrap_tokens2.default)('marpit_advanced_background_section', Object.assign({}, open.attrs.reduce((o, [k, v]) => Object.assign({}, o, { [k]: v }), {}), { | ||
tokens = [...(0, _wrap_tokens2.default)('marpit_advanced_background_foreign_object', { tag: 'foreignObject', width, height }, (0, _wrap_tokens2.default)('marpit_advanced_background_section', Object.assign({}, open.attrs.reduce((o, [k, v]) => Object.assign({}, o, { [k]: v }), {}), { | ||
tag: 'section', | ||
@@ -159,6 +151,25 @@ id: undefined, | ||
style: [`background-image:url("${img.url}");`, img.size && `background-size:${img.size};`, img.filter && `filter:${img.filter};`].filter(s => s).join('') | ||
})], [])))); | ||
})], [])))), t]; | ||
} else if (current && t.type === 'marpit_inline_svg_content_close') { | ||
const { open } = current.meta.marpitBackground; | ||
const marpitPagination = open.attrGet('data-marpit-pagination'); | ||
if (marpitPagination) { | ||
const { height, width } = current.meta.marpitBackground; | ||
tokens = [t, ...(0, _wrap_tokens2.default)('marpit_advanced_background_foreign_object', { | ||
tag: 'foreignObject', | ||
width, | ||
height, | ||
'data-marpit-advanced-background': 'pagination' | ||
}, (0, _wrap_tokens2.default)('marpit_advanced_pagination_section', { | ||
tag: 'section', | ||
'data-marpit-advanced-background': 'pagination', | ||
'data-marpit-pagination': marpitPagination | ||
}))]; | ||
} | ||
current = undefined; | ||
} | ||
return [...arr, ...advancedBgs, ...tokens]; | ||
return [...ret, ...tokens]; | ||
}, []); | ||
@@ -165,0 +176,0 @@ }); |
@@ -13,5 +13,8 @@ 'use strict'; | ||
var _inline_style = require('../../helpers/inline_style'); | ||
var _inline_style2 = _interopRequireDefault(_inline_style); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** @module */ | ||
const publicDirectives = [...Object.keys(_directives.globals), ...Object.keys(_directives.locals)]; | ||
@@ -33,2 +36,3 @@ | ||
*/ | ||
/** @module */ | ||
function apply(md, opts = {}) { | ||
@@ -44,6 +48,6 @@ const dataset = opts.dataset === undefined ? true : !!opts.dataset; | ||
state.tokens.forEach(token => { | ||
const { marpitDirectives } = token.meta || {}; | ||
const { marpitDirectives, marpitSlide } = token.meta || {}; | ||
if (!marpitDirectives) return; | ||
const styles = {}; | ||
const style = new _inline_style2.default(token.attrGet('style')); | ||
@@ -56,3 +60,3 @@ Object.keys(marpitDirectives).filter(filterFunc).forEach(dir => { | ||
if (dataset) token.attrSet(`data-${kebabCaseDir}`, value); | ||
if (css) styles[`--${kebabCaseDir}`] = value; | ||
if (css) style.set(`--${kebabCaseDir}`, value); | ||
}); | ||
@@ -64,16 +68,15 @@ | ||
if (marpitDirectives.backgroundImage) { | ||
styles['background-image'] = marpitDirectives.backgroundImage; | ||
styles['background-position'] = 'center'; | ||
styles['background-repeat'] = 'no-repeat'; | ||
styles['background-size'] = 'cover'; | ||
style.set('background-image', marpitDirectives.backgroundImage).set('background-position', 'center').set('background-repeat', 'no-repeat').set('background-size', 'cover'); | ||
if (marpitDirectives.backgroundPosition) styles['background-position'] = marpitDirectives.backgroundPosition; | ||
if (marpitDirectives.backgroundPosition) style.set('background-position', marpitDirectives.backgroundPosition); | ||
if (marpitDirectives.backgroundRepeat) styles['background-repeat'] = marpitDirectives.backgroundRepeat; | ||
if (marpitDirectives.backgroundRepeat) style.set('background-repeat', marpitDirectives.backgroundRepeat); | ||
if (marpitDirectives.backgroundSize) styles['background-size'] = marpitDirectives.backgroundSize; | ||
if (marpitDirectives.backgroundSize) style.set('background-size', marpitDirectives.backgroundSize); | ||
} | ||
const styleStr = Object.keys(styles).reduce((arr, dir) => `${arr}${dir}:${styles[dir]};`, ''); | ||
if (styleStr.length > 0) token.attrSet('style', styleStr); | ||
if (marpitDirectives.paginate) token.attrSet('data-marpit-pagination', marpitSlide + 1); | ||
const styleStr = style.toString(); | ||
if (styleStr !== '') token.attrSet('style', styleStr); | ||
}); | ||
@@ -80,0 +83,0 @@ }); |
@@ -1,2 +0,2 @@ | ||
"use strict"; | ||
'use strict'; | ||
@@ -45,3 +45,2 @@ Object.defineProperty(exports, "__esModule", { | ||
* | ||
* @prop {Directive} class Specify HTML class of section element(s). | ||
* @prop {Directive} backgroundImage Specify background-image style. | ||
@@ -54,2 +53,4 @@ * @prop {Directive} backgroundPosition Specify background-position style. The | ||
* value while setting backgroundImage is `cover`. | ||
* @prop {Directive} class Specify HTML class of section element(s). | ||
* @prop {Directive} pagination Show page number on the slide if you set `true`. | ||
*/ | ||
@@ -71,2 +72,5 @@ const locals = exports.locals = { | ||
return { class: value }; | ||
}, | ||
paginate(value) { | ||
return { paginate: (value || '').toLowerCase() === 'true' }; | ||
} | ||
@@ -73,0 +77,0 @@ }; |
@@ -6,5 +6,11 @@ 'use strict'; | ||
}); | ||
/** @module */ | ||
const escapeStyle = target => target.replace(/[\\;:()]/g, matched => `\\${matched[0]}`); | ||
var _inline_style = require('../helpers/inline_style'); | ||
var _inline_style2 = _interopRequireDefault(_inline_style); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const escape = target => target.replace(/[\\;:()]/g, matched => `\\${matched[0].codePointAt(0).toString(16)} `); | ||
/** | ||
@@ -22,2 +28,3 @@ * Marpit parse image plugin. | ||
*/ | ||
/** @module */ | ||
function parseImage(md, opts = {}) { | ||
@@ -35,9 +42,9 @@ const pluginOptions = Object.assign({ filters: true }, opts); | ||
optionMatchers.set(/^blur(?::(.+))?$/, (matches, meta) => ({ | ||
filters: [...meta.filters, ['blur', escapeStyle(matches[1] || '10px')]] | ||
filters: [...meta.filters, ['blur', escape(matches[1] || '10px')]] | ||
})); | ||
optionMatchers.set(/^brightness(?::(.+))?$/, (matches, meta) => ({ | ||
filters: [...meta.filters, ['brightness', escapeStyle(matches[1] || '1.5')]] | ||
filters: [...meta.filters, ['brightness', escape(matches[1] || '1.5')]] | ||
})); | ||
optionMatchers.set(/^contrast(?::(.+))?$/, (matches, meta) => ({ | ||
filters: [...meta.filters, ['contrast', escapeStyle(matches[1] || '2')]] | ||
filters: [...meta.filters, ['contrast', escape(matches[1] || '2')]] | ||
})); | ||
@@ -48,3 +55,3 @@ optionMatchers.set(/^drop-shadow(?::(.+?),(.+?)(?:,(.+?))?(?:,(.+?))?)?$/, (matches, meta) => { | ||
return colorFunc ? `${colorFunc[1]}(${escapeStyle(colorFunc[2])})` : escapeStyle(arg); | ||
return colorFunc ? `${colorFunc[1]}(${escape(colorFunc[2])})` : escape(arg); | ||
}); | ||
@@ -57,18 +64,18 @@ | ||
optionMatchers.set(/^grayscale(?::(.+))?$/, (matches, meta) => ({ | ||
filters: [...meta.filters, ['grayscale', escapeStyle(matches[1] || '1')]] | ||
filters: [...meta.filters, ['grayscale', escape(matches[1] || '1')]] | ||
})); | ||
optionMatchers.set(/^hue-rotate(?::(.+))?$/, (matches, meta) => ({ | ||
filters: [...meta.filters, ['hue-rotate', escapeStyle(matches[1] || '180deg')]] | ||
filters: [...meta.filters, ['hue-rotate', escape(matches[1] || '180deg')]] | ||
})); | ||
optionMatchers.set(/^invert(?::(.+))?$/, (matches, meta) => ({ | ||
filters: [...meta.filters, ['invert', escapeStyle(matches[1] || '1')]] | ||
filters: [...meta.filters, ['invert', escape(matches[1] || '1')]] | ||
})); | ||
optionMatchers.set(/^opacity(?::(.+))?$/, (matches, meta) => ({ | ||
filters: [...meta.filters, ['opacity', escapeStyle(matches[1] || '.5')]] | ||
filters: [...meta.filters, ['opacity', escape(matches[1] || '.5')]] | ||
})); | ||
optionMatchers.set(/^saturate(?::(.+))?$/, (matches, meta) => ({ | ||
filters: [...meta.filters, ['saturate', escapeStyle(matches[1] || '2')]] | ||
filters: [...meta.filters, ['saturate', escape(matches[1] || '2')]] | ||
})); | ||
optionMatchers.set(/^sepia(?::(.+))?$/, (matches, meta) => ({ | ||
filters: [...meta.filters, ['sepia', escapeStyle(matches[1] || '1')]] | ||
filters: [...meta.filters, ['sepia', escape(matches[1] || '1')]] | ||
})); | ||
@@ -102,3 +109,5 @@ } | ||
token.attrJoin('style', `filter:${token.meta.marpitImage.filter};`); | ||
const style = new _inline_style2.default(token.attrGet('style')).set('filter', token.meta.marpitImage.filter); | ||
token.attrSet('style', style.toString()); | ||
} | ||
@@ -105,0 +114,0 @@ } |
@@ -61,2 +61,6 @@ 'use strict'; | ||
var _unicode_emoji = require('./markdown/unicode_emoji'); | ||
var _unicode_emoji2 = _interopRequireDefault(_unicode_emoji); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -133,3 +137,3 @@ | ||
applyMarkdownItPlugins(md = this.markdown) { | ||
md.use(_comment2.default).use(_slide2.default).use(_parse2.default, this).use(_apply2.default).use(_slide_container2.default, this.slideContainers).use(_container2.default, this.containers).use(_parse_image2.default, { filters: this.options.filters }).use(_sweep2.default).use(_inline_svg2.default, this); | ||
md.use(_comment2.default).use(_slide2.default).use(_parse2.default, this).use(_apply2.default).use(_slide_container2.default, this.slideContainers).use(_container2.default, this.containers).use(_parse_image2.default, { filters: this.options.filters }).use(_unicode_emoji2.default).use(_sweep2.default).use(_inline_svg2.default, this); | ||
@@ -136,0 +140,0 @@ if (this.options.backgroundSyntax) md.use(_background_image2.default); |
@@ -26,2 +26,7 @@ 'use strict'; | ||
section[data-marpit-advanced-background="background"]::after, | ||
section[data-marpit-advanced-background="content"]::after { | ||
display: none !important; | ||
} | ||
section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container] { | ||
@@ -53,6 +58,12 @@ all: initial; | ||
section[data-marpit-advanced-background="content"] { | ||
section[data-marpit-advanced-background="content"], | ||
section[data-marpit-advanced-background="pagination"] { | ||
background: transparent !important; | ||
} | ||
section[data-marpit-advanced-background="pagination"], | ||
:marpit-container > svg > foreignObject[data-marpit-advanced-background="pagination"] { | ||
pointer-events: none !important; | ||
} | ||
section[data-marpit-advanced-background-split] { | ||
@@ -59,0 +70,0 @@ width: 100%; |
@@ -49,2 +49,6 @@ 'use strict'; | ||
} | ||
[data-marpit-emoji] { | ||
filter: invert(0); | ||
} | ||
} | ||
@@ -51,0 +55,0 @@ `.trim())); /** @module */ |
@@ -19,2 +19,6 @@ 'use strict'; | ||
var _pagination = require('./postcss/pagination'); | ||
var _pagination2 = _interopRequireDefault(_pagination); | ||
var _printable = require('./postcss/printable'); | ||
@@ -188,3 +192,3 @@ | ||
height: this.getThemeProp(theme, 'height') | ||
}), theme !== _scaffold2.default && (css => css.first.before(_scaffold2.default.css)), opts.inlineSVG && _advanced_background2.default, _prepend2.default, (0, _replace2.default)(opts.containers, slideElements), opts.inlineSVG === 'workaround' && _inline_svg_workaround2.default].filter(p => p)); | ||
}), theme !== _scaffold2.default && (css => css.first.before(_scaffold2.default.css)), opts.inlineSVG && _advanced_background2.default, _pagination2.default, _prepend2.default, (0, _replace2.default)(opts.containers, slideElements), opts.inlineSVG === 'workaround' && _inline_svg_workaround2.default].filter(p => p)); | ||
@@ -191,0 +195,0 @@ return packer.process(theme.css).css; |
@@ -13,2 +13,5 @@ 'use strict'; | ||
const emojiFonts = ['Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', 'Segoe UI Symbol', 'Android Emoji', 'Twitter Color Emoji', 'EmojiOne Color', 'Symbola', 'EmojiSymbols']; /** @module */ | ||
const css = ` | ||
@@ -21,2 +24,3 @@ section { | ||
overflow: hidden; | ||
position: relative; | ||
@@ -26,2 +30,15 @@ scroll-snap-align: center center; | ||
section::after { | ||
bottom: 0; | ||
content: attr(data-marpit-pagination); | ||
padding: inherit; | ||
pointer-events: none; | ||
position: absolute; | ||
right: 0; | ||
} | ||
[data-marpit-emoji] { | ||
font-family: ${emojiFonts.map(f => `'${f}'`).join(',')}; | ||
} | ||
/* Normalization */ | ||
@@ -39,2 +56,3 @@ h1 { | ||
* - Set default style for `<section>`. | ||
* - Set unicode emoji style for using system emoji fonts. | ||
* - Normalize `<h1>` heading style. | ||
@@ -45,3 +63,2 @@ * | ||
*/ | ||
/** @module */ | ||
const scaffoldTheme = _theme2.default.fromCSS(css, false); | ||
@@ -48,0 +65,0 @@ |
{ | ||
"name": "@marp-team/marpit", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "The skinny framework for creating slide deck from Markdown", | ||
@@ -45,3 +45,4 @@ "license": "MIT", | ||
"test:coverage": "cross-env NODE_ENV=test nyc mocha", | ||
"version": "bash version.sh" | ||
"version": "bash version.sh", | ||
"watch": "babel src --out-dir lib -w" | ||
}, | ||
@@ -56,6 +57,6 @@ "devDependencies": { | ||
"babel-plugin-transform-object-rest-spread": "^6.26.0", | ||
"babel-preset-env": "^1.6.1", | ||
"babel-preset-env": "^1.7.0", | ||
"cheerio": "^1.0.0-rc.2", | ||
"coveralls": "^3.0.0", | ||
"cross-env": "^5.1.4", | ||
"coveralls": "^3.0.1", | ||
"cross-env": "^5.1.5", | ||
"dedent": "^0.7.0", | ||
@@ -70,4 +71,4 @@ "eslint": "^4.19.1", | ||
"mocha": "^5.1.1", | ||
"npm-run-all": "^4.1.2", | ||
"nyc": "^11.7.1", | ||
"npm-run-all": "^4.1.3", | ||
"nyc": "^11.7.3", | ||
"power-assert": "^1.5.0", | ||
@@ -78,2 +79,3 @@ "prettier": "^1.12.1", | ||
"dependencies": { | ||
"emoji-regex": "^6.5.1", | ||
"js-yaml": "^3.11.0", | ||
@@ -80,0 +82,0 @@ "lodash.kebabcase": "^4.1.1", |
@@ -40,3 +40,3 @@ <div align="center"> | ||
* Removed directives about slide size. Use `width` / `height` declaration of theme CSS. | ||
* Removed directives about slide size. [Use `width` / `height` declaration of theme CSS.](#slide-size) | ||
* Parse directives by YAML parser. ([js-yaml](https://github.com/nodeca/js-yaml) + [`FAILSAFE_SCHEMA`](http://www.yaml.org/spec/1.2/spec.html#id2802346)) | ||
@@ -48,2 +48,28 @@ * Support [Jekyll style front-matter](https://jekyllrb.com/docs/frontmatter/). | ||
#### Pagination | ||
We support a pagination by the `paginate` local directive. It is same as [the `page_number` directive in pre-released Marp](https://github.com/yhatt/marp/blob/master/example.md#page_number). | ||
``` | ||
<!-- paginate: true --> | ||
You would be able to see a page number of slide in the lower right. | ||
``` | ||
##### Skip pagination on title slide | ||
Simply you have to move a definition of `paginate` directive to an inside of a second page. | ||
```markdown | ||
# Title slide | ||
(This page will not paginate by lack of `paginate` local directive) | ||
--- | ||
<!-- paginate: true --> | ||
It will paginate slide from a this page. | ||
``` | ||
### Slide backgrounds | ||
@@ -187,3 +213,2 @@ | ||
* [ ] Header and footer directive | ||
* [ ] Slide page number | ||
@@ -232,2 +257,3 @@ ## Markup | ||
font-size: 40px; | ||
padding: 40px; | ||
} | ||
@@ -240,2 +266,40 @@ | ||
#### The root `section` selector | ||
In Marpit theme CSS, the root `section` selector means like a viewport of each slide. | ||
##### Slide size | ||
`width` and `height` declaration in `section` selector can specify a slide size. (1280x720 pixels by default) | ||
The specified size is not only used in the section element size but also used in the size of each page of printed PDF. | ||
For example, try these declarations in your theme CSS if you want a classic 4:3 slide: | ||
```css | ||
section { | ||
width: 960px; | ||
height: 720px; | ||
} | ||
``` | ||
Please notice _these must define a length in **an absolute unit.**_ We support `cm`, `in`, `mm`, `pc`, `pt`, and `px`. | ||
##### Styling paginations | ||
You can style the page number through `section::after` pseudo-element. (It is shown by `paginate` local directive) | ||
```css | ||
section::after { | ||
font-weight: bold; | ||
text-shadow: 1px 1px 0 #fff; | ||
} | ||
``` | ||
Please refer to [the default style of `section::after` in a scaffold theme](src/theme/scaffold.js) as well. | ||
> :information_source: The root `section::after` has preserved a content of page number from Marpit. At present, you cannot use the root `section::after` selector for other use. | ||
#### Theme set | ||
The `Marpit` instance has a `themeSet` member that manages usable themes in the `theme` directive of Marpit Markdown. You have to add theme CSS by using `themeSet.add(string)`. | ||
@@ -242,0 +306,0 @@ |
84923
34
1724
355
6
+ Addedemoji-regex@^6.5.1
+ Addedemoji-regex@6.5.1(transitive)