124 KiB
// 清除供应商前缀缓存的方法 cleanPrefixes: function() { // 将 mVENDOR_PREFIXES 属性置为 null,清除之前缓存的供应商前缀信息 this.mVENDOR_PREFIXES = null; },
// 根据属性获取对应的供应商前缀数组的方法 prefixesForProperty: function(aProperty) { // 检查 mVENDOR_PREFIXES 是否为 null,如果为 null 则进行初始化 if (!this.mVENDOR_PREFIXES) { // 初始化 mVENDOR_PREFIXES 为一个空对象 this.mVENDOR_PREFIXES = {}; // 遍历 kCSS_VENDOR_PREFIXES.properties 数组 for (var i = 0; i < kCSS_VENDOR_PREFIXES.properties.length; i++) { // 获取当前属性 var p = kCSS_VENDOR_PREFIXES.properties[i]; // 检查该属性是否有 gecko 前缀,并且有 webkit、presto 或 trident 前缀之一 if (p.gecko && (p.webkit || p.presto || p.trident)) { // 初始化一个空对象 o 用于存储不同前缀 var o = {}; // 如果 kEXPORTS_FOR_GECKO 为 true,则将 gecko 前缀添加到 o 中 if (this.kEXPORTS_FOR_GECKO) o[p.gecko] = true; // 如果 kEXPORTS_FOR_WEBKIT 为 true 且有 webkit 前缀,则将 webkit 前缀添加到 o 中 if (this.kEXPORTS_FOR_WEBKIT && p.webkit) o[p.webkit] = true; // 如果 kEXPORTS_FOR_PRESTO 为 true 且有 presto 前缀,则将 presto 前缀添加到 o 中 if (this.kEXPORTS_FOR_PRESTO && p.presto) o[p.presto] = true; // 如果 kEXPORTS_FOR_TRIDENT 为 true 且有 trident 前缀,则将 trident 前缀添加到 o 中 if (this.kEXPORTS_FOR_TRIDENT && p.trident) o[p.trident] = true; // 在 mVENDOR_PREFIXES 中为 gecko 前缀创建一个空数组 this.mVENDOR_PREFIXES[p.gecko] = []; // 遍历 o 对象,将其中的前缀添加到 mVENDOR_PREFIXES[p.gecko] 数组中 for (var j in o) this.mVENDOR_PREFIXES[p.gecko].push(j) } } } // 检查传入的属性是否存在于 mVENDOR_PREFIXES 中 if (aProperty in this.mVENDOR_PREFIXES) // 如果存在,则对该属性对应的前缀数组进行排序并返回 return this.mVENDOR_PREFIXES[aProperty].sort(); // 如果不存在,则返回 null return null; },
// 解析颜色停止点的方法 parseColorStop: function(parser, token) { // 调用 parser 的 parseColor 方法解析颜色 var color = parser.parseColor(token); // 初始化位置为空字符串 var position = ""; // 如果颜色解析失败,则返回 null if (!color) return null; // 获取下一个标记 token = parser.getToken(true, true); // 检查标记是否为百分比或指定单位的尺寸 if (token.isPercentage() || token.isDimensionOfUnit("cm") || token.isDimensionOfUnit("mm") || token.isDimensionOfUnit("in") || token.isDimensionOfUnit("pc") || token.isDimensionOfUnit("px") || token.isDimensionOfUnit("em") || token.isDimensionOfUnit("ex") || token.isDimensionOfUnit("pt")) { // 如果是,则将标记的值赋给位置 position = token.value; // 获取下一个标记 token = parser.getToken(true, true); } // 返回包含颜色和位置的对象 return { color: color, position: position } },
// 解析渐变的方法 parseGradient: function (parser, token) { // 初始化是否为径向渐变的标志为 false var isRadial = false; // 初始化渐变对象,设置是否重复为 false var gradient = { isRepeating: false }; // 检查标记是否不为空 if (token.isNotNull()) { // 检查标记是否为特定的渐变函数 if (token.isFunction("-moz-linear-gradient(") || token.isFunction("-moz-radial-gradient(") || token.isFunction("-moz-repeating-linear-gradient(") || token.isFunction("-moz-repeating-radial-gradient(")) { // 如果是径向渐变函数,则将 isRadial 标志置为 true if (token.isFunction("-moz-radial-gradient(") || token.isFunction("-moz-repeating-radial-gradient(")) { gradient.isRadial = true; } // 如果是重复渐变函数,则将 isRepeating 标志置为 true if (token.isFunction("-moz-repeating-linear-gradient(") || token.isFunction("-moz-repeating-radial-gradient(")) { gradient.isRepeating = true; }
// 获取下一个标记
token = parser.getToken(true, true);
// 初始化是否有渐变线的标志为 false
var haveGradientLine = false;
// 初始化是否找到水平位置的标志为 false
var foundHorizPosition = false;
// 初始化是否有角度的标志为 false
var haveAngle = false;
// 检查标记是否为角度
if (token.isAngle()) {
// 如果是,则将角度值赋给渐变对象的 angle 属性
gradient.angle = token.value;
// 将 haveGradientLine 标志置为 true
haveGradientLine = true;
// 将 haveAngle 标志置为 true
haveAngle = true;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 检查标记是否为长度或特定的标识符
if (token.isLength()
|| token.isIdent("top")
|| token.isIdent("center")
|| token.isIdent("bottom")
|| token.isIdent("left")
|| token.isIdent("right")) {
// 如果是,则将 haveGradientLine 标志置为 true
haveGradientLine = true;
// 检查标记是否为长度或水平位置标识符
if (token.isLength()
|| token.isIdent("left")
|| token.isIdent("right")) {
// 如果是,则将 foundHorizPosition 标志置为 true
foundHorizPosition = true;
}
// 将标记的值赋给渐变对象的 position 属性
gradient.position = token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 如果有渐变线
if (haveGradientLine) {
// 如果没有角度且标记为角度
if (!haveAngle && token.isAngle()) {
// 将角度值赋给渐变对象的 angle 属性
gradient.angle = token.value;
// 将 haveAngle 标志置为 true
haveAngle = true;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 检查标记是否符合特定条件
else if (token.isLength()
|| (foundHorizPosition && (token.isIdent("top")
|| token.isIdent("center")
|| token.isIdent("bottom")))
|| (!foundHorizPosition && (token.isLength()
|| token.isIdent("top")
|| token.isIdent("center")
|| token.isIdent("bottom")
|| token.isIdent("left")
|| token.isIdent("right")))) {
// 如果符合条件,则更新渐变对象的 position 属性
gradient.position = ("position" in gradient) ? gradient.position + " ": "";
gradient.position += token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 如果没有角度且标记为角度
if (!haveAngle && token.isAngle()) {
// 将角度值赋给渐变对象的 angle 属性
gradient.angle = token.value;
// 将 haveAngle 标志置为 true
haveAngle = true;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 检查标记是否为逗号
if (!token.isSymbol(","))
// 如果不是,则返回 null
return null;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 如果是径向渐变
if (gradient.isRadial) {
// 检查标记是否为圆形或椭圆形标识符
if (token.isIdent("circle") ||
token.isIdent("ellipse")) {
// 如果是,则将标识符的值赋给渐变对象的 shape 属性
gradient.shape = token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 检查标记是否为特定的尺寸标识符
if (token.isIdent("closest-side") ||
token.isIdent("closest-corner") ||
token.isIdent("farthest-side") ||
token.isIdent("farthest-corner") ||
token.isIdent("contain") ||
token.isIdent("cover")) {
// 如果是,则将标识符的值赋给渐变对象的 size 属性
gradient.size = token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 如果 shape 属性不存在且标记为圆形或椭圆形标识符
if (!("shape" in gradient) &&
(token.isIdent("circle") ||
token.isIdent("ellipse"))) {
// 将标识符的值赋给渐变对象的 shape 属性
gradient.shape = token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 如果 shape 或 size 属性存在且标记不是逗号
if ((("shape" in gradient) || ("size" in gradient)) && !token.isSymbol(","))
// 返回 null
return null;
// 如果 shape 或 size 属性存在
else if (("shape" in gradient) || ("size" in gradient))
// 获取下一个标记
token = parser.getToken(true, true);
}
// 解析第一个颜色停止点
var stop1 = this.parseColorStop(parser, token);
// 如果解析失败,则返回 null
if (!stop1)
return null;
// 获取当前标记
token = parser.currentToken();
// 检查标记是否为逗号
if (!token.isSymbol(","))
// 如果不是,则返回 null
return null;
// 获取下一个标记
token = parser.getToken(true, true);
// 解析第二个颜色停止点
var stop2 = this.parseColorStop(parser, token);
// 如果解析失败,则返回 null
if (!stop2)
return null;
// 获取当前标记
token = parser.currentToken();
// 如果标记为逗号
if (token.isSymbol(",")) {
// 获取下一个标记
token = parser.getToken(true, true);
}
// 将前两个颜色停止点添加到渐变对象的 stops 数组中
gradient.stops = [stop1, stop2];
// 循环解析剩余的颜色停止点,直到遇到右括号
while (!token.isSymbol(")")) {
// 解析颜色停止点
var colorstop = this.parseColorStop(parser, token);
// 如果解析失败,则返回 null
if (!colorstop)
return null;
// 获取当前标记
token = parser.currentToken();
// 检查标记是否为右括号或逗号
if (!token.isSymbol(")") && !token.isSymbol(","))
// 如果不是,则返回 null
return null;
// 如果标记为逗号
if (token.isSymbol(","))
// 获取下一个标记
token = parser.getToken(true, true);
// 将颜色停止点添加到渐变对象的 stops 数组中
gradient.stops.push(colorstop);
}
// 返回解析好的渐变对象
return gradient;
}
}
// 如果解析失败,则返回 null
return null;
},
// 解析盒阴影的方法 parseBoxShadows: function(aString) { // 创建一个 CSSParser 实例 var parser = new CSSParser(); // 初始化解析器 parser._init(); // 设置解析器不保留空白字符 parser.mPreserveWS = false; // 设置解析器不保留注释 parser.mPreserveComments = false; // 初始化保留标记数组 parser.mPreservedTokens = []; // 初始化扫描器,传入要解析的字符串 parser.mScanner.init(aString);
// 初始化阴影数组
var shadows = [];
// 获取第一个标记
var token = parser.getToken(true, true);
// 初始化颜色、模糊半径、水平偏移、垂直偏移和扩展半径
var color = "", blurRadius = "0px", offsetX = "0px", offsetY = "0px", spreadRadius = "0px";
// 初始化是否为内阴影的标志为 false
var inset = false;
// 循环处理标记,直到标记为空
while (token.isNotNull()) {
// 检查标记是否为 "none"
if (token.isIdent("none")) {
// 如果是,则将一个包含 none 为 true 的对象添加到阴影数组中
shadows.push( { none: true } );
// 获取下一个标记
token = parser.getToken(true, true);
}
else {
// 检查标记是否为 "inset"
if (token.isIdent('inset')) {
// 如果是,则将 inset 标志置为 true
inset = true;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 检查标记是否为百分比或指定单位的尺寸
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
// 如果是,则将标记的值赋给 offsetX
var offsetX = token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
else
// 如果不是,则返回空数组
return [];
// 如果不是内阴影且标记为 "inset"
if (!inset && token.isIdent('inset')) {
// 将 inset 标志置为 true
inset = true;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 检查标记是否为百分比或指定单位的尺寸
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
// 如果是,则将标记的值赋给 offsetY
var offsetY = token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
else
// 如果不是,则返回空数组
return [];
// 如果不是内阴影且标记为 "inset"
if (!inset && token.isIdent('inset')) {
// 将 inset 标志置为 true
inset = true;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 检查标记是否为百分比或指定单位的尺寸
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
// 如果是,则将标记的值赋给 blurRadius
var blurRadius = token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 如果不是内阴影且标记为 "inset"
if (!inset && token.isIdent('inset')) {
// 将 inset 标志置为 true
inset = true;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 检查标记是否为颜色函数、符号或标识符
if (token.isFunction("rgb(") ||
token.isFunction("rgba(") ||
token.isFunction("hsl(") ||
token.isFunction("hsla(") ||
token.isSymbol("#") ||
token.isIdent()) {
// 如果是,则调用解析器的 parseColor 方法解析颜色
var color = parser.parseColor(token);
// 获取下一个标记
token = parser.getToken(true, true);
}
// 如果不是内阴影且标记为 "inset"
if (!inset && token.isIdent('inset')) {
// 将 inset 标志置为 true
inset = true;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 将解析好的阴影信息添加到阴影数组中
shadows.push( { none: false,
color: color,
offsetX: offsetX, offsetY: offsetY,
blurRadius: blurRadius,
spreadRadius: spreadRadius } );
// 检查标记是否为逗号
if (token.isSymbol(",")) {
// 如果是,则重置相关变量
inset = false;
color = "";
blurRadius = "0px";
spreadRadius = "0px"
offsetX = "0px";
offsetY = "0px";
// 获取下一个标记
token = parser.getToken(true, true);
}
else if (!token.isNotNull())
// 如果标记为空,则返回阴影数组
return shadows;
else
// 否则返回空数组
return [];
}
}
// 返回阴影数组
return shadows;
},
// 解析文本阴影的方法 parseTextShadows: function(aString) { // 创建一个 CSSParser 实例 var parser = new CSSParser(); // 初始化解析器 parser._init(); // 设置解析器不保留空白字符 parser.mPreserveWS = false; // 设置解析器不保留注释 parser.mPreserveComments = false; // 初始化保留标记数组 parser.mPreservedTokens = []; // 初始化扫描器,传入要解析的字符串 parser.mScanner.init(aString);
// 初始化阴影数组
var shadows = [];
// 获取第一个标记
var token = parser.getToken(true, true);
// 初始化颜色、模糊半径、水平偏移和垂直偏移
var color = "", blurRadius = "0px", offsetX = "0px", offsetY = "0px";
// 循环处理标记,直到标记为空
while (token.isNotNull()) {
// 检查标记是否为 "none"
if (token.isIdent("none")) {
// 如果是,则将一个包含 none 为 true 的对象添加到阴影数组中
shadows.push( { none: true } );
// 获取下一个标记
token = parser.getToken(true, true);
}
else {
// 检查标记是否为颜色函数、符号或标识符
if (token.isFunction("rgb(") ||
token.isFunction("rgba(") ||
token.isFunction("hsl(") ||
token.isFunction("hsla(") ||
token.isSymbol("#") ||
token.isIdent()) {
// 如果是,则调用解析器的 parseColor 方法解析颜色
var color = parser.parseColor(token);
// 获取下一个标记
token = parser.getToken(true, true);
}
// 检查标记是否为百分比或指定单位的尺寸
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
// 如果是,则将标记的值赋给 offsetX
var offsetX = token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
else
// 如果不是,则返回空数组
return [];
// 检查标记是否为百分比或指定单位的尺寸
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
// 如果是,则将标记的值赋给 offsetY
var offsetY = token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
else
// 如果不是,则返回空数组
return [];
// 检查标记是否为百分比或指定单位的尺寸
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
// 如果是,则将标记的值赋给 blurRadius
var blurRadius = token.value;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 如果颜色为空且标记为颜色函数、符号或标识符
if (!color &&
(token.isFunction("rgb(") ||
token.isFunction("rgba(") ||
token.isFunction("hsl(") ||
token.isFunction("hsla(") ||
token.isSymbol("#") ||
token.isIdent())) {
// 调用解析器的 parseColor 方法解析颜色
var color = parser.parseColor(token);
// 获取下一个标记
token = parser.getToken(true, true);
}
// 将解析好的阴影信息添加到阴影数组中
shadows.push( { none: false,
color: color,
offsetX: offsetX, offsetY: offsetY,
blurRadius: blurRadius } );
// 检查标记是否为逗号
if (token.isSymbol(",")) {
// 如果是,则重置相关变量
color = "";
blurRadius = "0px";
offsetX = "0px";
offsetY = "0px";
// 获取下一个标记
token = parser.getToken(true, true);
}
else if (!token.isNotNull())
// 如果标记为空,则返回阴影数组
return shadows;
else
// 否则返回空数组
return [];
}
}
// 返回阴影数组
return shadows;
},
// 解析背景图像的方法 parseBackgroundImages: function(aString) { // 创建一个 CSSParser 实例 var parser = new CSSParser(); // 初始化解析器 parser._init(); // 设置解析器不保留空白字符 parser.mPreserveWS = false; // 设置解析器不保留注释 parser.mPreserveComments = false; // 初始化保留标记数组 parser.mPreservedTokens = []; // 初始化扫描器,传入要解析的字符串 parser.mScanner.init(aString);
// 初始化背景数组
var backgrounds = [];
// 获取第一个标记
var token = parser.getToken(true, true);
// 循环处理标记,直到标记为空
while (token.isNotNull()) {
/*if (token.isFunction("rgb(") ||
token.isFunction("rgba(") ||
token.isFunction("hsl(") ||
token.isFunction("hsla(") ||
token.isSymbol("#") ||
token.isIdent()) {
// 如果标记为颜色相关,解析颜色并添加到背景数组中
var color = parser.parseColor(token);
backgrounds.push( { type: "color", value: color });
token = parser.getToken(true, true);
}
else */
// 检查标记是否为 url 函数
if (token.isFunction("url(")) {
// 获取下一个标记
token = parser.getToken(true, true);
// 调用解析器的 parseURL 方法解析 URL
var urlContent = parser.parseURL(token);
// 将解析好的 URL 信息添加到背景数组中
backgrounds.push( { type: "image", value: "url(" + urlContent });
// 获取下一个标记
token = parser.getToken(true, true);
}
// 检查标记是否为渐变函数
else if (token.isFunction("-moz-linear-gradient(") ||
token.isFunction("-moz-radial-gradient(") ||
token.isFunction("-moz-repeating-linear-gradient(") ||
token.isFunction("-moz-repeating-radial-gradient(")) {
// 调用 parseGradient 方法解析渐变
var gradient = this.parseGradient(parser, token);
// 根据渐变类型将渐变信息添加到背景数组中
backgrounds.push( { type: gradient.isRadial ? "radial-gradient" : "linear-gradient", value: gradient });
// 获取下一个标记
token = parser.getToken(true, true);
}
else
// 如果标记不符合要求,则返回 null
return null;
// 检查标记是否为逗号
if (token.isSymbol(",")) {
// 获取下一个标记
token = parser.getToken(true, true);
// 如果标记为空,则返回 null
if (!token.isNotNull())
return null;
}
}
// 返回背景数组
return backgrounds;
},
- // 序列化渐变对象为字符串的方法
- serializeGradient: function(gradient)
- {
- // 根据渐变类型和是否重复构建渐变字符串的开头部分
- var s = gradient.isRadial
- ? (gradient.isRepeating ? "-moz-repeating-radial-gradient(" : "-moz-radial-gradient(" )
- (gradient.isRepeating ? "-moz-repeating-linear-gradient(" : "-moz-linear-gradient(" ); // 如果渐变有角度或位置信息 if (gradient.angle || gradient.position) s += (gradient.angle ? gradient.angle + " ": "") + (gradient.position ? gradient.position : "") + ", "; // 如果是径向渐变且有形状或尺寸信息 if (gradient.isRadial && (gradient.shape || gradient.size)) s += (gradient.shape ? gradient.shape : "") + " " + (gradient.size ? gradient.size : "") + ", "; // 遍历渐变的颜色停止点数组 for (var i = 0; i < gradient.stops.length; i++) { // 获取当前颜色停止点 var colorstop = gradient.stops[i]; // 将颜色停止点信息添加到渐变字符串中 s += colorstop.color + (colorstop.position ? " " + colorstop.position : ""); // 如果不是最后一个颜色停止点,则添加逗号 if (i != gradient.stops.length -1) s += ", "; } // 添加右括号完成渐变字符串 s += ")"; // 返回序列化后的渐变字符串 return s; },
// 解析边框图像的方法 parseBorderImage: function(aString) { // 创建一个 CSSParser 实例 var parser = new CSSParser(); // 初始化解析器 parser._init(); // 设置解析器不保留空白字符 parser.mPreserveWS = false; // 设置解析器不保留注释 parser.mPreserveComments = false; // 初始化保留标记数组 parser.mPreservedTokens = []; // 初始化扫描器,传入要解析的字符串 parser.mScanner.init(aString);
// 初始化边框图像对象
var borderImage = {url: "", offsets: [], widths: [], sizes: []};
// 获取第一个标记
var token = parser.getToken(true, true);
// 检查标记是否为 url 函数
if (token.isFunction("url(")) {
// 获取下一个标记
token = parser.getToken(true, true);
// 调用解析器的 parseURL 方法解析 URL
var urlContent = parser.parseURL(token);
// 如果 URL 解析成功
if (urlContent) {
// 处理 URL 字符串,去除首尾引号
borderImage.url = urlContent.substr(0, urlContent.length - 1).trim();
if ((borderImage.url[0] == '"' && borderImage.url[borderImage.url.length - 1] == '"') ||
(borderImage.url[0] == "'" && borderImage.url[borderImage.url.length - 1] == "'"))
borderImage.url = borderImage.url.substr(1, borderImage.url.length - 2);
}
else
// 如果 URL 解析失败,则返回 null
return null;
}
else
// 如果标记不是 url 函数,则返回 null
return null;
// 获取下一个标记
token = parser.getToken(true, true);
// 检查标记是否为数字或百分比
if (token.isNumber() || token.isPercentage())
// 如果是,则将标记的值添加到边框图像的 offsets 数组中
borderImage.offsets.push(token.value);
else
// 如果不是,则返回 null
return null;
// 循环处理后续的标记,最多处理 3 个
var i;
for (i= 0; i < 3; i++) {
// 获取下一个标记
token = parser.getToken(true, true);
// 检查标记是否为数字或百分比
if (token.isNumber() || token.isPercentage())
// 如果是,则将标记的值添加到边框图像的 offsets 数组中
borderImage.offsets.push(token.value);
else
// 如果不是,则跳出循环
break;
}
// 如果处理了 3 个标记,则获取下一个标记
if (i == 3)
token = parser.getToken(true, true);
// 检查标记是否为斜杠
if (token.isSymbol("/")) {
// 获取下一个标记
token = parser.getToken(true, true);
// 检查标记是否为尺寸、数字 0 或特定的边框宽度名称
if (token.isDimension()
|| token.isNumber("0")
|| (token.isIdent() && token.value in parser.kBORDER_WIDTH_NAMES))
// 如果是,则将标记的值添加到边框图像的 widths 数组中
borderImage.widths.push(token.value);
else
// 如果不是,则返回 null
return null;
// 循环处理后续的标记,最多处理 3 个
for (var i = 0; i < 3; i++) {
// 获取下一个标记
token = parser.getToken(true, true);
// 检查标记是否为尺寸、数字 0 或特定的边框宽度名称
if (token.isDimension()
|| token.isNumber("0")
|| (token.isIdent() && token.value in parser.kBORDER_WIDTH_NAMES))
// 如果是,则将标记的值添加到边框图像的 widths 数组中
borderImage.widths.push(token.value);
else
// 如果不是,则跳出循环
break;
}
// 如果处理了 3 个标记,则获取下一个标记
if (i == 3)
token = parser.getToken(true, true);
}
// 循环处理后续的标记,最多处理 2 个
for (var i = 0; i < 2; i++) {
// 检查标记是否为特定的尺寸标识符
if (token.isIdent("stretch")
|| token.isIdent("repeat")
|| token.isIdent("round"))
// 如果是,则将标记的值添加到边框图像的 sizes 数组中
borderImage.sizes.push(token.value);
else if (!token.isNotNull())
// 如果标记为空,则返回边框图像对象
return borderImage;
else
// 如果标记不符合要求,则返回 null
return null;
// 获取下一个标记
token = parser.getToken(true, true);
}
// 如果标记为空,则返回边框图像对象
if (!token.isNotNull())
return borderImage;
// 如果解析失败,则返回 null
return null;
},
// 解析媒体查询的方法 parseMediaQuery: function(aString) { // 定义一个包含所有有效约束条件的对象 var kCONSTRAINTS = { "width": true, "min-width": true, "max-width": true, "height": true, "min-height": true, "max-height": true, "device-width": true, "min-device-width": true, "max-device-width": true, "device-height": true, "min-device-height": true, "max-device-height": true, "orientation": true, "aspect-ratio": true, "min-aspect-ratio": true, "max-aspect-ratio": true, "device-aspect-ratio": true, "min-device-aspect-ratio": true, "max-device-aspect-ratio": true, "color": true, "min-color": true, "max-color": true, "color-index": true, "min-color-index": true, "max-color-index": true, "monochrome": true, "min-monochrome": true, "max-monochrome": true, "resolution": true, "min-resolution
// 模拟 kCSS_VENDOR_PREFIXES const kCSS_VENDOR_PREFIXES = { properties: [ { gecko: '-moz-example', webkit: '-webkit-example', presto: '-o-example', trident: '-ms-example' } ] };
// 模拟 CSSParser 类 class CSSParser { constructor() { this.mScanner = { init: function (aString) { // 初始化扫描器逻辑 } }; }
_init() {
// 初始化解析器逻辑
}
getToken() {
// 模拟获取标记逻辑
return {
isNotNull: function () { return true; },
isFunction: function (name) { return false; },
isAngle: function () { return false; },
isLength: function () { return false; },
isIdent: function (value) { return false; },
isSymbol: function (symbol) { return false; },
isPercentage: function () { return false; },
isDimensionOfUnit: function (unit) { return false; },
parseColor: function (token) { return 'color'; },
currentToken: function () { return { isSymbol: function (symbol) { return false; } }; },
parseURL: function (token) { return 'url-content'; }
};
}
}
// 定义对象 const obj = { kEXPORTS_FOR_GECKO: true, kEXPORTS_FOR_WEBKIT: true, kEXPORTS_FOR_PRESTO: true, kEXPORTS_FOR_TRIDENT: true, mVENDOR_PREFIXES: null,
// 清除前缀缓存
cleanPrefixes: function () {
this.mVENDOR_PREFIXES = null;
},
// 获取属性的前缀列表
prefixesForProperty: function (aProperty) {
if (!this.mVENDOR_PREFIXES) {
this.mVENDOR_PREFIXES = {};
// 遍历所有属性前缀
for (var i = 0; i < kCSS_VENDOR_PREFIXES.properties.length; i++) {
var p = kCSS_VENDOR_PREFIXES.properties[i];
if (p.gecko && (p.webkit || p.presto || p.trident)) {
var o = {};
// 根据导出标志添加前缀
if (this.kEXPORTS_FOR_GECKO) o[p.gecko] = true;
if (this.kEXPORTS_FOR_WEBKIT && p.webkit) o[p.webkit] = true;
if (this.kEXPORTS_FOR_PRESTO && p.presto) o[p.presto] = true;
if (this.kEXPORTS_FOR_TRIDENT && p.trident) o[p.trident] = true;
this.mVENDOR_PREFIXES[p.gecko] = [];
for (var j in o)
this.mVENDOR_PREFIXES[p.gecko].push(j)
}
}
}
if (aProperty in this.mVENDOR_PREFIXES)
return this.mVENDOR_PREFIXES[aProperty].sort();
return null;
},
// 解析颜色停止点
parseColorStop: function (parser, token) {
var color = parser.parseColor(token);
var position = "";
if (!color)
return null;
token = parser.getToken(true, true);
// 检查是否有位置信息
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
position = token.value;
token = parser.getToken(true, true);
}
return { color: color, position: position }
},
// 解析渐变
parseGradient: function (parser, token) {
var isRadial = false;
var gradient = { isRepeating: false };
if (token.isNotNull()) {
if (token.isFunction("-moz-linear-gradient(") ||
token.isFunction("-moz-radial-gradient(") ||
token.isFunction("-moz-repeating-linear-gradient(") ||
token.isFunction("-moz-repeating-radial-gradient(")) {
if (token.isFunction("-moz-radial-gradient(") ||
token.isFunction("-moz-repeating-radial-gradient(")) {
gradient.isRadial = true;
}
if (token.isFunction("-moz-repeating-linear-gradient(") ||
token.isFunction("-moz-repeating-radial-gradient(")) {
gradient.isRepeating = true;
}
token = parser.getToken(true, true);
var haveGradientLine = false;
var foundHorizPosition = false;
var haveAngle = false;
// 检查是否有角度信息
if (token.isAngle()) {
gradient.angle = token.value;
haveGradientLine = true;
haveAngle = true;
token = parser.getToken(true, true);
}
// 检查是否有位置信息
if (token.isLength()
|| token.isIdent("top")
|| token.isIdent("center")
|| token.isIdent("bottom")
|| token.isIdent("left")
|| token.isIdent("right")) {
haveGradientLine = true;
if (token.isLength()
|| token.isIdent("left")
|| token.isIdent("right")) {
foundHorizPosition = true;
}
gradient.position = token.value;
token = parser.getToken(true, true);
}
if (haveGradientLine) {
if (!haveAngle && token.isAngle()) {
gradient.angle = token.value;
haveAngle = true;
token = parser.getToken(true, true);
}
else if (token.isLength()
|| (foundHorizPosition && (token.isIdent("top")
|| token.isIdent("center")
|| token.isIdent("bottom")))
|| (!foundHorizPosition && (token.isLength()
|| token.isIdent("top")
|| token.isIdent("center")
|| token.isIdent("bottom")
|| token.isIdent("left")
|| token.isIdent("right")))) {
gradient.position = ("position" in gradient) ? gradient.position + " " : "";
gradient.position += token.value;
token = parser.getToken(true, true);
}
if (!haveAngle && token.isAngle()) {
gradient.angle = token.value;
haveAngle = true;
token = parser.getToken(true, true);
}
if (!token.isSymbol(","))
return null;
token = parser.getToken(true, true);
}
if (gradient.isRadial) {
// 检查是否有形状信息
if (token.isIdent("circle") ||
token.isIdent("ellipse")) {
gradient.shape = token.value;
token = parser.getToken(true, true);
}
// 检查是否有大小信息
if (token.isIdent("closest-side") ||
token.isIdent("closest-corner") ||
token.isIdent("farthest-side") ||
token.isIdent("farthest-corner") ||
token.isIdent("contain") ||
token.isIdent("cover")) {
gradient.size = token.value;
token = parser.getToken(true, true);
}
if (!("shape" in gradient) &&
(token.isIdent("circle") ||
token.isIdent("ellipse"))) {
gradient.shape = token.value;
token = parser.getToken(true, true);
}
if ((("shape" in gradient) || ("size" in gradient)) && !token.isSymbol(","))
return null;
else if (("shape" in gradient) || ("size" in gradient))
token = parser.getToken(true, true);
}
var stop1 = this.parseColorStop(parser, token);
if (!stop1)
return null;
token = parser.currentToken();
if (!token.isSymbol(","))
return null;
token = parser.getToken(true, true);
var stop2 = this.parseColorStop(parser, token);
if (!stop2)
return null;
token = parser.currentToken();
if (token.isSymbol(",")) {
token = parser.getToken(true, true);
}
gradient.stops = [stop1, stop2];
// 解析所有颜色停止点
while (!token.isSymbol(")")) {
var colorstop = this.parseColorStop(parser, token);
if (!colorstop)
return null;
token = parser.currentToken();
if (!token.isSymbol(")") && !token.isSymbol(","))
return null;
if (token.isSymbol(","))
token = parser.getToken(true, true);
gradient.stops.push(colorstop);
}
return gradient;
}
}
return null;
},
// 解析盒子阴影
parseBoxShadows: function (aString) {
var parser = new CSSParser();
parser._init();
parser.mPreserveWS = false;
parser.mPreserveComments = false;
parser.mPreservedTokens = [];
parser.mScanner.init(aString);
var shadows = [];
var token = parser.getToken(true, true);
var color = "", blurRadius = "0px", offsetX = "0px", offsetY = "0px", spreadRadius = "0px";
var inset = false;
while (token.isNotNull()) {
if (token.isIdent("none")) {
shadows.push({ none: true });
token = parser.getToken(true, true);
}
else {
// 检查是否有 inset 关键字
if (token.isIdent('inset')) {
inset = true;
token = parser.getToken(true, true);
}
// 解析偏移量 X
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
var offsetX = token.value;
token = parser.getToken(true, true);
}
else
return [];
if (!inset && token.isIdent('inset')) {
inset = true;
token = parser.getToken(true, true);
}
// 解析偏移量 Y
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
var offsetY = token.value;
token = parser.getToken(true, true);
}
else
return [];
if (!inset && token.isIdent('inset')) {
inset = true;
token = parser.getToken(true, true);
}
// 解析模糊半径
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
var blurRadius = token.value;
token = parser.getToken(true, true);
}
if (!inset && token.isIdent('inset')) {
inset = true;
token = parser.getToken(true, true);
}
// 解析颜色
if (token.isFunction("rgb(") ||
token.isFunction("rgba(") ||
token.isFunction("hsl(") ||
token.isFunction("hsla(") ||
token.isSymbol("#") ||
token.isIdent()) {
var color = parser.parseColor(token);
token = parser.getToken(true, true);
}
if (!inset && token.isIdent('inset')) {
inset = true;
token = parser.getToken(true, true);
}
shadows.push({ none: false,
color: color,
offsetX: offsetX, offsetY: offsetY,
blurRadius: blurRadius,
spreadRadius: spreadRadius });
if (token.isSymbol(",")) {
inset = false;
color = "";
blurRadius = "0px";
spreadRadius = "0px"
offsetX = "0px";
offsetY = "0px";
token = parser.getToken(true, true);
}
else if (!token.isNotNull())
return shadows;
else
return [];
}
}
return shadows;
},
// 解析文本阴影
parseTextShadows: function (aString) {
var parser = new CSSParser();
parser._init();
parser.mPreserveWS = false;
parser.mPreserveComments = false;
parser.mPreservedTokens = [];
parser.mScanner.init(aString);
var shadows = [];
var token = parser.getToken(true, true);
var color = "", blurRadius = "0px", offsetX = "0px", offsetY = "0px";
while (token.isNotNull()) {
if (token.isIdent("none")) {
shadows.push({ none: true });
token = parser.getToken(true, true);
}
else {
// 解析颜色
if (token.isFunction("rgb(") ||
token.isFunction("rgba(") ||
token.isFunction("hsl(") ||
token.isFunction("hsla(") ||
token.isSymbol("#") ||
token.isIdent()) {
var color = parser.parseColor(token);
token = parser.getToken(true, true);
}
// 解析偏移量 X
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
var offsetX = token.value;
token = parser.getToken(true, true);
}
else
return [];
// 解析偏移量 Y
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
var offsetY = token.value;
token = parser.getToken(true, true);
}
else
return [];
// 解析模糊半径
if (token.isPercentage() ||
token.isDimensionOfUnit("cm") ||
token.isDimensionOfUnit("mm") ||
token.isDimensionOfUnit("in") ||
token.isDimensionOfUnit("pc") ||
token.isDimensionOfUnit("px") ||
token.isDimensionOfUnit("em") ||
token.isDimensionOfUnit("ex") ||
token.isDimensionOfUnit("pt")) {
var blurRadius = token.value;
token = parser.getToken(true, true);
}
if (!color &&
(token.isFunction("rgb(") ||
token.isFunction("rgba(") ||
token.isFunction("hsl(") ||
token.isFunction("hsla(") ||
token.isSymbol("#") ||
token.isIdent())) {
var color = parser.parseColor(token);
token = parser.getToken(true, true);
}
shadows.push({ none: false,
color: color,
offsetX: offsetX, offsetY: offsetY,
blurRadius: blurRadius });
if (token.isSymbol(",")) {
color = "";
blurRadius = "0px";
offsetX = "0px";
offsetY = "0px";
token = parser.getToken(true, true);
}
else if (!token.isNotNull())
return shadows;
else
return [];
}
}
return shadows;
},
// 解析背景图像
parseBackgroundImages: function (aString) {
var parser = new CSSParser();
parser._init();
parser.mPreserveWS = false;
parser.mPreserveComments = false;
parser.mPreservedTokens = [];
parser.mScanner.init(aString);
var backgrounds = [];
var token = parser.getToken(true, true);
while (token.isNotNull()) {
if (token.isFunction("url(")) {
token = parser.getToken(true, true);
var urlContent = parser.parseURL(token);
backgrounds.push({ type: "image", value: "url(" + urlContent });
token = parser.getToken(true, true);
}
else if (token.isFunction("-moz-linear-gradient(") ||
token.isFunction("-moz-radial-gradient(") ||
token.isFunction("-moz-repeating-linear-gradient(") ||
token.isFunction("-moz-repeating-radial-gradient(")) {
var gradient = this.parseGradient(parser, token);
backgrounds.push({ type: gradient.isRadial ? "radial-gradient" : "linear-gradient", value: gradient });
token = parser.getToken(true, true);
}
else
return null;
if (token.isSymbol(",")) {
token = parser.getToken(true, true);
if (!token.isNotNull())
return null;
}
}
return backgrounds;
},
// 序列化渐变
serializeGradient: function (gradient) {
var s = gradient.isRadial
? (gradient.isRepeating ? "-moz-repeating-radial-gradient(" : "-moz-radial-gradient(" )
: (gradient.isRepeating ? "-moz-repeating-linear-gradient(" : "-moz-linear-gradient(" );
if (gradient.angle || gradient.position)
s += (gradient.angle ? gradient.angle + " " : "") +
(gradient.position ? gradient.position : "") +
", ";
if (gradient.isRadial && (gradient.shape || gradient.size))
s += (gradient.shape ? gradient.shape : "") +
" " +
(gradient.size ? gradient.size : "") +
", ";
for (var i = 0; i < gradient.stops.length; i++) {
var colorstop = gradient.stops[i];
s += colorstop.color + (colorstop.position ? " " + colorstop.position : "");
if (i != gradient.stops.length - 1)
s += ", ";
}
s += ")";
return s;
},
// 解析边框图像
parseBorderImage: function (aString) {
var parser = new CSSParser();
parser._init();
parser.mPreserveWS = false;
parser.mPreserveComments = false;
parser.mPreservedTokens = [];
parser.mScanner.init(aString);
var borderImage = { url: "", offsets: [], widths: [], sizes: [] };
var token = parser.getToken(true, true);
if (token.isFunction("url(")) {
token = parser.getToken(true, true);
var urlContent = parser.parseURL(token);
if (urlContent) {
borderImage.url = urlContent.substr(0, urlContent.length - 1).trim();
if ((borderImage.url[0] == '"' && borderImage.url[borderImage.url.length - 1] == '"') ||
(borderImage.url[0] == "'" && borderImage.url[borderImage.url.length - 1] == "'"))
borderImage.url = borderImage.url.substr(1, borderImage.url.length - 2);
}
else
return null;
}
else
return null;
token = parser.getToken(true, true);
if (token.isNumber() || token.isPercentage())
borderImage.offsets.push(token.value);
else
return null;
var i;
for (i = 0; i < 3; i++) {
token = parser.getToken(true, true);
if (token.isNumber() || token.isPercentage())
borderImage.offsets.push(token.value);
else
break;
}
if (i == 3)
token = parser.getToken(true, true);
if (token.isSymbol("/")) {
token = parser.getToken(true, true);
if (token.isDimension()
|| token.isNumber("0")
|| (token.isIdent() && token.value in parser.kBORDER_WIDTH_NAMES))
borderImage.widths.push(token.value);
else
return null;
for (var i = 0; i < 3; i++) {
token = parser.getToken(true, true);
if (token.isDimension()
|| token.isNumber("0")
|| (token.isIdent() && token.value in parser.kBORDER_WIDTH_NAMES))
borderImage.widths.push(token.value);
else
break;
}
if (i == 3)
token = parser.getToken(true, true);
}
for (var i = 0; i < 2; i++) {
if (token.isIdent("stretch")
|| token.isIdent("repeat")
|| token.isIdent("round"))
borderImage.sizes.push(token.value);
else if (!token.isNotNull())
return borderImage;
else
return null;
token = parser.getToken(true, true);
}
if (!token.isNotNull())
return borderImage;
return null;
},
// 解析媒体查询
parseMediaQuery: function (aString) {
var kCONSTRAINTS = {
"width": true,
"min-width": true,
"max-width": true,
"height": true,
"min-height": true,
"max-height": true,
"device-width": true,
"min-device-width": true,
"max-device-width": true,
"device-height": true,
"min-device-height": true,
"max-device-height": true,
"orientation": true,
"aspect-ratio": true,
"min-aspect-ratio": true,
"max-aspect-ratio": true,
"device-aspect-ratio": true,
"min-device-aspect-ratio": true,
"max-device-aspect-ratio": true,
"color": true,
"min-color": true,
"max-color": true,
"color-index": true,
"min-color-index": true,
"max-color-index": true,
"monochrome": true,
"min-monochrome": true,
"max-monochrome": true,
"resolution": true,
"min-resolution": true,
"max-resolution": true,
"scan": true,
"grid": true
};
var parser = new CSSParser();
parser._init();
parser.mPreserveWS = false;
parser.mPreserveComments = false;
parser.mPreservedTokens = [];
parser.mScanner.init(aString);
var m = { amplifier: "", medium: "", constraints: [] };
var token = parser.getToken(true, true);
if (token.isIdent("all") ||
token.isIdent("aural") ||
token.isIdent("braille") ||
token.isIdent("handheld") ||
token.isIdent("print") ||
token.isIdent("projection") ||
token.isIdent("screen") ||
token.isIdent("tty") ||
token.isIdent("tv")) {
m.medium = token.value;
token = parser.getToken(true, true);
}
else if (token.isIdent("not") || token.isIdent("only")) {
m.amplifier = token.value;
token = parser.getToken(true, true);
if (token.isIdent("all") ||
token.isIdent("aural") ||
token.isIdent("braille") ||
token.isIdent("handheld") ||
token.isIdent("print") ||
token.isIdent("projection") ||
token.isIdent("screen") ||
token.isIdent("tty") ||
token.isIdent("tv")) {
m.medium = token.value;
token = parser.getToken(true, true);
}
else
return null;
}
if (m.medium) {
if (!token.isNotNull())
return m;
if (token.isIdent("and")) {
token = parser.getToken(true, true);
}
else
return null;
}
while (token.isSymbol("(")) {
token = parser.getToken(true, true);
if (token.isIdent() && (token.value in kCONSTRAINTS)) {
var constraint = token.value;
token = parser.getToken(true, true);
if (token.isSymbol(":")) {
token = parser.getToken(true, true);
var values = [];
while (!token.isSymbol(")")) {
values.push(token.value);
token = parser.getToken(true, true);
}
if (token.isSymbol(")")) {
m.constraints.push({ constraint: constraint, value: values });
token = parser.getToken(true, true);
if (token.isNotNull()) {
if (token.isIdent("and")) {
token = parser.getToken(true, true);
}
else
return null;
}
else
return m;
}
else
return null;
}
else if (token.isSymbol(")")) {
m.constraints.push({ constraint: constraint, value: null });
token = parser.getToken(true, true);
if (token.isNotNull()) {
if (token.isIdent("and")) {
token = parser.getToken(true, true);
}
else
return null;
}
else
return m;
}
else
return null;
}
else
return null;
}
return m;
}
};
// 简单测试 console.log(obj.prefixesForProperty('-moz-example'));
// 解析命名空间规则 parseNamespaceRule: function(aToken, aSheet) { // 获取当前行号,通过 CountLF 函数统计已扫描内容中的换行符数量 var currentLine = CountLF(this.mScanner.getAlreadyScanned()); // 初始化规则字符串,赋值为当前 token 的值 var s = aToken.value; // 标记规则是否有效,初始为 false var valid = false; // 保存当前解析状态 this.preserveState(); // 获取下一个 token var token = this.getToken(true, true); if (token.isNotNull()) { // 初始化前缀为空字符串 var prefix = ""; // 初始化 URL 为空字符串 var url = ""; if (token.isIdent()) { // 如果 token 是标识符,将其赋值给前缀 prefix = token.value; // 将前缀添加到规则字符串中 s += " " + prefix; // 获取下一个 token token = this.getToken(true, true); } if (token) { // 标记是否找到 URL,初始为 false var foundURL = false; if (token.isString()) { // 如果 token 是字符串,标记找到 URL foundURL = true; // 将字符串赋值给 URL url = token.value; // 将 URL 添加到规则字符串中 s += " " + url; } else if (token.isFunction("url(")) { // 如果 token 是 url 函数,获取下一个 token token = this.getToken(true, true); // 解析 URL 内容 var urlContent = this.parseURL(token); if (urlContent) { // 如果解析成功,将 url 内容添加到 URL 中 url += "url(" + urlContent; // 标记找到 URL foundURL = true; // 将 url 内容添加到规则字符串中 s += " " + urlContent; } } } if (foundURL) { // 如果找到 URL,获取下一个 token token = this.getToken(true, true); if (token.isSymbol(";")) { // 如果 token 是分号,将分号添加到规则字符串中 s += ";"; // 忘记之前保存的状态 this.forgetState(); // 创建一个新的 jscsspNamespaceRule 对象 var rule = new jscsspNamespaceRule(); // 设置规则的当前行号 rule.currentLine = currentLine; // 设置规则的解析后的 CSS 文本 rule.parsedCssText = s; // 设置规则的前缀 rule.prefix = prefix; // 设置规则的 URL rule.url = url; // 设置规则的父样式表 rule.parentStyleSheet = aSheet; // 将规则添加到父样式表的 CSS 规则列表中 aSheet.cssRules.push(rule); // 返回 true 表示规则解析成功 return true; } } } // 恢复之前保存的状态 this.restoreState(); // 将未知的 @namespace 规则添加到样式表中 this.addUnknownAtRule(aSheet, "@namespace"); // 返回 false 表示规则解析失败 return false; },
// 解析字体规则 parseFontFaceRule: function(aToken, aSheet) { // 获取当前行号,通过 CountLF 函数统计已扫描内容中的换行符数量 var currentLine = CountLF(this.mScanner.getAlreadyScanned()); // 初始化规则字符串,赋值为当前 token 的值 var s = aToken.value; // 标记规则是否有效,初始为 false var valid = false; // 初始化描述符数组 var descriptors = []; // 保存当前解析状态 this.preserveState(); // 获取下一个 token var token = this.getToken(true, true); if (token.isNotNull()) { // 期望遇到块开始符号 { if (token.isSymbol("{")) { // 将块开始符号添加到规则字符串中 s += " " + token.value; // 获取下一个 token var token = this.getToken(true, false); while (true) { if (token.isSymbol("}")) { // 如果遇到块结束符号 },将其添加到规则字符串中 s += "}"; // 标记规则有效 valid = true; // 跳出循环 break; } else { // 解析声明 var d = this.parseDeclaration(token, descriptors, false, false, aSheet); // 将声明添加到规则字符串中 s += ((d && descriptors.length) ? " " : "") + d; } // 获取下一个 token token = this.getToken(true, false); } } } if (valid) { // 如果规则有效,忘记之前保存的状态 this.forgetState(); // 创建一个新的 jscsspFontFaceRule 对象 var rule = new jscsspFontFaceRule(); // 设置规则的当前行号 rule.currentLine = currentLine; // 设置规则的解析后的 CSS 文本 rule.parsedCssText = s; // 设置规则的描述符 rule.descriptors = descriptors; // 设置规则的父样式表 rule.parentStyleSheet = aSheet; // 将规则添加到父样式表的 CSS 规则列表中 aSheet.cssRules.push(rule); // 返回 true 表示规则解析成功 return true; } // 恢复之前保存的状态 this.restoreState(); // 返回 false 表示规则解析失败 return false; },
// 解析页面规则 parsePageRule: function(aToken, aSheet) { // 获取当前行号,通过 CountLF 函数统计已扫描内容中的换行符数量 var currentLine = CountLF(this.mScanner.getAlreadyScanned()); // 初始化规则字符串,赋值为当前 token 的值 var s = aToken.value; // 标记规则是否有效,初始为 false var valid = false; // 初始化声明数组 var declarations = []; // 保存当前解析状态 this.preserveState(); // 获取下一个 token var token = this.getToken(true, true); // 初始化页面选择器为空字符串 var pageSelector = ""; if (token.isSymbol(":") || token.isIdent()) { if (token.isSymbol(":")) { // 如果 token 是冒号,将其添加到页面选择器中 pageSelector = ":"; // 获取下一个 token token = this.getToken(false, false); } if (token.isIdent()) { // 如果 token 是标识符,将其添加到页面选择器中 pageSelector += token.value; // 将页面选择器添加到规则字符串中 s += " " + pageSelector; // 获取下一个 token token = this.getToken(true, true); } } if (token.isNotNull()) { // 期望遇到块开始符号 { if (token.isSymbol("{")) { // 将块开始符号添加到规则字符串中 s += " " + token.value; // 获取下一个 token var token = this.getToken(true, false); while (true) { if (token.isSymbol("}")) { // 如果遇到块结束符号 },将其添加到规则字符串中 s += "}"; // 标记规则有效 valid = true; // 跳出循环 break; } else { // 解析声明 var d = this.parseDeclaration(token, declarations, true, true, aSheet); // 将声明添加到规则字符串中 s += ((d && declarations.length) ? " " : "") + d; } // 获取下一个 token token = this.getToken(true, false); } } } if (valid) { // 如果规则有效,忘记之前保存的状态 this.forgetState(); // 创建一个新的 jscsspPageRule 对象 var rule = new jscsspPageRule(); // 设置规则的当前行号 rule.currentLine = currentLine; // 设置规则的解析后的 CSS 文本 rule.parsedCssText = s; // 设置规则的页面选择器 rule.pageSelector = pageSelector; // 设置规则的声明 rule.declarations = declarations; // 设置规则的父样式表 rule.parentStyleSheet = aSheet; // 将规则添加到父样式表的 CSS 规则列表中 aSheet.cssRules.push(rule); // 返回 true 表示规则解析成功 return true; } // 恢复之前保存的状态 this.restoreState(); // 返回 false 表示规则解析失败 return false; },
// 解析默认属性值 parseDefaultPropertyValue: function(token, aDecl, aAcceptPriority, descriptor, aSheet) { // 初始化属性值文本为空字符串 var valueText = ""; // 初始化块栈,用于处理嵌套的块 var blocks = []; // 标记是否找到优先级,初始为 false var foundPriority = false; // 初始化值数组 var values = []; while (token.isNotNull()) { if ((token.isSymbol(";") || token.isSymbol("}") || token.isSymbol("!")) && !blocks.length) { if (token.isSymbol("}")) { // 如果遇到块结束符号 },将其放回扫描器 this.ungetToken(); } // 跳出循环 break; } if (token.isIdent(this.kINHERIT)) { if (values.length) { // 如果值数组不为空,返回空字符串表示解析失败 return ""; } else { // 将 inherit 赋值给属性值文本 valueText = this.kINHERIT; // 创建一个新的 jscsspVariable 对象表示 inherit 值 var value = new jscsspVariable(kJscsspINHERIT_VALUE, aSheet); // 将值添加到值数组中 values.push(value); // 获取下一个 token token = this.getToken(true, true); // 跳出循环 break; } } else if (token.isSymbol("{") || token.isSymbol("(") || token.isSymbol("[")) { // 如果遇到块开始符号,将其添加到块栈中 blocks.push(token.value); } else if (token.isSymbol("}") || token.isSymbol("]")) { if (blocks.length) { // 获取块栈顶元素 var ontop = blocks[blocks.length - 1]; if ((token.isSymbol("}") && ontop == "{") || (token.isSymbol(")") && ontop == "(") || (token.isSymbol("]") && ontop == "[")) { // 如果匹配到对应的块结束符号,将栈顶元素弹出 blocks.pop(); } } } // 处理函数调用 if (token.isFunction()) { if (token.isFunction("var(")) { // 如果是 var 函数,获取下一个 token token = this.getToken(true, true); if (token.isIdent()) { // 如果是标识符,获取变量名 var name = token.value; // 获取下一个 token token = this.getToken(true, true); if (token.isSymbol(")")) { // 如果是右括号,创建一个新的 jscsspVariable 对象表示变量值 var value = new jscsspVariable(kJscsspVARIABLE_VALUE, aSheet); // 将变量名添加到属性值文本中 valueText += "var(" + name + ")"; // 设置变量名 value.name = name; // 将值添加到值数组中 values.push(value); } else { // 解析失败,返回空字符串 return ""; } } else { // 解析失败,返回空字符串 return ""; } } else { // 如果是其他函数,获取函数名 var fn = token.value; // 获取下一个 token token = this.getToken(false, true); // 解析函数参数 var arg = this.parseFunctionArgument(token); if (arg) { // 如果解析成功,将函数名和参数添加到属性值文本中 valueText += fn + arg; // 创建一个新的 jscsspVariable 对象表示函数值 var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, aSheet); // 设置函数值 value.value = fn + arg; // 将值添加到值数组中 values.push(value); } else { // 解析失败,返回空字符串 return ""; } } } else if (token.isSymbol("#")) { // 如果是 # 符号,解析颜色值 var color = this.parseColor(token); if (color) { // 如果解析成功,将颜色值添加到属性值文本中 valueText += color; // 创建一个新的 jscsspVariable 对象表示颜色值 var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, aSheet); // 设置颜色值 value.value = color; // 将值添加到值数组中 values.push(value); } else { // 解析失败,返回空字符串 return ""; } } else if (!token.isWhiteSpace() && !token.isSymbol(",")) { // 如果不是空白字符或逗号,创建一个新的 jscsspVariable 对象表示原始值 var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, aSheet); // 设置原始值 value.value = token.value; // 将值添加到值数组中 values.push(value); // 将原始值添加到属性值文本中 valueText += token.value; } else { // 将空白字符或逗号添加到属性值文本中 valueText += token.value; } // 获取下一个 token token = this.getToken(false, true); } if (values.length && valueText) { // 如果值数组和属性值文本都不为空,忘记之前保存的状态 this.forgetState(); // 创建一个新的 jscsspDeclaration 对象并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValuesArray(descriptor, values, valueText)); // 返回属性值文本 return valueText; } // 解析失败,返回空字符串 return ""; },
// 解析边距或内边距简写属性 parseMarginOrPaddingShorthand: function(token, aDecl, aAcceptPriority, aProperty) { // 初始化顶部边距或内边距为 null var top = null; // 初始化底部边距或内边距为 null var bottom = null; // 初始化左边距或内边距为 null var left = null; // 初始化右边距或内边距为 null var right = null; // 初始化值数组 var values = []; while (true) { if (!token.isNotNull()) { // 如果 token 为空,跳出循环 break; } if (token.isSymbol(";") || (aAcceptPriority && token.isSymbol("!")) || token.isSymbol("}")) { if (token.isSymbol("}")) { // 如果遇到块结束符号 },将其放回扫描器 this.ungetToken(); } // 跳出循环 break; } else if (!values.length && token.isIdent(this.kINHERIT)) { // 如果值数组为空且 token 是 inherit,将 inherit 添加到值数组中 values.push(token.value); // 获取下一个 token token = this.getToken(true, true); // 跳出循环 break; } else if (token.isDimension() || token.isNumber("0") || token.isPercentage() || token.isIdent("auto")) { // 如果 token 是尺寸、数字 0、百分比或 auto,将其添加到值数组中 values.push(token.value); } else { // 解析失败,返回空字符串 return ""; } // 获取下一个 token token = this.getToken(true, true); } // 获取值数组的长度 var count = values.length; switch (count) { case 1: // 如果只有一个值,将其赋值给顶部、底部、左边和右边的边距或内边距 top = values[0]; bottom = top; left = top; right = top; break; case 2: // 如果有两个值,将第一个值赋值给顶部和底部,第二个值赋值给左边和右边 top = values[0]; bottom = top; left = values[1]; right = left; break; case 3: // 如果有三个值,将第一个值赋值给顶部,第二个值赋值给左边和右边,第三个值赋值给底部 top = values[0]; left = values[1]; right = left; bottom = values[2]; break; case 4: // 如果有四个值,分别赋值给顶部、右边、底部和左边 top = values[0]; right = values[1]; bottom = values[2]; left = values[3]; break; default: // 解析失败,返回空字符串 return ""; } // 忘记之前保存的状态 this.forgetState(); // 创建顶部边距或内边距的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-top", top)); // 创建右边距或内边距的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-right", right)); // 创建底部边距或内边距的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-bottom", bottom)); // 创建左边距或内边距的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-left", left)); // 返回边距或内边距的值 return top + " " + right + " " + bottom + " " + left; },
// 解析边框颜色简写属性 parseBorderColorShorthand: function(token, aDecl, aAcceptPriority) { // 初始化顶部边框颜色为 null var top = null; // 初始化底部边框颜色为 null var bottom = null; // 初始化左边框颜色为 null var left = null; // 初始化右边框颜色为 null var right = null; // 初始化值数组 var values = []; while (true) { if (!token.isNotNull()) { // 如果 token 为空,跳出循环 break; } if (token.isSymbol(";") || (aAcceptPriority && token.isSymbol("!")) || token.isSymbol("}")) { if (token.isSymbol("}")) { // 如果遇到块结束符号 },将其放回扫描器 this.ungetToken(); } // 跳出循环 break; } else if (!values.length && token.isIdent(this.kINHERIT)) { // 如果值数组为空且 token 是 inherit,将 inherit 添加到值数组中 values.push(token.value); // 获取下一个 token token = this.getToken(true, true); // 跳出循环 break; } else { // 解析颜色值 var color = this.parseColor(token); if (color) { // 如果解析成功,将颜色值添加到值数组中 values.push(color); } else { // 解析失败,返回空字符串 return ""; } } // 获取下一个 token token = this.getToken(true, true); } // 获取值数组的长度 var count = values.length; switch (count) { case 1: // 如果只有一个值,将其赋值给顶部、底部、左边和右边的边框颜色 top = values[0]; bottom = top; left = top; right = top; break; case 2: // 如果有两个值,将第一个值赋值给顶部和底部,第二个值赋值给左边和右边 top = values[0]; bottom = top; left = values[1]; right = left; break; case 3: // 如果有三个值,将第一个值赋值给顶部,第二个值赋值给左边和右边,第三个值赋值给底部 top = values[0]; left = values[1]; right = left; bottom = values[2]; break; case 4: // 如果有四个值,分别赋值给顶部、右边、底部和左边 top = values[0]; right = values[1]; bottom = values[2]; left = values[3]; break; default: // 解析失败,返回空字符串 return ""; } // 忘记之前保存的状态 this.forgetState(); // 创建顶部边框颜色的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("border-top-color", top)); // 创建右边框颜色的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("border-right-color", right)); // 创建底部边框颜色的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-color", bottom)); // 创建左边框颜色的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("border-left-color", left)); // 返回边框颜色的值 return top + " " + right + " " + bottom + " " + left; },
// 解析提示音简写属性 parseCueShorthand: function(token, declarations, aAcceptPriority) { // 初始化提示音开始为空字符串 var before = ""; // 初始化提示音结束为空字符串 var after = ""; // 初始化值数组 var values = []; while (true) { if (!token.isNotNull()) { // 如果 token 为空,跳出循环 break; } if (token.isSymbol(";") || (aAcceptPriority && token.isSymbol("!")) || token.isSymbol("}")) { if (token.isSymbol("}")) { // 如果遇到块结束符号 },将其放回扫描器 this.ungetToken(); } // 跳出循环 break; } else if (!values.length && token.isIdent(this.kINHERIT)) { // 如果值数组为空且 token 是 inherit,将 inherit 添加到值数组中 values.push(token.value); } else if (token.isIdent("none")) { // 如果 token 是 none,将其添加到值数组中 values.push(token.value); } else if (token.isFunction("url(")) { // 如果 token 是 url 函数,获取下一个 token var token = this.getToken(true, true); // 解析 URL 内容 var urlContent = this.parseURL(token); if (urlContent) { // 如果解析成功,将 url 内容添加到值数组中 values.push("url(" + urlContent); } else { // 解析失败,返回空字符串 return ""; } } else { // 解析失败,返回空字符串 return ""; } // 获取下一个 token token = this.getToken(true, true); } // 获取值数组的长度 var count = values.length; switch (count) { case 1: // 如果只有一个值,将其赋值给提示音开始和结束 before = values[0]; after = before; break; case 2: // 如果有两个值,分别赋值给提示音开始和结束 before = values[0]; after = values[1]; break; default: // 解析失败,返回空字符串 return ""; } // 忘记之前保存的状态 this.forgetState(); // 创建提示音开始的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("cue-before", before)); // 创建提示音结束的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("cue-after", after)); // 返回提示音的值 return before + " " + after; },
// 解析暂停时间简写属性 parsePauseShorthand: function(token, declarations, aAcceptPriority) { // 初始化暂停开始时间为空字符串 var before = ""; // 初始化暂停结束时间为空字符串 var after = ""; // 初始化值数组 var values = []; while (true) { if (!token.isNotNull()) { // 如果 token 为空,跳出循环 break; } if (token.isSymbol(";") || (aAcceptPriority && token.isSymbol("!")) || token.isSymbol("}")) { if (token.isSymbol("}")) { // 如果遇到块结束符号 },将其放回扫描器 this.ungetToken(); } // 跳出循环 break; } else if (!values.length && token.isIdent(this.kINHERIT)) { // 如果值数组为空且 token 是 inherit,将 inherit 添加到值数组中 values.push(token.value); } else if (token.isDimensionOfUnit("ms") || token.isDimensionOfUnit("s") || token.isPercentage() || token.isNumber("0")) { // 如果 token 是毫秒、秒、百分比或数字 0,将其添加到值数组中 values.push(token.value); } else { // 解析失败,返回空字符串 return ""; } // 获取下一个 token token = this.getToken(true, true); } // 获取值数组的长度 var count = values.length; switch (count) { case 1: // 如果只有一个值,将其赋值给暂停开始和结束时间 before = values[0]; after = before; break; case 2: // 如果有两个值,分别赋值给暂停开始和结束时间 before = values[0]; after = values[1]; break; default: // 解析失败,返回空字符串 return ""; } // 忘记之前保存的状态 this.forgetState(); // 创建暂停开始时间的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("pause-before", before)); // 创建暂停结束时间的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("pause-after", after)); // 返回暂停时间的值 return before + " " + after; },
// 解析边框宽度简写属性 parseBorderWidthShorthand: function(token, aDecl, aAcceptPriority) { // 初始化顶部边框宽度为 null var top = null; // 初始化底部边框宽度为 null var bottom = null; // 初始化左边框宽度为 null var left = null; // 初始化右边框宽度为 null var right = null; // 初始化值数组 var values = []; while (true) { if (!token.isNotNull()) { // 如果 token 为空,跳出循环 break; } if (token.isSymbol(";") || (aAcceptPriority && token.isSymbol("!")) || token.isSymbol("}")) { if (token.isSymbol("}")) { // 如果遇到块结束符号 },将其放回扫描器 this.ungetToken(); } // 跳出循环 break; } else if (!values.length && token.isIdent(this.kINHERIT)) { // 如果值数组为空且 token 是 inherit,将 inherit 添加到值数组中 values.push(token.value); } else if (token.isDimension() || token.isNumber("0") || (token.isIdent() && token.value in this.kBORDER_WIDTH_NAMES)) { // 如果 token 是尺寸、数字 0 或边框宽度名称,将其添加到值数组中 values.push(token.value); } else { // 解析失败,返回空字符串 return ""; } // 获取下一个 token token = this.getToken(true, true); } // 获取值数组的长度 var count = values.length; switch (count) { case 1: // 如果只有一个值,将其赋值给顶部、底部、左边和右边的边框宽度 top = values[0]; bottom = top; left = top; right = top; break; case 2: // 如果有两个值,将第一个值赋值给顶部和底部,第二个值赋值给左边和右边 top = values[0]; bottom = top; left = values[1]; right = left; break; case 3: // 如果有三个值,将第一个值赋值给顶部,第二个值赋值给左边和右边,第三个值赋值给底部 top = values[0]; left = values[1]; right = left; bottom = values[2]; break; case 4: // 如果有四个值,分别赋值给顶部、右边、底部和左边 top = values[0]; right = values[1]; bottom = values[2]; left = values[3]; break; default: // 解析失败,返回空字符串 return ""; } // 忘记之前保存的状态 this.forgetState(); // 创建顶部边框宽度的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("border-top-width", top)); // 创建右边框宽度的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("border-right-width", right)); // 创建底部边框宽度的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-width", bottom)); // 创建左边框宽度的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFromValue("border-left-width", left)); // 返回边框宽度的值 return top + " " + right + " " + bottom + " " + left; },
// 解析边框样式简写属性 parseBorderStyleShorthand: function(token, aDecl, aAcceptPriority) { // 初始化顶部边框样式为 null var top = null; // 初始化底部边框样式为 null var bottom = null; // 初始化左边框样式为 null var left = null; // 初始化右边框样式为 null var right = null; // 初始化值数组 var values = []; while (true) { if (!token.isNotNull()) { // 如果 token 为空,跳出循环 break; } if (token.isSymbol(";") || (aAcceptPriority && token.isSymbol("!")) || token.isSymbol("}")) { if (token.isSymbol("}")) { // 如果遇到块结束符号 },将其放回扫描器 this.ungetToken(); } // 跳出循环 break; } else if (!values.length && token.isIdent(this.kINHERIT)) { // 如果值数组为空且 token 是 inherit,将 inherit 添加到值数组中 values.push(token.value); } else if (token.isIdent() && token.value in this.kBORDER_STYLE_NAMES) { // 如果 token 是边框样式名称,将其添加到值数组中 values.push(token.value); } else { // 解析失败,返回空字符串 return ""; } // 获取下一个 token token = this.getToken(true, true); } // 获取值数组的长度 var count = values.length; switch (count) { case 1: // 如果只有一个值,将其赋值给顶部、底部、左边和右边的边框样式 top = values[0]; bottom = top; left = top; right = top; break; case 2: // 如果有两个值,将第一个值赋值给顶部和底部,第二个值赋值给左边和右边 top = values[0]; bottom = top; left = values[1]; right = left; break; case 3: // 如果有三个值,将第一个值赋值给顶部,第二个值赋值给左边和右边,第三个值赋值给底部 top = values[0]; left = values[1]; right = left; bottom = values[2]; break; case 4: // 如果有四个值,分别赋值给顶部、右边、底部和左边 top = values[0]; right = values[1]; bottom = values[2]; left = values[3]; break; default: // 解析失败,返回空字符串 return ""; } // 忘记之前保存的状态 this.forgetState(); // 创建顶部边框样式的声明并添加到声明数组中 aDecl.push(this._createJscsspDeclarationFrom
以下是为你提供的代码注释:
// 解析媒体规则的函数
// aToken: 当前的 token
// aSheet: 当前的样式表
parseMediaRule: function(aToken, aSheet) {
// 开启媒体查询模式
this.mScanner.mMediaQueryMode = true;
// 计算当前行数
var currentLine = CountLF(this.mScanner.getAlreadyScanned());
// 获取当前 token 的值
var s = aToken.value;
// 标记规则是否有效
var valid = false;
// 创建一个新的媒体规则对象
var mediaRule = new jscsspMediaRule();
// 设置媒体规则的当前行数
mediaRule.currentLine = currentLine;
// 保存当前状态
this.preserveState();
// 获取下一个 token
var token = this.getToken(true, true);
// 标记是否找到媒体类型
var foundMedia = false;
// 循环处理 token
while (token.isNotNull()) {
if (token.isIdent()) {
// 找到媒体类型
foundMedia = true;
// 拼接媒体类型到字符串 s 中
s += " " + token.value;
// 将媒体类型添加到媒体规则的媒体列表中
mediaRule.media.push(token.value);
// 获取下一个 token
token = this.getToken(true, true);
if (token.isSymbol(",")) {
// 如果是逗号,拼接逗号到字符串 s 中
s += ",";
} else {
if (token.isSymbol("{"))
// 如果是左花括号,将 token 放回队列
this.ungetToken();
else {
// 错误处理,将 token 类型设为 NULL_TYPE
token.type = jscsspToken.NULL_TYPE;
break;
}
}
}
else if (token.isSymbol("{"))
// 如果是左花括号,跳出循环
break;
else if (foundMedia) {
// 如果已经找到媒体类型,但当前 token 不符合要求,将 token 类型设为 NULL_TYPE
token.type = jscsspToken.NULL_TYPE;
// 不是有效的媒体列表,跳出循环
break;
}
// 获取下一个 token
token = this.getToken(true, true);
}
if (token.isSymbol("{") && mediaRule.media.length) {
// 如果是左花括号且媒体列表不为空,开始解析样式规则
s += " { ";
// 获取下一个 token
token = this.getToken(true, false);
while (token.isNotNull()) {
if (token.isComment() && this.mPreserveComments) {
// 如果是注释且需要保留注释,拼接注释到字符串 s 中
s += " " + token.value;
// 创建一个新的注释对象
var comment = new jscsspComment();
// 设置注释对象的解析后的 CSS 文本
comment.parsedCssText = token.value;
// 将注释对象添加到媒体规则的 CSS 规则列表中
mediaRule.cssRules.push(comment);
} else if (token.isSymbol("}")) {
// 如果是右花括号,标记规则有效
valid = true;
break;
} else {
// 解析样式规则
var r = this.parseStyleRule(token, mediaRule, true);
if (r)
// 如果解析成功,拼接解析结果到字符串 s 中
s += r;
}
// 获取下一个 token
token = this.getToken(true, false);
}
}
if (valid) {
// 如果规则有效,忘记保存的状态
this.forgetState();
// 设置媒体规则的解析后的 CSS 文本
mediaRule.parsedCssText = s;
// 将媒体规则添加到样式表的 CSS 规则列表中
aSheet.cssRules.push(mediaRule);
return true;
}
// 恢复保存的状态
this.restoreState();
return false;
},
// 去除字符串首尾空格的函数
// str: 要处理的字符串
trim11: function(str) {
// 去除字符串开头的空格
str = str.replace(/^\s+/, '');
// 从字符串末尾开始遍历
for (var i = str.length - 1; i >= 0; i--) {
if (/\S/.test( str.charAt(i) )) {
// 如果当前字符不是空格,截取字符串
str = str.substring(0, i + 1);
break;
}
}
return str;
},
// 解析样式规则的函数
// aToken: 当前的 token
// aOwner: 规则的所有者
// aIsInsideMediaRule: 是否在媒体规则内部
parseStyleRule: function(aToken, aOwner, aIsInsideMediaRule)
{
// 计算当前行数
var currentLine = CountLF(this.mScanner.getAlreadyScanned());
// 保存当前状态
this.preserveState();
// 解析选择器
var selector = this.parseSelector(aToken, false);
// 标记规则是否有效
var valid = false;
// 声明列表
var declarations = [];
if (selector) {
// 去除选择器首尾空格
selector = this.trim11(selector.selector);
// 选择器字符串
var s = selector;
// 获取下一个 token
var token = this.getToken(true, true);
if (token.isSymbol("{")) {
// 如果是左花括号,拼接左花括号到字符串 s 中
s += " { ";
// 获取下一个 token
var token = this.getToken(true, false);
while (true) {
if (!token.isNotNull()) {
// 如果 token 为空,标记规则有效
valid = true;
break;
}
if (token.isSymbol("}")) {
// 如果是右花括号,拼接右花括号到字符串 s 中,标记规则有效
s += "}";
valid = true;
break;
} else {
// 解析声明
var d = this.parseDeclaration(token, declarations, true, true, aOwner);
s += ((d && declarations.length) ? " " : "") + d;
}
// 获取下一个 token
token = this.getToken(true, false);
}
}
}
else {
// 选择器无效,整个规则无效
}
if (valid) {
// 如果规则有效,创建一个新的样式规则对象
var rule = new jscsspStyleRule();
// 设置样式规则的当前行数
rule.currentLine = currentLine;
// 设置样式规则的解析后的 CSS 文本
rule.parsedCssText = s;
// 设置样式规则的声明列表
rule.declarations = declarations;
// 设置样式规则的选择器文本
rule.mSelectorText = selector;
if (aIsInsideMediaRule)
// 如果在媒体规则内部,设置样式规则的父规则
rule.parentRule = aOwner;
else
// 否则,设置样式规则的父样式表
rule.parentStyleSheet = aOwner;
// 将样式规则添加到所有者的 CSS 规则列表中
aOwner.cssRules.push(rule);
return s;
}
// 恢复保存的状态
this.restoreState();
// 获取当前 token 的值
s = this.currentToken().value;
// 添加未知的 @ 规则
this.addUnknownAtRule(aOwner, s);
return "";
},
// 解析选择器的函数
// aToken: 当前的 token
// aParseSelectorOnly: 是否只解析选择器
parseSelector: function(aToken, aParseSelectorOnly) {
// 选择器字符串
var s = "";
// 选择器的优先级
var specificity = {a: 0, b: 0, c: 0, d: 0};
// 标记是否是选择器链的第一个元素
var isFirstInChain = true;
// 当前 token
var token = aToken;
// 标记选择器是否有效
var valid = false;
// 标记是否找到组合器
var combinatorFound = false;
while (true) {
if (!token.isNotNull()) {
if (aParseSelectorOnly)
// 如果只解析选择器,返回选择器和优先级
return {selector: s, specificity: specificity };
return "";
}
if (!aParseSelectorOnly && token.isSymbol("{")) {
// 如果不是只解析选择器且遇到左花括号,结束选择器解析
valid = !combinatorFound;
if (valid) this.ungetToken();
break;
}
if (token.isSymbol(",")) {
// 如果是逗号,拼接逗号到字符串 s 中
s += token.value;
// 标记是选择器链的第一个元素
isFirstInChain = true;
// 标记未找到组合器
combinatorFound = false;
// 获取下一个 token
token = this.getToken(false, true);
continue;
}
// 处理组合器和分组
else if (!combinatorFound
&& (token.isWhiteSpace()
|| token.isSymbol(">")
|| token.isSymbol("+")
|| token.isSymbol("~"))) {
if (token.isWhiteSpace()) {
// 如果是空格,拼接空格到字符串 s 中
s += " ";
// 查看下一个 token
var nextToken = this.lookAhead(true, true);
if (!nextToken.isNotNull()) {
if (aParseSelectorOnly)
// 如果只解析选择器,返回选择器和优先级
return {selector: s, specificity: specificity };
return "";
}
if (nextToken.isSymbol(">")
|| nextToken.isSymbol("+")
|| nextToken.isSymbol("~")) {
// 如果下一个 token 是组合器,获取下一个 token 并拼接
token = this.getToken(true, true);
s += token.value + " ";
// 标记找到组合器
combinatorFound = true;
}
}
else {
// 如果不是空格,拼接组合器到字符串 s 中
s += token.value;
// 标记找到组合器
combinatorFound = true;
}
// 标记是选择器链的第一个元素
isFirstInChain = true;
// 获取下一个 token
token = this.getToken(true, true);
continue;
}
else {
// 解析简单选择器
var simpleSelector = this.parseSimpleSelector(token, isFirstInChain, true);
if (!simpleSelector)
// 如果解析失败,跳出循环
break;
// 拼接简单选择器到字符串 s 中
s += simpleSelector.selector;
// 更新选择器的优先级
specificity.b += simpleSelector.specificity.b;
specificity.c += simpleSelector.specificity.c;
specificity.d += simpleSelector.specificity.d;
// 标记不是选择器链的第一个元素
isFirstInChain = false;
// 标记未找到组合器
combinatorFound = false;
}
// 获取下一个 token
token = this.getToken(false, true);
}
if (valid) {
// 如果选择器有效,返回选择器和优先级
return {selector: s, specificity: specificity };
}
return "";
},
// 判断是否为伪元素的函数
// aIdent: 要判断的标识符
isPseudoElement: function(aIdent)
{
switch (aIdent) {
case "first-letter":
case "first-line":
case "before":
case "after":
case "marker":
return true;
break;
default: return false;
break;
}
},
// 解析简单选择器的函数
// token: 当前的 token
// isFirstInChain: 是否是选择器链的第一个元素
// canNegate: 是否可以使用否定伪类
parseSimpleSelector: function(token, isFirstInChain, canNegate)
{
// 简单选择器字符串
var s = "";
// 简单选择器的优先级
var specificity = {a: 0, b: 0, c: 0, d: 0};
if (isFirstInChain
&& (token.isSymbol("*") || token.isSymbol("|") || token.isIdent())) {
// 如果是选择器链的第一个元素,处理类型或通用选择器
if (token.isSymbol("*") || token.isIdent()) {
// 可能是前缀或通用选择器
s += token.value;
// 标记是否为标识符
var isIdent = token.isIdent();
// 获取下一个 token
token = this.getToken(false, true);
if (token.isSymbol("|")) {
// 如果是竖线,拼接竖线到字符串 s 中
s += token.value;
// 获取下一个 token
token = this.getToken(false, true);
if (token.isIdent() || token.isSymbol("*")) {
// 如果是标识符或星号,拼接标识符或星号到字符串 s 中
s += token.value;
if (token.isIdent())
// 如果是标识符,更新优先级
specificity.d++;
} else
// 错误处理,返回 null
return null;
} else {
// 将 token 放回队列
this.ungetToken();
if (isIdent)
// 如果是标识符,更新优先级
specificity.d++;
}
} else if (token.isSymbol("|")) {
// 如果是竖线,拼接竖线到字符串 s 中
s += token.value;
// 获取下一个 token
token = this.getToken(false, true);
if (token.isIdent() || token.isSymbol("*")) {
// 如果是标识符或星号,拼接标识符或星号到字符串 s 中
s += token.value;
if (token.isIdent())
// 如果是标识符,更新优先级
specificity.d++;
} else
// 错误处理,返回 null
return null;
}
}
else if (token.isSymbol(".") || token.isSymbol("#")) {
// 如果是点号或井号,处理类选择器或 ID 选择器
var isClass = token.isSymbol(".");
// 拼接点号或井号到字符串 s 中
s += token.value;
// 获取下一个 token
token = this.getToken(false, true);
if (token.isIdent()) {
// 如果是标识符,拼接标识符到字符串 s 中
s += token.value;
if (isClass)
// 如果是类选择器,更新优先级
specificity.c++;
else
// 如果是 ID 选择器,更新优先级
specificity.b++;
}
else
// 错误处理,返回 null
return null;
}
else if (token.isSymbol(":")) {
// 如果是冒号,处理伪类或伪元素
s += token.value;
// 获取下一个 token
token = this.getToken(false, true);
if (token.isSymbol(":")) {
// 如果是双冒号,拼接双冒号到字符串 s 中
s += token.value;
// 获取下一个 token
token = this.getToken(false, true);
}
if (token.isIdent()) {
// 如果是标识符,拼接标识符到字符串 s 中
s += token.value;
if (this.isPseudoElement(token.value))
// 如果是伪元素,更新优先级
specificity.d++;
else
// 如果是伪类,更新优先级
specificity.c++;
}
else if (token.isFunction()) {
// 如果是函数,拼接函数到字符串 s 中
s += token.value;
if (token.isFunction(":not(")) {
// 如果是 :not() 函数
if (!canNegate)
// 如果不允许使用否定伪类,返回 null
return null;
// 获取下一个 token
token = this.getToken(true, true);
// 解析简单选择器
var simpleSelector = this.parseSimpleSelector(token, isFirstInChain, false);
if (!simpleSelector)
// 如果解析失败,返回 null
return null;
else {
// 拼接简单选择器到字符串 s 中
s += simpleSelector.selector;
// 获取下一个 token
token = this.getToken(true, true);
if (token.isSymbol(")"))
// 如果是右括号,拼接右括号到字符串 s 中
s += ")";
else
// 错误处理,返回 null
return null;
}
// 更新优先级
specificity.c++;
}
else {
while (true) {
// 处理函数参数
token = this.getToken(false, true);
if (token.isSymbol(")")) {
// 如果是右括号,拼接右括号到字符串 s 中
s += ")";
break;
} else
// 拼接参数到字符串 s 中
s += token.value;
}
// 更新优先级
specificity.c++;
}
} else
// 错误处理,返回 null
return null;
} else if (token.isSymbol("[")) {
// 如果是左方括号,处理属性选择器
s += "[";
// 获取下一个 token
token = this.getToken(true, true);
if (token.isIdent() || token.isSymbol("*")) {
// 如果是标识符或星号,拼接标识符或星号到字符串 s 中
s += token.value;
// 获取下一个 token
var nextToken = this.getToken(true, true);
if (token.isSymbol("|")) {
// 如果是竖线,拼接竖线到字符串 s 中
s += "|";
// 获取下一个 token
token = this.getToken(true, true);
if (token.isIdent())
// 如果是标识符,拼接标识符到字符串 s 中
s += token.value;
else
// 错误处理,返回 null
return null;
} else
// 将 token 放回队列
this.ungetToken();
} else if (token.isSymbol("|")) {
// 如果是竖线,拼接竖线到字符串 s 中
s += "|";
// 获取下一个 token
token = this.getToken(true, true);
if (token.isIdent())
// 如果是标识符,拼接标识符到字符串 s 中
s += token.value;
else
// 错误处理,返回 null
return null;
}
else
// 错误处理,返回 null
return null;
// 处理属性选择器的操作符
token = this.getToken(true, true);
if (token.isIncludes()
|| token.isDashmatch()
|| token.isBeginsmatch()
|| token.isEndsmatch()
|| token.isContainsmatch()
|| token.isSymbol("=")) {
// 如果是操作符,拼接操作符到字符串 s 中
s += token.value;
// 获取下一个 token
token = this.getToken(true, true);
if (token.isString() || token.isIdent()) {
// 如果是字符串或标识符,拼接字符串或标识符到字符串 s 中
s += token.value;
// 获取下一个 token
token = this.getToken(true, true);
}
else
// 错误处理,返回 null
return null;
if (token.isSymbol("]")) {
// 如果是右方括号,拼接右方括号到字符串 s 中
s += token.value;
// 更新优先级
specificity.c++;
}
else
// 错误处理,返回 null
return null;
}
else if (token.isSymbol("]")) {
// 如果是右方括号,拼接右方括号到字符串 s 中
s += token.value;
// 更新优先级
specificity.c++;
}
else
// 错误处理,返回 null
return null;
}
else if (token.isWhiteSpace()) {
// 如果是空格,查看下一个 token
var t = this.lookAhead(true, true);
if (t.isSymbol('{'))
// 如果下一个 token 是左花括号,返回空字符串
return ""
}
if (s)
// 如果简单选择器字符串不为空,返回简单选择器和优先级
return {selector: s, specificity: specificity };
return null;
},
// 保存当前状态的函数
preserveState: function() {
// 将当前 token 保存到保存的 token 列表中
this.mPreservedTokens.push(this.currentToken());
// 保存扫描器的状态
this.mScanner.preserveState();
},
// 恢复保存状态的函数
restoreState: function() {
if (this.mPreservedTokens.length) {
// 如果保存的 token 列表不为空,恢复扫描器的状态
this.mScanner.restoreState();
// 从保存的 token 列表中取出最后一个 token
this.mToken = this.mPreservedTokens.pop();
}
},
// 忘记保存状态的函数
forgetState: function() {
if (this.mPreservedTokens.length) {
// 如果保存的 token 列表不为空,忘记扫描器的状态
this.mScanner.forgetState();
// 从保存的 token 列表中取出最后一个 token
this.mPreservedTokens.pop();
}
},
// 解析 CSS 字符串的函数
// aString: 要解析的 CSS 字符串
// aTryToPreserveWhitespaces: 是否尝试保留空格
// aTryToPreserveComments: 是否尝试保留注释
parse: function(aString, aTryToPreserveWhitespaces, aTryToPreserveComments) {
if (!aString)
// 如果字符串为空,返回 null
return null;
// 设置是否保留空格
this.mPreserveWS = aTryToPreserveWhitespaces;
// 设置是否保留注释
this.mPreserveComments = aTryToPreserveComments;
// 初始化保存的 token 列表
this.mPreservedTokens = [];
// 初始化扫描器
this.mScanner.init(aString);
// 创建一个新的样式表对象
var sheet = new jscsspStylesheet();
// @charset 规则只能出现在样式表的开头
var token = this.getToken(false, false);
if (!token.isNotNull())
return;
if (token.isAtRule("@charset")) {
// 解析 @charset 规则
this.parseCharsetRule(token, sheet);
// 获取下一个 token
token = this.getToken(false, false);
}
// 标记是否找到样式规则
var foundStyleRules = false;
// 标记是否找到 @import 规则
var foundImportRules = false;
// 标记是否找到 @namespace 规则
var foundNameSpaceRules = false;
while (true) {
if (!token.isNotNull())
// 如果 token 为空,跳出循环
break;
if (token.isWhiteSpace())
{
if (aTryToPreserveWhitespaces)
// 如果需要保留空格,添加空格到样式表中
this.addWhitespace(sheet, token.value);
}
else if (token.isComment())
{
if (this.mPreserveComments)
// 如果需要保留注释,添加注释到样式表中
this.addComment(sheet, token.value);
}
else if (token.isAtRule()) {
if (token.isAtRule("@variables")) {
// 如果是 @variables 规则
if (!foundImportRules && !foundStyleRules)
// 如果还没有找到 @import 规则和样式规则,解析 @variables 规则
this.parseVariablesRule(token, sheet);
else {
// 错误处理,报告错误并添加未知的 @ 规则
this.reportError(kVARIABLES_RULE_POSITION);
this.addUnknownAtRule(sheet, token.value);
}
}
else if (token.isAtRule("@import")) {
// 如果是 @import 规则
// @import 规则必须出现在所有样式规则和 @namespace 规则之前
if (!foundStyleRules && !foundNameSpaceRules)
// 如果还没有找到样式规则和 @namespace 规则,解析 @import 规则
foundImportRules = this.parseImportRule(token, sheet);
else {
// 错误处理,报告错误并添加未知的 @ 规则
this.reportError(kIMPORT_RULE_POSITION);
this.addUnknownAtRule(sheet, token.value);
}
}
else if (token.isAtRule("@namespace")) {
// 如果是 @namespace 规则
// @namespace 规则必须出现在所有样式规则之后,所有 @import 规则之前
if (!foundStyleRules)
// 如果还没有找到样式规则,解析 @namespace 规则
foundNameSpaceRules = this.parseNamespaceRule(token, sheet);
else {
// 错误处理,报告错误并添加未知的 @ 规则
this.reportError(kNAMESPACE_RULE_POSITION);
this.addUnknownAtRule(sheet, token.value);
}
}
else if (token.isAtRule("@font-face")) {
// 如果是 @font-face 规则
if (this.parseFontFaceRule(token, sheet))
// 如果解析成功,标记找到样式规则
foundStyleRules = true;
else
// 解析失败,添加未知的 @ 规则
this.addUnknownAtRule(sheet, token.value);
}
else if (token.isAtRule("@page")) {
// 如果是 @page 规则
if (this.parsePageRule(token, sheet))
// 如果解析成功,标记找到样式规则
foundStyleRules = true;
else
// 解析失败,添加未知的 @ 规则
this.addUnknownAtRule(sheet, token.value);
}
else if (token.isAtRule("@media")) {
// 如果是 @media 规则
if (this.parseMediaRule(token, sheet))
// 如果解析成功,标记找到样式规则
foundStyleRules = true;
else
// 解析失败,添加未知的 @ 规则
this.addUnknownAtRule(sheet, token.value);
}
else if (token.isAtRule("@keyframes")) {
// 如果是 @keyframes 规则
if (!this.parseKeyframesRule(token, sheet))
// 如果解析失败,添加未知的 @ 规则
this.addUnknownAtRule(sheet, token.value);
}
else if (token.isAtRule("@charset")) {
// 如果是 @charset 规则出现在非开头位置,报告错误并添加未知的 @ 规则
this.reportError(kCHARSET_RULE_CHARSET_SOF);
this.addUnknownAtRule(sheet, token.value);
}
else {
// 未知的 @ 规则,报告错误并添加未知的 @ 规则
this.reportError(kUNKNOWN_AT_RULE);
this.addUnknownAtRule(sheet, token.value);
}
}
else // 普通样式规则
{
// 解析样式规则
var ruleText = this.parseStyleRule(token, sheet, false);
if (ruleText)
// 如果解析成功,标记找到样式规则
foundStyleRules = true;
}
// 获取下一个 token
token = this.getToken(false);
}
return sheet;
}
};
// jscsspToken 构造函数
// aType: token 的类型
// aValue: token 的值
// aUnit: token 的单位
function jscsspToken(aType, aValue, aUnit)
{
// 设置 token 的类型
this.type = aType;
// 设置 token 的值
this.value = aValue;
// 设置 token 的单位
this.unit = aUnit;
}
// 定义 token 的类型
jscsspToken.NULL_TYPE = 0;
jscsspToken.WHITESPACE_TYPE = 1;
jscsspToken.STRING_TYPE = 2;
jscsspToken.COMMENT_TYPE = 3;
jscsspToken.NUMBER_TYPE = 4;
jscsspToken.IDENT_TYPE = 5;
jscsspToken.FUNCTION_TYPE = 6;
jscsspToken.ATRULE_TYPE = 7;
jscsspToken.INCLUDES_TYPE = 8;
jscsspToken.DASHMATCH_TYPE = 9;
jscsspToken.BEGINSMATCH_TYPE = 10;
jscsspToken.ENDSMATCH_TYPE = 11;
jscsspToken.CONTAINSMATCH_TYPE = 12;
jscsspToken.SYMBOL_TYPE = 13;
jscsspToken.DIMENSION_TYPE = 14;
jscsspToken.PERCENTAGE_TYPE = 15;
jscsspToken.HEX_TYPE = 16;
// jscsspToken 原型对象
jscsspToken.prototype = {
// 判断 token 是否不为空的函数
isNotNull: function ()
{
return this.type;
},
// 判断 token 是否为指定类型和值的函数
_isOfType: function (aType, aValue)
{
return (this.type == aType && (!aValue || this.value.toLowerCase() == aValue));
},
// 判断 token 是否为空格的函数
isWhiteSpace: function(w)
{
return this._isOfType(jscsspToken.WHITESPACE_TYPE, w);
},
// 判断 token 是否为字符串的函数
isString: function()
{
return this._isOfType(jscsspToken.STRING_TYPE);
},
// 判断 token 是否为注释的函数
isComment: function()
{
return this._isOfType(jscsspToken.COMMENT_TYPE);
},
// 判断 token 是否为数字的函数
isNumber: function(n)
{
return this._isOfType(jscsspToken.NUMBER_TYPE, n);
},
// 判断 token 是否为符号的函数
isSymbol: function(c)
{
return this._isOfType(jscsspToken.SYMBOL_TYPE, c);
},
// 判断 token 是否为标识符的函数
isIdent: function(i)
{
return this._isOfType(jscsspToken.IDENT_TYPE, i);
},
// 判断 token 是否为函数的函数
isFunction: function(f)
{
return this._isOfType(jscsspToken.FUNCTION_TYPE, f);
},
// 判断 token 是否为 @ 规则的函数
isAtRule: function(a)
{
return this._isOfType(jscsspToken.ATRULE_TYPE, a);
},
// 判断 token 是否为包含操作符的函数
isIncludes: function()
{
return this._isOfType(jscsspToken.INCLUDES_TYPE);
},
// 判断 token 是否为连字符匹配操作符的函数
isDashmatch: function()
{
return this._isOfType(jscsspToken.DASHMATCH_TYPE);
},
// 判断 token 是否为开头匹配操作符的函数
isBeginsmatch: function()
{
return this._isOfType(jscsspToken.BEGINSMATCH_TYPE);
},
// 判断 token 是否为结尾匹配操作符的函数
isEndsmatch: function()
{
return this._isOfType(jscsspToken.ENDSMATCH_TYPE);
},
// 判断 token 是否为包含匹配操作符的函数
isContainsmatch: function()
{
return this._isOfType(jscsspToken.CONTAINSMATCH_TYPE);
},
// 判断 token 是否为符号的函数
isSymbol: function(c)
{
return this._isOfType(jscsspToken.SYMBOL_TYPE, c);
},
// 判断 token 是否为维度的函数
isDimension: function()
{
return this._isOfType(jscsspToken.DIMENSION_TYPE);
},
// 判断 token 是否为百分比的函数
isPercentage: function()
{
return this._isOfType(jscsspToken.PERCENTAGE_TYPE);
},
// 判断 token 是否为十六进制的函数
isHex: function()
{
return this._isOfType(jscsspToken.HEX_TYPE);
},
// 判断 token 是否为指定单位的维度的函数
isDimensionOfUnit: function(aUnit)
{
return (this.isDimension() && this.unit == aUnit);
},
// 判断 token 是否为长度的函数
isLength: function()
{
return (this.isPercentage() ||
this.isDimensionOfUnit("cm") ||
this.isDimensionOfUnit("mm") ||
this.isDimensionOfUnit("in") ||
this.isDimensionOfUnit("pc") ||
this.isDimensionOfUnit("px") ||
this.isDimensionOfUnit("em") ||
this.isDimensionOfUnit("ex") ||
this.isDimensionOfUnit("pt"));
},
// 判断 token 是否为角度的函数
isAngle: function()
{
return (this.isDimensionOfUnit("deg") ||
this.isDimensionOfUnit("rad") ||
this.isDimensionOfUnit("grad"));
}
}
// 定义规则类型常量
var kJscsspUNKNOWN_RULE = 0;
var kJscsspSTYLE_RULE = 1
var kJscsspCHARSET_RULE = 2;
var kJscsspIMPORT_RULE = 3;
var kJscsspMEDIA_RULE = 4;
var kJscsspFONT_FACE_RULE = 5;
var kJscsspPAGE_RULE = 6;
var kJscsspKEYFRAMES_RULE = 7;
var kJscsspKEYFRAME_RULE = 8;
var kJscsspNAMESPACE_RULE = 100;
var kJscsspCOMMENT = 101;
var kJscsspWHITE_SPACE