Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@emmetio/css-abbreviation

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@emmetio/css-abbreviation - npm Package Compare versions

Comparing version 0.2.2 to 0.3.0

533

dist/css-abbreviation.cjs.js

@@ -7,2 +7,3 @@ 'use strict';

var StreamReader = _interopDefault(require('@emmetio/stream-reader'));
var _emmetio_streamReaderUtils = require('@emmetio/stream-reader-utils');

@@ -13,96 +14,24 @@ /**

class CSSValue {
constructor() {
this.type = 'css-value';
this.value = [];
}
constructor() {
this.type = 'css-value';
this.value = [];
}
get size() {
return this.value.length;
}
get size() {
return this.value.length;
}
add(value) {
this.value.push(value);
}
add(value) {
this.value.push(value);
}
has(value) {
return this.value.indexOf(value) !== -1;
}
has(value) {
return this.value.indexOf(value) !== -1;
}
toString() {
return this.value.join(' ');
}
toString() {
return this.value.join(' ');
}
}
/**
* Consumes characters in given string while they pass `test` code test
* @param {StreamReader} stream
* @param {Function} test
* @return {Boolean} Returns `true` stream was consumed at least once
*/
function eatWhile(stream, test) {
const start = stream.pos;
while (!stream.eol() && test(stream.peekCode())) {
stream.pos++;
}
return start < stream.pos;
}
/**
* Eats alpha word in given stream
* @param {StreamReader} stream
* @return {Boolean} Returns `true` if word was consumed
*/
function eatAlphaWord(stream) {
return eatWhile(stream, isAlphaWord);
}
/**
* Eats alpha word in given stream
* @param {StreamReader} stream
* @return {Boolean} Returns `true` if word was consumed
*/
function eatAlphaNumericWord(stream) {
return eatWhile(stream, isAlphaNumericWord);
}
/**
* @param {Number} code
* @return {Boolean}
*/
function isAlphaNumericWord(code) {
return isNumber(code) || isAlphaWord(code);
}
/**
* @param {Number} code
* @return {Boolean}
*/
function isAlphaWord(code) {
return code === 95 /* _ */ || isAlpha(code);
}
/**
* Check if given code is a number
* @param {Number} code
* @return {Boolean}
*/
function isNumber(code) {
return code > 47 && code < 58;
}
/**
* Check if given character code is alpha code (letter though A to Z)
* @param {Number} code
* @param {Number} [from]
* @param {Number} [to]
* @return {Boolean}
*/
function isAlpha(code, from, to) {
from = from || 65; // A
to = to || 90; // Z
code &= ~32; // quick hack to convert any char code to uppercase char code
return code >= from && code <= to; // A-F
}
const HASH = 35; // #

@@ -117,96 +46,98 @@ const DOT = 46; // .

