@acemir/cssom 0.9.0 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,6 +16,8 @@ CSSOM.CSSImportRule = function CSSImportRule() {
16
16
  CSSOM.CSSRule.call(this);
17
17
  this.href = "";
18
18
  this.media = new CSSOM.MediaList();
19
+ this.layerName = null;
20
+ this.supportsText = null;
19
21
  this.styleSheet = new CSSOM.CSSStyleSheet();
20
22
  };
21
23
 
@@ -26,7 +28,7 @@ CSSOM.CSSImportRule.prototype.type = 3;
26
28
  Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
27
29
  get: function() {
28
30
  var mediaText = this.media.mediaText;
29
- return "@import url(" + this.href + ")" + (mediaText ? " " + mediaText : "") + ";";
31
+ return "@import url(" + this.href + ")" + (this.layerName !== null ? " layer" + (this.layerName && "(" + this.layerName + ")") : "" ) + (this.supportsText ? " supports(" + this.supportsText + ")" : "" ) + (mediaText ? " " + mediaText : "") + ";";
30
32
  },
31
33
  set: function(cssText) {
32
34
  var i = 0;
@@ -42,6 +44,12 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
42
44
 
43
45
  var buffer = '';
44
46
  var index;
47
+
48
+ var layerRegExp = /layer\(([^)]*)\)/;
49
+ var layerRuleNameRegExp = /^(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)$/;
50
+ var supportsRegExp = /supports\(([^)]+)\)/;
51
+ var doubleOrMoreSpacesRegExp = /\s{2,}/g;
52
+
45
53
  for (var character; (character = cssText.charAt(i)); i++) {
46
54
 
47
55
  switch (character) {
@@ -66,6 +74,9 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
66
74
  break;
67
75
 
68
76
  case 'u':
77
+ if (state === 'media') {
78
+ buffer += character;
79
+ }
69
80
  if (state === 'url' && cssText.indexOf('url(', i) === i) {
70
81
  index = cssText.indexOf(')', i + 1);
71
82
  if (index === -1) {
@@ -85,7 +96,7 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
85
96
  break;
86
97
 
87
98
  case '"':
88
- if (state === 'url') {
99
+ if (state === 'after-import' || state === 'url') {
89
100
  index = cssText.indexOf('"', i + 1);
90
101
  if (!index) {
91
102
  throw i + ": '\"' not found";
@@ -97,7 +108,7 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
97
108
  break;
98
109
 
99
110
  case "'":
100
- if (state === 'url') {
111
+ if (state === 'after-import' || state === 'url') {
101
112
  index = cssText.indexOf("'", i + 1);
102
113
  if (!index) {
103
114
  throw i + ': "\'" not found';
@@ -111,7 +122,47 @@ Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
111
122
  case ';':
112
123
  if (state === 'media') {
113
124
  if (buffer) {
114
- this.media.mediaText = buffer.trim();
125
+ var bufferTrimmed = buffer.trim();
126
+
127
+ if (bufferTrimmed.indexOf('layer') === 0) {
128
+ var layerMatch = bufferTrimmed.match(layerRegExp);
129
+
130
+ if (layerMatch) {
131
+ var layerName = layerMatch[1].trim();
132
+ bufferTrimmed = bufferTrimmed.replace(layerRegExp, '')
133
+ .replace(doubleOrMoreSpacesRegExp, ' ') // Replace double or more spaces with single space
134
+ .trim();
135
+
136
+ if (layerName.match(layerRuleNameRegExp) !== null) {
137
+ this.layerName = layerMatch[1].trim();
138
+ } else {
139
+ // REVIEW: In the browser, an empty layer() is not processed as a unamed layer
140
+ // and treats the rest of the string as mediaText, ignoring the parse of supports()
141
+ if (bufferTrimmed) {
142
+ this.media.mediaText = bufferTrimmed;
143
+ return;
144
+ }
145
+ }
146
+ } else {
147
+ this.layerName = "";
148
+ bufferTrimmed = bufferTrimmed.substring('layer'.length).trim()
149
+ }
150
+ }
151
+
152
+ var supportsMatch = bufferTrimmed.match(supportsRegExp);
153
+
154
+ if (supportsMatch && supportsMatch.index === 0) {
155
+ // REVIEW: In the browser, an empty supports() invalidates and ignores the entire @import rule
156
+ this.supportsText = supportsMatch[1].trim();
157
+ bufferTrimmed = bufferTrimmed.replace(supportsRegExp, '')
158
+ .replace(doubleOrMoreSpacesRegExp, ' ') // Replace double or more spaces with single space
159
+ .trim();
160
+ }
161
+
162
+ // REVIEW: In the browser, any invalid media is replaced with 'not all'
163
+ if (bufferTrimmed) {
164
+ this.media.mediaText = bufferTrimmed;
165
+ }
115
166
  }
116
167
  }
117
168
  break;
@@ -11,7 +11,7 @@ var CSSOM = {
11
11
  */
12
12
  CSSOM.CSSLayerBlockRule = function CSSLayerBlockRule() {
13
13
  CSSOM.CSSGroupingRule.call(this);
14
- this.layerName = "";
14
+ this.name = "";
15
15
  this.cssRules = [];
16
16
  };
17
17
 
@@ -20,23 +20,13 @@ CSSOM.CSSLayerBlockRule.prototype.constructor = CSSOM.CSSLayerBlockRule;
20
20
  CSSOM.CSSLayerBlockRule.prototype.type = 18;
21
21
 
22
22
  Object.defineProperties(CSSOM.CSSLayerBlockRule.prototype, {
23
- layerNameText: {
24
- get: function () {
25
- return this.layerName;
26
- },
27
- set: function (value) {
28
- this.layerName = value;
29
- },
30
- configurable: true,
31
- enumerable: true,
32
- },
33
23
  cssText: {
34
24
  get: function () {
35
25
  var cssTexts = [];
36
26
  for (var i = 0, length = this.cssRules.length; i < length; i++) {
37
27
  cssTexts.push(this.cssRules[i].cssText);
38
28
  }
39
- return "@layer " + this.layerNameText + " {" + cssTexts.join("") + "}";
29
+ return "@layer " + this.name + (this.name && " ") + "{" + cssTexts.join("") + "}";
40
30
  },
41
31
  configurable: true,
42
32
  enumerable: true,
@@ -0,0 +1,32 @@
1
+ //.CommonJS
2
+ var CSSOM = {
3
+ CSSRule: require("./CSSRule").CSSRule,
4
+ };
5
+ ///CommonJS
6
+
7
+ /**
8
+ * @constructor
9
+ * @see https://drafts.csswg.org/css-cascade-5/#csslayerstatementrule
10
+ */
11
+ CSSOM.CSSLayerStatementRule = function CSSLayerStatementRule() {
12
+ CSSOM.CSSRule.call(this);
13
+ this.nameList = [];
14
+ };
15
+
16
+ CSSOM.CSSLayerStatementRule.prototype = new CSSOM.CSSRule();
17
+ CSSOM.CSSLayerStatementRule.prototype.constructor = CSSOM.CSSLayerStatementRule;
18
+ CSSOM.CSSLayerStatementRule.prototype.type = 0;
19
+
20
+ Object.defineProperties(CSSOM.CSSLayerStatementRule.prototype, {
21
+ cssText: {
22
+ get: function () {
23
+ return "@layer " + this.nameList.join(", ") + ";";
24
+ },
25
+ configurable: true,
26
+ enumerable: true,
27
+ },
28
+ });
29
+
30
+ //.CommonJS
31
+ exports.CSSLayerStatementRule = CSSOM.CSSLayerStatementRule;
32
+ ///CommonJS
@@ -2,6 +2,28 @@
2
2
  var CSSOM = {};
3
3
  ///CommonJS
4
4
 
5
+ // NOTE: Check viability to add a validation for css values or use a dependency like csstree-validator
6
+ /**
7
+ * Regular expression to detect invalid characters in the value portion of a CSS style declaration.
8
+ *
9
+ * This regex matches a colon (:) that is not inside parentheses and not inside single or double quotes.
10
+ * It is used to ensure that the value part of a CSS property does not contain unexpected colons,
11
+ * which would indicate a malformed declaration (e.g., "color: foo:bar;" is invalid).
12
+ *
13
+ * The negative lookahead `(?![^(]*\))` ensures that the colon is not followed by a closing
14
+ * parenthesis without encountering an opening parenthesis, effectively ignoring colons inside
15
+ * function-like values (e.g., `url(data:image/png;base64,...)`).
16
+ *
17
+ * The lookahead `(?=(?:[^'"]|'[^']*'|"[^"]*")*$)` ensures that the colon is not inside single or double quotes,
18
+ * allowing colons within quoted strings (e.g., `content: ":";` or `background: url("foo:bar.png");`).
19
+ *
20
+ * Example:
21
+ * "color: red;" // valid, does not match
22
+ * "background: url(data:image/png;base64,...);" // valid, does not match
23
+ * "content: ':';" // valid, does not match
24
+ * "color: foo:bar;" // invalid, matches
25
+ */
26
+ var basicStylePropertyValueValidationRegExp = /:(?![^(]*\))(?=(?:[^'"]|'[^']*'|"[^"]*")*$)/;
5
27
 
6
28
  /**
7
29
  * @constructor
@@ -38,21 +60,36 @@ CSSOM.CSSStyleDeclaration.prototype = {
38
60
  * @param {string} [priority=null] "important" or null
39
61
  * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-setProperty
40
62
  */
41
- setProperty: function(name, value, priority) {
42
- if (this[name]) {
63
+ setProperty: function(name, value, priority, parseErrorHandler)
64
+ {
65
+ // NOTE: Check viability to add a validation for css values or use a dependency like csstree-validator
66
+ if (basicStylePropertyValueValidationRegExp.test(value)) {
67
+ parseErrorHandler && parseErrorHandler('Invalid CSSStyleDeclaration property value');
68
+ } else if (this[name]) {
43
69
  // Property already exist. Overwrite it.
44
70
  var index = Array.prototype.indexOf.call(this, name);
45
71
  if (index < 0) {
46
72
  this[this.length] = name;
47
73
  this.length++;
48
74
  }
75
+
76
+ // If the priority value of the incoming property is "important",
77
+ // or the value of the existing property is not "important",
78
+ // then remove the existing property and rewrite it.
79
+ if (priority || !this._importants[name]) {
80
+ this.removeProperty(name);
81
+ this[this.length] = name;
82
+ this.length++;
83
+ this[name] = value + '';
84
+ this._importants[name] = priority;
85
+ }
49
86
  } else {
50
87
  // New property.
51
88
  this[this.length] = name;
52
89
  this.length++;
90
+ this[name] = value + '';
91
+ this._importants[name] = priority;
53
92
  }
54
- this[name] = value + "";
55
- this._importants[name] = priority;
56
93
  },
57
94
 
58
95
  /**
@@ -32,11 +32,14 @@ CSSOM.CSSStyleSheet.prototype.constructor = CSSOM.CSSStyleSheet;
32
32
  * -> "img{border:none;}body{margin:0;}"
33
33
  *
34
34
  * @param {string} rule
35
- * @param {number} index
35
+ * @param {number} [index=0]
36
36
  * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-insertRule
37
37
  * @return {number} The index within the style sheet's rule collection of the newly inserted rule.
38
38
  */
39
39
  CSSOM.CSSStyleSheet.prototype.insertRule = function(rule, index) {
40
+ if (index === void 0) {
41
+ index = 0;
42
+ }
40
43
  if (index < 0 || index > this.cssRules.length) {
41
44
  throw new RangeError("INDEX_SIZE_ERR");
42
45
  }
package/lib/clone.js CHANGED
@@ -12,7 +12,8 @@ var CSSOM = {
12
12
  CSSStyleDeclaration: require("./CSSStyleDeclaration").CSSStyleDeclaration,
13
13
  CSSKeyframeRule: require('./CSSKeyframeRule').CSSKeyframeRule,
14
14
  CSSKeyframesRule: require('./CSSKeyframesRule').CSSKeyframesRule,
15
- CSSLayerBlockRule: require('./CSSLayerBlockRule').CSSLayerBlockRule
15
+ CSSLayerBlockRule: require('./CSSLayerBlockRule').CSSLayerBlockRule,
16
+ CSSLayerStatementRule: require('./CSSLayerStatementRule').CSSLayerStatementRule
16
17
  };
17
18
  ///CommonJS
18
19
 
@@ -59,6 +60,10 @@ CSSOM.clone = function clone(stylesheet) {
59
60
  ruleClone.mediaText = rule.mediaText;
60
61
  }
61
62
 
63
+ if (rule.hasOwnProperty('supportsText')) {
64
+ ruleClone.supports = rule.supports;
65
+ }
66
+
62
67
  if (rule.hasOwnProperty('conditionText')) {
63
68
  ruleClone.conditionText = rule.conditionText;
64
69
  }
@@ -67,6 +72,18 @@ CSSOM.clone = function clone(stylesheet) {
67
72
  ruleClone.layerName = rule.layerName;
68
73
  }
69
74
 
75
+ if (rule.hasOwnProperty('href')) {
76
+ ruleClone.href = rule.href;
77
+ }
78
+
79
+ if (rule.hasOwnProperty('name')) {
80
+ ruleClone.name = rule.name;
81
+ }
82
+
83
+ if (rule.hasOwnProperty('nameList')) {
84
+ ruleClone.nameList = rule.nameList;
85
+ }
86
+
70
87
  if (rule.hasOwnProperty('cssRules')) {
71
88
  ruleClone.cssRules = clone(rule).cssRules;
72
89
  }
package/lib/index.js CHANGED
@@ -23,5 +23,6 @@ exports.CSSDocumentRule = require('./CSSDocumentRule').CSSDocumentRule;
23
23
  exports.CSSValue = require('./CSSValue').CSSValue;
24
24
  exports.CSSValueExpression = require('./CSSValueExpression').CSSValueExpression;
25
25
  exports.CSSLayerBlockRule = require('./CSSLayerBlockRule').CSSLayerBlockRule;
26
+ exports.CSSLayerStatementRule = require('./CSSLayerStatementRule').CSSLayerStatementRule;
26
27
  exports.parse = require('./parse').parse;
27
28
  exports.clone = require('./clone').clone;