初始化
This commit is contained in:
329
uni_modules/UniDevTools/node_modules/licia/css.js
generated
vendored
Normal file
329
uni_modules/UniDevTools/node_modules/licia/css.js
generated
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
var Class = require('./Class');
|
||||
var trim = require('./trim');
|
||||
var repeat = require('./repeat');
|
||||
var defaults = require('./defaults');
|
||||
var camelCase = require('./camelCase');
|
||||
|
||||
exports = {
|
||||
parse: function(css) {
|
||||
return new Parser(css).parse();
|
||||
},
|
||||
stringify: function(stylesheet, options) {
|
||||
return new Compiler(stylesheet, options).compile();
|
||||
}
|
||||
};
|
||||
var regComments = /(\/\*[\s\S]*?\*\/)/gi;
|
||||
var regOpen = /^{\s*/;
|
||||
var regClose = /^}/;
|
||||
var regWhitespace = /^\s*/;
|
||||
var regProperty = /^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/;
|
||||
var regValue = /^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/;
|
||||
var regSelector = /^([^{]+)/;
|
||||
var regSemicolon = /^[;\s]*/;
|
||||
var regColon = /^:\s*/;
|
||||
var regMedia = /^@media *([^{]+)/;
|
||||
var regKeyframes = /^@([-\w]+)?keyframes\s*/;
|
||||
var regFontFace = /^@font-face\s*/;
|
||||
var regSupports = /^@supports *([^{]+)/;
|
||||
var regIdentifier = /^([-\w]+)\s*/;
|
||||
var regKeyframeSelector = /^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/;
|
||||
var regComma = /^,\s*/;
|
||||
var Parser = Class({
|
||||
initialize: function Parser(css) {
|
||||
this.input = stripCmt(css);
|
||||
this.open = this._createMatcher(regOpen);
|
||||
this.close = this._createMatcher(regClose);
|
||||
this.whitespace = this._createMatcher(regWhitespace);
|
||||
this.atImport = this._createAtRule('import');
|
||||
this.atCharset = this._createAtRule('charset');
|
||||
this.atNamespace = this._createAtRule('namespace');
|
||||
},
|
||||
parse: function() {
|
||||
return this.stylesheet();
|
||||
},
|
||||
stylesheet: function() {
|
||||
return {
|
||||
type: 'stylesheet',
|
||||
rules: this.rules()
|
||||
};
|
||||
},
|
||||
rules: function() {
|
||||
var rule;
|
||||
var rules = [];
|
||||
this.whitespace();
|
||||
while (
|
||||
this.input.length &&
|
||||
this.input[0] !== '}' &&
|
||||
(rule = this.atRule() || this.rule())
|
||||
) {
|
||||
rules.push(rule);
|
||||
this.whitespace();
|
||||
}
|
||||
return rules;
|
||||
},
|
||||
atRule: function() {
|
||||
if (this.input[0] !== '@') return;
|
||||
return (
|
||||
this.atKeyframes() ||
|
||||
this.atMedia() ||
|
||||
this.atSupports() ||
|
||||
this.atImport() ||
|
||||
this.atCharset() ||
|
||||
this.atNamespace() ||
|
||||
this.atFontFace()
|
||||
);
|
||||
},
|
||||
atKeyframes: function() {
|
||||
var matched = this.match(regKeyframes);
|
||||
if (!matched) return;
|
||||
var vendor = matched[1] || '';
|
||||
matched = this.match(regIdentifier);
|
||||
if (!matched) throw Error('@keyframes missing name');
|
||||
var name = matched[1];
|
||||
if (!this.open()) throw Error("@keyframes missing '{'");
|
||||
var keyframes = [];
|
||||
var keyframe;
|
||||
while ((keyframe = this.keyframe())) {
|
||||
keyframes.push(keyframe);
|
||||
}
|
||||
if (!this.close()) throw Error("@keyframes missing '}'");
|
||||
return {
|
||||
type: 'keyframes',
|
||||
name: name,
|
||||
vendor: vendor,
|
||||
keyframes: keyframes
|
||||
};
|
||||
},
|
||||
keyframe: function() {
|
||||
var selector = [];
|
||||
var matched;
|
||||
while ((matched = this.match(regKeyframeSelector))) {
|
||||
selector.push(matched[1]);
|
||||
this.match(regComma);
|
||||
}
|
||||
if (!selector.length) return;
|
||||
this.whitespace();
|
||||
return {
|
||||
type: 'keyframe',
|
||||
selector: selector.join(', '),
|
||||
declarations: this.declarations()
|
||||
};
|
||||
},
|
||||
atSupports: function() {
|
||||
var matched = this.match(regSupports);
|
||||
if (!matched) return;
|
||||
var supports = trim(matched[1]);
|
||||
if (!this.open()) throw Error("@supports missing '{'");
|
||||
var rules = this.rules();
|
||||
if (!this.close()) throw Error("@supports missing '}'");
|
||||
return {
|
||||
type: 'supports',
|
||||
supports: supports,
|
||||
rules: rules
|
||||
};
|
||||
},
|
||||
atFontFace: function() {
|
||||
var matched = this.match(regFontFace);
|
||||
if (!matched) return;
|
||||
if (!this.open()) throw Error("@font-face missing '{'");
|
||||
var declaration;
|
||||
var declarations = [];
|
||||
while ((declaration = this.declaration())) {
|
||||
declarations.push(declaration);
|
||||
}
|
||||
if (!this.close()) throw Error("@font-face missing '}'");
|
||||
return {
|
||||
type: 'font-face',
|
||||
declarations: declarations
|
||||
};
|
||||
},
|
||||
atMedia: function() {
|
||||
var matched = this.match(regMedia);
|
||||
if (!matched) return;
|
||||
var media = trim(matched[1]);
|
||||
if (!this.open()) throw Error("@media missing '{'");
|
||||
this.whitespace();
|
||||
var rules = this.rules();
|
||||
if (!this.close()) throw Error("@media missing '}'");
|
||||
return {
|
||||
type: 'media',
|
||||
media: media,
|
||||
rules: rules
|
||||
};
|
||||
},
|
||||
rule: function() {
|
||||
var selector = this.selector();
|
||||
if (!selector) throw Error('missing selector');
|
||||
return {
|
||||
type: 'rule',
|
||||
selector: selector,
|
||||
declarations: this.declarations()
|
||||
};
|
||||
},
|
||||
declarations: function() {
|
||||
var declarations = [];
|
||||
if (!this.open()) throw Error("missing '{'");
|
||||
this.whitespace();
|
||||
var declaration;
|
||||
while ((declaration = this.declaration())) {
|
||||
declarations.push(declaration);
|
||||
}
|
||||
if (!this.close()) throw Error("missing '}'");
|
||||
this.whitespace();
|
||||
return declarations;
|
||||
},
|
||||
declaration: function() {
|
||||
var property = this.match(regProperty);
|
||||
if (!property) return;
|
||||
property = trim(property[0]);
|
||||
if (!this.match(regColon)) throw Error("property missing ':'");
|
||||
var value = this.match(regValue);
|
||||
this.match(regSemicolon);
|
||||
this.whitespace();
|
||||
return {
|
||||
type: 'declaration',
|
||||
property: property,
|
||||
value: value ? trim(value[0]) : ''
|
||||
};
|
||||
},
|
||||
selector: function() {
|
||||
var matched = this.match(regSelector);
|
||||
if (!matched) return;
|
||||
return trim(matched[0]);
|
||||
},
|
||||
match: function(reg) {
|
||||
var matched = reg.exec(this.input);
|
||||
if (!matched) return;
|
||||
this.input = this.input.slice(matched[0].length);
|
||||
return matched;
|
||||
},
|
||||
_createMatcher: function(reg) {
|
||||
var _this = this;
|
||||
return function() {
|
||||
return _this.match(reg);
|
||||
};
|
||||
},
|
||||
_createAtRule: function(name) {
|
||||
var reg = new RegExp('^@' + name + '\\s*([^;]+);');
|
||||
return function() {
|
||||
var matched = this.match(reg);
|
||||
if (!matched) return;
|
||||
var ret = {
|
||||
type: name
|
||||
};
|
||||
ret[name] = trim(matched[1]);
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
});
|
||||
var Compiler = Class({
|
||||
initialize: function Compiler(input) {
|
||||
var options =
|
||||
arguments.length > 1 && arguments[1] !== undefined
|
||||
? arguments[1]
|
||||
: {};
|
||||
defaults(options, {
|
||||
indent: ' '
|
||||
});
|
||||
this.input = input;
|
||||
this.indentLevel = 0;
|
||||
this.indentation = options.indent;
|
||||
},
|
||||
compile: function() {
|
||||
return this.stylesheet(this.input);
|
||||
},
|
||||
stylesheet: function(node) {
|
||||
return this.mapVisit(node.rules, '\n\n');
|
||||
},
|
||||
media: function(node) {
|
||||
return (
|
||||
'@media ' +
|
||||
node.media +
|
||||
' {\n' +
|
||||
this.indent(1) +
|
||||
this.mapVisit(node.rules, '\n\n') +
|
||||
this.indent(-1) +
|
||||
'\n}'
|
||||
);
|
||||
},
|
||||
keyframes: function(node) {
|
||||
return (
|
||||
'@'.concat(node.vendor, 'keyframes ') +
|
||||
node.name +
|
||||
' {\n' +
|
||||
this.indent(1) +
|
||||
this.mapVisit(node.keyframes, '\n') +
|
||||
this.indent(-1) +
|
||||
'\n}'
|
||||
);
|
||||
},
|
||||
supports: function(node) {
|
||||
return (
|
||||
'@supports ' +
|
||||
node.supports +
|
||||
' {\n' +
|
||||
this.indent(1) +
|
||||
this.mapVisit(node.rules, '\n\n') +
|
||||
this.indent(-1) +
|
||||
'\n}'
|
||||
);
|
||||
},
|
||||
keyframe: function(node) {
|
||||
return this.rule(node);
|
||||
},
|
||||
mapVisit: function(nodes, delimiter) {
|
||||
var str = '';
|
||||
for (var i = 0, len = nodes.length; i < len; i++) {
|
||||
var node = nodes[i];
|
||||
str += this[camelCase(node.type)](node);
|
||||
if (delimiter && i < len - 1) str += delimiter;
|
||||
}
|
||||
return str;
|
||||
},
|
||||
fontFace: function(node) {
|
||||
return (
|
||||
'@font-face {\n' +
|
||||
this.indent(1) +
|
||||
this.mapVisit(node.declarations, '\n') +
|
||||
this.indent(-1) +
|
||||
'\n}'
|
||||
);
|
||||
},
|
||||
rule: function(node) {
|
||||
return (
|
||||
this.indent() +
|
||||
node.selector +
|
||||
' {\n' +
|
||||
this.indent(1) +
|
||||
this.mapVisit(node.declarations, '\n') +
|
||||
this.indent(-1) +
|
||||
'\n' +
|
||||
this.indent() +
|
||||
'}'
|
||||
);
|
||||
},
|
||||
declaration: function(node) {
|
||||
return this.indent() + node.property + ': ' + node.value + ';';
|
||||
},
|
||||
import: function(node) {
|
||||
return '@import '.concat(node.import, ';');
|
||||
},
|
||||
charset: function(node) {
|
||||
return '@charset '.concat(node.charset, ';');
|
||||
},
|
||||
namespace: function(node) {
|
||||
return '@namespace '.concat(node.namespace, ';');
|
||||
},
|
||||
indent: function(level) {
|
||||
if (level) {
|
||||
this.indentLevel += level;
|
||||
return '';
|
||||
}
|
||||
return repeat(this.indentation, this.indentLevel);
|
||||
}
|
||||
});
|
||||
var stripCmt = function(str) {
|
||||
return str.replace(regComments, '');
|
||||
};
|
||||
|
||||
module.exports = exports;
|
||||
Reference in New Issue
Block a user