var consumeColor = function(stream) {
// supported color variations:
// #abc → #aabbccc
// #0 → #000000
// #fff.5 → rgba(255, 255, 255, 0.5)
// #t → transparent
if (stream.peekCode() === HASH) {
stream.start = stream.pos++;
stream.eat(116) /* t */ || eatWhile(stream, isHex);
const base = stream.current();
// supported color variations:
// #abc → #aabbccc
// #0 → #000000
// #fff.5 → rgba(255, 255, 255, 0.5)
// #t → transparent
if (stream.peek() === HASH) {
stream.start = stream.pos;
stream.next();
// a hex color can be followed by `.num` alpha value
stream.start = stream.pos;
if (stream.eat(DOT) && !eatWhile(stream, isNumber)) {
throw stream.error('Unexpected character for alpha value of color');
}
stream.eat(116) /* t */ || stream.eatWhile(isHex);
const base = stream.current();
return new Color(base, stream.current());
}
// a hex color can be followed by `.num` alpha value
stream.start = stream.pos;
if (stream.eat(DOT) && !stream.eatWhile(_emmetio_streamReaderUtils.isNumber)) {
throw stream.error('Unexpected character for alpha value of color');
}
return new Color(base, stream.current());
}
};
class Color {
constructor(value, alpha) {
this.type = 'color';
this.raw = value;
this.alpha = Number(alpha != null && alpha !== '' ? alpha : 1);
value = value.slice(1); // remove #
constructor(value, alpha) {
this.type = 'color';
this.raw = value;
this.alpha = Number(alpha != null && alpha !== '' ? alpha : 1);
value = value.slice(1); // remove #
let r = 0, g = 0, b = 0;
let r = 0, g = 0, b = 0;
if (value === 't') {
this.alpha = 0;
} else {
switch (value.length) {
case 0:
break;
if (value === 't') {
this.alpha = 0;
} else {
switch (value.length) {
case 0:
break;
case 1:
r = g = b = value + value;
break;
case 1:
r = g = b = value + value;
break;
case 2:
r = g = b = value;
break;
case 2:
r = g = b = value;
break;
case 3:
r = value[0] + value[0];
g = value[1] + value[1];
b = value[2] + value[2];
break;
case 3:
r = value[0] + value[0];
g = value[1] + value[1];
b = value[2] + value[2];
break;
default:
value += value;
r = value.slice(0, 2);
g = value.slice(2, 4);
b = value.slice(4, 6);
}
}
default:
value += value;
r = value.slice(0, 2);
g = value.slice(2, 4);
b = value.slice(4, 6);
}
}
this.r = parseInt(r, 16);
this.g = parseInt(g, 16);
this.b = parseInt(b, 16);
}
this.r = parseInt(r, 16);
this.g = parseInt(g, 16);
this.b = parseInt(b, 16);
}
/**
* Output current color as hex value
* @param {Boolean} shor Produce short value (e.g. #fff instead of #ffffff), if possible
* @return {String}
*/
toHex(short) {
const fn = (short && isShortHex(this.r) && isShortHex(this.g) && isShortHex(this.b))
? toShortHex : toHex;
/**
* Output current color as hex value
* @param {Boolean} shor Produce short value (e.g. #fff instead of #ffffff), if possible
* @return {String}
*/
toHex(short) {
const fn = (short && isShortHex(this.r) && isShortHex(this.g) && isShortHex(this.b))
? toShortHex : toHex;
return '#' + fn(this.r) + fn(this.g) + fn(this.b);
}
return '#' + fn(this.r) + fn(this.g) + fn(this.b);
}
/**
* Output current color as `rgba?(...)` CSS color
* @return {String}
*/
toRGB() {
const values = [this.r, this.g, this.b];
if (this.alpha !== 1) {
values.push(this.alpha.toFixed(8).replace(/\.?0+$/, ''));
}
/**
* Output current color as `rgba?(...)` CSS color
* @return {String}
*/
toRGB() {
const values = [this.r, this.g, this.b];
if (this.alpha !== 1) {
values.push(this.alpha.toFixed(8).replace(/\.?0+$/, ''));
}
return `${values.length === 3 ? 'rgb' : 'rgba'}(${values.join(', ')})`;
}
return `${values.length === 3 ? 'rgb' : 'rgba'}(${values.join(', ')})`;
}
toString(short) {
if (!this.r && !this.g && !this.b && !this.alpha) {
return 'transparent';
}
return this.alpha === 1 ? this.toHex(short) : this.toRGB();
}
toString(short) {
if (!this.r && !this.g && !this.b && !this.alpha) {
return 'transparent';
}
return this.alpha === 1 ? this.toHex(short) : this.toRGB();
}
}

@@ -220,24 +151,40 @@

function isHex(code) {
return isNumber(code) || isAlpha(code, 65, 70); // A-F
return _emmetio_streamReaderUtils.isNumber(code) || _emmetio_streamReaderUtils.isAlpha(code, 65, 70); // A-F
}
function isShortHex(hex) {
return !(hex % 17);
return !(hex % 17);
}
function toShortHex(num) {
return (num >> 4).toString(16);
return (num >> 4).toString(16);
}
function toHex(num) {
return pad(num.toString(16), 2);
return pad(num.toString(16), 2);
}
function pad(value, len) {
while (value.length < len) {
value = '0' + value;
}
return value;
while (value.length < len) {
value = '0' + value;
}
return value;
}
/**
* @param {Number} code
* @return {Boolean}
*/
function isAlphaNumericWord(code) {
return _emmetio_streamReaderUtils.isNumber(code) || isAlphaWord(code);
}
/**
* @param {Number} code
* @return {Boolean}
*/
function isAlphaWord(code) {
return code === 95 /* _ */ || _emmetio_streamReaderUtils.isAlpha(code);
}
const PERCENT = 37; // %

@@ -254,11 +201,11 @@ const DOT$1 = 46; // .

