Ratio.js 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. var isDigit = require('../../tokenizer').isDigit;
  2. var TYPE = require('../../tokenizer').TYPE;
  3. var CHARCODE = require('../../tokenizer').CHARCODE;
  4. var NUMBER = TYPE.Number;
  5. var DELIM = TYPE.Delim;
  6. var SOLIDUS = CHARCODE.Solidus;
  7. var FULLSTOP = CHARCODE.FullStop;
  8. // Terms of <ratio> should be a positive numbers (not zero or negative)
  9. // (see https://drafts.csswg.org/mediaqueries-3/#values)
  10. // However, -o-min-device-pixel-ratio takes fractional values as a ratio's term
  11. // and this is using by various sites. Therefore we relax checking on parse
  12. // to test a term is unsigned number without an exponent part.
  13. // Additional checking may be applied on lexer validation.
  14. function consumeNumber() {
  15. this.scanner.skipWS();
  16. var value = this.consume(NUMBER);
  17. for (var i = 0; i < value.length; i++) {
  18. var code = value.charCodeAt(i);
  19. if (!isDigit(code) && code !== FULLSTOP) {
  20. this.error('Unsigned number is expected', this.scanner.tokenStart - value.length + i);
  21. }
  22. }
  23. if (Number(value) === 0) {
  24. this.error('Zero number is not allowed', this.scanner.tokenStart - value.length);
  25. }
  26. return value;
  27. }
  28. // <positive-integer> S* '/' S* <positive-integer>
  29. module.exports = {
  30. name: 'Ratio',
  31. structure: {
  32. left: String,
  33. right: String
  34. },
  35. parse: function() {
  36. var start = this.scanner.tokenStart;
  37. var left = consumeNumber.call(this);
  38. var right;
  39. this.scanner.skipWS();
  40. if (!this.scanner.isDelim(SOLIDUS)) {
  41. this.error('Solidus is expected');
  42. }
  43. this.eat(DELIM);
  44. right = consumeNumber.call(this);
  45. return {
  46. type: 'Ratio',
  47. loc: this.getLocation(start, this.scanner.tokenStart),
  48. left: left,
  49. right: right
  50. };
  51. },
  52. generate: function(node) {
  53. this.chunk(node.left);
  54. this.chunk('/');
  55. this.chunk(node.right);
  56. }
  57. };