diff --git a/.changeset/two-bears-kick.md b/.changeset/two-bears-kick.md new file mode 100644 index 0000000..132ad09 --- /dev/null +++ b/.changeset/two-bears-kick.md @@ -0,0 +1,5 @@ +--- +"rrweb-cssom": minor +--- + +add support for @container diff --git a/lib/CSSContainerRule.js b/lib/CSSContainerRule.js new file mode 100644 index 0000000..9989771 --- /dev/null +++ b/lib/CSSContainerRule.js @@ -0,0 +1,50 @@ +//.CommonJS +var CSSOM = { + CSSRule: require("./CSSRule").CSSRule, + CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule, + CSSConditionRule: require("./CSSConditionRule").CSSConditionRule, +}; +///CommonJS + + +/** + * @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 + } +}); + + +//.CommonJS +exports.CSSContainerRule = CSSOM.CSSContainerRule; +///CommonJS diff --git a/lib/CSSRule.js b/lib/CSSRule.js index d40c2dd..0c095c1 100644 --- a/lib/CSSRule.js +++ b/lib/CSSRule.js @@ -30,6 +30,7 @@ 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.STARTING_STYLE_RULE = 1002; diff --git a/lib/clone.js b/lib/clone.js index a4162ad..9c5e6aa 100644 --- a/lib/clone.js +++ b/lib/clone.js @@ -6,6 +6,7 @@ var CSSOM = { CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule, CSSConditionRule: require("./CSSConditionRule").CSSConditionRule, CSSMediaRule: require("./CSSMediaRule").CSSMediaRule, + CSSContainerRule: require("./CSSContainerRule").CSSContainerRule, CSSSupportsRule: require("./CSSSupportsRule").CSSSupportsRule, CSSStyleDeclaration: require("./CSSStyleDeclaration").CSSStyleDeclaration, CSSKeyframeRule: require('./CSSKeyframeRule').CSSKeyframeRule, diff --git a/lib/index.js b/lib/index.js index ec8d799..5132203 100644 --- a/lib/index.js +++ b/lib/index.js @@ -7,6 +7,7 @@ exports.CSSConditionRule = require('./CSSConditionRule').CSSConditionRule; exports.CSSStyleRule = require('./CSSStyleRule').CSSStyleRule; exports.MediaList = require('./MediaList').MediaList; exports.CSSMediaRule = require('./CSSMediaRule').CSSMediaRule; +exports.CSSContainerRule = require('./CSSContainerRule').CSSContainerRule; exports.CSSSupportsRule = require('./CSSSupportsRule').CSSSupportsRule; exports.CSSImportRule = require('./CSSImportRule').CSSImportRule; exports.CSSFontFaceRule = require('./CSSFontFaceRule').CSSFontFaceRule; diff --git a/lib/parse.js b/lib/parse.js index 8c5c022..575d96f 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -35,23 +35,24 @@ CSSOM.parse = function parse(token) { "importRule-begin": true, "importRule": true, "atBlock": true, + "containerBlock": true, "conditionBlock": true, 'documentRule-begin': true }; var styleSheet = new CSSOM.CSSStyleSheet(); - // @type CSSStyleSheet|CSSMediaRule|CSSSupportsRule|CSSFontFaceRule|CSSKeyframesRule|CSSDocumentRule + // @type CSSStyleSheet|CSSMediaRule|CSSContainerRule|CSSSupportsRule|CSSFontFaceRule|CSSKeyframesRule|CSSDocumentRule var currentScope = styleSheet; - // @type CSSMediaRule|CSSSupportsRule|CSSKeyframesRule|CSSDocumentRule + // @type CSSMediaRule|CSSContainerRule|CSSSupportsRule|CSSKeyframesRule|CSSDocumentRule var parentRule; var ancestorRules = []; var hasAncestors = false; var prevScope; - var name, priority="", styleRule, mediaRule, supportsRule, importRule, fontFaceRule, keyframesRule, documentRule, hostRule, startingStyleRule; + var name, priority="", styleRule, mediaRule, containerRule, supportsRule, importRule, fontFaceRule, keyframesRule, documentRule, hostRule, startingStyleRule; var atKeyframesRegExp = /@(-(?:\w+-)+)?keyframes/g; @@ -157,6 +158,13 @@ CSSOM.parse = function parse(token) { 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("@supports", i) === i) { state = "conditionBlock"; supportsRule = new CSSOM.CSSSupportsRule(); @@ -225,6 +233,16 @@ CSSOM.parse = function parse(token) { 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(); @@ -411,6 +429,7 @@ CSSOM.parse = function parse(token) { if ( parentRule.constructor.name === "CSSMediaRule" || parentRule.constructor.name === "CSSSupportsRule" + || parentRule.constructor.name === "CSSContainerRule" ) { prevScope = currentScope; currentScope = parentRule; @@ -470,6 +489,7 @@ CSSOM.CSSStyleRule = require("./CSSStyleRule").CSSStyleRule; CSSOM.CSSImportRule = require("./CSSImportRule").CSSImportRule; CSSOM.CSSGroupingRule = require("./CSSGroupingRule").CSSGroupingRule; CSSOM.CSSMediaRule = require("./CSSMediaRule").CSSMediaRule; +CSSOM.CSSContainerRule = require("./CSSContainerRule").CSSContainerRule; CSSOM.CSSConditionRule = require("./CSSConditionRule").CSSConditionRule; CSSOM.CSSSupportsRule = require("./CSSSupportsRule").CSSSupportsRule; CSSOM.CSSFontFaceRule = require("./CSSFontFaceRule").CSSFontFaceRule; diff --git a/spec/parse.spec.js b/spec/parse.spec.js index 06ba800..c851c6f 100644 --- a/spec/parse.spec.js +++ b/spec/parse.spec.js @@ -1246,6 +1246,39 @@ var TESTS = [ return result; })() }, + { + input: "@container sidebar (min-width: 400px) { body{max-width:480px} }", + result: (function() { + var result = { + cssRules: [ + { + containerText: "sidebar (min-width: 400px)", + cssRules: [ + { + selectorText: "body", + style: { + 0: "max-width", + "max-width": "480px", + __starts: 64, + length: 1 + }, + __starts: 60, + __ends: 81 + } + ], + parentRule: null, + __starts: 0, + __ends: 82 + } + ], + parentStyleSheet: null + }; + result.cssRules[0].parentStyleSheet = result.cssRules[0].cssRules[0].parentStyleSheet = result; + result.cssRules[0].cssRules[0].style.parentRule = result.cssRules[0].cssRules[0]; + result.cssRules[0].cssRules[0].parentRule = result.cssRules[0]; + return result; + })() + }, { input: "a{}@-moz-document/**/url-prefix(http://www.w3.org/Style/){body { color: purple; background: yellow; }}", result: (function(){ diff --git a/src/files.js b/src/files.js index a6bad45..5368f1d 100644 --- a/src/files.js +++ b/src/files.js @@ -6,6 +6,7 @@ exports.files = [ "CSSConditionRule", "MediaList", "CSSMediaRule", + "CSSContainerRule", "CSSSupportsRule", "CSSImportRule", "CSSFontFaceRule",