@marp-team/marpit
Advanced tools
Comparing version 2.1.2 to 2.2.0
@@ -16,3 +16,3 @@ declare namespace MarpitEnv { | ||
slideContainer?: false | Element | Element[] | ||
inlineSVG?: boolean | ||
inlineSVG?: boolean | InlineSVGOptions | ||
} | ||
@@ -22,2 +22,7 @@ | ||
type InlineSVGOptions = { | ||
enabled?: boolean | ||
backdropSelector?: boolean | ||
} | ||
type RenderResult<T = string> = { | ||
@@ -24,0 +29,0 @@ html: T |
@@ -25,7 +25,7 @@ "use strict"; | ||
* | ||
* When Marpit `inlineSVG` option is `false`, the image will convert to | ||
* When Marpit inline SVG mode is disabled, the image will convert to | ||
* `backgroundImage` and `backgroundSize` spot directive. It supports only | ||
* single background and resizing by using CSS. | ||
* | ||
* When `inlineSVG` option is true, the plugin enables advanced background mode. | ||
* When inline SVG mode is enabled, the plugin enables advanced background mode. | ||
* In addition to the basic background implementation, it supports multiple | ||
@@ -32,0 +32,0 @@ * background images, filters, and split background. |
@@ -42,3 +42,3 @@ "use strict"; | ||
if (t.meta.marpitImage.options.includes('bg')) { | ||
if (marpitImage.options.some(v => !v.consumed && v.content === 'bg')) { | ||
marpitImage.background = true; | ||
@@ -48,7 +48,15 @@ t.hidden = true; | ||
for (const opt of marpitImage.options) { | ||
// Background size keyword | ||
if (bgSizeKeywords[opt]) marpitImage.backgroundSize = bgSizeKeywords[opt]; // Split background keyword | ||
if (opt.consumed) continue; | ||
let consumed = false; // bg keyword | ||
const matched = opt.match(splitSizeMatcher); | ||
if (opt.content === 'bg') consumed = true; // Background size keyword | ||
if (bgSizeKeywords[opt.content]) { | ||
marpitImage.backgroundSize = bgSizeKeywords[opt.content]; | ||
consumed = true; | ||
} // Split background keyword | ||
const matched = opt.content.match(splitSizeMatcher); | ||
if (matched) { | ||
@@ -58,6 +66,12 @@ const [, splitSide, splitSize] = matched; | ||
marpitImage.backgroundSplitSize = splitSize; | ||
consumed = true; | ||
} // Background aligned direction | ||
if (opt === 'vertical' || opt === 'horizontal') marpitImage.backgroundDirection = opt; | ||
if (opt.content === 'vertical' || opt.content === 'horizontal') { | ||
marpitImage.backgroundDirection = opt.content; | ||
consumed = true; | ||
} | ||
if (consumed) opt.consumed = true; | ||
} | ||
@@ -64,0 +78,0 @@ } |
@@ -51,3 +51,3 @@ "use strict"; | ||
if (arg) { | ||
const colorFunc = arg.match(/^(rgba?|hsla?)\((.*)\)$/); | ||
const colorFunc = arg.match(/^(rgba?|hsla?|hwb|(?:ok)?(?:lab|lch)|color)\((.*)\)$/); | ||
args.push(colorFunc ? `${colorFunc[1]}(${escape(colorFunc[2])})` : escape(arg)); | ||
@@ -99,9 +99,31 @@ } | ||
const finalizeTokenAttr = token => { | ||
const finalizeTokenAttr = (token, state) => { | ||
// Convert imprimitive attribute value into primitive string | ||
if (token.attrs && Array.isArray(token.attrs)) token.attrs = token.attrs.map(([name, value]) => [name, value.toString()]); | ||
if (token.attrs && Array.isArray(token.attrs)) { | ||
token.attrs = token.attrs.map(([name, value]) => [name, value.toString()]); | ||
} // Apply finalization recursively to inline tokens | ||
if (token.type === 'inline') { | ||
// Apply finalization recursively to inline tokens | ||
for (const t of token.children) finalizeTokenAttr(t); | ||
for (const t of token.children) finalizeTokenAttr(t, state); | ||
} // Re-generate the alt text of image token to remove Marpit specific options | ||
if (token.type === 'image' && token.meta && token.meta.marpitImage) { | ||
let updatedAlt = ''; | ||
let hasConsumed = false; | ||
for (const opt of token.meta.marpitImage.options) { | ||
if (opt.consumed) { | ||
hasConsumed = true; | ||
} else { | ||
updatedAlt += opt.leading + opt.content; | ||
} | ||
} | ||
if (hasConsumed) { | ||
let newTokens = []; | ||
md.inline.parse(updatedAlt.trimLeft(), state.md, state.env, newTokens); | ||
token.children = newTokens; | ||
} | ||
} | ||
@@ -132,3 +154,3 @@ }; | ||
// Apply finalization for every tokens | ||
for (const token of state.tokens) finalizeTokenAttr(token); | ||
for (const token of state.tokens) finalizeTokenAttr(token, state); | ||
} | ||
@@ -143,3 +165,23 @@ } | ||
if (token.type === 'image') { | ||
const options = token.content.split(/\s+/).filter(s => s.length > 0); | ||
// Parse alt text as options | ||
const optsBase = token.content.split(/(\s+)/); | ||
let currentIdx = 0; | ||
let leading = ''; | ||
const options = optsBase.reduce((acc, opt, i) => { | ||
if (i % 2 === 0 && opt.length > 0) { | ||
currentIdx += leading.length; | ||
acc.push({ | ||
content: opt, | ||
index: currentIdx, | ||
leading, | ||
consumed: false | ||
}); | ||
leading = ''; | ||
currentIdx += opt.length; | ||
} else { | ||
leading += opt; | ||
} | ||
return acc; | ||
}, []); | ||
const url = token.attrGet('src'); | ||
@@ -161,6 +203,11 @@ const originalUrl = originalURLMap.has(url) ? originalURLMap.get(url) : url; | ||
for (const [regexp, mergeFunc] of optionMatchers) { | ||
const matched = opt.match(regexp); | ||
if (matched) token.meta.marpitImage = _objectSpread(_objectSpread({}, token.meta.marpitImage), mergeFunc(matched, _objectSpread({ | ||
filters: [] | ||
}, token.meta.marpitImage))); | ||
if (opt.consumed) continue; | ||
const matched = opt.content.match(regexp); | ||
if (matched) { | ||
opt.consumed = true; | ||
token.meta.marpitImage = _objectSpread(_objectSpread({}, token.meta.marpitImage), mergeFunc(matched, _objectSpread({ | ||
filters: [] | ||
}, token.meta.marpitImage))); | ||
} | ||
} | ||
@@ -167,0 +214,0 @@ } |
@@ -29,3 +29,3 @@ "use strict"; | ||
md.core.ruler.after('marpit_directives_parse', 'marpit_inline_svg', state => { | ||
if (!marpit.options.inlineSVG || state.inlineMode) return; | ||
if (!(marpit.inlineSVGOptions && marpit.inlineSVGOptions.enabled) || state.inlineMode) return; | ||
const { | ||
@@ -32,0 +32,0 @@ themeSet, |
@@ -79,2 +79,6 @@ "use strict"; | ||
}; | ||
const defaultInlineSVGOptions = { | ||
enabled: true, | ||
backdropSelector: true | ||
}; | ||
/** | ||
@@ -88,2 +92,10 @@ * Parse Marpit Markdown and render to the slide HTML/CSS. | ||
/** | ||
* @typedef {Object} Marpit~InlineSVGOptions | ||
* @property {boolean} [enabled=true] Whether inline SVG mode is enabled. | ||
* @property {boolean} [backdropSelector=true] Whether `::backdrop` selector | ||
* support is enabled. If enabled, the `::backdrop` CSS selector will | ||
* match to the SVG container element. | ||
*/ | ||
/** | ||
* Create a Marpit instance. | ||
@@ -107,4 +119,4 @@ * | ||
* wrapping each slide sections. | ||
* @param {boolean} [opts.inlineSVG=false] Wrap each sections by inline SVG. | ||
* _(Experimental)_ | ||
* @param {boolean|Marpit~InlineSVGOptions} [opts.inlineSVG=false] Wrap each | ||
* slide sections by inline SVG. _(Experimental)_ | ||
*/ | ||
@@ -263,3 +275,3 @@ constructor(opts = {}) { | ||
containers: [...(0, _wrap_array.default)(this.options.container), ...(0, _wrap_array.default)(this.options.slideContainer)], | ||
inlineSVG: this.options.inlineSVG, | ||
inlineSVG: this.inlineSVGOptions, | ||
printable: this.options.printable | ||
@@ -269,2 +281,17 @@ }; | ||
/** | ||
* @private | ||
* @returns {Marpit~InlineSVGOptions} Options for inline SVG. | ||
*/ | ||
get inlineSVGOptions() { | ||
if (typeof this.options.inlineSVG === 'object') { | ||
return _objectSpread(_objectSpread({}, defaultInlineSVGOptions), this.options.inlineSVG); | ||
} | ||
return _objectSpread(_objectSpread({}, defaultInlineSVGOptions), {}, { | ||
enabled: !!this.options.inlineSVG | ||
}); | ||
} | ||
/** | ||
* Load the specified markdown-it plugin with given parameters. | ||
@@ -271,0 +298,0 @@ * |
@@ -36,2 +36,4 @@ "use strict"; | ||
var _svg_backdrop = _interopRequireDefault(require("./postcss/svg_backdrop")); | ||
var _theme = _interopRequireDefault(require("./theme")); | ||
@@ -262,4 +264,4 @@ | ||
* @param {boolean} [opts.printable] Make style printable to PDF. | ||
* @param {boolean} [opts.inlineSVG] Apply a hierarchy of inline SVG to CSS | ||
* selector by setting `true`. _(Experimental)_ | ||
* @param {Marpit~InlineSVGOptions} [opts.inlineSVG] Apply a hierarchy of | ||
* inline SVG to CSS selector by setting `true`. _(Experimental)_ | ||
* @return {string} The converted CSS string. | ||
@@ -274,8 +276,12 @@ */ | ||
const theme = this.get(name, true); | ||
if (opts.inlineSVG) slideElements.unshift({ | ||
tag: 'svg' | ||
}, { | ||
tag: 'foreignObject' | ||
}); | ||
const inlineSVGOpts = opts.inlineSVG || {}; | ||
if (inlineSVGOpts.enabled) { | ||
slideElements.unshift({ | ||
tag: 'svg' | ||
}, { | ||
tag: 'foreignObject' | ||
}); | ||
} | ||
const additionalCSS = css => { | ||
@@ -298,3 +304,3 @@ if (!css) return undefined; | ||
height: this.getThemeProp(theme, 'height') | ||
}), theme !== _scaffold.default && (0, _postcss_plugin.default)('marpit-pack-scaffold', () => css => css.first.before(_scaffold.default.css)), opts.inlineSVG && _advanced_background.default, _pagination.default, (0, _replace3.default)({ | ||
}), theme !== _scaffold.default && (0, _postcss_plugin.default)('marpit-pack-scaffold', () => css => css.first.before(_scaffold.default.css)), inlineSVGOpts.enabled && _advanced_background.default, inlineSVGOpts.enabled && inlineSVGOpts.backdropSelector && _svg_backdrop.default, _pagination.default, (0, _replace3.default)({ | ||
pseudoClass: _increasing_specificity.pseudoClass | ||
@@ -301,0 +307,0 @@ }), _font_size.default, _increasing_specificity.default, _prepend.default, (0, _replace2.default)(opts.containers, slideElements), opts.printable && _printable.postprocess, _rem.default, _rollup.default].filter(p => p)); |
{ | ||
"name": "@marp-team/marpit", | ||
"version": "2.1.2", | ||
"version": "2.2.0", | ||
"description": "The skinny framework for creating slide deck from Markdown", | ||
@@ -62,15 +62,15 @@ "license": "MIT", | ||
"devDependencies": { | ||
"@babel/cli": "^7.15.7", | ||
"@babel/core": "^7.15.8", | ||
"@babel/eslint-parser": "^7.15.8", | ||
"@babel/preset-env": "^7.15.8", | ||
"autoprefixer": "^10.3.7", | ||
"@babel/cli": "^7.16.0", | ||
"@babel/core": "^7.16.0", | ||
"@babel/eslint-parser": "^7.16.3", | ||
"@babel/preset-env": "^7.16.4", | ||
"autoprefixer": "^10.4.0", | ||
"cheerio": "^1.0.0-rc.10", | ||
"chokidar": "^3.5.2", | ||
"cssnano": "^5.0.8", | ||
"cssnano": "^5.0.11", | ||
"dedent": "^0.7.0", | ||
"docsify-themeable": "^0.8.6", | ||
"eslint": "^8.1.0", | ||
"eslint": "^8.2.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-plugin-import": "^2.25.2", | ||
"eslint-plugin-import": "^2.25.3", | ||
"jest": "^27.3.1", | ||
@@ -83,7 +83,7 @@ "jest-junit": "^13.0.0", | ||
"rimraf": "^3.0.2", | ||
"sass": "1.43.3", | ||
"sass": "1.43.4", | ||
"serve-handler": "^6.1.3", | ||
"stylelint": "^14.0.1", | ||
"stylelint": "^14.1.0", | ||
"stylelint-config-prettier": "^9.0.3", | ||
"stylelint-config-standard-scss": "^2.0.0", | ||
"stylelint-config-standard-scss": "^2.0.1", | ||
"ws": "^8.2.3" | ||
@@ -90,0 +90,0 @@ }, |
154121
57
3582