UNPKG

@gechiui/block-editor

Version:
702 lines (538 loc) 12.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = _default; /* eslint-disable @gechiui/no-unused-vars-before-return */ // Adapted from https://github.com/reworkcss/css // because we needed to remove source map support. // http://www.w3.org/TR/CSS21/grammar.htm // https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027 const commentre = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//g; function _default(css, options) { options = options || {}; /** * Positional. */ let lineno = 1; let column = 1; /** * Update lineno and column based on `str`. */ function updatePosition(str) { const lines = str.match(/\n/g); if (lines) { lineno += lines.length; } const i = str.lastIndexOf('\n'); // eslint-disable-next-line no-bitwise column = ~i ? str.length - i : column + str.length; } /** * Mark position and patch `node.position`. */ function position() { const start = { line: lineno, column }; return function (node) { node.position = new Position(start); whitespace(); return node; }; } /** * Store position information for a node */ function Position(start) { this.start = start; this.end = { line: lineno, column }; this.source = options.source; } /** * Non-enumerable source string */ Position.prototype.content = css; /** * Error `msg`. */ const errorsList = []; function error(msg) { const err = new Error(options.source + ':' + lineno + ':' + column + ': ' + msg); err.reason = msg; err.filename = options.source; err.line = lineno; err.column = column; err.source = css; if (options.silent) { errorsList.push(err); } else { throw err; } } /** * Parse stylesheet. */ function stylesheet() { const rulesList = rules(); return { type: 'stylesheet', stylesheet: { source: options.source, rules: rulesList, parsingErrors: errorsList } }; } /** * Opening brace. */ function open() { return match(/^{\s*/); } /** * Closing brace. */ function close() { return match(/^}/); } /** * Parse ruleset. */ function rules() { let node; const accumulator = []; whitespace(); comments(accumulator); while (css.length && css.charAt(0) !== '}' && (node = atrule() || rule())) { if (node !== false) { accumulator.push(node); comments(accumulator); } } return accumulator; } /** * Match `re` and return captures. */ function match(re) { const m = re.exec(css); if (!m) { return; } const str = m[0]; updatePosition(str); css = css.slice(str.length); return m; } /** * Parse whitespace. */ function whitespace() { match(/^\s*/); } /** * Parse comments; */ function comments(accumulator) { let c; accumulator = accumulator || []; // eslint-disable-next-line no-cond-assign while (c = comment()) { if (c !== false) { accumulator.push(c); } } return accumulator; } /** * Parse comment. */ function comment() { const pos = position(); if ('/' !== css.charAt(0) || '*' !== css.charAt(1)) { return; } let i = 2; while ('' !== css.charAt(i) && ('*' !== css.charAt(i) || '/' !== css.charAt(i + 1))) { ++i; } i += 2; if ('' === css.charAt(i - 1)) { return error('End of comment missing'); } const str = css.slice(2, i - 2); column += 2; updatePosition(str); css = css.slice(i); column += 2; return pos({ type: 'comment', comment: str }); } /** * Parse selector. */ function selector() { const m = match(/^([^{]+)/); if (!m) { return; } // FIXME: Remove all comments from selectors http://ostermiller.org/findcomment.html return trim(m[0]).replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '').replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, function (matched) { return matched.replace(/,/g, '\u200C'); }).split(/\s*(?![^(]*\)),\s*/).map(function (s) { return s.replace(/\u200C/g, ','); }); } /** * Parse declaration. */ function declaration() { const pos = position(); // prop let prop = match(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/); if (!prop) { return; } prop = trim(prop[0]); // : if (!match(/^:\s*/)) { return error("property missing ':'"); } // val const val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/); const ret = pos({ type: 'declaration', property: prop.replace(commentre, ''), value: val ? trim(val[0]).replace(commentre, '') : '' }); // ; match(/^[;\s]*/); return ret; } /** * Parse declarations. */ function declarations() { const decls = []; if (!open()) { return error("missing '{'"); } comments(decls); // declarations let decl; // eslint-disable-next-line no-cond-assign while (decl = declaration()) { if (decl !== false) { decls.push(decl); comments(decls); } } if (!close()) { return error("missing '}'"); } return decls; } /** * Parse keyframe. */ function keyframe() { let m; const vals = []; const pos = position(); // eslint-disable-next-line no-cond-assign while (m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)) { vals.push(m[1]); match(/^,\s*/); } if (!vals.length) { return; } return pos({ type: 'keyframe', values: vals, declarations: declarations() }); } /** * Parse keyframes. */ function atkeyframes() { const pos = position(); let m = match(/^@([-\w]+)?keyframes\s*/); if (!m) { return; } const vendor = m[1]; // identifier m = match(/^([-\w]+)\s*/); if (!m) { return error('@keyframes missing name'); } const name = m[1]; if (!open()) { return error("@keyframes missing '{'"); } let frame; let frames = comments(); // eslint-disable-next-line no-cond-assign while (frame = keyframe()) { frames.push(frame); frames = frames.concat(comments()); } if (!close()) { return error("@keyframes missing '}'"); } return pos({ type: 'keyframes', name, vendor, keyframes: frames }); } /** * Parse supports. */ function atsupports() { const pos = position(); const m = match(/^@supports *([^{]+)/); if (!m) { return; } const supports = trim(m[1]); if (!open()) { return error("@supports missing '{'"); } const style = comments().concat(rules()); if (!close()) { return error("@supports missing '}'"); } return pos({ type: 'supports', supports, rules: style }); } /** * Parse host. */ function athost() { const pos = position(); const m = match(/^@host\s*/); if (!m) { return; } if (!open()) { return error("@host missing '{'"); } const style = comments().concat(rules()); if (!close()) { return error("@host missing '}'"); } return pos({ type: 'host', rules: style }); } /** * Parse media. */ function atmedia() { const pos = position(); const m = match(/^@media *([^{]+)/); if (!m) { return; } const media = trim(m[1]); if (!open()) { return error("@media missing '{'"); } const style = comments().concat(rules()); if (!close()) { return error("@media missing '}'"); } return pos({ type: 'media', media, rules: style }); } /** * Parse custom-media. */ function atcustommedia() { const pos = position(); const m = match(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/); if (!m) { return; } return pos({ type: 'custom-media', name: trim(m[1]), media: trim(m[2]) }); } /** * Parse paged media. */ function atpage() { const pos = position(); const m = match(/^@page */); if (!m) { return; } const sel = selector() || []; if (!open()) { return error("@page missing '{'"); } let decls = comments(); // declarations let decl; // eslint-disable-next-line no-cond-assign while (decl = declaration()) { decls.push(decl); decls = decls.concat(comments()); } if (!close()) { return error("@page missing '}'"); } return pos({ type: 'page', selectors: sel, declarations: decls }); } /** * Parse document. */ function atdocument() { const pos = position(); const m = match(/^@([-\w]+)?document *([^{]+)/); if (!m) { return; } const vendor = trim(m[1]); const doc = trim(m[2]); if (!open()) { return error("@document missing '{'"); } const style = comments().concat(rules()); if (!close()) { return error("@document missing '}'"); } return pos({ type: 'document', document: doc, vendor, rules: style }); } /** * Parse font-face. */ function atfontface() { const pos = position(); const m = match(/^@font-face\s*/); if (!m) { return; } if (!open()) { return error("@font-face missing '{'"); } let decls = comments(); // declarations let decl; // eslint-disable-next-line no-cond-assign while (decl = declaration()) { decls.push(decl); decls = decls.concat(comments()); } if (!close()) { return error("@font-face missing '}'"); } return pos({ type: 'font-face', declarations: decls }); } /** * Parse import */ const atimport = _compileAtrule('import'); /** * Parse charset */ const atcharset = _compileAtrule('charset'); /** * Parse namespace */ const atnamespace = _compileAtrule('namespace'); /** * Parse non-block at-rules */ function _compileAtrule(name) { const re = new RegExp('^@' + name + '\\s*([^;]+);'); return function () { const pos = position(); const m = match(re); if (!m) { return; } const ret = { type: name }; ret[name] = m[1].trim(); return pos(ret); }; } /** * Parse at rule. */ function atrule() { if (css[0] !== '@') { return; } return atkeyframes() || atmedia() || atcustommedia() || atsupports() || atimport() || atcharset() || atnamespace() || atdocument() || atpage() || athost() || atfontface(); } /** * Parse rule. */ function rule() { const pos = position(); const sel = selector(); if (!sel) { return error('selector missing'); } comments(); return pos({ type: 'rule', selectors: sel, declarations: declarations() }); } return addParent(stylesheet()); } /** * Trim `str`. */ function trim(str) { return str ? str.replace(/^\s+|\s+$/g, '') : ''; } /** * Adds non-enumerable parent node reference to each node. */ function addParent(obj, parent) { const isNode = obj && typeof obj.type === 'string'; const childParent = isNode ? obj : parent; for (const k in obj) { const value = obj[k]; if (Array.isArray(value)) { value.forEach(function (v) { addParent(v, childParent); }); } else if (value && typeof value === 'object') { addParent(value, childParent); } } if (isNode) { Object.defineProperty(obj, 'parent', { configurable: true, writable: true, enumerable: false, value: parent || null }); } return obj; } /* eslint-enable @gechiui/no-unused-vars-before-return */ //# sourceMappingURL=parse.js.map