diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2023-10-14 15:05:55 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2023-10-14 15:05:55 +0800 |
| commit | c06f7ee0a40255214c477e13d9b956a7e07c2900 (patch) | |
| tree | f5982a568ef8fab865d0142e71c7494fea3e4c1b /node_modules/css-tree/lib/lexer/structure.js | |
| parent | 3fd9400d4dccc25aa29b5702216732e0b7542073 (diff) | |
postcss,(plugins): nanocss, postcss-preset-env
Diffstat (limited to 'node_modules/css-tree/lib/lexer/structure.js')
| -rw-r--r-- | node_modules/css-tree/lib/lexer/structure.js | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/node_modules/css-tree/lib/lexer/structure.js b/node_modules/css-tree/lib/lexer/structure.js new file mode 100644 index 00000000..0c8ee62f --- /dev/null +++ b/node_modules/css-tree/lib/lexer/structure.js @@ -0,0 +1,164 @@ +import { List } from '../utils/List.js'; + +const { hasOwnProperty } = Object.prototype; + +function isValidNumber(value) { + // Number.isInteger(value) && value >= 0 + return ( + typeof value === 'number' && + isFinite(value) && + Math.floor(value) === value && + value >= 0 + ); +} + +function isValidLocation(loc) { + return ( + Boolean(loc) && + isValidNumber(loc.offset) && + isValidNumber(loc.line) && + isValidNumber(loc.column) + ); +} + +function createNodeStructureChecker(type, fields) { + return function checkNode(node, warn) { + if (!node || node.constructor !== Object) { + return warn(node, 'Type of node should be an Object'); + } + + for (let key in node) { + let valid = true; + + if (hasOwnProperty.call(node, key) === false) { + continue; + } + + if (key === 'type') { + if (node.type !== type) { + warn(node, 'Wrong node type `' + node.type + '`, expected `' + type + '`'); + } + } else if (key === 'loc') { + if (node.loc === null) { + continue; + } else if (node.loc && node.loc.constructor === Object) { + if (typeof node.loc.source !== 'string') { + key += '.source'; + } else if (!isValidLocation(node.loc.start)) { + key += '.start'; + } else if (!isValidLocation(node.loc.end)) { + key += '.end'; + } else { + continue; + } + } + + valid = false; + } else if (fields.hasOwnProperty(key)) { + valid = false; + + for (let i = 0; !valid && i < fields[key].length; i++) { + const fieldType = fields[key][i]; + + switch (fieldType) { + case String: + valid = typeof node[key] === 'string'; + break; + + case Boolean: + valid = typeof node[key] === 'boolean'; + break; + + case null: + valid = node[key] === null; + break; + + default: + if (typeof fieldType === 'string') { + valid = node[key] && node[key].type === fieldType; + } else if (Array.isArray(fieldType)) { + valid = node[key] instanceof List; + } + } + } + } else { + warn(node, 'Unknown field `' + key + '` for ' + type + ' node type'); + } + + if (!valid) { + warn(node, 'Bad value for `' + type + '.' + key + '`'); + } + } + + for (const key in fields) { + if (hasOwnProperty.call(fields, key) && + hasOwnProperty.call(node, key) === false) { + warn(node, 'Field `' + type + '.' + key + '` is missed'); + } + } + }; +} + +function processStructure(name, nodeType) { + const structure = nodeType.structure; + const fields = { + type: String, + loc: true + }; + const docs = { + type: '"' + name + '"' + }; + + for (const key in structure) { + if (hasOwnProperty.call(structure, key) === false) { + continue; + } + + const docsTypes = []; + const fieldTypes = fields[key] = Array.isArray(structure[key]) + ? structure[key].slice() + : [structure[key]]; + + for (let i = 0; i < fieldTypes.length; i++) { + const fieldType = fieldTypes[i]; + if (fieldType === String || fieldType === Boolean) { + docsTypes.push(fieldType.name); + } else if (fieldType === null) { + docsTypes.push('null'); + } else if (typeof fieldType === 'string') { + docsTypes.push('<' + fieldType + '>'); + } else if (Array.isArray(fieldType)) { + docsTypes.push('List'); // TODO: use type enum + } else { + throw new Error('Wrong value `' + fieldType + '` in `' + name + '.' + key + '` structure definition'); + } + } + + docs[key] = docsTypes.join(' | '); + } + + return { + docs, + check: createNodeStructureChecker(name, fields) + }; +} + +export function getStructureFromConfig(config) { + const structure = {}; + + if (config.node) { + for (const name in config.node) { + if (hasOwnProperty.call(config.node, name)) { + const nodeType = config.node[name]; + + if (nodeType.structure) { + structure[name] = processStructure(name, nodeType); + } else { + throw new Error('Missed `structure` field in `' + name + '` node type definition'); + } + } + } + } + + return structure; +}; |
