You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
2.9 KiB
106 lines
2.9 KiB
const keywords = new Map(); |
|
const properties = new Map(); |
|
const HYPHENMINUS = 45; // '-'.charCodeAt() |
|
|
|
export const keyword = getKeywordDescriptor; |
|
export const property = getPropertyDescriptor; |
|
export const vendorPrefix = getVendorPrefix; |
|
export function isCustomProperty(str, offset) { |
|
offset = offset || 0; |
|
|
|
return str.length - offset >= 2 && |
|
str.charCodeAt(offset) === HYPHENMINUS && |
|
str.charCodeAt(offset + 1) === HYPHENMINUS; |
|
} |
|
|
|
function getVendorPrefix(str, offset) { |
|
offset = offset || 0; |
|
|
|
// verdor prefix should be at least 3 chars length |
|
if (str.length - offset >= 3) { |
|
// vendor prefix starts with hyper minus following non-hyper minus |
|
if (str.charCodeAt(offset) === HYPHENMINUS && |
|
str.charCodeAt(offset + 1) !== HYPHENMINUS) { |
|
// vendor prefix should contain a hyper minus at the ending |
|
const secondDashIndex = str.indexOf('-', offset + 2); |
|
|
|
if (secondDashIndex !== -1) { |
|
return str.substring(offset, secondDashIndex + 1); |
|
} |
|
} |
|
} |
|
|
|
return ''; |
|
} |
|
|
|
function getKeywordDescriptor(keyword) { |
|
if (keywords.has(keyword)) { |
|
return keywords.get(keyword); |
|
} |
|
|
|
const name = keyword.toLowerCase(); |
|
let descriptor = keywords.get(name); |
|
|
|
if (descriptor === undefined) { |
|
const custom = isCustomProperty(name, 0); |
|
const vendor = !custom ? getVendorPrefix(name, 0) : ''; |
|
descriptor = Object.freeze({ |
|
basename: name.substr(vendor.length), |
|
name, |
|
prefix: vendor, |
|
vendor, |
|
custom |
|
}); |
|
} |
|
|
|
keywords.set(keyword, descriptor); |
|
|
|
return descriptor; |
|
} |
|
|
|
function getPropertyDescriptor(property) { |
|
if (properties.has(property)) { |
|
return properties.get(property); |
|
} |
|
|
|
let name = property; |
|
let hack = property[0]; |
|
|
|
if (hack === '/') { |
|
hack = property[1] === '/' ? '//' : '/'; |
|
} else if (hack !== '_' && |
|
hack !== '*' && |
|
hack !== '$' && |
|
hack !== '#' && |
|
hack !== '+' && |
|
hack !== '&') { |
|
hack = ''; |
|
} |
|
|
|
const custom = isCustomProperty(name, hack.length); |
|
|
|
// re-use result when possible (the same as for lower case) |
|
if (!custom) { |
|
name = name.toLowerCase(); |
|
if (properties.has(name)) { |
|
const descriptor = properties.get(name); |
|
properties.set(property, descriptor); |
|
return descriptor; |
|
} |
|
} |
|
|
|
const vendor = !custom ? getVendorPrefix(name, hack.length) : ''; |
|
const prefix = name.substr(0, hack.length + vendor.length); |
|
const descriptor = Object.freeze({ |
|
basename: name.substr(prefix.length), |
|
name: name.substr(hack.length), |
|
hack, |
|
vendor, |
|
prefix, |
|
custom |
|
}); |
|
|
|
properties.set(property, descriptor); |
|
|
|
return descriptor; |
|
}
|
|
|