Add: parse more metas, add variable type
This commit is contained in:
parent
b3b47697ca
commit
78264a1c34
141
js/usercss.js
141
js/usercss.js
|
@ -4,6 +4,12 @@
|
|||
|
||||
// eslint-disable-next-line no-var
|
||||
var usercss = (function () {
|
||||
const METAS = [
|
||||
'author', 'description', 'homepageURL', 'icon', 'license', 'name',
|
||||
'namespace', 'noframes', 'preprocessor', 'supportURL', 'var', 'version'
|
||||
];
|
||||
|
||||
// FIXME: use a real semver module
|
||||
function semverTest(a, b) {
|
||||
a = a.split('.').map(Number);
|
||||
b = b.split('.').map(Number);
|
||||
|
@ -27,23 +33,6 @@ var usercss = (function () {
|
|||
return 0;
|
||||
}
|
||||
|
||||
function guessType(value) {
|
||||
if (/^url\(.+\)$/i.test(value)) {
|
||||
return 'image';
|
||||
}
|
||||
if (/^#[0-9a-f]{3,8}$/i.test(value)) {
|
||||
return 'color';
|
||||
}
|
||||
if (/^hsla?\(.+\)$/i.test(value)) {
|
||||
return 'color';
|
||||
}
|
||||
if (/^rgba?\(.+\)$/i.test(value)) {
|
||||
return 'color';
|
||||
}
|
||||
// should we use a color-name table to guess type?
|
||||
return 'text';
|
||||
}
|
||||
|
||||
const BUILDER = {
|
||||
default: {
|
||||
postprocess(sections, vars) {
|
||||
|
@ -102,6 +91,70 @@ var usercss = (function () {
|
|||
return style;
|
||||
}
|
||||
|
||||
function *parseMetas(source) {
|
||||
for (const line of source.split(/\r?\n/)) {
|
||||
const match = line.match(/@(\w+)/);
|
||||
if (!match) {
|
||||
continue;
|
||||
}
|
||||
yield [match[1], line.slice(match.index + match[0].length).trim()];
|
||||
}
|
||||
}
|
||||
|
||||
function matchString(s) {
|
||||
const match = matchFollow(s, /^(?:\w+|(['"])(?:\\\1|.)*?\1)/);
|
||||
match.value = match[1] ? match[0].slice(1, -1) : match[0];
|
||||
return match;
|
||||
}
|
||||
|
||||
function matchFollow(s, re) {
|
||||
const match = s.match(re);
|
||||
match.follow = s.slice(match.index + match[0].length).trim();
|
||||
return match;
|
||||
}
|
||||
|
||||
// FIXME: need color converter
|
||||
function normalizeColor(color) {
|
||||
return color;
|
||||
}
|
||||
|
||||
function parseVar(source) {
|
||||
const result = {
|
||||
label: null,
|
||||
name: null,
|
||||
value: null,
|
||||
default: null,
|
||||
select: null
|
||||
};
|
||||
|
||||
{
|
||||
// type & name
|
||||
const match = matchFollow(source, /^([\w-]+)\s+([\w-]+)/);
|
||||
([, result.type, result.name] = match);
|
||||
source = match.follow;
|
||||
}
|
||||
|
||||
{
|
||||
// label
|
||||
const match = matchString(source);
|
||||
result.label = match.value;
|
||||
source = match.follow;
|
||||
}
|
||||
|
||||
// value
|
||||
if (result.type === 'color') {
|
||||
source = normalizeColor(source);
|
||||
} else if (result.type === 'select') {
|
||||
const match = matchString(source);
|
||||
result.select = JSON.parse(match.follow);
|
||||
source = match.value;
|
||||
}
|
||||
|
||||
result.default = source;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function _buildMeta(source) {
|
||||
const style = {
|
||||
name: null,
|
||||
|
@ -111,52 +164,27 @@ var usercss = (function () {
|
|||
enabled: true,
|
||||
sections: [],
|
||||
vars: {},
|
||||
preprocessor: null
|
||||
preprocessor: null,
|
||||
noframes: false
|
||||
};
|
||||
|
||||
const metaSource = getMetaSource(source);
|
||||
|
||||
const match = (re, callback) => {
|
||||
let m;
|
||||
if (!re.global) {
|
||||
if ((m = metaSource.match(re))) {
|
||||
if (m.length === 1) {
|
||||
callback(m[0]);
|
||||
for (const [key, value] of parseMetas(metaSource)) {
|
||||
if (!METAS.includes(key)) {
|
||||
continue;
|
||||
}
|
||||
if (key === 'noframes') {
|
||||
style.noframes = true;
|
||||
} else if (key === 'var') {
|
||||
const va = parseVar(value);
|
||||
style.vars[va.name] = va;
|
||||
} else if (key === 'homepageURL') {
|
||||
style.url = value;
|
||||
} else {
|
||||
callback(...m.slice(1));
|
||||
style[key] = value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const result = [];
|
||||
while ((m = re.exec(metaSource))) {
|
||||
if (m.length <= 2) {
|
||||
result.push(m[m.length - 1]);
|
||||
} else {
|
||||
result.push(m.slice(1));
|
||||
}
|
||||
}
|
||||
if (result.length) {
|
||||
callback(result);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: finish all metas
|
||||
match(/@name[^\S\r\n]+(.+?)[^\S\r\n]*$/m, m => (style.name = m));
|
||||
match(/@namespace[^\S\r\n]+(\S+)/, m => (style.namespace = m));
|
||||
match(/@preprocessor[^\S\r\n]+(\S+)/, m => (style.preprocessor = m));
|
||||
match(/@version[^\S\r\n]+(\S+)/, m => (style.version = m));
|
||||
match(
|
||||
/@var[^\S\r\n]+(\S+)[^\S\r\n]+(?:(['"])((?:\\\2|.)*?)\2|(\S+))[^\S\r\n]+(.+?)[^\S\r\n]*$/gm,
|
||||
ms => ms.forEach(([key,, label1, label2, value]) => (
|
||||
style.vars[key] = {
|
||||
type: guessType(value),
|
||||
label: label1 || label2,
|
||||
value: null, // '.value' holds the value set by users.
|
||||
default: value // '.default' holds the value extract from meta.
|
||||
}
|
||||
))
|
||||
);
|
||||
|
||||
return style;
|
||||
}
|
||||
|
@ -212,6 +240,7 @@ var usercss = (function () {
|
|||
throw new Error(chrome.i18n.getMessage('styleMissingMeta', prop));
|
||||
}
|
||||
}
|
||||
// FIXME: validate variable formats
|
||||
}
|
||||
|
||||
return {buildMeta, buildCode, semverTest};
|
||||
|
|
Loading…
Reference in New Issue
Block a user