1
0

add initial marp implementation with sample content and build configuration

This commit is contained in:
2025-09-13 18:13:22 +02:00
parent dcacc9b409
commit e5f219507f
10319 changed files with 1402023 additions and 0 deletions

66
node_modules/@marp-team/marpit/lib/element.js generated vendored Normal file
View File

@@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.marpitContainer = exports.default = void 0;
/** @module */
/**
* Marpit element class.
*
* @alias Element
*/
class Element {
/**
* Create a Element instance.
*
* Element instance has compatibility with a plain object that is consists by
* `tag` key and pairs of attribute names and values. A difference is whether
* object has been frozen.
*
* ```js
* import assert from 'assert'
* import { Element } from 'marpit'
*
* const obj = { tag: 'div', class: 'marpit' }
* const elm = new Element('div', { class: 'marpit' })
*
* // This assertion would pass.
* assert.deepStrictEqual(obj, { ...elm })
* ```
*
* @param {string} tag Tag name
* @param {Object} [attributes={}] Tag attributes
*/
constructor(tag, attributes = {}) {
Object.defineProperties(this, {
attributes: {
value: attributes
},
tag: {
enumerable: true,
value: tag
}
});
for (const attr of Object.keys(attributes)) {
Object.defineProperty(this, attr, {
enumerable: true,
value: attributes[attr]
});
}
Object.freeze(this);
}
}
/**
* Marpit's default container.
*
* It would output `<div class="marpit"></div>`.
*
* @alias module:element.marpitContainer
* @type {Element}
*/
const marpitContainer = exports.marpitContainer = new Element('div', {
class: 'marpit'
});
var _default = exports.default = Element;

View File

@@ -0,0 +1,92 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _postcss = _interopRequireDefault(require("postcss"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* InlineStyle helper class.
*
* This is the declarative builder of an inline style using PostCSS. The output
* string by `toString()` is sanitized unexpected declarations.
*
* @module
* @alias module:helpers/inline_style
*/
class InlineStyle {
/**
* Create an InlineStyle instance.
*
* @function constructor
* @param {Object|String|InlineStyle} [initialDecls] The initial declarations.
*/
constructor(initialDecls) {
this.decls = {};
if (initialDecls) {
if (initialDecls instanceof InlineStyle || typeof initialDecls === 'string') {
const root = _postcss.default.parse(initialDecls.toString(), {
from: undefined
});
root.each(node => {
if (node.type === 'decl') this.decls[node.prop] = node.value;
});
} else {
this.decls = {
...initialDecls
};
}
}
}
/**
* Delete declaration.
*
* @param {string} prop A property name of declaration.
* @returns {InlineStyle} Returns myself for chaining methods.
*/
delete(prop) {
delete this.decls[prop];
return this;
}
/**
* Set declaration.
*
* @param {string} prop A property name of declaration.
* @param {string} value A value of declaration.
* @returns {InlineStyle} Returns myself for chaining methods.
*/
set(prop, value) {
this.decls[prop] = value;
return this;
}
/**
* Build a string of declarations for the inline style.
*
* The unexpected declarations will strip to prevent a style injection.
*/
toString() {
let built = '';
for (const prop of Object.keys(this.decls)) {
let parsed;
try {
parsed = _postcss.default.parse(`${prop}:${this.decls[prop]}`, {
from: undefined
});
} catch {
// A declaration that have value it cannot parse will ignore.
}
if (parsed) {
parsed.each(node => {
if (node.type !== 'decl' || node.prop !== prop) node.remove();
});
built += `${parsed.toString()};`;
}
}
return built;
}
}
exports.default = InlineStyle;

View File

@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.plugin = plugin;
/** @module */
/**
* Generate PostCSS plugin.
*
* This is a glue code generator to migrate existed plugins to support
* PostCSS 8.
*
* @param {string} name Plugin name.
* @param {(Function|Object)} func Function with PostCSS plugin interface.
* @returns {Function} A PostCSS plugin.
*/
function plugin(name, func) {
return Object.defineProperty(function intrface(...args) {
const retFunc = func.apply(this, args);
return Object.defineProperty(typeof retFunc === 'function' ? {
Once: retFunc
} : retFunc, 'postcssPlugin', {
value: name
});
}, 'postcss', {
value: true
});
}
var _default = exports.default = plugin;

35
node_modules/@marp-team/marpit/lib/helpers/split.js generated vendored Normal file
View File

@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.split = split;
/** @module */
/**
* Split array into multiple arrays by specified condition.
*
* @param {Array} arr Target array.
* @param {splitCallback} func Callback to split array.
* @param {boolean} [keepSplitedValue=false] Keep splited value. The split
* point is before the matched value.
* @returns {Array[]} Splited array.
*/
function split(arr, func, keepSplitedValue = false) {
const ret = [[]];
for (const value of arr) {
/**
* Return true at the split point.
*
* @callback splitCallback
* @param {*} value
*/
if (func(value)) {
ret.push(keepSplitedValue ? [value] : []);
} else {
ret[ret.length - 1].push(value);
}
}
return ret;
}
var _default = exports.default = split;

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.wrapArray = exports.default = void 0;
/** @module */
/**
* Wrap value in array if it is not an array.
*
* @function wrapArray
* @param {*} valOrArr
* @return {Array}
*/
const wrapArray = valOrArr => {
if (valOrArr == null || valOrArr === false) return [];
if (valOrArr instanceof Array) return valOrArr;
return [valOrArr];
};
exports.wrapArray = wrapArray;
var _default = exports.default = wrapArray;

View File

@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.wrapTokens = wrapTokens;
/** @module */
/**
* Wrap array of tokens by specified container object.
*
* @param {Token} Token markdown-it's Token class.
* @param {String} type Token type. It will be suffixed by `_open` / `_close`.
* @param {Object} container A container object to wrap tokens, includes tag
* name and attributes.
* @param {String} container.tag The name of container element.
* @param {Object} [container.open] The object assigning to an opening token.
* @param {Object} [container.close] The object assigning to a closing token.
* @param {Token[]} [tokens=[]] Wrapping tokens.
* @returns {Token[]} Wrapped tokens.
*/
function wrapTokens(Token, type, container, tokens = []) {
const {
tag
} = container;
// Update nesting level of wrapping tokens
for (const t of tokens) t.level += 1;
// Create markdown-it tokens
const open = new Token(`${type}_open`, tag, 1);
const close = new Token(`${type}_close`, tag, -1);
Object.assign(open, {
...(container.open || {})
});
Object.assign(close, {
...(container.close || {})
});
// Assign attributes
for (const attr of Object.keys(container)) {
if (!['open', 'close', 'tag'].includes(attr) && container[attr] != null) open.attrSet(attr, container[attr]);
}
return [open, ...tokens, close];
}
var _default = exports.default = wrapTokens;

36
node_modules/@marp-team/marpit/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "Element", {
enumerable: true,
get: function () {
return _element.default;
}
});
Object.defineProperty(exports, "Marpit", {
enumerable: true,
get: function () {
return _marpit.default;
}
});
Object.defineProperty(exports, "Theme", {
enumerable: true,
get: function () {
return _theme.default;
}
});
Object.defineProperty(exports, "ThemeSet", {
enumerable: true,
get: function () {
return _theme_set.default;
}
});
exports.default = void 0;
var _element = _interopRequireDefault(require("./element"));
var _marpit = _interopRequireDefault(require("./marpit"));
var _theme = _interopRequireDefault(require("./theme"));
var _theme_set = _interopRequireDefault(require("./theme_set"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = _marpit.default;

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.backgroundImage = void 0;
var _plugin = _interopRequireDefault(require("../plugin"));
var _advanced = _interopRequireDefault(require("./background_image/advanced"));
var _apply = _interopRequireDefault(require("./background_image/apply"));
var _parse = _interopRequireDefault(require("./background_image/parse"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit background image plugin.
*
* Convert image token to backgrounds when the alternate text includes `bg`.
*
* 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 inline SVG mode is enabled, the plugin enables advanced background mode.
* In addition to the basic background implementation, it supports multiple
* background images, filters, and split background.
*
* @function backgroundImage
* @param {MarkdownIt} md markdown-it instance.
*/
function _backgroundImage(md) {
(0, _parse.default)(md);
(0, _apply.default)(md);
(0, _advanced.default)(md);
}
const backgroundImage = exports.backgroundImage = (0, _plugin.default)(_backgroundImage);
var _default = exports.default = backgroundImage;

View File

@@ -0,0 +1,142 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.advancedBackground = void 0;
var _inline_style = _interopRequireDefault(require("../../helpers/inline_style"));
var _wrap_tokens = require("../../helpers/wrap_tokens");
var _plugin = _interopRequireDefault(require("../../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit advanced background image plugin.
*
* Support the advanced features for background image, by using `<figure>`
* element(s) instead of CSS backgrounds. It works by creating the isolated
* layer into inline SVG.
*
* @function advancedBackground
* @param {MarkdownIt} md markdown-it instance.
*/
function _advancedBackground(md) {
md.core.ruler.after('marpit_directives_apply', 'marpit_advanced_background', state => {
let current;
const newTokens = [];
for (const t of state.tokens) {
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');
// Aligned direction
const direction = t.meta.marpitBackground.direction || 'horizontal';
// Split backgrounds
const splitSide = t.meta.marpitBackground.split;
if (splitSide) {
open.attrSet('data-marpit-advanced-background-split', splitSide);
const splitBgSize = t.meta.marpitBackground.splitSize || '50%';
t.attrSet('width', `${100 - Number.parseFloat(splitBgSize.slice(0, -1))}%`);
if (splitSide === 'left') t.attrSet('x', splitBgSize);
const style = new _inline_style.default(open.attrGet('style'));
style.set('--marpit-advanced-background-split', splitBgSize);
open.attrSet('style', style.toString());
}
// Add the isolated layer for background image
newTokens.push(...(0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_advanced_background_foreign_object', {
tag: 'foreignObject',
width,
height
}, (0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_advanced_background_section', {
...open.attrs.reduce((o, [k, v]) => ({
...o,
[k]: v
}), {}),
tag: 'section',
id: undefined,
'data-marpit-advanced-background': 'background'
}, (0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_advanced_background_image_container', {
tag: 'div',
'data-marpit-advanced-background-container': true,
'data-marpit-advanced-background-direction': direction
}, (() => {
const imageTokens = [];
// Add multiple image elements
for (const img of images) {
const style = new _inline_style.default({
'background-image': `url("${img.url}")`
});
// Image sizing
if (img.size) style.set('background-size', img.size);
// Image filter for backgrounds (Only in advanced BG)
if (img.filter) style.set('filter', img.filter);
imageTokens.push(...(0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_advanced_background_image', {
tag: 'figure',
style: style.toString(),
open: {
meta: {
marpitBackgroundAlt: img.alt
}
}
}));
}
return imageTokens;
})()))), t);
} else if (current && t.type === 'marpit_inline_svg_content_close') {
const {
open,
height,
width
} = current.meta.marpitBackground;
// Apply styles
const style = new _inline_style.default();
if (open.meta && open.meta.marpitDirectives && open.meta.marpitDirectives.color) style.set('color', open.meta.marpitDirectives.color);
// Add the isolated layer for pseudo contents (e.g. Page number)
newTokens.push(t, ...(0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_advanced_background_foreign_object', {
tag: 'foreignObject',
width,
height,
'data-marpit-advanced-background': 'pseudo'
}, (0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_advanced_pseudo_section', {
...open.attrs.reduce((o, [k, v]) => ({
...o,
[k]: v
}), {}),
tag: 'section',
id: undefined,
style: style.toString(),
'data-marpit-advanced-background': 'pseudo'
})));
current = undefined;
} else {
newTokens.push(t);
}
}
state.tokens = newTokens;
});
// Renderer for advanced background image
md.renderer.rules.marpit_advanced_background_image_open = (tokens, idx, options, _env, self) => {
const token = tokens[idx];
const open = self.renderToken(tokens, idx, options);
if (token.meta?.marpitBackgroundAlt) {
return `${open}<figcaption>${md.utils.escapeHtml(token.meta.marpitBackgroundAlt)}</figcaption>`;
}
return open;
};
}
const advancedBackground = exports.advancedBackground = (0, _plugin.default)(_advancedBackground);
var _default = exports.default = advancedBackground;

View File