var consumeNumericValue = function(stream) {
stream.start = stream.pos;
if (eatNumber(stream)) {
const num = stream.current();
stream.start = stream.pos;
stream.start = stream.pos;
if (eatNumber(stream)) {
const num = stream.current();
stream.start = stream.pos;
// eat unit, which can be a % or alpha word
stream.eat(PERCENT) || eatAlphaWord(stream);
return new NumericValue(num, stream.current());
}
// eat unit, which can be a % or alpha word
stream.eat(PERCENT) || stream.eatWhile(isAlphaWord);
return new NumericValue(num, stream.current());
}
};

@@ -270,11 +217,11 @@

class NumericValue {
constructor(value, unit) {
this.type = 'numeric';
this.value = Number(value);
this.unit = unit || '';
}
constructor(value, unit) {
this.type = 'numeric';
this.value = Number(value);
this.unit = unit || '';
}
toString() {
return `${this.value}${this.unit}`;
}
toString() {
return `${this.value}${this.unit}`;
}
}

@@ -289,26 +236,28 @@

const start = stream.pos;
const negative = stream.eat(DASH$1);
let hadDot = false, code;
const negative = stream.eat(DASH$1);
let hadDot = false, consumed = false, code;
while (!stream.eol()) {
code = stream.peekCode();
while (!stream.eof()) {
code = stream.peek();
// either a second dot or not a number: stop parsing
if (code === DOT$1 ? hadDot : !isNumber(code)) {
// either a second dot or not a number: stop parsing
if (code === DOT$1 ? hadDot : !_emmetio_streamReaderUtils.isNumber(code)) {
break;
}
if (code === DOT$1) {
hadDot = true;
}
consumed = true;
stream.pos++;
if (code === DOT$1) {
hadDot = true;
}
stream.next();
}
if (negative && stream.pos - start === 1) {
// edge case: consumed dash only, bail out
stream.pos = start;
}
if (negative && !consumed) {
// edge case: consumed dash only, bail out
stream.pos = start;
}
return start < stream.pos;
return start !== stream.pos;
}

@@ -331,14 +280,14 @@

var consumeKeyword = function(stream, short) {
stream.start = stream.pos;
stream.start = stream.pos;
if (stream.eat(DOLLAR$1) || stream.eat(AT$1)) {
// SCSS or LESS variable
eatAlphaNumericWord(stream);
} else if (short) {
eatAlphaWord(stream);
} else {
eatKeyword(stream);
if (stream.eat(DOLLAR$1) || stream.eat(AT$1)) {
// SCSS or LESS variable
stream.eatWhile(isAlphaNumericWord);
} else if (short) {
stream.eatWhile(isAlphaWord);
} else {
stream.eatWhile(isKeyword);
}
return stream.start !== stream.pos ? new Keyword(stream.current()) : null;
return stream.start !== stream.pos ? new Keyword(stream.current()) : null;
};

@@ -357,6 +306,2 @@

function eatKeyword(stream) {
return eatWhile(stream, isKeyword);
}
function isKeyword(code) {

@@ -366,4 +311,3 @@ return isAlphaNumericWord(code) || code === DASH$2;

const SINGLE_QUOTE = 39; // '
const DOUBLE_QUOTE = 34; // "
const opt = { throws: true };

@@ -376,7 +320,3 @@ /**

var consumeQuoted = function(stream) {
const code = stream.peekCode();
if (code === SINGLE_QUOTE || code === DOUBLE_QUOTE) {
stream.start = stream.pos++;
stream.eatQuoted(code);
if (_emmetio_streamReaderUtils.eatQuoted(stream, opt)) {
return new QuotedString(stream.current());

@@ -397,4 +337,2 @@ }

const TAB = 9; // \t
const SPACE = 32; // (
const LBRACE = 40; // (

@@ -412,11 +350,11 @@ const RBRACE = 41; // )

function consumeArgumentList(stream) {
if (!stream.eat(LBRACE)) {
// not an argument list
return null;
}
if (!stream.eat(LBRACE)) {
// not an argument list
return null;
}
let level = 1, code, arg;
const argsList = [];
let level = 1, code, arg;
const argsList = [];
while (!stream.eol()) {
while (!stream.eof()) {
if (arg = consumeArgument(stream)) {

@@ -426,3 +364,3 @@ argsList.push(arg);

// didn’t consumed argument, expect argument separator or end-of-arguments
eatSpace(stream);
stream.eatWhile(_emmetio_streamReaderUtils.isWhiteSpace);

@@ -438,5 +376,5 @@ if (stream.eat(RBRACE)) {

}
}
}
return argsList;
return argsList;
}

@@ -454,4 +392,4 @@

while (!stream.eol()) {
eatSpace(stream);
while (!stream.eof()) {
stream.eatWhile(_emmetio_streamReaderUtils.isWhiteSpace);
value = consumeNumericValue(stream) || consumeColor(stream)

@@ -499,19 +437,2 @@ || consumeQuoted(stream) || consumeKeywordOrFunction(stream);

/**
* Check if given character code is a white-space code
* @param {Number} code
* @return {Boolean}
*/
function isWhite(code) {
return code === SPACE || code === TAB;
}
/**
* @param {StreamReader} stream
* @return {Boolean} Returns `true` if space was consumed
*/
function eatSpace(stream) {
return eatWhile(stream, isWhite);
}
const EXCL = 33; // !

@@ -529,38 +450,38 @@ const DOLLAR = 36; // $

var index = function(abbr) {
const root = new Node();
const stream = new StreamReader(abbr);
let node;
const root = new Node();
const stream = new StreamReader(abbr);
let node;
while (!stream.eol()) {
let node = new Node(consumeIdent(stream));
node.value = consumeValue(stream);
while (!stream.eof()) {
let node = new Node(consumeIdent(stream));
node.value = consumeValue(stream);
const args = consumeArgumentList(stream);
if (args) {
// technically, arguments in CSS are anonymous Emmet Node attributes,
// but since Emmet can support only one anonymous, `null`-name
// attribute (for good reasons), we’ll use argument index as name
for (let i = 0; i < args.length; i++) {
node.setAttribute(String(i), args[i]);
}
}
const args = consumeArgumentList(stream);
if (args) {
// technically, arguments in CSS are anonymous Emmet Node attributes,
// but since Emmet can support only one anonymous, `null`-name
// attribute (for good reasons), we’ll use argument index as name
for (let i = 0; i < args.length; i++) {
node.setAttribute(String(i), args[i]);
}
}
// Consume `!important` modifier at the end of expression
if (stream.eat(EXCL)) {
node.value.add('!');
}
// Consume `!important` modifier at the end of expression
if (stream.eat(EXCL)) {
node.value.add('!');
}
root.appendChild(node);
root.appendChild(node);
// CSS abbreviations cannot be nested, only listed
if (!stream.eat(PLUS)) {
break;
}
}
// CSS abbreviations cannot be nested, only listed
if (!stream.eat(PLUS)) {
break;
}
}
if (!stream.eol()) {
throw stream.error('Unexpected character');
}
if (!stream.eof()) {
throw stream.error('Unexpected character');
}
return root;
return root;
};

@@ -574,6 +495,6 @@

function consumeIdent(stream) {
stream.start = stream.pos;
eatWhile(stream, isIdentPrefix);
eatWhile(stream, isIdent);
return stream.start !== stream.pos ? stream.current() : null;
stream.start = stream.pos;
stream.eatWhile(isIdentPrefix);
stream.eatWhile(isIdent);
return stream.start !== stream.pos ? stream.current() : null;
}

@@ -587,25 +508,25 @@

function consumeValue(stream) {
const values = new CSSValue();
let value;
const values = new CSSValue();
let value;
while (!stream.eol()) {
if (value = consumeNumericValue(stream) || consumeColor(stream)) {
// edge case: a dash after unit-less numeric value or color should
// be treated as value separator, not negative sign
if (!value.unit) {
stream.eat(DASH);
}
} else {
stream.eat(DASH);
value = consumeKeyword(stream, true);
}
while (!stream.eof()) {
if (value = consumeNumericValue(stream) || consumeColor(stream)) {
// edge case: a dash after unit-less numeric value or color should
// be treated as value separator, not negative sign
if (!value.unit) {
stream.eat(DASH);
}
} else {
stream.eat(DASH);
value = consumeKeyword(stream, true);
}
if (!value) {
if (!value) {
break;
}
}
values.add(value);
}
}
return values;
return values;
}

@@ -618,3 +539,3 @@

function isIdent(code) {
return isAlphaWord(code);
return isAlphaWord(code);
}

@@ -621,0 +542,0 @@

import Node from '@emmetio/node';
import StreamReader from '@emmetio/stream-reader';
import { eatQuoted, isAlpha, isNumber, isWhiteSpace } from '@emmetio/stream-reader-utils';

@@ -8,96 +9,24 @@ /**

class CSSValue {
constructor() {
this.type = 'css-value';
this.value = [];
}
constructor() {
this.type = 'css-value';
this.value = [];
}
get size() {
return this.value.length;
}
get size() {
return this.value.length;
}
add(value) {
this.value.push(value);
}
add(value) {
this.value.push(value);
}
has(value) {
return this.value.indexOf(value) !== -1;
}
has(value) {
return this.value.indexOf(value) !== -1;
}
toString() {
return this.value.join(' ');
}
toString() {
return this.value.join(' ');
}
}
/**
* Consumes characters in given string while they pass `test` code test
* @param {StreamReader} stream
* @param {Function} test
* @return {Boolean} Returns `true` stream was consumed at least once
*/
function eatWhile(stream, test) {
const start = stream.pos;
while (!stream.eol() && test(stream.peekCode())) {
stream.pos++;
}
return start < stream.pos;
}
/**
* Eats alpha word in given stream
* @param {StreamReader} stream
* @return {Boolean} Returns `true` if word was consumed
*/
function eatAlphaWord(stream) {
return eatWhile(stream, isAlphaWord);
}
/**
* Eats alpha word in given stream
* @param {StreamReader} stream
* @return {Boolean} Returns `true` if word was consumed
*/
function eatAlphaNumericWord(stream) {
return eatWhile(stream, isAlphaNumericWord);
}
/**
* @param {Number} code
* @return {Boolean}
*/
function isAlphaNumericWord(code) {
return isNumber(code) || isAlphaWord(code);
}
/**
* @param {Number} code
* @return {Boolean}
*/
function isAlphaWord(code) {
return code === 95 /* _ */ || isAlpha(code);
}
/**
* Check if given code is a number
* @param {Number} code
* @return {Boolean}
*/
function isNumber(code) {
return code > 47 && code < 58;
}
/**
* Check if given character code is alpha code (letter though A to Z)
* @param {Number} code
* @param {Number} [from]
* @param {Number} [to]
* @return {Boolean}
*/
function isAlpha(code, from, to) {
from = from || 65; // A
to = to || 90; // Z
code &= ~32; // quick hack to convert any char code to uppercase char code
return code >= from && code <= to; // A-F
}
const HASH = 35; // #

@@ -112,96 +41,98 @@ const DOT = 46; // .

var consumeColor = function(stream) {
// supported color variations:
// #abc → #aabbccc
// #0 → #000000
// #fff.5 → rgba(255, 255, 255, 0.5)
// #t → transparent
if (stream.peekCode() === HASH) {
stream.start = stream.pos++;
stream.eat(116) /* t */ || eatWhile(stream, isHex);
const base = stream.current();
// supported color variations:
// #abc → #aabbccc
// #0 → #000000
// #fff.5 → rgba(255, 255, 255, 0.5)
// #t → transparent
if (stream.peek() === HASH) {
stream.start = stream.pos;
stream.next();
// a hex color can be followed by `.num` alpha value
stream.start = stream.pos;
if (stream.eat(DOT) && !eatWhile(stream, isNumber)) {
throw stream.error('Unexpected character for alpha value of color');
}
stream.eat(116) /* t */ || stream.eatWhile(isHex);
const base = stream.current();
return new Color(base, stream.current());
}
// a hex color can be followed by `.num` alpha value
stream.start = stream.pos;
if (stream.eat(DOT) && !stream.eatWhile(isNumber)) {
throw stream.error('Unexpected character for alpha value of color');
}
return new Color(base, stream.current());
}
};
class Color {
constructor(value, alpha) {
this.type = 'color';
this.raw = value;
this.alpha = Number(alpha != null && alpha !== '' ? alpha : 1);
value = value.slice(1); // remove #
constructor(value, alpha) {
this.type = 'color';
this.raw = value;
this.alpha = Number(alpha != null && alpha !== '' ? alpha : 1);
value = value.slice(1); // remove #
let r = 0, g = 0, b = 0;
let r = 0, g = 0, b = 0;
if (value === 't') {
this.alpha = 0;
} else {
switch (value.length) {
case 0:
break;
if (value === 't') {
this.alpha = 0;
} else {
switch (value.length) {
case 0:
break;
case 1:
r = g = b = value + value;
break;
case 1:
r = g = b = value + value;
break;
case 2:
r = g = b = value;
break;
case 2:
r = g = b = value;
break;
case 3:
r = value[0] + value[0];
g = value[1] + value[1];
b = value[2] + value[2];
break;
case 3:
r = value[0] + value[0];
g = value[1] + value[1];
b = value[2] + value[2];
break;
default:
value += value;
r = value.slice(0, 2);
g = value.slice(2, 4);
b = value.slice(4, 6);
}
}
default:
value += value;
r = value.slice(0, 2);
g = value.slice(2, 4);
b = value.slice(4, 6);
}
}
this.r = parseInt(r, 16);
this.g = parseInt(g, 16);
this.b = parseInt(b, 16);
}
this.r = parseInt(r, 16);
this.g = parseInt(g, 16);
this.b = parseInt(b, 16);
}
/**
* Output current color as hex value
* @param {Boolean} shor Produce short value (e.g. #fff instead of #ffffff), if possible
* @return {String}
*/
toHex(short) {
const fn = (short && isShortHex(this.r) && isShortHex(this.g) && isShortHex(this.b))
? toShortHex : toHex;
/**
* Output current color as hex value
* @param {Boolean} shor Produce short value (e.g. #fff instead of #ffffff), if possible
* @return {String}
*/
toHex(short) {
const fn = (short && isShortHex(this.r) && isShortHex(this.g) && isShortHex(this.b))
? toShortHex : toHex;
return '#' + fn(this.r) + fn(this.g) + fn(this.b);
}
return '#' + fn(this.r) + fn(this.g) + fn(this.b);
}
/**
* Output current color as `rgba?(...)` CSS color
* @return {String}
*/
toRGB() {
const values = [this.r, this.g, this.b];
if (this.alpha !== 1) {
values.push(this.alpha.toFixed(8).replace(/\.?0+$/, ''));
}
/**
* Output current color as `rgba?(...)` CSS color
* @return {String}
*/
toRGB() {
const values = [this.r, this.g, this.b];
if (this.alpha !== 1) {
values.push(this.alpha.toFixed(8).replace(/\.?0+$/, ''));
}
return `${values.length === 3 ? 'rgb' : 'rgba'}(${values.join(', ')})`;
}
return `${values.length === 3 ? 'rgb' : 'rgba'}(${values.join(', ')})`;
}
toString(short) {
if (!this.r && !this.g && !this.b && !this.alpha) {
return 'transparent';
}
return this.alpha === 1 ? this.toHex(short) : this.toRGB();
}
toString(short) {
if (!this.r && !this.g && !this.b && !this.alpha) {
return 'transparent';
}
return this.alpha === 1 ? this.toHex(short) : this.toRGB();
}
}

@@ -215,24 +146,40 @@

function isHex(code) {
return isNumber(code) || isAlpha(code, 65, 70); // A-F
return isNumber(code) || isAlpha(code, 65, 70); // A-F
}
function isShortHex(hex) {
return !(hex % 17);
return !(hex % 17);
}
function toShortHex(num) {
return (num >> 4).toString(16);
return (num >> 4).toString(16);
}
function toHex(num) {
return pad(num.toString(16), 2);
return pad(num.toString(16), 2);
}
function pad(value, len) {
while (value.length < len) {
value = '0' + value;
}
return value;
while (value.length < len) {
value = '0' + value;
}
return value;
}
/**
* @param {Number} code
* @return {Boolean}
*/
function isAlphaNumericWord(code) {
return isNumber(code) || isAlphaWord(code);
}
/**
* @param {Number} code
* @return {Boolean}
*/
function isAlphaWord(code) {
return code === 95 /* _ */ || isAlpha(code);
}
const PERCENT = 37; // %

@@ -249,11 +196,11 @@ const DOT$1 = 46; // .

var consumeNumericValue = function(stream) {
stream.start = stream.pos;
if (eatNumber(stream)) {
const num = stream.current();
stream.start = stream.pos;
stream.start = stream.pos;
if (eatNumber(stream)) {
const num = stream.current();
stream.start = stream.pos;
// eat unit, which can be a % or alpha word
stream.eat(PERCENT) || eatAlphaWord(stream);
return new NumericValue(num, stream.current());
}
// eat unit, which can be a % or alpha word
stream.eat(PERCENT) || stream.eatWhile(isAlphaWord);
return new NumericValue(num, stream.current());
}
};

@@ -265,11 +212,11 @@

class NumericValue {
constructor(value, unit) {
this.type = 'numeric';
this.value = Number(value);
this.unit = unit || '';
}
constructor(value, unit) {
this.type = 'numeric';
this.value = Number(value);
this.unit = unit || '';
}
toString() {
return `${this.value}${this.unit}`;
}
toString() {
return `${this.value}${this.unit}`;
}
}

@@ -284,9 +231,9 @@

const start = stream.pos;
const negative = stream.eat(DASH$1);
let hadDot = false, code;
const negative = stream.eat(DASH$1);
let hadDot = false, consumed = false, code;
while (!stream.eol()) {
code = stream.peekCode();
while (!stream.eof()) {
code = stream.peek();
// either a second dot or not a number: stop parsing
// either a second dot or not a number: stop parsing
if (code === DOT$1 ? hadDot : !isNumber(code)) {

@@ -296,15 +243,17 @@ break;

if (code === DOT$1) {
hadDot = true;
}
consumed = true;
stream.pos++;
if (code === DOT$1) {
hadDot = true;
}
stream.next();
}
if (negative && stream.pos - start === 1) {
// edge case: consumed dash only, bail out
stream.pos = start;
}
if (negative && !consumed) {
// edge case: consumed dash only, bail out
stream.pos = start;
}
return start < stream.pos;
return start !== stream.pos;
}

@@ -327,14 +276,14 @@

var consumeKeyword = function(stream, short) {
stream.start = stream.pos;
stream.start = stream.pos;
if (stream.eat(DOLLAR$1) || stream.eat(AT$1)) {
// SCSS or LESS variable
eatAlphaNumericWord(stream);
} else if (short) {
eatAlphaWord(stream);
} else {
eatKeyword(stream);
if (stream.eat(DOLLAR$1) || stream.eat(AT$1)) {
// SCSS or LESS variable
stream.eatWhile(isAlphaNumericWord);
} else if (short) {
stream.eatWhile(isAlphaWord);
} else {
stream.eatWhile(isKeyword);
}
return stream.start !== stream.pos ? new Keyword(stream.current()) : null;
return stream.start !== stream.pos ? new Keyword(stream.current()) : null;
};

@@ -353,6 +302,2 @@

function eatKeyword(stream) {
return eatWhile(stream, isKeyword);
}
function isKeyword(code) {

@@ -362,4 +307,3 @@ return isAlphaNumericWord(code) || code === DASH$2;

const SINGLE_QUOTE = 39; // '
const DOUBLE_QUOTE = 34; // "
const opt = { throws: true };

@@ -372,7 +316,3 @@ /**

var consumeQuoted = function(stream) {
const code = stream.peekCode();
if (code === SINGLE_QUOTE || code === DOUBLE_QUOTE) {
stream.start = stream.pos++;
stream.eatQuoted(code);
if (eatQuoted(stream, opt)) {
return new QuotedString(stream.current());

@@ -393,4 +333,2 @@ }

const TAB = 9; // \t
const SPACE = 32; // (
const LBRACE = 40; // (

@@ -408,11 +346,11 @@ const RBRACE = 41; // )

function consumeArgumentList(stream) {
if (!stream.eat(LBRACE)) {
// not an argument list
return null;
}
if (!stream.eat(LBRACE)) {
// not an argument list
return null;
}
let level = 1, code, arg;
const argsList = [];
let level = 1, code, arg;
const argsList = [];
while (!stream.eol()) {
while (!stream.eof()) {
if (arg = consumeArgument(stream)) {

@@ -422,3 +360,3 @@ argsList.push(arg);

// didn’t consumed argument, expect argument separator or end-of-arguments
eatSpace(stream);
stream.eatWhile(isWhiteSpace);

@@ -434,5 +372,5 @@ if (stream.eat(RBRACE)) {

}
}
}
return argsList;
return argsList;
}

@@ -450,4 +388,4 @@

while (!stream.eol()) {
eatSpace(stream);
while (!stream.eof()) {
stream.eatWhile(isWhiteSpace);
value = consumeNumericValue(stream) || consumeColor(stream)

@@ -495,19 +433,2 @@ || consumeQuoted(stream) || consumeKeywordOrFunction(stream);

/**
* Check if given character code is a white-space code
* @param {Number} code
* @return {Boolean}
*/
function isWhite(code) {
return code === SPACE || code === TAB;
}
/**
* @param {StreamReader} stream
* @return {Boolean} Returns `true` if space was consumed
*/
function eatSpace(stream) {
return eatWhile(stream, isWhite);
}
const EXCL = 33; // !

@@ -525,38 +446,38 @@ const DOLLAR = 36; // $

var index = function(abbr) {
const root = new Node();
const stream = new StreamReader(abbr);
let node;
const root = new Node();
const stream = new StreamReader(abbr);
let node;
while (!stream.eol()) {
let node = new Node(consumeIdent(stream));
node.value = consumeValue(stream);
while (!stream.eof()) {
let node = new Node(consumeIdent(stream));
node.value = consumeValue(stream);
const args = consumeArgumentList(stream);
if (args) {
// technically, arguments in CSS are anonymous Emmet Node attributes,
// but since Emmet can support only one anonymous, `null`-name
// attribute (for good reasons), we’ll use argument index as name
for (let i = 0; i < args.length; i++) {
node.setAttribute(String(i), args[i]);
}
}
const args = consumeArgumentList(stream);
if (args) {
// technically, arguments in CSS are anonymous Emmet Node attributes,
// but since Emmet can support only one anonymous, `null`-name
// attribute (for good reasons), we’ll use argument index as name
for (let i = 0; i < args.length; i++) {
node.setAttribute(String(i), args[i]);
}
}
// Consume `!important` modifier at the end of expression
if (stream.eat(EXCL)) {
node.value.add('!');
}
// Consume `!important` modifier at the end of expression
if (stream.eat(EXCL)) {
node.value.add('!');
}
root.appendChild(node);
root.appendChild(node);
// CSS abbreviations cannot be nested, only listed
if (!stream.eat(PLUS)) {
break;
}
}
// CSS abbreviations cannot be nested, only listed
if (!stream.eat(PLUS)) {
break;
}
}
if (!stream.eol()) {
throw stream.error('Unexpected character');
}
if (!stream.eof()) {
throw stream.error('Unexpected character');
}
return root;
return root;
};

@@ -570,6 +491,6 @@

function consumeIdent(stream) {
stream.start = stream.pos;
eatWhile(stream, isIdentPrefix);
eatWhile(stream, isIdent);
return stream.start !== stream.pos ? stream.current() : null;
stream.start = stream.pos;
stream.eatWhile(isIdentPrefix);
stream.eatWhile(isIdent);
return stream.start !== stream.pos ? stream.current() : null;
}

@@ -583,25 +504,25 @@

function consumeValue(stream) {
const values = new CSSValue();
let value;
const values = new CSSValue();
let value;
while (!stream.eol()) {
if (value = consumeNumericValue(stream) || consumeColor(stream)) {
// edge case: a dash after unit-less numeric value or color should
// be treated as value separator, not negative sign
if (!value.unit) {
stream.eat(DASH);
}
} else {
stream.eat(DASH);
value = consumeKeyword(stream, true);
}
while (!stream.eof()) {
if (value = consumeNumericValue(stream) || consumeColor(stream)) {
// edge case: a dash after unit-less numeric value or color should
// be treated as value separator, not negative sign
if (!value.unit) {
stream.eat(DASH);
}
} else {
stream.eat(DASH);
value = consumeKeyword(stream, true);
}
if (!value) {
if (!value) {
break;
}
}
values.add(value);
}
}
return values;
return values;
}

@@ -614,3 +535,3 @@

function isIdent(code) {
return isAlphaWord(code);
return isAlphaWord(code);
}

@@ -617,0 +538,0 @@

{
"name": "@emmetio/css-abbreviation",
"version": "0.2.2",
"version": "0.3.0",
"description": "Parses Emmet CSS abbreviatoin into AST tree",

@@ -25,3 +25,4 @@ "main": "dist/css-abbreviation.cjs.js",

"@emmetio/node": "^0.1.0",
"@emmetio/stream-reader": "^1.0.0"
"@emmetio/stream-reader": "^2.0.0",
"@emmetio/stream-reader-utils": "^0.1.0"
},

@@ -28,0 +29,0 @@ "devDependencies": {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc