StyleSheet.js 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import {
  2. WhiteSpace,
  3. Comment,
  4. AtKeyword,
  5. CDO,
  6. CDC
  7. } from '../../tokenizer/index.js';
  8. const EXCLAMATIONMARK = 0x0021; // U+0021 EXCLAMATION MARK (!)
  9. function consumeRaw() {
  10. return this.Raw(null, false);
  11. }
  12. export const name = 'StyleSheet';
  13. export const walkContext = 'stylesheet';
  14. export const structure = {
  15. children: [[
  16. 'Comment',
  17. 'CDO',
  18. 'CDC',
  19. 'Atrule',
  20. 'Rule',
  21. 'Raw'
  22. ]]
  23. };
  24. export function parse() {
  25. const start = this.tokenStart;
  26. const children = this.createList();
  27. let child;
  28. scan:
  29. while (!this.eof) {
  30. switch (this.tokenType) {
  31. case WhiteSpace:
  32. this.next();
  33. continue;
  34. case Comment:
  35. // ignore comments except exclamation comments (i.e. /*! .. */) on top level
  36. if (this.charCodeAt(this.tokenStart + 2) !== EXCLAMATIONMARK) {
  37. this.next();
  38. continue;
  39. }
  40. child = this.Comment();
  41. break;
  42. case CDO: // <!--
  43. child = this.CDO();
  44. break;
  45. case CDC: // -->
  46. child = this.CDC();
  47. break;
  48. // CSS Syntax Module Level 3
  49. // §2.2 Error handling
  50. // At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule.
  51. case AtKeyword:
  52. child = this.parseWithFallback(this.Atrule, consumeRaw);
  53. break;
  54. // Anything else starts a qualified rule ...
  55. default:
  56. child = this.parseWithFallback(this.Rule, consumeRaw);
  57. }
  58. children.push(child);
  59. }
  60. return {
  61. type: 'StyleSheet',
  62. loc: this.getLocation(start, this.tokenStart),
  63. children
  64. };
  65. }
  66. export function generate(node) {
  67. this.children(node);
  68. }