@@ -0,0 +1,111 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.backgroundImageApply = void 0;
var _plugin = _interopRequireDefault(require("../../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit background image apply plugin.
*
* Apply parsed meta for background image / color into directives of each page.
*
* When inline SVG is enabled, it will reshape meta for advanced process instead
* of converting to directives.
*
* @function backgroundImageApply
* @param {MarkdownIt} md markdown-it instance.
*/
function _backgroundImageApply(md) {
md.core.ruler.after('marpit_inline_svg', 'marpit_apply_background_image', ({
inlineMode,
tokens
}) => {
if (inlineMode) return;
let current = {};
for (const tb of tokens) {
if (tb.type === 'marpit_slide_open') current.open = tb;
if (tb.type === 'marpit_inline_svg_content_open') current.svgContent = tb;
if (tb.type === 'marpit_slide_close') {
if (current.images && current.images.length > 0) {
if (current.svgContent) {
// Reshape meta for advanced background
current.svgContent.meta = {
...(current.svgContent.meta || {}),
marpitBackground: {
direction: current.direction,
height: current.svgContent.attrGet('height'),
images: current.images,
open: current.open,
split: current.split,
splitSize: current.splitSize,
width: current.svgContent.attrGet('width')
}
};
} else {
// Apply simple CSS background
const img = current.images[current.images.length - 1];
current.open.meta.marpitDirectives = {
...(current.open.meta.marpitDirectives || {}),
backgroundImage: `url("${img.url}")`
};
if (img.size) current.open.meta.marpitDirectives.backgroundSize = img.size;
}
}
current = {};
}
// Collect parsed inline image meta
if (current.open && tb.type === 'inline') for (const t of tb.children) {
if (t.type === 'image') {
const {
background,
backgroundDirection,
backgroundSize,
backgroundSplit,
backgroundSplitSize,
color,
filter,
height,
size,
url,
width,
options
} = t.meta.marpitImage;
if (background && !url.match(/^\s*$/)) {
if (color) {
// Background color
current.open.meta.marpitDirectives = {
...(current.open.meta.marpitDirectives || {}),
backgroundColor: color
};
} else {
// Background image
let altText = '';
for (const opt of options) if (!opt.consumed) altText += opt.leading + opt.content;
current.images = [...(current.images || []), {
filter,
height,
size: (() => {
const s = size || backgroundSize || undefined;
return !['contain', 'cover'].includes(s) && (width || height) ? `${width || s || 'auto'} ${height || s || 'auto'}` : s;
})(),
url,
width,
alt: altText.trimStart()
}];
}
}
if (backgroundDirection) current.direction = backgroundDirection;
if (backgroundSplit) current.split = backgroundSplit;
if (backgroundSplitSize) current.splitSize = backgroundSplitSize;
}
}
}
});
}
const backgroundImageApply = exports.backgroundImageApply = (0, _plugin.default)(_backgroundImageApply);
var _default = exports.default = backgroundImageApply;

View File

@@ -0,0 +1,77 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.backgroundImageParse = void 0;
var _plugin = _interopRequireDefault(require("../../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const bgSizeKeywords = {
auto: 'auto',
contain: 'contain',
cover: 'cover',
fit: 'contain'
};
const splitSizeMatcher = /^(left|right)(?::((?:\d*\.)?\d+%))?$/;
/**
* Marpit background image parse plugin.
*
* Parse Marpit's image token and mark as background image when the alternate
* text includes `bg`. The marked images will not show as the regular image.
*
* Furthermore, it parses additional keywords needed for background image.
*
* @function backgroundImageParse
* @param {MarkdownIt} md markdown-it instance.
*/
function _backgroundImageParse(md) {
md.inline.ruler2.after('marpit_parse_image', 'marpit_background_image', ({
tokens
}) => {
for (const t of tokens) {
if (t.type === 'image') {
const {
marpitImage
} = t.meta;
if (marpitImage.options.some(v => !v.consumed && v.content === 'bg')) {
marpitImage.background = true;
t.hidden = true;
for (const opt of marpitImage.options) {
if (opt.consumed) continue;
let consumed = false;
// bg keyword
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) {
const [, splitSide, splitSize] = matched;
marpitImage.backgroundSplit = splitSide;
marpitImage.backgroundSplitSize = splitSize;
consumed = true;
}
// Background aligned direction
if (opt.content === 'vertical' || opt.content === 'horizontal') {
marpitImage.backgroundDirection = opt.content;
consumed = true;
}
if (consumed) opt.consumed = true;
}
}
}
}
});
}
const backgroundImageParse = exports.backgroundImageParse = (0, _plugin.default)(_backgroundImageParse);
var _default = exports.default = backgroundImageParse;

59
node_modules/@marp-team/marpit/lib/markdown/collect.js generated vendored Normal file
View File

@@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.collect = void 0;
var _plugin = _interopRequireDefault(require("../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit collect plugin.
*
* Collect parsed tokens per slide and comments except marked as used for
* internally. These will store to lastSlideTokens and lastComments member of
* Marpit instance. It would use in the returned object from
* {@link Marpit#render}.
*
* @function collect
* @param {MarkdownIt} md markdown-it instance.
*/
function _collect(md) {
const {
marpit
} = md;
md.core.ruler.push('marpit_collect', state => {
if (state.inlineMode) return;
marpit.lastComments = [];
marpit.lastSlideTokens = [];
let currentPage;
let pageIdx = -1;
const collectComment = token => {
if (currentPage >= 0 && !(token.meta && token.meta.marpitCommentParsed !== undefined)) marpit.lastComments[currentPage].push(token.content);
};
const collectable = () => currentPage >= 0 && marpit.lastSlideTokens[currentPage] !== undefined;
for (const token of state.tokens) {
if (token.meta && token.meta.marpitSlideElement === 1) {
pageIdx += 1;
currentPage = pageIdx;
if (marpit.lastSlideTokens[currentPage] === undefined) {
marpit.lastSlideTokens[currentPage] = [token];
marpit.lastComments[currentPage] = [];
}
} else if (token.meta && token.meta.marpitSlideElement === -1) {
if (collectable()) marpit.lastSlideTokens[currentPage].push(token);
currentPage = undefined;
} else {
if (collectable()) marpit.lastSlideTokens[currentPage].push(token);
if (token.type === 'marpit_comment') {
collectComment(token);
} else if (token.type === 'inline') {
for (const t of token.children) if (t.type === 'marpit_comment') collectComment(t);
}
}
}
});
}
const collect = exports.collect = (0, _plugin.default)(_collect);
var _default = exports.default = collect;

108
node_modules/@marp-team/marpit/lib/markdown/comment.js generated vendored Normal file
View File

@@ -0,0 +1,108 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.comment = void 0;
exports.markAsParsed = markAsParsed;
var _plugin = _interopRequireDefault(require("../plugin"));
var _yaml = require("./directives/yaml");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const commentMatcher = /<!--+\s*([\s\S]*?)\s*--+>/;
const commentMatcherOpening = /^<!--/;
const commentMatcherClosing = /-->/;
const magicCommentMatchers = [
// Prettier
/^prettier-ignore(-(start|end))?$/,
// markdownlint
/^markdownlint-((disable|enable).*|capture|restore)$/,
// remark-lint (remark-message-control)
/^lint (disable|enable|ignore).*$/];
function markAsParsed(token, kind) {
token.meta = token.meta || {};
token.meta.marpitCommentParsed = kind;
}
/**
* Marpit comment plugin.
*
* Parse HTML comment as token. Comments will strip regardless of html setting
* provided by markdown-it.
*
* @function comment
* @param {MarkdownIt} md markdown-it instance.
*/
function _comment(md) {
const parse = (token, content) => {
const parsed = (0, _yaml.yaml)(content, !!md.marpit.options.looseYAML);
token.meta = token.meta || {};
token.meta.marpitParsedDirectives = parsed === false ? {} : parsed;
// Mark well-known magic comments as parsed comment
for (const magicCommentMatcher of magicCommentMatchers) {
if (magicCommentMatcher.test(content.trim())) {
markAsParsed(token, 'well-known-magic-comment');
break;
}
}
};
md.block.ruler.before('html_block', 'marpit_comment', (state, startLine, endLine, silent) => {
// Fast fail
let pos = state.bMarks[startLine] + state.tShift[startLine];
if (state.src.charCodeAt(pos) !== 0x3c) return false;
let max = state.eMarks[startLine];
let line = state.src.slice(pos, max);
// Match to opening element
if (!commentMatcherOpening.test(line)) return false;
if (silent) return true;
// Parse ending element
let nextLine = startLine + 1;
if (!commentMatcherClosing.test(line)) {
while (nextLine < endLine) {
if (state.sCount[nextLine] < state.blkIndent) break;
pos = state.bMarks[nextLine] + state.tShift[nextLine];
max = state.eMarks[nextLine];
line = state.src.slice(pos, max);
nextLine += 1;
if (commentMatcherClosing.test(line)) break;
}
}
state.line = nextLine;
// Create token
const token = state.push('marpit_comment', '', 0);
token.map = [startLine, nextLine];
token.markup = state.getLines(startLine, nextLine, state.blkIndent, true);
token.hidden = true;
const matchedContent = commentMatcher.exec(token.markup);
token.content = matchedContent ? matchedContent[1].trim() : '';
parse(token, token.content);
return true;
});
md.inline.ruler.before('html_inline', 'marpit_inline_comment', (state, silent) => {
const {
posMax,
src
} = state;
// Quick fail by checking `<` and `!`
if (state.pos + 2 >= posMax || src.charCodeAt(state.pos) !== 0x3c || src.charCodeAt(state.pos + 1) !== 0x21) return false;
const match = src.slice(state.pos).match(commentMatcher);
if (!match) return false;
if (!silent) {
const token = state.push('marpit_comment', '', 0);
token.hidden = true;
token.markup = src.slice(state.pos, state.pos + match[0].length);
token.content = match[1].trim();
parse(token, token.content);
}
state.pos += match[0].length;
return true;
});
}
const comment = exports.comment = (0, _plugin.default)(_comment);
var _default = exports.default = comment;

View File

@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.container = void 0;
var _wrap_array = require("../helpers/wrap_array");
var _wrap_tokens = require("../helpers/wrap_tokens");
var _plugin = _interopRequireDefault(require("../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit container plugin.
*
* @function container
* @param {MarkdownIt} md markdown-it instance.
*/
function _container(md) {
const containers = (0, _wrap_array.wrapArray)(md.marpit.options.container);
if (!containers) return;
const target = [...containers].reverse();
md.core.ruler.push('marpit_containers', state => {
if (state.inlineMode) return;
for (const cont of target) state.tokens = (0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_containers', cont, state.tokens);
});
}
const container = exports.container = (0, _plugin.default)(_container);
var _default = exports.default = container;

View File

@@ -0,0 +1,98 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.apply = void 0;
var _lodash = _interopRequireDefault(require("lodash.kebabcase"));
var _inline_style = _interopRequireDefault(require("../../helpers/inline_style"));
var _plugin = _interopRequireDefault(require("../../plugin"));
var _directives = _interopRequireDefault(require("./directives"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Apply parsed Marpit directives to markdown-it tokens.
*
* @function apply
* @param {MarkdownIt} md markdown-it instance.
* @param {Object} [opts]
* @param {boolean} [opts.dataset=true] Assigns directives as HTML data
* attributes of each section tag.
* @param {boolean} [opts.css=true] Assigns directives as CSS Custom Properties
* of each section tag.
*/
function _apply(md, opts = {}) {
const {
marpit
} = md;
const {
lang
} = marpit.options;
const dataset = opts.dataset === undefined ? true : !!opts.dataset;
const css = opts.css === undefined ? true : !!opts.css;
const {
global,
local
} = marpit.customDirectives;
const directives = [...Object.keys(global), ...Object.keys(local), ..._directives.default];
md.core.ruler.after('marpit_directives_parse', 'marpit_directives_apply', state => {
if (state.inlineMode) return;
let pageNumber = 0;
const tokensForPaginationTotal = [];
for (const token of state.tokens) {
const {
marpitDirectives
} = token.meta || {};
if (token.type === 'marpit_slide_open') {
// `skip` and `hold` disable increment of the page number
if (!(marpitDirectives?.paginate === 'skip' || marpitDirectives?.paginate === 'hold')) {
pageNumber += 1;
}
}
if (marpitDirectives) {
const style = new _inline_style.default(token.attrGet('style'));
for (const dir of Object.keys(marpitDirectives)) {
if (directives.includes(dir)) {
const value = marpitDirectives[dir];
if (value) {
const kebabCaseDir = (0, _lodash.default)(dir);
if (dataset) token.attrSet(`data-${kebabCaseDir}`, value);
if (css) style.set(`--${kebabCaseDir}`, value);
}
}
}
// Apply attribute to token
if (marpitDirectives.lang || lang) token.attrSet('lang', marpitDirectives.lang || lang);
if (marpitDirectives.class) token.attrJoin('class', marpitDirectives.class);
if (marpitDirectives.color) style.set('color', marpitDirectives.color);
if (marpitDirectives.backgroundColor) style.set('background-color', marpitDirectives.backgroundColor).set('background-image', 'none');
if (marpitDirectives.backgroundImage) {
style.set('background-image', marpitDirectives.backgroundImage).set('background-position', 'center').set('background-repeat', 'no-repeat').set('background-size', 'cover');
if (marpitDirectives.backgroundPosition) style.set('background-position', marpitDirectives.backgroundPosition);
if (marpitDirectives.backgroundRepeat) style.set('background-repeat', marpitDirectives.backgroundRepeat);
if (marpitDirectives.backgroundSize) style.set('background-size', marpitDirectives.backgroundSize);
}
if (marpitDirectives.paginate && marpitDirectives.paginate !== 'skip') {
// If the page number was still not incremented, mark this page as
// the first page.
if (pageNumber <= 0) pageNumber = 1;
token.attrSet('data-marpit-pagination', pageNumber);
tokensForPaginationTotal.push(token);
}
if (marpitDirectives.header) token.meta.marpitHeader = marpitDirectives.header;
if (marpitDirectives.footer) token.meta.marpitFooter = marpitDirectives.footer;
const styleStr = style.toString();
if (styleStr !== '') token.attrSet('style', styleStr);
}
}
// Set total page number to each slide page that has pagination attribute
for (const token of tokensForPaginationTotal) {
token.attrSet('data-marpit-pagination-total', pageNumber);
}
});
}
const apply = exports.apply = (0, _plugin.default)(_apply);
var _default = exports.default = apply;

View File

@@ -0,0 +1,126 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.locals = exports.globals = exports.default = void 0;
/**
* The definition of Marpit directives
* @module
*/
/**
* @typedef {Function} Directive
* @param {string} value Parsed value.
* @param {Marpit} marpit Marpit instance.
* @returns {Object} Assigning object to token meta.
*/
/**
* Global directives.
*
* Each global directive assigns to the whole slide deck. If you wrote a same
* directive many times, Marpit only recognizes the last value.
*
* @prop {Directive} headingDivider Specify heading divider option.
* @prop {Directive} style Specify the CSS style to apply additionally.
* @prop {Directive} theme Specify theme of the slide deck.
* @prop {Directive} lang Specify the language of the slide deck. It will
* assign as `lang` attribute for each slide.
*/
const globals = exports.globals = Object.assign(Object.create(null), {
headingDivider: value => {
const headings = [1, 2, 3, 4, 5, 6];
const toInt = v => Array.isArray(v) || Number.isNaN(v) ? v : Number.parseInt(v, 10);
const converted = toInt(value);
if (Array.isArray(converted)) {
const convertedArr = converted.map(toInt);
return {
headingDivider: headings.filter(v => convertedArr.includes(v))
};
}
if (value === 'false') return {
headingDivider: false
};
if (headings.includes(converted)) return {
headingDivider: converted
};
return {};
},
style: v => ({
style: v
}),
theme: (v, marpit) => marpit.themeSet.has(v) ? {
theme: v
} : {},
lang: v => ({
lang: v
})
});
/**
* Local directives.
*
* Mainly these are used to change settings each slide page. By default, a
* local directive applies to the defined page and followed pages.
*
* If you want to set a local directive to single page only, you can add the
* prefix `_` (underbar) to directive name. (Spot directives)
*
* @prop {Directive} backgroundColor Specify background-color style.
* @prop {Directive} backgroundImage Specify background-image style.
* @prop {Directive} backgroundPosition Specify background-position style. The
* default value while setting backgroundImage is `center`.
* @prop {Directive} backgroundRepeat Specify background-repeat style. The
* default value while setting backgroundImage is `no-repeat`.
* @prop {Directive} backgroundSize Specify background-size style. The default
* value while setting backgroundImage is `cover`.
* @prop {Directive} class Specify HTML class of section element(s).
* @prop {Directive} color Specify color style (base text color).
* @prop {Directive} footer Specify the content of slide footer. It will insert
* a `<footer>` element to the last of each slide contents.
* @prop {Directive} header Specify the content of slide header. It will insert
* a `<header>` element to the first of each slide contents.
* @prop {Directive} paginate Show page number on the slide if you set `true`.
* `hold` and `skip` are also available to disable increment of the page
* number.
*/
const locals = exports.locals = Object.assign(Object.create(null), {
backgroundColor: v => ({
backgroundColor: v
}),
backgroundImage: v => ({
backgroundImage: v
}),
backgroundPosition: v => ({
backgroundPosition: v
}),
backgroundRepeat: v => ({
backgroundRepeat: v
}),
backgroundSize: v => ({
backgroundSize: v
}),
class: v => ({
class: Array.isArray(v) ? v.join(' ') : v
}),
color: v => ({
color: v
}),
footer: v => typeof v === 'string' ? {
footer: v
} : {},
header: v => typeof v === 'string' ? {
header: v
} : {},
paginate: v => {
const normalized = (v || '').toLowerCase();
if (['hold', 'skip'].includes(normalized)) return {
paginate: normalized
};
return {
paginate: normalized === 'true'
};
}
});
var _default = exports.default = [...Object.keys(globals), ...Object.keys(locals)];

View File

@@ -0,0 +1,182 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.parse = exports.default = void 0;
var _markdownItFrontMatter = _interopRequireDefault(require("markdown-it-front-matter"));
var _plugin = _interopRequireDefault(require("../../plugin"));
var _comment = require("../comment");
var directives = _interopRequireWildcard(require("./directives"));
var _yaml = require("./yaml");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const isDirectiveComment = token => token.type === 'marpit_comment' && token.meta.marpitParsedDirectives;
/**
* Parse Marpit directives and store result to the slide token meta.
*
* Marpit comment plugin ans slide plugin requires already loaded to
* markdown-it instance.
*
* @function parse
* @param {MarkdownIt} md markdown-it instance.
* @param {Object} [opts]
* @param {boolean} [opts.frontMatter=true] Switch feature to support YAML
* front-matter. If true, you can use Jekyll style directive setting to the
* first page.
*/
function _parse(md, opts = {}) {
const {
marpit
} = md;
const applyBuiltinDirectives = (newProps, builtinDirectives) => {
let ret = {};
for (const prop of Object.keys(newProps)) {
if (builtinDirectives[prop]) {
ret = {
...ret,
...builtinDirectives[prop](newProps[prop], marpit)
};
} else {
ret[prop] = newProps[prop];
}
}
return ret;
};
// Front-matter support
const frontMatter = opts.frontMatter === undefined ? true : !!opts.frontMatter;
let frontMatterObject = {};
if (frontMatter) {
md.core.ruler.before('block', 'marpit_directives_front_matter', state => {
frontMatterObject = {};
if (!state.inlineMode) marpit.lastGlobalDirectives = {};
});
md.use(_markdownItFrontMatter.default, fm => {
frontMatterObject.text = fm;
const parsed = (0, _yaml.yaml)(fm, marpit.options.looseYAML ? [...Object.keys(marpit.customDirectives.global), ...Object.keys(marpit.customDirectives.local)] : false);
if (parsed !== false) frontMatterObject.yaml = parsed;
});
}
// Parse global directives
md.core.ruler.after('inline', 'marpit_directives_global_parse', state => {
if (state.inlineMode) return;
let globalDirectives = {};
const applyDirectives = obj => {
let recognized = false;
for (const key of Object.keys(obj)) {
if (directives.globals[key]) {
recognized = true;
globalDirectives = {
...globalDirectives,
...directives.globals[key](obj[key], marpit)
};
} else if (marpit.customDirectives.global[key]) {
recognized = true;
globalDirectives = {
...globalDirectives,
...applyBuiltinDirectives(marpit.customDirectives.global[key](obj[key], marpit), directives.globals)
};
}
}
return recognized;
};
if (frontMatterObject.yaml) applyDirectives(frontMatterObject.yaml);
for (const token of state.tokens) {
if (isDirectiveComment(token) && applyDirectives(token.meta.marpitParsedDirectives)) {
(0, _comment.markAsParsed)(token, 'directive');
} else if (token.type === 'inline') {
for (const t of token.children) {
if (isDirectiveComment(t) && applyDirectives(t.meta.marpitParsedDirectives)) (0, _comment.markAsParsed)(t, 'directive');
}
}
}
marpit.lastGlobalDirectives = {
...globalDirectives
};
});
// Parse local directives and apply meta to slide
md.core.ruler.after('marpit_slide', 'marpit_directives_parse', state => {
if (state.inlineMode) return;
const slides = [];
const cursor = {
slide: undefined,
local: {},
spot: {}
};
const applyDirectives = obj => {
let recognized = false;
for (const key of Object.keys(obj)) {
if (directives.locals[key]) {
recognized = true;
cursor.local = {
...cursor.local,
...directives.locals[key](obj[key], marpit)
};
} else if (marpit.customDirectives.local[key]) {
recognized = true;
cursor.local = {
...cursor.local,
...applyBuiltinDirectives(marpit.customDirectives.local[key](obj[key], marpit), directives.locals)
};
}
// Spot directives
// (Apply local directive to only current slide by prefix "_")
if (key.startsWith('_')) {
const spotKey = key.slice(1);
if (directives.locals[spotKey]) {
recognized = true;
cursor.spot = {
...cursor.spot,
...directives.locals[spotKey](obj[key], marpit)
};
} else if (marpit.customDirectives.local[spotKey]) {
recognized = true;
cursor.spot = {
...cursor.spot,
...applyBuiltinDirectives(marpit.customDirectives.local[spotKey](obj[key], marpit), directives.locals)
};
}
}
}
return recognized;
};
if (frontMatterObject.yaml) applyDirectives(frontMatterObject.yaml);
for (const token of state.tokens) {
if (token.meta && token.meta.marpitSlideElement === 1) {
// Initialize Marpit directives meta
token.meta.marpitDirectives = {};
slides.push(token);
cursor.slide = token;
} else if (token.meta && token.meta.marpitSlideElement === -1) {
// Assign local and spot directives to meta
cursor.slide.meta.marpitDirectives = {
...cursor.slide.meta.marpitDirectives,
...cursor.local,
...cursor.spot
};
cursor.spot = {};
} else if (isDirectiveComment(token) && applyDirectives(token.meta.marpitParsedDirectives)) {
(0, _comment.markAsParsed)(token, 'directive');
} else if (token.type === 'inline') {
for (const t of token.children) {
if (isDirectiveComment(t) && applyDirectives(t.meta.marpitParsedDirectives)) (0, _comment.markAsParsed)(t, 'directive');
}
}
}
// Assign global directives to meta
for (const token of slides) token.meta.marpitDirectives = {
...token.meta.marpitDirectives,
...marpit.lastGlobalDirectives
};
});
}
const parse = exports.parse = (0, _plugin.default)(_parse);
var _default = exports.default = parse;

View File

@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.yaml = exports.default = void 0;
var _jsYaml = require("js-yaml");
var _directives = _interopRequireDefault(require("./directives"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const createPatterns = keys => {
const set = new Set();
for (const k of keys) {
const normalized = '_?' + k.replace(/[.*+?^=!:${}()|[\]\\/]/g, '\\$&');
set.add(normalized);
set.add(`"${normalized}"`);
set.add(`'${normalized}'`);
}
return [...set.values()];
};
const yamlSpecialChars = `["'{|>~&*`;
function parse(text) {
try {
const obj = (0, _jsYaml.load)(text, {
schema: _jsYaml.FAILSAFE_SCHEMA
});
if (obj === null || typeof obj !== 'object') return false;
return obj;
} catch {
return false;
}
}
function convertLoose(text, looseDirectives) {
const keyPattern = `(?:${createPatterns(looseDirectives).join('|')})`;
const looseMatcher = new RegExp(`^(${keyPattern}\\s*:)(.+)$`);
let normalized = '';
for (const line of text.split(/\r?\n/)) normalized += `${line.replace(looseMatcher, (original, prop, value) => {
const trimmed = value.trim();
if (trimmed.length === 0 || yamlSpecialChars.includes(trimmed[0])) return original;
const spaceLength = value.length - value.trimLeft().length;
const spaces = value.substring(0, spaceLength);
return `${prop}${spaces}"${trimmed.split('"').join('\\"')}"`;
})}\n`;
return normalized.trim();
}
/**
* Parse text as YAML by using js-yaml's FAILSAFE_SCHEMA.
*
* @function yaml
* @param {String} text Target text.
* @param {boolean|string[]} [looseDirectives=false] By setting `true`, it try
* to parse as loose YAML only in defined Marpit built-in directives. You
* may also extend target keys for loose parsing by passing an array of
* strings.
* @returns {Object|false} Return parse result, or `false` when failed to parse.
*/
const yaml = (text, looseDirectives = false) => parse(looseDirectives ? convertLoose(text, [..._directives.default, ...(Array.isArray(looseDirectives) ? looseDirectives : [])]) : text);
exports.yaml = yaml;
var _default = exports.default = yaml;

View File

@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.fragment = exports.default = void 0;
var _plugin = _interopRequireDefault(require("../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const fragmentedListMarkups = ['*', ')'];
/**
* Marpit fragment plugin.
*
* @function 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);
}
}
});
}
const fragment = exports.fragment = (0, _plugin.default)(_fragment);
var _default = exports.default = fragment;

View File

@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.headerAndFooter = exports.default = void 0;
var _wrap_tokens = require("../helpers/wrap_tokens");
var _plugin = _interopRequireDefault(require("../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit header and footer plugin.
*
* At each slide, add header and footer that are provided by directives.
*
* @function headerAndFooter
* @param {MarkdownIt} md markdown-it instance.
*/
function _headerAndFooter(md) {
md.core.ruler.after('marpit_directives_apply', 'marpit_header_and_footer', state => {
if (state.inlineMode) return;
const parsedInlines = new Map();
const getParsed = markdown => {
let parsed = parsedInlines.get(markdown);
if (!parsed) {
parsed = md.parseInline(markdown, state.env);
delete parsed.map;
parsedInlines.set(markdown, parsed);
}
return parsed;
};
const createMarginalTokens = (tag, markdown) => (0, _wrap_tokens.wrapTokens)(state.Token, `marpit_${tag}`, {
tag,
close: {
block: true
}
}, getParsed(markdown));
let current;
const newTokens = [];
for (const token of state.tokens) {
if (token.type === 'marpit_slide_open') {
current = token;
newTokens.push(token);
if (current.meta && current.meta.marpitHeader) newTokens.push(...createMarginalTokens('header', current.meta.marpitHeader));
} else if (token.type === 'marpit_slide_close') {
if (current.meta && current.meta.marpitFooter) newTokens.push(...createMarginalTokens('footer', current.meta.marpitFooter));
newTokens.push(token);
} else {
newTokens.push(token);
}
}
state.tokens = newTokens;
});
}
const headerAndFooter = exports.headerAndFooter = (0, _plugin.default)(_headerAndFooter);
var _default = exports.default = headerAndFooter;

View File

@@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.headingDivider = exports.default = void 0;
var _split = require("../helpers/split");
var _plugin = _interopRequireDefault(require("../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit heading divider plugin.
*
* Start a new slide page at before of headings by prepending hidden `<hr>`
* elements.
*
* @function headingDivider
* @param {MarkdownIt} md markdown-it instance.
*/
function _headingDivider(md) {
const {
marpit
} = md;
md.core.ruler.before('marpit_slide', 'marpit_heading_divider', state => {
let target = marpit.options.headingDivider;
if (marpit.lastGlobalDirectives && Object.prototype.hasOwnProperty.call(marpit.lastGlobalDirectives, 'headingDivider')) target = marpit.lastGlobalDirectives.headingDivider;
if (state.inlineMode || target === false) return;
if (Number.isInteger(target) && target >= 1 && target <= 6) target = [...Array(target).keys()].map(i => i + 1);
if (!Array.isArray(target)) return;
const splitTag = target.map(i => `h${i}`);
const splitFunc = t => t.type === 'heading_open' && splitTag.includes(t.tag);
const newTokens = [];
for (const slideTokens of (0, _split.split)(state.tokens, splitFunc, true)) {
const [token] = slideTokens;
if (token && splitFunc(token) && newTokens.some(t => !t.hidden)) {
const hr = new state.Token('hr', '', 0);
hr.hidden = true;
hr.map = token.map;
newTokens.push(hr);
}
newTokens.push(...slideTokens);
}
state.tokens = newTokens;
});
}
const headingDivider = exports.headingDivider = (0, _plugin.default)(_headingDivider);
var _default = exports.default = headingDivider;

24
node_modules/@marp-team/marpit/lib/markdown/image.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.image = exports.default = void 0;
var _plugin = _interopRequireDefault(require("../plugin"));
var _apply = _interopRequireDefault(require("./image/apply"));
var _parse = _interopRequireDefault(require("./image/parse"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit image plugin.
*
* @function image
* @param {MarkdownIt} md markdown-it instance.
*/
function _image(md) {
(0, _parse.default)(md);
(0, _apply.default)(md);
}
const image = exports.image = (0, _plugin.default)(_image);
var _default = exports.default = image;

View File

@@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.applyImage = void 0;
var _inline_style = _interopRequireDefault(require("../../helpers/inline_style"));
var _plugin = _interopRequireDefault(require("../../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit image apply plugin.
*
* Apply image style and color spot directive based on parsed meta.
*
* @function applyImage
* @param {MarkdownIt} md markdown-it instance.
*/
function _applyImage(md) {
// Build and apply image style
md.inline.ruler2.push('marpit_apply_image', ({
tokens
}) => {
for (const token of tokens) {
if (token.type === 'image') {
const {
filters,
height,
width
} = token.meta.marpitImage;
const style = new _inline_style.default(token.attrGet('style'));
if (width && !width.endsWith('%')) style.set('width', width);
if (height && !height.endsWith('%')) style.set('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);
}
}
});
}
const applyImage = exports.applyImage = (0, _plugin.default)(_applyImage);
var _default = exports.default = applyImage;

View File

@@ -0,0 +1,175 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.parseImage = exports.default = void 0;
var _plugin = _interopRequireDefault(require("../../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const escape = target => target.replace(/[\\;:()]/g, matched => `\\${matched[0].codePointAt(0).toString(16)} `);
const optionMatchers = new Map();
// The scale percentage for resize background
optionMatchers.set(/^(\d*\.)?\d+%$/, matches => ({
size: matches[0]
}));
// width and height
const normalizeLength = v => `${v}${/^(\d*\.)?\d+$/.test(v) ? 'px' : ''}`;
optionMatchers.set(/^w(?:idth)?:((?:\d*\.)?\d+(?:%|ch|cm|em|ex|in|mm|pc|pt|px)?|auto)$/, matches => ({
width: normalizeLength(matches[1])
}));
optionMatchers.set(/^h(?:eight)?:((?:\d*\.)?\d+(?:%|ch|cm|em|ex|in|mm|pc|pt|px)?|auto)$/, matches => ({
height: normalizeLength(matches[1])
}));
// 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?|hwb|(?:ok)?(?:lab|lch)|color)\((.*)\)$/);
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')]]
}));
/**
* Marpit image parse 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.
*
* @function parseImage
* @param {MarkdownIt} md markdown-it instance.
*/
function _parseImage(md) {
const {
process
} = md.core;
let refCount = 0;
const finalizeTokenAttr = (token, state) => {
// Apply finalization recursively to inline tokens
if (token.type === 'inline') {
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.trimStart(), state.md, state.env, newTokens);
token.children = newTokens;
}
}
};
md.core.process = state => {
try {
refCount += 1;
return process.call(md.core, state);
} finally {
refCount -= 1;
if (refCount === 0) {
// Apply finalization for every tokens
for (const token of state.tokens) finalizeTokenAttr(token, state);
}
}
};
md.inline.ruler2.push('marpit_parse_image', ({
tokens
}) => {
for (const token of tokens) {
if (token.type === 'image') {
// 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');
token.meta = token.meta || {};
token.meta.marpitImage = {
...(token.meta.marpitImage || {}),
url: url.toString(),
options
};
// Parse keyword through matchers
for (const opt of options) {
for (const [regexp, mergeFunc] of optionMatchers) {
if (opt.consumed) continue;
const matched = opt.content.match(regexp);
if (matched) {
opt.consumed = true;
token.meta.marpitImage = {
...token.meta.marpitImage,
...mergeFunc(matched, {
filters: [],
...token.meta.marpitImage
})
};
}
}
}
}
}
});
}
const parseImage = exports.parseImage = (0, _plugin.default)(_parseImage);
var _default = exports.default = parseImage;

View File

@@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.inlineSVG = exports.default = void 0;
var _split = require("../helpers/split");
var _wrap_tokens = require("../helpers/wrap_tokens");
var _plugin = _interopRequireDefault(require("../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit Inline SVG plugin.
*
* @function inlineSVG
* @param {MarkdownIt} md markdown-it instance.
*/
function _inlineSVG(md) {
const {
marpit
} = md;
md.core.ruler.after('marpit_directives_parse', 'marpit_inline_svg', state => {
if (!(marpit.inlineSVGOptions && marpit.inlineSVGOptions.enabled) || state.inlineMode) return;
const {
themeSet,
lastGlobalDirectives
} = marpit;
const w = themeSet.getThemeProp(lastGlobalDirectives.theme, 'widthPixel');
const h = themeSet.getThemeProp(lastGlobalDirectives.theme, 'heightPixel');
const newTokens = [];
for (const tokens of (0, _split.split)(state.tokens, t => t.meta && t.meta.marpitSlideElement === 1, true)) {
if (tokens.length > 0) {
for (const t of tokens) if (t.meta && t.meta.marpitSlideElement) delete t.meta.marpitSlideElement;
newTokens.push(...(0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_inline_svg', {
tag: 'svg',
'data-marpit-svg': '',
viewBox: `0 0 ${w} ${h}`,
open: {
meta: {
marpitSlideElement: 1
}
},
close: {
meta: {
marpitSlideElement: -1
}
}
}, (0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_inline_svg_content', {
tag: 'foreignObject',
width: w,
height: h
}, tokens)));
}
}
state.tokens = newTokens;
});
}
const inlineSVG = exports.inlineSVG = (0, _plugin.default)(_inlineSVG);
var _default = exports.default = inlineSVG;

73
node_modules/@marp-team/marpit/lib/markdown/slide.js generated vendored Normal file
View File

@@ -0,0 +1,73 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.slide = exports.defaultAnchorCallback = exports.default = void 0;
var _split = require("../helpers/split");
var _wrap_tokens = require("../helpers/wrap_tokens");
var _plugin = _interopRequireDefault(require("../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const defaultAnchorCallback = i => `${i + 1}`;
/**
* Marpit slide plugin.
*
* Split markdown-it tokens into the slides by horizontal rule. Each slides
* will be wrapped by section element.
*
* @function slide
* @param {MarkdownIt} md markdown-it instance.
* @param {Object} [opts]
* @param {Object} [opts.attributes] The `<section>` element attributes by
* key-value pairs.
* @param {(boolean|Marpit~AnchorCallback)} [opts.anchor=true] If true, assign
* the anchor with the page number starting from 1. You can customize anchor
* name by passing callback function.
*/
exports.defaultAnchorCallback = defaultAnchorCallback;
function _slide(md, opts = {}) {
const anchor = opts.anchor === undefined ? true : opts.anchor;
const anchorCallback = (() => {
if (typeof anchor === 'function') return anchor;
if (anchor) return defaultAnchorCallback;
return () => undefined;
})();
md.core.ruler.push('marpit_slide', state => {
if (state.inlineMode) return;
const splittedTokens = (0, _split.split)(state.tokens, t => t.type === 'hr' && t.level === 0, true);
const {
length: marpitSlideTotal
} = splittedTokens;
state.tokens = splittedTokens.reduce((arr, slideTokens, marpitSlide) => {
const firstHr = slideTokens[0] && slideTokens[0].type === 'hr' ? slideTokens[0] : undefined;
const mapTarget = firstHr || slideTokens.find(t => t.map);
return [...arr, ...(0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_slide', {
...(opts.attributes || {}),
tag: 'section',
id: anchorCallback(marpitSlide),
open: {
block: true,
meta: {
marpitSlide,
marpitSlideTotal,
marpitSlideElement: 1
},
map: mapTarget ? mapTarget.map : [0, 1]
},
close: {
block: true,
meta: {
marpitSlide,
marpitSlideTotal,
marpitSlideElement: -1
}
}
}, slideTokens.slice(firstHr ? 1 : 0))];
}, []);
});
}
const slide = exports.slide = (0, _plugin.default)(_slide);
var _default = exports.default = slide;

View File

@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.slideContainer = exports.default = void 0;
var _split = require("../helpers/split");
var _wrap_array = require("../helpers/wrap_array");
var _wrap_tokens = require("../helpers/wrap_tokens");
var _plugin = _interopRequireDefault(require("../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit slide container plugin.
*
* @function slideContainer
* @param {MarkdownIt} md markdown-it instance.
*/
function _slideContainer(md) {
const containers = (0, _wrap_array.wrapArray)(md.marpit.options.slideContainer);
if (!containers) return;
const target = [...containers].reverse();
md.core.ruler.push('marpit_slide_containers', state => {
if (state.inlineMode) return;
const newTokens = [];
for (const tokens of (0, _split.split)(state.tokens, t => t.meta && t.meta.marpitSlideElement === 1, true)) {
if (tokens.length > 0) newTokens.push(...target.reduce((slides, conts) => (0, _wrap_tokens.wrapTokens)(state.Token, 'marpit_slide_containers', conts, slides), tokens));
}
state.tokens = newTokens;
});
}
const slideContainer = exports.slideContainer = (0, _plugin.default)(_slideContainer);
var _default = exports.default = slideContainer;

View File

@@ -0,0 +1,128 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.assign = void 0;
var _postcss = _interopRequireDefault(require("postcss"));
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
var _plugin = _interopRequireDefault(require("../../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const uniqKeyChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const uniqKeyCharsLength = uniqKeyChars.length;
const generateScopeAttr = uniqKey => `data-marpit-scope-${uniqKey}`;
const generateUniqKey = (length = 8) => {
let ret = '';
for (let i = 0; i < length; i += 1) ret += uniqKeyChars[Math.floor(Math.random() * uniqKeyCharsLength)];
return ret;
};
const injectScopePostCSSplugin = (0, _postcss_plugin.default)('marpit-style-assign-postcss-inject-scope', (key, keyframeSet) => css => css.each(function inject(node) {
const {
type,
name
} = node;
if (type === 'atrule') {
if (name === 'keyframes' && node.params) {
keyframeSet.add(node.params);
node.params += `-${key}`;
} else if (name === 'media' || name === 'supports') {
node.each(inject);
}
} else if (type === 'rule') {
node.selectors = node.selectors.map(selector => {
const injectSelector = /^section(?![\w-])/.test(selector) ? selector.slice(7) : ` ${selector}`;
return `section[${generateScopeAttr(key)}]${injectSelector}`;
});
}
}));
const scopeKeyframesPostCSSPlugin = (0, _postcss_plugin.default)('marpit-style-assign-postcss-scope-keyframes', (key, keyframeSet) => css => {
if (keyframeSet.size === 0) return;
const keyframeMatcher = new RegExp(`\\b(${[...keyframeSet.values()].map(kf => kf.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&')).join('|')})(?!\\()\\b`);
css.walkDecls(/^animation(-name)?$/, decl => {
decl.value = decl.value.replace(keyframeMatcher, kf => `${kf}-${key}`);
});
});
/**
* Marpit style assign plugin.
*
* Assign style global directive and parsed styles to Marpit instance's
* `lastStyles' property.
*
* @function assign
* @param {MarkdownIt} md markdown-it instance.
*/
function _assign(md) {
const {
marpit
} = md;
md.core.ruler.after('marpit_slide', 'marpit_style_assign', state => {
if (state.inlineMode) return;
const directives = marpit.lastGlobalDirectives || {};
marpit.lastStyles = directives.style ? [directives.style] : [];
let current;
for (const token of state.tokens) {
if (token.meta && token.meta.marpitSlideElement === 1) {
current = token;
} else if (token.meta && token.meta.marpitSlideElement === -1) {
if (current.meta && current.meta.marpitStyleScoped) {
const {
key,
keyframeSet,
styles
} = current.meta.marpitStyleScoped;
// Rewrite keyframes name in animation decls
const processor = (0, _postcss.default)([scopeKeyframesPostCSSPlugin(key, keyframeSet)]);
current.meta.marpitStyleScoped.styles = styles.map(style => {
try {
return processor.process(style).css;
} catch {
return style;
}
});
// Assign scoped styles
marpit.lastStyles.push(...current.meta.marpitStyleScoped.styles);
}
current = undefined;
} else if (token.type === 'marpit_style') {
const {
content
} = token;
// Scoped style
const {
marpitStyleScoped
} = token.meta || {};
if (current && marpitStyleScoped) {
current.meta = current.meta || {};
current.meta.marpitStyleScoped = current.meta.marpitStyleScoped || {};
let {
key
} = current.meta.marpitStyleScoped;
if (!key) {
key = generateUniqKey();
current.meta.marpitStyleScoped.key = key;
current.attrSet(generateScopeAttr(key), '');
}
current.meta.marpitStyleScoped.styles = current.meta.marpitStyleScoped.styles || [];
current.meta.marpitStyleScoped.keyframeSet = current.meta.marpitStyleScoped.keyframeSet || new Set();
const processor = (0, _postcss.default)([injectScopePostCSSplugin(key, current.meta.marpitStyleScoped.keyframeSet)]);
try {
current.meta.marpitStyleScoped.styles.push(processor.process(content).css);
} catch {
// No ops
}
} else if (content) {
// Global style
marpit.lastStyles.push(content);
}
}
}
});
}
const assign = exports.assign = (0, _plugin.default)(_assign);
var _default = exports.default = assign;

View File

@@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.parse = exports.default = void 0;
var _plugin = _interopRequireDefault(require("../../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const styleMatcher = /<style([\s\S]*?)>([\s\S]*?)<\/style>/i;
const styleMatcherOpening = /^<style(?=(\s|>|$))/i;
const styleMatcherClosing = /<\/style>/i;
const styleMatcherScoped = /\bscoped\b/i;
/**
* Marpit style parse plugin.
*
* Parse `<style>` elements as the hidden `marpit_style` token. The parsed style
* will use in {@link ThemeSet#pack} to append the style additionally.
*
* `<style>` elements will strip regardless of html setting provided by
* markdown-it.
*
* @function parse
* @param {MarkdownIt} md markdown-it instance.
*/
function _parse(md) {
/**
* Based on markdown-it html_block rule
* https://github.com/markdown-it/markdown-it/blob/master/lib/rules_block/html_block.js
*/
md.block.ruler.before('html_block', 'marpit_style_parse', (state, startLine, endLine, silent) => {
// Fast fail
let pos = state.bMarks[startLine] + state.tShift[startLine];
if (state.src.charCodeAt(pos) !== 0x3c) return false;
let max = state.eMarks[startLine];
let line = state.src.slice(pos, max);
// Match to opening element
if (!styleMatcherOpening.test(line)) return false;
if (silent) return true;
// Parse ending element
let nextLine = startLine + 1;
if (!styleMatcherClosing.test(line)) {
while (nextLine < endLine) {
if (state.sCount[nextLine] < state.blkIndent) break;
pos = state.bMarks[nextLine] + state.tShift[nextLine];
max = state.eMarks[nextLine];
line = state.src.slice(pos, max);
nextLine += 1;
if (styleMatcherClosing.test(line)) break;
}
}
state.line = nextLine;
// Create token
const token = state.push('marpit_style', '', 0);
token.map = [startLine, nextLine];
token.markup = state.getLines(startLine, nextLine, state.blkIndent, true);
token.meta = {};
token.hidden = true;
const matchedContent = styleMatcher.exec(token.markup);
if (matchedContent) {
const [, attrStr, contentStr] = matchedContent;
token.content = contentStr.trim();
token.meta.marpitStyleScoped = styleMatcherScoped.test(attrStr.trim());
}
return true;
});
}
const parse = exports.parse = (0, _plugin.default)(_parse);
var _default = exports.default = parse;

59
node_modules/@marp-team/marpit/lib/markdown/sweep.js generated vendored Normal file
View File

@@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.sweep = exports.default = void 0;
var _plugin = _interopRequireDefault(require("../plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit sweep plugin.
*
* Hide blank paragraphs. For better support of the background image syntax and
* directives through HTML comment, Marpit will sweep paragraphs included only
* whitespace by setting `hidden: true`.
*
* It also sweep the inline token marked as hidden forcely. Please notice that
* plugins executed after this cannot handle hidden inline tokens.
*
* @function sweep
* @param {MarkdownIt} md markdown-it instance.
*/
function _sweep(md) {
md.core.ruler.after('inline', 'marpit_sweep', state => {
if (state.inlineMode) return;
for (const token of state.tokens) {
if (token.type === 'html_block' && token.content.match(/^\s*$/) || token.type === 'inline' && token.children.filter(t => !(t.hidden || t.type === 'softbreak')).every(t => t.type === 'text' && t.content.match(/^\s*$/))) token.hidden = true;
}
});
md.core.ruler.push('marpit_sweep_paragraph', state => {
if (state.inlineMode) return;
const current = {
open: [],
tokens: {}
};
for (const token of state.tokens) {
if (token.type === 'inline' && token.hidden) {
// markdown-it's "inline" type is not following a `hidden` flag. Marpit
// changes the token type to unique name to hide token forcely.
token.type = 'marpit_hidden_inline';
} else if (token.type === 'paragraph_open') {
current.open.push(token);
current.tokens[token] = [];
} else if (token.type === 'paragraph_close') {
const openToken = current.open.pop();
if (current.tokens[openToken].every(t => t.hidden)) {
openToken.hidden = true;
token.hidden = true;
}
} else {
const len = current.open.length;
if (len > 0) current.tokens[current.open[len - 1]].push(token);
}
}
});
}
const sweep = exports.sweep = (0, _plugin.default)(_sweep);
var _default = exports.default = sweep;

291
node_modules/@marp-team/marpit/lib/marpit.js generated vendored Normal file
View File

@@ -0,0 +1,291 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _markdownIt = _interopRequireDefault(require("markdown-it"));
var _element = require("./element");
var _wrap_array = require("./helpers/wrap_array");
var _background_image = _interopRequireDefault(require("./markdown/background_image"));
var _collect = _interopRequireDefault(require("./markdown/collect"));
var _comment = _interopRequireDefault(require("./markdown/comment"));
var _container = _interopRequireDefault(require("./markdown/container"));
var _apply = _interopRequireDefault(require("./markdown/directives/apply"));
var _parse = _interopRequireDefault(require("./markdown/directives/parse"));
var _fragment = _interopRequireDefault(require("./markdown/fragment"));
var _header_and_footer = _interopRequireDefault(require("./markdown/header_and_footer"));
var _heading_divider = _interopRequireDefault(require("./markdown/heading_divider"));
var _image = _interopRequireDefault(require("./markdown/image"));
var _inline_svg = _interopRequireDefault(require("./markdown/inline_svg"));
var _slide = _interopRequireWildcard(require("./markdown/slide"));
var _slide_container = _interopRequireDefault(require("./markdown/slide_container"));
var _assign = _interopRequireDefault(require("./markdown/style/assign"));
var _parse2 = _interopRequireDefault(require("./markdown/style/parse"));
var _sweep = _interopRequireDefault(require("./markdown/sweep"));
var _theme_set = _interopRequireDefault(require("./theme_set"));
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const defaultOptions = {
anchor: true,
container: _element.marpitContainer,
cssContainerQuery: false,
cssNesting: true,
headingDivider: false,
lang: undefined,
looseYAML: false,
markdown: undefined,
printable: true,
slideContainer: false,
inlineSVG: false
};
const defaultInlineSVGOptions = {
enabled: true,
backdropSelector: true
};
/**
* Parse Marpit Markdown and render to the slide HTML/CSS.
*/
class Marpit {
#markdown = undefined;
/**
* @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.
*/
/**
* Convert slide page index into anchor string.
*
* @callback Marpit~AnchorCallback
* @param {number} index Slide page index, beginning from zero.
* @returns {string} The text of anchor for id attribute, without prefix `#`.
*/
/**
* Create a Marpit instance.
*
* @param {Object} [opts]
* @param {boolean|Marpit~AnchorCallback} [opts.anchor=true] Set the page
* number as anchor of each slides (`id` attribute). You can customize the
* anchor text by defining a custom callback function.
* @param {false|Element|Element[]}
* [opts.container={@link module:element.marpitContainer}] Container
* element(s) wrapping whole slide deck.
* @param {boolean|string|string[]} [opts.cssContainerQuery=false] Set whether
* to enable CSS container query (`@container`). By setting the string or
* string array, you can specify the container name(s) for the CSS
* container.
* @param {boolean} [opts.cssNesting=false] Enable CSS nesting support. If
* enabled, Marpit will try to make flatten the CSS with nested rules
* before rendering, to make it compatible with Marpit preprocessings.
* @param {false|number|number[]} [opts.headingDivider=false] Start a new
* slide page at before of headings. it would apply to headings whose
* larger than or equal to the specified level if a number is given, or
* ONLY specified levels if a number array.
* @param {string} [opts.lang] Set the default `lang` attribute of each slide.
* It can override by `lang` global directive in the Markdown.
* @param {boolean} [opts.looseYAML=false] Allow loose YAML parsing in
* built-in directives, and custom directives defined in current instance.
* @param {MarkdownIt|string|Object|Array} [opts.markdown] An instance of
* markdown-it or its constructor option(s) for wrapping. Marpit will
* create its instance based on CommonMark when omitted.
* @param {boolean} [opts.printable=true] Make style printable to PDF.
* @param {false|Element|Element[]} [opts.slideContainer] Container element(s)
* wrapping each slide sections.
* @param {boolean|Marpit~InlineSVGOptions} [opts.inlineSVG=false] Wrap each
* slide sections by inline SVG. _(Experimental)_
*/
constructor(opts = {}) {
/**
* The current options for this instance.
*
* This property is read-only and marked as immutable. You cannot change the
* value of options after creating instance.
*
* @member {Object} options
* @memberOf Marpit#
* @readonly
*/
Object.defineProperty(this, 'options', {
enumerable: true,
value: Object.freeze({
...defaultOptions,
...opts
})
});
/**
* Definitions of the custom directive.
*
* It has the assignable `global` and `local` object. They have consisted of
* the directive name as a key, and parser function as a value. The parser
* should return the validated object for updating meta of markdown-it
* token.
*
* @member {Object} customDirectives
* @memberOf Marpit#
* @readonly
*/
Object.defineProperty(this, 'customDirectives', {
value: Object.seal({
global: Object.create(null),
local: Object.create(null)
})
});
/**
* @type {ThemeSet}
*/
this.themeSet = new _theme_set.default({
cssNesting: this.options.cssNesting
});
this.applyMarkdownItPlugins((() => {
// Use CommonMark based instance by default
if (!this.options.markdown) return new _markdownIt.default('commonmark');
// Detect markdown-it features
if (typeof this.options.markdown === 'object' && typeof this.options.markdown.parse === 'function' && typeof this.options.markdown.renderer === 'object') return this.options.markdown;
// Create instance with passed argument(s)
return new _markdownIt.default(...(0, _wrap_array.wrapArray)(this.options.markdown));
})());
}
/**
* @type {MarkdownIt}
*/
get markdown() {
return this.#markdown;
}
set markdown(md) {
if (this.#markdown && this.#markdown.marpit) delete this.#markdown.marpit;
this.#markdown = md;
if (md) {
Object.defineProperty(md, 'marpit', {
configurable: true,
value: this
});
}
}
/** @private */
applyMarkdownItPlugins(md) {
this.markdown = md;
const slideAnchorCallback = (...args) => {
const {
anchor
} = this.options;
if (typeof anchor === 'function') return anchor(...args);
if (anchor) return (0, _slide.defaultAnchorCallback)(...args);
return undefined;
};
md.use(_comment.default).use(_parse2.default).use(_slide.default, {
anchor: slideAnchorCallback
}).use(_parse.default).use(_apply.default).use(_header_and_footer.default).use(_heading_divider.default).use(_slide_container.default).use(_container.default).use(_inline_svg.default).use(_image.default).use(_background_image.default).use(_sweep.default).use(_assign.default).use(_fragment.default).use(_collect.default);
}
/**
* @typedef {Object} Marpit~RenderResult
* @property {string|string[]} html Rendered HTML.
* @property {string} css Rendered CSS.
* @property {string[][]} comments Parsed HTML comments per slide pages,
* excepted YAML for directives. It would be useful for presenter notes.
*/
/**
* Render Markdown into HTML and CSS string.
*
* @param {string} markdown A Markdown string.
* @param {Object} [env={}] Environment object for passing to markdown-it.
* @param {boolean} [env.htmlAsArray=false] Output rendered HTML as array per
* slide.
* @returns {Marpit~RenderResult} An object of rendering result.
*/
render(markdown, env = {}) {
return {
html: this.renderMarkdown(markdown, env),
css: this.renderStyle(this.lastGlobalDirectives.theme),
comments: this.lastComments
};
}
/**
* Render Markdown by using `markdownIt#render`.
*
* This method is for internal. You can override this method if you have to
* render with customized way.
*
* @private
* @param {string} markdown A Markdown string.
* @param {Object} [env] Environment object for passing to markdown-it.
* @param {boolean} [env.htmlAsArray=false] Output rendered HTML as array per
* slide.
* @returns {string|string[]} The result string(s) of rendering Markdown.
*/
renderMarkdown(markdown, env = {}) {
const tokens = this.markdown.parse(markdown, env);
if (env.htmlAsArray) {
return this.lastSlideTokens.map(slideTokens => this.markdown.renderer.render(slideTokens, this.markdown.options, env));
}
return this.markdown.renderer.render(tokens, this.markdown.options, env);
}
/**
* Render style by using `themeSet#pack`.
*
* This method is for internal.
*
* @private
* @param {string|undefined} theme Theme name.
* @returns {string} The result string of rendering style.
*/
renderStyle(theme) {
return this.themeSet.pack(theme, this.themeSetPackOptions());
}
/** @private */
themeSetPackOptions() {
return {
after: this.lastStyles ? this.lastStyles.join('\n') : undefined,
containers: [...(0, _wrap_array.wrapArray)(this.options.container), ...(0, _wrap_array.wrapArray)(this.options.slideContainer)],
containerQuery: this.options.cssContainerQuery,
inlineSVG: this.inlineSVGOptions,
printable: this.options.printable
};
}
/**
* @private
* @returns {Marpit~InlineSVGOptions} Options for inline SVG.
*/
get inlineSVGOptions() {
if (typeof this.options.inlineSVG === 'object') {
return {
...defaultInlineSVGOptions,
...this.options.inlineSVG
};
}
return {
...defaultInlineSVGOptions,
enabled: !!this.options.inlineSVG
};
}
/**
* Load the specified markdown-it plugin with given parameters.
*
* @param {Function} plugin markdown-it plugin.
* @param {...*} params Params to pass into plugin.
* @returns {Marpit} The called {@link Marpit} instance for chainable.
*/
use(plugin, ...params) {
plugin.call(this.markdown, this.markdown, ...params);
return this;
}
}
var _default = exports.default = Marpit;

47
node_modules/@marp-team/marpit/lib/plugin.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
"use strict";
/** @module */
/**
* Create Marpit plugin.
*
* Generate Marpit plugin from passed markdown-it plugin. Marpit plugin needs
* markdown-it instance with `marpit` member.
*
* @example
* import { marpitPlugin } from '@marp-team/marpit/plugin'
*
* export default marpitPlugin((md) => {
* // Compatible with markdown-it plugin
* md.renderer.rules.your_rule = (tokens, idx, options, env, self) => {
* // ...
* }
*
* // And accessible to Marpit instance as `md.marpit`
* const { marpit } = md
*
* marpit.customDirectives.local.yourDirective = (value) => {
* return { yourDirective: value }
* }
* })
*
* @function marpitPlugin
* @param {Function} plugin Base plugin for markdown-it.
* @returns {Function} Generated Marpit plugin.
*/
function marpitPlugin(plugin) {
return function (md, ...args) {
if (md.marpit) return plugin.call(this, md, ...args);
throw new Error('Marpit plugin has detected incompatible markdown-it instance.');
};
}
Object.defineProperty(marpitPlugin, '__esModule', {
value: true
});
Object.defineProperty(marpitPlugin, 'default', {
value: marpitPlugin
});
Object.defineProperty(marpitPlugin, 'marpitPlugin', {
value: marpitPlugin
});
module.exports = marpitPlugin;

View File

@@ -0,0 +1,91 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.advancedBackground = void 0;
var _postcss_plugin = _interopRequireDefault(require("../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit PostCSS advanced background plugin.
*
* Append style to suport the advanced background.
*
* @function advancedBackground
*/
const advancedBackground = exports.advancedBackground = (0, _postcss_plugin.default)('marpit-postcss-advanced-background', () => css => {
css.last.after(`
section[data-marpit-advanced-background="background"] {
columns: initial !important;
display: block !important;
padding: 0 !important;
}
section[data-marpit-advanced-background="background"]::before,
section[data-marpit-advanced-background="background"]::after,
section[data-marpit-advanced-background="content"]::before,
section[data-marpit-advanced-background="content"]::after {
display: none !important;
}
section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container] {
all: initial;
display: flex;
flex-direction: row;
height: 100%;
overflow: hidden;
width: 100%;
}
section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction="vertical"] {
flex-direction: column;
}
section[data-marpit-advanced-background="background"][data-marpit-advanced-background-split] > div[data-marpit-advanced-background-container] {
width: var(--marpit-advanced-background-split, 50%);
}
section[data-marpit-advanced-background="background"][data-marpit-advanced-background-split="right"] > div[data-marpit-advanced-background-container] {
margin-left: calc(100% - var(--marpit-advanced-background-split, 50%));
}
section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container] > figure {
all: initial;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
flex: auto;
margin: 0;
}
section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container] > figure > figcaption {
position: absolute;
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
white-space: nowrap;
width: 1px;
}
section[data-marpit-advanced-background="content"],
section[data-marpit-advanced-background="pseudo"] {
background: transparent !important;
}
section[data-marpit-advanced-background="pseudo"],
:marpit-container > svg[data-marpit-svg] > foreignObject[data-marpit-advanced-background="pseudo"] {
pointer-events: none !important;
}
section[data-marpit-advanced-background-split] {
width: 100%;
height: 100%;
}
`.trim());
});
var _default = exports.default = advancedBackground;

View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.postprocess = exports.default = exports.containerQuery = void 0;
var _cssesc = _interopRequireDefault(require("cssesc"));
var _postcss_plugin = _interopRequireDefault(require("../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const reservedNames = ['none', 'inherit', 'initial', 'revert', 'revert-layer', 'unset'];
const marpitContainerQueryPseudoMatcher = /\bsection:marpit-container-query\b/g;
/**
* Marpit PostCSS container query plugin.
*
* Add support of container queries for child elements of the `section` element.
* (`@container` at-rule, and `cqw` `cqh` `cqi` `cqb` `cqmin` `cqmax` units)
*
* @function meta
* @param {string|string[]} [containerName=undefined] Container name
* @param {boolean} [escape=true] Set whether to escape container name
*/
const containerQuery = exports.containerQuery = (0, _postcss_plugin.default)('marpit-postcss-container-query', (containerName = undefined, escape = true) => css => {
const containerNames = (Array.isArray(containerName) ? containerName : [containerName]).filter(name => name && !reservedNames.includes(name));
const containerNameDeclaration = containerNames.length > 0 ? `\n container-name: ${containerNames.map(name => escape ? (0, _cssesc.default)(name.toString(), {
isIdentifier: true
}) : name.toString()).join(' ')};` : '';
const style = `
section:marpit-container-query {
container-type: size;${containerNameDeclaration}
}
`.trim();
if (css.first) {
css.first.before(style);
} else {
css.append(style);
}
});
const postprocess = exports.postprocess = (0, _postcss_plugin.default)('marpit-postcss-container-query-postprocess', () => css => css.walkRules(marpitContainerQueryPseudoMatcher, rule => {
rule.selectors = rule.selectors.map(selector => selector.replace(marpitContainerQueryPseudoMatcher, ':where(section)'));
}));
var _default = exports.default = containerQuery;

View File

@@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.importHoisting = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit PostCSS import hoisting plugin.
*
* Hoist `@charset` and `@import` at-rule to the beginning of CSS. Marpit is
* manipulating CSS with many PostCSS plugins, so sometimes a few at-rules
* cannot keep specification.
*
* This plugin takes care of hoisting for invalid at-rules.
*
* @function importHoisting
*/
const importHoisting = exports.importHoisting = (0, _postcss_plugin.default)('marpit-postcss-import-hoisting', () => css => {
const hoisted = {
charset: undefined,
imports: []
};
css.walkAtRules(rule => {
if (rule.name === 'charset') {
rule.remove();
if (!hoisted.charset) hoisted.charset = rule;
} else if (rule.name === 'import') {
hoisted.imports.push(rule.remove());
}
});
const {
first
} = css
// Hoist at-rules
;
[hoisted.charset, ...hoisted.imports].filter(r => r).forEach((rule, idx) => {
// Strip whitespace from the beginning of first at-rule
const prependRule = idx === 0 ? rule.clone({
raws: {
before: undefined
}
}) : rule;
first.before(prependRule);
});
});
var _default = exports.default = importHoisting;

View File

@@ -0,0 +1,80 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.importParse = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* @typedef {object} ImportMeta
* @prop {AtRule} node The at-rule node parsed by PostCSS.
* @prop {string} value The specified value.
*/
/**
* Marpit PostCSS import parse plugin.
*
* Parse `@import` and `@import-theme` rules that specify a plain string.
*
* The `@import` rule for Marpit theme follows CSS spec. It must precede all
* other statements. (excepted `@charset`)
*
* When you are using CSS preprocessors like Sass, `@import` would resolve path
* in compiling and would be lost definition. So you can use `@import-theme`
* rule alternatively.
*
* A specification of `@import-theme` has a bit different from `@import`. You
* can place `@import-theme` rule at any in the CSS root, and the content of
* imported theme will always append to the beginning of CSS.
*
* @function importParse
*/
const importParse = exports.importParse = (0, _postcss_plugin.default)('marpit-postcss-import-parse', () => (css, {
result
}) => {
const imports = {
import: [],
importTheme: []
};
let allowImport = true;
css.walk(node => {
if (node.type === 'atrule') {
const push = target => {
const [quote] = node.params;
if (quote !== '"' && quote !== "'") return;
const splitedValue = node.params.slice(1).split(quote);
let value = '';
splitedValue.every(v => {
if (v.endsWith('\\')) {
value = `${value}${v.slice(0, -1)}${quote}`;
return true;
}
value = `${value}${v}`;
return false;
});
node.marpitImportParse = value;
target.push({
node,
value
});
};
if (allowImport) {
if (node.name === 'import') {
push(imports.import);
} else if (node.name !== 'charset') {
allowImport = false;
}
}
if (node.name === 'import-theme' && node.parent.type === 'root') {
push(imports.importTheme);
}
} else if (node.type !== 'comment') {
allowImport = false;
}
});
result.marpitImport = [...imports.importTheme, ...imports.import];
});
var _default = exports.default = importParse;

View File

@@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.importReplace = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
var _parse = _interopRequireDefault(require("./parse"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit PostCSS import replace plugin.
*
* Replace parsed `@import` / `@import-theme` rules.
*
* Please see {@link module:postcss/import/parse} about the specification of
* each syntax.
*
* @function importReplace
* @param {ThemeSet} themeSet ThemeSet instance.
*/
const importReplace = (themeSet, importedThemes = []) => (0, _postcss_plugin.default)('marpit-postcss-import-replace', () => ({
plugins: [(0, _parse.default)(), (0, _postcss_plugin.default)('marpit-postcss-import-replace-processor', () => (css, {
postcss
}) => {
const prepends = [];
css.walk(node => {
const name = node.marpitImportParse;
if (name) {
const theme = themeSet.get(name);
if (theme) {
if (importedThemes.includes(name)) throw new Error(`Circular "${name}" theme import is detected.`);
const processed = postcss([importReplace(themeSet, [...importedThemes, name])]).process(theme.css);
if (node.name === 'import') {
node.replaceWith(processed.root);
} else {
node.remove();
prepends.unshift(processed.root);
}
}
}
});
for (const root of prepends) css.first.before(root);
})()]
}));
exports.importReplace = importReplace;
var _default = exports.default = importReplace;

View File

@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.importSuppress = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
var _parse = _interopRequireDefault(require("./parse"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit PostCSS import suppress plugin.
*
* Comment out `@import` / `@import-theme` rules that have imported theme.
*
* This plugin is useful to prevent the inline style's rolled-up theme import by
* unexpected order.
*
* @function importSuppress
* @param {ThemeSet} themeSet ThemeSet instance.
*/
const importSuppress = exports.importSuppress = (0, _postcss_plugin.default)('marpit-postcss-import-suppress', themeSet => ({
plugins: [(0, _parse.default)(), (0, _postcss_plugin.default)('marpit-postcss-import-suppress', () => css => {
css.walk(node => {
if (node.marpitImportParse && themeSet.has(node.marpitImportParse)) node.replaceWith(`${node.raw('before')}/* ${node.toString()}; */`);
});
})()]
}));
var _default = exports.default = importSuppress;

37
node_modules/@marp-team/marpit/lib/postcss/meta.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.meta = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit PostCSS meta plugin.
*
* Parse CSS comment written in the format of `@key value`.
*
* @function meta
* @param {Object} [opts]
* @param {Object} [opts.metaType] An object for defined types for metadata.
*/
const meta = exports.meta = (0, _postcss_plugin.default)('marpit-postcss-meta', (opts = {}) => (css, {
result
}) => {
const metaType = opts.metaType || {};
result.marpitMeta = result.marpitMeta || {};
css.walkComments(comment => {
comment.text.slice(0).replace(/^[*!\s]*@([\w-]+)\s+(.+)$/gim, (_, metaName, value) => {
if (metaType[metaName] === Array) {
// Array meta
result.marpitMeta[metaName] = [...(result.marpitMeta[metaName] || []), value];
} else {
// String meta (default)
result.marpitMeta[metaName] = value;
}
});
});
});
var _default = exports.default = meta;

44
node_modules/@marp-team/marpit/lib/postcss/nesting.js generated vendored Normal file
View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.nesting = exports.default = void 0;
var _postcssIsPseudoClass = _interopRequireDefault(require("@csstools/postcss-is-pseudo-class"));
var _postcssNesting = _interopRequireDefault(require("postcss-nesting"));
var _postcss_plugin = _interopRequireDefault(require("../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const {
Rule: applyPostCSSNesting
} = (0, _postcssNesting.default)();
const matcher = /:is\((?:section|:root)\b/;
const nesting = exports.nesting = (0, _postcss_plugin.default)('marpit-postcss-nesting', () => (root, helpers) => {
const rules = [];
// Note: Use walk instead of walkRules to include nested rules
root.walk(node => {
if (node.type !== 'rule') return;
rules.push(node);
node.__marpitNestingOriginalSelector = node.selector;
});
// Apply postcss-nesting
root.walkRules(rule => applyPostCSSNesting(rule, helpers));
const {
Rule: applyPostCSSIsPseudoClass
} = (0, _postcssIsPseudoClass.default)({
onComplexSelector: 'warning'
}).prepare();
for (const rule of rules) {
if (rule.__marpitNestingOriginalSelector !== rule.selector && matcher.test(rule.selector)) {
// Apply postcss-is-pseudo-class only to transformed rules that is
// including `:is() selector starting from `section` element or `:root`
// pseudo-class
applyPostCSSIsPseudoClass(rule, helpers);
}
delete rule.__marpitNestingOriginalSelector;
}
});
var _default = exports.default = nesting;

View File

@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.pagination = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit PostCSS pagination plugin.
*
* Marpit uses `section::after` to show the pagination on each slide. It defines
* in the scaffold theme.
*
* This plugin will comment out a `content` declaration defined in any
* `section::after` of the root, to prevent override the defined attribute for
* paginating.
*
* @function pagination
*/
const pagination = exports.pagination = (0, _postcss_plugin.default)('marpit-postcss-pagination', () => css => {
css.walkRules(rule => {
if (rule.selectors.some(selector => /^section(?![\w-])[^\s>+~]*::?after$/.test(selector.replace(/\[.*?\]/g, '')))) rule.walkDecls('content', decl => {
if (!decl.value.includes('attr(data-marpit-pagination)')) decl.replaceWith(`${decl.raw('before')}/* ${decl.toString()}; */`);
});
});
});
var _default = exports.default = pagination;

View File

@@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.printable = exports.postprocess = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const marpitPrintContainerStyle = `
html, body {
background-color: #fff;
margin: 0;
page-break-inside: avoid;
break-inside: avoid-page;
}
`.trim();
/**
* Marpit PostCSS printable plugin.
*
* Make printable slide deck as PDF.
*
* @param {Object} opts
* @param {string} opts.width
* @param {string} opts.height
* @function printable
*/
const printable = exports.printable = (0, _postcss_plugin.default)('marpit-postcss-printable', opts => css => {
css.walkAtRules('media', rule => {
if (rule.params === 'marpit-print') rule.remove();
});
css.first.before(`
@page {
size: ${opts.width} ${opts.height};
margin: 0;
}
@media marpit-print {
section {
page-break-before: always;
break-before: page;
}
section, section * {
-webkit-print-color-adjust: exact !important;
animation-delay: 0s !important;
animation-duration: 0s !important;
color-adjust: exact !important;
print-color-adjust: exact !important;
transition: none !important;
}
:marpit-container > svg[data-marpit-svg] {
display: block;
height: 100vh;
width: 100vw;
}
}
`.trim());
});
/**
* The post-process PostCSS plugin of Marpit printable plugin.
*
* @function postprocess
*/
const postprocess = exports.postprocess = (0, _postcss_plugin.default)('marpit-postcss-printable-postprocess', () => css => css.walkAtRules('media', rule => {
if (rule.params !== 'marpit-print') return;
rule.params = 'print';
rule.first.before(marpitPrintContainerStyle);
}));
var _default = exports.default = printable;

View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.pseudoSelectorPrepend = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit PostCSS pseudo selector prepending plugin.
*
* Prepend `:marpit-container > :marpit-slide` pseudo selector to each selector
* of Marpit theme CSS for modulized styling.
*
* @function pseudoSelectorPrepend
*/
const pseudoSelectorPrepend = exports.pseudoSelectorPrepend = (0, _postcss_plugin.default)('marpit-postcss-pseudo-selector-prepend', () => css => css.walkRules(rule => {
const {
type,
name
} = rule.parent || {};
if (type === 'atrule' && name === 'keyframes') return;
rule.selectors = rule.selectors.map(selector => {
if (/^section(?![\w-])/.test(selector)) return `:marpit-container > :marpit-slide${selector.slice(7)}`;
if (selector.startsWith(':marpit-container')) return selector;
return `:marpit-container > :marpit-slide ${selector}`;
});
}));
var _default = exports.default = pseudoSelectorPrepend;

View File

@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.pseudoSelectorReplace = exports.default = void 0;
var _cssesc = _interopRequireDefault(require("cssesc"));
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
var _wrap_array = require("../../helpers/wrap_array");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const buildSelector = elms => elms.map(e => {
const classes = new Set((e.class || '').split(/\s+/).filter(c => c));
let element = [e.tag, ...classes].map(c => (0, _cssesc.default)(c, {
isIdentifier: true
})).join('.');
if (e.id) element += `#${(0, _cssesc.default)(e.id, {
isIdentifier: true
})}`;
return element;
}).join(' > ');
/**
* Marpit PostCSS pseudo selector replace plugin.
*
* Replace `:marpit-container` and `:marpit-slide` pseudo selector into
* container element(s).
*
* @function pseudoSelectorReplace
* @param {Element|Element[]} [elements] Container elements
* @param {Element|Element[]} [slideElements={ tag: 'section' }] Slide elements
*/
const pseudoSelectorReplace = exports.pseudoSelectorReplace = (0, _postcss_plugin.default)('marpit-postcss-pseudo-selector-replace', (elements, slideElements = {
tag: 'section'
}) => {
const container = buildSelector([...(0, _wrap_array.wrapArray)(elements)]);
const section = buildSelector([...(0, _wrap_array.wrapArray)(slideElements)]);
return css => css.walkRules(rule => {
rule.selectors = rule.selectors.map(selector => selector.replace(/:marpit-container(?![\w-])/g, container).replace(/:marpit-slide(?![\w-])/g, section).replace(/^\s*>\s*/, ''));
});
});
var _default = exports.default = pseudoSelectorReplace;

View File

@@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.rootFontSizeCustomProp = exports.rootFontSize = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const rootFontSizeCustomProp = exports.rootFontSizeCustomProp = '--marpit-root-font-size';
/**
* Marpit PostCSS root font size plugin.
*
* Inject CSS variable based on the root slide container `section` for correct
* calculation of `rem` unit in the context of Marpit.
*
* @function rootFontSize
*/
const rootFontSize = exports.rootFontSize = (0, _postcss_plugin.default)('marpit-postcss-root-font-size', () => (css, postcss) => css.walkRules(rule => {
const injectSelector = new Set();
for (const selector of rule.selectors) {
// Detect whether the selector is targeted to section
const parentSelectors = selector.split(/(\s+|\s*[>~+]\s*)/);
const targetSelector = parentSelectors.pop();
const delimiterMatched = targetSelector.match(/[.:#[]/);
const target = delimiterMatched ? targetSelector.slice(0, delimiterMatched.index) : targetSelector;
if (target === 'section' || target.endsWith('*') || target === '') {
// Generate selector for injection
injectSelector.add([...parentSelectors, target === 'section' ? 'section' : ':marpit-container > :marpit-slide section',
// Universal selector is targeted to the children `section` of root `section`
delimiterMatched ? targetSelector.slice(delimiterMatched.index) : ''].join(''));
}
}
if (injectSelector.size === 0) return;
// Inject CSS variable
const injectRule = postcss.rule({
selectors: [...injectSelector.values()]
});
rule.walkDecls('font-size', decl => {
injectRule.append(decl.clone({
prop: rootFontSizeCustomProp
}));
});
if (injectRule.nodes.length > 0) rule.parent.insertAfter(rule, injectRule);
}));
var _default = exports.default = rootFontSize;

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.rootIncreasingSpecificity = exports.pseudoClass = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const pseudoClass = exports.pseudoClass = ':marpit-root';
const matcher = new RegExp(`\\b(?:section)?${pseudoClass}\\b`, 'g');
/**
* Marpit PostCSS root increasing specificity plugin.
*
* Replace specific pseudo-class selector to `:where(section):not([\20 root])`,
* to increase specificity. `:marpit-root` is always added to `section` selector
* by root replace plugin so `:where(section):not([\20 root])` must always match
* too (HTML does not allow U+0020 SPACE in the attribute name.).
*
* @function rootIncreasingSpecificity
*/
const rootIncreasingSpecificity = exports.rootIncreasingSpecificity = (0, _postcss_plugin.default)('marpit-postcss-root-increasing-specificity', () => css => css.walkRules(rule => {
rule.selectors = rule.selectors.map(selector => selector.replace(matcher, ':where(section):not([\\20 root])'));
}));
var _default = exports.default = rootIncreasingSpecificity;

27
node_modules/@marp-team/marpit/lib/postcss/root/rem.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.rem = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
var _font_size = require("./font_size");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const skipParsingMatcher = /("[^"]*"|'[^']*'|(?:attr|url|var)\([^)]*\))/g;
/**
* Marpit PostCSS rem plugin.
*
* Replace `rem` unit to calculated value from CSS variable.
*
* @function rem
*/
const rem = exports.rem = (0, _postcss_plugin.default)('marpit-postcss-rem', () => css => css.walkDecls(decl => {
decl.value = decl.value.split(skipParsingMatcher).map((v, i) => {
if (i % 2) return v;
return v.replace(/(\d*\.?\d+)rem\b/g, (_, num) => `calc(var(${_font_size.rootFontSizeCustomProp}, 1rem) * ${num})`);
}).join('');
}));
var _default = exports.default = rem;

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.rootReplace = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit PostCSS root replace plugin.
*
* Replace `:root` pseudo-class selector into `section`. It can add custom
* pseudo class through `pseudoClass` option to make distinguishable from
* `section` selector.
*
* @function rootReplace
*/
const rootReplace = exports.rootReplace = (0, _postcss_plugin.default)('marpit-postcss-root-replace', ({
pseudoClass
} = {}) => css => css.walkRules(rule => {
// Replace `:root` pseudo-class selectors into `section`
rule.selectors = rule.selectors.map(selector => selector.replace(/(^|[\s>+~(])(?:section)?:root\b/g, (_, s) => `${s}section${pseudoClass || ''}`));
}));
var _default = exports.default = rootReplace;

View File

@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.sectionSize = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
/**
* Marpit PostCSS section size plugin.
*
* Parse width and height declartaion on `section` selector.
*
* @function sectionSize
*/
const sectionSize = exports.sectionSize = (0, _postcss_plugin.default)('marpit-postcss-section-size', ({
preferedPseudoClass
} = {}) => {
const rootSectionMatcher = new RegExp(`^section${preferedPseudoClass ? `(${preferedPseudoClass})?` : ''}$`);
return (css, {
result
}) => {
const originalSize = result.marpitSectionSize || {};
const detectedSize = {};
const preferedSize = {};
let matched;
css.walkRules(rule => {
if (rule.selectors.some(s => {
matched = s.match(rootSectionMatcher);
return !!matched;
})) {
rule.walkDecls(/^(width|height)$/, decl => {
const {
prop
} = decl;
const value = decl.value.trim();
if (matched[1]) {
preferedSize[prop] = value;
} else {
detectedSize[prop] = value;
}
});
}
});
const width = preferedSize.width || detectedSize.width || originalSize.width;
const height = preferedSize.height || detectedSize.height || originalSize.height;
result.marpitSectionSize = {
...originalSize
};
if (width) result.marpitSectionSize.width = width;
if (height) result.marpitSectionSize.height = height;
};
});
var _default = exports.default = sectionSize;

View File

@@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.svgBackdrop = exports.default = void 0;
var _postcss_plugin = _interopRequireDefault(require("../helpers/postcss_plugin"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const backdropMatcher = /(?:\b|^)::backdrop$/;
/**
* Marpit PostCSS SVG backdrop plugin.
*
* Retarget `::backdrop` and `section::backdrop` selector to
* `@media screen { :marpit-container > svg[data-marpit-svg] { .. } }`. It means
* `::backdrop` targets the SVG container in inline SVG mode.
*
* It's useful for setting style of the letterbox and pillarbox in the SVG
* scaled slide.
*
* ```css
* ::backdrop {
* background-color: #448;
* }
* ```
*
* The original definition will remain to support an original usage of
* `::backdrop`.
*
* The important differences from an original `::backdrop` are following:
*
* - In original spec, `::backdrop` creates a separated layer from the target
* element, but Marpit's `::backdrop` does not. The slide elements still
* become the child of `::backdrop` so setting some properties that are
* inherited may make broken slide rendering.
* - Even if the browser is not fullscreen, `::backdrop` will match to SVG
* container whenever matched to `@media screen` media query.
*
* If concerned to conflict with the style provided by the app, consider to
* disable the selector support by `inlineSVG: { backdropSelector: false }`.
*
* @see https://developer.mozilla.org/docs/Web/CSS/::backdrop
* @function svgBackdrop
*/
const svgBackdrop = exports.svgBackdrop = (0, _postcss_plugin.default)('marpit-postcss-svg-backdrop', () => (css, postcss) => {
css.walkRules(rule => {
const injectSelectors = new Set();
for (const selector of rule.selectors) {
// Detect pseudo-element (must appear after the simple selectors)
if (!selector.match(backdropMatcher)) continue;
// Detect whether the selector is targeted to section
const delimiterMatched = selector.match(/[.:#[]/); // must match
const target = selector.slice(0, delimiterMatched.index);
if (target === 'section' || target === '') {
const delimiter = selector.slice(delimiterMatched.index, -10);
injectSelectors.add(`:marpit-container > svg[data-marpit-svg]${delimiter}`);
}
}
if (injectSelectors.size > 0 && rule.nodes.length > 0) {
rule.parent.insertAfter(rule, postcss.atRule({
name: 'media',
params: 'screen',
nodes: [postcss.rule({
selectors: [...injectSelectors.values()],
nodes: rule.nodes
})]
}));
}
});
});
var _default = exports.default = svgBackdrop;

168
node_modules/@marp-team/marpit/lib/theme.js generated vendored Normal file
View File

@@ -0,0 +1,168 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _postcss = _interopRequireDefault(require("postcss"));
var _parse = _interopRequireDefault(require("./postcss/import/parse"));
var _meta = _interopRequireDefault(require("./postcss/meta"));
var _nesting = _interopRequireDefault(require("./postcss/nesting"));
var _increasing_specificity = require("./postcss/root/increasing_specificity");
var _replace = _interopRequireDefault(require("./postcss/root/replace"));
var _section_size = _interopRequireDefault(require("./postcss/section_size"));
var _symbol = _interopRequireDefault(require("./theme/symbol"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const absoluteUnits = {
cm: v => v * 960 / 25.4,
in: v => v * 96,
mm: v => v * 96 / 25.4,
pc: v => v * 16,
pt: v => v * 4 / 3,
px: v => v,
q: v => v * 24 / 25.4
};
const convertToPixel = value => {
if (typeof value !== 'string') return undefined;
const matched = value.match(/^(-?[.0-9]+)([a-z]+)$/i);
if (!matched) return undefined;
const [, num, unit] = matched;
const parsed = Number.parseFloat(num);
if (Number.isNaN(parsed)) return undefined;
const conv = absoluteUnits[unit.toLowerCase()];
return conv ? conv(parsed) : undefined;
};
const memoizeProp = name => `${name}Memoized`;
const reservedMetaType = {
theme: String
};
/**
* Marpit theme class.
*/
class Theme {
/**
* Create a Theme instance.
*
* You should use {@link Theme.fromCSS} unless there is some particular
* reason.
*
* @param {string} name The name of theme.
* @param {string} css The content of CSS.
* @hideconstructor
*/
constructor(name, css) {
/**
* The name of theme.
* @type {string}
*/
this.name = name;
/**
* The content of theme CSS.
* @type {string}
*/
this.css = css;
/**
* Parsed metadata from CSS comments.
* @type {Object}
*/
this.meta = Object.freeze({});
/**
* Parsed `@import` rules.
* @type {module:postcss/import/parse~ImportMeta[]}
*/
this.importRules = [];
/**
* Slide width. It requires the absolute unit supported in CSS.
* @type {string}
*/
this.width = undefined;
/**
* Slide height. It requires the absolute unit supported in CSS.
* @type {string}
*/
this.height = undefined;
this.memoizeInit('width');
this.memoizeInit('height');
}
/**
* Create a Theme instance from Marpit theme CSS.
*
* @alias Theme.fromCSS
* @param {string} cssString The string of Marpit theme CSS. It requires
* `@theme` meta comment.
* @param {Object} [opts]
* @param {Object} [opts.metaType] An object for defined types for metadata.
* @param {Object} [opts.cssNesting] Enable support for CSS nesting.
*/
static fromCSS(cssString, opts = {}) {
const metaType = {
...(opts.metaType || {}),
...reservedMetaType
};
const {
css,
result
} = (0, _postcss.default)([!!opts.cssNesting && _nesting.default, (0, _meta.default)({
metaType
}), (0, _replace.default)({
pseudoClass: _increasing_specificity.pseudoClass
}), (0, _section_size.default)({
preferedPseudoClass: _increasing_specificity.pseudoClass
}), _parse.default].filter(p => p)).process(cssString);
if (!opts[_symbol.default] && !result.marpitMeta.theme) throw new Error('Marpit theme CSS requires @theme meta.');
const theme = new Theme(result.marpitMeta.theme, css);
theme.importRules = [...result.marpitImport];
theme.meta = Object.freeze({
...result.marpitMeta
});
Object.assign(theme, {
...result.marpitSectionSize
});
return Object.freeze(theme);
}
/**
* The converted width into pixel.
*
* @alias Theme#widthPixel
* @type {number}
* @readonly
*/
get widthPixel() {
return this.memoize('width', convertToPixel);
}
/**
* The converted height into pixel.
*
* @alias Theme#heightPixel
* @type {number}
* @readonly
*/
get heightPixel() {
return this.memoize('height', convertToPixel);
}
/** @private */
memoize(prop, func) {
if (this[memoizeProp(prop)].has(this[prop])) return this[memoizeProp(prop)].get(this[prop]);
const converted = func(this[prop]);
this[memoizeProp(prop)].set(this[prop], converted);
return converted;
}
/** @private */
memoizeInit(prop) {
if (!this[memoizeProp(prop)]) Object.defineProperty(this, memoizeProp(prop), {
value: new Map()
});
}
}
var _default = exports.default = Theme;

64
node_modules/@marp-team/marpit/lib/theme/scaffold.js generated vendored Normal file
View File

@@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.scaffoldTheme = exports.default = void 0;
var _theme = _interopRequireDefault(require("../theme"));
var _symbol = _interopRequireDefault(require("./symbol"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/** @module */
const css = `
section {
width: 1280px;
height: 720px;
box-sizing: border-box;
overflow: hidden;
position: relative;
scroll-snap-align: center center;
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
section::after {
bottom: 0;
content: attr(data-marpit-pagination);
padding: inherit;
pointer-events: none;
position: absolute;
right: 0;
}
section:not([data-marpit-pagination])::after {
display: none;
}
/* Normalization */
h1 {
font-size: 2em;
margin-block: 0.67em;
}
video::-webkit-media-controls {
will-change: transform;
}
`.trim();
/**
* The scaffold theme. It includes these features:
*
* - Define the default slide size.
* - Set default style for `<section>`.
* - Normalize `<h1>` heading style.
* - Apply workaround for glitched video control on Chromium (https://github.com/marp-team/marpit/issues/205)
*
* @type {Theme}
*/
const scaffoldTheme = exports.scaffoldTheme = _theme.default.fromCSS(css, {
[_symbol.default]: true
});
var _default = exports.default = scaffoldTheme;

8
node_modules/@marp-team/marpit/lib/theme/symbol.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
// This symbol is for internal to skip name validation when creating theme.
var _default = exports.default = Symbol('skipThemeValidation');

321
node_modules/@marp-team/marpit/lib/theme_set.js generated vendored Normal file
View File

@@ -0,0 +1,321 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _postcss = _interopRequireDefault(require("postcss"));
var _postcss_plugin = _interopRequireDefault(require("./helpers/postcss_plugin"));
var _advanced_background = _interopRequireDefault(require("./postcss/advanced_background"));
var _container_query = _interopRequireWildcard(require("./postcss/container_query"));
var _hoisting = _interopRequireDefault(require("./postcss/import/hoisting"));
var _replace = _interopRequireDefault(require("./postcss/import/replace"));
var _suppress = _interopRequireDefault(require("./postcss/import/suppress"));
var _nesting = _interopRequireDefault(require("./postcss/nesting"));
var _pagination = _interopRequireDefault(require("./postcss/pagination"));
var _printable = _interopRequireWildcard(require("./postcss/printable"));
var _prepend = _interopRequireDefault(require("./postcss/pseudo_selector/prepend"));
var _replace2 = _interopRequireDefault(require("./postcss/pseudo_selector/replace"));
var _font_size = _interopRequireDefault(require("./postcss/root/font_size"));
var _increasing_specificity = _interopRequireWildcard(require("./postcss/root/increasing_specificity"));
var _rem = _interopRequireDefault(require("./postcss/root/rem"));
var _replace3 = _interopRequireDefault(require("./postcss/root/replace"));
var _svg_backdrop = _interopRequireDefault(require("./postcss/svg_backdrop"));
var _theme = _interopRequireDefault(require("./theme"));
var _scaffold = _interopRequireDefault(require("./theme/scaffold"));
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const defaultOptions = {
cssNesting: false
};
/**
* Marpit theme set class.
*/
class ThemeSet {
/**
* Create a ThemeSet instance.
*
* @param {Object} [opts]
* @param {boolean} [opts.cssNesting=true] Enable CSS nesting support.
*/
constructor(opts = defaultOptions) {
/**
* An instance of default theme.
*
* While running {@link ThemeSet#pack}, ThemeSet will use this theme when
* the definition of theme directive or the theme with specified name is not
* found.
*
* By default, Marpit does not provide default theme (`undefined`).
*
* @type {Theme|undefined}
*/
this.default = undefined;
/**
* The default type settings for theme metadata added by
* {@link ThemeSet#add}.
*
* A key of object is the name of metadata and a value is the type which of
* `String` and `Array`. You have to set `Array` if the theme allows
* multi-time definitions in same meta key.
*
* ```css
* /**
* * @theme example
* * @foo Single value
* * @foo allows only one string
* * @bar Multiple value 1
* * @bar Multiple value 2
* * @bar Multiple value 3
* * ...
* ```
*
* ```js
* const themeSet = new ThemeSet()
*
* themeSet.metaType = {
* foo: String,
* bar: Array,
* }
*
* themeSet.add(css)
*
* console.log(themeSet.getThemeMeta('example', 'foo'))
* // => 'allows only one string'
*
* console.log(themeSet.getThemeMeta('example', 'bar'))
* // => ['Multiple value 1', 'Multiple value 2', 'Multiple value 3']
* ```
*
* @type {Object}
*/
this.metaType = {};
/**
* A boolean value indicating whether the theme set is enabling CSS nesting
* or not.
*
* @type {boolean}
*/
this.cssNesting = !!opts.cssNesting;
Object.defineProperty(this, 'themeMap', {
value: new Map()
});
}
/**
* Return the number of themes.
*
* @type {number}
* @readonly
*/
get size() {
return this.themeMap.size;
}
/**
* Add theme CSS from string.
*
* @param {string} css The theme CSS string.
* @returns {Theme} A created {@link Theme} instance.
* @throws Will throw an error if the theme name is not specified by `@theme`
* metadata.
*/
add(css) {
const theme = _theme.default.fromCSS(css, {
metaType: this.metaType,
cssNesting: this.cssNesting
});
this.addTheme(theme);
return theme;
}
/**
* Add theme instance.
*
* @param {Theme} theme The theme instance.
* @throws Will throw an error if the theme name is not specified.
*/
addTheme(theme) {
if (!(theme instanceof _theme.default)) throw new Error('ThemeSet can add only an instance of Theme.');
if (typeof theme.name !== 'string') throw new Error('An instance of Theme requires name.');
this.themeMap.set(theme.name, theme);
}
/**
* Removes all themes from a {@link themeSet} object.
*/
clear() {
return this.themeMap.clear();
}
/**
* Remove a specific named theme from a {@link themeSet} object.
*
* @param {string} name The theme name to delete.
* @returns {boolean} Returns `true` if a theme in current {@link ThemeSet}
* existed and has been removed, or `false` if the theme does not exist.
*/
delete(name) {
return this.themeMap.delete(name);
}
/**
* Returns a specific named theme.
*
* @param {string} name The theme name to get.
* @param {boolean} [fallback=false] If true, return instance's default theme
* or scaffold theme when specified theme cannot find.
* @returns {Theme|undefined} Returns specified or fallbacked theme, or
* `undefined` if `fallback` is false and the specified theme has not
* existed.
*/
get(name, fallback = false) {
const theme = this.themeMap.get(name);
return fallback ? theme || this.default || _scaffold.default : theme;
}
/**
* Returns value(s) of specified metadata from a theme. It considers `@import`
* and `@import-theme` rules in getting meta value. On the other hand, the
* default theme specified by the instance is not considered.
*
* To support metadata with array type, it will merge into a flatten array
* when the all of got valid values that includes imported themes are array.
*
* @param {string|Theme} theme The theme name or instance.
* @param {string} meta The meta name to get.
* @returns {string|string[]|undefined}
*/
getThemeMeta(theme, meta) {
const themeInstance = theme instanceof _theme.default ? theme : this.get(theme);
const metas = themeInstance ? this.resolveImport(themeInstance).map(t => t.meta[meta]).filter(m => m) : [];
// Flatten in order of definitions when the all of valid values are array
if (metas.length > 0 && metas.every(m => Array.isArray(m))) {
const mergedArray = [];
for (const m of metas) mergedArray.unshift(...m);
return mergedArray;
}
return metas[0];
}
/**
* Returns the value of specified property name from a theme. It considers
* `@import` and `@import-theme` rules in getting value.
*
* It will fallback the reference object into the instance's default theme or
* scaffold theme when the specified theme is `undefined`.
*
* @param {string|Theme} theme The theme name or instance.
* @param {string} prop The property name to get.
* @returns {*}
*/
getThemeProp(theme, prop) {
const themeInstance = theme instanceof _theme.default ? theme : this.get(theme);
const props = themeInstance ? this.resolveImport(themeInstance).map(t => t[prop]) : [];
return [...props, this.default && this.default[prop], _scaffold.default[prop]].find(t => t);
}
/**
* Returns a boolean indicating whether a specific named theme exists or not.
*
* @param {string} name The theme name.
* @returns {boolean} Returns `true` if a specific named theme exists,
* otherwise `false`.
*/
has(name) {
return this.themeMap.has(name);
}
/**
* Convert registered theme CSS into usable in the rendered markdown by
* {@link Marpit#render}.
*
* **This method is designed for internal use by {@link Marpit} class.** Use
* {@link Marpit#render} instead unless there is some particular reason.
*
* @param {string} name The theme name. It will use the instance's default
* theme or scaffold theme when a specific named theme does not exist.
* @param {Object} [opts] The option object passed by {@link Marpit#render}.
* @param {string} [opts.after] A CSS string to append into after theme.
* @param {string} [opts.before] A CSS string to prepend into before theme.
* @param {Element[]} [opts.containers] Container elements wrapping whole
* slide deck.
* @param {boolean|string|string[]} [opts.containerQuery] Enable CSS container
* query by setting `true`. You can also specify the name of container for
* CSS container query used by the `@container` at-rule in child elements.
* @param {boolean} [opts.printable] Make style printable to PDF.
* @param {Marpit~InlineSVGOptions} [opts.inlineSVG] Apply a hierarchy of
* inline SVG to CSS selector by setting `true`. _(Experimental)_
* @return {string} The converted CSS string.
*/
pack(name, opts = {}) {
const slideElements = [{
tag: 'section'
}];
const theme = this.get(name, true);
const inlineSVGOpts = opts.inlineSVG || {};
if (inlineSVGOpts.enabled) {
slideElements.unshift({
tag: 'svg'
}, {
tag: 'foreignObject'
});
}
const runPostCSS = (css, plugins) => (0, _postcss.default)([this.cssNesting && (0, _nesting.default)(), ...plugins].filter(p => p)).process(css).css;
const additionalCSS = css => {
if (!css) return undefined;
try {
return runPostCSS(css, [(0, _suppress.default)(this)]);
} catch {
return undefined;
}
};
const after = additionalCSS(opts.after);
const before = additionalCSS(opts.before);
const containerName = typeof opts.containerQuery === 'string' || Array.isArray(opts.containerQuery) ? opts.containerQuery : undefined;
return runPostCSS(theme.css, [before && (0, _postcss_plugin.default)('marpit-pack-before', () => css => css.first.before(before)), after && (0, _postcss_plugin.default)('marpit-pack-after', () => css => {
css.last.after(after);
}), opts.containerQuery && (0, _container_query.default)(containerName), _hoisting.default, (0, _replace.default)(this), opts.printable && (0, _printable.default)({
width: this.getThemeProp(theme, 'width'),
height: this.getThemeProp(theme, 'height')
}), 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
}), _font_size.default, _prepend.default, (0, _replace2.default)(opts.containers, slideElements), _increasing_specificity.default, opts.printable && _printable.postprocess, opts.containerQuery && _container_query.postprocess, _rem.default, _hoisting.default]);
}
/**
* Returns a `Iterator` object that contains registered themes to current
* instance.
*
* @returns {Iterator.<Theme>}
*/
themes() {
return this.themeMap.values();
}
/**
* Resolves `@import` and `@import-theme` and returns an array of using theme
* instances.
*
* @private
* @param {Theme} theme Theme instance
* @returns {Theme[]}
*/
resolveImport(theme, importedThemes = []) {
const {
name
} = theme;
if (importedThemes.includes(name)) throw new Error(`Circular "${name}" theme import is detected.`);
const resolvedThemes = [theme];
theme.importRules.forEach(m => {
const importTheme = this.get(m.value);
if (importTheme) resolvedThemes.push(...this.resolveImport(importTheme, [...importedThemes, name].filter(n => n)));
});
return resolvedThemes.filter(v => v);
}
}
var _default = exports.default = ThemeSet;