@marp-team/marpit
Version:
The skinny framework for creating slide deck from Markdown
147 lines (122 loc) • 5.73 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _inline_style = _interopRequireDefault(require("../helpers/inline_style"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const escape = target => target.replace(/[\\;:()]/g, matched => `\\${matched[0].codePointAt(0).toString(16)} `);
/**
* Marpit parse image plugin.
*
* Parse image tokens and store the result into `marpitImage` meta. It has an
* image url and options. The alternative text is regarded as space-separated
* options.
*
* @alias module:markdown/parse_image
* @param {MarkdownIt} md markdown-it instance.
* @param {Object} [opts]
* @param {boolean} [opts.filters=true] Switch feature to support CSS filters.
*/
function parseImage(md, opts = {}) {
const pluginOptions = _objectSpread({
filters: true
}, opts);
const optionMatchers = new Map(); // The scale percentage for resize background
optionMatchers.set(/^(\d*\.)?\d+%$/, matches => ({
size: matches[0]
})); // width and height
optionMatchers.set(/^w(?:idth)?:((?:\d*\.)?\d+(?:%|ch|cm|em|ex|in|mm|pc|pt|px)?|auto)$/, matches => ({
width: matches[1]
}));
optionMatchers.set(/^h(?:eight)?:((?:\d*\.)?\d+(?:%|ch|cm|em|ex|in|mm|pc|pt|px)?|auto)$/, matches => ({
height: matches[1]
}));
if (pluginOptions.filters) {
// CSS filters
optionMatchers.set(/^blur(?::(.+))?$/, (matches, meta) => ({
filters: [...meta.filters, ['blur', escape(matches[1] || '10px')]]
}));
optionMatchers.set(/^brightness(?::(.+))?$/, (matches, meta) => ({
filters: [...meta.filters, ['brightness', escape(matches[1] || '1.5')]]
}));
optionMatchers.set(/^contrast(?::(.+))?$/, (matches, meta) => ({
filters: [...meta.filters, ['contrast', escape(matches[1] || '2')]]
}));
optionMatchers.set(/^drop-shadow(?::(.+?),(.+?)(?:,(.+?))?(?:,(.+?))?)?$/, (matches, meta) => {
const args = [];
for (const arg of matches.slice(1)) {
if (arg) {
const colorFunc = arg.match(/^(rgba?|hsla?)\((.*)\)$/);
args.push(colorFunc ? `${colorFunc[1]}(${escape(colorFunc[2])})` : escape(arg));
}
}
return {
filters: [...meta.filters, ['drop-shadow', args.join(' ') || '0 5px 10px rgba(0,0,0,.4)']]
};
});
optionMatchers.set(/^grayscale(?::(.+))?$/, (matches, meta) => ({
filters: [...meta.filters, ['grayscale', escape(matches[1] || '1')]]
}));
optionMatchers.set(/^hue-rotate(?::(.+))?$/, (matches, meta) => ({
filters: [...meta.filters, ['hue-rotate', escape(matches[1] || '180deg')]]
}));
optionMatchers.set(/^invert(?::(.+))?$/, (matches, meta) => ({
filters: [...meta.filters, ['invert', escape(matches[1] || '1')]]
}));
optionMatchers.set(/^opacity(?::(.+))?$/, (matches, meta) => ({
filters: [...meta.filters, ['opacity', escape(matches[1] || '.5')]]
}));
optionMatchers.set(/^saturate(?::(.+))?$/, (matches, meta) => ({
filters: [...meta.filters, ['saturate', escape(matches[1] || '2')]]
}));
optionMatchers.set(/^sepia(?::(.+))?$/, (matches, meta) => ({
filters: [...meta.filters, ['sepia', escape(matches[1] || '1')]]
}));
}
md.inline.ruler2.push('marpit_parse_image', ({
tokens
}) => {
for (const token of tokens) {
if (token.type === 'image') {
const options = token.content.split(/\s+/).filter(s => s.length > 0);
token.meta = token.meta || {};
token.meta.marpitImage = _objectSpread({}, token.meta.marpitImage || {}, {
url: token.attrGet('src'),
options
});
for (const opt of options) for (const [regexp, mergeFunc] of optionMatchers) {
const matched = opt.match(regexp);
if (matched) token.meta.marpitImage = _objectSpread({}, token.meta.marpitImage, mergeFunc(matched, _objectSpread({
filters: []
}, token.meta.marpitImage)));
} // Build and apply styles
const {
filters,
height,
width
} = token.meta.marpitImage;
const style = new _inline_style.default(token.attrGet('style'));
const assign = (decl, value) => {
const normalize = `${value}${/^(\d*\.)?\d+$/.test(value) ? 'px' : ''}`;
token.meta.marpitImage[decl] = normalize;
if (!value.endsWith('%')) style.set(decl, normalize);
};
if (width) assign('width', width);
if (height) assign('height', height);
if (filters) {
const filterStyle = [];
for (const fltrs of filters) filterStyle.push(`${fltrs[0]}(${fltrs[1]})`);
token.meta.marpitImage.filter = filterStyle.join(' ');
style.set('filter', token.meta.marpitImage.filter);
}
const stringified = style.toString();
if (stringified) token.attrSet('style', stringified);
}
}
});
}
var _default = parseImage;
exports.default = _default;