Atrule.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import {
  2. AtKeyword,
  3. Semicolon,
  4. LeftCurlyBracket,
  5. RightCurlyBracket
  6. } from '../../tokenizer/index.js';
  7. function consumeRaw() {
  8. return this.Raw(this.consumeUntilLeftCurlyBracketOrSemicolon, true);
  9. }
  10. function isDeclarationBlockAtrule() {
  11. for (let offset = 1, type; type = this.lookupType(offset); offset++) {
  12. if (type === RightCurlyBracket) {
  13. return true;
  14. }
  15. if (type === LeftCurlyBracket ||
  16. type === AtKeyword) {
  17. return false;
  18. }
  19. }
  20. return false;
  21. }
  22. export const name = 'Atrule';
  23. export const walkContext = 'atrule';
  24. export const structure = {
  25. name: String,
  26. prelude: ['AtrulePrelude', 'Raw', null],
  27. block: ['Block', null]
  28. };
  29. export function parse(isDeclaration = false) {
  30. const start = this.tokenStart;
  31. let name;
  32. let nameLowerCase;
  33. let prelude = null;
  34. let block = null;
  35. this.eat(AtKeyword);
  36. name = this.substrToCursor(start + 1);
  37. nameLowerCase = name.toLowerCase();
  38. this.skipSC();
  39. // parse prelude
  40. if (this.eof === false &&
  41. this.tokenType !== LeftCurlyBracket &&
  42. this.tokenType !== Semicolon) {
  43. if (this.parseAtrulePrelude) {
  44. prelude = this.parseWithFallback(this.AtrulePrelude.bind(this, name, isDeclaration), consumeRaw);
  45. } else {
  46. prelude = consumeRaw.call(this, this.tokenIndex);
  47. }
  48. this.skipSC();
  49. }
  50. switch (this.tokenType) {
  51. case Semicolon:
  52. this.next();
  53. break;
  54. case LeftCurlyBracket:
  55. if (hasOwnProperty.call(this.atrule, nameLowerCase) &&
  56. typeof this.atrule[nameLowerCase].block === 'function') {
  57. block = this.atrule[nameLowerCase].block.call(this, isDeclaration);
  58. } else {
  59. // TODO: should consume block content as Raw?
  60. block = this.Block(isDeclarationBlockAtrule.call(this));
  61. }
  62. break;
  63. }
  64. return {
  65. type: 'Atrule',
  66. loc: this.getLocation(start, this.tokenStart),
  67. name,
  68. prelude,
  69. block
  70. };
  71. }
  72. export function generate(node) {
  73. this.token(AtKeyword, '@' + node.name);
  74. if (node.prelude !== null) {
  75. this.node(node.prelude);
  76. }
  77. if (node.block) {
  78. this.node(node.block);
  79. } else {
  80. this.token(Semicolon, ';');
  81. }
  82. }