1 | const handler = {
|
2 | has(target, property) {
|
3 | switch (property) {
|
4 | case 'cssText':
|
5 | return true;
|
6 | }
|
7 | return _.get(target).props.hasOwnProperty(property);
|
8 | },
|
9 | get(target, property, receiver) {
|
10 | switch (property) {
|
11 | case 'cssText': return target.toString();
|
12 | case 'getPropertyValue': return target.getPropertyValue.bind(_.get(target).props);
|
13 | case 'setProperty': return target.setProperty.bind(_.get(target).props);
|
14 | }
|
15 | return _.get(target).props[property];
|
16 | },
|
17 | set(target, property, value) {
|
18 | const rel = _.get(target);
|
19 | const {props} = rel;
|
20 | rel.value = ('' + value).trim();
|
21 | switch (property) {
|
22 | case 'cssText':
|
23 | for (const key in props) delete props[key];
|
24 | (value || '').split(';').forEach(pair => {
|
25 | const kv = pair.split(':');
|
26 | if (kv.length < 2)
|
27 | return;
|
28 | const key = toProperty((kv[0] || '').trim());
|
29 | if (key) {
|
30 | const value = kv[1].trim();
|
31 | props[key] = (key === '_hyper' ? ' ' : '') + value;
|
32 | }
|
33 | });
|
34 | break;
|
35 | default:
|
36 | props[property] = value;
|
37 | break;
|
38 | }
|
39 | return true;
|
40 | }
|
41 | };
|
42 |
|
43 | const _ = new WeakMap;
|
44 |
|
45 | module.exports = class CSSStyleDeclaration {
|
46 | constructor() {
|
47 | _.set(this, {props: {}, value: ''});
|
48 | return new Proxy(this, handler);
|
49 | }
|
50 | getPropertyValue(key) {
|
51 | return this[key];
|
52 | }
|
53 | setProperty(key, value) {
|
54 | this[key] = value;
|
55 | }
|
56 | toString() {
|
57 | const {props, value} = _.get(this);
|
58 | return Object.keys(props).reduce(
|
59 | (css, key) => css + toStyle(key) + ':' + props[key] + ';',
|
60 | ''
|
61 | ) || value;
|
62 | }
|
63 | };
|
64 |
|
65 | function toProperty(key) {
|
66 | return key.replace(/-([^-])/g, ($0, $1) => $1.toUpperCase());
|
67 | }
|
68 |
|
69 | function toStyle(key) {
|
70 | return key.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
71 | }
|