"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;