You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
2.9 KiB
JavaScript

'use strict';
const uhyphen = (m => /* c8 ignore start */ m.__esModule ? m.default : m /* c8 ignore stop */)(require('uhyphen'));
const {CHANGED, PRIVATE, VALUE} = require('../shared/symbols.js');
const refs = new WeakMap;
const getKeys = style => [...style.keys()].filter(key => key !== PRIVATE);
const updateKeys = style => {
const attr = refs.get(style).getAttributeNode('style');
if (!attr || attr[CHANGED] || style.get(PRIVATE) !== attr) {
style.clear();
if (attr) {
style.set(PRIVATE, attr);
for (const rule of attr[VALUE].split(/\s*;\s*/)) {
let [key, ...rest] = rule.split(':');
if (rest.length > 0) {
key = key.trim();
const value = rest.join(':').trim();
if (key && value)
style.set(key, value);
}
}
}
}
return attr;
};
const handler = {
get(style, name) {
if (name in prototype)
return style[name];
updateKeys(style);
if (name === 'length')
return getKeys(style).length;
if (/^\d+$/.test(name))
return getKeys(style)[name];
return style.get(uhyphen(name));
},
set(style, name, value) {
if (name === 'cssText')
style[name] = value;
else {
let attr = updateKeys(style);
if (value == null)
style.delete(uhyphen(name));
else
style.set(uhyphen(name), value);
if (!attr) {
const element = refs.get(style);
attr = element.ownerDocument.createAttribute('style');
element.setAttributeNode(attr);
style.set(PRIVATE, attr);
}
attr[CHANGED] = false;
attr[VALUE] = style.toString();
}
return true;
}
};
/**
* @implements globalThis.CSSStyleDeclaration
*/
class CSSStyleDeclaration extends Map {
constructor(element) {
super();
refs.set(this, element);
/* c8 ignore start */
return new Proxy(this, handler);
/* c8 ignore stop */
}
get cssText() {
return this.toString();
}
set cssText(value) {
refs.get(this).setAttribute('style', value);
}
getPropertyValue(name) {
const self = this[PRIVATE];
return handler.get(self, name);
}
setProperty(name, value) {
const self = this[PRIVATE];
handler.set(self, name, value);
}
removeProperty(name) {
const self = this[PRIVATE];
handler.set(self, name, null);
}
[Symbol.iterator]() {
const self = this[PRIVATE];
updateKeys(self);
const keys = getKeys(self);
const {length} = keys;
let i = 0;
return {
next() {
const done = i === length;
return {done, value: done ? null : keys[i++]};
}
};
}
get[PRIVATE]() { return this; }
toString() {
const self = this[PRIVATE];
updateKeys(self);
const cssText = [];
self.forEach(push, cssText);
return cssText.join(';');
}
}
exports.CSSStyleDeclaration = CSSStyleDeclaration
const {prototype} = CSSStyleDeclaration;
function push(value, key) {
if (key !== PRIVATE)
this.push(`${key}:${value}`);
}