Comparing version
@@ -350,3 +350,3 @@ # AST format | ||
| "type": "Rule", | ||
| "selector": <SelectorList> | <Raw>, | ||
| "prelude": <SelectorList> | <Raw>, | ||
| "block": <Block> | ||
@@ -353,0 +353,0 @@ } |
@@ -35,3 +35,3 @@ # Parsing CSS into AST | ||
| - [parseAtrulePrelude](#parseatruleprelude) | ||
| - [parseSelector](#parseselector) | ||
| - [parseRulePrelude](#parseruleprelude) | ||
| - [parseValue](#parsevalue) | ||
@@ -187,3 +187,3 @@ - [parseCustomProperty](#parsecustomproperty) | ||
| ### parseSelector | ||
| ### parseRulePrelude | ||
@@ -193,3 +193,3 @@ Type: `boolean` | ||
| Defines to parse a rule selector in details (represents as `SelectorList`). Otherwise represents selector as `Raw` node. | ||
| Defines to parse a rule prelude in details or left unparsed (represents as `Raw` node). | ||
@@ -217,3 +217,3 @@ ```js | ||
| csstree.parse('.foo {}', { parseSelector: false }); | ||
| csstree.parse('.foo {}', { parseRulePrelude: false }); | ||
| // { | ||
@@ -223,3 +223,3 @@ // "type": "Rule", | ||
| // "type": "Raw", | ||
| // "value": ".foo " | ||
| // "value": ".foo" | ||
| // }, | ||
@@ -226,0 +226,0 @@ // "block": { |
@@ -0,6 +1,20 @@ | ||
| ## 1.0.0-alpha24 (September 14, 2017) | ||
| - Improved CSSTree to be stable for standart build-in objects extension (#58) | ||
| - Parser | ||
| - Renamed rule's `selector` to `prelude`. The reasons: [spec names this part so](https://www.w3.org/TR/css-syntax-3/#qualified-rule), and this branch can contain not only a selector (`SelectorList`) but also a raw payload (`Raw`). What's changed: | ||
| - Renamed `Rule.selector` to `Rule.prelude` | ||
| - Renamed `parseSelector` parser option to `parseRulePrelude` | ||
| - Removed option for selector parse in `SelectorList` | ||
| - Lexer | ||
| - Fixed undefined positions in a error when match a syntax to empty or white space only value | ||
| - Improved `Lexer#checkStructure()` | ||
| - Return a warning as an object with node reference and message | ||
| - No exception on unknown node type, return a warning instead | ||
| ## 1.0.0-alpha23 (September 10, 2017) | ||
| - Fixed `Tokenizer#getRawLength()`'s false positive balance match to the end of input in some cases (#56) | ||
| - Rename walker's entry point methods to be the as CSSTree methods (i.e. `walk()`, `walkUp` etc) | ||
| - Rename at-rule `expression` to `prelude`: | ||
| - Rename walker's entry point methods to be the same as CSSTree exposed methods (i.e. `walk()`, `walkUp()` etc) | ||
| - Rename at-rule's `expression` to `prelude` (since [spec names it so](https://www.w3.org/TR/css-syntax-3/#at-rule)) | ||
| - `AtruleExpression` node type → `AtrulePrelude` | ||
@@ -7,0 +21,0 @@ - `Atrule.expression` field → `Atrule.prelude` |
@@ -92,3 +92,3 @@ 'use strict'; | ||
| if (!result.match) { | ||
| return buildMatchResult(null, new MatchError('Mismatch', lexer, syntax.syntax, value, result.badNode || unwrapNode(result.next))); | ||
| return buildMatchResult(null, new MatchError('Mismatch', lexer, syntax.syntax, value, result.badNode || unwrapNode(result.next) || value)); | ||
| } | ||
@@ -114,3 +114,3 @@ } | ||
| if (result.next && !isNextMayToBeIgnored(result.next)) { | ||
| return buildMatchResult(null, new MatchError('Uncomplete match', lexer, syntax.syntax, value, result.badNode || unwrapNode(result.next))); | ||
| return buildMatchResult(null, new MatchError('Uncomplete match', lexer, syntax.syntax, value, result.badNode || unwrapNode(result.next) || value)); | ||
| } | ||
@@ -154,2 +154,9 @@ | ||
| checkStructure: function(ast) { | ||
| function collectWarning(node, message) { | ||
| warns.push({ | ||
| node: node, | ||
| message: message | ||
| }); | ||
| } | ||
| var structure = this.structure; | ||
@@ -160,5 +167,5 @@ var warns = []; | ||
| if (structure.hasOwnProperty(node.type)) { | ||
| structure[node.type].check(node, warns.push.bind(warns)); | ||
| structure[node.type].check(node, collectWarning); | ||
| } else { | ||
| throw new Error('Unknown node type: ' + node.type); | ||
| collectWarning(node, 'Unknown node type `' + node.type + '`'); | ||
| } | ||
@@ -165,0 +172,0 @@ }); |
| var List = require('../utils/list'); | ||
| var hasOwnProperty = Object.prototype.hasOwnProperty; | ||
@@ -25,9 +26,15 @@ function isValidNumber(value) { | ||
| if (!node || node.constructor !== Object) { | ||
| return warn('Type of node should be an object'); | ||
| return warn(node, 'Type of node should be an Object'); | ||
| } | ||
| for (var key in node) { | ||
| var valid = true; | ||
| if (hasOwnProperty.call(node, key) === false) { | ||
| continue; | ||
| } | ||
| if (key === 'type') { | ||
| if (node.type !== type) { | ||
| warn('Wrong node type `' + node.type + '` but expected `' + type + '`'); | ||
| warn(node, 'Wrong node type `' + node.type + '`, expected `' + type + '`'); | ||
| } | ||
@@ -38,9 +45,14 @@ } else if (key === 'loc') { | ||
| } else if (node.loc && node.loc.constructor === Object) { | ||
| if (typeof node.loc.source === 'string' && | ||
| isValidLocation(node.loc.start) && | ||
| isValidLocation(node.loc.end)) { | ||
| 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; | ||
| } | ||
| } | ||
| warn('Wrong value for `' + type + '.' + key + '` field'); | ||
| valid = false; | ||
| } else if (fields.hasOwnProperty(key)) { | ||
@@ -71,13 +83,15 @@ for (var i = 0, valid = false; !valid && i < fields[key].length; i++) { | ||
| } | ||
| if (!valid) { | ||
| warn('Wrong value for `' + type + '.' + key + '` field'); | ||
| } | ||
| } else { | ||
| warn('Unknown field `' + key + '` for ' + type); | ||
| warn(node, 'Unknown field `' + key + '` for ' + type + ' node type'); | ||
| } | ||
| if (!valid) { | ||
| warn(node, 'Bad value for `' + type + '.' + key + '`'); | ||
| } | ||
| } | ||
| for (var key in fields) { | ||
| if (hasOwnProperty.call(node, key) === false) { | ||
| warn('Field `' + type + '.' + key + '` is missed'); | ||
| if (hasOwnProperty.call(fields, key) && | ||
| hasOwnProperty.call(node, key) === false) { | ||
| warn(node, 'Field `' + type + '.' + key + '` is missed'); | ||
| } | ||
@@ -99,2 +113,6 @@ } | ||
| for (var key in structure) { | ||
| if (hasOwnProperty.call(structure, key) === false) { | ||
| continue; | ||
| } | ||
| var docsTypes = []; | ||
@@ -116,3 +134,3 @@ var fieldTypes = fields[key] = Array.isArray(structure[key]) | ||
| } else { | ||
| throw new Error('Wrong value in `' + name + '` structure definition'); | ||
| throw new Error('Wrong value `' + fieldType + '` in `' + name + '.' + key + '` structure definition'); | ||
| } | ||
@@ -136,8 +154,10 @@ } | ||
| for (var name in config.node) { | ||
| var nodeType = config.node[name]; | ||
| if (hasOwnProperty.call(config.node, name)) { | ||
| var nodeType = config.node[name]; | ||
| if (nodeType.structure) { | ||
| structure[name] = processStructure(name, nodeType); | ||
| } else { | ||
| throw new Error('Missed `structure` field in `' + name + '` node type definition'); | ||
| if (nodeType.structure) { | ||
| structure[name] = processStructure(name, nodeType); | ||
| } else { | ||
| throw new Error('Missed `structure` field in `' + name + '` node type definition'); | ||
| } | ||
| } | ||
@@ -144,0 +164,0 @@ } |
@@ -78,3 +78,3 @@ 'use strict'; | ||
| parseAtrulePrelude: true, | ||
| parseSelector: true, | ||
| parseRulePrelude: true, | ||
| parseValue: true, | ||
@@ -141,3 +141,3 @@ parseCustomProperty: false, | ||
| parser.parseAtrulePrelude = 'parseAtrulePrelude' in options ? Boolean(options.parseAtrulePrelude) : true; | ||
| parser.parseSelector = 'parseSelector' in options ? Boolean(options.parseSelector) : true; | ||
| parser.parseRulePrelude = 'parseRulePrelude' in options ? Boolean(options.parseRulePrelude) : true; | ||
| parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true; | ||
@@ -144,0 +144,0 @@ parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false; |
@@ -0,1 +1,2 @@ | ||
| var hasOwnProperty = Object.prototype.hasOwnProperty; | ||
| var shape = { | ||
@@ -20,3 +21,5 @@ generic: true, | ||
| for (var key in value) { | ||
| res[key] = value[key]; | ||
| if (hasOwnProperty.call(value, key)) { | ||
| res[key] = value[key]; | ||
| } | ||
| } | ||
@@ -31,6 +34,8 @@ return res; | ||
| for (var key in src) { | ||
| if (isObject(dest[key])) { | ||
| extend(dest[key], copy(src[key])); | ||
| } else { | ||
| dest[key] = copy(src[key]); | ||
| if (hasOwnProperty.call(src, key)) { | ||
| if (isObject(dest[key])) { | ||
| extend(dest[key], copy(src[key])); | ||
| } else { | ||
| dest[key] = copy(src[key]); | ||
| } | ||
| } | ||
@@ -42,5 +47,11 @@ } | ||
| for (var key in shape) { | ||
| if (hasOwnProperty.call(shape, key) === false) { | ||
| continue; | ||
| } | ||
| if (shape[key] === true) { | ||
| if (key in src) { | ||
| dest[key] = copy(src[key]); | ||
| if (hasOwnProperty.call(src, key)) { | ||
| dest[key] = copy(src[key]); | ||
| } | ||
| } | ||
@@ -60,14 +71,18 @@ } else if (shape[key]) { | ||
| for (var name in dest[key]) { | ||
| res[name] = {}; | ||
| if (dest[key] && dest[key][name]) { | ||
| mix(res[name], dest[key][name], innerShape); | ||
| if (hasOwnProperty.call(dest[key], name)) { | ||
| res[name] = {}; | ||
| if (dest[key] && dest[key][name]) { | ||
| mix(res[name], dest[key][name], innerShape); | ||
| } | ||
| } | ||
| } | ||
| for (var name in src[key]) { | ||
| if (!res[name]) { | ||
| res[name] = {}; | ||
| if (hasOwnProperty.call(src[key], name)) { | ||
| if (!res[name]) { | ||
| res[name] = {}; | ||
| } | ||
| if (src[key] && src[key][name]) { | ||
| mix(res[name], src[key][name], innerShape); | ||
| } | ||
| } | ||
| if (src[key] && src[key][name]) { | ||
| mix(res[name], src[key][name], innerShape); | ||
| } | ||
| } | ||
@@ -74,0 +89,0 @@ dest[key] = res; |
@@ -12,3 +12,3 @@ var TYPE = require('../../tokenizer').TYPE; | ||
| structure: { | ||
| selector: ['SelectorList', 'Raw'], | ||
| prelude: ['SelectorList', 'Raw'], | ||
| block: ['Block'] | ||
@@ -19,3 +19,3 @@ }, | ||
| var startOffset = this.scanner.tokenStart; | ||
| var selector = this.parseSelector | ||
| var prelude = this.parseRulePrelude | ||
| ? this.tolerantParse(this.SelectorList, consumeRaw) | ||
@@ -28,3 +28,3 @@ : consumeRaw.call(this, startToken); | ||
| loc: this.getLocation(startOffset, this.scanner.tokenStart), | ||
| selector: selector, | ||
| prelude: prelude, | ||
| block: block | ||
@@ -34,3 +34,3 @@ }; | ||
| generate: function(processChunk, node) { | ||
| this.generate(processChunk, node.selector); | ||
| this.generate(processChunk, node.prelude); | ||
| this.generate(processChunk, node.block); | ||
@@ -37,0 +37,0 @@ }, |
@@ -5,3 +5,2 @@ var List = require('../../utils/list'); | ||
| var COMMA = TYPE.Comma; | ||
| var LEFTCURLYBRACKET = TYPE.LeftCurlyBracket; | ||
@@ -17,6 +16,3 @@ module.exports = { | ||
| while (!this.scanner.eof) { | ||
| children.appendData(this.parseSelector | ||
| ? this.Selector() | ||
| : this.Raw(this.scanner.currentToken, COMMA, LEFTCURLYBRACKET, false, false) | ||
| ); | ||
| children.appendData(this.Selector()); | ||
@@ -23,0 +19,0 @@ if (this.scanner.tokenType === COMMA) { |
| 'use strict'; | ||
| var hasOwnProperty = Object.prototype.hasOwnProperty; | ||
| function walkRules(node, item, list) { | ||
@@ -145,2 +147,7 @@ switch (node.type) { | ||
| for (var key in structure) { | ||
| if (hasOwnProperty.call(structure, key) === false) { | ||
| continue; | ||
| } | ||
| var fieldTypes = structure[key]; | ||
| var walker = { | ||
@@ -152,4 +159,2 @@ name: key, | ||
| var fieldTypes = structure[key]; | ||
| if (!Array.isArray(structure[key])) { | ||
@@ -190,11 +195,13 @@ fieldTypes = [structure[key]]; | ||
| for (var name in config.node) { | ||
| var nodeType = config.node[name]; | ||
| if (hasOwnProperty.call(config.node, name)) { | ||
| var nodeType = config.node[name]; | ||
| if (nodeType.structure) { | ||
| var walkers = getWalkersFromStructure(name, nodeType); | ||
| if (walkers !== null) { | ||
| types[name] = walkers; | ||
| if (nodeType.structure) { | ||
| var walkers = getWalkersFromStructure(name, nodeType); | ||
| if (walkers !== null) { | ||
| types[name] = walkers; | ||
| } | ||
| } else { | ||
| throw new Error('Missed `structure` field in `' + name + '` node type definition'); | ||
| } | ||
| } else { | ||
| throw new Error('Missed `structure` field in `' + name + '` node type definition'); | ||
| } | ||
@@ -229,18 +236,20 @@ } | ||
| for (var name in types) { | ||
| var config = types[name]; | ||
| walkers[name] = Function('node', 'context', 'walk', | ||
| (config.context ? 'var old = context.' + config.context + ';\ncontext.' + config.context + ' = node;\n' : '') + | ||
| config.fields.map(function(field) { | ||
| var line = field.type === 'list' | ||
| ? 'node.' + field.name + '.each(walk);' | ||
| : 'walk(node.' + field.name + ');'; | ||
| if (hasOwnProperty.call(types, name)) { | ||
| var config = types[name]; | ||
| walkers[name] = Function('node', 'context', 'walk', | ||
| (config.context ? 'var old = context.' + config.context + ';\ncontext.' + config.context + ' = node;\n' : '') + | ||
| config.fields.map(function(field) { | ||
| var line = field.type === 'list' | ||
| ? 'node.' + field.name + '.each(walk);' | ||
| : 'walk(node.' + field.name + ');'; | ||
| if (field.nullable) { | ||
| line = 'if (node.' + field.name + ') {\n ' + line + '}'; | ||
| } | ||
| if (field.nullable) { | ||
| line = 'if (node.' + field.name + ') {\n ' + line + '}'; | ||
| } | ||
| return line; | ||
| }).join('\n') + | ||
| (config.context ? '\ncontext.' + config.context + ' = old;' : '') | ||
| ); | ||
| return line; | ||
| }).join('\n') + | ||
| (config.context ? '\ncontext.' + config.context + ' = old;' : '') | ||
| ); | ||
| } | ||
| } | ||
@@ -247,0 +256,0 @@ |
| { | ||
| "name": "css-tree", | ||
| "version": "1.0.0-alpha23", | ||
| "version": "1.0.0-alpha24", | ||
| "description": "Fast detailed CSS parser", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Sorry, the diff of this file is too big to display
575016
0.49%7840
0.5%