mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-01 08:16:03 +00:00
83 lines
2.0 KiB
JavaScript
83 lines
2.0 KiB
JavaScript
|
|
export class CSS
|
|
{
|
|
/*
|
|
Parses given css string, and returns css object
|
|
keys as selectors and values are css rules
|
|
eliminates all css comments before parsing
|
|
|
|
@param source css string to be parsed
|
|
|
|
@return object css
|
|
*/
|
|
parse(source) {
|
|
|
|
const css = [];
|
|
|
|
css.toString = () => css.reduce(
|
|
(ret, tmp) =>
|
|
ret + tmp.selector + ' {\n'
|
|
+ (tmp.type === 'media' ? tmp.subStyles.toString() : tmp.rules)
|
|
+ '}\n'
|
|
,
|
|
''
|
|
);
|
|
|
|
/**
|
|
* Given css array, parses it and then for every selector,
|
|
* prepends namespace to prevent css collision issues
|
|
*/
|
|
css.applyNamespace = (namespace) => css.forEach(obj => {
|
|
if (obj.type === 'media') {
|
|
obj.subStyles.applyNamespace(namespace);
|
|
} else {
|
|
obj.selector = obj.selector.split(',').map(selector => namespace + ' ' + selector).join(',');
|
|
}
|
|
});
|
|
|
|
if (source) {
|
|
source = source
|
|
// strip comments
|
|
.replace(/\/\*[\s\S]*?\*\/|<!--|-->/gi, '')
|
|
// strip import statements
|
|
.replace(/@import .*?;/gi , '')
|
|
// strip keyframe statements
|
|
.replace(/((@.*?keyframes [\s\S]*?){([\s\S]*?}\s*?)})/gi, '');
|
|
|
|
// unified regex to match css & media queries together
|
|
let unified = /((\s*?(?:\/\*[\s\S]*?\*\/)?\s*?@media[\s\S]*?){([\s\S]*?)}\s*?})|(([\s\S]*?){([\s\S]*?)})/gi,
|
|
arr;
|
|
|
|
while (true) {
|
|
arr = unified.exec(source);
|
|
if (arr === null) {
|
|
break;
|
|
}
|
|
|
|
let selector = arr[arr[2] === undefined ? 5 : 2].split('\r\n').join('\n').trim()
|
|
// Never have more than a single line break in a row
|
|
.replace(/\n+/, "\n");
|
|
|
|
// determine the type
|
|
if (selector.includes('@media')) {
|
|
// we have a media query
|
|
css.push({
|
|
selector: selector,
|
|
type: 'media',
|
|
subStyles: this.parse(arr[3] + '\n}') //recursively parse media query inner css
|
|
});
|
|
} else if (!selector.includes('@') && ![':root','html','body'].includes(selector)) {
|
|
// we have standard css
|
|
css.push({
|
|
selector: selector,
|
|
rules: arr[6]
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return css;
|
|
}
|
|
|
|
}
|