node_modules

This commit is contained in:
saeid
2019-07-15 13:07:31 +04:30
parent d3735c6d30
commit ce1a3ebf9c
35713 changed files with 3639219 additions and 1 deletions
Generated Vendored
+24
View File
@@ -0,0 +1,24 @@
Copyright (c) 2016, Gajus Kuizinas (http://gajus.com/)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+671
View File
@@ -0,0 +1,671 @@
<a name="table"></a>
# Table
[![Travis build status](http://img.shields.io/travis/gajus/table/master.svg?style=flat)](https://travis-ci.org/gajus/table)
[![NPM version](http://img.shields.io/npm/v/table.svg?style=flat)](https://www.npmjs.com/package/table)
[![js-canonical-style](https://img.shields.io/badge/code%20style-canonical-brightgreen.svg?style=flat)](https://github.com/gajus/canonical)
* [Table](#table)
* [Features](#table-features)
* [Usage](#table-usage)
* [Cell Content Alignment](#table-usage-cell-content-alignment)
* [Column Width](#table-usage-column-width)
* [Custom Border](#table-usage-custom-border)
* [Draw Horizontal Line](#table-usage-draw-horizontal-line)
* [Padding Cell Content](#table-usage-padding-cell-content)
* [Predefined Border Templates](#table-usage-predefined-border-templates)
* [Streaming](#table-usage-streaming)
* [Text Truncation](#table-usage-text-truncation)
* [Text Wrapping](#table-usage-text-wrapping)
Produces a string that represents array data in a text table.
![Demo of table displaying a list of missions to the Moon.](./.README/demo.png)
<a name="table-features"></a>
## Features
* Works with strings containing [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) characters.
* Works with strings containing [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code).
* Configurable border characters.
* Configurable content alignment per column.
* Configurable content padding per column.
* Configurable column width.
* Text wrapping.
<a name="table-usage"></a>
## Usage
Table data is described using an array (rows) of array (cells).
```js
import {
table
} from 'table';
// Using commonjs?
// const {table} = require('table');
let data,
output;
data = [
['0A', '0B', '0C'],
['1A', '1B', '1C'],
['2A', '2B', '2C']
];
/**
* @typedef {string} table~cell
*/
/**
* @typedef {table~cell[]} table~row
*/
/**
* @typedef {Object} table~columns
* @property {string} alignment Cell content alignment (enum: left, center, right) (default: left).
* @property {number} width Column width (default: auto).
* @property {number} truncate Number of characters are which the content will be truncated (default: Infinity).
* @property {number} paddingLeft Cell content padding width left (default: 1).
* @property {number} paddingRight Cell content padding width right (default: 1).
*/
/**
* @typedef {Object} table~border
* @property {string} topBody
* @property {string} topJoin
* @property {string} topLeft
* @property {string} topRight
* @property {string} bottomBody
* @property {string} bottomJoin
* @property {string} bottomLeft
* @property {string} bottomRight
* @property {string} bodyLeft
* @property {string} bodyRight
* @property {string} bodyJoin
* @property {string} joinBody
* @property {string} joinLeft
* @property {string} joinRight
* @property {string} joinJoin
*/
/**
* Used to dynamically tell table whether to draw a line separating rows or not.
* The default behavior is to always return true.
*
* @typedef {function} drawJoin
* @param {number} index
* @param {number} size
* @return {boolean}
*/
/**
* @typedef {Object} table~config
* @property {table~border} border
* @property {table~columns[]} columns Column specific configuration.
* @property {table~columns} columnDefault Default values for all columns. Column specific settings overwrite the default values.
* @property {table~drawJoin} drawHorizontalLine
*/
/**
* Generates a text table.
*
* @param {table~row[]} rows
* @param {table~config} config
* @return {String}
*/
output = table(data);
console.log(output);
```
```
╔════╤════╤════╗
║ 0A │ 0B │ 0C ║
╟────┼────┼────╢
║ 1A │ 1B │ 1C ║
╟────┼────┼────╢
║ 2A │ 2B │ 2C ║
╚════╧════╧════╝
```
<a name="table-usage-cell-content-alignment"></a>
### Cell Content Alignment
`{string} config.columns[{number}].alignment` property controls content horizontal alignment within a cell.
Valid values are: "left", "right" and "center".
```js
let config,
data,
output;
data = [
['0A', '0B', '0C'],
['1A', '1B', '1C'],
['2A', '2B', '2C']
];
config = {
columns: {
0: {
alignment: 'left',
minWidth: 10
},
1: {
alignment: 'center',
minWidth: 10
},
2: {
alignment: 'right',
minWidth: 10
}
}
};
output = table(data, config);
console.log(output);
```
```
╔════════════╤════════════╤════════════╗
║ 0A │ 0B │ 0C ║
╟────────────┼────────────┼────────────╢
║ 1A │ 1B │ 1C ║
╟────────────┼────────────┼────────────╢
║ 2A │ 2B │ 2C ║
╚════════════╧════════════╧════════════╝
```
<a name="table-usage-column-width"></a>
### Column Width
`{number} config.columns[{number}].width` property restricts column width to a fixed width.
```js
let data,
output,
options;
data = [
['0A', '0B', '0C'],
['1A', '1B', '1C'],
['2A', '2B', '2C']
];
options = {
columns: {
1: {
width: 10
}
}
};
output = table(data, options);
console.log(output);
```
```
╔════╤════════════╤════╗
║ 0A │ 0B │ 0C ║
╟────┼────────────┼────╢
║ 1A │ 1B │ 1C ║
╟────┼────────────┼────╢
║ 2A │ 2B │ 2C ║
╚════╧════════════╧════╝
```
<a name="table-usage-custom-border"></a>
### Custom Border
`{object} config.border` property describes characters used to draw the table border.
```js
let config,
data,
output;
data = [
['0A', '0B', '0C'],
['1A', '1B', '1C'],
['2A', '2B', '2C']
];
config = {
border: {
topBody: `─`,
topJoin: `┬`,
topLeft: `┌`,
topRight: `┐`,
bottomBody: `─`,
bottomJoin: `┴`,
bottomLeft: `└`,
bottomRight: `┘`,
bodyLeft: `│`,
bodyRight: `│`,
bodyJoin: `│`,
joinBody: `─`,
joinLeft: `├`,
joinRight: `┤`,
joinJoin: `┼`
}
};
output = table(data, config);
console.log(output);
```
```
┌────┬────┬────┐
│ 0A │ 0B │ 0C │
├────┼────┼────┤
│ 1A │ 1B │ 1C │
├────┼────┼────┤
│ 2A │ 2B │ 2C │
└────┴────┴────┘
```
<a name="table-usage-draw-horizontal-line"></a>
### Draw Horizontal Line
`{function} config.drawHorizontalLine` property is a function that is called for every non-content row in the table. The result of the function `{boolean}` determines whether a row is drawn.
```js
let data,
output,
options;
data = [
['0A', '0B', '0C'],
['1A', '1B', '1C'],
['2A', '2B', '2C'],
['3A', '3B', '3C'],
['4A', '4B', '4C']
];
options = {
/**
* @typedef {function} drawJoin
* @param {number} index
* @param {number} size
* @return {boolean}
*/
drawHorizontalLine: (index, size) => {
return index === 0 || index === 1 || index === size - 1 || index === size;
}
};
output = table(data, options);
console.log(output);
```
```
╔════╤════╤════╗
║ 0A │ 0B │ 0C ║
╟────┼────┼────╢
║ 1A │ 1B │ 1C ║
║ 2A │ 2B │ 2C ║
║ 3A │ 3B │ 3C ║
╟────┼────┼────╢
║ 4A │ 4B │ 4C ║
╚════╧════╧════╝
```
<a name="table-usage-padding-cell-content"></a>
### Padding Cell Content
`{number} config.columns[{number}].paddingLeft` and `{number} config.columns[{number}].paddingRight` properties control content padding within a cell. Property value represents a number of whitespaces used to pad the content.
```js
let config,
data,
output;
data = [
['0A', 'AABBCC', '0C'],
['1A', '1B', '1C'],
['2A', '2B', '2C']
];
config = {
columns: {
0: {
paddingLeft: 3
},
1: {
width: 2,
paddingRight: 3
}
}
};
output = table(data, config);
console.log(output);
```
```
╔══════╤══════╤════╗
║ 0A │ AA │ 0C ║
║ │ BB │ ║
║ │ CC │ ║
╟──────┼──────┼────╢
║ 1A │ 1B │ 1C ║
╟──────┼──────┼────╢
║ 2A │ 2B │ 2C ║
╚══════╧══════╧════╝
```
<a name="table-usage-predefined-border-templates"></a>
### Predefined Border Templates
You can load one of the predefined border templates using `getBorderCharacters` function.
```js
import {
table,
getBorderCharacters
} from 'table';
let config,
data;
data = [
['0A', '0B', '0C'],
['1A', '1B', '1C'],
['2A', '2B', '2C']
];
config = {
border: getBorderCharacters(`name of the template`)
};
table(data, config);
```
```
# honeywell
╔════╤════╤════╗
║ 0A │ 0B │ 0C ║
╟────┼────┼────╢
║ 1A │ 1B │ 1C ║
╟────┼────┼────╢
║ 2A │ 2B │ 2C ║
╚════╧════╧════╝
# norc
┌────┬────┬────┐
│ 0A │ 0B │ 0C │
├────┼────┼────┤
│ 1A │ 1B │ 1C │
├────┼────┼────┤
│ 2A │ 2B │ 2C │
└────┴────┴────┘
# ramac (ASCII; for use in terminals that do not support Unicode characters)
+----+----+----+
| 0A | 0B | 0C |
|----|----|----|
| 1A | 1B | 1C |
|----|----|----|
| 2A | 2B | 2C |
+----+----+----+
# void (no borders; see "bordless table" section of the documentation)
0A 0B 0C
1A 1B 1C
2A 2B 2C
```
Raise [an issue](https://github.com/gajus/table/issues) if you'd like to contribute a new border template.
<a name="table-usage-predefined-border-templates-borderless-table"></a>
#### Borderless Table
Simply using "void" border character template creates a table with a lot of unnecessary spacing.
To create a more plesant to the eye table, reset the padding and remove the joining rows, e.g.
```js
let output;
output = table(data, {
border: getBorderCharacters(`void`),
columnDefault: {
paddingLeft: 0,
paddingRight: 1
},
drawJoin: () => {
return false
}
});
console.log(output);
```
```
0A 0B 0C
1A 1B 1C
2A 2B 2C
```
<a name="table-usage-streaming"></a>
### Streaming
`table` package exports `createStream` function used to draw a table and append rows.
`createStream` requires `{number} columnDefault.width` and `{number} columnCount` configuration properties.
```js
import {
createStream
} from 'table';
let config,
stream;
config = {
columnDefault: {
width: 50
},
columnCount: 1
};
stream = createStream(config);
setInterval(() => {
stream.write([new Date()]);
}, 500);
```
![Streaming current date.](./.README/streaming.gif)
`table` package uses ANSI escape codes to overwrite the output of the last line when a new row is printed.
The underlying implementation is explained in this [Stack Overflow answer](http://stackoverflow.com/a/32938658/368691).
Streaming supports all of the configuration properties and functionality of a static table (such as auto text wrapping, alignment and padding), e.g.
```js
import {
createStream
} from 'table';
import _ from 'lodash';
let config,
stream,
i;
config = {
columnDefault: {
width: 50
},
columnCount: 3,
columns: {
0: {
width: 10,
alignment: 'right'
},
1: {
alignment: 'center',
},
2: {
width: 10
}
}
};
stream = createStream(config);
i = 0;
setInterval(() => {
let random;
random = _.sample('abcdefghijklmnopqrstuvwxyz', _.random(1, 30)).join('');
stream.write([i++, new Date(), random]);
}, 500);
```
![Streaming random data.](./.README/streaming-random.gif)
<a name="table-usage-text-truncation"></a>
### Text Truncation
To handle a content that overflows the container width, `table` package implements [text wrapping](#table-usage-text-wrapping). However, sometimes you may want to truncate content that is too long to be displayed in the table.
`{number} config.columns[{number}].truncate` property (default: `Infinity`) truncates the text at the specified length.
```js
let config,
data,
output;
data = [
['Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pulvinar nibh sed mauris convallis dapibus. Nunc venenatis tempus nulla sit amet viverra.']
];
config = {
columns: {
0: {
width: 20,
truncate: 100
}
}
};
output = table(data, config);
console.log(output);
```
```
╔══════════════════════╗
║ Lorem ipsum dolor si ║
║ t amet, consectetur ║
║ adipiscing elit. Pha ║
║ sellus pulvinar nibh ║
║ sed mauris conva... ║
╚══════════════════════╝
```
<a name="table-usage-text-wrapping"></a>
### Text Wrapping
`table` package implements auto text wrapping, i.e. text that has width greater than the container width will be separated into multiple lines, e.g.
```js
let config,
data,
output;
data = [
['Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pulvinar nibh sed mauris convallis dapibus. Nunc venenatis tempus nulla sit amet viverra.']
];
config = {
columns: {
0: {
width: 20
}
}
};
output = table(data, config);
console.log(output);
```
```
╔══════════════════════╗
║ Lorem ipsum dolor si ║
║ t amet, consectetur ║
║ adipiscing elit. Pha ║
║ sellus pulvinar nibh ║
║ sed mauris convallis ║
║ dapibus. Nunc venena ║
║ tis tempus nulla sit ║
║ amet viverra. ║
╚══════════════════════╝
```
When `wrapWord` is `true` the text is broken at the nearest space or one of the special characters ("-", "_", "\", "/", ".", ",", ";"), e.g.
```js
let config,
data,
output;
data = [
['Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pulvinar nibh sed mauris convallis dapibus. Nunc venenatis tempus nulla sit amet viverra.']
];
config = {
columns: {
0: {
width: 20,
wrapWord: true
}
}
};
output = table(data, config);
console.log(output);
```
```
╔══════════════════════╗
║ Lorem ipsum dolor ║
║ sit amet, ║
║ consectetur ║
║ adipiscing elit. ║
║ Phasellus pulvinar ║
║ nibh sed mauris ║
║ convallis dapibus. ║
║ Nunc venenatis ║
║ tempus nulla sit ║
║ amet viverra. ║
╚══════════════════════╝
```
+106
View File
@@ -0,0 +1,106 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _stringWidth = require('string-width');
var _stringWidth2 = _interopRequireDefault(_stringWidth);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const alignments = ['left', 'right', 'center'];
/**
* @param {string} subject
* @param {number} width
* @returns {string}
*/
const alignLeft = (subject, width) => {
return subject + _lodash2.default.repeat(' ', width);
};
/**
* @param {string} subject
* @param {number} width
* @returns {string}
*/
const alignRight = (subject, width) => {
return _lodash2.default.repeat(' ', width) + subject;
};
/**
* @param {string} subject
* @param {number} width
* @returns {string}
*/
const alignCenter = (subject, width) => {
let halfWidth;
halfWidth = width / 2;
if (halfWidth % 2 === 0) {
return _lodash2.default.repeat(' ', halfWidth) + subject + _lodash2.default.repeat(' ', halfWidth);
} else {
halfWidth = _lodash2.default.floor(halfWidth);
return _lodash2.default.repeat(' ', halfWidth) + subject + _lodash2.default.repeat(' ', halfWidth + 1);
}
};
/**
* Pads a string to the left and/or right to position the subject
* text in a desired alignment within a container.
*
* @param {string} subject
* @param {number} containerWidth
* @param {string} alignment One of the valid options (left, right, center).
* @returns {string}
*/
exports.default = (subject, containerWidth, alignment) => {
if (!_lodash2.default.isString(subject)) {
throw new TypeError('Subject parameter value must be a string.');
}
if (!_lodash2.default.isNumber(containerWidth)) {
throw new TypeError('Container width parameter value must be a number.');
}
const subjectWidth = (0, _stringWidth2.default)(subject);
if (subjectWidth > containerWidth) {
// console.log('subjectWidth', subjectWidth, 'containerWidth', containerWidth, 'subject', subject);
throw new Error('Subject parameter value width cannot be greater than the container width.');
}
if (!_lodash2.default.isString(alignment)) {
throw new TypeError('Alignment parameter value must be a string.');
}
if (alignments.indexOf(alignment) === -1) {
throw new Error('Alignment parameter value must be a known alignment parameter value (left, right, center).');
}
if (subjectWidth === 0) {
return _lodash2.default.repeat(' ', containerWidth);
}
const availableWidth = containerWidth - subjectWidth;
if (alignment === 'left') {
return alignLeft(subject, availableWidth);
}
if (alignment === 'right') {
return alignRight(subject, availableWidth);
}
return alignCenter(subject, availableWidth);
};
+34
View File
@@ -0,0 +1,34 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _stringWidth = require('string-width');
var _stringWidth2 = _interopRequireDefault(_stringWidth);
var _alignString = require('./alignString');
var _alignString2 = _interopRequireDefault(_alignString);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @param {table~row[]} rows
* @param {Object} config
* @returns {table~row[]}
*/
exports.default = (rows, config) => {
return rows.map(cells => {
return cells.map((value, index1) => {
const column = config.columns[index1];
if ((0, _stringWidth2.default)(value) === column.width) {
return value;
} else {
return (0, _alignString2.default)(value, column.width, column.alignment);
}
});
});
};
+47
View File
@@ -0,0 +1,47 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _stringWidth = require('string-width');
var _stringWidth2 = _interopRequireDefault(_stringWidth);
var _wrapWord = require('./wrapWord');
var _wrapWord2 = _interopRequireDefault(_wrapWord);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @param {string} value
* @param {number} columnWidth
* @param {boolean} useWrapWord
* @returns {number}
*/
exports.default = function (value, columnWidth) {
let useWrapWord = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
if (!_lodash2.default.isString(value)) {
throw new TypeError('Value must be a string.');
}
if (!_lodash2.default.isInteger(columnWidth)) {
throw new TypeError('Column width must be an integer.');
}
if (columnWidth < 1) {
throw new Error('Column width must be greater than 0.');
}
if (useWrapWord) {
return (0, _wrapWord2.default)(value, columnWidth).length;
}
return _lodash2.default.ceil((0, _stringWidth2.default)(value) / columnWidth);
};
+23
View File
@@ -0,0 +1,23 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _stringWidth = require('string-width');
var _stringWidth2 = _interopRequireDefault(_stringWidth);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Calculates width of each cell contents.
*
* @param {string[]} cells
* @returns {number[]}
*/
exports.default = cells => {
return cells.map(value => {
return (0, _stringWidth2.default)(value);
});
};
+41
View File
@@ -0,0 +1,41 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _calculateCellWidthIndex = require('./calculateCellWidthIndex');
var _calculateCellWidthIndex2 = _interopRequireDefault(_calculateCellWidthIndex);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Produces an array of values that describe the largest value length (width) in every column.
*
* @param {Array[]} rows
* @returns {number[]}
*/
exports.default = rows => {
if (!rows[0]) {
throw new Error('Dataset must have at least one row.');
}
const columns = _lodash2.default.fill(Array(rows[0].length), 0);
_lodash2.default.forEach(rows, row => {
const columnWidthIndex = (0, _calculateCellWidthIndex2.default)(row);
_lodash2.default.forEach(columnWidthIndex, (valueWidth, index0) => {
if (columns[index0] < valueWidth) {
columns[index0] = valueWidth;
}
});
});
return columns;
};
+48
View File
@@ -0,0 +1,48 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _calculateCellHeight = require('./calculateCellHeight');
var _calculateCellHeight2 = _interopRequireDefault(_calculateCellHeight);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Calculates the vertical row span index.
*
* @param {Array[]} rows
* @param {Object} config
* @returns {number[]}
*/
exports.default = (rows, config) => {
const tableWidth = rows[0].length;
const rowSpanIndex = [];
_lodash2.default.forEach(rows, cells => {
const cellHeightIndex = _lodash2.default.fill(Array(tableWidth), 1);
_lodash2.default.forEach(cells, (value, index1) => {
if (!_lodash2.default.isNumber(config.columns[index1].width)) {
throw new TypeError('column[index].width must be a number.');
}
if (!_lodash2.default.isBoolean(config.columns[index1].wrapWord)) {
throw new TypeError('column[index].wrapWord must be a boolean.');
}
cellHeightIndex[index1] = (0, _calculateCellHeight2.default)(value, config.columns[index1].width, config.columns[index1].wrapWord);
});
rowSpanIndex.push(_lodash2.default.max(cellHeightIndex));
});
return rowSpanIndex;
};
+157
View File
@@ -0,0 +1,157 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _makeStreamConfig = require('./makeStreamConfig');
var _makeStreamConfig2 = _interopRequireDefault(_makeStreamConfig);
var _drawRow = require('./drawRow');
var _drawRow2 = _interopRequireDefault(_drawRow);
var _drawBorder = require('./drawBorder');
var _stringifyTableData = require('./stringifyTableData');
var _stringifyTableData2 = _interopRequireDefault(_stringifyTableData);
var _truncateTableData = require('./truncateTableData');
var _truncateTableData2 = _interopRequireDefault(_truncateTableData);
var _mapDataUsingRowHeightIndex = require('./mapDataUsingRowHeightIndex');
var _mapDataUsingRowHeightIndex2 = _interopRequireDefault(_mapDataUsingRowHeightIndex);
var _alignTableData = require('./alignTableData');
var _alignTableData2 = _interopRequireDefault(_alignTableData);
var _padTableData = require('./padTableData');
var _padTableData2 = _interopRequireDefault(_padTableData);
var _calculateRowHeightIndex = require('./calculateRowHeightIndex');
var _calculateRowHeightIndex2 = _interopRequireDefault(_calculateRowHeightIndex);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @param {Array} data
* @param {Object} config
* @returns {Array}
*/
const prepareData = (data, config) => {
let rows;
rows = (0, _stringifyTableData2.default)(data);
rows = (0, _truncateTableData2.default)(data, config);
const rowHeightIndex = (0, _calculateRowHeightIndex2.default)(rows, config);
rows = (0, _mapDataUsingRowHeightIndex2.default)(rows, rowHeightIndex, config);
rows = (0, _alignTableData2.default)(rows, config);
rows = (0, _padTableData2.default)(rows, config);
return rows;
};
/**
* @param {string[]} row
* @param {number[]} columnWidthIndex
* @param {Object} config
* @returns {undefined}
*/
const create = (row, columnWidthIndex, config) => {
const rows = prepareData([row], config);
const body = _lodash2.default.map(rows, literalRow => {
return (0, _drawRow2.default)(literalRow, config.border);
}).join('');
let output;
output = '';
output += (0, _drawBorder.drawBorderTop)(columnWidthIndex, config.border);
output += body;
output += (0, _drawBorder.drawBorderBottom)(columnWidthIndex, config.border);
output = _lodash2.default.trimEnd(output);
process.stdout.write(output);
};
/**
* @param {string[]} row
* @param {number[]} columnWidthIndex
* @param {Object} config
* @returns {undefined}
*/
const append = (row, columnWidthIndex, config) => {
const rows = prepareData([row], config);
const body = _lodash2.default.map(rows, literalRow => {
return (0, _drawRow2.default)(literalRow, config.border);
}).join('');
let output;
output = '\r\u001B[K';
output += (0, _drawBorder.drawBorderJoin)(columnWidthIndex, config.border);
output += body;
output += (0, _drawBorder.drawBorderBottom)(columnWidthIndex, config.border);
output = _lodash2.default.trimEnd(output);
process.stdout.write(output);
};
/**
* @param {Object} userConfig
* @returns {Object}
*/
exports.default = function () {
let userConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
const config = (0, _makeStreamConfig2.default)(userConfig);
const columnWidthIndex = _lodash2.default.mapValues(config.columns, column => {
return column.width + column.paddingLeft + column.paddingRight;
});
let empty;
empty = true;
return {
/**
* @param {string[]} row
* @returns {undefined}
*/
write: row => {
if (row.length !== config.columnCount) {
throw new Error('Row cell count does not match the config.columnCount.');
}
if (empty) {
empty = false;
return create(row, columnWidthIndex, config);
} else {
return append(row, columnWidthIndex, config);
}
}
};
};
+104
View File
@@ -0,0 +1,104 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.drawBorderTop = exports.drawBorderJoin = exports.drawBorderBottom = exports.drawBorder = undefined;
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @typedef drawBorder~parts
* @property {string} left
* @property {string} right
* @property {string} body
* @property {string} join
*/
/**
* @param {number[]} columnSizeIndex
* @param {drawBorder~parts} parts
* @returns {string}
*/
const drawBorder = (columnSizeIndex, parts) => {
const columns = _lodash2.default.map(columnSizeIndex, size => {
return _lodash2.default.repeat(parts.body, size);
}).join(parts.join);
return parts.left + columns + parts.right + '\n';
};
/**
* @typedef drawBorderTop~parts
* @property {string} topLeft
* @property {string} topRight
* @property {string} topBody
* @property {string} topJoin
*/
/**
* @param {number[]} columnSizeIndex
* @param {drawBorderTop~parts} parts
* @returns {string}
*/
const drawBorderTop = (columnSizeIndex, parts) => {
return drawBorder(columnSizeIndex, {
body: parts.topBody,
join: parts.topJoin,
left: parts.topLeft,
right: parts.topRight
});
};
/**
* @typedef drawBorderJoin~parts
* @property {string} joinLeft
* @property {string} joinRight
* @property {string} joinBody
* @property {string} joinJoin
*/
/**
* @param {number[]} columnSizeIndex
* @param {drawBorderJoin~parts} parts
* @returns {string}
*/
const drawBorderJoin = (columnSizeIndex, parts) => {
return drawBorder(columnSizeIndex, {
body: parts.joinBody,
join: parts.joinJoin,
left: parts.joinLeft,
right: parts.joinRight
});
};
/**
* @typedef drawBorderBottom~parts
* @property {string} topLeft
* @property {string} topRight
* @property {string} topBody
* @property {string} topJoin
*/
/**
* @param {number[]} columnSizeIndex
* @param {drawBorderBottom~parts} parts
* @returns {string}
*/
const drawBorderBottom = (columnSizeIndex, parts) => {
return drawBorder(columnSizeIndex, {
body: parts.bottomBody,
join: parts.bottomJoin,
left: parts.bottomLeft,
right: parts.bottomRight
});
};
exports.drawBorder = drawBorder;
exports.drawBorderBottom = drawBorderBottom;
exports.drawBorderJoin = drawBorderJoin;
exports.drawBorderTop = drawBorderTop;
+21
View File
@@ -0,0 +1,21 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
/**
* @typedef {Object} drawRow~border
* @property {string} bodyLeft
* @property {string} bodyRight
* @property {string} bodyJoin
*/
/**
* @param {number[]} columns
* @param {drawRow~border} border
* @returns {string}
*/
exports.default = (columns, border) => {
return border.bodyLeft + columns.join(border.bodyJoin) + border.bodyRight + '\n';
};
+63
View File
@@ -0,0 +1,63 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _drawBorder = require('./drawBorder');
var _drawRow = require('./drawRow');
var _drawRow2 = _interopRequireDefault(_drawRow);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @param {Array} rows
* @param {Object} border
* @param {Array} columnSizeIndex
* @param {Array} rowSpanIndex
* @param {Function} drawHorizontalLine
* @returns {string}
*/
exports.default = (rows, border, columnSizeIndex, rowSpanIndex, drawHorizontalLine) => {
let output;
let realRowIndex;
let rowHeight;
const rowCount = rows.length;
realRowIndex = 0;
output = '';
if (drawHorizontalLine(realRowIndex, rowCount)) {
output += (0, _drawBorder.drawBorderTop)(columnSizeIndex, border);
}
_lodash2.default.forEach(rows, (row, index0) => {
output += (0, _drawRow2.default)(row, border);
if (!rowHeight) {
rowHeight = rowSpanIndex[realRowIndex];
realRowIndex++;
}
rowHeight--;
if (rowHeight === 0 && index0 !== rowCount - 1 && drawHorizontalLine(realRowIndex, rowCount)) {
output += (0, _drawBorder.drawBorderJoin)(columnSizeIndex, border);
}
});
if (drawHorizontalLine(realRowIndex, rowCount)) {
output += (0, _drawBorder.drawBorderBottom)(columnSizeIndex, border);
}
return output;
};
+126
View File
@@ -0,0 +1,126 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
/* eslint-disable sort-keys */
/**
* @typedef border
* @property {string} topBody
* @property {string} topJoin
* @property {string} topLeft
* @property {string} topRight
* @property {string} bottomBody
* @property {string} bottomJoin
* @property {string} bottomLeft
* @property {string} bottomRight
* @property {string} bodyLeft
* @property {string} bodyRight
* @property {string} bodyJoin
* @property {string} joinBody
* @property {string} joinLeft
* @property {string} joinRight
* @property {string} joinJoin
*/
/**
* @param {string} name
* @returns {border}
*/
exports.default = name => {
if (name === 'honeywell') {
return {
topBody: '═',
topJoin: '╤',
topLeft: '╔',
topRight: '╗',
bottomBody: '═',
bottomJoin: '╧',
bottomLeft: '╚',
bottomRight: '╝',
bodyLeft: '║',
bodyRight: '║',
bodyJoin: '│',
joinBody: '─',
joinLeft: '╟',
joinRight: '╢',
joinJoin: '┼'
};
}
if (name === 'norc') {
return {
topBody: '─',
topJoin: '┬',
topLeft: '┌',
topRight: '┐',
bottomBody: '─',
bottomJoin: '┴',
bottomLeft: '└',
bottomRight: '┘',
bodyLeft: '│',
bodyRight: '│',
bodyJoin: '│',
joinBody: '─',
joinLeft: '├',
joinRight: '┤',
joinJoin: '┼'
};
}
if (name === 'ramac') {
return {
topBody: '-',
topJoin: '+',
topLeft: '+',
topRight: '+',
bottomBody: '-',
bottomJoin: '+',
bottomLeft: '+',
bottomRight: '+',
bodyLeft: '|',
bodyRight: '|',
bodyJoin: '|',
joinBody: '-',
joinLeft: '|',
joinRight: '|',
joinJoin: '|'
};
}
if (name === 'void') {
return {
topBody: '',
topJoin: '',
topLeft: '',
topRight: '',
bottomBody: '',
bottomJoin: '',
bottomLeft: '',
bottomRight: '',
bodyLeft: '',
bodyRight: '',
bodyJoin: '',
joinBody: '',
joinLeft: '',
joinRight: '',
joinJoin: ''
};
}
throw new Error('Unknown border template "' + name + '".');
};
+24
View File
@@ -0,0 +1,24 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getBorderCharacters = exports.createStream = exports.table = undefined;
var _table = require('./table');
var _table2 = _interopRequireDefault(_table);
var _createStream = require('./createStream');
var _createStream2 = _interopRequireDefault(_createStream);
var _getBorderCharacters = require('./getBorderCharacters');
var _getBorderCharacters2 = _interopRequireDefault(_getBorderCharacters);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.table = _table2.default;
exports.createStream = _createStream2.default;
exports.getBorderCharacters = _getBorderCharacters2.default;
+99
View File
@@ -0,0 +1,99 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _getBorderCharacters = require('./getBorderCharacters');
var _getBorderCharacters2 = _interopRequireDefault(_getBorderCharacters);
var _validateConfig = require('./validateConfig');
var _validateConfig2 = _interopRequireDefault(_validateConfig);
var _calculateMaximumColumnWidthIndex = require('./calculateMaximumColumnWidthIndex');
var _calculateMaximumColumnWidthIndex2 = _interopRequireDefault(_calculateMaximumColumnWidthIndex);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Merges user provided border characters with the default border ("honeywell") characters.
*
* @param {Object} border
* @returns {Object}
*/
const makeBorder = function makeBorder() {
let border = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return Object.assign({}, (0, _getBorderCharacters2.default)('honeywell'), border);
};
/**
* Creates a configuration for every column using default
* values for the missing configuration properties.
*
* @param {Array[]} rows
* @param {Object} columns
* @param {Object} columnDefault
* @returns {Object}
*/
const makeColumns = function makeColumns(rows) {
let columns = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
let columnDefault = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
const maximumColumnWidthIndex = (0, _calculateMaximumColumnWidthIndex2.default)(rows);
_lodash2.default.times(rows[0].length, index => {
if (_lodash2.default.isUndefined(columns[index])) {
columns[index] = {};
}
columns[index] = _lodash2.default.assign({
alignment: 'left',
paddingLeft: 1,
paddingRight: 1,
truncate: Infinity,
width: maximumColumnWidthIndex[index],
wrapWord: false
}, columnDefault, columns[index]);
});
return columns;
};
/**
* Makes a new configuration object out of the userConfig object
* using default values for the missing configuration properties.
*
* @param {Array[]} rows
* @param {Object} userConfig
* @returns {Object}
*/
exports.default = function (rows) {
let userConfig = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
(0, _validateConfig2.default)('config.json', userConfig);
const config = _lodash2.default.cloneDeep(userConfig);
config.border = makeBorder(config.border);
config.columns = makeColumns(rows, config.columns, config.columnDefault);
if (!config.drawHorizontalLine) {
/**
* @returns {boolean}
*/
config.drawHorizontalLine = () => {
return true;
};
}
return config;
};
+107
View File
@@ -0,0 +1,107 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _getBorderCharacters = require('./getBorderCharacters');
var _getBorderCharacters2 = _interopRequireDefault(_getBorderCharacters);
var _validateConfig = require('./validateConfig');
var _validateConfig2 = _interopRequireDefault(_validateConfig);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Merges user provided border characters with the default border ("honeywell") characters.
*
* @param {Object} border
* @returns {Object}
*/
const makeBorder = function makeBorder() {
let border = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return Object.assign({}, (0, _getBorderCharacters2.default)('honeywell'), border);
};
/**
* Creates a configuration for every column using default
* values for the missing configuration properties.
*
* @param {number} columnCount
* @param {Object} columns
* @param {Object} columnDefault
* @returns {Object}
*/
const makeColumns = function makeColumns(columnCount) {
let columns = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
let columnDefault = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
_lodash2.default.times(columnCount, index => {
if (_lodash2.default.isUndefined(columns[index])) {
columns[index] = {};
}
columns[index] = Object.assign({
alignment: 'left',
paddingLeft: 1,
paddingRight: 1,
truncate: Infinity,
wrapWord: false
}, columnDefault, columns[index]);
});
return columns;
};
/**
* @typedef {Object} columnConfig
* @property {string} alignment
* @property {number} width
* @property {number} truncate
* @property {number} paddingLeft
* @property {number} paddingRight
*/
/**
* @typedef {Object} streamConfig
* @property {columnConfig} columnDefault
* @property {Object} border
* @property {columnConfig[]}
* @property {number} columnCount Number of columns in the table (required).
*/
/**
* Makes a new configuration object out of the userConfig object
* using default values for the missing configuration properties.
*
* @param {streamConfig} userConfig
* @returns {Object}
*/
exports.default = function () {
let userConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
(0, _validateConfig2.default)('streamConfig.json', userConfig);
const config = _lodash2.default.cloneDeep(userConfig);
if (!config.columnDefault || !config.columnDefault.width) {
throw new Error('Must provide config.columnDefault.width when creating a stream.');
}
if (!config.columnCount) {
throw new Error('Must provide config.columnCount.');
}
config.border = makeBorder(config.border);
config.columns = makeColumns(config.columnCount, config.columns, config.columnDefault);
return config;
};
+57
View File
@@ -0,0 +1,57 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _wrapString = require('./wrapString');
var _wrapString2 = _interopRequireDefault(_wrapString);
var _wrapWord = require('./wrapWord');
var _wrapWord2 = _interopRequireDefault(_wrapWord);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @param {Array} unmappedRows
* @param {number[]} rowHeightIndex
* @param {Object} config
* @returns {Array}
*/
exports.default = (unmappedRows, rowHeightIndex, config) => {
const tableWidth = unmappedRows[0].length;
const mappedRows = unmappedRows.map((cells, index0) => {
const rowHeight = _lodash2.default.times(rowHeightIndex[index0], () => {
return _lodash2.default.fill(Array(tableWidth), '');
});
// rowHeight
// [{row index within rowSaw; index2}]
// [{cell index within a virtual row; index1}]
_lodash2.default.forEach(cells, (value, index1) => {
let chunkedValue;
if (config.columns[index1].wrapWord) {
chunkedValue = (0, _wrapWord2.default)(value, config.columns[index1].width);
} else {
chunkedValue = (0, _wrapString2.default)(value, config.columns[index1].width);
}
_lodash2.default.forEach(chunkedValue, (part, index2) => {
rowHeight[index2][index1] = part;
});
});
return rowHeight;
});
return _lodash2.default.flatten(mappedRows);
};
+26
View File
@@ -0,0 +1,26 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @param {table~row[]} rows
* @param {Object} config
* @returns {table~row[]}
*/
exports.default = (rows, config) => {
return _lodash2.default.map(rows, cells => {
return _lodash2.default.map(cells, (value, index1) => {
const column = config.columns[index1];
return _lodash2.default.repeat(' ', column.paddingLeft) + value + _lodash2.default.repeat(' ', column.paddingRight);
});
});
};
+114
View File
@@ -0,0 +1,114 @@
{
"$id": "config.json",
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"properties": {
"border": {
"$ref": "#/definitions/borders"
},
"columns": {
"$ref": "#/definitions/columns"
},
"columnDefault": {
"$ref": "#/definitions/column"
},
"drawHorizontalLine": {
"typeof": "function"
}
},
"additionalProperties": false,
"definitions": {
"columns": {
"type": "object",
"patternProperties": {
"^[0-9]+$": {
"$ref": "#/definitions/column"
}
},
"additionalProperties": false
},
"column": {
"type": "object",
"properties": {
"alignment": {
"type": "string",
"enum": [
"left",
"right",
"center"
]
},
"width": {
"type": "number"
},
"wrapWord": {
"type": "boolean"
},
"truncate": {
"type": "number"
},
"paddingLeft": {
"type": "number"
},
"paddingRight": {
"type": "number"
}
},
"additionalProperties": false
},
"borders": {
"type": "object",
"properties": {
"topBody": {
"$ref": "#/definitions/border"
},
"topJoin": {
"$ref": "#/definitions/border"
},
"topLeft": {
"$ref": "#/definitions/border"
},
"topRight": {
"$ref": "#/definitions/border"
},
"bottomBody": {
"$ref": "#/definitions/border"
},
"bottomJoin": {
"$ref": "#/definitions/border"
},
"bottomLeft": {
"$ref": "#/definitions/border"
},
"bottomRight": {
"$ref": "#/definitions/border"
},
"bodyLeft": {
"$ref": "#/definitions/border"
},
"bodyRight": {
"$ref": "#/definitions/border"
},
"bodyJoin": {
"$ref": "#/definitions/border"
},
"joinBody": {
"$ref": "#/definitions/border"
},
"joinLeft": {
"$ref": "#/definitions/border"
},
"joinRight": {
"$ref": "#/definitions/border"
},
"joinJoin": {
"$ref": "#/definitions/border"
}
},
"additionalProperties": false
},
"border": {
"type": "string"
}
}
}
+114
View File
@@ -0,0 +1,114 @@
{
"$id": "streamConfig.json",
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"properties": {
"border": {
"$ref": "#/definitions/borders"
},
"columns": {
"$ref": "#/definitions/columns"
},
"columnDefault": {
"$ref": "#/definitions/column"
},
"columnCount": {
"type": "number"
}
},
"additionalProperties": false,
"definitions": {
"columns": {
"type": "object",
"patternProperties": {
"^[0-9]+$": {
"$ref": "#/definitions/column"
}
},
"additionalProperties": false
},
"column": {
"type": "object",
"properties": {
"alignment": {
"type": "string",
"enum": [
"left",
"right",
"center"
]
},
"width": {
"type": "number"
},
"wrapWord": {
"type": "boolean"
},
"truncate": {
"type": "number"
},
"paddingLeft": {
"type": "number"
},
"paddingRight": {
"type": "number"
}
},
"additionalProperties": false
},
"borders": {
"type": "object",
"properties": {
"topBody": {
"$ref": "#/definitions/border"
},
"topJoin": {
"$ref": "#/definitions/border"
},
"topLeft": {
"$ref": "#/definitions/border"
},
"topRight": {
"$ref": "#/definitions/border"
},
"bottomBody": {
"$ref": "#/definitions/border"
},
"bottomJoin": {
"$ref": "#/definitions/border"
},
"bottomLeft": {
"$ref": "#/definitions/border"
},
"bottomRight": {
"$ref": "#/definitions/border"
},
"bodyLeft": {
"$ref": "#/definitions/border"
},
"bodyRight": {
"$ref": "#/definitions/border"
},
"bodyJoin": {
"$ref": "#/definitions/border"
},
"joinBody": {
"$ref": "#/definitions/border"
},
"joinLeft": {
"$ref": "#/definitions/border"
},
"joinRight": {
"$ref": "#/definitions/border"
},
"joinJoin": {
"$ref": "#/definitions/border"
}
},
"additionalProperties": false
},
"border": {
"type": "string"
}
}
}
+17
View File
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
/**
* Casts all cell values to a string.
*
* @param {table~row[]} rows
* @returns {table~row[]}
*/
exports.default = rows => {
return rows.map(cells => {
return cells.map(String);
});
};
+133
View File
@@ -0,0 +1,133 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _drawTable = require('./drawTable');
var _drawTable2 = _interopRequireDefault(_drawTable);
var _calculateCellWidthIndex = require('./calculateCellWidthIndex');
var _calculateCellWidthIndex2 = _interopRequireDefault(_calculateCellWidthIndex);
var _makeConfig = require('./makeConfig');
var _makeConfig2 = _interopRequireDefault(_makeConfig);
var _calculateRowHeightIndex = require('./calculateRowHeightIndex');
var _calculateRowHeightIndex2 = _interopRequireDefault(_calculateRowHeightIndex);
var _mapDataUsingRowHeightIndex = require('./mapDataUsingRowHeightIndex');
var _mapDataUsingRowHeightIndex2 = _interopRequireDefault(_mapDataUsingRowHeightIndex);
var _alignTableData = require('./alignTableData');
var _alignTableData2 = _interopRequireDefault(_alignTableData);
var _padTableData = require('./padTableData');
var _padTableData2 = _interopRequireDefault(_padTableData);
var _validateTableData = require('./validateTableData');
var _validateTableData2 = _interopRequireDefault(_validateTableData);
var _stringifyTableData = require('./stringifyTableData');
var _stringifyTableData2 = _interopRequireDefault(_stringifyTableData);
var _truncateTableData = require('./truncateTableData');
var _truncateTableData2 = _interopRequireDefault(_truncateTableData);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @typedef {string} table~cell
*/
/**
* @typedef {table~cell[]} table~row
*/
/**
* @typedef {Object} table~columns
* @property {string} alignment Cell content alignment (enum: left, center, right) (default: left).
* @property {number} width Column width (default: auto).
* @property {number} truncate Number of characters are which the content will be truncated (default: Infinity).
* @property {number} paddingLeft Cell content padding width left (default: 1).
* @property {number} paddingRight Cell content padding width right (default: 1).
*/
/**
* @typedef {Object} table~border
* @property {string} topBody
* @property {string} topJoin
* @property {string} topLeft
* @property {string} topRight
* @property {string} bottomBody
* @property {string} bottomJoin
* @property {string} bottomLeft
* @property {string} bottomRight
* @property {string} bodyLeft
* @property {string} bodyRight
* @property {string} bodyJoin
* @property {string} joinBody
* @property {string} joinLeft
* @property {string} joinRight
* @property {string} joinJoin
*/
/**
* Used to tell whether to draw a horizontal line.
* This callback is called for each non-content line of the table.
* The default behavior is to always return true.
*
* @typedef {Function} drawHorizontalLine
* @param {number} index
* @param {number} size
* @returns {boolean}
*/
/**
* @typedef {Object} table~config
* @property {table~border} border
* @property {table~columns[]} columns Column specific configuration.
* @property {table~columns} columnDefault Default values for all columns. Column specific settings overwrite the default values.
* @property {table~drawHorizontalLine} drawHorizontalLine
*/
/**
* Generates a text table.
*
* @param {table~row[]} data
* @param {table~config} userConfig
* @returns {string}
*/
exports.default = function (data) {
let userConfig = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
let rows;
(0, _validateTableData2.default)(data);
rows = (0, _stringifyTableData2.default)(data);
const config = (0, _makeConfig2.default)(rows, userConfig);
rows = (0, _truncateTableData2.default)(data, config);
const rowHeightIndex = (0, _calculateRowHeightIndex2.default)(rows, config);
rows = (0, _mapDataUsingRowHeightIndex2.default)(rows, rowHeightIndex, config);
rows = (0, _alignTableData2.default)(rows, config);
rows = (0, _padTableData2.default)(rows, config);
const cellWidthIndex = (0, _calculateCellWidthIndex2.default)(rows[0]);
return (0, _drawTable2.default)(rows, config.border, cellWidthIndex, rowHeightIndex, config.drawHorizontalLine);
};
+27
View File
@@ -0,0 +1,27 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @todo Make it work with ASCII content.
* @param {table~row[]} rows
* @param {Object} config
* @returns {table~row[]}
*/
exports.default = (rows, config) => {
return _lodash2.default.map(rows, cells => {
return _lodash2.default.map(cells, (content, index) => {
return _lodash2.default.truncate(content, {
length: config.columns[index].truncate
});
});
});
};
+753
View File
@@ -0,0 +1,753 @@
'use strict';
var equal = require('ajv/lib/compile/equal');
var validate = (function() {
var pattern0 = new RegExp('^[0-9]+$');
var refVal = [];
var refVal1 = (function() {
var pattern0 = new RegExp('^[0-9]+$');
return function validate(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict';
var vErrors = null;
var errors = 0;
if (rootData === undefined) rootData = data;
if ((data && typeof data === "object" && !Array.isArray(data))) {
var errs__0 = errors;
var valid1 = true;
for (var key0 in data) {
var isAdditional0 = !(false || validate.schema.properties[key0]);
if (isAdditional0) {
valid1 = false;
var err = {
keyword: 'additionalProperties',
dataPath: (dataPath || '') + "",
schemaPath: '#/additionalProperties',
params: {
additionalProperty: '' + key0 + ''
},
message: 'should NOT have additional properties'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
}
if (data.topBody !== undefined) {
var errs_1 = errors;
if (!refVal2(data.topBody, (dataPath || '') + '.topBody', data, 'topBody', rootData)) {
if (vErrors === null) vErrors = refVal2.errors;
else vErrors = vErrors.concat(refVal2.errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.topJoin !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.topJoin, (dataPath || '') + '.topJoin', data, 'topJoin', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.topLeft !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.topLeft, (dataPath || '') + '.topLeft', data, 'topLeft', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.topRight !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.topRight, (dataPath || '') + '.topRight', data, 'topRight', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bottomBody !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bottomBody, (dataPath || '') + '.bottomBody', data, 'bottomBody', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bottomJoin !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bottomJoin, (dataPath || '') + '.bottomJoin', data, 'bottomJoin', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bottomLeft !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bottomLeft, (dataPath || '') + '.bottomLeft', data, 'bottomLeft', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bottomRight !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bottomRight, (dataPath || '') + '.bottomRight', data, 'bottomRight', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bodyLeft !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bodyLeft, (dataPath || '') + '.bodyLeft', data, 'bodyLeft', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bodyRight !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bodyRight, (dataPath || '') + '.bodyRight', data, 'bodyRight', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bodyJoin !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bodyJoin, (dataPath || '') + '.bodyJoin', data, 'bodyJoin', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.joinBody !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.joinBody, (dataPath || '') + '.joinBody', data, 'joinBody', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.joinLeft !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.joinLeft, (dataPath || '') + '.joinLeft', data, 'joinLeft', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.joinRight !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.joinRight, (dataPath || '') + '.joinRight', data, 'joinRight', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.joinJoin !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.joinJoin, (dataPath || '') + '.joinJoin', data, 'joinJoin', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
} else {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + "",
schemaPath: '#/type',
params: {
type: 'object'
},
message: 'should be object'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
validate.errors = vErrors;
return errors === 0;
};
})();
refVal1.schema = {
"type": "object",
"properties": {
"topBody": {
"$ref": "#/definitions/border"
},
"topJoin": {
"$ref": "#/definitions/border"
},
"topLeft": {
"$ref": "#/definitions/border"
},
"topRight": {
"$ref": "#/definitions/border"
},
"bottomBody": {
"$ref": "#/definitions/border"
},
"bottomJoin": {
"$ref": "#/definitions/border"
},
"bottomLeft": {
"$ref": "#/definitions/border"
},
"bottomRight": {
"$ref": "#/definitions/border"
},
"bodyLeft": {
"$ref": "#/definitions/border"
},
"bodyRight": {
"$ref": "#/definitions/border"
},
"bodyJoin": {
"$ref": "#/definitions/border"
},
"joinBody": {
"$ref": "#/definitions/border"
},
"joinLeft": {
"$ref": "#/definitions/border"
},
"joinRight": {
"$ref": "#/definitions/border"
},
"joinJoin": {
"$ref": "#/definitions/border"
}
},
"additionalProperties": false
};
refVal1.errors = null;
refVal[1] = refVal1;
var refVal2 = (function() {
var pattern0 = new RegExp('^[0-9]+$');
return function validate(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict';
var vErrors = null;
var errors = 0;
if (typeof data !== "string") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + "",
schemaPath: '#/type',
params: {
type: 'string'
},
message: 'should be string'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
validate.errors = vErrors;
return errors === 0;
};
})();
refVal2.schema = {
"type": "string"
};
refVal2.errors = null;
refVal[2] = refVal2;
var refVal3 = (function() {
var pattern0 = new RegExp('^[0-9]+$');
return function validate(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict';
var vErrors = null;
var errors = 0;
if (rootData === undefined) rootData = data;
if ((data && typeof data === "object" && !Array.isArray(data))) {
var errs__0 = errors;
var valid1 = true;
for (var key0 in data) {
var isAdditional0 = !(false || pattern0.test(key0));
if (isAdditional0) {
valid1 = false;
var err = {
keyword: 'additionalProperties',
dataPath: (dataPath || '') + "",
schemaPath: '#/additionalProperties',
params: {
additionalProperty: '' + key0 + ''
},
message: 'should NOT have additional properties'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
}
for (var key0 in data) {
if (pattern0.test(key0)) {
var errs_1 = errors;
if (!refVal4(data[key0], (dataPath || '') + '[\'' + key0 + '\']', data, key0, rootData)) {
if (vErrors === null) vErrors = refVal4.errors;
else vErrors = vErrors.concat(refVal4.errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
}
} else {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + "",
schemaPath: '#/type',
params: {
type: 'object'
},
message: 'should be object'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
validate.errors = vErrors;
return errors === 0;
};
})();
refVal3.schema = {
"type": "object",
"patternProperties": {
"^[0-9]+$": {
"$ref": "#/definitions/column"
}
},
"additionalProperties": false
};
refVal3.errors = null;
refVal[3] = refVal3;
var refVal4 = (function() {
var pattern0 = new RegExp('^[0-9]+$');
return function validate(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict';
var vErrors = null;
var errors = 0;
if ((data && typeof data === "object" && !Array.isArray(data))) {
var errs__0 = errors;
var valid1 = true;
for (var key0 in data) {
var isAdditional0 = !(false || validate.schema.properties[key0]);
if (isAdditional0) {
valid1 = false;
var err = {
keyword: 'additionalProperties',
dataPath: (dataPath || '') + "",
schemaPath: '#/additionalProperties',
params: {
additionalProperty: '' + key0 + ''
},
message: 'should NOT have additional properties'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
}
var data1 = data.alignment;
if (data1 !== undefined) {
var errs_1 = errors;
if (typeof data1 !== "string") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.alignment',
schemaPath: '#/properties/alignment/type',
params: {
type: 'string'
},
message: 'should be string'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var schema1 = validate.schema.properties.alignment.enum;
var valid1;
valid1 = false;
for (var i1 = 0; i1 < schema1.length; i1++)
if (equal(data1, schema1[i1])) {
valid1 = true;
break;
}
if (!valid1) {
var err = {
keyword: 'enum',
dataPath: (dataPath || '') + '.alignment',
schemaPath: '#/properties/alignment/enum',
params: {
allowedValues: schema1
},
message: 'should be equal to one of the allowed values'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
if (data.width !== undefined) {
var errs_1 = errors;
if (typeof data.width !== "number") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.width',
schemaPath: '#/properties/width/type',
params: {
type: 'number'
},
message: 'should be number'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
if (data.wrapWord !== undefined) {
var errs_1 = errors;
if (typeof data.wrapWord !== "boolean") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.wrapWord',
schemaPath: '#/properties/wrapWord/type',
params: {
type: 'boolean'
},
message: 'should be boolean'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
if (data.truncate !== undefined) {
var errs_1 = errors;
if (typeof data.truncate !== "number") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.truncate',
schemaPath: '#/properties/truncate/type',
params: {
type: 'number'
},
message: 'should be number'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
if (data.paddingLeft !== undefined) {
var errs_1 = errors;
if (typeof data.paddingLeft !== "number") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.paddingLeft',
schemaPath: '#/properties/paddingLeft/type',
params: {
type: 'number'
},
message: 'should be number'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
if (data.paddingRight !== undefined) {
var errs_1 = errors;
if (typeof data.paddingRight !== "number") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.paddingRight',
schemaPath: '#/properties/paddingRight/type',
params: {
type: 'number'
},
message: 'should be number'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
} else {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + "",
schemaPath: '#/type',
params: {
type: 'object'
},
message: 'should be object'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
validate.errors = vErrors;
return errors === 0;
};
})();
refVal4.schema = {
"type": "object",
"properties": {
"alignment": {
"type": "string",
"enum": ["left", "right", "center"]
},
"width": {
"type": "number"
},
"wrapWord": {
"type": "boolean"
},
"truncate": {
"type": "number"
},
"paddingLeft": {
"type": "number"
},
"paddingRight": {
"type": "number"
}
},
"additionalProperties": false
};
refVal4.errors = null;
refVal[4] = refVal4;
return function validate(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict'; /*# sourceURL=config.json */
var vErrors = null;
var errors = 0;
if (rootData === undefined) rootData = data;
if ((data && typeof data === "object" && !Array.isArray(data))) {
var errs__0 = errors;
var valid1 = true;
for (var key0 in data) {
var isAdditional0 = !(false || key0 == 'border' || key0 == 'columns' || key0 == 'columnDefault' || key0 == 'drawHorizontalLine');
if (isAdditional0) {
valid1 = false;
var err = {
keyword: 'additionalProperties',
dataPath: (dataPath || '') + "",
schemaPath: '#/additionalProperties',
params: {
additionalProperty: '' + key0 + ''
},
message: 'should NOT have additional properties'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
}
if (data.border !== undefined) {
var errs_1 = errors;
if (!refVal1(data.border, (dataPath || '') + '.border', data, 'border', rootData)) {
if (vErrors === null) vErrors = refVal1.errors;
else vErrors = vErrors.concat(refVal1.errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.columns !== undefined) {
var errs_1 = errors;
if (!refVal3(data.columns, (dataPath || '') + '.columns', data, 'columns', rootData)) {
if (vErrors === null) vErrors = refVal3.errors;
else vErrors = vErrors.concat(refVal3.errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.columnDefault !== undefined) {
var errs_1 = errors;
if (!refVal[4](data.columnDefault, (dataPath || '') + '.columnDefault', data, 'columnDefault', rootData)) {
if (vErrors === null) vErrors = refVal[4].errors;
else vErrors = vErrors.concat(refVal[4].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.drawHorizontalLine !== undefined) {
var errs_1 = errors;
var errs__1 = errors;
var valid1;
valid1 = typeof data.drawHorizontalLine == "function";
if (!valid1) {
if (errs__1 == errors) {
var err = {
keyword: 'typeof',
dataPath: (dataPath || '') + '.drawHorizontalLine',
schemaPath: '#/properties/drawHorizontalLine/typeof',
params: {
keyword: 'typeof'
},
message: 'should pass "typeof" keyword validation'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
} else {
for (var i1 = errs__1; i1 < errors; i1++) {
var ruleErr1 = vErrors[i1];
if (ruleErr1.dataPath === undefined) ruleErr1.dataPath = (dataPath || '') + '.drawHorizontalLine';
if (ruleErr1.schemaPath === undefined) {
ruleErr1.schemaPath = "#/properties/drawHorizontalLine/typeof";
}
}
}
}
var valid1 = errors === errs_1;
}
} else {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + "",
schemaPath: '#/type',
params: {
type: 'object'
},
message: 'should be object'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
validate.errors = vErrors;
return errors === 0;
};
})();
validate.schema = {
"$id": "config.json",
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"properties": {
"border": {
"$ref": "#/definitions/borders"
},
"columns": {
"$ref": "#/definitions/columns"
},
"columnDefault": {
"$ref": "#/definitions/column"
},
"drawHorizontalLine": {
"typeof": "function"
}
},
"additionalProperties": false,
"definitions": {
"columns": {
"type": "object",
"patternProperties": {
"^[0-9]+$": {
"$ref": "#/definitions/column"
}
},
"additionalProperties": false
},
"column": {
"type": "object",
"properties": {
"alignment": {
"type": "string",
"enum": ["left", "right", "center"]
},
"width": {
"type": "number"
},
"wrapWord": {
"type": "boolean"
},
"truncate": {
"type": "number"
},
"paddingLeft": {
"type": "number"
},
"paddingRight": {
"type": "number"
}
},
"additionalProperties": false
},
"borders": {
"type": "object",
"properties": {
"topBody": {
"$ref": "#/definitions/border"
},
"topJoin": {
"$ref": "#/definitions/border"
},
"topLeft": {
"$ref": "#/definitions/border"
},
"topRight": {
"$ref": "#/definitions/border"
},
"bottomBody": {
"$ref": "#/definitions/border"
},
"bottomJoin": {
"$ref": "#/definitions/border"
},
"bottomLeft": {
"$ref": "#/definitions/border"
},
"bottomRight": {
"$ref": "#/definitions/border"
},
"bodyLeft": {
"$ref": "#/definitions/border"
},
"bodyRight": {
"$ref": "#/definitions/border"
},
"bodyJoin": {
"$ref": "#/definitions/border"
},
"joinBody": {
"$ref": "#/definitions/border"
},
"joinLeft": {
"$ref": "#/definitions/border"
},
"joinRight": {
"$ref": "#/definitions/border"
},
"joinJoin": {
"$ref": "#/definitions/border"
}
},
"additionalProperties": false
},
"border": {
"type": "string"
}
}
};
validate.errors = null;
module.exports = validate;
+740
View File
@@ -0,0 +1,740 @@
'use strict';
var equal = require('ajv/lib/compile/equal');
var validate = (function() {
var pattern0 = new RegExp('^[0-9]+$');
var refVal = [];
var refVal1 = (function() {
var pattern0 = new RegExp('^[0-9]+$');
return function validate(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict';
var vErrors = null;
var errors = 0;
if (rootData === undefined) rootData = data;
if ((data && typeof data === "object" && !Array.isArray(data))) {
var errs__0 = errors;
var valid1 = true;
for (var key0 in data) {
var isAdditional0 = !(false || validate.schema.properties[key0]);
if (isAdditional0) {
valid1 = false;
var err = {
keyword: 'additionalProperties',
dataPath: (dataPath || '') + "",
schemaPath: '#/additionalProperties',
params: {
additionalProperty: '' + key0 + ''
},
message: 'should NOT have additional properties'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
}
if (data.topBody !== undefined) {
var errs_1 = errors;
if (!refVal2(data.topBody, (dataPath || '') + '.topBody', data, 'topBody', rootData)) {
if (vErrors === null) vErrors = refVal2.errors;
else vErrors = vErrors.concat(refVal2.errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.topJoin !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.topJoin, (dataPath || '') + '.topJoin', data, 'topJoin', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.topLeft !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.topLeft, (dataPath || '') + '.topLeft', data, 'topLeft', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.topRight !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.topRight, (dataPath || '') + '.topRight', data, 'topRight', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bottomBody !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bottomBody, (dataPath || '') + '.bottomBody', data, 'bottomBody', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bottomJoin !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bottomJoin, (dataPath || '') + '.bottomJoin', data, 'bottomJoin', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bottomLeft !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bottomLeft, (dataPath || '') + '.bottomLeft', data, 'bottomLeft', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bottomRight !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bottomRight, (dataPath || '') + '.bottomRight', data, 'bottomRight', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bodyLeft !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bodyLeft, (dataPath || '') + '.bodyLeft', data, 'bodyLeft', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bodyRight !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bodyRight, (dataPath || '') + '.bodyRight', data, 'bodyRight', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.bodyJoin !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.bodyJoin, (dataPath || '') + '.bodyJoin', data, 'bodyJoin', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.joinBody !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.joinBody, (dataPath || '') + '.joinBody', data, 'joinBody', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.joinLeft !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.joinLeft, (dataPath || '') + '.joinLeft', data, 'joinLeft', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.joinRight !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.joinRight, (dataPath || '') + '.joinRight', data, 'joinRight', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.joinJoin !== undefined) {
var errs_1 = errors;
if (!refVal[2](data.joinJoin, (dataPath || '') + '.joinJoin', data, 'joinJoin', rootData)) {
if (vErrors === null) vErrors = refVal[2].errors;
else vErrors = vErrors.concat(refVal[2].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
} else {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + "",
schemaPath: '#/type',
params: {
type: 'object'
},
message: 'should be object'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
validate.errors = vErrors;
return errors === 0;
};
})();
refVal1.schema = {
"type": "object",
"properties": {
"topBody": {
"$ref": "#/definitions/border"
},
"topJoin": {
"$ref": "#/definitions/border"
},
"topLeft": {
"$ref": "#/definitions/border"
},
"topRight": {
"$ref": "#/definitions/border"
},
"bottomBody": {
"$ref": "#/definitions/border"
},
"bottomJoin": {
"$ref": "#/definitions/border"
},
"bottomLeft": {
"$ref": "#/definitions/border"
},
"bottomRight": {
"$ref": "#/definitions/border"
},
"bodyLeft": {
"$ref": "#/definitions/border"
},
"bodyRight": {
"$ref": "#/definitions/border"
},
"bodyJoin": {
"$ref": "#/definitions/border"
},
"joinBody": {
"$ref": "#/definitions/border"
},
"joinLeft": {
"$ref": "#/definitions/border"
},
"joinRight": {
"$ref": "#/definitions/border"
},
"joinJoin": {
"$ref": "#/definitions/border"
}
},
"additionalProperties": false
};
refVal1.errors = null;
refVal[1] = refVal1;
var refVal2 = (function() {
var pattern0 = new RegExp('^[0-9]+$');
return function validate(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict';
var vErrors = null;
var errors = 0;
if (typeof data !== "string") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + "",
schemaPath: '#/type',
params: {
type: 'string'
},
message: 'should be string'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
validate.errors = vErrors;
return errors === 0;
};
})();
refVal2.schema = {
"type": "string"
};
refVal2.errors = null;
refVal[2] = refVal2;
var refVal3 = (function() {
var pattern0 = new RegExp('^[0-9]+$');
return function validate(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict';
var vErrors = null;
var errors = 0;
if (rootData === undefined) rootData = data;
if ((data && typeof data === "object" && !Array.isArray(data))) {
var errs__0 = errors;
var valid1 = true;
for (var key0 in data) {
var isAdditional0 = !(false || pattern0.test(key0));
if (isAdditional0) {
valid1 = false;
var err = {
keyword: 'additionalProperties',
dataPath: (dataPath || '') + "",
schemaPath: '#/additionalProperties',
params: {
additionalProperty: '' + key0 + ''
},
message: 'should NOT have additional properties'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
}
for (var key0 in data) {
if (pattern0.test(key0)) {
var errs_1 = errors;
if (!refVal4(data[key0], (dataPath || '') + '[\'' + key0 + '\']', data, key0, rootData)) {
if (vErrors === null) vErrors = refVal4.errors;
else vErrors = vErrors.concat(refVal4.errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
}
} else {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + "",
schemaPath: '#/type',
params: {
type: 'object'
},
message: 'should be object'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
validate.errors = vErrors;
return errors === 0;
};
})();
refVal3.schema = {
"type": "object",
"patternProperties": {
"^[0-9]+$": {
"$ref": "#/definitions/column"
}
},
"additionalProperties": false
};
refVal3.errors = null;
refVal[3] = refVal3;
var refVal4 = (function() {
var pattern0 = new RegExp('^[0-9]+$');
return function validate(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict';
var vErrors = null;
var errors = 0;
if ((data && typeof data === "object" && !Array.isArray(data))) {
var errs__0 = errors;
var valid1 = true;
for (var key0 in data) {
var isAdditional0 = !(false || validate.schema.properties[key0]);
if (isAdditional0) {
valid1 = false;
var err = {
keyword: 'additionalProperties',
dataPath: (dataPath || '') + "",
schemaPath: '#/additionalProperties',
params: {
additionalProperty: '' + key0 + ''
},
message: 'should NOT have additional properties'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
}
var data1 = data.alignment;
if (data1 !== undefined) {
var errs_1 = errors;
if (typeof data1 !== "string") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.alignment',
schemaPath: '#/properties/alignment/type',
params: {
type: 'string'
},
message: 'should be string'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var schema1 = validate.schema.properties.alignment.enum;
var valid1;
valid1 = false;
for (var i1 = 0; i1 < schema1.length; i1++)
if (equal(data1, schema1[i1])) {
valid1 = true;
break;
}
if (!valid1) {
var err = {
keyword: 'enum',
dataPath: (dataPath || '') + '.alignment',
schemaPath: '#/properties/alignment/enum',
params: {
allowedValues: schema1
},
message: 'should be equal to one of the allowed values'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
if (data.width !== undefined) {
var errs_1 = errors;
if (typeof data.width !== "number") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.width',
schemaPath: '#/properties/width/type',
params: {
type: 'number'
},
message: 'should be number'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
if (data.wrapWord !== undefined) {
var errs_1 = errors;
if (typeof data.wrapWord !== "boolean") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.wrapWord',
schemaPath: '#/properties/wrapWord/type',
params: {
type: 'boolean'
},
message: 'should be boolean'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
if (data.truncate !== undefined) {
var errs_1 = errors;
if (typeof data.truncate !== "number") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.truncate',
schemaPath: '#/properties/truncate/type',
params: {
type: 'number'
},
message: 'should be number'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
if (data.paddingLeft !== undefined) {
var errs_1 = errors;
if (typeof data.paddingLeft !== "number") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.paddingLeft',
schemaPath: '#/properties/paddingLeft/type',
params: {
type: 'number'
},
message: 'should be number'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
if (data.paddingRight !== undefined) {
var errs_1 = errors;
if (typeof data.paddingRight !== "number") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.paddingRight',
schemaPath: '#/properties/paddingRight/type',
params: {
type: 'number'
},
message: 'should be number'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
} else {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + "",
schemaPath: '#/type',
params: {
type: 'object'
},
message: 'should be object'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
validate.errors = vErrors;
return errors === 0;
};
})();
refVal4.schema = {
"type": "object",
"properties": {
"alignment": {
"type": "string",
"enum": ["left", "right", "center"]
},
"width": {
"type": "number"
},
"wrapWord": {
"type": "boolean"
},
"truncate": {
"type": "number"
},
"paddingLeft": {
"type": "number"
},
"paddingRight": {
"type": "number"
}
},
"additionalProperties": false
};
refVal4.errors = null;
refVal[4] = refVal4;
return function validate(data, dataPath, parentData, parentDataProperty, rootData) {
'use strict'; /*# sourceURL=streamConfig.json */
var vErrors = null;
var errors = 0;
if (rootData === undefined) rootData = data;
if ((data && typeof data === "object" && !Array.isArray(data))) {
var errs__0 = errors;
var valid1 = true;
for (var key0 in data) {
var isAdditional0 = !(false || key0 == 'border' || key0 == 'columns' || key0 == 'columnDefault' || key0 == 'columnCount');
if (isAdditional0) {
valid1 = false;
var err = {
keyword: 'additionalProperties',
dataPath: (dataPath || '') + "",
schemaPath: '#/additionalProperties',
params: {
additionalProperty: '' + key0 + ''
},
message: 'should NOT have additional properties'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
}
if (data.border !== undefined) {
var errs_1 = errors;
if (!refVal1(data.border, (dataPath || '') + '.border', data, 'border', rootData)) {
if (vErrors === null) vErrors = refVal1.errors;
else vErrors = vErrors.concat(refVal1.errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.columns !== undefined) {
var errs_1 = errors;
if (!refVal3(data.columns, (dataPath || '') + '.columns', data, 'columns', rootData)) {
if (vErrors === null) vErrors = refVal3.errors;
else vErrors = vErrors.concat(refVal3.errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.columnDefault !== undefined) {
var errs_1 = errors;
if (!refVal[4](data.columnDefault, (dataPath || '') + '.columnDefault', data, 'columnDefault', rootData)) {
if (vErrors === null) vErrors = refVal[4].errors;
else vErrors = vErrors.concat(refVal[4].errors);
errors = vErrors.length;
}
var valid1 = errors === errs_1;
}
if (data.columnCount !== undefined) {
var errs_1 = errors;
if (typeof data.columnCount !== "number") {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + '.columnCount',
schemaPath: '#/properties/columnCount/type',
params: {
type: 'number'
},
message: 'should be number'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
var valid1 = errors === errs_1;
}
} else {
var err = {
keyword: 'type',
dataPath: (dataPath || '') + "",
schemaPath: '#/type',
params: {
type: 'object'
},
message: 'should be object'
};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
}
validate.errors = vErrors;
return errors === 0;
};
})();
validate.schema = {
"$id": "streamConfig.json",
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "object",
"properties": {
"border": {
"$ref": "#/definitions/borders"
},
"columns": {
"$ref": "#/definitions/columns"
},
"columnDefault": {
"$ref": "#/definitions/column"
},
"columnCount": {
"type": "number"
}
},
"additionalProperties": false,
"definitions": {
"columns": {
"type": "object",
"patternProperties": {
"^[0-9]+$": {
"$ref": "#/definitions/column"
}
},
"additionalProperties": false
},
"column": {
"type": "object",
"properties": {
"alignment": {
"type": "string",
"enum": ["left", "right", "center"]
},
"width": {
"type": "number"
},
"wrapWord": {
"type": "boolean"
},
"truncate": {
"type": "number"
},
"paddingLeft": {
"type": "number"
},
"paddingRight": {
"type": "number"
}
},
"additionalProperties": false
},
"borders": {
"type": "object",
"properties": {
"topBody": {
"$ref": "#/definitions/border"
},
"topJoin": {
"$ref": "#/definitions/border"
},
"topLeft": {
"$ref": "#/definitions/border"
},
"topRight": {
"$ref": "#/definitions/border"
},
"bottomBody": {
"$ref": "#/definitions/border"
},
"bottomJoin": {
"$ref": "#/definitions/border"
},
"bottomLeft": {
"$ref": "#/definitions/border"
},
"bottomRight": {
"$ref": "#/definitions/border"
},
"bodyLeft": {
"$ref": "#/definitions/border"
},
"bodyRight": {
"$ref": "#/definitions/border"
},
"bodyJoin": {
"$ref": "#/definitions/border"
},
"joinBody": {
"$ref": "#/definitions/border"
},
"joinLeft": {
"$ref": "#/definitions/border"
},
"joinRight": {
"$ref": "#/definitions/border"
},
"joinJoin": {
"$ref": "#/definitions/border"
}
},
"additionalProperties": false
},
"border": {
"type": "string"
}
}
};
validate.errors = null;
module.exports = validate;
+51
View File
@@ -0,0 +1,51 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
/**
* @typedef {string} cell
*/
/**
* @typedef {cell[]} validateData~column
*/
/**
* @param {column[]} rows
* @returns {undefined}
*/
exports.default = rows => {
if (!Array.isArray(rows)) {
throw new TypeError('Table data must be an array.');
}
if (rows.length === 0) {
throw new Error('Table must define at least one row.');
}
if (rows[0].length === 0) {
throw new Error('Table must define at least one column.');
}
const columnNumber = rows[0].length;
for (const cells of rows) {
if (!Array.isArray(cells)) {
throw new TypeError('Table row data must be an array.');
}
if (cells.length !== columnNumber) {
throw new Error('Table must have a consistent number of cells.');
}
// @todo Make an exception for newline characters.
// @see https://github.com/gajus/table/issues/9
for (const cell of cells) {
if (/[\u0001-\u001A]/.test(cell)) {
throw new Error('Table data must not contain control characters.');
}
}
}
};
+46
View File
@@ -0,0 +1,46 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _sliceAnsi = require('slice-ansi');
var _sliceAnsi2 = _interopRequireDefault(_sliceAnsi);
var _stringWidth = require('string-width');
var _stringWidth2 = _interopRequireDefault(_stringWidth);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Creates an array of strings split into groups the length of size.
* This function works with strings that contain ASCII characters.
*
* wrapText is different from would-be "chunk" implementation
* in that whitespace characters that occur on a chunk size limit are trimmed.
*
* @param {string} subject
* @param {number} size
* @returns {Array}
*/
exports.default = (subject, size) => {
let subjectSlice;
subjectSlice = subject;
const chunks = [];
do {
chunks.push((0, _sliceAnsi2.default)(subjectSlice, 0, size));
subjectSlice = _lodash2.default.trim((0, _sliceAnsi2.default)(subjectSlice, size));
} while ((0, _stringWidth2.default)(subjectSlice));
return chunks;
};
+56
View File
@@ -0,0 +1,56 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _sliceAnsi = require('slice-ansi');
var _sliceAnsi2 = _interopRequireDefault(_sliceAnsi);
var _stringWidth = require('string-width');
var _stringWidth2 = _interopRequireDefault(_stringWidth);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @param {string} input
* @param {number} size
* @returns {Array}
*/
exports.default = (input, size) => {
let subject;
subject = input;
const chunks = [];
// https://regex101.com/r/gY5kZ1/1
const re = new RegExp('(^.{1,' + size + '}(\\s+|$))|(^.{1,' + (size - 1) + '}(\\\\|/|_|\\.|,|;|-))');
do {
let chunk;
chunk = subject.match(re);
if (chunk) {
chunk = chunk[0];
subject = (0, _sliceAnsi2.default)(subject, (0, _stringWidth2.default)(chunk));
chunk = _lodash2.default.trim(chunk);
} else {
chunk = (0, _sliceAnsi2.default)(subject, 0, size);
subject = (0, _sliceAnsi2.default)(subject, size);
}
chunks.push(chunk);
} while ((0, _stringWidth2.default)(subject));
return chunks;
};
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Evgeny Poberezkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+656
View File
@@ -0,0 +1,656 @@
# ajv-keywords
Custom JSON-Schema keywords for [Ajv](https://github.com/epoberezkin/ajv) validator
[![Build Status](https://travis-ci.org/epoberezkin/ajv-keywords.svg?branch=master)](https://travis-ci.org/epoberezkin/ajv-keywords)
[![npm version](https://badge.fury.io/js/ajv-keywords.svg)](https://www.npmjs.com/package/ajv-keywords)
[![npm downloads](https://img.shields.io/npm/dm/ajv-keywords.svg)](https://www.npmjs.com/package/ajv-keywords)
[![Coverage Status](https://coveralls.io/repos/github/epoberezkin/ajv-keywords/badge.svg?branch=master)](https://coveralls.io/github/epoberezkin/ajv-keywords?branch=master)
[![Greenkeeper badge](https://badges.greenkeeper.io/epoberezkin/ajv-keywords.svg)](https://greenkeeper.io/)
[![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv)
## Contents
- [Install](#install)
- [Usage](#usage)
- [Keywords](#keywords)
- [typeof](#typeof)
- [instanceof](#instanceof)
- [range and exclusiveRange](#range-and-exclusiverange)
- [if/then/else](#ifthenelse)
- [switch](#switch)
- [select/selectCases/selectDefault](#selectselectcasesselectdefault) (BETA)
- [patternRequired](#patternrequired)
- [prohibited](#prohibited)
- [deepProperties](#deepproperties)
- [deepRequired](#deeprequired)
- [uniqueItemProperties](#uniqueitemproperties)
- [regexp](#regexp)
- [formatMaximum / formatMinimum and formatExclusiveMaximum / formatExclusiveMinimum](#formatmaximum--formatminimum-and-formatexclusivemaximum--formatexclusiveminimum)
- [dynamicDefaults](#dynamicdefaults)
- [License](#license)
## Install
```
npm install ajv-keywords
```
## Usage
To add all available keywords:
```javascript
var Ajv = require('ajv');
var ajv = new Ajv;
require('ajv-keywords')(ajv);
ajv.validate({ instanceof: 'RegExp' }, /.*/); // true
ajv.validate({ instanceof: 'RegExp' }, '.*'); // false
```
To add a single keyword:
```javascript
require('ajv-keywords')(ajv, 'instanceof');
```
To add multiple keywords:
```javascript
require('ajv-keywords')(ajv, ['typeof', 'instanceof']);
```
To add a single keyword in browser (to avoid adding unused code):
```javascript
require('ajv-keywords/keywords/instanceof')(ajv);
```
## Keywords
### `typeof`
Based on JavaScript `typeof` operation.
The value of the keyword should be a string (`"undefined"`, `"string"`, `"number"`, `"object"`, `"function"`, `"boolean"` or `"symbol"`) or array of strings.
To pass validation the result of `typeof` operation on the value should be equal to the string (or one of the strings in the array).
```
ajv.validate({ typeof: 'undefined' }, undefined); // true
ajv.validate({ typeof: 'undefined' }, null); // false
ajv.validate({ typeof: ['undefined', 'object'] }, null); // true
```
### `instanceof`
Based on JavaScript `instanceof` operation.
The value of the keyword should be a string (`"Object"`, `"Array"`, `"Function"`, `"Number"`, `"String"`, `"Date"`, `"RegExp"` or `"Buffer"`) or array of strings.
To pass validation the result of `data instanceof ...` operation on the value should be true:
```
ajv.validate({ instanceof: 'Array' }, []); // true
ajv.validate({ instanceof: 'Array' }, {}); // false
ajv.validate({ instanceof: ['Array', 'Function'] }, function(){}); // true
```
You can add your own constructor function to be recognised by this keyword:
```javascript
function MyClass() {}
var instanceofDefinition = require('ajv-keywords').get('instanceof').definition;
// or require('ajv-keywords/keywords/instanceof').definition;
instanceofDefinition.CONSTRUCTORS.MyClass = MyClass;
ajv.validate({ instanceof: 'MyClass' }, new MyClass); // true
```
### `range` and `exclusiveRange`
Syntax sugar for the combination of minimum and maximum keywords, also fails schema compilation if there are no numbers in the range.
The value of this keyword must be the array consisting of two numbers, the second must be greater or equal than the first one.
If the validated value is not a number the validation passes, otherwise to pass validation the value should be greater (or equal) than the first number and smaller (or equal) than the second number in the array. If `exclusiveRange` keyword is present in the same schema and its value is true, the validated value must not be equal to the range boundaries.
```javascript
var schema = { range: [1, 3] };
ajv.validate(schema, 1); // true
ajv.validate(schema, 2); // true
ajv.validate(schema, 3); // true
ajv.validate(schema, 0.99); // false
ajv.validate(schema, 3.01); // false
var schema = { range: [1, 3], exclusiveRange: true };
ajv.validate(schema, 1.01); // true
ajv.validate(schema, 2); // true
ajv.validate(schema, 2.99); // true
ajv.validate(schema, 1); // false
ajv.validate(schema, 3); // false
```
### `if`/`then`/`else`
These keywords allow to implement conditional validation. Their values should be valid JSON-schemas.
If the data is valid according to the sub-schema in `if` keyword, then the result is equal to the result of data validation against the sub-schema in `then` keyword, otherwise - in `else` keyword (if `else` is absent, the validation succeeds).
```javascript
require('ajv-keywords')(ajv, 'if');
var schema = {
type: 'array',
items: {
type: 'integer',
minimum: 1,
if: { maximum: 10 },
then: { multipleOf: 2 },
else: { multipleOf: 5 }
}
};
var validItems = [ 2, 4, 6, 8, 10, 15, 20, 25 ]; // etc.
var invalidItems = [ 1, 3, 5, 11, 12 ]; // etc.
ajv.validate(schema, validItems); // true
ajv.validate(schema, invalidItems); // false
```
This keyword is [proposed](https://github.com/json-schema-org/json-schema-spec/issues/180) for the future version of JSON-Schema standard.
### `switch`
This keyword allows to perform advanced conditional validation.
The value of the keyword is the array of if/then clauses. Each clause is the object with the following properties:
- `if` (optional) - the value is JSON-schema
- `then` (required) - the value is JSON-schema or boolean
- `continue` (optional) - the value is boolean
The validation process is dynamic; all clauses are executed sequentially in the following way:
1. `if`:
1. `if` property is JSON-schema according to which the data is:
1. valid => go to step 2.
2. invalid => go to the NEXT clause, if this was the last clause the validation of `switch` SUCCEEDS.
2. `if` property is absent => go to step 2.
2. `then`:
1. `then` property is `true` or it is JSON-schema according to which the data is valid => go to step 3.
2. `then` property is `false` or it is JSON-schema according to which the data is invalid => the validation of `switch` FAILS.
3. `continue`:
1. `continue` property is `true` => go to the NEXT clause, if this was the last clause the validation of `switch` SUCCEEDS.
2. `continue` property is `false` or absent => validation of `switch` SUCCEEDS.
```javascript
require('ajv-keywords')(ajv, 'switch');
var schema = {
type: 'array',
items: {
type: 'integer',
'switch': [
{ if: { not: { minimum: 1 } }, then: false },
{ if: { maximum: 10 }, then: true },
{ if: { maximum: 100 }, then: { multipleOf: 10 } },
{ if: { maximum: 1000 }, then: { multipleOf: 100 } },
{ then: false }
]
}
};
var validItems = [1, 5, 10, 20, 50, 100, 200, 500, 1000];
var invalidItems = [1, 0, 2000, 11, 57, 123, 'foo'];
```
__Please note__: this keyword is moved here from Ajv, mainly to preserve backward compatibility. It is unlikely to become a standard. It's preferable to use `if`/`then`/`else` keywords if possible, as they are likely to be added to the standard. The above schema is equivalent to (for example):
```javascript
{
type: 'array',
items: {
type: 'integer',
if: { minimum: 1, maximum: 10 },
then: true,
else: {
if: { maximum: 100 },
then: { multipleOf: 10 },
else: {
if: { maximum: 1000 },
then: { multipleOf: 100 },
else: false
}
}
}
}
```
### `select`/`selectCases`/`selectDefault`
These keywords allow to choose the schema to validate the data based on the value of some property in the validated data.
These keywords must be present in the same schema object (`selectDefault` is optional).
The value of `select` keyword should be a [$data reference](https://github.com/epoberezkin/ajv/tree/5.0.2-beta.0#data-reference) that points to any primitive JSON type (string, number, boolean or null) in the data that is validated. You can also use a constant of primitive type as the value of this keyword (e.g., for debugging purposes).
The value of `selectCases` keyword must be an object where each property name is a possible string representation of the value of `select` keyword and each property value is a corresponding schema (from draft-06 it can be boolean) that must be used to validate the data.
The value of `selectDefault` keyword is a schema (from draft-06 it can be boolean) that must be used to validate the data in case `selectCases` has no key equal to the stringified value of `select` keyword.
The validation succeeds in one of the following cases:
- the validation of data using selected schema succeeds,
- none of the schemas is selected for validation,
- the value of select is undefined (no property in the data that the data reference points to).
If `select` value (in data) is not a primitive type the validation fails.
__Please note__: these keywords require Ajv `$data` option to support [$data reference](https://github.com/epoberezkin/ajv/tree/5.0.2-beta.0#data-reference).
```javascript
require('ajv-keywords')(ajv, 'select');
var schema = {
type: object,
required: ['kind'],
properties: {
kind: { type: 'string' }
},
select: { $data: '0/kind' },
selectCases: {
foo: {
required: ['foo'],
properties: {
kind: {},
foo: { type: 'string' }
},
additionalProperties: false
},
bar: {
required: ['bar'],
properties: {
kind: {},
bar: { type: 'number' }
},
additionalProperties: false
}
},
selectDefault: {
propertyNames: {
not: { enum: ['foo', 'bar'] }
}
}
};
var validDataList = [
{ kind: 'foo', foo: 'any' },
{ kind: 'bar', bar: 1 },
{ kind: 'anything_else', not_bar_or_foo: 'any value' }
];
var invalidDataList = [
{ kind: 'foo' }, // no propery foo
{ kind: 'bar' }, // no propery bar
{ kind: 'foo', foo: 'any', another: 'any value' }, // additional property
{ kind: 'bar', bar: 1, another: 'any value' }, // additional property
{ kind: 'anything_else', foo: 'any' } // property foo not allowed
{ kind: 'anything_else', bar: 1 } // property bar not allowed
];
```
__Please note__: the current implementation is BETA. It does not allow using relative URIs in $ref keywords in schemas in `selectCases` and `selectDefault` that point outside of these schemas. The workaround is to use absolute URIs (that can point to any (sub-)schema added to Ajv, including those inside the current root schema where `select` is used). See [tests](https://github.com/epoberezkin/ajv-keywords/blob/v2.0.0/spec/tests/select.json#L314).
### `patternRequired`
This keyword allows to require the presence of properties that match some pattern(s).
This keyword applies only to objects. If the data is not an object, the validation succeeds.
The value of this keyword should be an array of strings, each string being a regular expression. For data object to be valid each regular expression in this array should match at least one property name in the data object.
If the array contains multiple regular expressions, more than one expression can match the same property name.
```javascript
var schema = { patternRequired: [ 'f.*o', 'b.*r' ] };
var validData = { foo: 1, bar: 2 };
var alsoValidData = { foobar: 3 };
var invalidDataList = [ {}, { foo: 1 }, { bar: 2 } ];
```
### `prohibited`
This keyword allows to prohibit that any of the properties in the list is present in the object.
This keyword applies only to objects. If the data is not an object, the validation succeeds.
The value of this keyword should be an array of strings, each string being a property name. For data object to be valid none of the properties in this array should be present in the object.
```
var schema = { prohibited: ['foo', 'bar']};
var validData = { baz: 1 };
var alsoValidData = {};
var invalidDataList = [
{ foo: 1 },
{ bar: 2 },
{ foo: 1, bar: 2}
];
```
### `deepProperties`
This keyword allows to validate deep properties (identified by JSON pointers).
This keyword applies only to objects. If the data is not an object, the validation succeeds.
The value should be an object, where keys are JSON pointers to the data, starting from the current position in data, and the values are JSON schemas. For data object to be valid the value of each JSON pointer should be valid according to the corresponding schema.
```javascript
var schema = {
type: 'object',
deepProperties: {
"/users/1/role": { "enum": ["admin"] }
}
};
var validData = {
users: [
{},
{
id: 123,
role: 'admin'
}
]
};
var alsoValidData = {
users: {
"1": {
id: 123,
role: 'admin'
}
}
};
var invalidData = {
users: [
{},
{
id: 123,
role: 'user'
}
]
};
var alsoInvalidData = {
users: {
"1": {
id: 123,
role: 'user'
}
}
};
```
### `deepRequired`
This keyword allows to check that some deep properties (identified by JSON pointers) are available.
This keyword applies only to objects. If the data is not an object, the validation succeeds.
The value should be an array of JSON pointers to the data, starting from the current position in data. For data object to be valid each JSON pointer should be some existing part of the data.
```javascript
var schema = {
type: 'object',
deepRequired: ["/users/1/role"]
};
var validData = {
users: [
{},
{
id: 123,
role: 'admin'
}
]
};
var invalidData = {
users: [
{},
{
id: 123
}
]
};
```
See [json-schema-org/json-schema-spec#203](https://github.com/json-schema-org/json-schema-spec/issues/203#issue-197211916) for an example of the equivalent schema without `deepRequired` keyword.
### `uniqueItemProperties`
The keyword allows to check that some properties in array items are unique.
This keyword applies only to arrays. If the data is not an array, the validation succeeds.
The value of this keyword must be an array of strings - property names that should have unique values across all items.
```javascript
var schema = { uniqueItemProperties: [ "id", "name" ] };
var validData = [
{ id: 1 },
{ id: 2 },
{ id: 3 }
];
var invalidData1 = [
{ id: 1 },
{ id: 1 },
{ id: 3 }
];
var invalidData2 = [
{ id: 1, name: "taco" },
{ id: 2, name: "taco" }, // duplicate "name"
{ id: 3, name: "salsa" }
];
```
This keyword is contributed by [@blainesch](https://github.com/blainesch).
### `regexp`
This keyword allows to use regular expressions with flags in schemas (the standard `pattern` keyword does not support flags).
This keyword applies only to strings. If the data is not a string, the validation succeeds.
The value of this keyword can be either a string (the result of `regexp.toString()`) or an object with the properties `pattern` and `flags` (the same strings that should be passed to RegExp constructor).
```javascript
var schema = {
type: 'object',
properties: {
foo: { regexp: '/foo/i' },
bar: { regexp: { pattern: 'bar', flags: 'i' } }
}
};
var validData = {
foo: 'Food',
bar: 'Barmen'
};
var invalidData = {
foo: 'fog',
bar: 'bad'
};
```
### `formatMaximum` / `formatMinimum` and `formatExclusiveMaximum` / `formatExclusiveMinimum`
These keywords allow to define minimum/maximum constraints when the format keyword defines ordering.
These keywords apply only to strings. If the data is not a string, the validation succeeds.
The value of keyword `formatMaximum` (`formatMinimum`) should be a string. This value is the maximum (minimum) allowed value for the data to be valid as determined by `format` keyword.
When this keyword is added, it defines comparison rules for formats `"date"`, `"time"` and `"date-time". Custom formats also can have comparison rules. See [addFormat](https://github.com/epoberezkin/ajv#api-addformat) method.
The value of keyword `formatExclusiveMaximum` (`formatExclusiveMinimum`) should be a boolean value. These keyword cannot be used without `formatMaximum` (`formatMinimum`). If this keyword value is equal to `true`, the data to be valid should not be equal to the value in `formatMaximum` (`formatMinimum`) keyword.
```javascript
require('ajv-keywords')(ajv, ['formatMinimum', 'formatMaximum']);
var schema = {
format: 'date',
formatMinimum: '2016-02-06',
formatMaximum: '2016-12-27',
formatExclusiveMaximum: true
}
var validDataList = ['2016-02-06', '2016-12-26', 1];
var invalidDataList = ['2016-02-05', '2016-12-27', 'abc'];
```
### `dynamicDefaults`
This keyword allows to assign dynamic defaults to properties, such as timestamps, unique IDs etc.
This keyword only works if `useDefaults` options is used and not inside `anyOf` keywrods etc., in the same way as [default keyword treated by Ajv](https://github.com/epoberezkin/ajv#assigning-defaults).
The keyword should be added on the object level. Its value should be an object with each property corresponding to a property name, in the same way as in standard `properties` keyword. The value of each property can be:
- an identifier of default function (a string)
- an object with properties `func` (an identifier) and `args` (an object with parameters that will be passed to this function during schema compilation - see examples).
The properties used in `dynamicDefaults` should not be added to `required` keyword (or validation will fail), because unlike `default` this keyword is processed after validation.
There are several predefined dynamic default functions:
- `"timestamp"` - current timestamp in milliseconds
- `"datetime"` - current date and time as string (ISO, valid according to `date-time` format)
- `"date"` - current date as string (ISO, valid according to `date` format)
- `"time"` - current time as string (ISO, valid according to `time` format)
- `"random"` - pseudo-random number in [0, 1) interval
- `"randomint"` - pseudo-random integer number. If string is used as a property value, the function will randomly return 0 or 1. If object `{func: 'randomint', max: N}` is used then the default will be an integer number in [0, N) interval.
- `"seq"` - sequential integer number starting from 0. If string is used as a property value, the default sequence will be used. If object `{func: 'seq', name: 'foo'}` is used then the sequence with name `"foo"` will be used. Sequences are global, even if different ajv instances are used.
```javascript
var schema = {
type: 'object',
dynamicDefaults: {
ts: 'datetime',
r: { func: 'randomint', max: 100 },
id: { func: 'seq', name: 'id' }
},
properties: {
ts: {
type: 'string',
format: 'datetime'
},
r: {
type: 'integer',
minimum: 0,
maximum: 100,
exclusiveMaximum: true
},
id: {
type: 'integer',
minimum: 0
}
}
};
var data = {};
ajv.validate(data); // true
data; // { ts: '2016-12-01T22:07:28.829Z', r: 25, id: 0 }
var data1 = {};
ajv.validate(data1); // true
data1; // { ts: '2016-12-01T22:07:29.832Z', r: 68, id: 1 }
ajv.validate(data1); // true
data1; // didn't change, as all properties were defined
```
You can add your own dynamic default function to be recognised by this keyword:
```javascript
var uuid = require('uuid');
function uuidV4() { return uuid.v4(); }
var definition = require('ajv-keywords').get('dynamicDefaults').definition;
// or require('ajv-keywords/keywords/dynamicDefaults').definition;
definition.DEFAULTS.uuid = uuidV4;
var schema = {
dynamicDefaults: { id: 'uuid' },
properties: { id: { type: 'string', format: 'uuid' } }
};
var data = {};
ajv.validate(schema, data); // true
data; // { id: 'a1183fbe-697b-4030-9bcc-cfeb282a9150' };
var data1 = {};
ajv.validate(schema, data1); // true
data1; // { id: '5b008de7-1669-467a-a5c6-70fa244d7209' }
```
You also can define dynamic default that accepts parameters, e.g. version of uuid:
```javascript
var uuid = require('uuid');
function getUuid(args) {
var version = 'v' + (arvs && args.v || 4);
return function() {
return uuid[version]();
};
}
var definition = require('ajv-keywords').get('dynamicDefaults').definition;
definition.DEFAULTS.uuid = getUuid;
var schema = {
dynamicDefaults: {
id1: 'uuid', // v4
id2: { func: 'uuid', v: 4 }, // v4
id3: { func: 'uuid', v: 1 } // v1
}
};
```
## License
[MIT](https://github.com/epoberezkin/ajv-keywords/blob/master/LICENSE)
+35
View File
@@ -0,0 +1,35 @@
'use strict';
var KEYWORDS = require('./keywords');
module.exports = defineKeywords;
/**
* Defines one or several keywords in ajv instance
* @param {Ajv} ajv validator instance
* @param {String|Array<String>|undefined} keyword keyword(s) to define
* @return {Ajv} ajv instance (for chaining)
*/
function defineKeywords(ajv, keyword) {
if (Array.isArray(keyword)) {
for (var i=0; i<keyword.length; i++)
get(keyword[i])(ajv);
return ajv;
}
if (keyword) {
get(keyword)(ajv);
return ajv;
}
for (keyword in KEYWORDS) get(keyword)(ajv);
return ajv;
}
defineKeywords.get = get;
function get(keyword) {
var defFunc = KEYWORDS[keyword];
if (!defFunc) throw new Error('Unknown keyword ' + keyword);
return defFunc;
}
+90
View File
@@ -0,0 +1,90 @@
'use strict';
var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i;
var DATE_TIME_SEPARATOR = /t|\s/i;
var COMPARE_FORMATS = {
date: compareDate,
time: compareTime,
'date-time': compareDateTime
};
module.exports = function (minMax) {
var keyword = 'format' + minMax;
return function defFunc(ajv) {
defFunc.definition = {
type: 'string',
inline: require('./dotjs/_formatLimit'),
statements: true,
errors: 'full',
metaSchema: {
anyOf: [
{ type: 'string' },
{
type: 'object',
required: [ '$data' ],
properties: {
$data: {
type: 'string',
anyOf: [
{ format: 'relative-json-pointer' },
{ format: 'json-pointer' }
]
}
},
additionalProperties: false
}
]
}
};
ajv.addKeyword(keyword, defFunc.definition);
ajv.addKeyword('formatExclusive' + minMax);
extendFormats(ajv);
return ajv;
};
};
function extendFormats(ajv) {
var formats = ajv._formats;
for (var name in COMPARE_FORMATS) {
var format = formats[name];
// the last condition is needed if it's RegExp from another window
if (typeof format != 'object' || format instanceof RegExp || !format.validate)
format = formats[name] = { validate: format };
if (!format.compare)
format.compare = COMPARE_FORMATS[name];
}
}
function compareDate(d1, d2) {
if (!(d1 && d2)) return;
if (d1 > d2) return 1;
if (d1 < d2) return -1;
if (d1 === d2) return 0;
}
function compareTime(t1, t2) {
if (!(t1 && t2)) return;
t1 = t1.match(TIME);
t2 = t2.match(TIME);
if (!(t1 && t2)) return;
t1 = t1[1] + t1[2] + t1[3] + (t1[4]||'');
t2 = t2[1] + t2[2] + t2[3] + (t2[4]||'');
if (t1 > t2) return 1;
if (t1 < t2) return -1;
if (t1 === t2) return 0;
}
function compareDateTime(dt1, dt2) {
if (!(dt1 && dt2)) return;
dt1 = dt1.split(DATE_TIME_SEPARATOR);
dt2 = dt2.split(DATE_TIME_SEPARATOR);
var res = compareDate(dt1[0], dt2[0]);
if (res === undefined) return;
return res || compareTime(dt1[1], dt2[1]);
}
+15
View File
@@ -0,0 +1,15 @@
'use strict';
module.exports = {
metaSchemaRef: metaSchemaRef
};
var META_SCHEMA_ID = 'http://json-schema.org/draft-06/schema';
function metaSchemaRef(ajv) {
var defaultMeta = ajv._opts.defaultMeta;
if (typeof defaultMeta == 'string') return { $ref: defaultMeta };
if (ajv.getSchema(META_SCHEMA_ID)) return { $ref: META_SCHEMA_ID };
console.warn('meta schema not defined');
return {};
}
@@ -0,0 +1,54 @@
'use strict';
var util = require('./_util');
module.exports = function defFunc(ajv) {
defFunc.definition = {
type: 'object',
macro: function (schema) {
var schemas = [];
for (var pointer in schema)
schemas.push(getSchema(pointer, schema[pointer]));
return { 'allOf': schemas };
},
metaSchema: {
type: 'object',
propertyNames: {
type: 'string',
format: 'json-pointer'
},
additionalProperties: util.metaSchemaRef(ajv)
}
};
ajv.addKeyword('deepProperties', defFunc.definition);
return ajv;
};
function getSchema(jsonPointer, schema) {
var segments = jsonPointer.split('/');
var rootSchema = {};
var pointerSchema = rootSchema;
for (var i=1; i<segments.length; i++) {
var segment = segments[i];
var isLast = i == segments.length - 1;
segment = unescapeJsonPointer(segment);
var properties = pointerSchema.properties = {};
var items = undefined;
if (/[0-9]+/.test(segment)) {
var count = +segment;
items = pointerSchema.items = [];
while (count--) items.push({});
}
pointerSchema = isLast ? schema : {};
properties[segment] = pointerSchema;
if (items) items.push(pointerSchema);
}
return rootSchema;
}
function unescapeJsonPointer(str) {
return str.replace(/~1/g, '/').replace(/~0/g, '~');
}
+57
View File
@@ -0,0 +1,57 @@
'use strict';
module.exports = function defFunc(ajv) {
defFunc.definition = {
type: 'object',
inline: function (it, keyword, schema) {
var expr = '';
for (var i=0; i<schema.length; i++) {
if (i) expr += ' && ';
expr += '(' + getData(schema[i], it.dataLevel) + ' !== undefined)';
}
return expr;
},
metaSchema: {
type: 'array',
items: {
type: 'string',
format: 'json-pointer'
}
}
};
ajv.addKeyword('deepRequired', defFunc.definition);
return ajv;
};
function getData(jsonPointer, lvl) {
var data = 'data' + (lvl || '');
if (!jsonPointer) return data;
var expr = data;
var segments = jsonPointer.split('/');
for (var i=1; i<segments.length; i++) {
var segment = segments[i];
data += getProperty(unescapeJsonPointer(segment));
expr += ' && ' + data;
}
return expr;
}
var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;
var INTEGER = /^[0-9]+$/;
var SINGLE_QUOTE = /'|\\/g;
function getProperty(key) {
return INTEGER.test(key)
? '[' + key + ']'
: IDENTIFIER.test(key)
? '.' + key
: "['" + key.replace(SINGLE_QUOTE, '\\$&') + "']";
}
function unescapeJsonPointer(str) {
return str.replace(/~1/g, '/').replace(/~0/g, '~');
}
@@ -0,0 +1,116 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
var {{=$valid}} = undefined;
{{## def.skipFormatLimit:
{{=$valid}} = true;
{{ return out; }}
#}}
{{## def.compareFormat:
{{? $isData }}
if ({{=$schemaValue}} === undefined) {{=$valid}} = true;
else if (typeof {{=$schemaValue}} != 'string') {{=$valid}} = false;
else {
{{ $closingBraces += '}'; }}
{{?}}
{{? $isDataFormat }}
if (!{{=$compare}}) {{=$valid}} = true;
else {
{{ $closingBraces += '}'; }}
{{?}}
var {{=$result}} = {{=$compare}}({{=$data}}, {{# def.schemaValueQS }});
if ({{=$result}} === undefined) {{=$valid}} = false;
#}}
{{? it.opts.format === false }}{{# def.skipFormatLimit }}{{?}}
{{
var $schemaFormat = it.schema.format
, $isDataFormat = it.opts.$data && $schemaFormat.$data
, $closingBraces = '';
}}
{{? $isDataFormat }}
{{
var $schemaValueFormat = it.util.getData($schemaFormat.$data, $dataLvl, it.dataPathArr)
, $format = 'format' + $lvl
, $compare = 'compare' + $lvl;
}}
var {{=$format}} = formats[{{=$schemaValueFormat}}]
, {{=$compare}} = {{=$format}} && {{=$format}}.compare;
{{??}}
{{ var $format = it.formats[$schemaFormat]; }}
{{? !($format && $format.compare) }}
{{# def.skipFormatLimit }}
{{?}}
{{ var $compare = 'formats' + it.util.getProperty($schemaFormat) + '.compare'; }}
{{?}}
{{
var $isMax = $keyword == 'formatMaximum'
, $exclusiveKeyword = 'formatExclusive' + ($isMax ? 'Maximum' : 'Minimum')
, $schemaExcl = it.schema[$exclusiveKeyword]
, $isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data
, $op = $isMax ? '<' : '>'
, $result = 'result' + $lvl;
}}
{{# def.$data }}
{{? $isDataExcl }}
{{
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr)
, $exclusive = 'exclusive' + $lvl
, $opExpr = 'op' + $lvl
, $opStr = '\' + ' + $opExpr + ' + \'';
}}
var schemaExcl{{=$lvl}} = {{=$schemaValueExcl}};
{{ $schemaValueExcl = 'schemaExcl' + $lvl; }}
if (typeof {{=$schemaValueExcl}} != 'boolean' && {{=$schemaValueExcl}} !== undefined) {
{{=$valid}} = false;
{{ var $errorKeyword = $exclusiveKeyword; }}
{{# def.error:'_formatExclusiveLimit' }}
}
{{# def.elseIfValid }}
{{# def.compareFormat }}
var {{=$exclusive}} = {{=$schemaValueExcl}} === true;
if ({{=$valid}} === undefined) {
{{=$valid}} = {{=$exclusive}}
? {{=$result}} {{=$op}} 0
: {{=$result}} {{=$op}}= 0;
}
if (!{{=$valid}}) var op{{=$lvl}} = {{=$exclusive}} ? '{{=$op}}' : '{{=$op}}=';
{{??}}
{{
var $exclusive = $schemaExcl === true
, $opStr = $op; /*used in error*/
if (!$exclusive) $opStr += '=';
var $opExpr = '\'' + $opStr + '\''; /*used in error*/
}}
{{# def.compareFormat }}
if ({{=$valid}} === undefined)
{{=$valid}} = {{=$result}} {{=$op}}{{?!$exclusive}}={{?}} 0;
{{?}}
{{= $closingBraces }}
if (!{{=$valid}}) {
{{ var $errorKeyword = $keyword; }}
{{# def.error:'_formatLimit' }}
}
@@ -0,0 +1,33 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{
var $key = 'key' + $lvl
, $idx = 'idx' + $lvl
, $matched = 'patternMatched' + $lvl
, $dataProperties = 'dataProperties' + $lvl
, $closingBraces = ''
, $ownProperties = it.opts.ownProperties;
}}
var {{=$valid}} = true;
{{? $ownProperties }}
var {{=$dataProperties}} = undefined;
{{?}}
{{~ $schema:$pProperty }}
var {{=$matched}} = false;
{{# def.iterateProperties }}
{{=$matched}} = {{= it.usePattern($pProperty) }}.test({{=$key}});
if ({{=$matched}}) break;
}
{{ var $missingPattern = it.util.escapeQuotes($pProperty); }}
if (!{{=$matched}}) {
{{=$valid}} = false;
{{# def.addError:'patternRequired' }}
} {{# def.elseIfValid }}
{{~}}
{{= $closingBraces }}
+73
View File
@@ -0,0 +1,73 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{## def.validateIf:
{{# def.setCompositeRule }}
{{ $it.createErrors = false; }}
{{# def._validateSwitchRule:if }}
{{ $it.createErrors = true; }}
{{# def.resetCompositeRule }}
{{=$ifPassed}} = {{=$nextValid}};
#}}
{{## def.validateThen:
{{? typeof $sch.then == 'boolean' }}
{{? $sch.then === false }}
{{# def.error:'switch' }}
{{?}}
var {{=$nextValid}} = {{= $sch.then }};
{{??}}
{{# def._validateSwitchRule:then }}
{{?}}
#}}
{{## def._validateSwitchRule:_clause:
{{
$it.schema = $sch._clause;
$it.schemaPath = $schemaPath + '[' + $caseIndex + ']._clause';
$it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/_clause';
}}
{{# def.insertSubschemaCode }}
#}}
{{## def.switchCase:
{{? $sch.if && {{# def.nonEmptySchema:$sch.if }} }}
var {{=$errs}} = errors;
{{# def.validateIf }}
if ({{=$ifPassed}}) {
{{# def.validateThen }}
} else {
{{# def.resetErrors }}
}
{{??}}
{{=$ifPassed}} = true;
{{# def.validateThen }}
{{?}}
#}}
{{
var $ifPassed = 'ifPassed' + it.level
, $currentBaseId = $it.baseId
, $shouldContinue;
}}
var {{=$ifPassed}};
{{~ $schema:$sch:$caseIndex }}
{{? $caseIndex && !$shouldContinue }}
if (!{{=$ifPassed}}) {
{{ $closingBraces+= '}'; }}
{{?}}
{{# def.switchCase }}
{{ $shouldContinue = $sch.continue }}
{{~}}
{{= $closingBraces }}
var {{=$valid}} = {{=$nextValid}};
{{# def.cleanUp }}
@@ -0,0 +1,3 @@
These files are compiled dot templates from dot folder.
Do NOT edit them directly, edit the templates and run `npm run build` from main ajv-keywords folder.
@@ -0,0 +1,176 @@
'use strict';
module.exports = function generate__formatLimit(it, $keyword, $ruleType) {
var out = ' ';
var $lvl = it.level;
var $dataLvl = it.dataLevel;
var $schema = it.schema[$keyword];
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
out += 'var ' + ($valid) + ' = undefined;';
if (it.opts.format === false) {
out += ' ' + ($valid) + ' = true; ';
return out;
}
var $schemaFormat = it.schema.format,
$isDataFormat = it.opts.$data && $schemaFormat.$data,
$closingBraces = '';
if ($isDataFormat) {
var $schemaValueFormat = it.util.getData($schemaFormat.$data, $dataLvl, it.dataPathArr),
$format = 'format' + $lvl,
$compare = 'compare' + $lvl;
out += ' var ' + ($format) + ' = formats[' + ($schemaValueFormat) + '] , ' + ($compare) + ' = ' + ($format) + ' && ' + ($format) + '.compare;';
} else {
var $format = it.formats[$schemaFormat];
if (!($format && $format.compare)) {
out += ' ' + ($valid) + ' = true; ';
return out;
}
var $compare = 'formats' + it.util.getProperty($schemaFormat) + '.compare';
}
var $isMax = $keyword == 'formatMaximum',
$exclusiveKeyword = 'formatExclusive' + ($isMax ? 'Maximum' : 'Minimum'),
$schemaExcl = it.schema[$exclusiveKeyword],
$isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data,
$op = $isMax ? '<' : '>',
$result = 'result' + $lvl;
var $isData = it.opts.$data && $schema && $schema.$data,
$schemaValue;
if ($isData) {
out += ' var schema' + ($lvl) + ' = ' + (it.util.getData($schema.$data, $dataLvl, it.dataPathArr)) + '; ';
$schemaValue = 'schema' + $lvl;
} else {
$schemaValue = $schema;
}
if ($isDataExcl) {
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr),
$exclusive = 'exclusive' + $lvl,
$opExpr = 'op' + $lvl,
$opStr = '\' + ' + $opExpr + ' + \'';
out += ' var schemaExcl' + ($lvl) + ' = ' + ($schemaValueExcl) + '; ';
$schemaValueExcl = 'schemaExcl' + $lvl;
out += ' if (typeof ' + ($schemaValueExcl) + ' != \'boolean\' && ' + ($schemaValueExcl) + ' !== undefined) { ' + ($valid) + ' = false; ';
var $errorKeyword = $exclusiveKeyword;
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ($errorKeyword || '_formatExclusiveLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} ';
if (it.opts.messages !== false) {
out += ' , message: \'' + ($exclusiveKeyword) + ' should be boolean\' ';
}
if (it.opts.verbose) {
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
out += ' } ';
if ($breakOnError) {
$closingBraces += '}';
out += ' else { ';
}
if ($isData) {
out += ' if (' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'string\') ' + ($valid) + ' = false; else { ';
$closingBraces += '}';
}
if ($isDataFormat) {
out += ' if (!' + ($compare) + ') ' + ($valid) + ' = true; else { ';
$closingBraces += '}';
}
out += ' var ' + ($result) + ' = ' + ($compare) + '(' + ($data) + ', ';
if ($isData) {
out += '' + ($schemaValue);
} else {
out += '' + (it.util.toQuotedString($schema));
}
out += ' ); if (' + ($result) + ' === undefined) ' + ($valid) + ' = false; var ' + ($exclusive) + ' = ' + ($schemaValueExcl) + ' === true; if (' + ($valid) + ' === undefined) { ' + ($valid) + ' = ' + ($exclusive) + ' ? ' + ($result) + ' ' + ($op) + ' 0 : ' + ($result) + ' ' + ($op) + '= 0; } if (!' + ($valid) + ') var op' + ($lvl) + ' = ' + ($exclusive) + ' ? \'' + ($op) + '\' : \'' + ($op) + '=\';';
} else {
var $exclusive = $schemaExcl === true,
$opStr = $op;
if (!$exclusive) $opStr += '=';
var $opExpr = '\'' + $opStr + '\'';
if ($isData) {
out += ' if (' + ($schemaValue) + ' === undefined) ' + ($valid) + ' = true; else if (typeof ' + ($schemaValue) + ' != \'string\') ' + ($valid) + ' = false; else { ';
$closingBraces += '}';
}
if ($isDataFormat) {
out += ' if (!' + ($compare) + ') ' + ($valid) + ' = true; else { ';
$closingBraces += '}';
}
out += ' var ' + ($result) + ' = ' + ($compare) + '(' + ($data) + ', ';
if ($isData) {
out += '' + ($schemaValue);
} else {
out += '' + (it.util.toQuotedString($schema));
}
out += ' ); if (' + ($result) + ' === undefined) ' + ($valid) + ' = false; if (' + ($valid) + ' === undefined) ' + ($valid) + ' = ' + ($result) + ' ' + ($op);
if (!$exclusive) {
out += '=';
}
out += ' 0;';
}
out += '' + ($closingBraces) + 'if (!' + ($valid) + ') { ';
var $errorKeyword = $keyword;
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ($errorKeyword || '_formatLimit') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { comparison: ' + ($opExpr) + ', limit: ';
if ($isData) {
out += '' + ($schemaValue);
} else {
out += '' + (it.util.toQuotedString($schema));
}
out += ' , exclusive: ' + ($exclusive) + ' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should be ' + ($opStr) + ' "';
if ($isData) {
out += '\' + ' + ($schemaValue) + ' + \'';
} else {
out += '' + (it.util.escapeQuotes($schema));
}
out += '"\' ';
}
if (it.opts.verbose) {
out += ' , schema: ';
if ($isData) {
out += 'validate.schema' + ($schemaPath);
} else {
out += '' + (it.util.toQuotedString($schema));
}
out += ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
out += '}';
return out;
}
@@ -0,0 +1,58 @@
'use strict';
module.exports = function generate_patternRequired(it, $keyword, $ruleType) {
var out = ' ';
var $lvl = it.level;
var $dataLvl = it.dataLevel;
var $schema = it.schema[$keyword];
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $key = 'key' + $lvl,
$idx = 'idx' + $lvl,
$matched = 'patternMatched' + $lvl,
$dataProperties = 'dataProperties' + $lvl,
$closingBraces = '',
$ownProperties = it.opts.ownProperties;
out += 'var ' + ($valid) + ' = true;';
if ($ownProperties) {
out += ' var ' + ($dataProperties) + ' = undefined;';
}
var arr1 = $schema;
if (arr1) {
var $pProperty, i1 = -1,
l1 = arr1.length - 1;
while (i1 < l1) {
$pProperty = arr1[i1 += 1];
out += ' var ' + ($matched) + ' = false; ';
if ($ownProperties) {
out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; ';
} else {
out += ' for (var ' + ($key) + ' in ' + ($data) + ') { ';
}
out += ' ' + ($matched) + ' = ' + (it.usePattern($pProperty)) + '.test(' + ($key) + '); if (' + ($matched) + ') break; } ';
var $missingPattern = it.util.escapeQuotes($pProperty);
out += ' if (!' + ($matched) + ') { ' + ($valid) + ' = false; var err = '; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ('patternRequired') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingPattern: \'' + ($missingPattern) + '\' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should have property matching pattern \\\'' + ($missingPattern) + '\\\'\' ';
}
if (it.opts.verbose) {
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
out += '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; } ';
if ($breakOnError) {
$closingBraces += '}';
out += ' else { ';
}
}
}
out += '' + ($closingBraces);
return out;
}
+128
View File
@@ -0,0 +1,128 @@
'use strict';
module.exports = function generate_switch(it, $keyword, $ruleType) {
var out = ' ';
var $lvl = it.level;
var $dataLvl = it.dataLevel;
var $schema = it.schema[$keyword];
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $errs = 'errs__' + $lvl;
var $it = it.util.copy(it);
var $closingBraces = '';
$it.level++;
var $nextValid = 'valid' + $it.level;
var $ifPassed = 'ifPassed' + it.level,
$currentBaseId = $it.baseId,
$shouldContinue;
out += 'var ' + ($ifPassed) + ';';
var arr1 = $schema;
if (arr1) {
var $sch, $caseIndex = -1,
l1 = arr1.length - 1;
while ($caseIndex < l1) {
$sch = arr1[$caseIndex += 1];
if ($caseIndex && !$shouldContinue) {
out += ' if (!' + ($ifPassed) + ') { ';
$closingBraces += '}';
}
if ($sch.if && it.util.schemaHasRules($sch.if, it.RULES.all)) {
out += ' var ' + ($errs) + ' = errors; ';
var $wasComposite = it.compositeRule;
it.compositeRule = $it.compositeRule = true;
$it.createErrors = false;
$it.schema = $sch.if;
$it.schemaPath = $schemaPath + '[' + $caseIndex + '].if';
$it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/if';
out += ' ' + (it.validate($it)) + ' ';
$it.baseId = $currentBaseId;
$it.createErrors = true;
it.compositeRule = $it.compositeRule = $wasComposite;
out += ' ' + ($ifPassed) + ' = ' + ($nextValid) + '; if (' + ($ifPassed) + ') { ';
if (typeof $sch.then == 'boolean') {
if ($sch.then === false) {
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ('switch') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { caseIndex: ' + ($caseIndex) + ' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should pass "switch" keyword validation\' ';
}
if (it.opts.verbose) {
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
}
out += ' var ' + ($nextValid) + ' = ' + ($sch.then) + '; ';
} else {
$it.schema = $sch.then;
$it.schemaPath = $schemaPath + '[' + $caseIndex + '].then';
$it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/then';
out += ' ' + (it.validate($it)) + ' ';
$it.baseId = $currentBaseId;
}
out += ' } else { errors = ' + ($errs) + '; if (vErrors !== null) { if (' + ($errs) + ') vErrors.length = ' + ($errs) + '; else vErrors = null; } } ';
} else {
out += ' ' + ($ifPassed) + ' = true; ';
if (typeof $sch.then == 'boolean') {
if ($sch.then === false) {
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = ''; /* istanbul ignore else */
if (it.createErrors !== false) {
out += ' { keyword: \'' + ('switch') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { caseIndex: ' + ($caseIndex) + ' } ';
if (it.opts.messages !== false) {
out += ' , message: \'should pass "switch" keyword validation\' ';
}
if (it.opts.verbose) {
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
}
out += ' } ';
} else {
out += ' {} ';
}
var __err = out;
out = $$outStack.pop();
if (!it.compositeRule && $breakOnError) { /* istanbul ignore if */
if (it.async) {
out += ' throw new ValidationError([' + (__err) + ']); ';
} else {
out += ' validate.errors = [' + (__err) + ']; return false; ';
}
} else {
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
}
}
out += ' var ' + ($nextValid) + ' = ' + ($sch.then) + '; ';
} else {
$it.schema = $sch.then;
$it.schemaPath = $schemaPath + '[' + $caseIndex + '].then';
$it.errSchemaPath = $errSchemaPath + '/' + $caseIndex + '/then';
out += ' ' + (it.validate($it)) + ' ';
$it.baseId = $currentBaseId;
}
}
$shouldContinue = $sch.continue
}
}
out += '' + ($closingBraces) + 'var ' + ($valid) + ' = ' + ($nextValid) + '; ';
out = it.util.cleanUpCode(out);
return out;
}
@@ -0,0 +1,68 @@
'use strict';
var sequences = {};
var DEFAULTS = {
timestamp: function() { return Date.now(); },
datetime: function() { return (new Date).toISOString(); },
date: function() { return (new Date).toISOString().slice(0, 10); },
time: function() { return (new Date).toISOString().slice(11); },
random: function() { return Math.random(); },
randomint: function (args) {
var limit = args && args.max || 2;
return function() { return Math.floor(Math.random() * limit); };
},
seq: function (args) {
var name = args && args.name || '';
sequences[name] = sequences[name] || 0;
return function() { return sequences[name]++; };
}
};
module.exports = function defFunc(ajv) {
defFunc.definition = {
compile: function (schema, parentSchema, it) {
var funcs = {};
for (var key in schema) {
var d = schema[key];
var func = getDefault(typeof d == 'string' ? d : d.func);
funcs[key] = func.length ? func(d.args) : func;
}
return it.opts.useDefaults && !it.compositeRule
? assignDefaults
: noop;
function assignDefaults(data) {
for (var prop in schema)
if (data[prop] === undefined) data[prop] = funcs[prop]();
return true;
}
function noop() { return true; }
},
DEFAULTS: DEFAULTS,
metaSchema: {
type: 'object',
additionalProperties: {
type: ['string', 'object'],
additionalProperties: false,
required: ['func', 'args'],
properties: {
func: { type: 'string' },
args: { type: 'object' }
}
}
}
};
ajv.addKeyword('dynamicDefaults', defFunc.definition);
return ajv;
function getDefault(d) {
var def = DEFAULTS[d];
if (def) return def;
throw new Error('invalid "dynamicDefaults" keyword property value: ' + d);
}
};
@@ -0,0 +1,3 @@
'use strict';
module.exports = require('./_formatLimit')('Maximum');
@@ -0,0 +1,3 @@
'use strict';
module.exports = require('./_formatLimit')('Minimum');
+21
View File
@@ -0,0 +1,21 @@
'use strict';
module.exports = function defFunc(ajv) {
if (!ajv.RULES.keywords.switch) require('./switch')(ajv);
defFunc.definition = {
macro: function (schema, parentSchema) {
if (parentSchema.then === undefined)
throw new Error('keyword "then" is absent');
var cases = [ { 'if': schema, 'then': parentSchema.then } ];
if (parentSchema.else !== undefined)
cases[1] = { 'then': parentSchema.else };
return { switch: cases };
}
};
ajv.addKeyword('if', defFunc.definition);
ajv.addKeyword('then');
ajv.addKeyword('else');
return ajv;
};
+19
View File
@@ -0,0 +1,19 @@
'use strict';
module.exports = {
'instanceof': require('./instanceof'),
range: require('./range'),
regexp: require('./regexp'),
'typeof': require('./typeof'),
dynamicDefaults: require('./dynamicDefaults'),
'if': require('./if'),
prohibited: require('./prohibited'),
uniqueItemProperties: require('./uniqueItemProperties'),
deepProperties: require('./deepProperties'),
deepRequired: require('./deepRequired'),
formatMinimum: require('./formatMinimum'),
formatMaximum: require('./formatMaximum'),
patternRequired: require('./patternRequired'),
'switch': require('./switch'),
select: require('./select')
};
+54
View File
@@ -0,0 +1,54 @@
'use strict';
var CONSTRUCTORS = {
Object: Object,
Array: Array,
Function: Function,
Number: Number,
String: String,
Date: Date,
RegExp: RegExp
};
module.exports = function defFunc(ajv) {
/* istanbul ignore else */
if (typeof Buffer != 'undefined')
CONSTRUCTORS.Buffer = Buffer;
defFunc.definition = {
compile: function (schema) {
if (typeof schema == 'string') {
var Constructor = getConstructor(schema);
return function (data) {
return data instanceof Constructor;
};
}
var constructors = schema.map(getConstructor);
return function (data) {
for (var i=0; i<constructors.length; i++)
if (data instanceof constructors[i]) return true;
return false;
};
},
CONSTRUCTORS: CONSTRUCTORS,
metaSchema: {
anyOf: [
{ type: 'string' },
{
type: 'array',
items: { type: 'string' }
}
]
}
};
ajv.addKeyword('instanceof', defFunc.definition);
return ajv;
function getConstructor(c) {
var Constructor = CONSTRUCTORS[c];
if (Constructor) return Constructor;
throw new Error('invalid "instanceof" keyword value ' + c);
}
};
@@ -0,0 +1,21 @@
'use strict';
module.exports = function defFunc(ajv) {
defFunc.definition = {
type: 'object',
inline: require('./dotjs/patternRequired'),
statements: true,
errors: 'full',
metaSchema: {
type: 'array',
items: {
type: 'string',
format: 'regex'
},
uniqueItems: true
}
};
ajv.addKeyword('patternRequired', defFunc.definition);
return ajv;
};
+25
View File
@@ -0,0 +1,25 @@
'use strict';
module.exports = function defFunc(ajv) {
defFunc.definition = {
type: 'object',
macro: function (schema) {
if (schema.length == 0) return {};
if (schema.length == 1) return { not: { required: schema } };
var schemas = schema.map(function (prop) {
return { required: [prop] };
});
return { not: { anyOf: schemas } };
},
metaSchema: {
type: 'array',
items: {
type: 'string'
}
}
};
ajv.addKeyword('prohibited', defFunc.definition);
return ajv;
};
+36
View File
@@ -0,0 +1,36 @@
'use strict';
module.exports = function defFunc(ajv) {
defFunc.definition = {
type: 'number',
macro: function (schema, parentSchema) {
var min = schema[0]
, max = schema[1]
, exclusive = parentSchema.exclusiveRange;
validateRangeSchema(min, max, exclusive);
return exclusive === true
? {exclusiveMinimum: min, exclusiveMaximum: max}
: {minimum: min, maximum: max};
},
metaSchema: {
type: 'array',
minItems: 2,
maxItems: 2,
items: { type: 'number' }
}
};
ajv.addKeyword('range', defFunc.definition);
ajv.addKeyword('exclusiveRange');
return ajv;
function validateRangeSchema(min, max, exclusive) {
if (exclusive !== undefined && typeof exclusive != 'boolean')
throw new Error('Invalid schema for exclusiveRange keyword, should be boolean');
if (min > max || (exclusive && min == max))
throw new Error('There are no numbers in range');
}
};
+36
View File
@@ -0,0 +1,36 @@
'use strict';
module.exports = function defFunc(ajv) {
defFunc.definition = {
type: 'string',
inline: function (it, keyword, schema) {
return getRegExp() + '.test(data' + (it.dataLevel || '') + ')';
function getRegExp() {
try {
if (typeof schema == 'object')
return new RegExp(schema.pattern, schema.flags);
var rx = schema.match(/^\/(.*)\/([gimy]*)$/);
if (rx) return new RegExp(rx[1], rx[2]);
throw new Error('cannot parse string into RegExp');
} catch(e) {
console.error('regular expression', schema, 'is invalid');
throw e;
}
}
},
metaSchema: {
type: ['string', 'object'],
properties: {
pattern: { type: 'string' },
flags: { type: 'string' }
},
required: ['pattern'],
additionalProperties: false
}
};
ajv.addKeyword('regexp', defFunc.definition);
return ajv;
};
+79
View File
@@ -0,0 +1,79 @@
'use strict';
var util = require('./_util');
module.exports = function defFunc(ajv) {
if (!ajv._opts.$data) {
console.warn('keyword select requires $data option');
return ajv;
}
var metaSchemaRef = util.metaSchemaRef(ajv);
var compiledCaseSchemas = [];
defFunc.definition = {
validate: function v(schema, data, parentSchema) {
if (parentSchema.selectCases === undefined)
throw new Error('keyword "selectCases" is absent');
var compiled = getCompiledSchemas(parentSchema, false);
var validate = compiled.cases[schema];
if (validate === undefined) validate = compiled.default;
if (typeof validate == 'boolean') return validate;
var valid = validate(data);
if (!valid) v.errors = validate.errors;
return valid;
},
$data: true,
metaSchema: { type: ['string', 'number', 'boolean', 'null'] }
};
ajv.addKeyword('select', defFunc.definition);
ajv.addKeyword('selectCases', {
compile: function (schemas, parentSchema) {
var compiled = getCompiledSchemas(parentSchema);
for (var value in schemas)
compiled.cases[value] = compileOrBoolean(schemas[value]);
return function() { return true; };
},
valid: true,
metaSchema: {
type: 'object',
additionalProperties: metaSchemaRef
}
});
ajv.addKeyword('selectDefault', {
compile: function (schema, parentSchema) {
var compiled = getCompiledSchemas(parentSchema);
compiled.default = compileOrBoolean(schema);
return function() { return true; };
},
valid: true,
metaSchema: metaSchemaRef
});
return ajv;
function getCompiledSchemas(parentSchema, create) {
var compiled;
compiledCaseSchemas.some(function (c) {
if (c.parentSchema === parentSchema) {
compiled = c;
return true;
}
});
if (!compiled && create !== false) {
compiled = {
parentSchema: parentSchema,
cases: {},
default: true
};
compiledCaseSchemas.push(compiled);
}
return compiled;
}
function compileOrBoolean(schema) {
return typeof schema == 'boolean'
? schema
: ajv.compile(schema);
}
};
+38
View File
@@ -0,0 +1,38 @@
'use strict';
var util = require('./_util');
module.exports = function defFunc(ajv) {
if (ajv.RULES.keywords.switch && ajv.RULES.keywords.if) return;
var metaSchemaRef = util.metaSchemaRef(ajv);
defFunc.definition = {
inline: require('./dotjs/switch'),
statements: true,
errors: 'full',
metaSchema: {
type: 'array',
items: {
required: [ 'then' ],
properties: {
'if': metaSchemaRef,
'then': {
anyOf: [
{ type: 'boolean' },
metaSchemaRef
]
},
'continue': { type: 'boolean' }
},
additionalProperties: false,
dependencies: {
'continue': [ 'if' ]
}
}
}
};
ajv.addKeyword('switch', defFunc.definition);
return ajv;
};
+32
View File
@@ -0,0 +1,32 @@
'use strict';
var KNOWN_TYPES = ['undefined', 'string', 'number', 'object', 'function', 'boolean', 'symbol'];
module.exports = function defFunc(ajv) {
defFunc.definition = {
inline: function (it, keyword, schema) {
var data = 'data' + (it.dataLevel || '');
if (typeof schema == 'string') return 'typeof ' + data + ' == "' + schema + '"';
schema = 'validate.schema' + it.schemaPath + '.' + keyword;
return schema + '.indexOf(typeof ' + data + ') >= 0';
},
metaSchema: {
anyOf: [
{
type: 'string',
enum: KNOWN_TYPES
},
{
type: 'array',
items: {
type: 'string',
enum: KNOWN_TYPES
}
}
]
}
};
ajv.addKeyword('typeof', defFunc.definition);
return ajv;
};
@@ -0,0 +1,32 @@
'use strict';
module.exports = function defFunc(ajv) {
defFunc.definition = {
type: 'array',
compile: function(keys, parentSchema, it) {
var equal = it.util.equal;
return function(data) {
if (data.length > 1) {
for (var k=0; k < keys.length; k++) {
var key = keys[k];
for (var i = data.length; i--;) {
if (typeof data[i] != 'object') continue;
for (var j = i; j--;) {
if (typeof data[j] == 'object' && equal(data[i][key], data[j][key]))
return false;
}
}
}
}
return true;
};
},
metaSchema: {
type: 'array',
items: {type: 'string'}
}
};
ajv.addKeyword('uniqueItemProperties', defFunc.definition);
return ajv;
};
+78
View File
@@ -0,0 +1,78 @@
{
"_from": "ajv-keywords@^2.1.0",
"_id": "ajv-keywords@2.1.1",
"_inBundle": false,
"_integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
"_location": "/table/ajv-keywords",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "ajv-keywords@^2.1.0",
"name": "ajv-keywords",
"escapedName": "ajv-keywords",
"rawSpec": "^2.1.0",
"saveSpec": null,
"fetchSpec": "^2.1.0"
},
"_requiredBy": [
"/table"
],
"_resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
"_shasum": "617997fc5f60576894c435f940d819e135b80762",
"_spec": "ajv-keywords@^2.1.0",
"_where": "D:\\Atom\\Git\\Laravel_CSSd\\node_modules\\table",
"author": {
"name": "Evgeny Poberezkin"
},
"bugs": {
"url": "https://github.com/epoberezkin/ajv-keywords/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Custom JSON-Schema keywords for Ajv validator",
"devDependencies": {
"ajv": "^5.0.0",
"ajv-pack": "^0.3.0",
"chai": "^4.0.2",
"coveralls": "^3.0.0",
"dot": "^1.1.1",
"eslint": "^4.9.0",
"glob": "^7.1.1",
"istanbul": "^0.4.3",
"js-beautify": "^1.7.4",
"json-schema-test": "^1.3.0",
"mocha": "^4.0.0",
"pre-commit": "^1.1.3",
"uuid": "^3.0.1"
},
"files": [
"index.js",
"keywords"
],
"homepage": "https://github.com/epoberezkin/ajv-keywords#readme",
"keywords": [
"JSON-Schema",
"ajv",
"keywords"
],
"license": "MIT",
"main": "index.js",
"name": "ajv-keywords",
"peerDependencies": {
"ajv": "^5.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/epoberezkin/ajv-keywords.git"
},
"scripts": {
"build": "node node_modules/ajv/scripts/compile-dots.js node_modules/ajv/lib keywords",
"eslint": "eslint index.js keywords/*.js",
"prepublish": "npm run build",
"test": "npm run build && npm run eslint && npm run test-cov",
"test-cov": "istanbul cover -x 'spec/**' node_modules/mocha/bin/_mocha -- spec/*.spec.js -R spec",
"test-spec": "mocha spec/*.spec.js -R spec"
},
"version": "2.1.1"
}
+20
View File
@@ -0,0 +1,20 @@
var Ajv = require('ajv');
var ajv = new Ajv({allErrors: true});
var schema = {
"properties": {
"foo": { "type": "string" },
"bar": { "type": "number", "maximum": 3 }
}
};
var validate = ajv.compile(schema);
test({"foo": "abc", "bar": 2});
test({"foo": 2, "bar": 4});
function test(data) {
var valid = validate(data);
if (valid) console.log('Valid!');
else console.log('Invalid: ' + ajv.errorsText(validate.errors));
}
+22
View File
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Evgeny Poberezkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+1327
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+49
View File
@@ -0,0 +1,49 @@
'use strict';
var KEYWORDS = [
'multipleOf',
'maximum',
'exclusiveMaximum',
'minimum',
'exclusiveMinimum',
'maxLength',
'minLength',
'pattern',
'additionalItems',
'maxItems',
'minItems',
'uniqueItems',
'maxProperties',
'minProperties',
'required',
'additionalProperties',
'enum',
'format',
'const'
];
module.exports = function (metaSchema, keywordsJsonPointers) {
for (var i=0; i<keywordsJsonPointers.length; i++) {
metaSchema = JSON.parse(JSON.stringify(metaSchema));
var segments = keywordsJsonPointers[i].split('/');
var keywords = metaSchema;
var j;
for (j=1; j<segments.length; j++)
keywords = keywords[segments[j]];
for (j=0; j<KEYWORDS.length; j++) {
var key = KEYWORDS[j];
var schema = keywords[key];
if (schema) {
keywords[key] = {
anyOf: [
schema,
{ $ref: 'https://raw.githubusercontent.com/epoberezkin/ajv/master/lib/refs/$data.json#' }
]
};
}
}
}
return metaSchema;
};
+358
View File
@@ -0,0 +1,358 @@
declare var ajv: {
(options?: ajv.Options): ajv.Ajv;
new (options?: ajv.Options): ajv.Ajv;
ValidationError: ValidationError;
MissingRefError: MissingRefError;
$dataMetaSchema: object;
}
declare namespace ajv {
interface Ajv {
/**
* Validate data using schema
* Schema will be compiled and cached (using serialized JSON as key, [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize by default).
* @param {string|object|Boolean} schemaKeyRef key, ref or schema object
* @param {Any} data to be validated
* @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`).
*/
validate(schemaKeyRef: object | string | boolean, data: any): boolean | Thenable<any>;
/**
* Create validating function for passed schema.
* @param {object|Boolean} schema schema object
* @return {Function} validating function
*/
compile(schema: object | boolean): ValidateFunction;
/**
* Creates validating function for passed schema with asynchronous loading of missing schemas.
* `loadSchema` option should be a function that accepts schema uri and node-style callback.
* @this Ajv
* @param {object|Boolean} schema schema object
* @param {Boolean} meta optional true to compile meta-schema; this parameter can be skipped
* @param {Function} callback optional node-style callback, it is always called with 2 parameters: error (or null) and validating function.
* @return {Thenable<ValidateFunction>} validating function
*/
compileAsync(schema: object | boolean, meta?: Boolean, callback?: (err: Error, validate: ValidateFunction) => any): Thenable<ValidateFunction>;
/**
* Adds schema to the instance.
* @param {object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
* @param {string} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
* @return {Ajv} this for method chaining
*/
addSchema(schema: Array<object> | object, key?: string): Ajv;
/**
* Add schema that will be used to validate other schemas
* options in META_IGNORE_OPTIONS are alway set to false
* @param {object} schema schema object
* @param {string} key optional schema key
* @return {Ajv} this for method chaining
*/
addMetaSchema(schema: object, key?: string): Ajv;
/**
* Validate schema
* @param {object|Boolean} schema schema to validate
* @return {Boolean} true if schema is valid
*/
validateSchema(schema: object | boolean): boolean;
/**
* Get compiled schema from the instance by `key` or `ref`.
* @param {string} keyRef `key` that was passed to `addSchema` or full schema reference (`schema.id` or resolved id).
* @return {Function} schema validating function (with property `schema`).
*/
getSchema(keyRef: string): ValidateFunction;
/**
* Remove cached schema(s).
* If no parameter is passed all schemas but meta-schemas are removed.
* If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
* Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
* @param {string|object|RegExp|Boolean} schemaKeyRef key, ref, pattern to match key/ref or schema object
* @return {Ajv} this for method chaining
*/
removeSchema(schemaKeyRef?: object | string | RegExp | boolean): Ajv;
/**
* Add custom format
* @param {string} name format name
* @param {string|RegExp|Function} format string is converted to RegExp; function should return boolean (true when valid)
* @return {Ajv} this for method chaining
*/
addFormat(name: string, format: FormatValidator | FormatDefinition): Ajv;
/**
* Define custom keyword
* @this Ajv
* @param {string} keyword custom keyword, should be a valid identifier, should be different from all standard, custom and macro keywords.
* @param {object} definition keyword definition object with properties `type` (type(s) which the keyword applies to), `validate` or `compile`.
* @return {Ajv} this for method chaining
*/
addKeyword(keyword: string, definition: KeywordDefinition): Ajv;
/**
* Get keyword definition
* @this Ajv
* @param {string} keyword pre-defined or custom keyword.
* @return {object|Boolean} custom keyword definition, `true` if it is a predefined keyword, `false` otherwise.
*/
getKeyword(keyword: string): object | boolean;
/**
* Remove keyword
* @this Ajv
* @param {string} keyword pre-defined or custom keyword.
* @return {Ajv} this for method chaining
*/
removeKeyword(keyword: string): Ajv;
/**
* Convert array of error message objects to string
* @param {Array<object>} errors optional array of validation errors, if not passed errors from the instance are used.
* @param {object} options optional options with properties `separator` and `dataVar`.
* @return {string} human readable string with all errors descriptions
*/
errorsText(errors?: Array<ErrorObject>, options?: ErrorsTextOptions): string;
errors?: Array<ErrorObject>;
}
interface Thenable <R> {
then <U> (onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => U | Thenable<U>): Thenable<U>;
}
interface ValidateFunction {
(
data: any,
dataPath?: string,
parentData?: object | Array<any>,
parentDataProperty?: string | number,
rootData?: object | Array<any>
): boolean | Thenable<any>;
schema?: object | boolean;
errors?: null | Array<ErrorObject>;
refs?: object;
refVal?: Array<any>;
root?: ValidateFunction | object;
$async?: true;
source?: object;
}
interface Options {
$data?: boolean;
allErrors?: boolean;
verbose?: boolean;
jsonPointers?: boolean;
uniqueItems?: boolean;
unicode?: boolean;
format?: string;
formats?: object;
unknownFormats?: true | string[] | 'ignore';
schemas?: Array<object> | object;
schemaId?: '$id' | 'id';
missingRefs?: true | 'ignore' | 'fail';
extendRefs?: true | 'ignore' | 'fail';
loadSchema?: (uri: string, cb?: (err: Error, schema: object) => void) => Thenable<object | boolean>;
removeAdditional?: boolean | 'all' | 'failing';
useDefaults?: boolean | 'shared';
coerceTypes?: boolean | 'array';
async?: boolean | string;
transpile?: string | ((code: string) => string);
meta?: boolean | object;
validateSchema?: boolean | 'log';
addUsedSchema?: boolean;
inlineRefs?: boolean | number;
passContext?: boolean;
loopRequired?: number;
ownProperties?: boolean;
multipleOfPrecision?: boolean | number;
errorDataPath?: string,
messages?: boolean;
sourceCode?: boolean;
processCode?: (code: string) => string;
cache?: object;
}
type FormatValidator = string | RegExp | ((data: string) => boolean | Thenable<any>);
interface FormatDefinition {
validate: FormatValidator;
compare: (data1: string, data2: string) => number;
async?: boolean;
}
interface KeywordDefinition {
type?: string | Array<string>;
async?: boolean;
$data?: boolean;
errors?: boolean | string;
metaSchema?: object;
// schema: false makes validate not to expect schema (ValidateFunction)
schema?: boolean;
modifying?: boolean;
valid?: boolean;
// one and only one of the following properties should be present
validate?: SchemaValidateFunction | ValidateFunction;
compile?: (schema: any, parentSchema: object, it: CompilationContext) => ValidateFunction;
macro?: (schema: any, parentSchema: object, it: CompilationContext) => object | boolean;
inline?: (it: CompilationContext, keyword: string, schema: any, parentSchema: object) => string;
}
interface CompilationContext {
level: number;
dataLevel: number;
schema: any;
schemaPath: string;
baseId: string;
async: boolean;
opts: Options;
formats: {
[index: string]: FormatDefinition | undefined;
};
compositeRule: boolean;
validate: (schema: object) => boolean;
util: {
copy(obj: any, target?: any): any;
toHash(source: string[]): { [index: string]: true | undefined };
equal(obj: any, target: any): boolean;
getProperty(str: string): string;
schemaHasRules(schema: object, rules: any): string;
escapeQuotes(str: string): string;
toQuotedString(str: string): string;
getData(jsonPointer: string, dataLevel: number, paths: string[]): string;
escapeJsonPointer(str: string): string;
unescapeJsonPointer(str: string): string;
escapeFragment(str: string): string;
unescapeFragment(str: string): string;
};
self: Ajv;
}
interface SchemaValidateFunction {
(
schema: any,
data: any,
parentSchema?: object,
dataPath?: string,
parentData?: object | Array<any>,
parentDataProperty?: string | number,
rootData?: object | Array<any>
): boolean | Thenable<any>;
errors?: Array<ErrorObject>;
}
interface ErrorsTextOptions {
separator?: string;
dataVar?: string;
}
interface ErrorObject {
keyword: string;
dataPath: string;
schemaPath: string;
params: ErrorParameters;
// Added to validation errors of propertyNames keyword schema
propertyName?: string;
// Excluded if messages set to false.
message?: string;
// These are added with the `verbose` option.
schema?: any;
parentSchema?: object;
data?: any;
}
type ErrorParameters = RefParams | LimitParams | AdditionalPropertiesParams |
DependenciesParams | FormatParams | ComparisonParams |
MultipleOfParams | PatternParams | RequiredParams |
TypeParams | UniqueItemsParams | CustomParams |
PatternGroupsParams | PatternRequiredParams |
PropertyNamesParams | SwitchParams | NoParams | EnumParams;
interface RefParams {
ref: string;
}
interface LimitParams {
limit: number;
}
interface AdditionalPropertiesParams {
additionalProperty: string;
}
interface DependenciesParams {
property: string;
missingProperty: string;
depsCount: number;
deps: string;
}
interface FormatParams {
format: string
}
interface ComparisonParams {
comparison: string;
limit: number | string;
exclusive: boolean;
}
interface MultipleOfParams {
multipleOf: number;
}
interface PatternParams {
pattern: string;
}
interface RequiredParams {
missingProperty: string;
}
interface TypeParams {
type: string;
}
interface UniqueItemsParams {
i: number;
j: number;
}
interface CustomParams {
keyword: string;
}
interface PatternGroupsParams {
reason: string;
limit: number;
pattern: string;
}
interface PatternRequiredParams {
missingPattern: string;
}
interface PropertyNamesParams {
propertyName: string;
}
interface SwitchParams {
caseIndex: number;
}
interface NoParams {}
interface EnumParams {
allowedValues: Array<any>;
}
}
declare class ValidationError extends Error {
constructor(errors: Array<ajv.ErrorObject>);
message: string;
errors: Array<ajv.ErrorObject>;
ajv: true;
validation: true;
}
declare class MissingRefError extends Error {
constructor(baseId: string, ref: string, message?: string);
static message: (baseId: string, ref: string) => string;
message: string;
missingRef: string;
missingSchema: string;
}
export = ajv;
+502
View File
@@ -0,0 +1,502 @@
'use strict';
var compileSchema = require('./compile')
, resolve = require('./compile/resolve')
, Cache = require('./cache')
, SchemaObject = require('./compile/schema_obj')
, stableStringify = require('fast-json-stable-stringify')
, formats = require('./compile/formats')
, rules = require('./compile/rules')
, $dataMetaSchema = require('./$data')
, patternGroups = require('./patternGroups')
, util = require('./compile/util')
, co = require('co');
module.exports = Ajv;
Ajv.prototype.validate = validate;
Ajv.prototype.compile = compile;
Ajv.prototype.addSchema = addSchema;
Ajv.prototype.addMetaSchema = addMetaSchema;
Ajv.prototype.validateSchema = validateSchema;
Ajv.prototype.getSchema = getSchema;
Ajv.prototype.removeSchema = removeSchema;
Ajv.prototype.addFormat = addFormat;
Ajv.prototype.errorsText = errorsText;
Ajv.prototype._addSchema = _addSchema;
Ajv.prototype._compile = _compile;
Ajv.prototype.compileAsync = require('./compile/async');
var customKeyword = require('./keyword');
Ajv.prototype.addKeyword = customKeyword.add;
Ajv.prototype.getKeyword = customKeyword.get;
Ajv.prototype.removeKeyword = customKeyword.remove;
var errorClasses = require('./compile/error_classes');
Ajv.ValidationError = errorClasses.Validation;
Ajv.MissingRefError = errorClasses.MissingRef;
Ajv.$dataMetaSchema = $dataMetaSchema;
var META_SCHEMA_ID = 'http://json-schema.org/draft-06/schema';
var META_IGNORE_OPTIONS = [ 'removeAdditional', 'useDefaults', 'coerceTypes' ];
var META_SUPPORT_DATA = ['/properties'];
/**
* Creates validator instance.
* Usage: `Ajv(opts)`
* @param {Object} opts optional options
* @return {Object} ajv instance
*/
function Ajv(opts) {
if (!(this instanceof Ajv)) return new Ajv(opts);
opts = this._opts = util.copy(opts) || {};
setLogger(this);
this._schemas = {};
this._refs = {};
this._fragments = {};
this._formats = formats(opts.format);
var schemaUriFormat = this._schemaUriFormat = this._formats['uri-reference'];
this._schemaUriFormatFunc = function (str) { return schemaUriFormat.test(str); };
this._cache = opts.cache || new Cache;
this._loadingSchemas = {};
this._compilations = [];
this.RULES = rules();
this._getId = chooseGetId(opts);
opts.loopRequired = opts.loopRequired || Infinity;
if (opts.errorDataPath == 'property') opts._errorDataPathProperty = true;
if (opts.serialize === undefined) opts.serialize = stableStringify;
this._metaOpts = getMetaSchemaOptions(this);
if (opts.formats) addInitialFormats(this);
addDraft6MetaSchema(this);
if (typeof opts.meta == 'object') this.addMetaSchema(opts.meta);
addInitialSchemas(this);
if (opts.patternGroups) patternGroups(this);
}
/**
* Validate data using schema
* Schema will be compiled and cached (using serialized JSON as key. [fast-json-stable-stringify](https://github.com/epoberezkin/fast-json-stable-stringify) is used to serialize.
* @this Ajv
* @param {String|Object} schemaKeyRef key, ref or schema object
* @param {Any} data to be validated
* @return {Boolean} validation result. Errors from the last validation will be available in `ajv.errors` (and also in compiled schema: `schema.errors`).
*/
function validate(schemaKeyRef, data) {
var v;
if (typeof schemaKeyRef == 'string') {
v = this.getSchema(schemaKeyRef);
if (!v) throw new Error('no schema with key or ref "' + schemaKeyRef + '"');
} else {
var schemaObj = this._addSchema(schemaKeyRef);
v = schemaObj.validate || this._compile(schemaObj);
}
var valid = v(data);
if (v.$async === true)
return this._opts.async == '*' ? co(valid) : valid;
this.errors = v.errors;
return valid;
}
/**
* Create validating function for passed schema.
* @this Ajv
* @param {Object} schema schema object
* @param {Boolean} _meta true if schema is a meta-schema. Used internally to compile meta schemas of custom keywords.
* @return {Function} validating function
*/
function compile(schema, _meta) {
var schemaObj = this._addSchema(schema, undefined, _meta);
return schemaObj.validate || this._compile(schemaObj);
}
/**
* Adds schema to the instance.
* @this Ajv
* @param {Object|Array} schema schema or array of schemas. If array is passed, `key` and other parameters will be ignored.
* @param {String} key Optional schema key. Can be passed to `validate` method instead of schema object or id/ref. One schema per instance can have empty `id` and `key`.
* @param {Boolean} _skipValidation true to skip schema validation. Used internally, option validateSchema should be used instead.
* @param {Boolean} _meta true if schema is a meta-schema. Used internally, addMetaSchema should be used instead.
* @return {Ajv} this for method chaining
*/
function addSchema(schema, key, _skipValidation, _meta) {
if (Array.isArray(schema)){
for (var i=0; i<schema.length; i++) this.addSchema(schema[i], undefined, _skipValidation, _meta);
return this;
}
var id = this._getId(schema);
if (id !== undefined && typeof id != 'string')
throw new Error('schema id must be string');
key = resolve.normalizeId(key || id);
checkUnique(this, key);
this._schemas[key] = this._addSchema(schema, _skipValidation, _meta, true);
return this;
}
/**
* Add schema that will be used to validate other schemas
* options in META_IGNORE_OPTIONS are alway set to false
* @this Ajv
* @param {Object} schema schema object
* @param {String} key optional schema key
* @param {Boolean} skipValidation true to skip schema validation, can be used to override validateSchema option for meta-schema
* @return {Ajv} this for method chaining
*/
function addMetaSchema(schema, key, skipValidation) {
this.addSchema(schema, key, skipValidation, true);
return this;
}
/**
* Validate schema
* @this Ajv
* @param {Object} schema schema to validate
* @param {Boolean} throwOrLogError pass true to throw (or log) an error if invalid
* @return {Boolean} true if schema is valid
*/
function validateSchema(schema, throwOrLogError) {
var $schema = schema.$schema;
if ($schema !== undefined && typeof $schema != 'string')
throw new Error('$schema must be a string');
$schema = $schema || this._opts.defaultMeta || defaultMeta(this);
if (!$schema) {
this.logger.warn('meta-schema not available');
this.errors = null;
return true;
}
var currentUriFormat = this._formats.uri;
this._formats.uri = typeof currentUriFormat == 'function'
? this._schemaUriFormatFunc
: this._schemaUriFormat;
var valid;
try { valid = this.validate($schema, schema); }
finally { this._formats.uri = currentUriFormat; }
if (!valid && throwOrLogError) {
var message = 'schema is invalid: ' + this.errorsText();
if (this._opts.validateSchema == 'log') this.logger.error(message);
else throw new Error(message);
}
return valid;
}
function defaultMeta(self) {
var meta = self._opts.meta;
self._opts.defaultMeta = typeof meta == 'object'
? self._getId(meta) || meta
: self.getSchema(META_SCHEMA_ID)
? META_SCHEMA_ID
: undefined;
return self._opts.defaultMeta;
}
/**
* Get compiled schema from the instance by `key` or `ref`.
* @this Ajv
* @param {String} keyRef `key` that was passed to `addSchema` or full schema reference (`schema.id` or resolved id).
* @return {Function} schema validating function (with property `schema`).
*/
function getSchema(keyRef) {
var schemaObj = _getSchemaObj(this, keyRef);
switch (typeof schemaObj) {
case 'object': return schemaObj.validate || this._compile(schemaObj);
case 'string': return this.getSchema(schemaObj);
case 'undefined': return _getSchemaFragment(this, keyRef);
}
}
function _getSchemaFragment(self, ref) {
var res = resolve.schema.call(self, { schema: {} }, ref);
if (res) {
var schema = res.schema
, root = res.root
, baseId = res.baseId;
var v = compileSchema.call(self, schema, root, undefined, baseId);
self._fragments[ref] = new SchemaObject({
ref: ref,
fragment: true,
schema: schema,
root: root,
baseId: baseId,
validate: v
});
return v;
}
}
function _getSchemaObj(self, keyRef) {
keyRef = resolve.normalizeId(keyRef);
return self._schemas[keyRef] || self._refs[keyRef] || self._fragments[keyRef];
}
/**
* Remove cached schema(s).
* If no parameter is passed all schemas but meta-schemas are removed.
* If RegExp is passed all schemas with key/id matching pattern but meta-schemas are removed.
* Even if schema is referenced by other schemas it still can be removed as other schemas have local references.
* @this Ajv
* @param {String|Object|RegExp} schemaKeyRef key, ref, pattern to match key/ref or schema object
* @return {Ajv} this for method chaining
*/
function removeSchema(schemaKeyRef) {
if (schemaKeyRef instanceof RegExp) {
_removeAllSchemas(this, this._schemas, schemaKeyRef);
_removeAllSchemas(this, this._refs, schemaKeyRef);
return this;
}
switch (typeof schemaKeyRef) {
case 'undefined':
_removeAllSchemas(this, this._schemas);
_removeAllSchemas(this, this._refs);
this._cache.clear();
return this;
case 'string':
var schemaObj = _getSchemaObj(this, schemaKeyRef);
if (schemaObj) this._cache.del(schemaObj.cacheKey);
delete this._schemas[schemaKeyRef];
delete this._refs[schemaKeyRef];
return this;
case 'object':
var serialize = this._opts.serialize;
var cacheKey = serialize ? serialize(schemaKeyRef) : schemaKeyRef;
this._cache.del(cacheKey);
var id = this._getId(schemaKeyRef);
if (id) {
id = resolve.normalizeId(id);
delete this._schemas[id];
delete this._refs[id];
}
}
return this;
}
function _removeAllSchemas(self, schemas, regex) {
for (var keyRef in schemas) {
var schemaObj = schemas[keyRef];
if (!schemaObj.meta && (!regex || regex.test(keyRef))) {
self._cache.del(schemaObj.cacheKey);
delete schemas[keyRef];
}
}
}
/* @this Ajv */
function _addSchema(schema, skipValidation, meta, shouldAddSchema) {
if (typeof schema != 'object' && typeof schema != 'boolean')
throw new Error('schema should be object or boolean');
var serialize = this._opts.serialize;
var cacheKey = serialize ? serialize(schema) : schema;
var cached = this._cache.get(cacheKey);
if (cached) return cached;
shouldAddSchema = shouldAddSchema || this._opts.addUsedSchema !== false;
var id = resolve.normalizeId(this._getId(schema));
if (id && shouldAddSchema) checkUnique(this, id);
var willValidate = this._opts.validateSchema !== false && !skipValidation;
var recursiveMeta;
if (willValidate && !(recursiveMeta = id && id == resolve.normalizeId(schema.$schema)))
this.validateSchema(schema, true);
var localRefs = resolve.ids.call(this, schema);
var schemaObj = new SchemaObject({
id: id,
schema: schema,
localRefs: localRefs,
cacheKey: cacheKey,
meta: meta
});
if (id[0] != '#' && shouldAddSchema) this._refs[id] = schemaObj;
this._cache.put(cacheKey, schemaObj);
if (willValidate && recursiveMeta) this.validateSchema(schema, true);
return schemaObj;
}
/* @this Ajv */
function _compile(schemaObj, root) {
if (schemaObj.compiling) {
schemaObj.validate = callValidate;
callValidate.schema = schemaObj.schema;
callValidate.errors = null;
callValidate.root = root ? root : callValidate;
if (schemaObj.schema.$async === true)
callValidate.$async = true;
return callValidate;
}
schemaObj.compiling = true;
var currentOpts;
if (schemaObj.meta) {
currentOpts = this._opts;
this._opts = this._metaOpts;
}
var v;
try { v = compileSchema.call(this, schemaObj.schema, root, schemaObj.localRefs); }
finally {
schemaObj.compiling = false;
if (schemaObj.meta) this._opts = currentOpts;
}
schemaObj.validate = v;
schemaObj.refs = v.refs;
schemaObj.refVal = v.refVal;
schemaObj.root = v.root;
return v;
function callValidate() {
var _validate = schemaObj.validate;
var result = _validate.apply(null, arguments);
callValidate.errors = _validate.errors;
return result;
}
}
function chooseGetId(opts) {
switch (opts.schemaId) {
case '$id': return _get$Id;
case 'id': return _getId;
default: return _get$IdOrId;
}
}
/* @this Ajv */
function _getId(schema) {
if (schema.$id) this.logger.warn('schema $id ignored', schema.$id);
return schema.id;
}
/* @this Ajv */
function _get$Id(schema) {
if (schema.id) this.logger.warn('schema id ignored', schema.id);
return schema.$id;
}
function _get$IdOrId(schema) {
if (schema.$id && schema.id && schema.$id != schema.id)
throw new Error('schema $id is different from id');
return schema.$id || schema.id;
}
/**
* Convert array of error message objects to string
* @this Ajv
* @param {Array<Object>} errors optional array of validation errors, if not passed errors from the instance are used.
* @param {Object} options optional options with properties `separator` and `dataVar`.
* @return {String} human readable string with all errors descriptions
*/
function errorsText(errors, options) {
errors = errors || this.errors;
if (!errors) return 'No errors';
options = options || {};
var separator = options.separator === undefined ? ', ' : options.separator;
var dataVar = options.dataVar === undefined ? 'data' : options.dataVar;
var text = '';
for (var i=0; i<errors.length; i++) {
var e = errors[i];
if (e) text += dataVar + e.dataPath + ' ' + e.message + separator;
}
return text.slice(0, -separator.length);
}
/**
* Add custom format
* @this Ajv
* @param {String} name format name
* @param {String|RegExp|Function} format string is converted to RegExp; function should return boolean (true when valid)
* @return {Ajv} this for method chaining
*/
function addFormat(name, format) {
if (typeof format == 'string') format = new RegExp(format);
this._formats[name] = format;
return this;
}
function addDraft6MetaSchema(self) {
var $dataSchema;
if (self._opts.$data) {
$dataSchema = require('./refs/$data.json');
self.addMetaSchema($dataSchema, $dataSchema.$id, true);
}
if (self._opts.meta === false) return;
var metaSchema = require('./refs/json-schema-draft-06.json');
if (self._opts.$data) metaSchema = $dataMetaSchema(metaSchema, META_SUPPORT_DATA);
self.addMetaSchema(metaSchema, META_SCHEMA_ID, true);
self._refs['http://json-schema.org/schema'] = META_SCHEMA_ID;
}
function addInitialSchemas(self) {
var optsSchemas = self._opts.schemas;
if (!optsSchemas) return;
if (Array.isArray(optsSchemas)) self.addSchema(optsSchemas);
else for (var key in optsSchemas) self.addSchema(optsSchemas[key], key);
}
function addInitialFormats(self) {
for (var name in self._opts.formats) {
var format = self._opts.formats[name];
self.addFormat(name, format);
}
}
function checkUnique(self, id) {
if (self._schemas[id] || self._refs[id])
throw new Error('schema with key or id "' + id + '" already exists');
}
function getMetaSchemaOptions(self) {
var metaOpts = util.copy(self._opts);
for (var i=0; i<META_IGNORE_OPTIONS.length; i++)
delete metaOpts[META_IGNORE_OPTIONS[i]];
return metaOpts;
}
function setLogger(self) {
var logger = self._opts.logger;
if (logger === false) {
self.logger = {log: noop, warn: noop, error: noop};
} else {
if (logger === undefined) logger = console;
if (!(typeof logger == 'object' && logger.log && logger.warn && logger.error))
throw new Error('logger must implement log, warn and error methods');
self.logger = logger;
}
}
function noop() {}
+26
View File
@@ -0,0 +1,26 @@
'use strict';
var Cache = module.exports = function Cache() {
this._cache = {};
};
Cache.prototype.put = function Cache_put(key, value) {
this._cache[key] = value;
};
Cache.prototype.get = function Cache_get(key) {
return this._cache[key];
};
Cache.prototype.del = function Cache_del(key) {
delete this._cache[key];
};
Cache.prototype.clear = function Cache_clear() {
this._cache = {};
};
+31
View File
@@ -0,0 +1,31 @@
'use strict';
//all requires must be explicit because browserify won't work with dynamic requires
module.exports = {
'$ref': require('../dotjs/ref'),
allOf: require('../dotjs/allOf'),
anyOf: require('../dotjs/anyOf'),
const: require('../dotjs/const'),
contains: require('../dotjs/contains'),
dependencies: require('../dotjs/dependencies'),
'enum': require('../dotjs/enum'),
format: require('../dotjs/format'),
items: require('../dotjs/items'),
maximum: require('../dotjs/_limit'),
minimum: require('../dotjs/_limit'),
maxItems: require('../dotjs/_limitItems'),
minItems: require('../dotjs/_limitItems'),
maxLength: require('../dotjs/_limitLength'),
minLength: require('../dotjs/_limitLength'),
maxProperties: require('../dotjs/_limitProperties'),
minProperties: require('../dotjs/_limitProperties'),
multipleOf: require('../dotjs/multipleOf'),
not: require('../dotjs/not'),
oneOf: require('../dotjs/oneOf'),
pattern: require('../dotjs/pattern'),
properties: require('../dotjs/properties'),
propertyNames: require('../dotjs/propertyNames'),
required: require('../dotjs/required'),
uniqueItems: require('../dotjs/uniqueItems'),
validate: require('../dotjs/validate')
};
+90
View File
@@ -0,0 +1,90 @@
'use strict';
var MissingRefError = require('./error_classes').MissingRef;
module.exports = compileAsync;
/**
* Creates validating function for passed schema with asynchronous loading of missing schemas.
* `loadSchema` option should be a function that accepts schema uri and returns promise that resolves with the schema.
* @this Ajv
* @param {Object} schema schema object
* @param {Boolean} meta optional true to compile meta-schema; this parameter can be skipped
* @param {Function} callback an optional node-style callback, it is called with 2 parameters: error (or null) and validating function.
* @return {Promise} promise that resolves with a validating function.
*/
function compileAsync(schema, meta, callback) {
/* eslint no-shadow: 0 */
/* global Promise */
/* jshint validthis: true */
var self = this;
if (typeof this._opts.loadSchema != 'function')
throw new Error('options.loadSchema should be a function');
if (typeof meta == 'function') {
callback = meta;
meta = undefined;
}
var p = loadMetaSchemaOf(schema).then(function () {
var schemaObj = self._addSchema(schema, undefined, meta);
return schemaObj.validate || _compileAsync(schemaObj);
});
if (callback) {
p.then(
function(v) { callback(null, v); },
callback
);
}
return p;
function loadMetaSchemaOf(sch) {
var $schema = sch.$schema;
return $schema && !self.getSchema($schema)
? compileAsync.call(self, { $ref: $schema }, true)
: Promise.resolve();
}
function _compileAsync(schemaObj) {
try { return self._compile(schemaObj); }
catch(e) {
if (e instanceof MissingRefError) return loadMissingSchema(e);
throw e;
}
function loadMissingSchema(e) {
var ref = e.missingSchema;
if (added(ref)) throw new Error('Schema ' + ref + ' is loaded but ' + e.missingRef + ' cannot be resolved');
var schemaPromise = self._loadingSchemas[ref];
if (!schemaPromise) {
schemaPromise = self._loadingSchemas[ref] = self._opts.loadSchema(ref);
schemaPromise.then(removePromise, removePromise);
}
return schemaPromise.then(function (sch) {
if (!added(ref)) {
return loadMetaSchemaOf(sch).then(function () {
if (!added(ref)) self.addSchema(sch, ref, undefined, meta);
});
}
}).then(function() {
return _compileAsync(schemaObj);
});
function removePromise() {
delete self._loadingSchemas[ref];
}
function added(ref) {
return self._refs[ref] || self._schemas[ref];
}
}
}
}
+3
View File
@@ -0,0 +1,3 @@
'use strict';
module.exports = require('fast-deep-equal');
+34
View File
@@ -0,0 +1,34 @@
'use strict';
var resolve = require('./resolve');
module.exports = {
Validation: errorSubclass(ValidationError),
MissingRef: errorSubclass(MissingRefError)
};
function ValidationError(errors) {
this.message = 'validation failed';
this.errors = errors;
this.ajv = this.validation = true;
}
MissingRefError.message = function (baseId, ref) {
return 'can\'t resolve reference ' + ref + ' from id ' + baseId;
};
function MissingRefError(baseId, ref, message) {
this.message = message || MissingRefError.message(baseId, ref);
this.missingRef = resolve.url(baseId, ref);
this.missingSchema = resolve.normalizeId(resolve.fullPath(this.missingRef));
}
function errorSubclass(Subclass) {
Subclass.prototype = Object.create(Error.prototype);
Subclass.prototype.constructor = Subclass;
return Subclass;
}
+135
View File
@@ -0,0 +1,135 @@
'use strict';
var util = require('./util');
var DATE = /^\d\d\d\d-(\d\d)-(\d\d)$/;
var DAYS = [0,31,29,31,30,31,30,31,31,30,31,30,31];
var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i;
var HOSTNAME = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*$/i;
var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
var URIREF = /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
// uri-template: https://tools.ietf.org/html/rfc6570
var URITEMPLATE = /^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i;
// For the source: https://gist.github.com/dperini/729294
// For test cases: https://mathiasbynens.be/demo/url-regex
// @todo Delete current URL in favour of the commented out URL rule when this issue is fixed https://github.com/eslint/eslint/issues/7983.
// var URL = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)(?:\.(?:[a-z\u{00a1}-\u{ffff}0-9]+-?)*[a-z\u{00a1}-\u{ffff}0-9]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu;
var URL = /^(?:(?:http[s\u017F]?|ftp):\/\/)(?:(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+(?::(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?@)?(?:(?!10(?:\.[0-9]{1,3}){3})(?!127(?:\.[0-9]{1,3}){3})(?!169\.254(?:\.[0-9]{1,3}){2})(?!192\.168(?:\.[0-9]{1,3}){2})(?!172\.(?:1[6-9]|2[0-9]|3[01])(?:\.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:\.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:\.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)(?:\.(?:(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+-?)*(?:[0-9KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+)*(?:\.(?:(?:[KSa-z\xA1-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]){2,})))(?::[0-9]{2,5})?(?:\/(?:[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uD7FF\uE000-\uFEFE\uFF00-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?$/i;
var UUID = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i;
var JSON_POINTER = /^(?:\/(?:[^~/]|~0|~1)*)*$|^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i;
var RELATIVE_JSON_POINTER = /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/;
module.exports = formats;
function formats(mode) {
mode = mode == 'full' ? 'full' : 'fast';
return util.copy(formats[mode]);
}
formats.fast = {
// date: http://tools.ietf.org/html/rfc3339#section-5.6
date: /^\d\d\d\d-[0-1]\d-[0-3]\d$/,
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6
time: /^[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i,
'date-time': /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s][0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i,
// uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js
uri: /^(?:[a-z][a-z0-9+-.]*)(?::|\/)\/?[^\s]*$/i,
'uri-reference': /^(?:(?:[a-z][a-z0-9+-.]*:)?\/\/)?[^\s]*$/i,
'uri-template': URITEMPLATE,
url: URL,
// email (sources from jsen validator):
// http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363
// http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'willful violation')
email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i,
hostname: HOSTNAME,
// optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
// optimized http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,
regex: regex,
// uuid: http://tools.ietf.org/html/rfc4122
uuid: UUID,
// JSON-pointer: https://tools.ietf.org/html/rfc6901
// uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A
'json-pointer': JSON_POINTER,
// relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00
'relative-json-pointer': RELATIVE_JSON_POINTER
};
formats.full = {
date: date,
time: time,
'date-time': date_time,
uri: uri,
'uri-reference': URIREF,
'uri-template': URITEMPLATE,
url: URL,
email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&''*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,
hostname: hostname,
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,
regex: regex,
uuid: UUID,
'json-pointer': JSON_POINTER,
'relative-json-pointer': RELATIVE_JSON_POINTER
};
function date(str) {
// full-date from http://tools.ietf.org/html/rfc3339#section-5.6
var matches = str.match(DATE);
if (!matches) return false;
var month = +matches[1];
var day = +matches[2];
return month >= 1 && month <= 12 && day >= 1 && day <= DAYS[month];
}
function time(str, full) {
var matches = str.match(TIME);
if (!matches) return false;
var hour = matches[1];
var minute = matches[2];
var second = matches[3];
var timeZone = matches[5];
return hour <= 23 && minute <= 59 && second <= 59 && (!full || timeZone);
}
var DATE_TIME_SEPARATOR = /t|\s/i;
function date_time(str) {
// http://tools.ietf.org/html/rfc3339#section-5.6
var dateTime = str.split(DATE_TIME_SEPARATOR);
return dateTime.length == 2 && date(dateTime[0]) && time(dateTime[1], true);
}
function hostname(str) {
// https://tools.ietf.org/html/rfc1034#section-3.5
// https://tools.ietf.org/html/rfc1123#section-2
return str.length <= 255 && HOSTNAME.test(str);
}
var NOT_URI_FRAGMENT = /\/|:/;
function uri(str) {
// http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "."
return NOT_URI_FRAGMENT.test(str) && URI.test(str);
}
var Z_ANCHOR = /[^\\]\\Z/;
function regex(str) {
if (Z_ANCHOR.test(str)) return false;
try {
new RegExp(str);
return true;
} catch(e) {
return false;
}
}
+380
View File
@@ -0,0 +1,380 @@
'use strict';
var resolve = require('./resolve')
, util = require('./util')
, errorClasses = require('./error_classes')
, stableStringify = require('fast-json-stable-stringify');
var validateGenerator = require('../dotjs/validate');
/**
* Functions below are used inside compiled validations function
*/
var co = require('co');
var ucs2length = util.ucs2length;
var equal = require('fast-deep-equal');
// this error is thrown by async schemas to return validation errors via exception
var ValidationError = errorClasses.Validation;
module.exports = compile;
/**
* Compiles schema to validation function
* @this Ajv
* @param {Object} schema schema object
* @param {Object} root object with information about the root schema for this schema
* @param {Object} localRefs the hash of local references inside the schema (created by resolve.id), used for inline resolution
* @param {String} baseId base ID for IDs in the schema
* @return {Function} validation function
*/
function compile(schema, root, localRefs, baseId) {
/* jshint validthis: true, evil: true */
/* eslint no-shadow: 0 */
var self = this
, opts = this._opts
, refVal = [ undefined ]
, refs = {}
, patterns = []
, patternsHash = {}
, defaults = []
, defaultsHash = {}
, customRules = [];
root = root || { schema: schema, refVal: refVal, refs: refs };
var c = checkCompiling.call(this, schema, root, baseId);
var compilation = this._compilations[c.index];
if (c.compiling) return (compilation.callValidate = callValidate);
var formats = this._formats;
var RULES = this.RULES;
try {
var v = localCompile(schema, root, localRefs, baseId);
compilation.validate = v;
var cv = compilation.callValidate;
if (cv) {
cv.schema = v.schema;
cv.errors = null;
cv.refs = v.refs;
cv.refVal = v.refVal;
cv.root = v.root;
cv.$async = v.$async;
if (opts.sourceCode) cv.source = v.source;
}
return v;
} finally {
endCompiling.call(this, schema, root, baseId);
}
function callValidate() {
var validate = compilation.validate;
var result = validate.apply(null, arguments);
callValidate.errors = validate.errors;
return result;
}
function localCompile(_schema, _root, localRefs, baseId) {
var isRoot = !_root || (_root && _root.schema == _schema);
if (_root.schema != root.schema)
return compile.call(self, _schema, _root, localRefs, baseId);
var $async = _schema.$async === true;
var sourceCode = validateGenerator({
isTop: true,
schema: _schema,
isRoot: isRoot,
baseId: baseId,
root: _root,
schemaPath: '',
errSchemaPath: '#',
errorPath: '""',
MissingRefError: errorClasses.MissingRef,
RULES: RULES,
validate: validateGenerator,
util: util,
resolve: resolve,
resolveRef: resolveRef,
usePattern: usePattern,
useDefault: useDefault,
useCustomRule: useCustomRule,
opts: opts,
formats: formats,
logger: self.logger,
self: self
});
sourceCode = vars(refVal, refValCode) + vars(patterns, patternCode)
+ vars(defaults, defaultCode) + vars(customRules, customRuleCode)
+ sourceCode;
if (opts.processCode) sourceCode = opts.processCode(sourceCode);
// console.log('\n\n\n *** \n', JSON.stringify(sourceCode));
var validate;
try {
var makeValidate = new Function(
'self',
'RULES',
'formats',
'root',
'refVal',
'defaults',
'customRules',
'co',
'equal',
'ucs2length',
'ValidationError',
sourceCode
);
validate = makeValidate(
self,
RULES,
formats,
root,
refVal,
defaults,
customRules,
co,
equal,
ucs2length,
ValidationError
);
refVal[0] = validate;
} catch(e) {
self.logger.error('Error compiling schema, function code:', sourceCode);
throw e;
}
validate.schema = _schema;
validate.errors = null;
validate.refs = refs;
validate.refVal = refVal;
validate.root = isRoot ? validate : _root;
if ($async) validate.$async = true;
if (opts.sourceCode === true) {
validate.source = {
code: sourceCode,
patterns: patterns,
defaults: defaults
};
}
return validate;
}
function resolveRef(baseId, ref, isRoot) {
ref = resolve.url(baseId, ref);
var refIndex = refs[ref];
var _refVal, refCode;
if (refIndex !== undefined) {
_refVal = refVal[refIndex];
refCode = 'refVal[' + refIndex + ']';
return resolvedRef(_refVal, refCode);
}
if (!isRoot && root.refs) {
var rootRefId = root.refs[ref];
if (rootRefId !== undefined) {
_refVal = root.refVal[rootRefId];
refCode = addLocalRef(ref, _refVal);
return resolvedRef(_refVal, refCode);
}
}
refCode = addLocalRef(ref);
var v = resolve.call(self, localCompile, root, ref);
if (v === undefined) {
var localSchema = localRefs && localRefs[ref];
if (localSchema) {
v = resolve.inlineRef(localSchema, opts.inlineRefs)
? localSchema
: compile.call(self, localSchema, root, localRefs, baseId);
}
}
if (v === undefined) {
removeLocalRef(ref);
} else {
replaceLocalRef(ref, v);
return resolvedRef(v, refCode);
}
}
function addLocalRef(ref, v) {
var refId = refVal.length;
refVal[refId] = v;
refs[ref] = refId;
return 'refVal' + refId;
}
function removeLocalRef(ref) {
delete refs[ref];
}
function replaceLocalRef(ref, v) {
var refId = refs[ref];
refVal[refId] = v;
}
function resolvedRef(refVal, code) {
return typeof refVal == 'object' || typeof refVal == 'boolean'
? { code: code, schema: refVal, inline: true }
: { code: code, $async: refVal && refVal.$async };
}
function usePattern(regexStr) {
var index = patternsHash[regexStr];
if (index === undefined) {
index = patternsHash[regexStr] = patterns.length;
patterns[index] = regexStr;
}
return 'pattern' + index;
}
function useDefault(value) {
switch (typeof value) {
case 'boolean':
case 'number':
return '' + value;
case 'string':
return util.toQuotedString(value);
case 'object':
if (value === null) return 'null';
var valueStr = stableStringify(value);
var index = defaultsHash[valueStr];
if (index === undefined) {
index = defaultsHash[valueStr] = defaults.length;
defaults[index] = value;
}
return 'default' + index;
}
}
function useCustomRule(rule, schema, parentSchema, it) {
var validateSchema = rule.definition.validateSchema;
if (validateSchema && self._opts.validateSchema !== false) {
var valid = validateSchema(schema);
if (!valid) {
var message = 'keyword schema is invalid: ' + self.errorsText(validateSchema.errors);
if (self._opts.validateSchema == 'log') self.logger.error(message);
else throw new Error(message);
}
}
var compile = rule.definition.compile
, inline = rule.definition.inline
, macro = rule.definition.macro;
var validate;
if (compile) {
validate = compile.call(self, schema, parentSchema, it);
} else if (macro) {
validate = macro.call(self, schema, parentSchema, it);
if (opts.validateSchema !== false) self.validateSchema(validate, true);
} else if (inline) {
validate = inline.call(self, it, rule.keyword, schema, parentSchema);
} else {
validate = rule.definition.validate;
if (!validate) return;
}
if (validate === undefined)
throw new Error('custom keyword "' + rule.keyword + '"failed to compile');
var index = customRules.length;
customRules[index] = validate;
return {
code: 'customRule' + index,
validate: validate
};
}
}
/**
* Checks if the schema is currently compiled
* @this Ajv
* @param {Object} schema schema to compile
* @param {Object} root root object
* @param {String} baseId base schema ID
* @return {Object} object with properties "index" (compilation index) and "compiling" (boolean)
*/
function checkCompiling(schema, root, baseId) {
/* jshint validthis: true */
var index = compIndex.call(this, schema, root, baseId);
if (index >= 0) return { index: index, compiling: true };
index = this._compilations.length;
this._compilations[index] = {
schema: schema,
root: root,
baseId: baseId
};
return { index: index, compiling: false };
}
/**
* Removes the schema from the currently compiled list
* @this Ajv
* @param {Object} schema schema to compile
* @param {Object} root root object
* @param {String} baseId base schema ID
*/
function endCompiling(schema, root, baseId) {
/* jshint validthis: true */
var i = compIndex.call(this, schema, root, baseId);
if (i >= 0) this._compilations.splice(i, 1);
}
/**
* Index of schema compilation in the currently compiled list
* @this Ajv
* @param {Object} schema schema to compile
* @param {Object} root root object
* @param {String} baseId base schema ID
* @return {Integer} compilation index
*/
function compIndex(schema, root, baseId) {
/* jshint validthis: true */
for (var i=0; i<this._compilations.length; i++) {
var c = this._compilations[i];
if (c.schema == schema && c.root == root && c.baseId == baseId) return i;
}
return -1;
}
function patternCode(i, patterns) {
return 'var pattern' + i + ' = new RegExp(' + util.toQuotedString(patterns[i]) + ');';
}
function defaultCode(i) {
return 'var default' + i + ' = defaults[' + i + '];';
}
function refValCode(i, refVal) {
return refVal[i] === undefined ? '' : 'var refVal' + i + ' = refVal[' + i + '];';
}
function customRuleCode(i) {
return 'var customRule' + i + ' = customRules[' + i + '];';
}
function vars(arr, statement) {
if (!arr.length) return '';
var code = '';
for (var i=0; i<arr.length; i++)
code += statement(i, arr);
return code;
}
+271
View File
@@ -0,0 +1,271 @@
'use strict';
var url = require('url')
, equal = require('fast-deep-equal')
, util = require('./util')
, SchemaObject = require('./schema_obj')
, traverse = require('json-schema-traverse');
module.exports = resolve;
resolve.normalizeId = normalizeId;
resolve.fullPath = getFullPath;
resolve.url = resolveUrl;
resolve.ids = resolveIds;
resolve.inlineRef = inlineRef;
resolve.schema = resolveSchema;
/**
* [resolve and compile the references ($ref)]
* @this Ajv
* @param {Function} compile reference to schema compilation funciton (localCompile)
* @param {Object} root object with information about the root schema for the current schema
* @param {String} ref reference to resolve
* @return {Object|Function} schema object (if the schema can be inlined) or validation function
*/
function resolve(compile, root, ref) {
/* jshint validthis: true */
var refVal = this._refs[ref];
if (typeof refVal == 'string') {
if (this._refs[refVal]) refVal = this._refs[refVal];
else return resolve.call(this, compile, root, refVal);
}
refVal = refVal || this._schemas[ref];
if (refVal instanceof SchemaObject) {
return inlineRef(refVal.schema, this._opts.inlineRefs)
? refVal.schema
: refVal.validate || this._compile(refVal);
}
var res = resolveSchema.call(this, root, ref);
var schema, v, baseId;
if (res) {
schema = res.schema;
root = res.root;
baseId = res.baseId;
}
if (schema instanceof SchemaObject) {
v = schema.validate || compile.call(this, schema.schema, root, undefined, baseId);
} else if (schema !== undefined) {
v = inlineRef(schema, this._opts.inlineRefs)
? schema
: compile.call(this, schema, root, undefined, baseId);
}
return v;
}
/**
* Resolve schema, its root and baseId
* @this Ajv
* @param {Object} root root object with properties schema, refVal, refs
* @param {String} ref reference to resolve
* @return {Object} object with properties schema, root, baseId
*/
function resolveSchema(root, ref) {
/* jshint validthis: true */
var p = url.parse(ref, false, true)
, refPath = _getFullPath(p)
, baseId = getFullPath(this._getId(root.schema));
if (refPath !== baseId) {
var id = normalizeId(refPath);
var refVal = this._refs[id];
if (typeof refVal == 'string') {
return resolveRecursive.call(this, root, refVal, p);
} else if (refVal instanceof SchemaObject) {
if (!refVal.validate) this._compile(refVal);
root = refVal;
} else {
refVal = this._schemas[id];
if (refVal instanceof SchemaObject) {
if (!refVal.validate) this._compile(refVal);
if (id == normalizeId(ref))
return { schema: refVal, root: root, baseId: baseId };
root = refVal;
} else {
return;
}
}
if (!root.schema) return;
baseId = getFullPath(this._getId(root.schema));
}
return getJsonPointer.call(this, p, baseId, root.schema, root);
}
/* @this Ajv */
function resolveRecursive(root, ref, parsedRef) {
/* jshint validthis: true */
var res = resolveSchema.call(this, root, ref);
if (res) {
var schema = res.schema;
var baseId = res.baseId;
root = res.root;
var id = this._getId(schema);
if (id) baseId = resolveUrl(baseId, id);
return getJsonPointer.call(this, parsedRef, baseId, schema, root);
}
}
var PREVENT_SCOPE_CHANGE = util.toHash(['properties', 'patternProperties', 'enum', 'dependencies', 'definitions']);
/* @this Ajv */
function getJsonPointer(parsedRef, baseId, schema, root) {
/* jshint validthis: true */
parsedRef.hash = parsedRef.hash || '';
if (parsedRef.hash.slice(0,2) != '#/') return;
var parts = parsedRef.hash.split('/');
for (var i = 1; i < parts.length; i++) {
var part = parts[i];
if (part) {
part = util.unescapeFragment(part);
schema = schema[part];
if (schema === undefined) break;
var id;
if (!PREVENT_SCOPE_CHANGE[part]) {
id = this._getId(schema);
if (id) baseId = resolveUrl(baseId, id);
if (schema.$ref) {
var $ref = resolveUrl(baseId, schema.$ref);
var res = resolveSchema.call(this, root, $ref);
if (res) {
schema = res.schema;
root = res.root;
baseId = res.baseId;
}
}
}
}
}
if (schema !== undefined && schema !== root.schema)
return { schema: schema, root: root, baseId: baseId };
}
var SIMPLE_INLINED = util.toHash([
'type', 'format', 'pattern',
'maxLength', 'minLength',
'maxProperties', 'minProperties',
'maxItems', 'minItems',
'maximum', 'minimum',
'uniqueItems', 'multipleOf',
'required', 'enum'
]);
function inlineRef(schema, limit) {
if (limit === false) return false;
if (limit === undefined || limit === true) return checkNoRef(schema);
else if (limit) return countKeys(schema) <= limit;
}
function checkNoRef(schema) {
var item;
if (Array.isArray(schema)) {
for (var i=0; i<schema.length; i++) {
item = schema[i];
if (typeof item == 'object' && !checkNoRef(item)) return false;
}
} else {
for (var key in schema) {
if (key == '$ref') return false;
item = schema[key];
if (typeof item == 'object' && !checkNoRef(item)) return false;
}
}
return true;
}
function countKeys(schema) {
var count = 0, item;
if (Array.isArray(schema)) {
for (var i=0; i<schema.length; i++) {
item = schema[i];
if (typeof item == 'object') count += countKeys(item);
if (count == Infinity) return Infinity;
}
} else {
for (var key in schema) {
if (key == '$ref') return Infinity;
if (SIMPLE_INLINED[key]) {
count++;
} else {
item = schema[key];
if (typeof item == 'object') count += countKeys(item) + 1;
if (count == Infinity) return Infinity;
}
}
}
return count;
}
function getFullPath(id, normalize) {
if (normalize !== false) id = normalizeId(id);
var p = url.parse(id, false, true);
return _getFullPath(p);
}
function _getFullPath(p) {
var protocolSeparator = p.protocol || p.href.slice(0,2) == '//' ? '//' : '';
return (p.protocol||'') + protocolSeparator + (p.host||'') + (p.path||'') + '#';
}
var TRAILING_SLASH_HASH = /#\/?$/;
function normalizeId(id) {
return id ? id.replace(TRAILING_SLASH_HASH, '') : '';
}
function resolveUrl(baseId, id) {
id = normalizeId(id);
return url.resolve(baseId, id);
}
/* @this Ajv */
function resolveIds(schema) {
var schemaId = normalizeId(this._getId(schema));
var baseIds = {'': schemaId};
var fullPaths = {'': getFullPath(schemaId, false)};
var localRefs = {};
var self = this;
traverse(schema, {allKeys: true}, function(sch, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) {
if (jsonPtr === '') return;
var id = self._getId(sch);
var baseId = baseIds[parentJsonPtr];
var fullPath = fullPaths[parentJsonPtr] + '/' + parentKeyword;
if (keyIndex !== undefined)
fullPath += '/' + (typeof keyIndex == 'number' ? keyIndex : util.escapeFragment(keyIndex));
if (typeof id == 'string') {
id = baseId = normalizeId(baseId ? url.resolve(baseId, id) : id);
var refVal = self._refs[id];
if (typeof refVal == 'string') refVal = self._refs[refVal];
if (refVal && refVal.schema) {
if (!equal(sch, refVal.schema))
throw new Error('id "' + id + '" resolves to more than one schema');
} else if (id != normalizeId(fullPath)) {
if (id[0] == '#') {
if (localRefs[id] && !equal(sch, localRefs[id]))
throw new Error('id "' + id + '" resolves to more than one schema');
localRefs[id] = sch;
} else {
self._refs[id] = fullPath;
}
}
}
baseIds[jsonPtr] = baseId;
fullPaths[jsonPtr] = fullPath;
});
return localRefs;
}
+58
View File
@@ -0,0 +1,58 @@
'use strict';
var ruleModules = require('./_rules')
, toHash = require('./util').toHash;
module.exports = function rules() {
var RULES = [
{ type: 'number',
rules: [ { 'maximum': ['exclusiveMaximum'] },
{ 'minimum': ['exclusiveMinimum'] }, 'multipleOf', 'format'] },
{ type: 'string',
rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] },
{ type: 'array',
rules: [ 'maxItems', 'minItems', 'uniqueItems', 'contains', 'items' ] },
{ type: 'object',
rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'propertyNames',
{ 'properties': ['additionalProperties', 'patternProperties'] } ] },
{ rules: [ '$ref', 'const', 'enum', 'not', 'anyOf', 'oneOf', 'allOf' ] }
];
var ALL = [ 'type' ];
var KEYWORDS = [
'additionalItems', '$schema', '$id', 'id', 'title',
'description', 'default', 'definitions'
];
var TYPES = [ 'number', 'integer', 'string', 'array', 'object', 'boolean', 'null' ];
RULES.all = toHash(ALL);
RULES.types = toHash(TYPES);
RULES.forEach(function (group) {
group.rules = group.rules.map(function (keyword) {
var implKeywords;
if (typeof keyword == 'object') {
var key = Object.keys(keyword)[0];
implKeywords = keyword[key];
keyword = key;
implKeywords.forEach(function (k) {
ALL.push(k);
RULES.all[k] = true;
});
}
ALL.push(keyword);
var rule = RULES.all[keyword] = {
keyword: keyword,
code: ruleModules[keyword],
implements: implKeywords
};
return rule;
});
if (group.type) RULES.types[group.type] = group;
});
RULES.keywords = toHash(ALL.concat(KEYWORDS));
RULES.custom = {};
return RULES;
};
+9
View File
@@ -0,0 +1,9 @@
'use strict';
var util = require('./util');
module.exports = SchemaObject;
function SchemaObject(obj) {
util.copy(obj, this);
}
+20
View File
@@ -0,0 +1,20 @@
'use strict';
// https://mathiasbynens.be/notes/javascript-encoding
// https://github.com/bestiejs/punycode.js - punycode.ucs2.decode
module.exports = function ucs2length(str) {
var length = 0
, len = str.length
, pos = 0
, value;
while (pos < len) {
length++;
value = str.charCodeAt(pos++);
if (value >= 0xD800 && value <= 0xDBFF && pos < len) {
// high surrogate, and there is a next character
value = str.charCodeAt(pos);
if ((value & 0xFC00) == 0xDC00) pos++; // low surrogate
}
}
return length;
};
+267
View File
@@ -0,0 +1,267 @@
'use strict';
module.exports = {
copy: copy,
checkDataType: checkDataType,
checkDataTypes: checkDataTypes,
coerceToTypes: coerceToTypes,
toHash: toHash,
getProperty: getProperty,
escapeQuotes: escapeQuotes,
equal: require('fast-deep-equal'),
ucs2length: require('./ucs2length'),
varOccurences: varOccurences,
varReplace: varReplace,
cleanUpCode: cleanUpCode,
finalCleanUpCode: finalCleanUpCode,
schemaHasRules: schemaHasRules,
schemaHasRulesExcept: schemaHasRulesExcept,
toQuotedString: toQuotedString,
getPathExpr: getPathExpr,
getPath: getPath,
getData: getData,
unescapeFragment: unescapeFragment,
unescapeJsonPointer: unescapeJsonPointer,
escapeFragment: escapeFragment,
escapeJsonPointer: escapeJsonPointer
};
function copy(o, to) {
to = to || {};
for (var key in o) to[key] = o[key];
return to;
}
function checkDataType(dataType, data, negate) {
var EQUAL = negate ? ' !== ' : ' === '
, AND = negate ? ' || ' : ' && '
, OK = negate ? '!' : ''
, NOT = negate ? '' : '!';
switch (dataType) {
case 'null': return data + EQUAL + 'null';
case 'array': return OK + 'Array.isArray(' + data + ')';
case 'object': return '(' + OK + data + AND +
'typeof ' + data + EQUAL + '"object"' + AND +
NOT + 'Array.isArray(' + data + '))';
case 'integer': return '(typeof ' + data + EQUAL + '"number"' + AND +
NOT + '(' + data + ' % 1)' +
AND + data + EQUAL + data + ')';
default: return 'typeof ' + data + EQUAL + '"' + dataType + '"';
}
}
function checkDataTypes(dataTypes, data) {
switch (dataTypes.length) {
case 1: return checkDataType(dataTypes[0], data, true);
default:
var code = '';
var types = toHash(dataTypes);
if (types.array && types.object) {
code = types.null ? '(': '(!' + data + ' || ';
code += 'typeof ' + data + ' !== "object")';
delete types.null;
delete types.array;
delete types.object;
}
if (types.number) delete types.integer;
for (var t in types)
code += (code ? ' && ' : '' ) + checkDataType(t, data, true);
return code;
}
}
var COERCE_TO_TYPES = toHash([ 'string', 'number', 'integer', 'boolean', 'null' ]);
function coerceToTypes(optionCoerceTypes, dataTypes) {
if (Array.isArray(dataTypes)) {
var types = [];
for (var i=0; i<dataTypes.length; i++) {
var t = dataTypes[i];
if (COERCE_TO_TYPES[t]) types[types.length] = t;
else if (optionCoerceTypes === 'array' && t === 'array') types[types.length] = t;
}
if (types.length) return types;
} else if (COERCE_TO_TYPES[dataTypes]) {
return [dataTypes];
} else if (optionCoerceTypes === 'array' && dataTypes === 'array') {
return ['array'];
}
}
function toHash(arr) {
var hash = {};
for (var i=0; i<arr.length; i++) hash[arr[i]] = true;
return hash;
}
var IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i;
var SINGLE_QUOTE = /'|\\/g;
function getProperty(key) {
return typeof key == 'number'
? '[' + key + ']'
: IDENTIFIER.test(key)
? '.' + key
: "['" + escapeQuotes(key) + "']";
}
function escapeQuotes(str) {
return str.replace(SINGLE_QUOTE, '\\$&')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/\f/g, '\\f')
.replace(/\t/g, '\\t');
}
function varOccurences(str, dataVar) {
dataVar += '[^0-9]';
var matches = str.match(new RegExp(dataVar, 'g'));
return matches ? matches.length : 0;
}
function varReplace(str, dataVar, expr) {
dataVar += '([^0-9])';
expr = expr.replace(/\$/g, '$$$$');
return str.replace(new RegExp(dataVar, 'g'), expr + '$1');
}
var EMPTY_ELSE = /else\s*{\s*}/g
, EMPTY_IF_NO_ELSE = /if\s*\([^)]+\)\s*\{\s*\}(?!\s*else)/g
, EMPTY_IF_WITH_ELSE = /if\s*\(([^)]+)\)\s*\{\s*\}\s*else(?!\s*if)/g;
function cleanUpCode(out) {
return out.replace(EMPTY_ELSE, '')
.replace(EMPTY_IF_NO_ELSE, '')
.replace(EMPTY_IF_WITH_ELSE, 'if (!($1))');
}
var ERRORS_REGEXP = /[^v.]errors/g
, REMOVE_ERRORS = /var errors = 0;|var vErrors = null;|validate.errors = vErrors;/g
, REMOVE_ERRORS_ASYNC = /var errors = 0;|var vErrors = null;/g
, RETURN_VALID = 'return errors === 0;'
, RETURN_TRUE = 'validate.errors = null; return true;'
, RETURN_ASYNC = /if \(errors === 0\) return data;\s*else throw new ValidationError\(vErrors\);/
, RETURN_DATA_ASYNC = 'return data;'
, ROOTDATA_REGEXP = /[^A-Za-z_$]rootData[^A-Za-z0-9_$]/g
, REMOVE_ROOTDATA = /if \(rootData === undefined\) rootData = data;/;
function finalCleanUpCode(out, async) {
var matches = out.match(ERRORS_REGEXP);
if (matches && matches.length == 2) {
out = async
? out.replace(REMOVE_ERRORS_ASYNC, '')
.replace(RETURN_ASYNC, RETURN_DATA_ASYNC)
: out.replace(REMOVE_ERRORS, '')
.replace(RETURN_VALID, RETURN_TRUE);
}
matches = out.match(ROOTDATA_REGEXP);
if (!matches || matches.length !== 3) return out;
return out.replace(REMOVE_ROOTDATA, '');
}
function schemaHasRules(schema, rules) {
if (typeof schema == 'boolean') return !schema;
for (var key in schema) if (rules[key]) return true;
}
function schemaHasRulesExcept(schema, rules, exceptKeyword) {
if (typeof schema == 'boolean') return !schema && exceptKeyword != 'not';
for (var key in schema) if (key != exceptKeyword && rules[key]) return true;
}
function toQuotedString(str) {
return '\'' + escapeQuotes(str) + '\'';
}
function getPathExpr(currentPath, expr, jsonPointers, isNumber) {
var path = jsonPointers // false by default
? '\'/\' + ' + expr + (isNumber ? '' : '.replace(/~/g, \'~0\').replace(/\\//g, \'~1\')')
: (isNumber ? '\'[\' + ' + expr + ' + \']\'' : '\'[\\\'\' + ' + expr + ' + \'\\\']\'');
return joinPaths(currentPath, path);
}
function getPath(currentPath, prop, jsonPointers) {
var path = jsonPointers // false by default
? toQuotedString('/' + escapeJsonPointer(prop))
: toQuotedString(getProperty(prop));
return joinPaths(currentPath, path);
}
var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
function getData($data, lvl, paths) {
var up, jsonPointer, data, matches;
if ($data === '') return 'rootData';
if ($data[0] == '/') {
if (!JSON_POINTER.test($data)) throw new Error('Invalid JSON-pointer: ' + $data);
jsonPointer = $data;
data = 'rootData';
} else {
matches = $data.match(RELATIVE_JSON_POINTER);
if (!matches) throw new Error('Invalid JSON-pointer: ' + $data);
up = +matches[1];
jsonPointer = matches[2];
if (jsonPointer == '#') {
if (up >= lvl) throw new Error('Cannot access property/index ' + up + ' levels up, current level is ' + lvl);
return paths[lvl - up];
}
if (up > lvl) throw new Error('Cannot access data ' + up + ' levels up, current level is ' + lvl);
data = 'data' + ((lvl - up) || '');
if (!jsonPointer) return data;
}
var expr = data;
var segments = jsonPointer.split('/');
for (var i=0; i<segments.length; i++) {
var segment = segments[i];
if (segment) {
data += getProperty(unescapeJsonPointer(segment));
expr += ' && ' + data;
}
}
return expr;
}
function joinPaths (a, b) {
if (a == '""') return b;
return (a + ' + ' + b).replace(/' \+ '/g, '');
}
function unescapeFragment(str) {
return unescapeJsonPointer(decodeURIComponent(str));
}
function escapeFragment(str) {
return encodeURIComponent(escapeJsonPointer(str));
}
function escapeJsonPointer(str) {
return str.replace(/~/g, '~0').replace(/\//g, '~1');
}
function unescapeJsonPointer(str) {
return str.replace(/~1/g, '/').replace(/~0/g, '~');
}
+96
View File
@@ -0,0 +1,96 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{## def.setExclusiveLimit:
$exclusive = true;
$errorKeyword = $exclusiveKeyword;
$errSchemaPath = it.errSchemaPath + '/' + $exclusiveKeyword;
#}}
{{
var $isMax = $keyword == 'maximum'
, $exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum'
, $schemaExcl = it.schema[$exclusiveKeyword]
, $isDataExcl = it.opts.$data && $schemaExcl && $schemaExcl.$data
, $op = $isMax ? '<' : '>'
, $notOp = $isMax ? '>' : '<'
, $errorKeyword = undefined;
}}
{{? $isDataExcl }}
{{
var $schemaValueExcl = it.util.getData($schemaExcl.$data, $dataLvl, it.dataPathArr)
, $exclusive = 'exclusive' + $lvl
, $exclType = 'exclType' + $lvl
, $exclIsNumber = 'exclIsNumber' + $lvl
, $opExpr = 'op' + $lvl
, $opStr = '\' + ' + $opExpr + ' + \'';
}}
var schemaExcl{{=$lvl}} = {{=$schemaValueExcl}};
{{ $schemaValueExcl = 'schemaExcl' + $lvl; }}
var {{=$exclusive}};
var {{=$exclType}} = typeof {{=$schemaValueExcl}};
if ({{=$exclType}} != 'boolean' && {{=$exclType}} != 'undefined' && {{=$exclType}} != 'number') {
{{ var $errorKeyword = $exclusiveKeyword; }}
{{# def.error:'_exclusiveLimit' }}
} else if ({{# def.$dataNotType:'number' }}
{{=$exclType}} == 'number'
? (
({{=$exclusive}} = {{=$schemaValue}} === undefined || {{=$schemaValueExcl}} {{=$op}}= {{=$schemaValue}})
? {{=$data}} {{=$notOp}}= {{=$schemaValueExcl}}
: {{=$data}} {{=$notOp}} {{=$schemaValue}}
)
: (
({{=$exclusive}} = {{=$schemaValueExcl}} === true)
? {{=$data}} {{=$notOp}}= {{=$schemaValue}}
: {{=$data}} {{=$notOp}} {{=$schemaValue}}
)
|| {{=$data}} !== {{=$data}}) {
var op{{=$lvl}} = {{=$exclusive}} ? '{{=$op}}' : '{{=$op}}=';
{{??}}
{{
var $exclIsNumber = typeof $schemaExcl == 'number'
, $opStr = $op; /*used in error*/
}}
{{? $exclIsNumber && $isData }}
{{ var $opExpr = '\'' + $opStr + '\''; /*used in error*/ }}
if ({{# def.$dataNotType:'number' }}
( {{=$schemaValue}} === undefined
|| {{=$schemaExcl}} {{=$op}}= {{=$schemaValue}}
? {{=$data}} {{=$notOp}}= {{=$schemaExcl}}
: {{=$data}} {{=$notOp}} {{=$schemaValue}} )
|| {{=$data}} !== {{=$data}}) {
{{??}}
{{
if ($exclIsNumber && $schema === undefined) {
{{# def.setExclusiveLimit }}
$schemaValue = $schemaExcl;
$notOp += '=';
} else {
if ($exclIsNumber)
$schemaValue = Math[$isMax ? 'min' : 'max']($schemaExcl, $schema);
if ($schemaExcl === ($exclIsNumber ? $schemaValue : true)) {
{{# def.setExclusiveLimit }}
$notOp += '=';
} else {
$exclusive = false;
$opStr += '=';
}
}
var $opExpr = '\'' + $opStr + '\''; /*used in error*/
}}
if ({{# def.$dataNotType:'number' }}
{{=$data}} {{=$notOp}} {{=$schemaValue}}
|| {{=$data}} !== {{=$data}}) {
{{?}}
{{?}}
{{ $errorKeyword = $errorKeyword || $keyword; }}
{{# def.error:'_limit' }}
} {{? $breakOnError }} else { {{?}}
+10
View File
@@ -0,0 +1,10 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $op = $keyword == 'maxItems' ? '>' : '<'; }}
if ({{# def.$dataNotType:'number' }} {{=$data}}.length {{=$op}} {{=$schemaValue}}) {
{{ var $errorKeyword = $keyword; }}
{{# def.error:'_limitItems' }}
} {{? $breakOnError }} else { {{?}}
+10
View File
@@ -0,0 +1,10 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $op = $keyword == 'maxLength' ? '>' : '<'; }}
if ({{# def.$dataNotType:'number' }} {{# def.strLength }} {{=$op}} {{=$schemaValue}}) {
{{ var $errorKeyword = $keyword; }}
{{# def.error:'_limitLength' }}
} {{? $breakOnError }} else { {{?}}
+10
View File
@@ -0,0 +1,10 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $op = $keyword == 'maxProperties' ? '>' : '<'; }}
if ({{# def.$dataNotType:'number' }} Object.keys({{=$data}}).length {{=$op}} {{=$schemaValue}}) {
{{ var $errorKeyword = $keyword; }}
{{# def.error:'_limitProperties' }}
} {{? $breakOnError }} else { {{?}}
+34
View File
@@ -0,0 +1,34 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{
var $currentBaseId = $it.baseId
, $allSchemasEmpty = true;
}}
{{~ $schema:$sch:$i }}
{{? {{# def.nonEmptySchema:$sch }} }}
{{
$allSchemasEmpty = false;
$it.schema = $sch;
$it.schemaPath = $schemaPath + '[' + $i + ']';
$it.errSchemaPath = $errSchemaPath + '/' + $i;
}}
{{# def.insertSubschemaCode }}
{{# def.ifResultValid }}
{{?}}
{{~}}
{{? $breakOnError }}
{{? $allSchemasEmpty }}
if (true) {
{{??}}
{{= $closingBraces.slice(0,-1) }}
{{?}}
{{?}}
{{# def.cleanUp }}
+48
View File
@@ -0,0 +1,48 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{
var $noEmptySchema = $schema.every(function($sch) {
return {{# def.nonEmptySchema:$sch }};
});
}}
{{? $noEmptySchema }}
{{ var $currentBaseId = $it.baseId; }}
var {{=$errs}} = errors;
var {{=$valid}} = false;
{{# def.setCompositeRule }}
{{~ $schema:$sch:$i }}
{{
$it.schema = $sch;
$it.schemaPath = $schemaPath + '[' + $i + ']';
$it.errSchemaPath = $errSchemaPath + '/' + $i;
}}
{{# def.insertSubschemaCode }}
{{=$valid}} = {{=$valid}} || {{=$nextValid}};
if (!{{=$valid}}) {
{{ $closingBraces += '}'; }}
{{~}}
{{# def.resetCompositeRule }}
{{= $closingBraces }}
if (!{{=$valid}}) {
{{# def.extraError:'anyOf' }}
} else {
{{# def.resetErrors }}
{{? it.opts.allErrors }} } {{?}}
{{# def.cleanUp }}
{{??}}
{{? $breakOnError }}
if (true) {
{{?}}
{{?}}
+61
View File
@@ -0,0 +1,61 @@
{{## def.coerceType:
{{
var $dataType = 'dataType' + $lvl
, $coerced = 'coerced' + $lvl;
}}
var {{=$dataType}} = typeof {{=$data}};
{{? it.opts.coerceTypes == 'array'}}
if ({{=$dataType}} == 'object' && Array.isArray({{=$data}})) {{=$dataType}} = 'array';
{{?}}
var {{=$coerced}} = undefined;
{{ var $bracesCoercion = ''; }}
{{~ $coerceToTypes:$type:$i }}
{{? $i }}
if ({{=$coerced}} === undefined) {
{{ $bracesCoercion += '}'; }}
{{?}}
{{? it.opts.coerceTypes == 'array' && $type != 'array' }}
if ({{=$dataType}} == 'array' && {{=$data}}.length == 1) {
{{=$coerced}} = {{=$data}} = {{=$data}}[0];
{{=$dataType}} = typeof {{=$data}};
/*if ({{=$dataType}} == 'object' && Array.isArray({{=$data}})) {{=$dataType}} = 'array';*/
}
{{?}}
{{? $type == 'string' }}
if ({{=$dataType}} == 'number' || {{=$dataType}} == 'boolean')
{{=$coerced}} = '' + {{=$data}};
else if ({{=$data}} === null) {{=$coerced}} = '';
{{?? $type == 'number' || $type == 'integer' }}
if ({{=$dataType}} == 'boolean' || {{=$data}} === null
|| ({{=$dataType}} == 'string' && {{=$data}} && {{=$data}} == +{{=$data}}
{{? $type == 'integer' }} && !({{=$data}} % 1){{?}}))
{{=$coerced}} = +{{=$data}};
{{?? $type == 'boolean' }}
if ({{=$data}} === 'false' || {{=$data}} === 0 || {{=$data}} === null)
{{=$coerced}} = false;
else if ({{=$data}} === 'true' || {{=$data}} === 1)
{{=$coerced}} = true;
{{?? $type == 'null' }}
if ({{=$data}} === '' || {{=$data}} === 0 || {{=$data}} === false)
{{=$coerced}} = null;
{{?? it.opts.coerceTypes == 'array' && $type == 'array' }}
if ({{=$dataType}} == 'string' || {{=$dataType}} == 'number' || {{=$dataType}} == 'boolean' || {{=$data}} == null)
{{=$coerced}} = [{{=$data}}];
{{?}}
{{~}}
{{= $bracesCoercion }}
if ({{=$coerced}} === undefined) {
{{# def.error:'type' }}
} else {
{{# def.setParentData }}
{{=$data}} = {{=$coerced}};
{{? !$dataLvl }}if ({{=$parentData}} !== undefined){{?}}
{{=$parentData}}[{{=$parentDataProperty}}] = {{=$coerced}};
}
#}}
+11
View File
@@ -0,0 +1,11 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{? !$isData }}
var schema{{=$lvl}} = validate.schema{{=$schemaPath}};
{{?}}
var {{=$valid}} = equal({{=$data}}, schema{{=$lvl}});
{{# def.checkError:'const' }}
{{? $breakOnError }} else { {{?}}
+57
View File
@@ -0,0 +1,57 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{
var $idx = 'i' + $lvl
, $dataNxt = $it.dataLevel = it.dataLevel + 1
, $nextData = 'data' + $dataNxt
, $currentBaseId = it.baseId
, $nonEmptySchema = {{# def.nonEmptySchema:$schema }};
}}
var {{=$errs}} = errors;
var {{=$valid}};
{{? $nonEmptySchema }}
{{# def.setCompositeRule }}
{{
$it.schema = $schema;
$it.schemaPath = $schemaPath;
$it.errSchemaPath = $errSchemaPath;
}}
var {{=$nextValid}} = false;
for (var {{=$idx}} = 0; {{=$idx}} < {{=$data}}.length; {{=$idx}}++) {
{{
$it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true);
var $passData = $data + '[' + $idx + ']';
$it.dataPathArr[$dataNxt] = $idx;
}}
{{# def.generateSubschemaCode }}
{{# def.optimizeValidate }}
if ({{=$nextValid}}) break;
}
{{# def.resetCompositeRule }}
{{= $closingBraces }}
if (!{{=$nextValid}}) {
{{??}}
if ({{=$data}}.length == 0) {
{{?}}
{{# def.error:'contains' }}
} else {
{{? $nonEmptySchema }}
{{# def.resetErrors }}
{{?}}
{{? it.opts.allErrors }} } {{?}}
{{# def.cleanUp }}
+191
View File
@@ -0,0 +1,191 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{
var $rule = this
, $definition = 'definition' + $lvl
, $rDef = $rule.definition
, $closingBraces = '';
var $validate = $rDef.validate;
var $compile, $inline, $macro, $ruleValidate, $validateCode;
}}
{{? $isData && $rDef.$data }}
{{
$validateCode = 'keywordValidate' + $lvl;
var $validateSchema = $rDef.validateSchema;
}}
var {{=$definition}} = RULES.custom['{{=$keyword}}'].definition;
var {{=$validateCode}} = {{=$definition}}.validate;
{{??}}
{{
$ruleValidate = it.useCustomRule($rule, $schema, it.schema, it);
if (!$ruleValidate) return;
$schemaValue = 'validate.schema' + $schemaPath;
$validateCode = $ruleValidate.code;
$compile = $rDef.compile;
$inline = $rDef.inline;
$macro = $rDef.macro;
}}
{{?}}
{{
var $ruleErrs = $validateCode + '.errors'
, $i = 'i' + $lvl
, $ruleErr = 'ruleErr' + $lvl
, $asyncKeyword = $rDef.async;
if ($asyncKeyword && !it.async)
throw new Error('async keyword in sync schema');
}}
{{? !($inline || $macro) }}{{=$ruleErrs}} = null;{{?}}
var {{=$errs}} = errors;
var {{=$valid}};
{{## def.callRuleValidate:
{{=$validateCode}}.call(
{{? it.opts.passContext }}this{{??}}self{{?}}
{{? $compile || $rDef.schema === false }}
, {{=$data}}
{{??}}
, {{=$schemaValue}}
, {{=$data}}
, validate.schema{{=it.schemaPath}}
{{?}}
, {{# def.dataPath }}
{{# def.passParentData }}
, rootData
)
#}}
{{## def.extendErrors:_inline:
for (var {{=$i}}={{=$errs}}; {{=$i}}<errors; {{=$i}}++) {
var {{=$ruleErr}} = vErrors[{{=$i}}];
if ({{=$ruleErr}}.dataPath === undefined)
{{=$ruleErr}}.dataPath = (dataPath || '') + {{= it.errorPath }};
{{# _inline ? 'if (\{\{=$ruleErr\}\}.schemaPath === undefined) {' : '' }}
{{=$ruleErr}}.schemaPath = "{{=$errSchemaPath}}";
{{# _inline ? '}' : '' }}
{{? it.opts.verbose }}
{{=$ruleErr}}.schema = {{=$schemaValue}};
{{=$ruleErr}}.data = {{=$data}};
{{?}}
}
#}}
{{? $isData && $rDef.$data }}
{{ $closingBraces += '}'; }}
if ({{=$schemaValue}} === undefined) {
{{=$valid}} = true;
} else {
{{? $validateSchema }}
{{ $closingBraces += '}'; }}
{{=$valid}} = {{=$definition}}.validateSchema({{=$schemaValue}});
if ({{=$valid}}) {
{{?}}
{{?}}
{{? $inline }}
{{? $rDef.statements }}
{{= $ruleValidate.validate }}
{{??}}
{{=$valid}} = {{= $ruleValidate.validate }};
{{?}}
{{?? $macro }}
{{# def.setupNextLevel }}
{{
$it.schema = $ruleValidate.validate;
$it.schemaPath = '';
}}
{{# def.setCompositeRule }}
{{ var $code = it.validate($it).replace(/validate\.schema/g, $validateCode); }}
{{# def.resetCompositeRule }}
{{= $code }}
{{??}}
{{# def.beginDefOut}}
{{# def.callRuleValidate }}
{{# def.storeDefOut:def_callRuleValidate }}
{{? $rDef.errors === false }}
{{=$valid}} = {{? $asyncKeyword }}{{=it.yieldAwait}}{{?}}{{= def_callRuleValidate }};
{{??}}
{{? $asyncKeyword }}
{{ $ruleErrs = 'customErrors' + $lvl; }}
var {{=$ruleErrs}} = null;
try {
{{=$valid}} = {{=it.yieldAwait}}{{= def_callRuleValidate }};
} catch (e) {
{{=$valid}} = false;
if (e instanceof ValidationError) {{=$ruleErrs}} = e.errors;
else throw e;
}
{{??}}
{{=$ruleErrs}} = null;
{{=$valid}} = {{= def_callRuleValidate }};
{{?}}
{{?}}
{{?}}
{{? $rDef.modifying }}
if ({{=$parentData}}) {{=$data}} = {{=$parentData}}[{{=$parentDataProperty}}];
{{?}}
{{= $closingBraces }}
{{## def.notValidationResult:
{{? $rDef.valid === undefined }}
!{{? $macro }}{{=$nextValid}}{{??}}{{=$valid}}{{?}}
{{??}}
{{= !$rDef.valid }}
{{?}}
#}}
{{? $rDef.valid }}
{{? $breakOnError }} if (true) { {{?}}
{{??}}
if ({{# def.notValidationResult }}) {
{{ $errorKeyword = $rule.keyword; }}
{{# def.beginDefOut}}
{{# def.error:'custom' }}
{{# def.storeDefOut:def_customError }}
{{? $inline }}
{{? $rDef.errors }}
{{? $rDef.errors != 'full' }}
{{# def.extendErrors:true }}
{{?}}
{{??}}
{{? $rDef.errors === false}}
{{= def_customError }}
{{??}}
if ({{=$errs}} == errors) {
{{= def_customError }}
} else {
{{# def.extendErrors:true }}
}
{{?}}
{{?}}
{{?? $macro }}
{{# def.extraError:'custom' }}
{{??}}
{{? $rDef.errors === false}}
{{= def_customError }}
{{??}}
if (Array.isArray({{=$ruleErrs}})) {
if (vErrors === null) vErrors = {{=$ruleErrs}};
else vErrors = vErrors.concat({{=$ruleErrs}});
errors = vErrors.length;
{{# def.extendErrors:false }}
} else {
{{= def_customError }}
}
{{?}}
{{?}}
} {{? $breakOnError }} else { {{?}}
{{?}}
+32
View File
@@ -0,0 +1,32 @@
{{## def.assignDefault:
if ({{=$passData}} === undefined)
{{=$passData}} = {{? it.opts.useDefaults == 'shared' }}
{{= it.useDefault($sch.default) }}
{{??}}
{{= JSON.stringify($sch.default) }}
{{?}};
#}}
{{## def.defaultProperties:
{{
var $schema = it.schema.properties
, $schemaKeys = Object.keys($schema); }}
{{~ $schemaKeys:$propertyKey }}
{{ var $sch = $schema[$propertyKey]; }}
{{? $sch.default !== undefined }}
{{ var $passData = $data + it.util.getProperty($propertyKey); }}
{{# def.assignDefault }}
{{?}}
{{~}}
#}}
{{## def.defaultItems:
{{~ it.schema.items:$sch:$i }}
{{? $sch.default !== undefined }}
{{ var $passData = $data + '[' + $i + ']'; }}
{{# def.assignDefault }}
{{?}}
{{~}}
#}}
+199
View File
@@ -0,0 +1,199 @@
{{## def.setupKeyword:
{{
var $lvl = it.level;
var $dataLvl = it.dataLevel;
var $schema = it.schema[$keyword];
var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
var $breakOnError = !it.opts.allErrors;
var $errorKeyword;
var $data = 'data' + ($dataLvl || '');
var $valid = 'valid' + $lvl;
var $errs = 'errs__' + $lvl;
}}
#}}
{{## def.setCompositeRule:
{{
var $wasComposite = it.compositeRule;
it.compositeRule = $it.compositeRule = true;
}}
#}}
{{## def.resetCompositeRule:
{{ it.compositeRule = $it.compositeRule = $wasComposite; }}
#}}
{{## def.setupNextLevel:
{{
var $it = it.util.copy(it);
var $closingBraces = '';
$it.level++;
var $nextValid = 'valid' + $it.level;
}}
#}}
{{## def.ifValid:
{{? $breakOnError }}
if ({{=$valid}}) {
{{ $closingBraces += '}'; }}
{{?}}
#}}
{{## def.ifResultValid:
{{? $breakOnError }}
if ({{=$nextValid}}) {
{{ $closingBraces += '}'; }}
{{?}}
#}}
{{## def.elseIfValid:
{{? $breakOnError }}
{{ $closingBraces += '}'; }}
else {
{{?}}
#}}
{{## def.nonEmptySchema:_schema:
it.util.schemaHasRules(_schema, it.RULES.all)
#}}
{{## def.strLength:
{{? it.opts.unicode === false }}
{{=$data}}.length
{{??}}
ucs2length({{=$data}})
{{?}}
#}}
{{## def.willOptimize:
it.util.varOccurences($code, $nextData) < 2
#}}
{{## def.generateSubschemaCode:
{{
var $code = it.validate($it);
$it.baseId = $currentBaseId;
}}
#}}
{{## def.insertSubschemaCode:
{{= it.validate($it) }}
{{ $it.baseId = $currentBaseId; }}
#}}
{{## def._optimizeValidate:
it.util.varReplace($code, $nextData, $passData)
#}}
{{## def.optimizeValidate:
{{? {{# def.willOptimize}} }}
{{= {{# def._optimizeValidate }} }}
{{??}}
var {{=$nextData}} = {{=$passData}};
{{= $code }}
{{?}}
#}}
{{## def.cleanUp: {{ out = it.util.cleanUpCode(out); }} #}}
{{## def.finalCleanUp: {{ out = it.util.finalCleanUpCode(out, $async); }} #}}
{{## def.$data:
{{
var $isData = it.opts.$data && $schema && $schema.$data
, $schemaValue;
}}
{{? $isData }}
var schema{{=$lvl}} = {{= it.util.getData($schema.$data, $dataLvl, it.dataPathArr) }};
{{ $schemaValue = 'schema' + $lvl; }}
{{??}}
{{ $schemaValue = $schema; }}
{{?}}
#}}
{{## def.$dataNotType:_type:
{{?$isData}} ({{=$schemaValue}} !== undefined && typeof {{=$schemaValue}} != _type) || {{?}}
#}}
{{## def.check$dataIsArray:
if (schema{{=$lvl}} === undefined) {{=$valid}} = true;
else if (!Array.isArray(schema{{=$lvl}})) {{=$valid}} = false;
else {
#}}
{{## def.beginDefOut:
{{
var $$outStack = $$outStack || [];
$$outStack.push(out);
out = '';
}}
#}}
{{## def.storeDefOut:_variable:
{{
var _variable = out;
out = $$outStack.pop();
}}
#}}
{{## def.dataPath:(dataPath || ''){{? it.errorPath != '""'}} + {{= it.errorPath }}{{?}}#}}
{{## def.setParentData:
{{
var $parentData = $dataLvl ? 'data' + (($dataLvl-1)||'') : 'parentData'
, $parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty';
}}
#}}
{{## def.passParentData:
{{# def.setParentData }}
, {{= $parentData }}
, {{= $parentDataProperty }}
#}}
{{## def.iterateProperties:
{{? $ownProperties }}
{{=$dataProperties}} = {{=$dataProperties}} || Object.keys({{=$data}});
for (var {{=$idx}}=0; {{=$idx}}<{{=$dataProperties}}.length; {{=$idx}}++) {
var {{=$key}} = {{=$dataProperties}}[{{=$idx}}];
{{??}}
for (var {{=$key}} in {{=$data}}) {
{{?}}
#}}
{{## def.noPropertyInData:
{{=$useData}} === undefined
{{? $ownProperties }}
|| !{{# def.isOwnProperty }}
{{?}}
#}}
{{## def.isOwnProperty:
Object.prototype.hasOwnProperty.call({{=$data}}, '{{=it.util.escapeQuotes($propertyKey)}}')
#}}
+80
View File
@@ -0,0 +1,80 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.missing }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{## def.propertyInData:
{{=$data}}{{= it.util.getProperty($property) }} !== undefined
{{? $ownProperties }}
&& Object.prototype.hasOwnProperty.call({{=$data}}, '{{=it.util.escapeQuotes($property)}}')
{{?}}
#}}
{{
var $schemaDeps = {}
, $propertyDeps = {}
, $ownProperties = it.opts.ownProperties;
for ($property in $schema) {
var $sch = $schema[$property];
var $deps = Array.isArray($sch) ? $propertyDeps : $schemaDeps;
$deps[$property] = $sch;
}
}}
var {{=$errs}} = errors;
{{ var $currentErrorPath = it.errorPath; }}
var missing{{=$lvl}};
{{ for (var $property in $propertyDeps) { }}
{{ $deps = $propertyDeps[$property]; }}
{{? $deps.length }}
if ({{# def.propertyInData }}
{{? $breakOnError }}
&& ({{# def.checkMissingProperty:$deps }})) {
{{# def.errorMissingProperty:'dependencies' }}
{{??}}
) {
{{~ $deps:$propertyKey }}
{{# def.allErrorsMissingProperty:'dependencies' }}
{{~}}
{{?}}
} {{# def.elseIfValid }}
{{?}}
{{ } }}
{{
it.errorPath = $currentErrorPath;
var $currentBaseId = $it.baseId;
}}
{{ for (var $property in $schemaDeps) { }}
{{ var $sch = $schemaDeps[$property]; }}
{{? {{# def.nonEmptySchema:$sch }} }}
{{=$nextValid}} = true;
if ({{# def.propertyInData }}) {
{{
$it.schema = $sch;
$it.schemaPath = $schemaPath + it.util.getProperty($property);
$it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($property);
}}
{{# def.insertSubschemaCode }}
}
{{# def.ifResultValid }}
{{?}}
{{ } }}
{{? $breakOnError }}
{{= $closingBraces }}
if ({{=$errs}} == errors) {
{{?}}
{{# def.cleanUp }}
+30
View File
@@ -0,0 +1,30 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{
var $i = 'i' + $lvl
, $vSchema = 'schema' + $lvl;
}}
{{? !$isData }}
var {{=$vSchema}} = validate.schema{{=$schemaPath}};
{{?}}
var {{=$valid}};
{{?$isData}}{{# def.check$dataIsArray }}{{?}}
{{=$valid}} = false;
for (var {{=$i}}=0; {{=$i}}<{{=$vSchema}}.length; {{=$i}}++)
if (equal({{=$data}}, {{=$vSchema}}[{{=$i}}])) {
{{=$valid}} = true;
break;
}
{{? $isData }} } {{?}}
{{# def.checkError:'enum' }}
{{? $breakOnError }} else { {{?}}
+194
View File
@@ -0,0 +1,194 @@
{{# def.definitions }}
{{## def._error:_rule:
{{ 'istanbul ignore else'; }}
{{? it.createErrors !== false }}
{
keyword: '{{= $errorKeyword || _rule }}'
, dataPath: (dataPath || '') + {{= it.errorPath }}
, schemaPath: {{=it.util.toQuotedString($errSchemaPath)}}
, params: {{# def._errorParams[_rule] }}
{{? it.opts.messages !== false }}
, message: {{# def._errorMessages[_rule] }}
{{?}}
{{? it.opts.verbose }}
, schema: {{# def._errorSchemas[_rule] }}
, parentSchema: validate.schema{{=it.schemaPath}}
, data: {{=$data}}
{{?}}
}
{{??}}
{}
{{?}}
#}}
{{## def._addError:_rule:
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
#}}
{{## def.addError:_rule:
var err = {{# def._error:_rule }};
{{# def._addError:_rule }}
#}}
{{## def.error:_rule:
{{# def.beginDefOut}}
{{# def._error:_rule }}
{{# def.storeDefOut:__err }}
{{? !it.compositeRule && $breakOnError }}
{{ 'istanbul ignore if'; }}
{{? it.async }}
throw new ValidationError([{{=__err}}]);
{{??}}
validate.errors = [{{=__err}}];
return false;
{{?}}
{{??}}
var err = {{=__err}};
{{# def._addError:_rule }}
{{?}}
#}}
{{## def.extraError:_rule:
{{# def.addError:_rule}}
{{? !it.compositeRule && $breakOnError }}
{{ 'istanbul ignore if'; }}
{{? it.async }}
throw new ValidationError(vErrors);
{{??}}
validate.errors = vErrors;
return false;
{{?}}
{{?}}
#}}
{{## def.checkError:_rule:
if (!{{=$valid}}) {
{{# def.error:_rule }}
}
#}}
{{## def.resetErrors:
errors = {{=$errs}};
if (vErrors !== null) {
if ({{=$errs}}) vErrors.length = {{=$errs}};
else vErrors = null;
}
#}}
{{## def.concatSchema:{{?$isData}}' + {{=$schemaValue}} + '{{??}}{{=$schema}}{{?}}#}}
{{## def.appendSchema:{{?$isData}}' + {{=$schemaValue}}{{??}}{{=$schemaValue}}'{{?}}#}}
{{## def.concatSchemaEQ:{{?$isData}}' + {{=$schemaValue}} + '{{??}}{{=it.util.escapeQuotes($schema)}}{{?}}#}}
{{## def._errorMessages = {
'false schema': "'boolean schema is false'",
$ref: "'can\\\'t resolve reference {{=it.util.escapeQuotes($schema)}}'",
additionalItems: "'should NOT have more than {{=$schema.length}} items'",
additionalProperties: "'should NOT have additional properties'",
anyOf: "'should match some schema in anyOf'",
const: "'should be equal to constant'",
contains: "'should contain a valid item'",
dependencies: "'should have {{? $deps.length == 1 }}property {{= it.util.escapeQuotes($deps[0]) }}{{??}}properties {{= it.util.escapeQuotes($deps.join(\", \")) }}{{?}} when property {{= it.util.escapeQuotes($property) }} is present'",
'enum': "'should be equal to one of the allowed values'",
format: "'should match format \"{{#def.concatSchemaEQ}}\"'",
_limit: "'should be {{=$opStr}} {{#def.appendSchema}}",
_exclusiveLimit: "'{{=$exclusiveKeyword}} should be boolean'",
_limitItems: "'should NOT have {{?$keyword=='maxItems'}}more{{??}}less{{?}} than {{#def.concatSchema}} items'",
_limitLength: "'should NOT be {{?$keyword=='maxLength'}}longer{{??}}shorter{{?}} than {{#def.concatSchema}} characters'",
_limitProperties:"'should NOT have {{?$keyword=='maxProperties'}}more{{??}}less{{?}} than {{#def.concatSchema}} properties'",
multipleOf: "'should be multiple of {{#def.appendSchema}}",
not: "'should NOT be valid'",
oneOf: "'should match exactly one schema in oneOf'",
pattern: "'should match pattern \"{{#def.concatSchemaEQ}}\"'",
patternGroups: "'should NOT have {{=$moreOrLess}} than {{=$limit}} properties matching pattern \"{{=it.util.escapeQuotes($pgProperty)}}\"'",
propertyNames: "'property name \\'{{=$invalidName}}\\' is invalid'",
required: "'{{? it.opts._errorDataPathProperty }}is a required property{{??}}should have required property \\'{{=$missingProperty}}\\'{{?}}'",
type: "'should be {{? $typeIsArray }}{{= $typeSchema.join(\",\") }}{{??}}{{=$typeSchema}}{{?}}'",
uniqueItems: "'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)'",
custom: "'should pass \"{{=$rule.keyword}}\" keyword validation'",
patternRequired: "'should have property matching pattern \\'{{=$missingPattern}}\\''",
switch: "'should pass \"switch\" keyword validation'",
_formatLimit: "'should be {{=$opStr}} \"{{#def.concatSchemaEQ}}\"'",
_formatExclusiveLimit: "'{{=$exclusiveKeyword}} should be boolean'"
} #}}
{{## def.schemaRefOrVal: {{?$isData}}validate.schema{{=$schemaPath}}{{??}}{{=$schema}}{{?}} #}}
{{## def.schemaRefOrQS: {{?$isData}}validate.schema{{=$schemaPath}}{{??}}{{=it.util.toQuotedString($schema)}}{{?}} #}}
{{## def._errorSchemas = {
'false schema': "false",
$ref: "{{=it.util.toQuotedString($schema)}}",
additionalItems: "false",
additionalProperties: "false",
anyOf: "validate.schema{{=$schemaPath}}",
const: "validate.schema{{=$schemaPath}}",
contains: "validate.schema{{=$schemaPath}}",
dependencies: "validate.schema{{=$schemaPath}}",
'enum': "validate.schema{{=$schemaPath}}",
format: "{{#def.schemaRefOrQS}}",
_limit: "{{#def.schemaRefOrVal}}",
_exclusiveLimit: "validate.schema{{=$schemaPath}}",
_limitItems: "{{#def.schemaRefOrVal}}",
_limitLength: "{{#def.schemaRefOrVal}}",
_limitProperties:"{{#def.schemaRefOrVal}}",
multipleOf: "{{#def.schemaRefOrVal}}",
not: "validate.schema{{=$schemaPath}}",
oneOf: "validate.schema{{=$schemaPath}}",
pattern: "{{#def.schemaRefOrQS}}",
patternGroups: "validate.schema{{=$schemaPath}}",
propertyNames: "validate.schema{{=$schemaPath}}",
required: "validate.schema{{=$schemaPath}}",
type: "validate.schema{{=$schemaPath}}",
uniqueItems: "{{#def.schemaRefOrVal}}",
custom: "validate.schema{{=$schemaPath}}",
patternRequired: "validate.schema{{=$schemaPath}}",
switch: "validate.schema{{=$schemaPath}}",
_formatLimit: "{{#def.schemaRefOrQS}}",
_formatExclusiveLimit: "validate.schema{{=$schemaPath}}"
} #}}
{{## def.schemaValueQS: {{?$isData}}{{=$schemaValue}}{{??}}{{=it.util.toQuotedString($schema)}}{{?}} #}}
{{## def._errorParams = {
'false schema': "{}",
$ref: "{ ref: '{{=it.util.escapeQuotes($schema)}}' }",
additionalItems: "{ limit: {{=$schema.length}} }",
additionalProperties: "{ additionalProperty: '{{=$additionalProperty}}' }",
anyOf: "{}",
const: "{}",
contains: "{}",
dependencies: "{ property: '{{= it.util.escapeQuotes($property) }}', missingProperty: '{{=$missingProperty}}', depsCount: {{=$deps.length}}, deps: '{{= it.util.escapeQuotes($deps.length==1 ? $deps[0] : $deps.join(\", \")) }}' }",
'enum': "{ allowedValues: schema{{=$lvl}} }",
format: "{ format: {{#def.schemaValueQS}} }",
_limit: "{ comparison: {{=$opExpr}}, limit: {{=$schemaValue}}, exclusive: {{=$exclusive}} }",
_exclusiveLimit: "{}",
_limitItems: "{ limit: {{=$schemaValue}} }",
_limitLength: "{ limit: {{=$schemaValue}} }",
_limitProperties:"{ limit: {{=$schemaValue}} }",
multipleOf: "{ multipleOf: {{=$schemaValue}} }",
not: "{}",
oneOf: "{}",
pattern: "{ pattern: {{#def.schemaValueQS}} }",
patternGroups: "{ reason: '{{=$reason}}', limit: {{=$limit}}, pattern: '{{=it.util.escapeQuotes($pgProperty)}}' }",
propertyNames: "{ propertyName: '{{=$invalidName}}' }",
required: "{ missingProperty: '{{=$missingProperty}}' }",
type: "{ type: '{{? $typeIsArray }}{{= $typeSchema.join(\",\") }}{{??}}{{=$typeSchema}}{{?}}' }",
uniqueItems: "{ i: i, j: j }",
custom: "{ keyword: '{{=$rule.keyword}}' }",
patternRequired: "{ missingPattern: '{{=$missingPattern}}' }",
switch: "{ caseIndex: {{=$caseIndex}} }",
_formatLimit: "{ comparison: {{=$opExpr}}, limit: {{#def.schemaValueQS}}, exclusive: {{=$exclusive}} }",
_formatExclusiveLimit: "{}"
} #}}
+106
View File
@@ -0,0 +1,106 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{## def.skipFormat:
{{? $breakOnError }} if (true) { {{?}}
{{ return out; }}
#}}
{{? it.opts.format === false }}{{# def.skipFormat }}{{?}}
{{# def.$data }}
{{## def.$dataCheckFormat:
{{# def.$dataNotType:'string' }}
({{? $unknownFormats != 'ignore' }}
({{=$schemaValue}} && !{{=$format}}
{{? $allowUnknown }}
&& self._opts.unknownFormats.indexOf({{=$schemaValue}}) == -1
{{?}}) ||
{{?}}
({{=$format}} && {{=$formatType}} == '{{=$ruleType}}'
&& !(typeof {{=$format}} == 'function'
? {{? it.async}}
(async{{=$lvl}} ? {{=it.yieldAwait}} {{=$format}}({{=$data}}) : {{=$format}}({{=$data}}))
{{??}}
{{=$format}}({{=$data}})
{{?}}
: {{=$format}}.test({{=$data}}))))
#}}
{{## def.checkFormat:
{{
var $formatRef = 'formats' + it.util.getProperty($schema);
if ($isObject) $formatRef += '.validate';
}}
{{? typeof $format == 'function' }}
{{=$formatRef}}({{=$data}})
{{??}}
{{=$formatRef}}.test({{=$data}})
{{?}}
#}}
{{
var $unknownFormats = it.opts.unknownFormats
, $allowUnknown = Array.isArray($unknownFormats);
}}
{{? $isData }}
{{
var $format = 'format' + $lvl
, $isObject = 'isObject' + $lvl
, $formatType = 'formatType' + $lvl;
}}
var {{=$format}} = formats[{{=$schemaValue}}];
var {{=$isObject}} = typeof {{=$format}} == 'object'
&& !({{=$format}} instanceof RegExp)
&& {{=$format}}.validate;
var {{=$formatType}} = {{=$isObject}} && {{=$format}}.type || 'string';
if ({{=$isObject}}) {
{{? it.async}}
var async{{=$lvl}} = {{=$format}}.async;
{{?}}
{{=$format}} = {{=$format}}.validate;
}
if ({{# def.$dataCheckFormat }}) {
{{??}}
{{ var $format = it.formats[$schema]; }}
{{? !$format }}
{{? $unknownFormats == 'ignore' }}
{{ it.logger.warn('unknown format "' + $schema + '" ignored in schema at path "' + it.errSchemaPath + '"'); }}
{{# def.skipFormat }}
{{?? $allowUnknown && $unknownFormats.indexOf($schema) >= 0 }}
{{# def.skipFormat }}
{{??}}
{{ throw new Error('unknown format "' + $schema + '" is used in schema at path "' + it.errSchemaPath + '"'); }}
{{?}}
{{?}}
{{
var $isObject = typeof $format == 'object'
&& !($format instanceof RegExp)
&& $format.validate;
var $formatType = $isObject && $format.type || 'string';
if ($isObject) {
var $async = $format.async === true;
$format = $format.validate;
}
}}
{{? $formatType != $ruleType }}
{{# def.skipFormat }}
{{?}}
{{? $async }}
{{
if (!it.async) throw new Error('async format in sync schema');
var $formatRef = 'formats' + it.util.getProperty($schema) + '.validate';
}}
if (!({{=it.yieldAwait}} {{=$formatRef}}({{=$data}}))) {
{{??}}
if (!{{# def.checkFormat }}) {
{{?}}
{{?}}
{{# def.error:'format' }}
} {{? $breakOnError }} else { {{?}}
+100
View File
@@ -0,0 +1,100 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{## def.validateItems:startFrom:
for (var {{=$idx}} = {{=startFrom}}; {{=$idx}} < {{=$data}}.length; {{=$idx}}++) {
{{
$it.errorPath = it.util.getPathExpr(it.errorPath, $idx, it.opts.jsonPointers, true);
var $passData = $data + '[' + $idx + ']';
$it.dataPathArr[$dataNxt] = $idx;
}}
{{# def.generateSubschemaCode }}
{{# def.optimizeValidate }}
{{? $breakOnError }}
if (!{{=$nextValid}}) break;
{{?}}
}
#}}
{{
var $idx = 'i' + $lvl
, $dataNxt = $it.dataLevel = it.dataLevel + 1
, $nextData = 'data' + $dataNxt
, $currentBaseId = it.baseId;
}}
var {{=$errs}} = errors;
var {{=$valid}};
{{? Array.isArray($schema) }}
{{ /* 'items' is an array of schemas */}}
{{ var $additionalItems = it.schema.additionalItems; }}
{{? $additionalItems === false }}
{{=$valid}} = {{=$data}}.length <= {{= $schema.length }};
{{
var $currErrSchemaPath = $errSchemaPath;
$errSchemaPath = it.errSchemaPath + '/additionalItems';
}}
{{# def.checkError:'additionalItems' }}
{{ $errSchemaPath = $currErrSchemaPath; }}
{{# def.elseIfValid}}
{{?}}
{{~ $schema:$sch:$i }}
{{? {{# def.nonEmptySchema:$sch }} }}
{{=$nextValid}} = true;
if ({{=$data}}.length > {{=$i}}) {
{{
var $passData = $data + '[' + $i + ']';
$it.schema = $sch;
$it.schemaPath = $schemaPath + '[' + $i + ']';
$it.errSchemaPath = $errSchemaPath + '/' + $i;
$it.errorPath = it.util.getPathExpr(it.errorPath, $i, it.opts.jsonPointers, true);
$it.dataPathArr[$dataNxt] = $i;
}}
{{# def.generateSubschemaCode }}
{{# def.optimizeValidate }}
}
{{# def.ifResultValid }}
{{?}}
{{~}}
{{? typeof $additionalItems == 'object' && {{# def.nonEmptySchema:$additionalItems }} }}
{{
$it.schema = $additionalItems;
$it.schemaPath = it.schemaPath + '.additionalItems';
$it.errSchemaPath = it.errSchemaPath + '/additionalItems';
}}
{{=$nextValid}} = true;
if ({{=$data}}.length > {{= $schema.length }}) {
{{# def.validateItems: $schema.length }}
}
{{# def.ifResultValid }}
{{?}}
{{?? {{# def.nonEmptySchema:$schema }} }}
{{ /* 'items' is a single schema */}}
{{
$it.schema = $schema;
$it.schemaPath = $schemaPath;
$it.errSchemaPath = $errSchemaPath;
}}
{{# def.validateItems: 0 }}
{{?}}
{{? $breakOnError }}
{{= $closingBraces }}
if ({{=$errs}} == errors) {
{{?}}
{{# def.cleanUp }}
+39
View File
@@ -0,0 +1,39 @@
{{## def.checkMissingProperty:_properties:
{{~ _properties:$propertyKey:$i }}
{{?$i}} || {{?}}
{{
var $prop = it.util.getProperty($propertyKey)
, $useData = $data + $prop;
}}
( ({{# def.noPropertyInData }}) && (missing{{=$lvl}} = {{= it.util.toQuotedString(it.opts.jsonPointers ? $propertyKey : $prop) }}) )
{{~}}
#}}
{{## def.errorMissingProperty:_error:
{{
var $propertyPath = 'missing' + $lvl
, $missingProperty = '\' + ' + $propertyPath + ' + \'';
if (it.opts._errorDataPathProperty) {
it.errorPath = it.opts.jsonPointers
? it.util.getPathExpr($currentErrorPath, $propertyPath, true)
: $currentErrorPath + ' + ' + $propertyPath;
}
}}
{{# def.error:_error }}
#}}
{{## def.allErrorsMissingProperty:_error:
{{
var $prop = it.util.getProperty($propertyKey)
, $missingProperty = it.util.escapeQuotes($propertyKey)
, $useData = $data + $prop;
if (it.opts._errorDataPathProperty) {
it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers);
}
}}
if ({{# def.noPropertyInData }}) {
{{# def.addError:_error }}
}
#}}
+20
View File
@@ -0,0 +1,20 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
var division{{=$lvl}};
if ({{?$isData}}
{{=$schemaValue}} !== undefined && (
typeof {{=$schemaValue}} != 'number' ||
{{?}}
(division{{=$lvl}} = {{=$data}} / {{=$schemaValue}},
{{? it.opts.multipleOfPrecision }}
Math.abs(Math.round(division{{=$lvl}}) - division{{=$lvl}}) > 1e-{{=it.opts.multipleOfPrecision}}
{{??}}
division{{=$lvl}} !== parseInt(division{{=$lvl}})
{{?}}
)
{{?$isData}} ) {{?}} ) {
{{# def.error:'multipleOf' }}
} {{? $breakOnError }} else { {{?}}
+43
View File
@@ -0,0 +1,43 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}
{{? {{# def.nonEmptySchema:$schema }} }}
{{
$it.schema = $schema;
$it.schemaPath = $schemaPath;
$it.errSchemaPath = $errSchemaPath;
}}
var {{=$errs}} = errors;
{{# def.setCompositeRule }}
{{
$it.createErrors = false;
var $allErrorsOption;
if ($it.opts.allErrors) {
$allErrorsOption = $it.opts.allErrors;
$it.opts.allErrors = false;
}
}}
{{= it.validate($it) }}
{{
$it.createErrors = true;
if ($allErrorsOption) $it.opts.allErrors = $allErrorsOption;
}}
{{# def.resetCompositeRule }}
if ({{=$nextValid}}) {
{{# def.error:'not' }}
} else {
{{# def.resetErrors }}
{{? it.opts.allErrors }} } {{?}}
{{??}}
{{# def.addError:'not' }}
{{? $breakOnError}}
if (false) {
{{?}}
{{?}}

Some files were not shown because too many files have changed in this diff Show More