isString
и isNumber
.const VALID_KEYS = [
/^(.+)-(contains)$/,
/^(.+)-(starts)$/,
/^(.+)-(ends)$/,
/^(.+)-(value)$/,
/^(.+)-(operation)$/,
];
const REQUIRED_KEYS = {
string: ['contains', 'starts', 'ends'],
number: ['value', 'operation'],
};
const isString = (entry) => {
const keys = Object.keys(entry);
return (
keys.some((key) => REQUIRED_KEYS.string.includes(key)) &&
REQUIRED_KEYS.string.some((requiredKey) => keys.includes(requiredKey))
);
};
const isNumber = (entry) => {
const keys = Object.keys(entry);
return (
keys.every((key) => REQUIRED_KEYS.number.includes(key)) &&
REQUIRED_KEYS.number.every((requiredKey) => keys.includes(requiredKey))
);
};
// https://www.30secondsofcode.org/js/s/to-camel-case
const toCamelCase = (key) => {
const string = key
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.map((entry) => entry.slice(0, 1).toUpperCase() + entry.slice(1).toLowerCase())
.join('');
return string.slice(0, 1).toLowerCase() + string.slice(1);
};
const getParams = (string) => {
const searchParams = new URLSearchParams(string);
const data = {};
for (const key of searchParams.keys()) {
for (const expression of VALID_KEYS) {
const match = key.match(expression);
if (match !== null) {
data[match[1]] ??= {};
data[match[1]][match[2]] = searchParams.get(key);
}
}
}
const params = {};
for (const [param, entry] of Object.entries(data)) {
if (isString(entry)) {
params[toCamelCase(param)] = entry;
}
if (isNumber(entry)) {
params[toCamelCase(param)] = {
...entry,
value: parseFloat(entry.value),
};
}
}
return params;
};
const params = getParams(
'name-contains=fd&price-value=2&price-operation==&quantity-value=5&quantity-operation=>&description-ends=abc'
);
console.log(params);
/*
{
"name": {
"contains": "fd"
},
"price": {
"value": 2,
"operation": "="
},
"quantity": {
"value": 5,
"operation": ">"
},
"description": {
"ends": "abc"
}
}
*/
z-index
. interface Color {
red: number;
green: number;
blue: number;
}
const color: Color = {
red: 255,
green: 120,
blue: 0
};
const keys = <T extends object>(entry: T) => Object.keys(entry) as (keyof T)[];
const entries = <T extends object>(entry: T) => Object.entries(entry) as [keyof T, T[keyof T]][];
const f1 = keys(color);
const f2 = entries(color);
абракадабра в теге pathчитайте статью из ответа.
background-image
, но ничего менять не сможете. Вот инструмент для подготовки SVG к использованию в CSS: https://yoksel.github.io/url-encoder/.
formatter
можно ещё так: