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

tartan

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tartan - npm Package Compare versions

Comparing version 3.4.0 to 4.0.0

src/filter/classify.js

8

package.json
{
"name": "tartan",
"version": "3.4.0",
"description": "Library to render tartan pattern using its textual descriptor (threadcount).",
"version": "4.0.0",
"description": "This library allows to parse tartan threadcount.",
"keywords": [

@@ -30,7 +30,7 @@ "tartan",

"bugs": {
"url": "https://github.com/kravets-levko/tartan/issues"
"url": "https://github.com/thetartan/tartan/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/kravets-levko/tartan.git"
"url": "https://github.com/thetartan/tartan.git"
},

@@ -37,0 +37,0 @@ "dependencies": {

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

module.exports.weave = {
// Thread above warp, threads under warp
plain: [1, 1],

@@ -11,3 +12,3 @@ serge: [2, 2]

module.exports.colors = utils.normalizeColorMap({
module.exports.colors = utils.color.buildColorMap({
/* eslint-disable key-spacing */

@@ -20,5 +21,7 @@ B: '#304080', G: '#004c00', K: '#000000',

module.exports.warpAndWeftSeparator = '//';
module.exports.insignificantTokens = [
utils.TokenType.invalid,
utils.TokenType.whitespace
'invalid',
'whitespace'
];

@@ -20,5 +20,3 @@ 'use strict';

module.exports.matchSquareBrackets = require('./match-square-brackets');
module.exports.pivotsToSquareBrackets = require('./pivots-to-square-brackets');
module.exports.classify = require('./classify');
module.exports.removeTokens = require('./remove-tokens');
module.exports.removeZeroWidthStripes = require('./remove-zero-width-stripes');

@@ -7,11 +7,9 @@ 'use strict';

module.exports.defaults = require('./defaults');
module.exports.parse = require('./parse');
module.exports.filter = require('./filter');
module.exports.transform = require('./transform');
module.exports.syntax = require('./syntax');
module.exports.transform = require('./transform');
module.exports.render = require('./render');
module.exports.schema = require('./schema');
module.exports.utils = require('./utils');
module.exports.helpers = require('./helpers');
module.exports.defaults = require('./defaults');
'use strict';
var _ = require('lodash');
var lexer = require('./tokenize');
var tokenize = require('./tokenize');
var defaultOptions = {
// function to filter parsed tokens: (tokens) => { return modifiedTokens; }
filterTokens: null,
// Function to build AST: (tokens) => { return newAST; }
buildSyntaxTree: null
errorHandler: null,
processTokens: null,
buildSyntaxTree: null,
foreseeLimit: 1
};
function factory(parsers, options) {
var tokenize = lexer(parsers, options);
options = _.extend({}, defaultOptions, options);
return function(source) {
if (!_.isString(source)) {
return null;
var context = tokenize(source, parsers, options);
var result = context.parse();
if (_.isFunction(options.processTokens)) {
result = options.processTokens(result);
}
var result = tokenize(source);
if (_.isFunction(options.filterTokens)) {
result = options.filterTokens(result);
}
if (_.isFunction(options.buildSyntaxTree)) {

@@ -27,0 +23,0 @@ result = options.buildSyntaxTree(result);

@@ -9,37 +9,19 @@ 'use strict';

allowLongNames: true,
// Use '=' symbol between name and value: 'none', 'allow', 'require'
valueAssignment: 'allow',
// Use '#' as color prefix: 'none', 'allow', 'require'
colorPrefix: 'require',
// Regular expression or string; case-insensitive
colorPrefix: /[=]?[#]/,
// Regular expression or string; case-insensitive
colorSuffix: /;?/,
// Formats: `short` (#fc0), `long` (#ffcc00) or `both`
colorFormat: 'both',
// Comment after color value: 'none', 'allow', 'require'.
// If `comment` != 'none' and `whitespaceBeforeComment` != 'require',
// `colorFormat` is forced to `long`
comment: 'none',
// Whitespace between value and comment: 'none', 'allow', 'require'.
// Ignored if `comment` options has value 'none'
whitespaceBeforeComment: 'require',
// Semicolon at the end of color definition: 'none', 'allow', 'require'
semicolonAtTheEnd: 'allow'
allowComment: false,
// Regular expression or string; case-insensitive
commentSuffix: /;/,
requireCommentSuffix: true,
// Regular expression; value of first group will be used to modify
// comment (if available)
commentFormat: /^\s*(.*)\s*;\s*$/
};
function validateOptions(options) {
var keys = [
'valueAssignment',
'colorPrefix',
'comment',
'whitespaceBeforeComment',
'semicolonAtTheEnd'
];
var values = ['none', 'allow', 'require'];
_.each(keys, function(key) {
var value = utils.trim(('' + options[key]).toLowerCase());
if (values.indexOf(value) == -1) {
value = defaultOptions[key];
}
options[key] = value;
});
options.colorFormat = utils.trim(('' + options.colorFormat).toLowerCase());
options.colorFormat = _.trim(('' + options.colorFormat).toLowerCase());
if (['long', 'short', 'both'].indexOf(options.colorFormat) == -1) {

@@ -49,16 +31,28 @@ options.colorFormat = defaultOptions.colorFormat;

// If comment is allowed and may be not separated from color
// by a whitespace, require long color format - since it is the only
// 100% way to extract color value
if (options.comment != 'none') {
if (options.whitespaceBeforeComment != 'require') {
options.colorFormat = 'long';
}
if (options.colorPrefix instanceof RegExp) {
options.colorPrefix = options.colorPrefix.source;
} else
if (!_.isString(options.colorPrefix)) {
options.colorPrefix = '';
}
// If color prefix is 'none', require value assignment
if (options.colorPrefix == 'none') {
options.valueAssignment = 'require';
if (options.colorSuffix instanceof RegExp) {
options.colorSuffix = options.colorSuffix.source;
} else
if (!_.isString(options.colorSuffix)) {
options.colorSuffix = '';
}
if (options.commentSuffix instanceof RegExp) {
var flags = options.commentSuffix.ignoreCase ? 'i' : '';
options.commentSuffix = new RegExp(
'^' + options.commentSuffix.source, flags);
} else {
options.commentSuffix = null;
}
if (!(options.commentFormat instanceof RegExp)) {
options.commentFormat = null;
}
return options;

@@ -68,3 +62,2 @@ }

function buildRegExp(options) {
/* eslint-disable max-statements-per-line */
var result = ['^'];

@@ -79,16 +72,4 @@

// Value assignment
switch (options.valueAssignment) {
case 'allow': result.push('=?'); break;
case 'require': result.push('='); break;
default: break;
}
// Color format
switch (options.colorPrefix) {
case 'allow': result.push('#?'); break;
case 'require': result.push('#'); break;
default: break;
}
result.push('(' + options.colorPrefix + ')');
switch (options.colorFormat) {

@@ -107,53 +88,79 @@ case 'long':

}
result.push(options.colorSuffix);
// Comments
if (options.comment != 'none') {
switch (options.whitespaceBeforeComment) {
case 'allow': result.push('\\s?'); break;
case 'require': result.push('\\s'); break;
default: break;
}
part = '';
switch (options.semicolonAtTheEnd) {
case 'none': part = '[^\\s]'; break;
case 'allow': part = '[^;\\s]'; break;
case 'require': part = '[^;]'; break;
default: break;
}
switch (options.comment) {
case 'allow': result.push('(' + part + '*)'); break;
case 'require': result.push('(' + part + '+)'); break;
default: break;
}
}
// Semicolon at the end
switch (options.semicolonAtTheEnd) {
case 'none': break;
case 'allow': result.push(';?'); break;
case 'require': result.push(';'); break;
default: break;
}
return new RegExp(result.join(''), 'i');
/* eslint-enable max-statements-per-line */
}
function parser(str, offset, pattern) {
function parser(context, offset, pattern, options) {
var source = context.source;
var matches;
var chunk;
var i;
// Color definition can have at most 107 characters
str = str.substr(offset, 110);
chunk = source.substr(offset, 200);
matches = pattern.exec(str);
matches = pattern.exec(chunk);
if (matches) {
return {
type: utils.TokenType.color,
var result = {
type: utils.token.color,
name: matches[1].toUpperCase(),
color: utils.normalizeColor('#' + matches[2]),
comment: utils.trim(matches[3]),
// matches[2] is color prefix
color: utils.color.normalizeColor(matches[3]),
comment: '',
length: matches[0].length
};
if (!context.inForesee) {
if (options.allowComment) {
var commentOffset = offset + result.length;
if (options.commentSuffix && options.requireCommentSuffix) {
// Fast case - just search for suffix
for (i = commentOffset; i < source.length; i++) {
chunk = source.substr(i, 10);
matches = options.commentSuffix.exec(chunk);
if (matches) {
result.comment = source.substr(commentOffset,
i - commentOffset + matches[0].length);
break;
}
}
if (i >= source.length) {
result.comment = source.substr(commentOffset, source.length);
}
} else {
var ignoreTokens = ['whitespace', 'invalid'];
// Slow - search for next token or suffix (if available)
for (i = commentOffset; i < source.length; i++) {
chunk = source.substr(i, 10);
matches = options.commentSuffix.exec(chunk);
if (matches) {
result.comment = source.substr(commentOffset,
i - commentOffset + matches[0].length);
break;
}
var token = context.foresee(i);
if (_.isObject(token) && (ignoreTokens.indexOf(token.type) == -1)) {
result.comment = source.substr(commentOffset,
i - commentOffset);
break;
}
}
if (i >= source.length) {
result.comment = source.substr(commentOffset, source.length);
}
}
}
result.length += result.comment.length;
if (options.commentFormat) {
matches = options.commentFormat.exec(result.comment);
if (matches && _.isString(matches[1])) {
result.comment = matches[1];
}
}
result.comment = _.trim(result.comment);
}
return result;
}

@@ -165,4 +172,4 @@ }

var pattern = buildRegExp(options);
return function(str, offset) {
return parser(str, offset, pattern);
return function(context, offset) {
return parser(context, offset, pattern, options);
};

@@ -169,0 +176,0 @@ }

@@ -5,22 +5,41 @@ 'use strict';

var utils = require('../../utils');
var errors = require('../../errors');
var defaultOptions = {
allowInvalidTokens: false
};
function parse(context, offset) {
var source = context.source;
var result = source.charAt(offset);
function factory(options) {
options = _.extend({}, defaultOptions, options);
return function(str, offset) {
if (!options.allowInvalidTokens) {
throw new errors.InvalidToken(str, offset);
if (!context.inForesee) {
var foreseeOffset = offset + 1;
while (true) {
var token = context.foresee(foreseeOffset);
if (_.isObject(token) && (token.type == 'invalid')) {
result += token.value;
foreseeOffset += token.length;
continue;
}
break;
}
return {
type: utils.TokenType.invalid,
value: str.charAt(offset),
length: 1
}
if (result != '') {
result = {
type: utils.token.invalid,
value: result,
length: result.length
};
};
if (!context.inForesee) {
context.errorHandler(
new Error(utils.error.message.invalidToken),
{token: result},
utils.error.severity.error
);
}
return result;
}
}
function factory() {
return parse;
}
module.exports = factory;

@@ -11,9 +11,10 @@ 'use strict';

function parser(str, offset, options) {
function parser(context, offset, options) {
var source = context.source;
if (options.string != '') {
var s = str.substr(offset, options.string.length);
var s = source.substr(offset, options.string.length);
var q = options.ignoreCase ? s.toUpperCase() : s;
if (q == options.string) {
return {
type: utils.TokenType.literal,
type: utils.token.literal,
value: s,

@@ -20,0 +21,0 @@ length: s.length

@@ -5,6 +5,4 @@ 'use strict';

var utils = require('../../utils');
var errors = require('../../errors');
var defaultOptions = {
allowZeroWidthStripes: false,
// Name can have more than one character

@@ -30,15 +28,14 @@ allowLongNames: true

function parser(str, offset, pattern, options) {
// Hope nobody will try to add stripe with 1e9 lines...
var matches = pattern.exec(str.substr(offset, 10));
function parser(context, offset, pattern, options) {
var source = context.source;
// Hope nobody will try to add stripe with 1e19 lines...
var matches = pattern.exec(source.substr(offset, 20));
if (matches) {
var count = parseInt(matches[2], 10) || 0;
if (count <= 0) {
if (!options.allowZeroWidthStripes) {
throw new errors.ZeroWidthStripe(str, offset, matches[0].length);
}
if (count < 0) {
count = 0;
}
return {
type: utils.TokenType.pivot,
var result = {
type: utils.token.pivot,
name: matches[1].toUpperCase(),

@@ -48,2 +45,12 @@ count: count,

};
if (result.count == 0) {
context.errorHandler(
new Error(utils.error.message.zeroWidthStripe),
{token: result},
utils.error.severity.warning
);
}
return result;
}

@@ -50,0 +57,0 @@ }

@@ -5,6 +5,4 @@ 'use strict';

var utils = require('../../utils');
var errors = require('../../errors');
var defaultOptions = {
allowZeroWidthStripes: false,
// Name can have more than one character

@@ -30,15 +28,14 @@ allowLongNames: true

function parser(str, offset, pattern, options) {
// Hope nobody will try to add stripe with 1e9 lines...
var matches = pattern.exec(str.substr(offset, 10));
function parser(context, offset, pattern, options) {
var source = context.source;
// Hope nobody will try to add stripe with 1e19 lines...
var matches = pattern.exec(source.substr(offset, 20));
if (matches) {
var count = parseInt(matches[2], 10) || 0;
if (count <= 0) {
if (!options.allowZeroWidthStripes) {
throw new errors.ZeroWidthStripe(str, offset, matches[0].length);
}
if (count < 0) {
count = 0;
}
return {
type: utils.TokenType.stripe,
var result = {
type: utils.token.stripe,
name: matches[1].toUpperCase(),

@@ -48,2 +45,12 @@ count: count,

};
if (result.count == 0) {
context.errorHandler(
new Error(utils.error.message.zeroWidthStripe),
{token: result},
utils.error.severity.warning
);
}
return result;
}

@@ -50,0 +57,0 @@ }

'use strict';
var pattern = /^\s+/i;
var utils = require('../../utils');
var pattern = /^\s+/i;
function parse(context, offset) {
var source = context.source;
var chunkSize = 10;
var result = '';
while (true) {
var chunk = source.substr(offset, chunkSize);
var matches = pattern.exec(chunk);
if (!matches) {
break;
}
result += matches[0];
if (matches[0].length < chunkSize) {
// Don't wait for next turn
break;
}
}
function parser(str, offset) {
// Try to capture at most 10 characters. If there are more
// whitespaces - we'll capture them on a next turn
var matches = pattern.exec(str.substr(offset, 10));
if (matches) {
if (result != '') {
return {
type: utils.TokenType.whitespace,
value: matches[0],
length: matches[0].length
type: utils.token.whitespace,
value: result,
length: result.length
};

@@ -21,5 +33,5 @@ }

function factory() {
return parser;
return parse;
}
module.exports = factory;
'use strict';
var _ = require('lodash');
var utils = require('../utils');
var whitespace = require('./token/whitespace');
var invalid = require('./token/invalid');
function canBeMerged(token) {
return utils.isInvalid(token) || utils.isWhitespace(token);
}
function Context(source, parsers, options) {
this.source = _.isString(source) ? source : '';
function appendToken(tokens, token) {
if (canBeMerged(token)) {
var last = _.last(tokens);
if (last && canBeMerged(last)) {
if (last.type == token.type) {
last.value += token.value;
last.length += token.length;
return;
}
}
parsers = _.filter(parsers, _.isFunction);
parsers.splice(0, 0, whitespace()); // Prepend this parser to skip spaces
parsers.push(invalid()); // This parser will handle invalid tokens
this.parsers = parsers;
this.options = options;
this.inForesee = 0;
if (_.isFunction(options.errorHandler)) {
this.errorHandler = function(error, data, severity) {
options.errorHandler(error, data, severity || 'error');
};
}
tokens.push(token);
}
function executeParsers(source, parsers, offset, result) {
_.each(parsers, function(parser) {
var token = parser(source, offset);
if (_.isObject(token)) {
token.offset = token.offset || offset;
token.source = source;
appendToken(result, token);
offset = token.offset + token.length;
return false;
Context.prototype = {};
Context.prototype.errorHandler = function(error, data, severity) {
// Do nothing - default error handler will just ignore all errors.
};
function getToken(context, offset) {
var result = null;
_.each(context.parsers, function(parser) {
result = parser(context, offset);
if (_.isObject(result)) {
result.offset = result.offset || offset;
return false; // Break
}
});
return offset;
return result;
}
function factory(parsers, options) {
parsers = _.filter(parsers, _.isFunction);
parsers.splice(0, 0, whitespace()); // Prepend this parser to skip spaces
parsers.push(invalid(options)); // This parser will handle invalid tokens
Context.prototype.foresee = function(offset) {
var foreseeLimit = this.options.foreseeLimit;
if (this.inForesee >= foreseeLimit) {
return null;
}
return function(source) {
var tokens = [];
var offset = 0;
offset = parseInt(offset, 10) || 0;
if (offset < 0) {
offset = 0;
}
while (offset < source.length) {
offset = executeParsers(source, parsers, offset, tokens);
if (offset <= this.offset) {
this.errorHandler(new Error('Parser should not go back.'), {
currentOffset: this.offset,
requestedOffset: offset,
source: this.source
});
return null;
}
this.inForesee++;
var result = getToken(this, offset);
if (this.inForesee > 0) {
this.inForesee--;
}
return result;
};
Context.prototype.parse = function(offset) {
var result = [];
offset = parseInt(offset, 10) || 0;
if (offset < 0) {
offset = 0;
}
while (offset < this.source.length) {
this.offset = offset;
var token = getToken(this, offset);
if (_.isObject(token)) {
result.push(token);
offset = token.offset + token.length;
}
}
return tokens;
};
return result;
};
function factory(source, parsers, options) {
options = _.extend({}, options);
options.foreseeLimit = parseInt(options.foreseeLimit, 10) || 0;
if (options.foreseeLimit < 1) {
options.foreseeLimit = 1;
}
return new Context(source, parsers, options);
}
module.exports = factory;

@@ -5,7 +5,8 @@ 'use strict';

var defaults = require('../defaults');
var rendering = require('./index');
var utils = require('../utils');
var defaultOptions = {
// Also options for `pattern` renderer
weave: defaults.weave.serge
weave: defaults.weave.serge,
defaultColors: null,
transformSyntaxTree: null
};

@@ -117,21 +118,11 @@

function preparePattern(pattern, weave) {
pattern = _.filter(pattern, function(item) {
return _.isArray(item) && (item.length >= 2) && (item[1] > 0);
});
function preparePattern(node, weave, colors, defaultColors) {
var items = _.isObject(node) && node.isBlock ? node.items : [];
var pattern = utils.sett.compile(items, colors, defaultColors);
var metrics = utils.sett.getPatternMetrics(pattern, weave);
var lengthOfPattern = _.reduce(pattern, function(result, item) {
return result + item[1];
}, 0);
var weaveLength = _.sum(weave);
var lengthOfCycle = lengthOfPattern;
while (lengthOfCycle % weaveLength != 0) {
lengthOfCycle += lengthOfPattern;
}
return {
pattern: pattern,
lengthOfPattern: lengthOfPattern,
lengthOfCycle: lengthOfCycle
lengthOfPattern: metrics.length,
lengthOfCycle: metrics.fullCycle
};

@@ -167,6 +158,2 @@ }

function chooseFirstArray() {
return _.find(arguments, _.isArray) || [];
}
function getMetrics(weave, preparedWarp, preparedWeft) {

@@ -200,12 +187,18 @@ return {

}
sett = rendering.pattern(options)(sett);
options = _.extend({}, defaultOptions, options);
if (_.isFunction(options.transformSyntaxTree)) {
sett = options.transformSyntaxTree(sett);
}
var warpIsSameAsWeft = sett.weft === sett.warp;
options = _.extend({}, defaultOptions, options);
var weave = prepareWeave(options.weave, defaults.weave.serge);
var warp = preparePattern(chooseFirstArray(sett.warp, sett.weft), weave);
var warp = preparePattern(sett.warp || sett.weft, weave,
sett.colors, options.defaultColors);
var weft = warp;
if (!warpIsSameAsWeft) {
weft = preparePattern(chooseFirstArray(sett.weft, sett.warp), weave);
weft = preparePattern(sett.weft || sett.warp, weave,
sett.colors, options.defaultColors);
}

@@ -212,0 +205,0 @@

'use strict';
var _ = require('lodash');
var utils = require('../utils');
var defaultOptions = {
// function to transform newly built AST: (sett) => { return modifiedSett; }
transformSett: null,
formatters: {
color: function(token) {
return token.name + token.color + ';';
transformSyntaxTree: null,
format: {
color: function(item) {
var comment = item.comment != '' ? ' ' + item.comment : '';
return item.name + item.value + comment + ';';
},
stripe: function(token) {
return token.name + token.count;
stripe: function(item) {
return item.name + item.count;
},
pivot: function(token) {
return token.name + '/' + token.count;
block: function(block) {
var result = _.chain(block.formattedItems).join(' ').trim().value();
return result != '' ? '[' + result + ']' : '';
}
},
defaultFormatter: function(token) {
return token.value;
join: function(components) {
var parts = [];
if (components.colors.length > 0) {
parts.push(components.colors.join(' '));
}
if (components.warp != components.weft) {
parts.push(components.warp + ' // ' + components.weft);
} else {
parts.push(components.warp);
}
return parts.join('\n');
},
prepareNestedBlock: function(nestedBlock) {
var result = [];
result.push(utils.newTokenOpeningSquareBracket());
result = result.concat(nestedBlock);
result.push(utils.newTokenClosingSquareBracket());
return result;
},
prepareRootBlock: function(block) {
return block;
},
joinComponents: function(formattedSett, originalSett) {
return utils.trim([
formattedSett.colors,
formattedSett.warp,
formattedSett.weft
].join('\n'));
},
defaultColors: {},
outputOnlyUsedColors: false
includeUnusedColors: true,
includeDefaultColors: true
};
function getOnlyUsedColors(tokens, colors, result) {
if (!_.isObject(result)) {
result = {};
function processColors(usedColors, settColors, options) {
var defaultColors = _.extend({}, options.defaultColors);
var keys = _.intersection(_.keys(settColors), _.keys(usedColors));
if (options.includeUnusedColors) {
keys = _.keys(settColors);
}
_.each(tokens, function(token) {
if (_.isArray(token)) {
result = getOnlyUsedColors(token, colors, result);
}
if (utils.isStripe(token) || utils.isPivot(token)) {
if (colors[token.name]) {
result[token.name] = colors[token.name];
}
}
});
return result;
}
if (options.includeDefaultColors) {
keys = _.union(_.keys(settColors), _.keys(usedColors));
}
function colorsAsTokens(colors, colorComments, options) {
colorComments = _.extend({}, colorComments);
return _.chain(utils.normalizeColorMap(colors))
.map(function(value, name) {
var result = utils.newTokenColor(name, value);
var key = name + value;
if (colorComments[key]) {
result.comment = colorComments[key];
var format = options.format;
if (!_.isFunction(format.color)) {
return [];
}
return _.chain(keys)
.sortBy()
.map(function(key) {
var color = settColors[key] || defaultColors[key];
if (color) {
return format.color(_.extend({name: key}, color));
}
return result;
return null;
})
.sortBy('name')
.filter(function(str) {
return _.isString(str) && (str.length > 0);
})
.value();
}
function renderTokens(tokens, options) {
return utils.trim(_.chain(tokens)
.map(function(token) {
var formatter = options.formatters[token.type];
if (!_.isFunction(formatter)) {
formatter = options.defaultFormatter;
function process(block, options, usedColors) {
var format = options.format;
if (!_.isFunction(format.stripe) || !_.isFunction(format.block)) {
return '';
}
block = _.clone(block);
block.formattedItems = _.chain(block.items)
.map(function(item) {
if (item.isStripe) {
usedColors[item.name] = true;
return format.stripe(item);
}
return formatter(token);
if (item.isBlock) {
return process(item, options, usedColors);
}
return '';
})
.filter()
.join(' ')
/* eslint-disable no-useless-escape */
.replace(/\[\s/ig, '[')
.replace(/\s\]/ig, ']')
/* eslint-enable no-useless-escape */
.value());
.filter(function(str) {
return str.length > 0;
})
.value();
return _.isFunction(format.block) ? format.block(block) : '';
}
function flattenTokens(tokens, options, isNested) {
var result = [];
var current;
if (!isNested) {
tokens = options.prepareRootBlock(tokens);
}
for (var i = 0; i < tokens.length; i++) {
current = tokens[i];
if (_.isArray(current)) {
// Flatten nested block
current = options.prepareNestedBlock(current);
current = flattenTokens(current, options, true);
[].push.apply(result, current);
} else {
result.push(current);
}
}
return result;
}
function render(sett, options) {
var warpIsSameAsWeft = sett.warp === sett.weft;
var warp = flattenTokens(sett.warp, options);
var usedColors = {};
var warp = process(sett.warp, options, usedColors);
var weft = warp;
if (!warpIsSameAsWeft) {
weft = flattenTokens(sett.weft, options);
weft = process(sett.weft, options, usedColors);
}
var colors = _.extend({}, options.defaultColors, sett.colors);
if (options.outputOnlyUsedColors) {
colors = _.extend({},
getOnlyUsedColors(sett.warp, colors),
getOnlyUsedColors(sett.weft, colors)
);
}
colors = colorsAsTokens(colors, sett.colorComments, options);
var colors = processColors(usedColors, sett.colors, options);
colors = renderTokens(colors, options);
warp = renderTokens(warp, options);
weft = renderTokens(weft, options);
if (weft == warp) {
weft = '';
}
return utils.trim(options.joinComponents({
return _.trim(options.join({
colors: colors,

@@ -152,24 +114,2 @@ warp: warp,

options = _.merge({}, defaultOptions, options);
if (!_.isFunction(options.defaultFormatter)) {
options.defaultFormatter = defaultOptions.defaultFormatter;
}
if (!_.isFunction(options.joinComponents)) {
options.joinComponents = defaultOptions.joinComponents;
}
if (!_.isFunction(options.prepareNestedBlock)) {
options.prepareNestedBlock = defaultOptions.prepareNestedBlock;
}
if (!_.isFunction(options.prepareRootBlock)) {
options.prepareRootBlock = defaultOptions.prepareRootBlock;
}
if (!_.isObject(options.formatters)) {
options.formatters = {};
}
options.formatters = _.chain(options.formatters)
.map(function(value, key) {
return _.isFunction(value) ? [key, value] : null;
})
.filter()
.fromPairs()
.value();

@@ -180,4 +120,4 @@ return function(sett) {

}
if (_.isFunction(options.transformSett)) {
sett = options.transformSett(sett);
if (_.isFunction(options.transformSyntaxTree)) {
sett = options.transformSyntaxTree(sett);
}

@@ -184,0 +124,0 @@

'use strict';
module.exports.canvas = require('./canvas');
module.exports.pattern = require('./pattern');
module.exports.format = require('./format');
module.exports.metrics = require('./metrics');
'use strict';
var _ = require('lodash');
var index = require('./index');
var render = require('../../render');
var transform = require('../../transform');
var utils = require('../../utils');
var defaults = require('../../defaults');
function formatPivot(str) {
return str.replace(/^([a-z]+)([0-9]+)$/i, '$1/$2');
}
var defaultOptions = {
format: {
color: function(item) {
var comment = item.comment != '' ? ' ' + item.comment : '';
return item.name + item.value + comment + ';';
},
stripe: function(item) {
return item.name + item.count;
},
block: function(block) {
var items = block.formattedItems;
if (block.reflect && (items.length >= 2)) {
// Convert first and last to pivots
items[0] = formatPivot(items[0]);
items[items.length - 1] = formatPivot(items[items.length - 1]);
}
return _.chain(items).join(' ').trim().value();
}
}
};
// Options same as for tartan.render.format():
// + warpAndWeftSeparator: index.warpAndWeftSeparator
// - format
// - join
function factory(options) {
options = _.extend({}, options);
options.transformSett = transform([
options.transformSett,
transform.flatten(options),
options = _.extend({}, options, defaultOptions);
if (!_.isString(options.warpAndWeftSeparator)) {
options.warpAndWeftSeparator = '';
}
if (options.warpAndWeftSeparator == '') {
options.warpAndWeftSeparator = index.warpAndWeftSeparator;
}
options.transformSyntaxTree = transform([
options.transformSyntaxTree,
transform.flatten(),
transform.fold()
]);
options.formatters = {
color: function(token) {
var comment = _.isString(token.comment) && (token.comment.length > 0) ?
' ' + utils.trim(token.comment) : '';
return token.name + token.color + comment + ';';
},
stripe: function(token) {
return token.name + token.count;
},
pivot: function(token) {
return token.name + '/' + token.count;
options.join = function(components) {
var parts = [];
if (components.colors.length > 0) {
parts.push(components.colors.join(' '));
}
};
options.prepareNestedBlock = function(nestedBlock) {
var result = [];
result.push(utils.stripeToPivot(_.first(nestedBlock)));
if (nestedBlock.length > 2) {
result = result.concat(nestedBlock.slice(1, nestedBlock.length - 1));
if (components.warp != components.weft) {
parts.push(components.warp + ' ' + options.warpAndWeftSeparator +
' ' + components.weft);
} else {
parts.push(components.warp);
}
result.push(utils.stripeToPivot(_.last(nestedBlock)));
return result;
return parts.join('\n');
};
options.prepareRootBlock = function(block) {
return block;
};
options.joinComponents = function(formattedSett, originalSett) {
var threadcount = formattedSett.warp;
var weft = formattedSett.weft;
if ((weft != '') && (weft != formattedSett.warp)) {
threadcount += ' // ' + formattedSett.weft;
}
return utils.trim([formattedSett.colors, threadcount].join('\n'));
};
return render.format(options);

@@ -49,0 +69,0 @@ }

@@ -10,1 +10,2 @@ 'use strict';

module.exports.colors = defaults.colors;
module.exports.warpAndWeftSeparator = defaults.warpAndWeftSeparator;
'use strict';
var _ = require('lodash');
var index = require('./index');
var defaults = require('../../defaults');

@@ -11,36 +12,54 @@ var parse = require('../../parse');

// Options for: tartan.parse() + `transformSett` for `buildSyntaxTree`
/*
options = {
warpAndWeftSeparator: index.warpAndWeftSeparator,
errorHandler: <default>,
processTokens: <default>,
transformSyntaxTree: <default>
}
*/
function factory(options) {
options = _.extend({}, options);
options.buildSyntaxTree = syntax.default({
filterTokens: filter.removeTokens(defaults.insignificantTokens),
isWarpAndWeftSeparator: function(token) {
return utils.isLiteral(token) && (token.value == '//');
},
transformSett: transform([
options.transformSett,
transform.checkClassicSyntax()
])
});
if (!_.isString(options.warpAndWeftSeparator)) {
options.warpAndWeftSeparator = '';
}
if (options.warpAndWeftSeparator == '') {
options.warpAndWeftSeparator = index.warpAndWeftSeparator;
}
return parse([
parse.stripe(_.extend({}, options, {
allowLongNames: true
})),
parse.pivot(),
parse.stripe(),
parse.literal(options.warpAndWeftSeparator),
parse.color({
allowLongNames: true,
valueAssignment: 'allow',
colorPrefix: 'require',
colorPrefix: /[=]?[#]/,
colorSuffix: null,
colorFormat: 'long',
comment: 'allow',
whitespaceBeforeComment: 'allow',
semicolonAtTheEnd: 'require'
}),
parse.literal('//'),
parse.pivot(_.extend({}, options, {
allowLongNames: true
}))
], options);
allowComment: true,
commentSuffix: /;/,
requireCommentSuffix: true,
commentFormat: /^\s*(.*)\s*;\s*$/
})
], {
errorHandler: options.errorHandler,
processTokens: filter([
options.processTokens,
filter.removeTokens(defaults.insignificantTokens)
]),
buildSyntaxTree: syntax.classic({
errorHandler: options.errorHandler,
processTokens: filter.classify({
isWarpAndWeftSeparator: function(token) {
return utils.token.isLiteral(token) &&
(token.value == options.warpAndWeftSeparator);
}
}),
transformSyntaxTree: options.transformSyntaxTree
})
});
}
module.exports = factory;
'use strict';
module.exports.default = require('./default');
module.exports.classic = require('./classic');
module.exports.extended = require('./extended');
module.exports.stwr = require('./stwr');
module.exports.weddslist = require('./weddslist');
'use strict';
var _ = require('lodash');
var index = require('./index');
var render = require('../../render');
var transform = require('../../transform');
var utils = require('../../utils');
var defaults = require('../../defaults');
function formatPivot(str) {
return str.replace(/^([a-z]+)([0-9]+)$/i, '$1/$2');
}
var defaultOptions = {
format: {
color: function(item) {
var comment = item.comment != '' ? ' ' + item.comment : '';
return item.name + '=' + item.value + comment + ';';
},
stripe: function(item) {
return item.name + item.count;
},
block: function(block) {
var items = block.formattedItems;
if (block.reflect && (items.length >= 2)) {
// Convert first and last to pivots
items[0] = formatPivot(items[0]);
items[items.length - 1] = formatPivot(items[items.length - 1]);
}
return _.chain(items).join(' ').trim().value();
}
}
};
// Options same as for tartan.render.format():
// + warpAndWeftSeparator: index.warpAndWeftSeparator
// - format
// - join
function factory(options) {
options = _.extend({}, options);
options.transformSett = transform([
options.transformSett,
transform.flatten(options),
options = _.extend({}, options, defaultOptions);
if (!_.isString(options.warpAndWeftSeparator)) {
options.warpAndWeftSeparator = '';
}
if (options.warpAndWeftSeparator == '') {
options.warpAndWeftSeparator = index.warpAndWeftSeparator;
}
options.transformSyntaxTree = transform([
options.transformSyntaxTree,
transform.flatten(),
transform.fold()
]);
options.formatters = {
color: function(token) {
var color = token.color;
color = color.substr(1, color.length).toUpperCase();
var comment = _.isString(token.comment) && (token.comment.length > 0) ?
' ' + utils.trim(token.comment) : '';
return token.name + '=' + color + comment + ';';
},
stripe: function(token) {
return token.name + token.count;
},
pivot: function(token) {
return token.name + '/' + token.count;
options.join = function(components) {
var parts = [];
if (components.colors.length > 0) {
parts.push(components.colors.join(' '));
}
};
options.prepareNestedBlock = function(nestedBlock) {
var result = [];
result.push(utils.stripeToPivot(_.first(nestedBlock)));
if (nestedBlock.length > 2) {
result = result.concat(nestedBlock.slice(1, nestedBlock.length - 1));
if (components.warp != components.weft) {
parts.push(components.warp + ' ' + options.warpAndWeftSeparator +
' ' + components.weft);
} else {
parts.push(components.warp);
}
result.push(utils.stripeToPivot(_.last(nestedBlock)));
return result;
return parts.join('\n');
};
options.prepareRootBlock = function(block) {
return block;
};
options.joinComponents = function(formattedSett, originalSett) {
var threadcount = formattedSett.warp;
var weft = formattedSett.weft;
if ((weft != '') && (weft != formattedSett.warp)) {
threadcount += ' . ' + formattedSett.weft;
}
return utils.trim([formattedSett.colors, threadcount].join('\n'));
};
return render.format(options);

@@ -51,0 +69,0 @@ }

'use strict';
var utils = require('../../utils');
module.exports.id = 'stwr';

@@ -8,3 +10,3 @@ module.exports.name = 'Scottish Register of Tartans / ' +

module.exports.format = require('./format');
module.exports.colors = {
module.exports.colors = utils.color.buildColorMap({
/* eslint-disable key-spacing */

@@ -23,2 +25,3 @@ K: '#000000', LP: '#9966ff', P: '#9933ff',

/* eslint-enable key-spacing */
};
});
module.exports.warpAndWeftSeparator = '.';
'use strict';
var _ = require('lodash');
var index = require('./index');
var defaults = require('../../defaults');

@@ -11,36 +12,54 @@ var parse = require('../../parse');

// Options for: tartan.parse() + `transformSett` for `buildSyntaxTree`
/*
options = {
warpAndWeftSeparator: index.warpAndWeftSeparator
errorHandler: <default>,
processTokens: <default>,
transformSyntaxTree: <default>
}
*/
function factory(options) {
options = _.extend({}, options);
options.buildSyntaxTree = syntax.default({
filterTokens: filter.removeTokens(defaults.insignificantTokens),
isWarpAndWeftSeparator: function(token) {
return utils.isLiteral(token) && (token.value == '.');
},
transformSett: transform([
options.transformSett,
transform.checkClassicSyntax()
])
});
if (!_.isString(options.warpAndWeftSeparator)) {
options.warpAndWeftSeparator = '';
}
if (options.warpAndWeftSeparator == '') {
options.warpAndWeftSeparator = index.warpAndWeftSeparator;
}
return parse([
parse.stripe(_.extend({}, options, {
allowLongNames: true
})),
parse.pivot(),
parse.stripe(),
parse.literal(options.warpAndWeftSeparator),
parse.color({
allowLongNames: true,
valueAssignment: 'require',
colorPrefix: 'allow',
colorPrefix: /[=][#]?/,
colorSuffix: null,
colorFormat: 'long',
comment: 'allow',
whitespaceBeforeComment: 'allow',
semicolonAtTheEnd: 'require'
}),
parse.literal('.'),
parse.pivot(_.extend({}, options, {
allowLongNames: true
}))
], options);
allowComment: true,
commentSuffix: /;/,
requireCommentSuffix: true,
commentFormat: /^\s*(.*)\s*;\s*$/
})
], {
errorHandler: options.errorHandler,
processTokens: filter([
options.processTokens,
filter.removeTokens(defaults.insignificantTokens)
]),
buildSyntaxTree: syntax.classic({
errorHandler: options.errorHandler,
processTokens: filter.classify({
isWarpAndWeftSeparator: function(token) {
return utils.token.isLiteral(token) &&
(token.value == options.warpAndWeftSeparator);
}
}),
transformSyntaxTree: options.transformSyntaxTree
})
});
}
module.exports = factory;
'use strict';
var _ = require('lodash');
var index = require('./index');
var render = require('../../render');
var transform = require('../../transform');
var utils = require('../../utils');
var defaults = require('../../defaults');
function factory(options) {
options = _.extend({}, options);
options.transformSett = transform([
options.transformSett,
transform.flatten(options),
transform.fold()
]);
options.formatters = {
color: function(token) {
return token.name + token.color;
function formatPivot(str) {
return str.replace(/^([a-z]+)([0-9]+)$/i, '$1/$2');
}
var defaultOptions = {
format: {
color: function(item) {
return item.name + item.value;
},
stripe: function(token) {
return token.name + token.count;
stripe: function(item) {
return item.name + item.count;
},
block: function(block) {
var items = block.formattedItems;
if (block.reflect && (items.length >= 3)) {
items.splice(1, 0, '(');
items.splice(-1, 0, ')');
}
return _.chain(items).join(' ').trim().value()
.replace(/\(\s+/g, '(')
.replace(/\s+\)/g, ')');
}
};
options.prepareNestedBlock = function(nestedBlock) {
var result = _.clone(nestedBlock);
if (nestedBlock.length > 2) {
result.splice(1, 0, utils.newTokenOpeningParenthesis());
result.splice(-1, 0, utils.newTokenClosingParenthesis());
},
join: function(components) {
var parts = [];
if (components.colors.length > 0) {
parts.push(components.colors.join(' '));
}
return result;
};
options.prepareRootBlock = function(block) {
var result = _.clone(block);
if ((result.length == 1) && _.isArray(result[0])) {
return result;
var warp = components.warp;
var weft = components.weft;
if (warp == '') {
warp = weft;
weft = '';
}
result.splice(0, 0, utils.newTokenOpeningParenthesis());
result.push(utils.newTokenClosingParenthesis());
return result;
};
options.joinComponents = function(formattedSett, originalSett) {
var warp = '[ ' + formattedSett.warp
.replace(/\(\s/g, '(').replace(/\s\)/g, ')');
var weft = '';
if (formattedSett.weft != formattedSett.warp) {
if (formattedSett.weft != '') {
weft = '] ' + formattedSett.weft
.replace(/\(\s/g, '(').replace(/\s\)/g, ')');
}
if (components.warp == components.weft) {
weft = '';
}
return utils.trim([formattedSett.colors, warp, weft].join('\n'));
};
if (warp != '') {
parts.push('[ ' + warp);
}
if (weft != '') {
parts.push('] ' + weft);
}
return parts.join('\n');
}
};
// Options same as for tartan.render.format():
// - format
// - join
function factory(options) {
options = _.extend({}, options, defaultOptions);
options.transformSyntaxTree = transform([
options.transformSyntaxTree,
transform.flatten(),
transform.fold()
]);
return render.format(options);

@@ -54,0 +72,0 @@ }

'use strict';
var utils = require('../../utils');
module.exports.id = 'weddslist';

@@ -8,3 +10,3 @@ module.exports.name = 'Syntax by Weddslist (TDF)';

module.exports.colors = {
module.exports.colors = utils.color.buildColorMap({
/* eslint-disable key-spacing */

@@ -22,2 +24,2 @@ W: '#ffffff', TR: '#ffffe9', R: '#800000',

/* eslint-enable key-spacing */
};
});

@@ -9,33 +9,62 @@ 'use strict';

var transform = require('../../transform');
var utils = require('../../utils');
// Options for: tartan.parse() + `transformSett` for `buildSyntaxTree`
/*
options = {
errorHandler: <default>,
processTokens: <default>,
transformSyntaxTree: <default>
}
*/
function factory(options) {
options = _.extend({}, options);
options.buildSyntaxTree = syntax.weddslist({
filterTokens: filter.removeTokens(defaults.insignificantTokens),
transformSett: transform([
options.transformSett,
transform.checkClassicSyntax()
])
});
return parse([
parse.stripe(_.extend({}, options, {
allowLongNames: true
})),
parse.color(_.extend({}, options, {
parse.stripe(),
parse.literal('('),
parse.literal(')'),
parse.literal('['),
parse.literal(']'),
parse.color({
allowLongNames: true,
valueAssignment: 'none',
colorPrefix: 'require',
colorPrefix: /[#]/,
colorSuffix: null,
colorFormat: 'long',
comment: 'none',
semicolonAtTheEnd: 'allow'
})),
parse.literal('['),
parse.literal(']'),
parse.literal('('),
parse.literal(')')
], options);
allowComment: false
})
], {
errorHandler: options.errorHandler,
processTokens: filter([
options.processTokens,
filter.removeTokens(defaults.insignificantTokens)
]),
buildSyntaxTree: syntax.weddslist({
errorHandler: options.errorHandler,
processTokens: filter.classify({
// Disable some token classes
isWarpAndWeftSeparator: null,
isPivot: null,
isBlockStart: null,
isBlockEnd: null,
// Add new token classes
isWarpStart: function(token) {
return utils.token.isLiteral(token) && (token.value == '[');
},
isWeftStart: function(token) {
return utils.token.isLiteral(token) && (token.value == ']');
},
isBlockBodyStart: function(token) {
return utils.token.isLiteral(token) && (token.value == '(');
},
isBlockBodyEnd: function(token) {
return utils.token.isLiteral(token) && (token.value == ')');
}
}),
transformSyntaxTree: options.transformSyntaxTree
})
});
}
module.exports = factory;
'use strict';
module.exports.default = require('./default');
module.exports.extended = require('./extended');
module.exports.classic = require('./classic');
module.exports.weddslist = require('./weddslist');

@@ -5,209 +5,167 @@ 'use strict';

var utils = require('../utils');
var errors = require('../errors');
var defaultOptions = {
// Error handler
errorHandler: function(error, data, severity) {
// Do nothing
},
// function to filter parsed tokens: (tokens) => { return modifiedTokens; }
filterTokens: null,
// Fail on invalid tokens; tokens outside warp and weft; multiple warp
// and weft delimiters, etc.
failOnMalformedSequence: true,
// function to transform newly built AST: (sett) => { return modifiedSett; }
transformSett: null
processTokens: null,
// function to transform newly built AST: (ast) => { return modifiedAst; }
transformSyntaxTree: null
};
function splitWarpAndWeft(tokens, options) {
var colors = [];
var warp = null;
var weft = null;
var currentBlock = 'colors';
var i;
var token;
/*
<sett> ::= [ { <color> } ]
<sequence> |
<warp> [ <weft> ] |
[ <warp> ] <weft> |
<weft> <warp>
for (i = 0; i < tokens.length; i++) {
token = tokens[i];
switch (currentBlock) {
case 'colors': {
if (utils.isColor(token)) {
colors.push(token);
continue;
}
if (utils.isLiteral(token)) {
switch (token.value) {
case '[':
if (!warp) {
warp = [];
currentBlock = 'warp';
continue;
}
break;
case ']':
if (!weft) {
weft = [];
currentBlock = 'weft';
continue;
}
break;
default: break;
}
}
break;
<warp> ::= '[' <sequence>
<weft> ::= ']' <sequence>
<sequence> ::= <reflected> | <repetitive>
<reflected> ::= <stripe> '(' { <stripe> } ')' <stripe>
<repetitive> ::= [ '(' ] { <stripe> } [ ')' ]
*/
function buildTree(tokens, options) {
var first;
var last;
var isReflected = false;
tokens = _.filter(tokens, function(token) {
return !token.isWarpStart && !token.isWeftStart;
});
// Strip parenthesis at beginning and end
if (tokens.length >= 2) {
first = _.first(tokens);
last = _.last(tokens);
if (first.isBlockBodyStart && last.isBlockBodyEnd) {
tokens.splice(0, 1);
tokens.splice(-1, 1);
} else {
if (first.isBlockBodyStart) {
options.errorHandler(
new Error(utils.error.message.unexpectedToken),
{token: first},
utils.error.severity.error
);
tokens.splice(0, 1);
}
case 'warp': {
if (utils.isStripe(token)) {
warp.push(token);
continue;
}
if (utils.isLiteral(token)) {
switch (token.value) {
case '(':
warp.push(token);
continue;
case ')':
warp.push(token);
continue;
case ']':
if (!weft) {
weft = [];
currentBlock = 'weft';
continue;
}
break;
default: break;
}
}
break;
if (last.isBlockBodyStart) {
options.errorHandler(
new Error(utils.error.message.unexpectedToken),
{token: last},
utils.error.severity.error
);
tokens.splice(-1, 1);
}
case 'weft': {
if (utils.isStripe(token)) {
weft.push(token);
continue;
}
if (utils.isLiteral(token)) {
switch (token.value) {
case '(':
weft.push(token);
continue;
case ')':
weft.push(token);
continue;
case '[':
if (!warp) {
warp = [];
currentBlock = 'warp';
continue;
}
break;
default: break;
}
}
break;
}
}
// Check if sequence is reflected
if (tokens.length >= 4) {
first = _.first(tokens);
last = _.last(tokens);
if (first.isStripe && last.isStripe) {
first = tokens[1];
last = tokens[tokens.length - 2];
if (first.isBlockBodyStart && last.isBlockBodyEnd) {
isReflected = true;
tokens.splice(1, 1);
tokens.splice(-2, 1);
}
default:
break;
}
// If we are here - we were unable to process token, so trigger error
if (options.failOnMalformedSequence) {
throw new errors.InvalidToken(token);
}
}
var result = {
colors: colors,
warp: warp || [],
weft: weft || []
};
// Convert all tokens to items
var items = _.chain(tokens)
.map(function(token) {
if (token.isStripe) {
return utils.node.newStripe(token);
}
options.errorHandler(
new Error(utils.error.message.unexpectedToken),
{token: token},
utils.error.severity.error
);
return null;
})
.filter()
.value();
if (result.warp.length == 0) {
result.warp = result.weft;
// Check for <stripe> '(' ')' <stripe>
if (items.length <= 2) {
isReflected = false;
}
if (result.weft.length == 0) {
result.weft = result.warp;
}
return result;
return utils.node.newRootBlock(items, isReflected);
}
function buildColorMap(tokens) {
var result = {};
function extractSequence(tokens, result, options, shouldBreak) {
var first = _.first(tokens);
_.each(tokens, function(token) {
result[token.name] = token.color;
if (shouldBreak(token)) {
return false; // Break
}
if (token.isWarpStart && (token !== first)) {
options.errorHandler(
new Error(utils.error.message.multipleWarpAnWeftSeparator),
{token: token},
utils.error.severity.warning
);
}
result.push(token);
});
return result;
}
function checkParenthesisSyntax(tokens, options) {
function extractWarpAndWeft(tokens, warp, weft, options) {
if (tokens.length == 0) {
return true;
return;
}
var openingCount = 0;
var closingCount = 0;
var first;
var isWarpExtracted = false;
_.each(tokens, function(token) {
if (utils.isOpeningParenthesis(token)) {
if ((openingCount == 1) && options.failOnMalformedSequence) {
throw new errors.InvalidToken(token);
}
openingCount++;
}
if (utils.isClosingParenthesis(token)) {
if ((closingCount == 1) && options.failOnMalformedSequence) {
throw new errors.InvalidToken(token);
}
closingCount++;
}
});
if ((openingCount > 1) || (closingCount > 1)) {
return false;
// Try to extract warp
first = _.first(tokens);
if (first.isWarpStart || first.isStripe || first.isBlockBodyStart) {
extractSequence(tokens, warp, options, function(token) {
return token.isWeftStart;
});
tokens.splice(0, warp.length);
isWarpExtracted = true;
}
if (
utils.isOpeningParenthesis(_.first(tokens)) &&
utils.isClosingParenthesis(_.last(tokens))
) {
return true;
}
if (tokens.length >= 4) {
if (
utils.isOpeningParenthesis(tokens[1]) &&
utils.isClosingParenthesis(tokens[tokens.length - 2])
) {
return true;
}
}
if (options.failOnMalformedSequence) {
var token = _.findLast(tokens, utils.isLiteral);
if (!token) {
// Hm. We have no parenthesis at all
return true;
}
throw new errors.InvalidToken(token);
}
return false;
}
function buildTree(tokens, options) {
var result = _.clone(tokens);
if (!checkParenthesisSyntax(result, options)) {
result = _.filter(result, function(token) {
return !utils.isLiteral(token);
// Try to extract weft
first = _.first(tokens);
if (first && first.isWeftStart) {
extractSequence(tokens, weft, options, function(token) {
return token.isWarpStart;
});
tokens.splice(0, weft.length);
}
if (result.length >= 2) {
var isReflective = utils.isOpeningParenthesis(result[1]);
result = _.filter(result, function(token) {
return !utils.isLiteral(token);
});
if (isReflective && (result.length > 0)) {
result = [result];
// If warp was not extracted, try again, but more strict
if (!isWarpExtracted) {
first = _.first(tokens);
if (first && first.isWarpStart) {
extractSequence(tokens, warp, options, function(token) {
return token.isWeftStart;
});
tokens.splice(0, warp.length);
}
}
return result;
// Trigger error for rest tokens
_.each(tokens, function(token) {
options.errorHandler(
new Error(utils.error.message.extraTokenInInputSequence),
{token: token},
utils.error.severity.warning
);
});
}

@@ -220,4 +178,4 @@

}
if (_.isFunction(options.filterTokens)) {
tokens = options.filterTokens(tokens);
if (_.isFunction(options.processTokens)) {
tokens = options.processTokens(tokens);
if (!_.isArray(tokens)) {

@@ -228,19 +186,31 @@ return tokens;

tokens = splitWarpAndWeft(tokens, options);
var warpIsSameAsWeft = tokens.warp === tokens.weft;
// Extract colors; split warp and weft
var colorTokens = _.filter(tokens, function(token) {
return token.isColor;
});
var warpTokens = [];
var weftTokens = [];
extractWarpAndWeft(_.filter(tokens, function(token) {
return !token.isColor;
}), warpTokens, weftTokens, options);
if (warpTokens.length == 0) {
warpTokens = weftTokens;
weftTokens = [];
}
if (weftTokens.length == 0) {
weftTokens = warpTokens;
}
var result = {};
result.colors = buildColorMap(tokens.colors);
result.warp = buildTree(tokens.warp, options);
if (warpIsSameAsWeft) {
result.colors = utils.color.buildColorMap(colorTokens);
result.warp = buildTree(warpTokens, options);
if (weftTokens === warpTokens) {
result.weft = result.warp;
} else {
result.weft = buildTree(tokens.weft, options);
result.weft = buildTree(weftTokens, options);
}
if (_.isFunction(options.transformSett)) {
result = options.transformSett(result);
if (_.isFunction(options.transformSyntaxTree)) {
result = options.transformSyntaxTree(result);
}
return result;

@@ -251,2 +221,5 @@ }

options = _.extend({}, defaultOptions, options);
if (!_.isFunction(options.errorHandler)) {
options.errorHandler = defaultOptions.errorHandler;
}
return function(tokens) {

@@ -253,0 +226,0 @@ return buildSyntaxTree(tokens, options);

'use strict';
var _ = require('lodash');
var mergeStripes = require('./merge-stripes');
var utils = require('../utils');
var defaultOptions = {
mergeStripes: true
};
function flatten(tokens, isNested) {
function flatten(block) {
var result = [];
var current;
for (var i = 0; i < tokens.length; i++) {
current = tokens[i];
if (_.isArray(current)) {
// Flatten nested blocks
_.each(block.items, function(item) {
if (item.isBlock) {
// Flatten nested block
current = flatten(current, true);
[].push.apply(result, current);
item = flatten(item);
[].push.apply(result, item.items);
} else {
result.push(current);
result.push(item);
}
}
});
// If we are flattening nested block, we need to reflect it
// Do not reflect blocks with single stripe
if (isNested && (result.length > 1)) {
var rest = result.slice(0, result.length - 1);
rest.reverse();
result = result.concat(rest);
}
// Special case.
// All nested blocks should be reflected relative to the last pivot;
// first pivot is duplicated.
// But if entire threadcount should be reflected, algorithm a bit differs:
// R/10 K20 Y10 W/2 should become R10 K20 Y10 W2 Y10 K20 - without last R20.
// So let's check this case:
if (!isNested && (tokens.length == 1) && _.isArray(tokens[0])) {
result.pop();
}
return result;
// Reflect and repeat
block = _.clone(block);
block.items = result;
return utils.sett.reflectAndRepeat(block);
}
function transform(sett, options) {
function transform(sett) {
var result = _.clone(sett);
var warpIsSameAsWeft = sett.warp == sett.weft;
if (_.isArray(sett.warp)) {
if (_.isObject(sett.warp)) {
result.warp = flatten(sett.warp);
}
if (_.isArray(sett.weft)) {
if (_.isObject(sett.weft)) {
if (warpIsSameAsWeft) {

@@ -61,16 +41,9 @@ result.weft = result.warp;

if (options.mergeStripes) {
result = mergeStripes()(result);
}
return result;
}
function factory(options) {
options = _.extend({}, defaultOptions, options);
return function(sett) {
return transform(sett, options);
};
function factory() {
return transform;
}
module.exports = factory;
'use strict';
var _ = require('lodash');
var utils = require('../utils');
function processTokens(tokens) {
if (tokens.length % 2 != 0) {
return tokens;
var defaultOptions = {
};
function processTokens(root, options) {
if (root.reflect || (root.items.length % 2 != 0)) {
return root;
}

@@ -13,4 +15,4 @@ // Smallest reflective sett contains 3 stripes in threadcount or

// R/10 K/2 => R10 K2
if (tokens.length < 4) {
return tokens;
if (root.items.length < 4) {
return root;
}

@@ -20,11 +22,11 @@

var i = 1;
var j = tokens.length - 1;
var j = root.items.length - 1;
var left;
var right;
result.push(tokens[0]);
result.push(root.items[0]);
while (true) {
left = tokens[i];
right = tokens[j];
if (utils.isStripe(left) && (utils.isStripe(right))) {
left = root.items[i];
right = root.items[j];
if (left.isStripe && right.isStripe) {
var isSameColor = left.name == right.name;

@@ -46,3 +48,8 @@ var isSameCount = left.count == right.count;

return result ? [result] : tokens;
if (result) {
root = _.clone(root);
root.items = result;
root.reflect = true;
}
return root;
}

@@ -54,6 +61,6 @@

var warpIsSameAsWeft = sett.warp === sett.weft;
if (_.isArray(sett.warp)) {
if (_.isObject(sett.warp)) {
result.warp = processTokens(sett.warp, options);
}
if (_.isArray(sett.weft)) {
if (_.isObject(sett.weft)) {
if (warpIsSameAsWeft) {

@@ -69,6 +76,9 @@ result.weft = result.warp;

function factory() {
return transform;
function factory(options) {
options = _.extend({}, defaultOptions, options);
return function(sett) {
return transform(sett, options);
};
}
module.exports = factory;

@@ -10,5 +10,5 @@ 'use strict';

if (_.isObject(sett)) {
for (var i = 0; i < processors.length; i++) {
sett = processors[i](sett);
}
_.each(processors, function(processor) {
sett = processor(sett);
});
}

@@ -21,6 +21,8 @@ return sett;

module.exports.checkClassicSyntax = require('./check-classic-syntax');
module.exports.flatten = require('./flatten');
module.exports.flattenSimpleBlocks = require('./flatten-simple-blocks');
module.exports.fold = require('./fold');
module.exports.mergeStripes = require('./merge-stripes');
module.exports.removeEmptyBlocks = require('./remove-empty-blocks');
module.exports.removeZeroWidthStripes = require('./remove-zero-width-stripes');
module.exports.optimize = require('./optimize');
'use strict';
var _ = require('lodash');
var utils = require('../utils');
// Do not merge first and last stripe in the only nested block in a root
// as they are pivots! For other nested blocks, first pivot can be merged.
// Do not merge last stripe in reflected blocks as it is central pivot.
// Do not merge first stripe in blocks if it is reflected and repeated.
// Example: [R20 R10 R5 Y2 K10 K5]

@@ -13,49 +12,37 @@ // Wrong: [R35 Y2 K15] => R35 Y2 K15 Y2

// => R35 Y2 K25 Y2 R15
function processTokens(tokens, isNested, doNotMergeFirstPivot) {
var result = [];
function processTokens(block) {
// Root is always repetitive
var first = block.reflect && (block.isRoot || (block.repeat > 1)) ?
_.first(block.items) : null;
var last = block.reflect ? _.last(block.items) : null;
// Special case
if (!isNested && (tokens.length == 1) && (_.isArray(tokens[0]))) {
result.push(processTokens(tokens[0], true, true));
return result;
}
var token;
var prev;
var correctionStart = doNotMergeFirstPivot ? 1 : 0;
var correctionEnd = isNested ? 1 : 0;
for (var i = correctionStart; i < tokens.length - correctionEnd; i++) {
token = tokens[i];
if (_.isArray(token)) {
result.push(processTokens(token, true));
continue;
block = _.clone(block);
block.items = _.reduce(block.items, function(accumulator, item) {
// Process nested blocks
if (item.isBlock) {
accumulator.push(processTokens(item));
return accumulator;
}
if (utils.isStripe(token)) {
prev = _.last(result);
// If current stripe is the same as previous - merge them
if (utils.isStripe(prev) && (prev.name == token.name)) {
prev = _.clone(result.pop());
prev.count += token.count;
result.push(prev);
continue;
if (item.isStripe) {
// Check last item
if (item === last) {
accumulator.push(item);
return accumulator;
}
var prev = _.last(accumulator);
// Check first item
if (prev && prev.isStripe && (prev !== first)) {
if (prev.name == item.name) {
prev = _.clone(accumulator.pop());
prev.count += item.count;
accumulator.push(prev);
return accumulator;
}
}
}
result.push(token);
}
accumulator.push(item);
return accumulator;
}, []);
// For nested blocks, keep first (depending on doNotMergeFirstPivot)
// and last stripe
if (isNested) {
token = _.first(tokens);
if (token && doNotMergeFirstPivot) {
result.splice(0, 0, token);
}
token = _.last(tokens);
if (token && (tokens.length > 1)) {
result.push(token);
}
}
return result;
return block;
}

@@ -67,6 +54,6 @@

var warpIsSameAsWeft = sett.warp === sett.weft;
if (_.isArray(sett.warp)) {
if (_.isObject(sett.warp)) {
result.warp = processTokens(sett.warp, options);
}
if (_.isArray(sett.weft)) {
if (_.isObject(sett.weft)) {
if (warpIsSameAsWeft) {

@@ -73,0 +60,0 @@ result.weft = result.warp;

'use strict';
var _ = require('lodash');
var utils = require('../utils');
var flattenSimpleBlocks = require('./flatten-simple-blocks');
var mergeStripes = require('./merge-stripes');
var removeEmptyBlocks = require('./remove-empty-blocks');
var removeZeroWidthStripes = require('./remove-zero-width-stripes');
var mergeStripes = require('./merge-stripes');
var defaultOptions = {
removeZeroWidthStripes: true,
removeEmptyBlocks: true,
mergeStripes: true,
unfoldSingleColorBlocks: true
// Also options for removeZeroWidthStripes
simplifyBlocks: true,
simplifyStripes: true
};
function removeEmptyBlocks(tokens) {
var result = [];
var token;
for (var i = 0; i < tokens.length; i++) {
token = tokens[i];
if (_.isArray(token)) {
// Double-check length to avoid unnecessary recursion
if (token.length > 0) {
token = removeEmptyBlocks(token);
if (token.length > 0) {
result.push(token);
}
}
} else {
// Keep everything else
result.push(token);
}
}
return result;
}
function optimize(sett, options) {
// Empty blocks anyway should be removed
sett = removeEmptyBlocks()(sett);
// [R20] => R20
// [R20 R10 R5] => R20 R10 R5 R10 => R65
function unfoldSingleColorBlocks(tokens, isNested, doNotMergeFirstPivot) {
if (tokens.length == 0) {
return tokens;
if (options.simplifyBlocks) {
// Try to unfold simple blocks; it may produce new stripes
// instead of blocks, so do it first
sett = flattenSimpleBlocks()(sett);
}
// Special case
if (!isNested) {
doNotMergeFirstPivot = (tokens.length == 1) && (_.isArray(tokens[0]));
}
// Zero-width stripes also should be removed
sett = removeZeroWidthStripes(options)(sett);
var result = _.clone(tokens); // We will edit it in-place
var token;
var firstToken = null;
var i;
// Process nested blocks first
for (i = 0; i < result.length; i++) {
token = result[i];
// Process nested blocks
if (_.isArray(token)) {
token = unfoldSingleColorBlocks(token, true, doNotMergeFirstPivot);
result[i] = token.length != 1 ? token : _.first(token);
}
if (options.simplifyStripes) {
sett = mergeStripes()(sett);
}
// Check input array
for (i = 0; i < result.length; i++) {
token = result[i];
if (!utils.isStripe(token)) {
return result;
}
if (firstToken) {
if (token.name != firstToken.name) {
return result;
}
} else {
firstToken = token;
}
}
// If we are here - we have all tokens with the same color
// For nested blocks, add each color twice (except of the first and last one)
// as they will be duplicated after reflecting
var multiplier = isNested ? 2 : 1;
var count = _.first(result).count;
if (!doNotMergeFirstPivot) {
count *= multiplier;
}
for (i = 1; i < result.length - 1; i++) {
count += multiplier * result[i].count;
}
if (result.length > 1) {
// Avoid adding first element twice if there is the only stripe
count += _.last(result).count;
}
result = utils.newTokenStripe(firstToken.name, count);
return isNested ? result : [result];
return sett;
}
function processTokens(tokens, options) {
// Remove empty blocks
if (options.removeEmptyBlocks) {
tokens = removeEmptyBlocks(tokens);
}
// Then simplify blocks that contains only single-color stripes
if (options.unfoldSingleColorBlocks) {
tokens = unfoldSingleColorBlocks(tokens);
}
return tokens;
}
function transform(sett, options) {
var result = _.clone(sett);
// First of all, remove zero-width stripes. It may create empty blocks
if (options.removeZeroWidthStripes) {
result = removeZeroWidthStripes(options)(result);
}
var warpIsSameAsWeft = result.warp === result.weft;
if (_.isArray(result.warp)) {
result.warp = processTokens(result.warp, options);
}
if (_.isArray(result.weft)) {
if (warpIsSameAsWeft) {
result.weft = result.warp;
} else {
result.weft = processTokens(result.weft, options);
}
}
if (options.mergeStripes) {
result = mergeStripes()(result);
}
return result;
}
function factory(options) {
options = _.extend({}, defaultOptions, options);
return function(sett) {
return transform(sett, options);
return optimize(sett, options);
};

@@ -143,0 +41,0 @@ }

'use strict';
var _ = require('lodash');
var utils = require('../utils');
// TODO: Last zero-width stripe in block can be removed...
// ... with modifying previous stripe:
// [R10 K4 W0] => R10 K4 W0 K4 R10 => R10 K8 R10
// [R10 K8] => R10 K8 R10
var defaultOptions = {

@@ -10,31 +14,44 @@ keepZeroWidthPivots: true

function removeZeroWidthStripes(tokens, options, isNested) {
var result = [];
var token;
var first = _.first(tokens);
var last = _.last(tokens);
for (var i = 0; i < tokens.length; i++) {
token = tokens[i];
// Recursive processing of nested blocks
if (_.isArray(token)) {
result.push(removeZeroWidthStripes(token, options, true));
} else
// Check stripes
if (utils.isStripe(token)) {
if (token.count > 0) {
result.push(token);
} else {
// Do not remove last stripe in reflected blocks as it is central pivot.
// Do not remove first stripe in blocks if it is reflected and repeated.
// Example: [R0 B10 Y2 K5]
// Wrong: [B10 Y2 K5] => B10 Y2 K5 Y2
// Right: [R0 B10 Y2 K5]
// => R0 B10 Y2 K5 Y2 B10
// => B10 Y2 K5 Y2 B10
function removeZeroWidthStripes(block, options) {
// Root is always repetitive
var first = block.reflect && (block.isRoot || (block.repeat > 1)) ?
_.first(block.items) : null;
var last = block.reflect ? _.last(block.items) : null;
block = _.clone(block);
block.items = _.chain(block.items)
.map(function(item) {
// Recursive processing of nested blocks
if (item.isBlock) {
item = removeZeroWidthStripes(item, options);
return item.items.length > 0 ? item : null;
} else
// Check stripes
if (item.isStripe) {
if (item.count > 0) {
return item;
}
if (options.keepZeroWidthPivots) {
// For nested blocks, keep first and last stripe as they are pivots
if (isNested && ((token === first) || (token === last))) {
result.push(token);
// Keep first and last stripes as they are pivots
if ((item === first) || (item === last)) {
return item;
}
}
} else {
// Keep everything else
return item;
}
} else {
// Keep everything else
result.push(token);
}
}
return result;
return null;
})
.filter()
.value();
return block;
}

@@ -46,6 +63,6 @@

if (_.isArray(sett.warp)) {
if (_.isObject(sett.warp)) {
result.warp = removeZeroWidthStripes(sett.warp, options);
}
if (_.isArray(sett.weft)) {
if (_.isObject(sett.weft)) {
if (warpIsSameAsWeft) {

@@ -52,0 +69,0 @@ result.weft = result.warp;

'use strict';
var _ = require('lodash');
var errors = require('../errors');
var TokenType = {
invalid: 'invalid',
whitespace: 'whitespace',
color: 'color',
stripe: 'stripe',
pivot: 'pivot',
literal: 'literal'
};
function trim(str) {
if (!_.isString(str)) {
return str;
}
return str.replace(/^\s+/i, '').replace(/\s+$/i, '');
}
function isValidName(str) {
return /^[a-z]+$/i.test(str);
}
function isValidColor(str, acceptShortFormat) {
if (acceptShortFormat) {
return /^#[0-9a-f]{3}([0-9a-f]{3})?$/i.test(str);
}
return /^#[0-9a-f]{6}$/i.test(str);
}
function normalizeColor(str) {
if (/^#[0-9a-f]{6}$/i.test(str)) {
return str.toLowerCase();
}
if (/^#[0-9a-f]{3}$/i.test(str)) {
// Duplicate each hexadecimal character
return str.replace(/[0-9a-f]/ig, '$&$&').toLowerCase();
}
return false;
}
function normalizeColorMap(colors) {
var result = {};
_.each(colors, function(value, name) {
name = isValidName(name) ? name : null;
value = normalizeColor(value);
if (name && value) {
result[name.toUpperCase()] = value;
}
});
return result;
}
function isToken(token, type) {
return _.isObject(token) && (token.type == type);
}
function isInvalid(token) {
return isToken(token, TokenType.invalid);
}
function isWhitespace(token) {
return isToken(token, TokenType.whitespace);
}
function isColor(token) {
return isToken(token, TokenType.color);
}
function isStripe(token) {
return isToken(token, TokenType.stripe);
}
function isPivot(token) {
return isToken(token, TokenType.pivot);
}
function isLiteral(token) {
return isToken(token, TokenType.literal);
}
function isSquareBracket(token) {
return isLiteral(token) && ((token.value == '[') || (token.value == ']'));
}
function isOpeningSquareBracket(token) {
return isLiteral(token) && (token.value == '[');
}
function isClosingSquareBracket(token) {
return isLiteral(token) && (token.value == ']');
}
function isParenthesis(token) {
return isLiteral(token) && ((token.value == '(') || (token.value == ')'));
}
function isOpeningParenthesis(token) {
return isLiteral(token) && (token.value == '(');
}
function isClosingParenthesis(token) {
return isLiteral(token) && (token.value == ')');
}
function pivotToStripe(token) {
if (isPivot(token)) {
token = _.clone(token);
token.type = TokenType.stripe;
}
return token;
}
function stripeToPivot(token) {
if (isStripe(token)) {
token = _.clone(token);
token.type = TokenType.pivot;
}
return token;
}
function newToken(type, value) {
var result = {
type: type,
source: '',
offset: -1,
length: -1
};
if (_.isString(value)) {
result.value = value;
result.length = value.length;
}
return result;
}
function newTokenInvalid(value) {
return newToken(TokenType.invalid, value);
}
function newTokenWhitespace(value) {
return newToken(TokenType.whitespace, value);
}
function newTokenColor(name, value) {
if (!isValidName(name)) {
throw new errors.CreateTokenError('Invalid color name ' +
JSON.stringify(name));
}
if (!isValidColor(value)) {
throw new errors.CreateTokenError('Invalid color ' + JSON.stringify(name));
}
var result = newToken(TokenType.color);
result.name = name;
result.color = value;
return result;
}
function newTokenStripe(name, count) {
if (!isValidName(name)) {
throw new errors.CreateTokenError('Invalid color name ' +
JSON.stringify(name));
}
count = parseInt(count, 10) || 0;
if (count < 0) {
throw new errors.CreateTokenError('Count of threads should be >= 0');
}
var result = newToken(TokenType.stripe);
result.name = name;
result.count = count;
return result;
}
function newTokenPivot(name, count) {
if (!isValidName(name)) {
throw new errors.CreateTokenError('Invalid color name ' +
JSON.stringify(name));
}
count = parseInt(count, 10) || 0;
if (count < 0) {
throw new errors.CreateTokenError('Count of threads should be >= 0');
}
var result = newToken(TokenType.pivot);
result.name = name;
result.count = count;
return result;
}
function newTokenSquareBracket(value) {
if ((value != '[') && (value != ']')) {
throw new errors.CreateTokenError('Invalid value ' + JSON.stringify(value));
}
return newToken(TokenType.literal, value);
}
function newTokenOpeningSquareBracket() {
return newToken(TokenType.literal, '[');
}
function newTokenClosingSquareBracket() {
return newToken(TokenType.literal, ']');
}
function newTokenParenthesis(value) {
if ((value != '(') && (value != ')')) {
throw new errors.CreateTokenError('Invalid value ' + JSON.stringify(value));
}
return newToken(TokenType.literal, value);
}
function newTokenOpeningParenthesis() {
return newToken(TokenType.literal, '(');
}
function newTokenClosingParenthesis() {
return newToken(TokenType.literal, ')');
}
function newTokenLiteral(value) {
return newToken(TokenType.literal, value);
}
module.exports.TokenType = TokenType;
module.exports.trim = trim;
module.exports.isValidName = isValidName;
module.exports.isValidColor = isValidColor;
module.exports.normalizeColor = normalizeColor;
module.exports.normalizeColorMap = normalizeColorMap;
module.exports.isToken = isToken;
module.exports.isInvalid = isInvalid;
module.exports.isWhitespace = isWhitespace;
module.exports.isColor = isColor;
module.exports.isStripe = isStripe;
module.exports.isPivot = isPivot;
module.exports.isSquareBracket = isSquareBracket;
module.exports.isOpeningSquareBracket = isOpeningSquareBracket;
module.exports.isClosingSquareBracket = isClosingSquareBracket;
module.exports.isParenthesis = isParenthesis;
module.exports.isOpeningParenthesis = isOpeningParenthesis;
module.exports.isClosingParenthesis = isClosingParenthesis;
module.exports.isLiteral = isLiteral;
module.exports.pivotToStripe = pivotToStripe;
module.exports.stripeToPivot = stripeToPivot;
module.exports.newToken = newToken;
module.exports.newTokenInvalid = newTokenInvalid;
module.exports.newTokenWhitespace = newTokenWhitespace;
module.exports.newTokenColor = newTokenColor;
module.exports.newTokenStripe = newTokenStripe;
module.exports.newTokenPivot = newTokenPivot;
module.exports.newTokenSquareBracket = newTokenSquareBracket;
module.exports.newTokenOpeningSquareBracket = newTokenOpeningSquareBracket;
module.exports.newTokenClosingSquareBracket = newTokenClosingSquareBracket;
module.exports.newTokenParenthesis = newTokenParenthesis;
module.exports.newTokenOpeningParenthesis = newTokenOpeningParenthesis;
module.exports.newTokenClosingParenthesis = newTokenClosingParenthesis;
module.exports.newTokenLiteral = newTokenLiteral;
module.exports.error = require('./error');
module.exports.color = require('./color');
module.exports.token = require('./token');
module.exports.node = require('./node');
module.exports.sett = require('./sett');
module.exports.repaint = require('./repaint');
'use strict';
var assert = require('chai').assert;
var packageInfo = require('../package.json');
var tartan = require('../src');
describe('Stub', function() {
describe('Core', function() {
it('Should check library interface', function(done) {
assert.equal(tartan.version, packageInfo.version);
assert(tartan.parse, 'Parser should be exported');
assert(tartan.filter, 'Filters should be exported');
assert(tartan.syntax, 'AST Builders should be exported');
assert(tartan.transform, 'AST Transformations should be exported');
assert(tartan.render, 'Renderers should be exported');
assert(tartan.defaults, 'Defaults should be exported');
it('Should pass', function(done) {
done();

@@ -20,0 +7,0 @@ });

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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