@marp-team/marpit
Version:
The skinny framework for creating slide deck from Markdown
167 lines (136 loc) • 4.61 kB
JavaScript
;
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 _section_size = _interopRequireDefault(require("./postcss/section_size"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const 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
};
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];
return conv ? conv(parsed) : undefined;
};
const memoizeProp = name => `${name}Memoized`;
const postcssParser = (0, _postcss.default)([_meta.default, _section_size.default, _parse.default]);
/**
* 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 = {};
/**
* 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.
*/
static fromCSS(cssString, validate = true) {
const processed = postcssParser.process(cssString);
const {
css,
result
} = processed; // validate option is for internal usage. User should never set as false.
if (validate && !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 = _objectSpread({}, result.marpitMeta);
Object.assign(theme, _objectSpread({}, 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 = Theme;
exports.default = _default;