168 lines
4.5 KiB
JavaScript
168 lines
4.5 KiB
JavaScript
"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; |