123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- var isHex = require('../../tokenizer').isHex;
- var TYPE = require('../../tokenizer').TYPE;
- var IDENTIFIER = TYPE.Identifier;
- var NUMBER = TYPE.Number;
- var PLUSSIGN = TYPE.PlusSign;
- var HYPHENMINUS = TYPE.HyphenMinus;
- var FULLSTOP = TYPE.FullStop;
- var QUESTIONMARK = TYPE.QuestionMark;
- function scanUnicodeNumber(scanner) {
- for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
- var code = scanner.source.charCodeAt(pos);
- // break on fullstop or hyperminus/plussign after exponent
- if (code === FULLSTOP || code === PLUSSIGN) {
- // break token, exclude symbol
- scanner.tokenStart = pos;
- return false;
- }
- }
- return true;
- }
- // https://drafts.csswg.org/css-syntax-3/#urange
- function scanUnicodeRange(scanner) {
- var hexStart = scanner.tokenStart + 1; // skip +
- var hexLength = 0;
- scan: {
- if (scanner.tokenType === NUMBER) {
- if (scanner.source.charCodeAt(scanner.tokenStart) !== FULLSTOP && scanUnicodeNumber(scanner)) {
- scanner.next();
- } else if (scanner.source.charCodeAt(scanner.tokenStart) !== HYPHENMINUS) {
- break scan;
- }
- } else {
- scanner.next(); // PLUSSIGN
- }
- if (scanner.tokenType === HYPHENMINUS) {
- scanner.next();
- }
- if (scanner.tokenType === NUMBER) {
- scanner.next();
- }
- if (scanner.tokenType === IDENTIFIER) {
- scanner.next();
- }
- if (scanner.tokenStart === hexStart) {
- scanner.error('Unexpected input', hexStart);
- }
- }
- // validate for U+x{1,6} or U+x{1,6}-x{1,6}
- // where x is [0-9a-fA-F]
- for (var i = hexStart, wasHyphenMinus = false; i < scanner.tokenStart; i++) {
- var code = scanner.source.charCodeAt(i);
- if (isHex(code) === false && (code !== HYPHENMINUS || wasHyphenMinus)) {
- scanner.error('Unexpected input', i);
- }
- if (code === HYPHENMINUS) {
- // hex sequence shouldn't be an empty
- if (hexLength === 0) {
- scanner.error('Unexpected input', i);
- }
- wasHyphenMinus = true;
- hexLength = 0;
- } else {
- hexLength++;
- // too long hex sequence
- if (hexLength > 6) {
- scanner.error('Too long hex sequence', i);
- }
- }
- }
- // check we have a non-zero sequence
- if (hexLength === 0) {
- scanner.error('Unexpected input', i - 1);
- }
- // U+abc???
- if (!wasHyphenMinus) {
- // consume as many U+003F QUESTION MARK (?) code points as possible
- for (; hexLength < 6 && !scanner.eof; scanner.next()) {
- if (scanner.tokenType !== QUESTIONMARK) {
- break;
- }
- hexLength++;
- }
- }
- }
- module.exports = {
- name: 'UnicodeRange',
- structure: {
- value: String
- },
- parse: function() {
- var start = this.scanner.tokenStart;
- this.scanner.next(); // U or u
- scanUnicodeRange(this.scanner);
- return {
- type: 'UnicodeRange',
- loc: this.getLocation(start, this.scanner.tokenStart),
- value: this.scanner.substrToCursor(start)
- };
- },
- generate: function(node) {
- this.chunk(node.value);
- }
- };
|