Block.cjs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. 'use strict';
  2. const types = require('../../tokenizer/types.cjs');
  3. const AMPERSAND = 0x0026; // U+0026 AMPERSAND (&)
  4. function consumeRaw() {
  5. return this.Raw(null, true);
  6. }
  7. function consumeRule() {
  8. return this.parseWithFallback(this.Rule, consumeRaw);
  9. }
  10. function consumeRawDeclaration() {
  11. return this.Raw(this.consumeUntilSemicolonIncluded, true);
  12. }
  13. function consumeDeclaration() {
  14. if (this.tokenType === types.Semicolon) {
  15. return consumeRawDeclaration.call(this, this.tokenIndex);
  16. }
  17. const node = this.parseWithFallback(this.Declaration, consumeRawDeclaration);
  18. if (this.tokenType === types.Semicolon) {
  19. this.next();
  20. }
  21. return node;
  22. }
  23. const name = 'Block';
  24. const walkContext = 'block';
  25. const structure = {
  26. children: [[
  27. 'Atrule',
  28. 'Rule',
  29. 'Declaration'
  30. ]]
  31. };
  32. function parse(isStyleBlock) {
  33. const consumer = isStyleBlock ? consumeDeclaration : consumeRule;
  34. const start = this.tokenStart;
  35. let children = this.createList();
  36. this.eat(types.LeftCurlyBracket);
  37. scan:
  38. while (!this.eof) {
  39. switch (this.tokenType) {
  40. case types.RightCurlyBracket:
  41. break scan;
  42. case types.WhiteSpace:
  43. case types.Comment:
  44. this.next();
  45. break;
  46. case types.AtKeyword:
  47. children.push(this.parseWithFallback(this.Atrule.bind(this, isStyleBlock), consumeRaw));
  48. break;
  49. default:
  50. if (isStyleBlock && this.isDelim(AMPERSAND)) {
  51. children.push(consumeRule.call(this));
  52. } else {
  53. children.push(consumer.call(this));
  54. }
  55. }
  56. }
  57. if (!this.eof) {
  58. this.eat(types.RightCurlyBracket);
  59. }
  60. return {
  61. type: 'Block',
  62. loc: this.getLocation(start, this.tokenStart),
  63. children
  64. };
  65. }
  66. function generate(node) {
  67. this.token(types.LeftCurlyBracket, '{');
  68. this.children(node, prev => {
  69. if (prev.type === 'Declaration') {
  70. this.token(types.Semicolon, ';');
  71. }
  72. });
  73. this.token(types.RightCurlyBracket, '}');
  74. }
  75. exports.generate = generate;
  76. exports.name = name;
  77. exports.parse = parse;
  78. exports.structure = structure;
  79. exports.walkContext = walkContext;