mirror of
https://github.com/wishthis/wishthis.git
synced 2025-12-26 08:48:18 -05:00
329 lines
10 KiB
JavaScript
329 lines
10 KiB
JavaScript
import { CssTypes, } from '../type';
|
|
class Compiler {
|
|
level = 0;
|
|
indentation = ' ';
|
|
compress = false;
|
|
constructor(options) {
|
|
if (typeof options?.indent === 'string') {
|
|
this.indentation = options?.indent;
|
|
}
|
|
if (options?.compress) {
|
|
this.compress = true;
|
|
}
|
|
}
|
|
// We disable no-unused-vars for _position. We keep position for potential reintroduction of source-map
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
emit(str, _position) {
|
|
return str;
|
|
}
|
|
/**
|
|
* Increase, decrease or return current indentation.
|
|
*/
|
|
indent(level) {
|
|
this.level = this.level || 1;
|
|
if (level) {
|
|
this.level += level;
|
|
return '';
|
|
}
|
|
return Array(this.level).join(this.indentation);
|
|
}
|
|
visit(node) {
|
|
switch (node.type) {
|
|
case CssTypes.stylesheet:
|
|
return this.stylesheet(node);
|
|
case CssTypes.rule:
|
|
return this.rule(node);
|
|
case CssTypes.declaration:
|
|
return this.declaration(node);
|
|
case CssTypes.comment:
|
|
return this.comment(node);
|
|
case CssTypes.container:
|
|
return this.container(node);
|
|
case CssTypes.charset:
|
|
return this.charset(node);
|
|
case CssTypes.document:
|
|
return this.document(node);
|
|
case CssTypes.customMedia:
|
|
return this.customMedia(node);
|
|
case CssTypes.fontFace:
|
|
return this.fontFace(node);
|
|
case CssTypes.host:
|
|
return this.host(node);
|
|
case CssTypes.import:
|
|
return this.import(node);
|
|
case CssTypes.keyframes:
|
|
return this.keyframes(node);
|
|
case CssTypes.keyframe:
|
|
return this.keyframe(node);
|
|
case CssTypes.layer:
|
|
return this.layer(node);
|
|
case CssTypes.media:
|
|
return this.media(node);
|
|
case CssTypes.namespace:
|
|
return this.namespace(node);
|
|
case CssTypes.page:
|
|
return this.page(node);
|
|
case CssTypes.supports:
|
|
return this.supports(node);
|
|
}
|
|
}
|
|
mapVisit(nodes, delim) {
|
|
let buf = '';
|
|
delim = delim || '';
|
|
for (let i = 0, length = nodes.length; i < length; i++) {
|
|
buf += this.visit(nodes[i]);
|
|
if (delim && i < length - 1) {
|
|
buf += this.emit(delim);
|
|
}
|
|
}
|
|
return buf;
|
|
}
|
|
compile(node) {
|
|
if (this.compress) {
|
|
return node.stylesheet.rules.map(this.visit, this).join('');
|
|
}
|
|
return this.stylesheet(node);
|
|
}
|
|
/**
|
|
* Visit stylesheet node.
|
|
*/
|
|
stylesheet(node) {
|
|
return this.mapVisit(node.stylesheet.rules, '\n\n');
|
|
}
|
|
/**
|
|
* Visit comment node.
|
|
*/
|
|
comment(node) {
|
|
if (this.compress) {
|
|
return this.emit('', node.position);
|
|
}
|
|
return this.emit(this.indent() + '/*' + node.comment + '*/', node.position);
|
|
}
|
|
/**
|
|
* Visit container node.
|
|
*/
|
|
container(node) {
|
|
if (this.compress) {
|
|
return (this.emit('@container ' + node.container, node.position) +
|
|
this.emit('{') +
|
|
this.mapVisit(node.rules) +
|
|
this.emit('}'));
|
|
}
|
|
return (this.emit(this.indent() + '@container ' + node.container, node.position) +
|
|
this.emit(' {\n' + this.indent(1)) +
|
|
this.mapVisit(node.rules, '\n\n') +
|
|
this.emit('\n' + this.indent(-1) + this.indent() + '}'));
|
|
}
|
|
/**
|
|
* Visit container node.
|
|
*/
|
|
layer(node) {
|
|
if (this.compress) {
|
|
return (this.emit('@layer ' + node.layer, node.position) +
|
|
(node.rules
|
|
? this.emit('{') +
|
|
this.mapVisit(node.rules) +
|
|
this.emit('}')
|
|
: ';'));
|
|
}
|
|
return (this.emit(this.indent() + '@layer ' + node.layer, node.position) +
|
|
(node.rules
|
|
? this.emit(' {\n' + this.indent(1)) +
|
|
this.mapVisit(node.rules, '\n\n') +
|
|
this.emit('\n' + this.indent(-1) + this.indent() + '}')
|
|
: ';'));
|
|
}
|
|
/**
|
|
* Visit import node.
|
|
*/
|
|
import(node) {
|
|
return this.emit('@import ' + node.import + ';', node.position);
|
|
}
|
|
/**
|
|
* Visit media node.
|
|
*/
|
|
media(node) {
|
|
if (this.compress) {
|
|
return (this.emit('@media ' + node.media, node.position) +
|
|
this.emit('{') +
|
|
this.mapVisit(node.rules) +
|
|
this.emit('}'));
|
|
}
|
|
return (this.emit(this.indent() + '@media ' + node.media, node.position) +
|
|
this.emit(' {\n' + this.indent(1)) +
|
|
this.mapVisit(node.rules, '\n\n') +
|
|
this.emit('\n' + this.indent(-1) + this.indent() + '}'));
|
|
}
|
|
/**
|
|
* Visit document node.
|
|
*/
|
|
document(node) {
|
|
const doc = '@' + (node.vendor || '') + 'document ' + node.document;
|
|
if (this.compress) {
|
|
return (this.emit(doc, node.position) +
|
|
this.emit('{') +
|
|
this.mapVisit(node.rules) +
|
|
this.emit('}'));
|
|
}
|
|
return (this.emit(doc, node.position) +
|
|
this.emit(' ' + ' {\n' + this.indent(1)) +
|
|
this.mapVisit(node.rules, '\n\n') +
|
|
this.emit(this.indent(-1) + '\n}'));
|
|
}
|
|
/**
|
|
* Visit charset node.
|
|
*/
|
|
charset(node) {
|
|
return this.emit('@charset ' + node.charset + ';', node.position);
|
|
}
|
|
/**
|
|
* Visit namespace node.
|
|
*/
|
|
namespace(node) {
|
|
return this.emit('@namespace ' + node.namespace + ';', node.position);
|
|
}
|
|
/**
|
|
* Visit supports node.
|
|
*/
|
|
supports(node) {
|
|
if (this.compress) {
|
|
return (this.emit('@supports ' + node.supports, node.position) +
|
|
this.emit('{') +
|
|
this.mapVisit(node.rules) +
|
|
this.emit('}'));
|
|
}
|
|
return (this.emit(this.indent() + '@supports ' + node.supports, node.position) +
|
|
this.emit(' {\n' + this.indent(1)) +
|
|
this.mapVisit(node.rules, '\n\n') +
|
|
this.emit('\n' + this.indent(-1) + this.indent() + '}'));
|
|
}
|
|
/**
|
|
* Visit keyframes node.
|
|
*/
|
|
keyframes(node) {
|
|
if (this.compress) {
|
|
return (this.emit('@' + (node.vendor || '') + 'keyframes ' + node.name, node.position) +
|
|
this.emit('{') +
|
|
this.mapVisit(node.keyframes) +
|
|
this.emit('}'));
|
|
}
|
|
return (this.emit('@' + (node.vendor || '') + 'keyframes ' + node.name, node.position) +
|
|
this.emit(' {\n' + this.indent(1)) +
|
|
this.mapVisit(node.keyframes, '\n') +
|
|
this.emit(this.indent(-1) + '}'));
|
|
}
|
|
/**
|
|
* Visit keyframe node.
|
|
*/
|
|
keyframe(node) {
|
|
const decls = node.declarations;
|
|
if (this.compress) {
|
|
return (this.emit(node.values.join(','), node.position) +
|
|
this.emit('{') +
|
|
this.mapVisit(decls) +
|
|
this.emit('}'));
|
|
}
|
|
return (this.emit(this.indent()) +
|
|
this.emit(node.values.join(', '), node.position) +
|
|
this.emit(' {\n' + this.indent(1)) +
|
|
this.mapVisit(decls, '\n') +
|
|
this.emit(this.indent(-1) + '\n' + this.indent() + '}\n'));
|
|
}
|
|
/**
|
|
* Visit page node.
|
|
*/
|
|
page(node) {
|
|
if (this.compress) {
|
|
const sel = node.selectors.length ? node.selectors.join(', ') : '';
|
|
return (this.emit('@page ' + sel, node.position) +
|
|
this.emit('{') +
|
|
this.mapVisit(node.declarations) +
|
|
this.emit('}'));
|
|
}
|
|
const sel = node.selectors.length ? node.selectors.join(', ') + ' ' : '';
|
|
return (this.emit('@page ' + sel, node.position) +
|
|
this.emit('{\n') +
|
|
this.emit(this.indent(1)) +
|
|
this.mapVisit(node.declarations, '\n') +
|
|
this.emit(this.indent(-1)) +
|
|
this.emit('\n}'));
|
|
}
|
|
/**
|
|
* Visit font-face node.
|
|
*/
|
|
fontFace(node) {
|
|
if (this.compress) {
|
|
return (this.emit('@font-face', node.position) +
|
|
this.emit('{') +
|
|
this.mapVisit(node.declarations) +
|
|
this.emit('}'));
|
|
}
|
|
return (this.emit('@font-face ', node.position) +
|
|
this.emit('{\n') +
|
|
this.emit(this.indent(1)) +
|
|
this.mapVisit(node.declarations, '\n') +
|
|
this.emit(this.indent(-1)) +
|
|
this.emit('\n}'));
|
|
}
|
|
/**
|
|
* Visit host node.
|
|
*/
|
|
host(node) {
|
|
if (this.compress) {
|
|
return (this.emit('@host', node.position) +
|
|
this.emit('{') +
|
|
this.mapVisit(node.rules) +
|
|
this.emit('}'));
|
|
}
|
|
return (this.emit('@host', node.position) +
|
|
this.emit(' {\n' + this.indent(1)) +
|
|
this.mapVisit(node.rules, '\n\n') +
|
|
this.emit(this.indent(-1) + '\n}'));
|
|
}
|
|
/**
|
|
* Visit custom-media node.
|
|
*/
|
|
customMedia(node) {
|
|
return this.emit('@custom-media ' + node.name + ' ' + node.media + ';', node.position);
|
|
}
|
|
/**
|
|
* Visit rule node.
|
|
*/
|
|
rule(node) {
|
|
const decls = node.declarations;
|
|
if (!decls.length) {
|
|
return '';
|
|
}
|
|
if (this.compress) {
|
|
return (this.emit(node.selectors.join(','), node.position) +
|
|
this.emit('{') +
|
|
this.mapVisit(decls) +
|
|
this.emit('}'));
|
|
}
|
|
const indent = this.indent();
|
|
return (this.emit(node.selectors
|
|
.map(s => {
|
|
return indent + s;
|
|
})
|
|
.join(',\n'), node.position) +
|
|
this.emit(' {\n') +
|
|
this.emit(this.indent(1)) +
|
|
this.mapVisit(decls, '\n') +
|
|
this.emit(this.indent(-1)) +
|
|
this.emit('\n' + this.indent() + '}'));
|
|
}
|
|
/**
|
|
* Visit declaration node.
|
|
*/
|
|
declaration(node) {
|
|
if (this.compress) {
|
|
return (this.emit(node.property + ':' + node.value, node.position) +
|
|
this.emit(';'));
|
|
}
|
|
return (this.emit(this.indent()) +
|
|
this.emit(node.property + ': ' + node.value, node.position) +
|
|
this.emit(';'));
|
|
}
|
|
}
|
|
export default Compiler;
|