UNPKG

@alyle/ui

Version:

Minimal Design, a set of components for Angular

354 lines • 12.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StringIdGenerator = exports.StyleCollection = exports.LylParse = void 0; exports.resolveSelectors = resolveSelectors; exports.lyl = lyl; exports.st2c = st2c; const LINE_FEED_REGEX = () => /[\n\s]*([^\n]+)/g; const AMPERSAND_REGEX = () => /&/g; var RuleType; (function (RuleType) { RuleType[RuleType["FontFace"] = 0] = "FontFace"; RuleType[RuleType["MediaQuery"] = 1] = "MediaQuery"; RuleType[RuleType["KeyFrame"] = 2] = "KeyFrame"; RuleType[RuleType["Style"] = 3] = "Style"; RuleType[RuleType["DynamicStyle"] = 4] = "DynamicStyle"; RuleType[RuleType["CompiledStyle"] = 5] = "CompiledStyle"; })(RuleType || (RuleType = {})); /** * Transform a lyl style block to CSS */ class LylParse { constructor(_template, _className = '${_className}', _isServer, /** Is true when used inside lyl */ _isDevMode) { this._template = _template; this._className = _className; this._isServer = _isServer; this._isDevMode = _isDevMode; } toCss() { const selectors = []; const resolvedSelectors = []; const rules = []; this._template .replace(/(\/\/\s[^\n\r]*(?:[\n\r]+|$))/g, '') // remove comments .replace(/,[\n\s]+/g, ',') .replace(LINE_FEED_REGEX(), (_ex, fullLine) => { if (fullLine.endsWith('{')) { if (selectors.length === 0) { selectors.push([this._className]); this._createRule(rules, RuleType.Style, selectors, resolvedSelectors); } else { const line_1 = fullLine.slice(0, fullLine.length - 1).trim(); if (line_1 === '@font-face') { selectors.push(line_1); this._createRule(rules, RuleType.FontFace, selectors, resolvedSelectors); } else if (line_1.startsWith('@m')) { selectors.push(line_1); this._createRule(rules, RuleType.MediaQuery, selectors, resolvedSelectors); } else if (line_1.startsWith('@k')) { selectors.push(line_1); this._createRule(rules, RuleType.KeyFrame, selectors, resolvedSelectors); } else { selectors.push(line_1 .split(',') .map(_ => _.trim())); this._createRule(rules, RuleType.Style, selectors, resolvedSelectors); } } } else if (fullLine.length === 1 && fullLine === '}') { this._removeParentSelector(rules, selectors, resolvedSelectors); } else if (this._isDevMode && fullLine.startsWith('/* >> ds')) { const lin = fullLine; this._createRuleWithResolvedSelector(rules, RuleType.DynamicStyle, selectors, resolvedSelectors, lin); } else if (this._isServer && fullLine.startsWith('...')) { const content = fullLine.slice(3); this._createRuleWithResolvedSelector(rules, RuleType.CompiledStyle, selectors, resolvedSelectors, content); } else { if (fullLine) { if (this._isDevMode && fullLine.includes('undefined')) { return ''; } if (this._isDevMode && fullLine.endsWith(';')) { throw new Error(`Do not require semicolon in [${fullLine}]`); } if (fullLine.includes(': ')) { fullLine = fullLine.replace(': ', ':'); } fullLine += ';'; this._appendDeclaration(rules, RuleType.Style, fullLine); } } return ''; }); return rules .filter(rule => !rule.isEmpty) .map(rule => { return rule.block; }).join(''); } _createRule(rules, type, selectors, resolvedSelectors) { const parentRule = resolvedSelectors[resolvedSelectors.length - 1]; const prevRule = rules[rules.length - 1]; if (prevRule && !prevRule.isReady) { prevRule.block += `}`; prevRule.isReady = true; } let selector = ''; if (type === RuleType.FontFace) { selector = `@font-face`; } else if (type === RuleType.KeyFrame) { selector = selectors[1]; } else if (parentRule && parentRule.type === RuleType.KeyFrame) { selector = selectors[selectors.length - 1][0]; } else if (type === RuleType.MediaQuery || (parentRule && parentRule.type === RuleType.MediaQuery && prevRule && prevRule.isEmpty)) { selector = resolveSelectors(selectors, false); } else { selector = resolveSelectors(selectors, true); } const rule = { selector, block: `${selector}{`, type: RuleType.Style, isEmpty: true }; resolvedSelectors.push({ selector: '', block: '', type: type, isEmpty: true }); rules.push(rule); // If is new media query if (type === RuleType.MediaQuery) { // rule.block += `{`; rule.hasMedia = true; } if (parentRule && parentRule.hasMedia) { rule.hasMedia = true; } if (type === RuleType.KeyFrame) { rule.isReady = true; rule.isEmpty = false; } return rule; } _createRuleWithResolvedSelector(rules, type, selectors, resolvedSelectors, content) { if (!content) { return; } const prevRule = rules[rules.length - 1]; const parentRule = resolvedSelectors[resolvedSelectors.length - 1]; const { hasMedia } = prevRule; let selector = ''; if (type === RuleType.MediaQuery || (parentRule && parentRule.type === RuleType.MediaQuery && prevRule && prevRule.isEmpty)) { selector = resolveSelectors(selectors, false); } else { selector = resolveSelectors(selectors, true); } // Close previous if (prevRule && !prevRule.isReady) { prevRule.block += `}`; } const rule = { selector: selector, block: ``, type, hasMedia, isEmpty: false }; if (type === RuleType.CompiledStyle) { rule.block = transformCC(content, selector); } else if (type === RuleType.DynamicStyle) { rule.block = content.replace(/\|\|\&\|\|/g, selector); } rule.isReady = true; rules.push(rule); } _appendDeclaration(rules, _type, content) { if (!content) { return; } let prevRule = rules[rules.length - 1]; if (prevRule && prevRule.isReady) { prevRule = { selector: prevRule.selector, block: `${prevRule.selector}{`, type: prevRule.type, hasMedia: prevRule.hasMedia, isEmpty: false }; rules.push(prevRule); } prevRule.block += content; prevRule.isEmpty = false; } _removeParentSelector(rules, selectors, resolvedSelectors) { selectors.pop(); const prevRule = rules[rules.length - 1]; const currentRule = resolvedSelectors.pop(); if (!prevRule) { return; } // Close previous rule if (!prevRule.isReady) { prevRule.block += `}`; prevRule.isReady = true; } if (currentRule && (currentRule.type === RuleType.MediaQuery || currentRule.type === RuleType.KeyFrame)) { prevRule.block += `}`; prevRule.isReady = true; } } } exports.LylParse = LylParse; function transformCC(content, sel) { content = content.replace(/\/\* >> cc[^\/\*]+\*\//g, ''); let expression = content.slice(2, content.length - 1); expression = `st2c((${expression}), \`${sel}\`)`; return `\${${expression}}`; } function resolveSelectors(selectors, ignoreMediaQuery) { let media = null; const sel = selectors .filter((_) => { if (typeof _ === 'string') { if (!ignoreMediaQuery) { media = _; } return false; } return !!_.filter(__ => __).length; }); const sel2 = sel.length === 1 ? sel[0].join(',') : sel.length ? sel.reduce((prv, curr) => { const result = prv.map(item => curr.map(cu => { if (cu.includes('&')) { return cu.replace(AMPERSAND_REGEX(), item); } return `${item} ${cu}`; })); return Array.prototype.concat.apply([], result); }).join(',') : ''; if (media) { return `${media}{${sel2}`; } return sel2; } function lyl(literals, ...placeholders) { return (className) => { let result = ''; // Save expressions for (let i = 0; i < placeholders.length; i++) { const placeholder = placeholders[i]; result += literals[i]; if (result.endsWith('...')) { result = result.slice(0, result.length - 3); if (typeof placeholder === 'function' || placeholder instanceof StyleCollection) { result += `${createUniqueCommentSelector('ds')}${st2c(placeholder, '||&||')}`; } } else { result += placeholder; } } // add the last literal result += literals[literals.length - 1]; const css = new LylParse(result, className, false, true).toCss(); return css; }; } function createUniqueCommentSelector(text = 'id') { return `/* >> ${text} -- ${Math.floor(new Date().valueOf() * Math.random()).toString(36)} */`; } class StyleCollection { constructor(...templates) { this._templates = templates; this.css = this.css.bind(this); } add(...templates) { // return new StyleCollection(...[...this._templates, ...templates]); this._templates.push(...templates); return this; } /** Transform style */ setTransformer(transformer) { this._transformer = transformer; return this; } /** * @return StyleTemplate * @docs-private */ css(className) { let lin = ''; const templates = this._templates; for (let index = 0; index < templates.length; index++) { let template; if (this._transformer) { template = ((this._transformer(templates[index]))); } else { template = templates[index]; } lin += template(className); } return lin; } } exports.StyleCollection = StyleCollection; /** * Transform a ...{style} to css * For internal use purposes only * @param fn StyleTemplate or StyleCollection * @param className class name */ function st2c(fn, className) { if (fn == null) { return ''; } if (fn instanceof StyleCollection) { return fn.css(className); } return fn(className); } class StringIdGenerator { constructor(chars = 'abcdefghijklmnopqrstuvwxyz') { this._chars = chars; this._nextId = [0]; } next() { const r = []; for (const char of this._nextId) { r.unshift(this._chars[char]); } this._increment(); return r.join(''); } _increment() { for (let i = 0; i < this._nextId.length; i++) { const val = ++this._nextId[i]; if (val >= this._chars.length) { this._nextId[i] = 0; } else { return; } } this._nextId.push(0); } } exports.StringIdGenerator = StringIdGenerator; //# sourceMappingURL=parse.js.map