123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995 |
- var CSSOM = {};
- /**
- * @constructor
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration
- */
- CSSOM.CSSStyleDeclaration = function CSSStyleDeclaration(){
- this.length = 0;
- this.parentRule = null;
- // NON-STANDARD
- this._importants = {};
- };
- CSSOM.CSSStyleDeclaration.prototype = {
- constructor: CSSOM.CSSStyleDeclaration,
- /**
- *
- * @param {string} name
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-getPropertyValue
- * @return {string} the value of the property if it has been explicitly set for this declaration block.
- * Returns the empty string if the property has not been set.
- */
- getPropertyValue: function(name) {
- return this[name] || "";
- },
- /**
- *
- * @param {string} name
- * @param {string} value
- * @param {string} [priority=null] "important" or null
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-setProperty
- */
- setProperty: function(name, value, priority) {
- if (this[name]) {
- // Property already exist. Overwrite it.
- var index = Array.prototype.indexOf.call(this, name);
- if (index < 0) {
- this[this.length] = name;
- this.length++;
- }
- } else {
- // New property.
- this[this.length] = name;
- this.length++;
- }
- this[name] = value + "";
- this._importants[name] = priority;
- },
- /**
- *
- * @param {string} name
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-removeProperty
- * @return {string} the value of the property if it has been explicitly set for this declaration block.
- * Returns the empty string if the property has not been set or the property name does not correspond to a known CSS property.
- */
- removeProperty: function(name) {
- if (!(name in this)) {
- return "";
- }
- var index = Array.prototype.indexOf.call(this, name);
- if (index < 0) {
- return "";
- }
- var prevValue = this[name];
- this[name] = "";
- // That's what WebKit and Opera do
- Array.prototype.splice.call(this, index, 1);
- // That's what Firefox does
- //this[index] = ""
- return prevValue;
- },
- getPropertyCSSValue: function() {
- //FIXME
- },
- /**
- *
- * @param {String} name
- */
- getPropertyPriority: function(name) {
- return this._importants[name] || "";
- },
- /**
- * element.style.overflow = "auto"
- * element.style.getPropertyShorthand("overflow-x")
- * -> "overflow"
- */
- getPropertyShorthand: function() {
- //FIXME
- },
- isPropertyImplicit: function() {
- //FIXME
- },
- // Doesn't work in IE < 9
- get cssText(){
- var properties = [];
- for (var i=0, length=this.length; i < length; ++i) {
- var name = this[i];
- var value = this.getPropertyValue(name);
- var priority = this.getPropertyPriority(name);
- if (priority) {
- priority = " !" + priority;
- }
- properties[i] = name + ": " + value + priority + ";";
- }
- return properties.join(" ");
- },
- set cssText(text){
- var i, name;
- for (i = this.length; i--;) {
- name = this[i];
- this[name] = "";
- }
- Array.prototype.splice.call(this, 0, this.length);
- this._importants = {};
- var dummyRule = CSSOM.parse('#bogus{' + text + '}').cssRules[0].style;
- var length = dummyRule.length;
- for (i = 0; i < length; ++i) {
- name = dummyRule[i];
- this.setProperty(dummyRule[i], dummyRule.getPropertyValue(name), dummyRule.getPropertyPriority(name));
- }
- }
- };
- /**
- * @constructor
- * @see http://dev.w3.org/csswg/cssom/#the-cssrule-interface
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule
- */
- CSSOM.CSSRule = function CSSRule() {
- this.parentRule = null;
- this.parentStyleSheet = null;
- };
- CSSOM.CSSRule.UNKNOWN_RULE = 0; // obsolete
- CSSOM.CSSRule.STYLE_RULE = 1;
- CSSOM.CSSRule.CHARSET_RULE = 2; // obsolete
- CSSOM.CSSRule.IMPORT_RULE = 3;
- CSSOM.CSSRule.MEDIA_RULE = 4;
- CSSOM.CSSRule.FONT_FACE_RULE = 5;
- CSSOM.CSSRule.PAGE_RULE = 6;
- CSSOM.CSSRule.KEYFRAMES_RULE = 7;
- CSSOM.CSSRule.KEYFRAME_RULE = 8;
- CSSOM.CSSRule.MARGIN_RULE = 9;
- CSSOM.CSSRule.NAMESPACE_RULE = 10;
- CSSOM.CSSRule.COUNTER_STYLE_RULE = 11;
- CSSOM.CSSRule.SUPPORTS_RULE = 12;
- CSSOM.CSSRule.DOCUMENT_RULE = 13;
- CSSOM.CSSRule.FONT_FEATURE_VALUES_RULE = 14;
- CSSOM.CSSRule.VIEWPORT_RULE = 15;
- CSSOM.CSSRule.REGION_STYLE_RULE = 16;
- CSSOM.CSSRule.CONTAINER_RULE = 17;
- CSSOM.CSSRule.LAYER_BLOCK_RULE = 18;
- CSSOM.CSSRule.STARTING_STYLE_RULE = 1002;
- CSSOM.CSSRule.prototype = {
- constructor: CSSOM.CSSRule,
- //FIXME
- };
- exports.CSSRule = CSSOM.CSSRule;
- ///CommonJS
- /**
- * @constructor
- * @see https://drafts.csswg.org/cssom/#the-cssgroupingrule-interface
- */
- CSSOM.CSSGroupingRule = function CSSGroupingRule() {
- CSSOM.CSSRule.call(this);
- this.cssRules = [];
- };
- CSSOM.CSSGroupingRule.prototype = new CSSOM.CSSRule();
- CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
- /**
- * Used to insert a new CSS rule to a list of CSS rules.
- *
- * @example
- * cssGroupingRule.cssText
- * -> "body{margin:0;}"
- * cssGroupingRule.insertRule("img{border:none;}", 1)
- * -> 1
- * cssGroupingRule.cssText
- * -> "body{margin:0;}img{border:none;}"
- *
- * @param {string} rule
- * @param {number} [index]
- * @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-insertrule
- * @return {number} The index within the grouping rule's collection of the newly inserted rule.
- */
- CSSOM.CSSGroupingRule.prototype.insertRule = function insertRule(rule, index) {
- if (index < 0 || index > this.cssRules.length) {
- throw new RangeError("INDEX_SIZE_ERR");
- }
- var cssRule = CSSOM.parse(rule).cssRules[0];
- cssRule.parentRule = this;
- this.cssRules.splice(index, 0, cssRule);
- return index;
- };
- /**
- * Used to delete a rule from the grouping rule.
- *
- * cssGroupingRule.cssText
- * -> "img{border:none;}body{margin:0;}"
- * cssGroupingRule.deleteRule(0)
- * cssGroupingRule.cssText
- * -> "body{margin:0;}"
- *
- * @param {number} index within the grouping rule's rule list of the rule to remove.
- * @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-deleterule
- */
- CSSOM.CSSGroupingRule.prototype.deleteRule = function deleteRule(index) {
- if (index < 0 || index >= this.cssRules.length) {
- throw new RangeError("INDEX_SIZE_ERR");
- }
- this.cssRules.splice(index, 1)[0].parentRule = null;
- };
- /**
- * @constructor
- * @see https://www.w3.org/TR/css-conditional-3/#the-cssconditionrule-interface
- */
- CSSOM.CSSConditionRule = function CSSConditionRule() {
- CSSOM.CSSGroupingRule.call(this);
- this.cssRules = [];
- };
- CSSOM.CSSConditionRule.prototype = new CSSOM.CSSGroupingRule();
- CSSOM.CSSConditionRule.prototype.constructor = CSSOM.CSSConditionRule;
- CSSOM.CSSConditionRule.prototype.conditionText = ''
- CSSOM.CSSConditionRule.prototype.cssText = ''
- /**
- * @constructor
- * @see http://dev.w3.org/csswg/cssom/#cssstylerule
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleRule
- */
- CSSOM.CSSStyleRule = function CSSStyleRule() {
- CSSOM.CSSRule.call(this);
- this.selectorText = "";
- this.style = new CSSOM.CSSStyleDeclaration();
- this.style.parentRule = this;
- };
- CSSOM.CSSStyleRule.prototype = new CSSOM.CSSRule();
- CSSOM.CSSStyleRule.prototype.constructor = CSSOM.CSSStyleRule;
- CSSOM.CSSStyleRule.prototype.type = 1;
- Object.defineProperty(CSSOM.CSSStyleRule.prototype, "cssText", {
- get: function() {
- var text;
- if (this.selectorText) {
- text = this.selectorText + " {" + this.style.cssText + "}";
- } else {
- text = "";
- }
- return text;
- },
- set: function(cssText) {
- var rule = CSSOM.CSSStyleRule.parse(cssText);
- this.style = rule.style;
- this.selectorText = rule.selectorText;
- }
- });
- /**
- * NON-STANDARD
- * lightweight version of parse.js.
- * @param {string} ruleText
- * @return CSSStyleRule
- */
- CSSOM.CSSStyleRule.parse = function(ruleText) {
- var i = 0;
- var state = "selector";
- var index;
- var j = i;
- var buffer = "";
- var SIGNIFICANT_WHITESPACE = {
- "selector": true,
- "value": true
- };
- var styleRule = new CSSOM.CSSStyleRule();
- var name, priority="";
- for (var character; (character = ruleText.charAt(i)); i++) {
- switch (character) {
- case " ":
- case "\t":
- case "\r":
- case "\n":
- case "\f":
- if (SIGNIFICANT_WHITESPACE[state]) {
- // Squash 2 or more white-spaces in the row into 1
- switch (ruleText.charAt(i - 1)) {
- case " ":
- case "\t":
- case "\r":
- case "\n":
- case "\f":
- break;
- default:
- buffer += " ";
- break;
- }
- }
- break;
- // String
- case '"':
- j = i + 1;
- index = ruleText.indexOf('"', j) + 1;
- if (!index) {
- throw '" is missing';
- }
- buffer += ruleText.slice(i, index);
- i = index - 1;
- break;
- case "'":
- j = i + 1;
- index = ruleText.indexOf("'", j) + 1;
- if (!index) {
- throw "' is missing";
- }
- buffer += ruleText.slice(i, index);
- i = index - 1;
- break;
- // Comment
- case "/":
- if (ruleText.charAt(i + 1) === "*") {
- i += 2;
- index = ruleText.indexOf("*/", i);
- if (index === -1) {
- throw new SyntaxError("Missing */");
- } else {
- i = index + 1;
- }
- } else {
- buffer += character;
- }
- break;
- case "{":
- if (state === "selector") {
- styleRule.selectorText = buffer.trim();
- buffer = "";
- state = "name";
- }
- break;
- case ":":
- if (state === "name") {
- name = buffer.trim();
- buffer = "";
- state = "value";
- } else {
- buffer += character;
- }
- break;
- case "!":
- if (state === "value" && ruleText.indexOf("!important", i) === i) {
- priority = "important";
- i += "important".length;
- } else {
- buffer += character;
- }
- break;
- case ";":
- if (state === "value") {
- styleRule.style.setProperty(name, buffer.trim(), priority);
- priority = "";
- buffer = "";
- state = "name";
- } else {
- buffer += character;
- }
- break;
- case "}":
- if (state === "value") {
- styleRule.style.setProperty(name, buffer.trim(), priority);
- priority = "";
- buffer = "";
- } else if (state === "name") {
- break;
- } else {
- buffer += character;
- }
- state = "selector";
- break;
- default:
- buffer += character;
- break;
- }
- }
- return styleRule;
- };
- /**
- * @constructor
- * @see http://dev.w3.org/csswg/cssom/#the-medialist-interface
- */
- CSSOM.MediaList = function MediaList(){
- this.length = 0;
- };
- CSSOM.MediaList.prototype = {
- constructor: CSSOM.MediaList,
- /**
- * @return {string}
- */
- get mediaText() {
- return Array.prototype.join.call(this, ", ");
- },
- /**
- * @param {string} value
- */
- set mediaText(value) {
- var values = value.split(",");
- var length = this.length = values.length;
- for (var i=0; i<length; i++) {
- this[i] = values[i].trim();
- }
- },
- /**
- * @param {string} medium
- */
- appendMedium: function(medium) {
- if (Array.prototype.indexOf.call(this, medium) === -1) {
- this[this.length] = medium;
- this.length++;
- }
- },
- /**
- * @param {string} medium
- */
- deleteMedium: function(medium) {
- var index = Array.prototype.indexOf.call(this, medium);
- if (index !== -1) {
- Array.prototype.splice.call(this, index, 1);
- }
- }
- };
- /**
- * @constructor
- * @see http://dev.w3.org/csswg/cssom/#cssmediarule
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule
- */
- CSSOM.CSSMediaRule = function CSSMediaRule() {
- CSSOM.CSSConditionRule.call(this);
- this.media = new CSSOM.MediaList();
- };
- CSSOM.CSSMediaRule.prototype = new CSSOM.CSSConditionRule();
- CSSOM.CSSMediaRule.prototype.constructor = CSSOM.CSSMediaRule;
- CSSOM.CSSMediaRule.prototype.type = 4;
- // https://opensource.apple.com/source/WebCore/WebCore-7611.1.21.161.3/css/CSSMediaRule.cpp
- Object.defineProperties(CSSOM.CSSMediaRule.prototype, {
- "conditionText": {
- get: function() {
- return this.media.mediaText;
- },
- set: function(value) {
- this.media.mediaText = value;
- },
- configurable: true,
- enumerable: true
- },
- "cssText": {
- get: function() {
- var cssTexts = [];
- for (var i=0, length=this.cssRules.length; i < length; i++) {
- cssTexts.push(this.cssRules[i].cssText);
- }
- return "@media " + this.media.mediaText + " {" + cssTexts.join("") + "}";
- },
- configurable: true,
- enumerable: true
- }
- });
- /**
- * @constructor
- * @see https://drafts.csswg.org/css-contain-3/
- * @see https://www.w3.org/TR/css-contain-3/
- */
- CSSOM.CSSContainerRule = function CSSContainerRule() {
- CSSOM.CSSConditionRule.call(this);
- };
- CSSOM.CSSContainerRule.prototype = new CSSOM.CSSConditionRule();
- CSSOM.CSSContainerRule.prototype.constructor = CSSOM.CSSContainerRule;
- CSSOM.CSSContainerRule.prototype.type = 17;
- Object.defineProperties(CSSOM.CSSContainerRule.prototype, {
- "conditionText": {
- get: function() {
- return this.containerText;
- },
- set: function(value) {
- this.containerText = value;
- },
- configurable: true,
- enumerable: true
- },
- "cssText": {
- get: function() {
- var cssTexts = [];
- for (var i=0, length=this.cssRules.length; i < length; i++) {
- cssTexts.push(this.cssRules[i].cssText);
- }
- return "@container " + this.containerText + " {" + cssTexts.join("") + "}";
- },
- configurable: true,
- enumerable: true
- }
- });
- /**
- * @constructor
- * @see https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface
- */
- CSSOM.CSSSupportsRule = function CSSSupportsRule() {
- CSSOM.CSSConditionRule.call(this);
- };
- CSSOM.CSSSupportsRule.prototype = new CSSOM.CSSConditionRule();
- CSSOM.CSSSupportsRule.prototype.constructor = CSSOM.CSSSupportsRule;
- CSSOM.CSSSupportsRule.prototype.type = 12;
- Object.defineProperty(CSSOM.CSSSupportsRule.prototype, "cssText", {
- get: function() {
- var cssTexts = [];
- for (var i = 0, length = this.cssRules.length; i < length; i++) {
- cssTexts.push(this.cssRules[i].cssText);
- }
- return "@supports " + this.conditionText + " {" + cssTexts.join("") + "}";
- }
- });
- /**
- * @constructor
- * @see http://dev.w3.org/csswg/cssom/#cssimportrule
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSImportRule
- */
- CSSOM.CSSImportRule = function CSSImportRule() {
- CSSOM.CSSRule.call(this);
- this.href = "";
- this.media = new CSSOM.MediaList();
- this.styleSheet = new CSSOM.CSSStyleSheet();
- };
- CSSOM.CSSImportRule.prototype = new CSSOM.CSSRule();
- CSSOM.CSSImportRule.prototype.constructor = CSSOM.CSSImportRule;
- CSSOM.CSSImportRule.prototype.type = 3;
- Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
- get: function() {
- var mediaText = this.media.mediaText;
- return "@import url(" + this.href + ")" + (mediaText ? " " + mediaText : "") + ";";
- },
- set: function(cssText) {
- var i = 0;
- /**
- * @import url(partial.css) screen, handheld;
- * || |
- * after-import media
- * |
- * url
- */
- var state = '';
- var buffer = '';
- var index;
- for (var character; (character = cssText.charAt(i)); i++) {
- switch (character) {
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- case '\f':
- if (state === 'after-import') {
- state = 'url';
- } else {
- buffer += character;
- }
- break;
- case '@':
- if (!state && cssText.indexOf('@import', i) === i) {
- state = 'after-import';
- i += 'import'.length;
- buffer = '';
- }
- break;
- case 'u':
- if (state === 'url' && cssText.indexOf('url(', i) === i) {
- index = cssText.indexOf(')', i + 1);
- if (index === -1) {
- throw i + ': ")" not found';
- }
- i += 'url('.length;
- var url = cssText.slice(i, index);
- if (url[0] === url[url.length - 1]) {
- if (url[0] === '"' || url[0] === "'") {
- url = url.slice(1, -1);
- }
- }
- this.href = url;
- i = index;
- state = 'media';
- }
- break;
- case '"':
- if (state === 'url') {
- index = cssText.indexOf('"', i + 1);
- if (!index) {
- throw i + ": '\"' not found";
- }
- this.href = cssText.slice(i + 1, index);
- i = index;
- state = 'media';
- }
- break;
- case "'":
- if (state === 'url') {
- index = cssText.indexOf("'", i + 1);
- if (!index) {
- throw i + ': "\'" not found';
- }
- this.href = cssText.slice(i + 1, index);
- i = index;
- state = 'media';
- }
- break;
- case ';':
- if (state === 'media') {
- if (buffer) {
- this.media.mediaText = buffer.trim();
- }
- }
- break;
- default:
- if (state === 'media') {
- buffer += character;
- }
- break;
- }
- }
- }
- });
- /**
- * @constructor
- * @see http://dev.w3.org/csswg/cssom/#css-font-face-rule
- */
- CSSOM.CSSFontFaceRule = function CSSFontFaceRule() {
- CSSOM.CSSRule.call(this);
- this.style = new CSSOM.CSSStyleDeclaration();
- this.style.parentRule = this;
- };
- CSSOM.CSSFontFaceRule.prototype = new CSSOM.CSSRule();
- CSSOM.CSSFontFaceRule.prototype.constructor = CSSOM.CSSFontFaceRule;
- CSSOM.CSSFontFaceRule.prototype.type = 5;
- //FIXME
- //CSSOM.CSSFontFaceRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
- //CSSOM.CSSFontFaceRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
- // http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSFontFaceRule.cpp
- Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "cssText", {
- get: function() {
- return "@font-face {" + this.style.cssText + "}";
- }
- });
- /**
- * @constructor
- * @see http://www.w3.org/TR/shadow-dom/#host-at-rule
- */
- CSSOM.CSSHostRule = function CSSHostRule() {
- CSSOM.CSSRule.call(this);
- this.cssRules = [];
- };
- CSSOM.CSSHostRule.prototype = new CSSOM.CSSRule();
- CSSOM.CSSHostRule.prototype.constructor = CSSOM.CSSHostRule;
- CSSOM.CSSHostRule.prototype.type = 1001;
- //FIXME
- //CSSOM.CSSHostRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
- //CSSOM.CSSHostRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
- Object.defineProperty(CSSOM.CSSHostRule.prototype, "cssText", {
- get: function() {
- var cssTexts = [];
- for (var i=0, length=this.cssRules.length; i < length; i++) {
- cssTexts.push(this.cssRules[i].cssText);
- }
- return "@host {" + cssTexts.join("") + "}";
- }
- });
- /**
- * @constructor
- * @see http://www.w3.org/TR/shadow-dom/#host-at-rule
- */
- CSSOM.CSSStartingStyleRule = function CSSStartingStyleRule() {
- CSSOM.CSSRule.call(this);
- this.cssRules = [];
- };
- CSSOM.CSSStartingStyleRule.prototype = new CSSOM.CSSRule();
- CSSOM.CSSStartingStyleRule.prototype.constructor = CSSOM.CSSStartingStyleRule;
- CSSOM.CSSStartingStyleRule.prototype.type = 1002;
- //FIXME
- //CSSOM.CSSStartingStyleRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
- //CSSOM.CSSStartingStyleRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
- Object.defineProperty(CSSOM.CSSStartingStyleRule.prototype, "cssText", {
- get: function() {
- var cssTexts = [];
- for (var i=0, length=this.cssRules.length; i < length; i++) {
- cssTexts.push(this.cssRules[i].cssText);
- }
- return "@starting-style {" + cssTexts.join("") + "}";
- }
- });
- /**
- * @constructor
- * @see http://dev.w3.org/csswg/cssom/#the-stylesheet-interface
- */
- CSSOM.StyleSheet = function StyleSheet() {
- this.parentStyleSheet = null;
- };
- /**
- * @constructor
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet
- */
- CSSOM.CSSStyleSheet = function CSSStyleSheet() {
- CSSOM.StyleSheet.call(this);
- this.cssRules = [];
- };
- CSSOM.CSSStyleSheet.prototype = new CSSOM.StyleSheet();
- CSSOM.CSSStyleSheet.prototype.constructor = CSSOM.CSSStyleSheet;
- /**
- * Used to insert a new rule into the style sheet. The new rule now becomes part of the cascade.
- *
- * sheet = new Sheet("body {margin: 0}")
- * sheet.toString()
- * -> "body{margin:0;}"
- * sheet.insertRule("img {border: none}", 0)
- * -> 0
- * sheet.toString()
- * -> "img{border:none;}body{margin:0;}"
- *
- * @param {string} rule
- * @param {number} index
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-insertRule
- * @return {number} The index within the style sheet's rule collection of the newly inserted rule.
- */
- CSSOM.CSSStyleSheet.prototype.insertRule = function(rule, index) {
- if (index < 0 || index > this.cssRules.length) {
- throw new RangeError("INDEX_SIZE_ERR");
- }
- var cssRule = CSSOM.parse(rule).cssRules[0];
- cssRule.parentStyleSheet = this;
- this.cssRules.splice(index, 0, cssRule);
- return index;
- };
- /**
- * Used to delete a rule from the style sheet.
- *
- * sheet = new Sheet("img{border:none} body{margin:0}")
- * sheet.toString()
- * -> "img{border:none;}body{margin:0;}"
- * sheet.deleteRule(0)
- * sheet.toString()
- * -> "body{margin:0;}"
- *
- * @param {number} index within the style sheet's rule list of the rule to remove.
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-deleteRule
- */
- CSSOM.CSSStyleSheet.prototype.deleteRule = function(index) {
- if (index < 0 || index >= this.cssRules.length) {
- throw new RangeError("INDEX_SIZE_ERR");
- }
- this.cssRules.splice(index, 1);
- };
- /**
- * NON-STANDARD
- * @return {string} serialize stylesheet
- */
- CSSOM.CSSStyleSheet.prototype.toString = function() {
- var result = "";
- var rules = this.cssRules;
- for (var i=0; i<rules.length; i++) {
- result += rules[i].cssText + "\n";
- }
- return result;
- };
- /**
- * @constructor
- * @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframesRule
- */
- CSSOM.CSSKeyframesRule = function CSSKeyframesRule() {
- CSSOM.CSSRule.call(this);
- this.name = '';
- this.cssRules = [];
- };
- CSSOM.CSSKeyframesRule.prototype = new CSSOM.CSSRule();
- CSSOM.CSSKeyframesRule.prototype.constructor = CSSOM.CSSKeyframesRule;
- CSSOM.CSSKeyframesRule.prototype.type = 7;
- //FIXME
- //CSSOM.CSSKeyframesRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
- //CSSOM.CSSKeyframesRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
- // http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframesRule.cpp
- Object.defineProperty(CSSOM.CSSKeyframesRule.prototype, "cssText", {
- get: function() {
- var cssTexts = [];
- for (var i=0, length=this.cssRules.length; i < length; i++) {
- cssTexts.push(" " + this.cssRules[i].cssText);
- }
- return "@" + (this._vendorPrefix || '') + "keyframes " + this.name + " { \n" + cssTexts.join("\n") + "\n}";
- }
- });
- /**
- * @constructor
- * @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframeRule
- */
- CSSOM.CSSKeyframeRule = function CSSKeyframeRule() {
- CSSOM.CSSRule.call(this);
- this.keyText = '';
- this.style = new CSSOM.CSSStyleDeclaration();
- this.style.parentRule = this;
- };
- CSSOM.CSSKeyframeRule.prototype = new CSSOM.CSSRule();
- CSSOM.CSSKeyframeRule.prototype.constructor = CSSOM.CSSKeyframeRule;
- CSSOM.CSSKeyframeRule.prototype.type = 8;
- //FIXME
- //CSSOM.CSSKeyframeRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
- //CSSOM.CSSKeyframeRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
- // http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframeRule.cpp
- Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "cssText", {
- get: function() {
- return this.keyText + " {" + this.style.cssText + "} ";
- }
- });
- /**
- * @constructor
- * @see https://developer.mozilla.org/en/CSS/@-moz-document
- */
- CSSOM.MatcherList = function MatcherList(){
- this.length = 0;
- };
- CSSOM.MatcherList.prototype = {
- constructor: CSSOM.MatcherList,
- /**
- * @return {string}
- */
- get matcherText() {
- return Array.prototype.join.call(this, ", ");
- },
- /**
- * @param {string} value
- */
- set matcherText(value) {
- // just a temporary solution, actually it may be wrong by just split the value with ',', because a url can include ','.
- var values = value.split(",");
- var length = this.length = values.length;
- for (var i=0; i<length; i++) {
- this[i] = values[i].trim();
- }
- },
- /**
- * @param {string} matcher
- */
- appendMatcher: function(matcher) {
- if (Array.prototype.indexOf.call(this, matcher) === -1) {
- this[this.length] = matcher;
- this.length++;
- }
- },
- /**
- * @param {string} matcher
- */
- deleteMatcher: function(matcher) {
- var index = Array.prototype.indexOf.call(this, matcher);
- if (index !== -1) {
- Array.prototype.splice.call(this, index, 1);
- }
- }
- };
- /**
- * @constructor
- * @see https://developer.mozilla.org/en/CSS/@-moz-document
- */
- CSSOM.CSSDocumentRule = function CSSDocumentRule() {
- CSSOM.CSSRule.call(this);
- this.matcher = new CSSOM.MatcherList();
- this.cssRules = [];
- };
- CSSOM.CSSDocumentRule.prototype = new CSSOM.CSSRule();
- CSSOM.CSSDocumentRule.prototype.constructor = CSSOM.CSSDocumentRule;
- CSSOM.CSSDocumentRule.prototype.type = 10;
- //FIXME
- //CSSOM.CSSDocumentRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
- //CSSOM.CSSDocumentRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
- Object.defineProperty(CSSOM.CSSDocumentRule.prototype, "cssText", {
- get: function() {
- var cssTexts = [];
- for (var i=0, length=this.cssRules.length; i < length; i++) {
- cssTexts.push(this.cssRules[i].cssText);
- }
- return "@-moz-document " + this.matcher.matcherText + " {" + cssTexts.join("") + "}";
- }
- });
- /**
- * @constructor
- * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue
- *
- * TODO: add if needed
- */
- CSSOM.CSSValue = function CSSValue() {
- };
- CSSOM.CSSValue.prototype = {
- constructor: CSSOM.CSSValue,
- // @see: http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue
- set cssText(text) {
- var name = this._getConstructorName();
- throw new Error('DOMException: property "cssText" of "' + name + '" is readonly and can not be replaced with "' + text + '"!');
- },
- get cssText() {
- var name = this._getConstructorName();
- throw new Error('getter "cssText" of "' + name + '" is not implemented!');
- },
- _getConstructorName: function() {
- var s = this.constructor.toString(),
- c = s.match(/function\s([^\(]+)/),
- name = c[1];
- return name;
- }
- };
- /**
- * @constructor
- * @see http://msdn.microsoft.com/en-us/library/ms537634(v=vs.85).aspx
- *
- */
- CSSOM.CSSValueExpression = function CSSValueExpression(token, idx) {
- this._token = token;
- this._idx = idx;
- };
- CSSOM.CSSValueExpression.prototype = new CSSOM.CSSValue();
- CSSOM.CSSValueExpression.prototype.constructor = CSSOM.CSSValueExpression;
- /**
- * parse css expression() value
- *
- * @return {Object}
- * - error:
- * or
- * - idx:
- * - expression:
- *
- * Example:
- *
- * .selector {
- * zoom: expression(documentElement.clientWidth > 1000 ? '1000px' : 'auto');
- * }
- */
- CSSOM.CSSValueExpression.prototype.parse = function() {
- var token = this._token,
- idx = this._idx;
- var character = '',
- expression = '',
- error = '',
- info,
- paren = [];
- for (; ; ++idx) {
- character = token.charAt(idx);
- // end of token
- if (character === '') {
- error = 'css expression error: unfinished expression!';
- break;
- }
- switch(character) {
- case '(':
- paren.push(character);
- expression += character;
- break;
- case ')':
- paren.pop(character);
- expression += character;
- break;
- case '/':
- if ((info = this._parseJSComment(token, idx))) { // comment?
- if (info.error) {
- error = 'css expression error: unfinished comment in expression!';
- } else {
- idx = info.idx;
- // ignore the comment
- }
- } else if ((info = this._parseJSRexExp(token, idx))) { // regexp
- idx = info.idx;
- expression += info.text;
- } else { // other
- expression += character;
- }
- break;
- case "'":
- case '"':
- info = this._parseJSString(token, idx, character);
- if (info) { // string
- idx = info.idx;
- expression += info.text;
- } else {
- expression += character;
- }
- break;
- default:
- expression += character;
- break;
- }
- if (error) {
- break;
- }
- // end of expression
- if (paren.length === 0) {
- break;
- }
- }
- var ret;
- if (error) {
- ret = {
- error: error
- };
- } else {
- ret = {
- idx: idx,
- expression: expression
- };
- }
- return ret;
- };
- /**
- *
- * @return {Object|false}
- * - idx:
- * - text:
- * or
- * - error:
- * or
- * false
- *
- */
- CSSOM.CSSValueExpression.prototype._parseJSComment = function(token, idx) {
- var nextChar = token.charAt(idx + 1),
- text;
- if (nextChar === '/' || nextChar === '*') {
- var startIdx = idx,
- endIdx,
- commentEndChar;
- if (nextChar === '/') { // line comment
- commentEndChar = '\n';
- } else if (nextChar === '*') { // block comment
- commentEndChar = '*/';
- }
- endIdx = token.indexOf(commentEndChar, startIdx + 1 + 1);
- if (endIdx !== -1) {
- endIdx = endIdx + commentEndChar.length - 1;
- text = token.substring(idx, endIdx + 1);
- return {
- idx: endIdx,
- text: text
- };
- } else {
- var error = 'css expression error: unfinished comment in expression!';
- return {
- error: error
- };
- }
- } else {
- return false;
- }
- };
- /**
- *
- * @return {Object|false}
- * - idx:
- * - text:
- * or
- * false
- *
- */
- CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep) {
- var endIdx = this._findMatchedIdx(token, idx, sep),
- text;
- if (endIdx === -1) {
- return false;
- } else {
- text = token.substring(idx, endIdx + sep.length);
- return {
- idx: endIdx,
- text: text
- };
- }
- };
- /**
- * parse regexp in css expression
- *
- * @return {Object|false}
- * - idx:
- * - regExp:
- * or
- * false
- */
- /*
- all legal RegExp
-
- /a/
- (/a/)
- [/a/]
- [12, /a/]
- !/a/
- +/a/
- -/a/
- * /a/
- / /a/
- %/a/
- ===/a/
- !==/a/
- ==/a/
- !=/a/
- >/a/
- >=/a/
- </a/
- <=/a/
- &/a/
- |/a/
- ^/a/
- ~/a/
- <</a/
- >>/a/
- >>>/a/
- &&/a/
- ||/a/
- ?/a/
- =/a/
- ,/a/
- delete /a/
- in /a/
- instanceof /a/
- new /a/
- typeof /a/
- void /a/
- */
- CSSOM.CSSValueExpression.prototype._parseJSRexExp = function(token, idx) {
- var before = token.substring(0, idx).replace(/\s+$/, ""),
- legalRegx = [
- /^$/,
- /\($/,
- /\[$/,
- /\!$/,
- /\+$/,
- /\-$/,
- /\*$/,
- /\/\s+/,
- /\%$/,
- /\=$/,
- /\>$/,
- /<$/,
- /\&$/,
- /\|$/,
- /\^$/,
- /\~$/,
- /\?$/,
- /\,$/,
- /delete$/,
- /in$/,
- /instanceof$/,
- /new$/,
- /typeof$/,
- /void$/
- ];
- var isLegal = legalRegx.some(function(reg) {
- return reg.test(before);
- });
- if (!isLegal) {
- return false;
- } else {
- var sep = '/';
- // same logic as string
- return this._parseJSString(token, idx, sep);
- }
- };
- /**
- *
- * find next sep(same line) index in `token`
- *
- * @return {Number}
- *
- */
- CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep) {
- var startIdx = idx,
- endIdx;
- var NOT_FOUND = -1;
- while(true) {
- endIdx = token.indexOf(sep, startIdx + 1);
- if (endIdx === -1) { // not found
- endIdx = NOT_FOUND;
- break;
- } else {
- var text = token.substring(idx + 1, endIdx),
- matched = text.match(/\\+$/);
- if (!matched || matched[0] % 2 === 0) { // not escaped
- break;
- } else {
- startIdx = endIdx;
- }
- }
- }
- // boundary must be in the same line(js sting or regexp)
- var nextNewLineIdx = token.indexOf('\n', idx + 1);
- if (nextNewLineIdx < endIdx) {
- endIdx = NOT_FOUND;
- }
- return endIdx;
- };
- /**
- * @constructor
- * @see https://drafts.csswg.org/css-cascade-5/#csslayerblockrule
- */
- CSSOM.CSSLayerBlockRule = function CSSLayerBlockRule() {
- CSSOM.CSSGroupingRule.call(this);
- this.layerName = "";
- this.cssRules = [];
- };
- CSSOM.CSSLayerBlockRule.prototype = new CSSOM.CSSGroupingRule();
- CSSOM.CSSLayerBlockRule.prototype.constructor = CSSOM.CSSLayerBlockRule;
- CSSOM.CSSLayerBlockRule.prototype.type = 18;
- Object.defineProperties(CSSOM.CSSLayerBlockRule.prototype, {
- layerNameText: {
- get: function () {
- return this.layerName;
- },
- set: function (value) {
- this.layerName = value;
- },
- configurable: true,
- enumerable: true,
- },
- cssText: {
- get: function () {
- var cssTexts = [];
- for (var i = 0, length = this.cssRules.length; i < length; i++) {
- cssTexts.push(this.cssRules[i].cssText);
- }
- return "@layer " + this.layerNameText + " {" + cssTexts.join("") + "}";
- },
- configurable: true,
- enumerable: true,
- },
- });
- /**
- * @param {string} token
- */
- CSSOM.parse = function parse(token) {
- var i = 0;
- /**
- "before-selector" or
- "selector" or
- "atRule" or
- "atBlock" or
- "conditionBlock" or
- "before-name" or
- "name" or
- "before-value" or
- "value"
- */
- var state = "before-selector";
- var index;
- var buffer = "";
- var valueParenthesisDepth = 0;
- var SIGNIFICANT_WHITESPACE = {
- "selector": true,
- "value": true,
- "value-parenthesis": true,
- "atRule": true,
- "importRule-begin": true,
- "importRule": true,
- "atBlock": true,
- "containerBlock": true,
- "conditionBlock": true,
- 'documentRule-begin': true,
- "layerBlock": true
- };
- var styleSheet = new CSSOM.CSSStyleSheet();
- // @type CSSStyleSheet|CSSMediaRule|CSSContainerRule|CSSSupportsRule|CSSFontFaceRule|CSSKeyframesRule|CSSDocumentRule
- var currentScope = styleSheet;
- // @type CSSMediaRule|CSSContainerRule|CSSSupportsRule|CSSKeyframesRule|CSSDocumentRule
- var parentRule;
- var ancestorRules = [];
- var hasAncestors = false;
- var prevScope;
- var name, priority="", styleRule, mediaRule, containerRule, supportsRule, importRule, fontFaceRule, keyframesRule, documentRule, hostRule, startingStyleRule, layerBlockRule;
- var atKeyframesRegExp = /@(-(?:\w+-)+)?keyframes/g;
- var parseError = function(message) {
- var lines = token.substring(0, i).split('\n');
- var lineCount = lines.length;
- var charCount = lines.pop().length + 1;
- var error = new Error(message + ' (line ' + lineCount + ', char ' + charCount + ')');
- error.line = lineCount;
- /* jshint sub : true */
- error['char'] = charCount;
- error.styleSheet = styleSheet;
- throw error;
- };
- for (var character; (character = token.charAt(i)); i++) {
- switch (character) {
- case " ":
- case "\t":
- case "\r":
- case "\n":
- case "\f":
- if (SIGNIFICANT_WHITESPACE[state]) {
- buffer += character;
- }
- break;
- // String
- case '"':
- index = i + 1;
- do {
- index = token.indexOf('"', index) + 1;
- if (!index) {
- parseError('Unmatched "');
- }
- } while (token[index - 2] === '\\');
- buffer += token.slice(i, index);
- i = index - 1;
- switch (state) {
- case 'before-value':
- state = 'value';
- break;
- case 'importRule-begin':
- state = 'importRule';
- break;
- }
- break;
- case "'":
- index = i + 1;
- do {
- index = token.indexOf("'", index) + 1;
- if (!index) {
- parseError("Unmatched '");
- }
- } while (token[index - 2] === '\\');
- buffer += token.slice(i, index);
- i = index - 1;
- switch (state) {
- case 'before-value':
- state = 'value';
- break;
- case 'importRule-begin':
- state = 'importRule';
- break;
- }
- break;
- // Comment
- case "/":
- if (token.charAt(i + 1) === "*") {
- i += 2;
- index = token.indexOf("*/", i);
- if (index === -1) {
- parseError("Missing */");
- } else {
- i = index + 1;
- }
- } else {
- buffer += character;
- }
- if (state === "importRule-begin") {
- buffer += " ";
- state = "importRule";
- }
- break;
- // At-rule
- case "@":
- if (token.indexOf("@-moz-document", i) === i) {
- state = "documentRule-begin";
- documentRule = new CSSOM.CSSDocumentRule();
- documentRule.__starts = i;
- i += "-moz-document".length;
- buffer = "";
- break;
- } else if (token.indexOf("@media", i) === i) {
- state = "atBlock";
- mediaRule = new CSSOM.CSSMediaRule();
- mediaRule.__starts = i;
- i += "media".length;
- buffer = "";
- break;
- } else if (token.indexOf("@container", i) === i) {
- state = "containerBlock";
- containerRule = new CSSOM.CSSContainerRule();
- containerRule.__starts = i;
- i += "container".length;
- buffer = "";
- break;
- } else if (token.indexOf("@layer", i) === i) {
- state = "layerBlock"
- layerBlockRule = new CSSOM.CSSLayerBlockRule();
- layerBlockRule.__starts = i;
- i += "layer".length;
- buffer = "";
- break;
- } else if (token.indexOf("@supports", i) === i) {
- state = "conditionBlock";
- supportsRule = new CSSOM.CSSSupportsRule();
- supportsRule.__starts = i;
- i += "supports".length;
- buffer = "";
- break;
- } else if (token.indexOf("@host", i) === i) {
- state = "hostRule-begin";
- i += "host".length;
- hostRule = new CSSOM.CSSHostRule();
- hostRule.__starts = i;
- buffer = "";
- break;
- } else if (token.indexOf("@starting-style", i) === i) {
- state = "startingStyleRule-begin";
- i += "starting-style".length;
- startingStyleRule = new CSSOM.CSSStartingStyleRule();
- startingStyleRule.__starts = i;
- buffer = "";
- break;
- } else if (token.indexOf("@import", i) === i) {
- state = "importRule-begin";
- i += "import".length;
- buffer += "@import";
- break;
- } else if (token.indexOf("@font-face", i) === i) {
- state = "fontFaceRule-begin";
- i += "font-face".length;
- fontFaceRule = new CSSOM.CSSFontFaceRule();
- fontFaceRule.__starts = i;
- buffer = "";
- break;
- } else {
- atKeyframesRegExp.lastIndex = i;
- var matchKeyframes = atKeyframesRegExp.exec(token);
- if (matchKeyframes && matchKeyframes.index === i) {
- state = "keyframesRule-begin";
- keyframesRule = new CSSOM.CSSKeyframesRule();
- keyframesRule.__starts = i;
- keyframesRule._vendorPrefix = matchKeyframes[1]; // Will come out as undefined if no prefix was found
- i += matchKeyframes[0].length - 1;
- buffer = "";
- break;
- } else if (state === "selector") {
- state = "atRule";
- }
- }
- buffer += character;
- break;
- case "{":
- if (state === "selector" || state === "atRule") {
- styleRule.selectorText = buffer.trim();
- styleRule.style.__starts = i;
- buffer = "";
- state = "before-name";
- } else if (state === "atBlock") {
- mediaRule.media.mediaText = buffer.trim();
- if (parentRule) {
- ancestorRules.push(parentRule);
- }
- currentScope = parentRule = mediaRule;
- mediaRule.parentStyleSheet = styleSheet;
- buffer = "";
- state = "before-selector";
- } else if (state === "containerBlock") {
- containerRule.containerText = buffer.trim();
- if (parentRule) {
- ancestorRules.push(parentRule);
- }
- currentScope = parentRule = containerRule;
- containerRule.parentStyleSheet = styleSheet;
- buffer = "";
- state = "before-selector";
- } else if (state === "conditionBlock") {
- supportsRule.conditionText = buffer.trim();
- if (parentRule) {
- ancestorRules.push(parentRule);
- }
- currentScope = parentRule = supportsRule;
- supportsRule.parentStyleSheet = styleSheet;
- buffer = "";
- state = "before-selector";
- } else if (state === "layerBlock") {
- layerBlockRule.layerNameText = buffer.trim();
- if (parentRule) {
- ancestorRules.push(parentRule);
- }
- currentScope = parentRule = layerBlockRule;
- layerBlockRule.parentStyleSheet = styleSheet;
- buffer = "";
- state = "before-selector";
- } else if (state === "hostRule-begin") {
- if (parentRule) {
- ancestorRules.push(parentRule);
- }
- currentScope = parentRule = hostRule;
- hostRule.parentStyleSheet = styleSheet;
- buffer = "";
- state = "before-selector";
- } else if (state === "startingStyleRule-begin") {
- if (parentRule) {
- ancestorRules.push(parentRule);
- }
- currentScope = parentRule = startingStyleRule;
- startingStyleRule.parentStyleSheet = styleSheet;
- buffer = "";
- state = "before-selector";
- } else if (state === "fontFaceRule-begin") {
- if (parentRule) {
- fontFaceRule.parentRule = parentRule;
- }
- fontFaceRule.parentStyleSheet = styleSheet;
- styleRule = fontFaceRule;
- buffer = "";
- state = "before-name";
- } else if (state === "keyframesRule-begin") {
- keyframesRule.name = buffer.trim();
- if (parentRule) {
- ancestorRules.push(parentRule);
- keyframesRule.parentRule = parentRule;
- }
- keyframesRule.parentStyleSheet = styleSheet;
- currentScope = parentRule = keyframesRule;
- buffer = "";
- state = "keyframeRule-begin";
- } else if (state === "keyframeRule-begin") {
- styleRule = new CSSOM.CSSKeyframeRule();
- styleRule.keyText = buffer.trim();
- styleRule.__starts = i;
- buffer = "";
- state = "before-name";
- } else if (state === "documentRule-begin") {
- // FIXME: what if this '{' is in the url text of the match function?
- documentRule.matcher.matcherText = buffer.trim();
- if (parentRule) {
- ancestorRules.push(parentRule);
- documentRule.parentRule = parentRule;
- }
- currentScope = parentRule = documentRule;
- documentRule.parentStyleSheet = styleSheet;
- buffer = "";
- state = "before-selector";
- }
- break;
- case ":":
- if (state === "name") {
- name = buffer.trim();
- buffer = "";
- state = "before-value";
- } else {
- buffer += character;
- }
- break;
- case "(":
- if (state === 'value') {
- // ie css expression mode
- if (buffer.trim() === 'expression') {
- var info = (new CSSOM.CSSValueExpression(token, i)).parse();
- if (info.error) {
- parseError(info.error);
- } else {
- buffer += info.expression;
- i = info.idx;
- }
- } else {
- state = 'value-parenthesis';
- //always ensure this is reset to 1 on transition
- //from value to value-parenthesis
- valueParenthesisDepth = 1;
- buffer += character;
- }
- } else if (state === 'value-parenthesis') {
- valueParenthesisDepth++;
- buffer += character;
- } else {
- buffer += character;
- }
- break;
- case ")":
- if (state === 'value-parenthesis') {
- valueParenthesisDepth--;
- if (valueParenthesisDepth === 0) state = 'value';
- }
- buffer += character;
- break;
- case "!":
- if (state === "value" && token.indexOf("!important", i) === i) {
- priority = "important";
- i += "important".length;
- } else {
- buffer += character;
- }
- break;
- case ";":
- switch (state) {
- case "value":
- styleRule.style.setProperty(name, buffer.trim(), priority);
- priority = "";
- buffer = "";
- state = "before-name";
- break;
- case "atRule":
- buffer = "";
- state = "before-selector";
- break;
- case "importRule":
- importRule = new CSSOM.CSSImportRule();
- importRule.parentStyleSheet = importRule.styleSheet.parentStyleSheet = styleSheet;
- importRule.cssText = buffer + character;
- styleSheet.cssRules.push(importRule);
- buffer = "";
- state = "before-selector";
- break;
- default:
- buffer += character;
- break;
- }
- break;
- case "}":
- switch (state) {
- case "value":
- styleRule.style.setProperty(name, buffer.trim(), priority);
- priority = "";
- /* falls through */
- case "before-name":
- case "name":
- styleRule.__ends = i + 1;
- if (parentRule) {
- styleRule.parentRule = parentRule;
- }
- styleRule.parentStyleSheet = styleSheet;
- currentScope.cssRules.push(styleRule);
- buffer = "";
- if (currentScope.constructor === CSSOM.CSSKeyframesRule) {
- state = "keyframeRule-begin";
- } else {
- state = "before-selector";
- }
- break;
- case "keyframeRule-begin":
- case "before-selector":
- case "selector":
- // End of media/supports/document rule.
- if (!parentRule) {
- parseError("Unexpected }");
- }
- // Handle rules nested in @media or @supports
- hasAncestors = ancestorRules.length > 0;
- while (ancestorRules.length > 0) {
- parentRule = ancestorRules.pop();
- if (
- parentRule.constructor.name === "CSSMediaRule"
- || parentRule.constructor.name === "CSSSupportsRule"
- || parentRule.constructor.name === "CSSContainerRule"
- || parentRule.constructor.name === "CSSLayerBlockRule"
- || parentRule.constructor.name === "CSSStartingStyleRule"
- ) {
- prevScope = currentScope;
- currentScope = parentRule;
- currentScope.cssRules.push(prevScope);
- break;
- }
- if (ancestorRules.length === 0) {
- hasAncestors = false;
- }
- }
-
- if (!hasAncestors) {
- currentScope.__ends = i + 1;
- styleSheet.cssRules.push(currentScope);
- currentScope = styleSheet;
- parentRule = null;
- }
- buffer = "";
- state = "before-selector";
- break;
- }
- break;
- default:
- switch (state) {
- case "before-selector":
- state = "selector";
- styleRule = new CSSOM.CSSStyleRule();
- styleRule.__starts = i;
- break;
- case "before-name":
- state = "name";
- break;
- case "before-value":
- state = "value";
- break;
- case "importRule-begin":
- state = "importRule";
- break;
- }
- buffer += character;
- break;
- }
- }
- return styleSheet;
- };
- /**
- * Produces a deep copy of stylesheet — the instance variables of stylesheet are copied recursively.
- * @param {CSSStyleSheet|CSSOM.CSSStyleSheet} stylesheet
- * @nosideeffects
- * @return {CSSOM.CSSStyleSheet}
- */
- CSSOM.clone = function clone(stylesheet) {
- var cloned = new CSSOM.CSSStyleSheet();
- var rules = stylesheet.cssRules;
- if (!rules) {
- return cloned;
- }
- for (var i = 0, rulesLength = rules.length; i < rulesLength; i++) {
- var rule = rules[i];
- var ruleClone = cloned.cssRules[i] = new rule.constructor();
- var style = rule.style;
- if (style) {
- var styleClone = ruleClone.style = new CSSOM.CSSStyleDeclaration();
- for (var j = 0, styleLength = style.length; j < styleLength; j++) {
- var name = styleClone[j] = style[j];
- styleClone[name] = style[name];
- styleClone._importants[name] = style.getPropertyPriority(name);
- }
- styleClone.length = style.length;
- }
- if (rule.hasOwnProperty('keyText')) {
- ruleClone.keyText = rule.keyText;
- }
- if (rule.hasOwnProperty('selectorText')) {
- ruleClone.selectorText = rule.selectorText;
- }
- if (rule.hasOwnProperty('mediaText')) {
- ruleClone.mediaText = rule.mediaText;
- }
- if (rule.hasOwnProperty('conditionText')) {
- ruleClone.conditionText = rule.conditionText;
- }
- if (rule.hasOwnProperty('layerName')) {
- ruleClone.layerName = rule.layerName;
- }
- if (rule.hasOwnProperty('cssRules')) {
- ruleClone.cssRules = clone(rule).cssRules;
- }
- }
- return cloned;
- };
|