|
|
var isDigit = require('../tokenizer').isDigit; var cmpChar = require('../tokenizer').cmpChar; var TYPE = require('../tokenizer').TYPE;
var DELIM = TYPE.Delim; var WHITESPACE = TYPE.WhiteSpace; var COMMENT = TYPE.Comment; var IDENT = TYPE.Ident; var NUMBER = TYPE.Number; var DIMENSION = TYPE.Dimension; var PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
var HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
var N = 0x006E; // U+006E LATIN SMALL LETTER N (n)
var DISALLOW_SIGN = true; var ALLOW_SIGN = false;
function isDelim(token, code) { return token !== null && token.type === DELIM && token.value.charCodeAt(0) === code; }
function skipSC(token, offset, getNextToken) { while (token !== null && (token.type === WHITESPACE || token.type === COMMENT)) { token = getNextToken(++offset); }
return offset; }
function checkInteger(token, valueOffset, disallowSign, offset) { if (!token) { return 0; }
var code = token.value.charCodeAt(valueOffset);
if (code === PLUSSIGN || code === HYPHENMINUS) { if (disallowSign) { // Number sign is not allowed
return 0; } valueOffset++; }
for (; valueOffset < token.value.length; valueOffset++) { if (!isDigit(token.value.charCodeAt(valueOffset))) { // Integer is expected
return 0; } }
return offset + 1; }
// ... <signed-integer>
// ... ['+' | '-'] <signless-integer>
function consumeB(token, offset_, getNextToken) { var sign = false; var offset = skipSC(token, offset_, getNextToken);
token = getNextToken(offset);
if (token === null) { return offset_; }
if (token.type !== NUMBER) { if (isDelim(token, PLUSSIGN) || isDelim(token, HYPHENMINUS)) { sign = true; offset = skipSC(getNextToken(++offset), offset, getNextToken); token = getNextToken(offset);
if (token === null && token.type !== NUMBER) { return 0; } } else { return offset_; } }
if (!sign) { var code = token.value.charCodeAt(0); if (code !== PLUSSIGN && code !== HYPHENMINUS) { // Number sign is expected
return 0; } }
return checkInteger(token, sign ? 0 : 1, sign, offset); }
// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
module.exports = function anPlusB(token, getNextToken) { /* eslint-disable brace-style*/ var offset = 0;
if (!token) { return 0; }
// <integer>
if (token.type === NUMBER) { return checkInteger(token, 0, ALLOW_SIGN, offset); // b
}
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
// -n- <signless-integer>
// <dashndashdigit-ident>
else if (token.type === IDENT && token.value.charCodeAt(0) === HYPHENMINUS) { // expect 1st char is N
if (!cmpChar(token.value, 1, N)) { return 0; }
switch (token.value.length) { // -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
case 2: return consumeB(getNextToken(++offset), offset, getNextToken);
// -n- <signless-integer>
case 3: if (token.value.charCodeAt(2) !== HYPHENMINUS) { return 0; }
offset = skipSC(getNextToken(++offset), offset, getNextToken); token = getNextToken(offset);
return checkInteger(token, 0, DISALLOW_SIGN, offset);
// <dashndashdigit-ident>
default: if (token.value.charCodeAt(2) !== HYPHENMINUS) { return 0; }
return checkInteger(token, 3, DISALLOW_SIGN, offset); } }
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
// '+'? n- <signless-integer>
// '+'? <ndashdigit-ident>
else if (token.type === IDENT || (isDelim(token, PLUSSIGN) && getNextToken(offset + 1).type === IDENT)) { // just ignore a plus
if (token.type !== IDENT) { token = getNextToken(++offset); }
if (token === null || !cmpChar(token.value, 0, N)) { return 0; }
switch (token.value.length) { // '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
case 1: return consumeB(getNextToken(++offset), offset, getNextToken);
// '+'? n- <signless-integer>
case 2: if (token.value.charCodeAt(1) !== HYPHENMINUS) { return 0; }
offset = skipSC(getNextToken(++offset), offset, getNextToken); token = getNextToken(offset);
return checkInteger(token, 0, DISALLOW_SIGN, offset);
// '+'? <ndashdigit-ident>
default: if (token.value.charCodeAt(1) !== HYPHENMINUS) { return 0; }
return checkInteger(token, 2, DISALLOW_SIGN, offset); } }
// <ndashdigit-dimension>
// <ndash-dimension> <signless-integer>
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
else if (token.type === DIMENSION) { var code = token.value.charCodeAt(0); var sign = code === PLUSSIGN || code === HYPHENMINUS ? 1 : 0;
for (var i = sign; i < token.value.length; i++) { if (!isDigit(token.value.charCodeAt(i))) { break; } }
if (i === sign) { // Integer is expected
return 0; }
if (!cmpChar(token.value, i, N)) { return 0; }
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
if (i + 1 === token.value.length) { return consumeB(getNextToken(++offset), offset, getNextToken); } else { if (token.value.charCodeAt(i + 1) !== HYPHENMINUS) { return 0; }
// <ndash-dimension> <signless-integer>
if (i + 2 === token.value.length) { offset = skipSC(getNextToken(++offset), offset, getNextToken); token = getNextToken(offset);
return checkInteger(token, 0, DISALLOW_SIGN, offset); } // <ndashdigit-dimension>
else { return checkInteger(token, i + 2, DISALLOW_SIGN, offset); } } }
return 0; };
|