Atrule.cjs 2.5 KB

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