Block.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. var TYPE = require('../../tokenizer').TYPE;
  2. var rawMode = require('./Raw').mode;
  3. var WHITESPACE = TYPE.WhiteSpace;
  4. var COMMENT = TYPE.Comment;
  5. var SEMICOLON = TYPE.Semicolon;
  6. var ATKEYWORD = TYPE.AtKeyword;
  7. var LEFTCURLYBRACKET = TYPE.LeftCurlyBracket;
  8. var RIGHTCURLYBRACKET = TYPE.RightCurlyBracket;
  9. function consumeRaw(startToken) {
  10. return this.Raw(startToken, null, true);
  11. }
  12. function consumeRule() {
  13. return this.parseWithFallback(this.Rule, consumeRaw);
  14. }
  15. function consumeRawDeclaration(startToken) {
  16. return this.Raw(startToken, rawMode.semicolonIncluded, true);
  17. }
  18. function consumeDeclaration() {
  19. if (this.scanner.tokenType === SEMICOLON) {
  20. return consumeRawDeclaration.call(this, this.scanner.tokenIndex);
  21. }
  22. var node = this.parseWithFallback(this.Declaration, consumeRawDeclaration);
  23. if (this.scanner.tokenType === SEMICOLON) {
  24. this.scanner.next();
  25. }
  26. return node;
  27. }
  28. module.exports = {
  29. name: 'Block',
  30. structure: {
  31. children: [[
  32. 'Atrule',
  33. 'Rule',
  34. 'Declaration'
  35. ]]
  36. },
  37. parse: function(isDeclaration) {
  38. var consumer = isDeclaration ? consumeDeclaration : consumeRule;
  39. var start = this.scanner.tokenStart;
  40. var children = this.createList();
  41. this.eat(LEFTCURLYBRACKET);
  42. scan:
  43. while (!this.scanner.eof) {
  44. switch (this.scanner.tokenType) {
  45. case RIGHTCURLYBRACKET:
  46. break scan;
  47. case WHITESPACE:
  48. case COMMENT:
  49. this.scanner.next();
  50. break;
  51. case ATKEYWORD:
  52. children.push(this.parseWithFallback(this.Atrule, consumeRaw));
  53. break;
  54. default:
  55. children.push(consumer.call(this));
  56. }
  57. }
  58. if (!this.scanner.eof) {
  59. this.eat(RIGHTCURLYBRACKET);
  60. }
  61. return {
  62. type: 'Block',
  63. loc: this.getLocation(start, this.scanner.tokenStart),
  64. children: children
  65. };
  66. },
  67. generate: function(node) {
  68. this.chunk('{');
  69. this.children(node, function(prev) {
  70. if (prev.type === 'Declaration') {
  71. this.chunk(';');
  72. }
  73. });
  74. this.chunk('}');
  75. },
  76. walkContext: 'block'
  77. };