Files
Notes/.obsidian/plugins/obsidian-csv-table/main.js
2025-11-12 12:52:06 +01:00

3456 lines
112 KiB
JavaScript

/*
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
if you want to view the source visit the plugins github repository
*/
'use strict';
var obsidian = require('obsidian');
var require$$0 = require('stream');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
class ResizeableBuffer{
constructor(size=100){
this.size = size;
this.length = 0;
this.buf = Buffer.alloc(size);
}
prepend(val){
if(Buffer.isBuffer(val)){
const length = this.length + val.length;
if(length >= this.size){
this.resize();
if(length >= this.size){
throw Error('INVALID_BUFFER_STATE')
}
}
const buf = this.buf;
this.buf = Buffer.alloc(this.size);
val.copy(this.buf, 0);
buf.copy(this.buf, val.length);
this.length += val.length;
}else {
const length = this.length++;
if(length === this.size){
this.resize();
}
const buf = this.clone();
this.buf[0] = val;
buf.copy(this.buf,1, 0, length);
}
}
append(val){
const length = this.length++;
if(length === this.size){
this.resize();
}
this.buf[length] = val;
}
clone(){
return Buffer.from(this.buf.slice(0, this.length))
}
resize(){
const length = this.length;
this.size = this.size * 2;
const buf = Buffer.alloc(this.size);
this.buf.copy(buf,0, 0, length);
this.buf = buf;
}
toString(encoding){
if(encoding){
return this.buf.slice(0, this.length).toString(encoding)
}else {
return Uint8Array.prototype.slice.call(this.buf.slice(0, this.length))
}
}
toJSON(){
return this.toString('utf8')
}
reset(){
this.length = 0;
}
}
var ResizeableBuffer_1 = ResizeableBuffer;
/*
CSV Parse
Please look at the [project documentation](https://csv.js.org/parse/) for
additional information.
*/
const { Transform } = require$$0__default["default"];
// white space characters
// https://en.wikipedia.org/wiki/Whitespace_character
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes#Types
// \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff
const tab = 9;
const nl = 10; // \n, 0x0A in hexadecimal, 10 in decimal
const np = 12;
const cr = 13; // \r, 0x0D in hexadécimal, 13 in decimal
const space = 32;
const boms = {
// Note, the following are equals:
// Buffer.from("\ufeff")
// Buffer.from([239, 187, 191])
// Buffer.from('EFBBBF', 'hex')
'utf8': Buffer.from([239, 187, 191]),
// Note, the following are equals:
// Buffer.from "\ufeff", 'utf16le
// Buffer.from([255, 254])
'utf16le': Buffer.from([255, 254])
};
class Parser extends Transform {
constructor(opts = {}){
super({...{readableObjectMode: true}, ...opts, encoding: null});
this.__originalOptions = opts;
this.__normalizeOptions(opts);
}
__normalizeOptions(opts){
const options = {};
// Merge with user options
for(let opt in opts){
options[underscore(opt)] = opts[opt];
}
// Normalize option `encoding`
// Note: defined first because other options depends on it
// to convert chars/strings into buffers.
if(options.encoding === undefined || options.encoding === true){
options.encoding = 'utf8';
}else if(options.encoding === null || options.encoding === false){
options.encoding = null;
}else if(typeof options.encoding !== 'string' && options.encoding !== null){
throw new CsvError('CSV_INVALID_OPTION_ENCODING', [
'Invalid option encoding:',
'encoding must be a string or null to return a buffer,',
`got ${JSON.stringify(options.encoding)}`
], options)
}
// Normalize option `bom`
if(options.bom === undefined || options.bom === null || options.bom === false){
options.bom = false;
}else if(options.bom !== true){
throw new CsvError('CSV_INVALID_OPTION_BOM', [
'Invalid option bom:', 'bom must be true,',
`got ${JSON.stringify(options.bom)}`
], options)
}
// Normalize option `cast`
let fnCastField = null;
if(options.cast === undefined || options.cast === null || options.cast === false || options.cast === ''){
options.cast = undefined;
}else if(typeof options.cast === 'function'){
fnCastField = options.cast;
options.cast = true;
}else if(options.cast !== true){
throw new CsvError('CSV_INVALID_OPTION_CAST', [
'Invalid option cast:', 'cast must be true or a function,',
`got ${JSON.stringify(options.cast)}`
], options)
}
// Normalize option `cast_date`
if(options.cast_date === undefined || options.cast_date === null || options.cast_date === false || options.cast_date === ''){
options.cast_date = false;
}else if(options.cast_date === true){
options.cast_date = function(value){
const date = Date.parse(value);
return !isNaN(date) ? new Date(date) : value
};
}else {
throw new CsvError('CSV_INVALID_OPTION_CAST_DATE', [
'Invalid option cast_date:', 'cast_date must be true or a function,',
`got ${JSON.stringify(options.cast_date)}`
], options)
}
// Normalize option `columns`
let fnFirstLineToHeaders = null;
if(options.columns === true){
// Fields in the first line are converted as-is to columns
fnFirstLineToHeaders = undefined;
}else if(typeof options.columns === 'function'){
fnFirstLineToHeaders = options.columns;
options.columns = true;
}else if(Array.isArray(options.columns)){
options.columns = normalizeColumnsArray(options.columns);
}else if(options.columns === undefined || options.columns === null || options.columns === false){
options.columns = false;
}else {
throw new CsvError('CSV_INVALID_OPTION_COLUMNS', [
'Invalid option columns:',
'expect an array, a function or true,',
`got ${JSON.stringify(options.columns)}`
], options)
}
// Normalize option `columns_duplicates_to_array`
if(options.columns_duplicates_to_array === undefined || options.columns_duplicates_to_array === null || options.columns_duplicates_to_array === false){
options.columns_duplicates_to_array = false;
}else if(options.columns_duplicates_to_array !== true){
throw new CsvError('CSV_INVALID_OPTION_COLUMNS_DUPLICATES_TO_ARRAY', [
'Invalid option columns_duplicates_to_array:',
'expect an boolean,',
`got ${JSON.stringify(options.columns_duplicates_to_array)}`
], options)
}else if(options.columns === false){
throw new CsvError('CSV_INVALID_OPTION_COLUMNS_DUPLICATES_TO_ARRAY', [
'Invalid option columns_duplicates_to_array:',
'the `columns` mode must be activated.'
], options)
}
// Normalize option `comment`
if(options.comment === undefined || options.comment === null || options.comment === false || options.comment === ''){
options.comment = null;
}else {
if(typeof options.comment === 'string'){
options.comment = Buffer.from(options.comment, options.encoding);
}
if(!Buffer.isBuffer(options.comment)){
throw new CsvError('CSV_INVALID_OPTION_COMMENT', [
'Invalid option comment:',
'comment must be a buffer or a string,',
`got ${JSON.stringify(options.comment)}`
], options)
}
}
// Normalize option `delimiter`
const delimiter_json = JSON.stringify(options.delimiter);
if(!Array.isArray(options.delimiter)) options.delimiter = [options.delimiter];
if(options.delimiter.length === 0){
throw new CsvError('CSV_INVALID_OPTION_DELIMITER', [
'Invalid option delimiter:',
'delimiter must be a non empty string or buffer or array of string|buffer,',
`got ${delimiter_json}`
], options)
}
options.delimiter = options.delimiter.map(function(delimiter){
if(delimiter === undefined || delimiter === null || delimiter === false){
return Buffer.from(',', options.encoding)
}
if(typeof delimiter === 'string'){
delimiter = Buffer.from(delimiter, options.encoding);
}
if( !Buffer.isBuffer(delimiter) || delimiter.length === 0){
throw new CsvError('CSV_INVALID_OPTION_DELIMITER', [
'Invalid option delimiter:',
'delimiter must be a non empty string or buffer or array of string|buffer,',
`got ${delimiter_json}`
], options)
}
return delimiter
});
// Normalize option `escape`
if(options.escape === undefined || options.escape === true){
options.escape = Buffer.from('"', options.encoding);
}else if(typeof options.escape === 'string'){
options.escape = Buffer.from(options.escape, options.encoding);
}else if (options.escape === null || options.escape === false){
options.escape = null;
}
if(options.escape !== null){
if(!Buffer.isBuffer(options.escape)){
throw new Error(`Invalid Option: escape must be a buffer, a string or a boolean, got ${JSON.stringify(options.escape)}`)
}
}
// Normalize option `from`
if(options.from === undefined || options.from === null){
options.from = 1;
}else {
if(typeof options.from === 'string' && /\d+/.test(options.from)){
options.from = parseInt(options.from);
}
if(Number.isInteger(options.from)){
if(options.from < 0){
throw new Error(`Invalid Option: from must be a positive integer, got ${JSON.stringify(opts.from)}`)
}
}else {
throw new Error(`Invalid Option: from must be an integer, got ${JSON.stringify(options.from)}`)
}
}
// Normalize option `from_line`
if(options.from_line === undefined || options.from_line === null){
options.from_line = 1;
}else {
if(typeof options.from_line === 'string' && /\d+/.test(options.from_line)){
options.from_line = parseInt(options.from_line);
}
if(Number.isInteger(options.from_line)){
if(options.from_line <= 0){
throw new Error(`Invalid Option: from_line must be a positive integer greater than 0, got ${JSON.stringify(opts.from_line)}`)
}
}else {
throw new Error(`Invalid Option: from_line must be an integer, got ${JSON.stringify(opts.from_line)}`)
}
}
// Normalize options `ignore_last_delimiters`
if(options.ignore_last_delimiters === undefined || options.ignore_last_delimiters === null){
options.ignore_last_delimiters = false;
}else if(typeof options.ignore_last_delimiters === 'number'){
options.ignore_last_delimiters = Math.floor(options.ignore_last_delimiters);
if(options.ignore_last_delimiters === 0){
options.ignore_last_delimiters = false;
}
}else if(typeof options.ignore_last_delimiters !== 'boolean'){
throw new CsvError('CSV_INVALID_OPTION_IGNORE_LAST_DELIMITERS', [
'Invalid option `ignore_last_delimiters`:',
'the value must be a boolean value or an integer,',
`got ${JSON.stringify(options.ignore_last_delimiters)}`
], options)
}
if(options.ignore_last_delimiters === true && options.columns === false){
throw new CsvError('CSV_IGNORE_LAST_DELIMITERS_REQUIRES_COLUMNS', [
'The option `ignore_last_delimiters`',
'requires the activation of the `columns` option'
], options)
}
// Normalize option `info`
if(options.info === undefined || options.info === null || options.info === false){
options.info = false;
}else if(options.info !== true){
throw new Error(`Invalid Option: info must be true, got ${JSON.stringify(options.info)}`)
}
// Normalize option `max_record_size`
if(options.max_record_size === undefined || options.max_record_size === null || options.max_record_size === false){
options.max_record_size = 0;
}else if(Number.isInteger(options.max_record_size) && options.max_record_size >= 0);else if(typeof options.max_record_size === 'string' && /\d+/.test(options.max_record_size)){
options.max_record_size = parseInt(options.max_record_size);
}else {
throw new Error(`Invalid Option: max_record_size must be a positive integer, got ${JSON.stringify(options.max_record_size)}`)
}
// Normalize option `objname`
if(options.objname === undefined || options.objname === null || options.objname === false){
options.objname = undefined;
}else if(Buffer.isBuffer(options.objname)){
if(options.objname.length === 0){
throw new Error(`Invalid Option: objname must be a non empty buffer`)
}
if(options.encoding === null);else {
options.objname = options.objname.toString(options.encoding);
}
}else if(typeof options.objname === 'string'){
if(options.objname.length === 0){
throw new Error(`Invalid Option: objname must be a non empty string`)
}
// Great, nothing to do
}else {
throw new Error(`Invalid Option: objname must be a string or a buffer, got ${options.objname}`)
}
// Normalize option `on_record`
if(options.on_record === undefined || options.on_record === null){
options.on_record = undefined;
}else if(typeof options.on_record !== 'function'){
throw new CsvError('CSV_INVALID_OPTION_ON_RECORD', [
'Invalid option `on_record`:',
'expect a function,',
`got ${JSON.stringify(options.on_record)}`
], options)
}
// Normalize option `quote`
if(options.quote === null || options.quote === false || options.quote === ''){
options.quote = null;
}else {
if(options.quote === undefined || options.quote === true){
options.quote = Buffer.from('"', options.encoding);
}else if(typeof options.quote === 'string'){
options.quote = Buffer.from(options.quote, options.encoding);
}
if(!Buffer.isBuffer(options.quote)){
throw new Error(`Invalid Option: quote must be a buffer or a string, got ${JSON.stringify(options.quote)}`)
}
}
// Normalize option `raw`
if(options.raw === undefined || options.raw === null || options.raw === false){
options.raw = false;
}else if(options.raw !== true){
throw new Error(`Invalid Option: raw must be true, got ${JSON.stringify(options.raw)}`)
}
// Normalize option `record_delimiter`
if(!options.record_delimiter){
options.record_delimiter = [];
}else if(!Array.isArray(options.record_delimiter)){
options.record_delimiter = [options.record_delimiter];
}
options.record_delimiter = options.record_delimiter.map( function(rd){
if(typeof rd === 'string'){
rd = Buffer.from(rd, options.encoding);
}
return rd
});
// Normalize option `relax`
if(typeof options.relax === 'boolean');else if(options.relax === undefined || options.relax === null){
options.relax = false;
}else {
throw new Error(`Invalid Option: relax must be a boolean, got ${JSON.stringify(options.relax)}`)
}
// Normalize option `relax_column_count`
if(typeof options.relax_column_count === 'boolean');else if(options.relax_column_count === undefined || options.relax_column_count === null){
options.relax_column_count = false;
}else {
throw new Error(`Invalid Option: relax_column_count must be a boolean, got ${JSON.stringify(options.relax_column_count)}`)
}
if(typeof options.relax_column_count_less === 'boolean');else if(options.relax_column_count_less === undefined || options.relax_column_count_less === null){
options.relax_column_count_less = false;
}else {
throw new Error(`Invalid Option: relax_column_count_less must be a boolean, got ${JSON.stringify(options.relax_column_count_less)}`)
}
if(typeof options.relax_column_count_more === 'boolean');else if(options.relax_column_count_more === undefined || options.relax_column_count_more === null){
options.relax_column_count_more = false;
}else {
throw new Error(`Invalid Option: relax_column_count_more must be a boolean, got ${JSON.stringify(options.relax_column_count_more)}`)
}
// Normalize option `skip_empty_lines`
if(typeof options.skip_empty_lines === 'boolean');else if(options.skip_empty_lines === undefined || options.skip_empty_lines === null){
options.skip_empty_lines = false;
}else {
throw new Error(`Invalid Option: skip_empty_lines must be a boolean, got ${JSON.stringify(options.skip_empty_lines)}`)
}
// Normalize option `skip_lines_with_empty_values`
if(typeof options.skip_lines_with_empty_values === 'boolean');else if(options.skip_lines_with_empty_values === undefined || options.skip_lines_with_empty_values === null){
options.skip_lines_with_empty_values = false;
}else {
throw new Error(`Invalid Option: skip_lines_with_empty_values must be a boolean, got ${JSON.stringify(options.skip_lines_with_empty_values)}`)
}
// Normalize option `skip_lines_with_error`
if(typeof options.skip_lines_with_error === 'boolean');else if(options.skip_lines_with_error === undefined || options.skip_lines_with_error === null){
options.skip_lines_with_error = false;
}else {
throw new Error(`Invalid Option: skip_lines_with_error must be a boolean, got ${JSON.stringify(options.skip_lines_with_error)}`)
}
// Normalize option `rtrim`
if(options.rtrim === undefined || options.rtrim === null || options.rtrim === false){
options.rtrim = false;
}else if(options.rtrim !== true){
throw new Error(`Invalid Option: rtrim must be a boolean, got ${JSON.stringify(options.rtrim)}`)
}
// Normalize option `ltrim`
if(options.ltrim === undefined || options.ltrim === null || options.ltrim === false){
options.ltrim = false;
}else if(options.ltrim !== true){
throw new Error(`Invalid Option: ltrim must be a boolean, got ${JSON.stringify(options.ltrim)}`)
}
// Normalize option `trim`
if(options.trim === undefined || options.trim === null || options.trim === false){
options.trim = false;
}else if(options.trim !== true){
throw new Error(`Invalid Option: trim must be a boolean, got ${JSON.stringify(options.trim)}`)
}
// Normalize options `trim`, `ltrim` and `rtrim`
if(options.trim === true && opts.ltrim !== false){
options.ltrim = true;
}else if(options.ltrim !== true){
options.ltrim = false;
}
if(options.trim === true && opts.rtrim !== false){
options.rtrim = true;
}else if(options.rtrim !== true){
options.rtrim = false;
}
// Normalize option `to`
if(options.to === undefined || options.to === null){
options.to = -1;
}else {
if(typeof options.to === 'string' && /\d+/.test(options.to)){
options.to = parseInt(options.to);
}
if(Number.isInteger(options.to)){
if(options.to <= 0){
throw new Error(`Invalid Option: to must be a positive integer greater than 0, got ${JSON.stringify(opts.to)}`)
}
}else {
throw new Error(`Invalid Option: to must be an integer, got ${JSON.stringify(opts.to)}`)
}
}
// Normalize option `to_line`
if(options.to_line === undefined || options.to_line === null){
options.to_line = -1;
}else {
if(typeof options.to_line === 'string' && /\d+/.test(options.to_line)){
options.to_line = parseInt(options.to_line);
}
if(Number.isInteger(options.to_line)){
if(options.to_line <= 0){
throw new Error(`Invalid Option: to_line must be a positive integer greater than 0, got ${JSON.stringify(opts.to_line)}`)
}
}else {
throw new Error(`Invalid Option: to_line must be an integer, got ${JSON.stringify(opts.to_line)}`)
}
}
this.info = {
bytes: 0,
comment_lines: 0,
empty_lines: 0,
invalid_field_length: 0,
lines: 1,
records: 0
};
this.options = options;
this.state = {
bomSkipped: false,
bufBytesStart: 0,
castField: fnCastField,
commenting: false,
// Current error encountered by a record
error: undefined,
enabled: options.from_line === 1,
escaping: false,
// escapeIsQuote: options.escape === options.quote,
escapeIsQuote: Buffer.isBuffer(options.escape) && Buffer.isBuffer(options.quote) && Buffer.compare(options.escape, options.quote) === 0,
// columns can be `false`, `true`, `Array`
expectedRecordLength: Array.isArray(options.columns) ? options.columns.length : undefined,
field: new ResizeableBuffer_1(20),
firstLineToHeaders: fnFirstLineToHeaders,
needMoreDataSize: Math.max(
// Skip if the remaining buffer smaller than comment
options.comment !== null ? options.comment.length : 0,
// Skip if the remaining buffer can be delimiter
...options.delimiter.map( (delimiter) => delimiter.length),
// Skip if the remaining buffer can be escape sequence
options.quote !== null ? options.quote.length : 0,
),
previousBuf: undefined,
quoting: false,
stop: false,
rawBuffer: new ResizeableBuffer_1(100),
record: [],
recordHasError: false,
record_length: 0,
recordDelimiterMaxLength: options.record_delimiter.length === 0 ? 2 : Math.max(...options.record_delimiter.map( (v) => v.length)),
trimChars: [Buffer.from(' ', options.encoding)[0], Buffer.from('\t', options.encoding)[0]],
wasQuoting: false,
wasRowDelimiter: false
};
}
// Implementation of `Transform._transform`
_transform(buf, encoding, callback){
if(this.state.stop === true){
return
}
const err = this.__parse(buf, false);
if(err !== undefined){
this.state.stop = true;
}
callback(err);
}
// Implementation of `Transform._flush`
_flush(callback){
if(this.state.stop === true){
return
}
const err = this.__parse(undefined, true);
callback(err);
}
// Central parser implementation
__parse(nextBuf, end){
const {bom, comment, escape, from_line, ltrim, max_record_size, quote, raw, relax, rtrim, skip_empty_lines, to, to_line} = this.options;
let {record_delimiter} = this.options;
const {bomSkipped, previousBuf, rawBuffer, escapeIsQuote} = this.state;
let buf;
if(previousBuf === undefined){
if(nextBuf === undefined){
// Handle empty string
this.push(null);
return
}else {
buf = nextBuf;
}
}else if(previousBuf !== undefined && nextBuf === undefined){
buf = previousBuf;
}else {
buf = Buffer.concat([previousBuf, nextBuf]);
}
// Handle UTF BOM
if(bomSkipped === false){
if(bom === false){
this.state.bomSkipped = true;
}else if(buf.length < 3){
// No enough data
if(end === false){
// Wait for more data
this.state.previousBuf = buf;
return
}
}else {
for(let encoding in boms){
if(boms[encoding].compare(buf, 0, boms[encoding].length) === 0){
// Skip BOM
let bomLength = boms[encoding].length;
this.state.bufBytesStart += bomLength;
buf = buf.slice(bomLength);
// Renormalize original options with the new encoding
this.__normalizeOptions({...this.__originalOptions, encoding: encoding});
break
}
}
this.state.bomSkipped = true;
}
}
const bufLen = buf.length;
let pos;
for(pos = 0; pos < bufLen; pos++){
// Ensure we get enough space to look ahead
// There should be a way to move this out of the loop
if(this.__needMoreData(pos, bufLen, end)){
break
}
if(this.state.wasRowDelimiter === true){
this.info.lines++;
this.state.wasRowDelimiter = false;
}
if(to_line !== -1 && this.info.lines > to_line){
this.state.stop = true;
this.push(null);
return
}
// Auto discovery of record_delimiter, unix, mac and windows supported
if(this.state.quoting === false && record_delimiter.length === 0){
const record_delimiterCount = this.__autoDiscoverRecordDelimiter(buf, pos);
if(record_delimiterCount){
record_delimiter = this.options.record_delimiter;
}
}
const chr = buf[pos];
if(raw === true){
rawBuffer.append(chr);
}
if((chr === cr || chr === nl) && this.state.wasRowDelimiter === false ){
this.state.wasRowDelimiter = true;
}
// Previous char was a valid escape char
// treat the current char as a regular char
if(this.state.escaping === true){
this.state.escaping = false;
}else {
// Escape is only active inside quoted fields
// We are quoting, the char is an escape chr and there is a chr to escape
// if(escape !== null && this.state.quoting === true && chr === escape && pos + 1 < bufLen){
if(escape !== null && this.state.quoting === true && this.__isEscape(buf, pos, chr) && pos + escape.length < bufLen){
if(escapeIsQuote){
if(this.__isQuote(buf, pos+escape.length)){
this.state.escaping = true;
pos += escape.length - 1;
continue
}
}else {
this.state.escaping = true;
pos += escape.length - 1;
continue
}
}
// Not currently escaping and chr is a quote
// TODO: need to compare bytes instead of single char
if(this.state.commenting === false && this.__isQuote(buf, pos)){
if(this.state.quoting === true){
const nextChr = buf[pos+quote.length];
const isNextChrTrimable = rtrim && this.__isCharTrimable(nextChr);
const isNextChrComment = comment !== null && this.__compareBytes(comment, buf, pos+quote.length, nextChr);
const isNextChrDelimiter = this.__isDelimiter(buf, pos+quote.length, nextChr);
const isNextChrRecordDelimiter = record_delimiter.length === 0 ? this.__autoDiscoverRecordDelimiter(buf, pos+quote.length) : this.__isRecordDelimiter(nextChr, buf, pos+quote.length);
// Escape a quote
// Treat next char as a regular character
if(escape !== null && this.__isEscape(buf, pos, chr) && this.__isQuote(buf, pos + escape.length)){
pos += escape.length - 1;
}else if(!nextChr || isNextChrDelimiter || isNextChrRecordDelimiter || isNextChrComment || isNextChrTrimable){
this.state.quoting = false;
this.state.wasQuoting = true;
pos += quote.length - 1;
continue
}else if(relax === false){
const err = this.__error(
new CsvError('CSV_INVALID_CLOSING_QUOTE', [
'Invalid Closing Quote:',
`got "${String.fromCharCode(nextChr)}"`,
`at line ${this.info.lines}`,
'instead of delimiter, record delimiter, trimable character',
'(if activated) or comment',
], this.options, this.__infoField())
);
if(err !== undefined) return err
}else {
this.state.quoting = false;
this.state.wasQuoting = true;
this.state.field.prepend(quote);
pos += quote.length - 1;
}
}else {
if(this.state.field.length !== 0){
// In relax mode, treat opening quote preceded by chrs as regular
if( relax === false ){
const err = this.__error(
new CsvError('INVALID_OPENING_QUOTE', [
'Invalid Opening Quote:',
`a quote is found inside a field at line ${this.info.lines}`,
], this.options, this.__infoField(), {
field: this.state.field,
})
);
if(err !== undefined) return err
}
}else {
this.state.quoting = true;
pos += quote.length - 1;
continue
}
}
}
if(this.state.quoting === false){
let recordDelimiterLength = this.__isRecordDelimiter(chr, buf, pos);
if(recordDelimiterLength !== 0){
// Do not emit comments which take a full line
const skipCommentLine = this.state.commenting && (this.state.wasQuoting === false && this.state.record.length === 0 && this.state.field.length === 0);
if(skipCommentLine){
this.info.comment_lines++;
// Skip full comment line
}else {
// Activate records emition if above from_line
if(this.state.enabled === false && this.info.lines + (this.state.wasRowDelimiter === true ? 1: 0) >= from_line){
this.state.enabled = true;
this.__resetField();
this.__resetRecord();
pos += recordDelimiterLength - 1;
continue
}
// Skip if line is empty and skip_empty_lines activated
if(skip_empty_lines === true && this.state.wasQuoting === false && this.state.record.length === 0 && this.state.field.length === 0){
this.info.empty_lines++;
pos += recordDelimiterLength - 1;
continue
}
this.info.bytes = this.state.bufBytesStart + pos;
const errField = this.__onField();
if(errField !== undefined) return errField
this.info.bytes = this.state.bufBytesStart + pos + recordDelimiterLength;
const errRecord = this.__onRecord();
if(errRecord !== undefined) return errRecord
if(to !== -1 && this.info.records >= to){
this.state.stop = true;
this.push(null);
return
}
}
this.state.commenting = false;
pos += recordDelimiterLength - 1;
continue
}
if(this.state.commenting){
continue
}
const commentCount = comment === null ? 0 : this.__compareBytes(comment, buf, pos, chr);
if(commentCount !== 0){
this.state.commenting = true;
continue
}
let delimiterLength = this.__isDelimiter(buf, pos, chr);
if(delimiterLength !== 0){
this.info.bytes = this.state.bufBytesStart + pos;
const errField = this.__onField();
if(errField !== undefined) return errField
pos += delimiterLength - 1;
continue
}
}
}
if(this.state.commenting === false){
if(max_record_size !== 0 && this.state.record_length + this.state.field.length > max_record_size){
const err = this.__error(
new CsvError('CSV_MAX_RECORD_SIZE', [
'Max Record Size:',
'record exceed the maximum number of tolerated bytes',
`of ${max_record_size}`,
`at line ${this.info.lines}`,
], this.options, this.__infoField())
);
if(err !== undefined) return err
}
}
const lappend = ltrim === false || this.state.quoting === true || this.state.field.length !== 0 || !this.__isCharTrimable(chr);
// rtrim in non quoting is handle in __onField
const rappend = rtrim === false || this.state.wasQuoting === false;
if( lappend === true && rappend === true ){
this.state.field.append(chr);
}else if(rtrim === true && !this.__isCharTrimable(chr)){
const err = this.__error(
new CsvError('CSV_NON_TRIMABLE_CHAR_AFTER_CLOSING_QUOTE', [
'Invalid Closing Quote:',
'found non trimable byte after quote',
`at line ${this.info.lines}`,
], this.options, this.__infoField())
);
if(err !== undefined) return err
}
}
if(end === true){
// Ensure we are not ending in a quoting state
if(this.state.quoting === true){
const err = this.__error(
new CsvError('CSV_QUOTE_NOT_CLOSED', [
'Quote Not Closed:',
`the parsing is finished with an opening quote at line ${this.info.lines}`,
], this.options, this.__infoField())
);
if(err !== undefined) return err
}else {
// Skip last line if it has no characters
if(this.state.wasQuoting === true || this.state.record.length !== 0 || this.state.field.length !== 0){
this.info.bytes = this.state.bufBytesStart + pos;
const errField = this.__onField();
if(errField !== undefined) return errField
const errRecord = this.__onRecord();
if(errRecord !== undefined) return errRecord
}else if(this.state.wasRowDelimiter === true){
this.info.empty_lines++;
}else if(this.state.commenting === true){
this.info.comment_lines++;
}
}
}else {
this.state.bufBytesStart += pos;
this.state.previousBuf = buf.slice(pos);
}
if(this.state.wasRowDelimiter === true){
this.info.lines++;
this.state.wasRowDelimiter = false;
}
}
__onRecord(){
const {columns, columns_duplicates_to_array, encoding, info, from, relax_column_count, relax_column_count_less, relax_column_count_more, raw, skip_lines_with_empty_values} = this.options;
const {enabled, record} = this.state;
if(enabled === false){
return this.__resetRecord()
}
// Convert the first line into column names
const recordLength = record.length;
if(columns === true){
if(skip_lines_with_empty_values === true && isRecordEmpty(record)){
this.__resetRecord();
return
}
return this.__firstLineToColumns(record)
}
if(columns === false && this.info.records === 0){
this.state.expectedRecordLength = recordLength;
}
if(recordLength !== this.state.expectedRecordLength){
const err = columns === false ?
// Todo: rename CSV_INCONSISTENT_RECORD_LENGTH to
// CSV_RECORD_INCONSISTENT_FIELDS_LENGTH
new CsvError('CSV_INCONSISTENT_RECORD_LENGTH', [
'Invalid Record Length:',
`expect ${this.state.expectedRecordLength},`,
`got ${recordLength} on line ${this.info.lines}`,
], this.options, this.__infoField(), {
record: record,
})
:
// Todo: rename CSV_RECORD_DONT_MATCH_COLUMNS_LENGTH to
// CSV_RECORD_INCONSISTENT_COLUMNS
new CsvError('CSV_RECORD_DONT_MATCH_COLUMNS_LENGTH', [
'Invalid Record Length:',
`columns length is ${columns.length},`, // rename columns
`got ${recordLength} on line ${this.info.lines}`,
], this.options, this.__infoField(), {
record: record,
});
if(relax_column_count === true ||
(relax_column_count_less === true && recordLength < this.state.expectedRecordLength) ||
(relax_column_count_more === true && recordLength > this.state.expectedRecordLength) ){
this.info.invalid_field_length++;
this.state.error = err;
// Error is undefined with skip_lines_with_error
}else {
const finalErr = this.__error(err);
if(finalErr) return finalErr
}
}
if(skip_lines_with_empty_values === true && isRecordEmpty(record)){
this.__resetRecord();
return
}
if(this.state.recordHasError === true){
this.__resetRecord();
this.state.recordHasError = false;
return
}
this.info.records++;
if(from === 1 || this.info.records >= from){
// With columns, records are object
if(columns !== false){
const obj = {};
// Transform record array to an object
for(let i = 0, l = record.length; i < l; i++){
if(columns[i] === undefined || columns[i].disabled) continue
// Turn duplicate columns into an array
if (columns_duplicates_to_array === true && obj[columns[i].name] !== undefined) {
if (Array.isArray(obj[columns[i].name])) {
obj[columns[i].name] = obj[columns[i].name].concat(record[i]);
} else {
obj[columns[i].name] = [obj[columns[i].name], record[i]];
}
} else {
obj[columns[i].name] = record[i];
}
}
const {objname} = this.options;
// Without objname (default)
if(objname === undefined){
if(raw === true || info === true){
const err = this.__push(Object.assign(
{record: obj},
(raw === true ? {raw: this.state.rawBuffer.toString(encoding)}: {}),
(info === true ? {info: this.__infoRecord()}: {})
));
if(err){
return err
}
}else {
const err = this.__push(obj);
if(err){
return err
}
}
// With objname (default)
}else {
if(raw === true || info === true){
const err = this.__push(Object.assign(
{record: [obj[objname], obj]},
raw === true ? {raw: this.state.rawBuffer.toString(encoding)}: {},
info === true ? {info: this.__infoRecord()}: {}
));
if(err){
return err
}
}else {
const err = this.__push([obj[objname], obj]);
if(err){
return err
}
}
}
// Without columns, records are array
}else {
if(raw === true || info === true){
const err = this.__push(Object.assign(
{record: record},
raw === true ? {raw: this.state.rawBuffer.toString(encoding)}: {},
info === true ? {info: this.__infoRecord()}: {}
));
if(err){
return err
}
}else {
const err = this.__push(record);
if(err){
return err
}
}
}
}
this.__resetRecord();
}
__firstLineToColumns(record){
const {firstLineToHeaders} = this.state;
try{
const headers = firstLineToHeaders === undefined ? record : firstLineToHeaders.call(null, record);
if(!Array.isArray(headers)){
return this.__error(
new CsvError('CSV_INVALID_COLUMN_MAPPING', [
'Invalid Column Mapping:',
'expect an array from column function,',
`got ${JSON.stringify(headers)}`
], this.options, this.__infoField(), {
headers: headers,
})
)
}
const normalizedHeaders = normalizeColumnsArray(headers);
this.state.expectedRecordLength = normalizedHeaders.length;
this.options.columns = normalizedHeaders;
this.__resetRecord();
return
}catch(err){
return err
}
}
__resetRecord(){
if(this.options.raw === true){
this.state.rawBuffer.reset();
}
this.state.error = undefined;
this.state.record = [];
this.state.record_length = 0;
}
__onField(){
const {cast, encoding, rtrim, max_record_size} = this.options;
const {enabled, wasQuoting} = this.state;
// Short circuit for the from_line options
if(enabled === false){
return this.__resetField()
}
let field = this.state.field.toString(encoding);
if(rtrim === true && wasQuoting === false){
field = field.trimRight();
}
if(cast === true){
const [err, f] = this.__cast(field);
if(err !== undefined) return err
field = f;
}
this.state.record.push(field);
// Increment record length if record size must not exceed a limit
if(max_record_size !== 0 && typeof field === 'string'){
this.state.record_length += field.length;
}
this.__resetField();
}
__resetField(){
this.state.field.reset();
this.state.wasQuoting = false;
}
__push(record){
const {on_record} = this.options;
if(on_record !== undefined){
const info = this.__infoRecord();
try{
record = on_record.call(null, record, info);
}catch(err){
return err
}
if(record === undefined || record === null){ return }
}
this.push(record);
}
// Return a tuple with the error and the casted value
__cast(field){
const {columns, relax_column_count} = this.options;
const isColumns = Array.isArray(columns);
// Dont loose time calling cast
// because the final record is an object
// and this field can't be associated to a key present in columns
if( isColumns === true && relax_column_count && this.options.columns.length <= this.state.record.length ){
return [undefined, undefined]
}
if(this.state.castField !== null){
try{
const info = this.__infoField();
return [undefined, this.state.castField.call(null, field, info)]
}catch(err){
return [err]
}
}
if(this.__isFloat(field)){
return [undefined, parseFloat(field)]
}else if(this.options.cast_date !== false){
const info = this.__infoField();
return [undefined, this.options.cast_date.call(null, field, info)]
}
return [undefined, field]
}
// Helper to test if a character is a space or a line delimiter
__isCharTrimable(chr){
return chr === space || chr === tab || chr === cr || chr === nl || chr === np
}
// Keep it in case we implement the `cast_int` option
// __isInt(value){
// // return Number.isInteger(parseInt(value))
// // return !isNaN( parseInt( obj ) );
// return /^(\-|\+)?[1-9][0-9]*$/.test(value)
// }
__isFloat(value){
return (value - parseFloat( value ) + 1) >= 0 // Borrowed from jquery
}
__compareBytes(sourceBuf, targetBuf, targetPos, firstByte){
if(sourceBuf[0] !== firstByte) return 0
const sourceLength = sourceBuf.length;
for(let i = 1; i < sourceLength; i++){
if(sourceBuf[i] !== targetBuf[targetPos+i]) return 0
}
return sourceLength
}
__needMoreData(i, bufLen, end){
if(end) return false
const {quote} = this.options;
const {quoting, needMoreDataSize, recordDelimiterMaxLength} = this.state;
const numOfCharLeft = bufLen - i - 1;
const requiredLength = Math.max(
needMoreDataSize,
// Skip if the remaining buffer smaller than record delimiter
recordDelimiterMaxLength,
// Skip if the remaining buffer can be record delimiter following the closing quote
// 1 is for quote.length
quoting ? (quote.length + recordDelimiterMaxLength) : 0,
);
return numOfCharLeft < requiredLength
}
__isDelimiter(buf, pos, chr){
const {delimiter, ignore_last_delimiters} = this.options;
if(ignore_last_delimiters === true && this.state.record.length === this.options.columns.length - 1){
return 0
}else if(ignore_last_delimiters !== false && typeof ignore_last_delimiters === 'number' && this.state.record.length === ignore_last_delimiters - 1){
return 0
}
loop1: for(let i = 0; i < delimiter.length; i++){
const del = delimiter[i];
if(del[0] === chr){
for(let j = 1; j < del.length; j++){
if(del[j] !== buf[pos+j]) continue loop1
}
return del.length
}
}
return 0
}
__isRecordDelimiter(chr, buf, pos){
const {record_delimiter} = this.options;
const recordDelimiterLength = record_delimiter.length;
loop1: for(let i = 0; i < recordDelimiterLength; i++){
const rd = record_delimiter[i];
const rdLength = rd.length;
if(rd[0] !== chr){
continue
}
for(let j = 1; j < rdLength; j++){
if(rd[j] !== buf[pos+j]){
continue loop1
}
}
return rd.length
}
return 0
}
__isEscape(buf, pos, chr){
const {escape} = this.options;
if(escape === null) return false
const l = escape.length;
if(escape[0] === chr){
for(let i = 0; i < l; i++){
if(escape[i] !== buf[pos+i]){
return false
}
}
return true
}
return false
}
__isQuote(buf, pos){
const {quote} = this.options;
if(quote === null) return false
const l = quote.length;
for(let i = 0; i < l; i++){
if(quote[i] !== buf[pos+i]){
return false
}
}
return true
}
__autoDiscoverRecordDelimiter(buf, pos){
const {encoding} = this.options;
const chr = buf[pos];
if(chr === cr){
if(buf[pos+1] === nl){
this.options.record_delimiter.push(Buffer.from('\r\n', encoding));
this.state.recordDelimiterMaxLength = 2;
return 2
}else {
this.options.record_delimiter.push(Buffer.from('\r', encoding));
this.state.recordDelimiterMaxLength = 1;
return 1
}
}else if(chr === nl){
this.options.record_delimiter.push(Buffer.from('\n', encoding));
this.state.recordDelimiterMaxLength = 1;
return 1
}
return 0
}
__error(msg){
const {skip_lines_with_error} = this.options;
const err = typeof msg === 'string' ? new Error(msg) : msg;
if(skip_lines_with_error){
this.state.recordHasError = true;
this.emit('skip', err);
return undefined
}else {
return err
}
}
__infoDataSet(){
return {
...this.info,
columns: this.options.columns
}
}
__infoRecord(){
const {columns} = this.options;
return {
...this.__infoDataSet(),
error: this.state.error,
header: columns === true,
index: this.state.record.length,
}
}
__infoField(){
const {columns} = this.options;
const isColumns = Array.isArray(columns);
return {
...this.__infoRecord(),
column: isColumns === true ?
( columns.length > this.state.record.length ?
columns[this.state.record.length].name :
null
) :
this.state.record.length,
quoting: this.state.wasQuoting,
}
}
}
const parse = function(){
let data, options, callback;
for(let i in arguments){
const argument = arguments[i];
const type = typeof argument;
if(data === undefined && (typeof argument === 'string' || Buffer.isBuffer(argument))){
data = argument;
}else if(options === undefined && isObject(argument)){
options = argument;
}else if(callback === undefined && type === 'function'){
callback = argument;
}else {
throw new CsvError('CSV_INVALID_ARGUMENT', [
'Invalid argument:',
`got ${JSON.stringify(argument)} at index ${i}`
], options || {})
}
}
const parser = new Parser(options);
if(callback){
const records = options === undefined || options.objname === undefined ? [] : {};
parser.on('readable', function(){
let record;
while((record = this.read()) !== null){
if(options === undefined || options.objname === undefined){
records.push(record);
}else {
records[record[0]] = record[1];
}
}
});
parser.on('error', function(err){
callback(err, undefined, parser.__infoDataSet());
});
parser.on('end', function(){
callback(undefined, records, parser.__infoDataSet());
});
}
if(data !== undefined){
// Give a chance for events to be registered later
if(typeof setImmediate === 'function'){
setImmediate(function(){
parser.write(data);
parser.end();
});
}else {
parser.write(data);
parser.end();
}
}
return parser
};
class CsvError extends Error {
constructor(code, message, options, ...contexts) {
if(Array.isArray(message)) message = message.join(' ');
super(message);
if(Error.captureStackTrace !== undefined){
Error.captureStackTrace(this, CsvError);
}
this.code = code;
for(const context of contexts){
for(const key in context){
const value = context[key];
this[key] = Buffer.isBuffer(value) ? value.toString(options.encoding) : value == null ? value : JSON.parse(JSON.stringify(value));
}
}
}
}
parse.Parser = Parser;
parse.CsvError = CsvError;
var lib = parse;
const underscore = function(str){
return str.replace(/([A-Z])/g, function(_, match){
return '_' + match.toLowerCase()
})
};
const isObject = function(obj){
return (typeof obj === 'object' && obj !== null && !Array.isArray(obj))
};
const isRecordEmpty = function(record){
return record.every( (field) => field == null || field.toString && field.toString().trim() === '' )
};
const normalizeColumnsArray = function(columns){
const normalizedColumns = [];
for(let i = 0, l = columns.length; i < l; i++){
const column = columns[i];
if(column === undefined || column === null || column === false){
normalizedColumns[i] = { disabled: true };
}else if(typeof column === 'string'){
normalizedColumns[i] = { name: column };
}else if(isObject(column)){
if(typeof column.name !== 'string'){
throw new CsvError('CSV_OPTION_COLUMNS_MISSING_NAME', [
'Option columns missing name:',
`property "name" is required at position ${i}`,
'when column is an object literal'
])
}
normalizedColumns[i] = column;
}else {
throw new CsvError('CSV_INVALID_COLUMN_DEFINITION', [
'Invalid column definition:',
'expect a string or a literal object,',
`got ${JSON.stringify(column)} at position ${i}`
])
}
}
return normalizedColumns;
};
var sync = function(data, options={}){
if(typeof data === 'string'){
data = Buffer.from(data);
}
const records = options && options.objname ? {} : [];
const parser = new lib.Parser(options);
parser.push = function(record){
if(record === null){
return
}
if(options.objname === undefined)
records.push(record);
else {
records[record[0]] = record[1];
}
};
const err1 = parser.__parse(data, false);
if(err1 !== undefined) throw err1
const err2 = parser.__parse(undefined, true);
if(err2 !== undefined) throw err2
return records
};
/* Jison generated parser */
var _parser = (function() {
var parser = {
trace: function trace() {},
yy: {},
symbols_: {
"error": 2,
"expressions": 3,
"e": 4,
"EOF": 5,
"+": 6,
"-": 7,
"*": 8,
"/": 9,
"%": 10,
"^": 11,
"and": 12,
"or": 13,
"not": 14,
"==": 15,
"!=": 16,
"~=": 17,
"<": 18,
"<=": 19,
">": 20,
">=": 21,
"?": 22,
":": 23,
"(": 24,
")": 25,
"array": 26,
",": 27,
"NUMBER": 28,
"STRING": 29,
"SYMBOL": 30,
"of": 31,
"argsList": 32,
"in": 33,
"inSet": 34,
"$accept": 0,
"$end": 1
},
terminals_: {
2: "error",
5: "EOF",
6: "+",
7: "-",
8: "*",
9: "/",
10: "%",
11: "^",
12: "and",
13: "or",
14: "not",
15: "==",
16: "!=",
17: "~=",
18: "<",
19: "<=",
20: ">",
21: ">=",
22: "?",
23: ":",
24: "(",
25: ")",
27: ",",
28: "NUMBER",
29: "STRING",
30: "SYMBOL",
31: "of",
33: "in"
},
productions_: [0, [3, 2],
[4, 3],
[4, 3],
[4, 3],
[4, 3],
[4, 3],
[4, 3],
[4, 2],
[4, 3],
[4, 3],
[4, 2],
[4, 3],
[4, 3],
[4, 3],
[4, 3],
[4, 3],
[4, 3],
[4, 3],
[4, 5],
[4, 3],
[4, 5],
[4, 1],
[4, 1],
[4, 1],
[4, 3],
[4, 3],
[4, 4],
[4, 3],
[4, 4],
[32, 1],
[32, 3],
[34, 1],
[34, 3],
[26, 1],
[26, 3]
],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
var $0 = $$.length - 1;
switch (yystate) {
case 1:
return $$[$0 - 1];
case 2:
this.$ = ["(", $$[$0 - 2], "+", $$[$0], ")"];
break;
case 3:
this.$ = ["(", $$[$0 - 2], "-", $$[$0], ")"];
break;
case 4:
this.$ = ["(", $$[$0 - 2], "*", $$[$0], ")"];
break;
case 5:
this.$ = ["(", $$[$0 - 2], "/", $$[$0], ")"];
break;
case 6:
this.$ = ["(", $$[$0 - 2], "%", $$[$0], ")"];
break;
case 7:
this.$ = ["(", "Math.pow(", $$[$0 - 2], ",", $$[$0], ")", ")"];
break;
case 8:
this.$ = ["(", "-", $$[$0], ")"];
break;
case 9:
this.$ = ["(", "Number(", $$[$0 - 2], "&&", $$[$0], ")", ")"];
break;
case 10:
this.$ = ["(", "Number(", $$[$0 - 2], "||", $$[$0], ")", ")"];
break;
case 11:
this.$ = ["(", "Number(!", $$[$0], ")", ")"];
break;
case 12:
this.$ = ["(", "Number(", $$[$0 - 2], "==", $$[$0], ")", ")"];
break;
case 13:
this.$ = ["(", "Number(", $$[$0 - 2], "!=", $$[$0], ")", ")"];
break;
case 14:
this.$ = ["(", "Number(RegExp(", $$[$0], ").test(", $$[$0 - 2], "))", ")"];
break;
case 15:
this.$ = ["(", "Number(", $$[$0 - 2], "<", $$[$0], ")", ")"];
break;
case 16:
this.$ = ["(", "Number(", $$[$0 - 2], "<=", $$[$0], ")", ")"];
break;
case 17:
this.$ = ["(", "Number(", $$[$0 - 2], "> ", $$[$0], ")", ")"];
break;
case 18:
this.$ = ["(", "Number(", $$[$0 - 2], ">=", $$[$0], ")", ")"];
break;
case 19:
this.$ = ["(", $$[$0 - 4], "?", $$[$0 - 2], ":", $$[$0], ")"];
break;
case 20:
this.$ = ["(", $$[$0 - 1], ")"];
break;
case 21:
this.$ = ["(", "[", $$[$0 - 3], ",", $$[$0 - 1], "]", ")"];
break;
case 22:
this.$ = ["(", $$[$0], ")"];
break;
case 23:
this.$ = ["(", $$[$0], ")"];
break;
case 24:
this.$ = ["(", "prop(", $$[$0], ", data)", ")"];
break;
case 25:
this.$ = ["(", "prop(", $$[$0 - 2], ",", $$[$0], ")", ")"];
break;
case 26:
this.$ = ["(", "(std.isfn(fns, ", $$[$0 - 2], ") ? fns[", $$[$0 - 2], "]() : std.unknown(", $$[$0 - 2], "))", ")"];
break;
case 27:
this.$ = ["(", "(std.isfn(fns, ", $$[$0 - 3], ") ? fns[", $$[$0 - 3], "](", $$[$0 - 1], ") : std.unknown(", $$[$0 - 3], "))", ")"];
break;
case 28:
this.$ = ["(", "std.isSubset(", $$[$0 - 2], ", ", $$[$0], ")", ")"];
break;
case 29:
this.$ = ["(", "+!std.isSubset(", $$[$0 - 3], ", ", $$[$0], ")", ")"];
break;
case 30:
this.$ = [$$[$0]];
break;
case 31:
this.$ = [$$[$0 - 2], ",", $$[$0]];
break;
case 32:
this.$ = ["o ==", $$[$0]];
break;
case 33:
this.$ = [$$[$0 - 2], "|| o ==", $$[$0]];
break;
case 34:
this.$ = ["(", $$[$0], ")"];
break;
case 35:
this.$ = [$$[$0 - 2], ",", $$[$0]];
break;
}
},
table: [{
3: 1,
4: 2,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
1: [3]
}, {
5: [1, 9],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [1, 16],
13: [1, 17],
14: [1, 27],
15: [1, 18],
16: [1, 19],
17: [1, 20],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [1, 25],
33: [1, 26]
}, {
4: 28,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 29,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 30,
7: [1, 3],
14: [1, 4],
24: [1, 5],
26: 31,
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
5: [2, 22],
6: [2, 22],
7: [2, 22],
8: [2, 22],
9: [2, 22],
10: [2, 22],
11: [2, 22],
12: [2, 22],
13: [2, 22],
14: [2, 22],
15: [2, 22],
16: [2, 22],
17: [2, 22],
18: [2, 22],
19: [2, 22],
20: [2, 22],
21: [2, 22],
22: [2, 22],
23: [2, 22],
25: [2, 22],
27: [2, 22],
33: [2, 22]
}, {
5: [2, 23],
6: [2, 23],
7: [2, 23],
8: [2, 23],
9: [2, 23],
10: [2, 23],
11: [2, 23],
12: [2, 23],
13: [2, 23],
14: [2, 23],
15: [2, 23],
16: [2, 23],
17: [2, 23],
18: [2, 23],
19: [2, 23],
20: [2, 23],
21: [2, 23],
22: [2, 23],
23: [2, 23],
25: [2, 23],
27: [2, 23],
33: [2, 23]
}, {
5: [2, 24],
6: [2, 24],
7: [2, 24],
8: [2, 24],
9: [2, 24],
10: [2, 24],
11: [2, 24],
12: [2, 24],
13: [2, 24],
14: [2, 24],
15: [2, 24],
16: [2, 24],
17: [2, 24],
18: [2, 24],
19: [2, 24],
20: [2, 24],
21: [2, 24],
22: [2, 24],
23: [2, 24],
24: [1, 33],
25: [2, 24],
27: [2, 24],
31: [1, 32],
33: [2, 24]
}, {
1: [2, 1]
}, {
4: 34,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 35,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 36,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 37,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 38,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 39,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 40,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 41,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 42,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 43,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 44,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 45,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 46,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 47,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 48,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 49,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 50,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
33: [1, 51]
}, {
5: [2, 8],
6: [2, 8],
7: [2, 8],
8: [2, 8],
9: [2, 8],
10: [2, 8],
11: [2, 8],
12: [2, 8],
13: [2, 8],
14: [2, 8],
15: [2, 8],
16: [2, 8],
17: [2, 8],
18: [2, 8],
19: [2, 8],
20: [2, 8],
21: [2, 8],
22: [2, 8],
23: [2, 8],
25: [2, 8],
27: [2, 8],
33: [2, 8]
}, {
5: [2, 11],
6: [2, 11],
7: [2, 11],
8: [2, 11],
9: [2, 11],
10: [2, 11],
11: [2, 11],
12: [2, 11],
13: [2, 11],
14: [2, 11],
15: [2, 11],
16: [2, 11],
17: [2, 11],
18: [2, 11],
19: [2, 11],
20: [2, 11],
21: [2, 11],
22: [2, 11],
23: [2, 11],
25: [2, 11],
27: [2, 11],
33: [2, 11]
}, {
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [1, 16],
13: [1, 17],
14: [1, 27],
15: [1, 18],
16: [1, 19],
17: [1, 20],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [1, 25],
25: [1, 52],
27: [2, 34],
33: [1, 26]
}, {
27: [1, 53]
}, {
4: 54,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
4: 57,
7: [1, 3],
14: [1, 4],
24: [1, 5],
25: [1, 55],
28: [1, 6],
29: [1, 7],
30: [1, 8],
32: 56
}, {
5: [2, 2],
6: [2, 2],
7: [2, 2],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 2],
13: [2, 2],
14: [1, 27],
15: [2, 2],
16: [2, 2],
17: [2, 2],
18: [2, 2],
19: [2, 2],
20: [2, 2],
21: [2, 2],
22: [2, 2],
23: [2, 2],
25: [2, 2],
27: [2, 2],
33: [2, 2]
}, {
5: [2, 3],
6: [2, 3],
7: [2, 3],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 3],
13: [2, 3],
14: [1, 27],
15: [2, 3],
16: [2, 3],
17: [2, 3],
18: [2, 3],
19: [2, 3],
20: [2, 3],
21: [2, 3],
22: [2, 3],
23: [2, 3],
25: [2, 3],
27: [2, 3],
33: [2, 3]
}, {
5: [2, 4],
6: [2, 4],
7: [2, 4],
8: [2, 4],
9: [2, 4],
10: [2, 4],
11: [1, 15],
12: [2, 4],
13: [2, 4],
14: [1, 27],
15: [2, 4],
16: [2, 4],
17: [2, 4],
18: [2, 4],
19: [2, 4],
20: [2, 4],
21: [2, 4],
22: [2, 4],
23: [2, 4],
25: [2, 4],
27: [2, 4],
33: [2, 4]
}, {
5: [2, 5],
6: [2, 5],
7: [2, 5],
8: [2, 5],
9: [2, 5],
10: [2, 5],
11: [1, 15],
12: [2, 5],
13: [2, 5],
14: [1, 27],
15: [2, 5],
16: [2, 5],
17: [2, 5],
18: [2, 5],
19: [2, 5],
20: [2, 5],
21: [2, 5],
22: [2, 5],
23: [2, 5],
25: [2, 5],
27: [2, 5],
33: [2, 5]
}, {
5: [2, 6],
6: [2, 6],
7: [2, 6],
8: [2, 6],
9: [2, 6],
10: [2, 6],
11: [1, 15],
12: [2, 6],
13: [2, 6],
14: [1, 27],
15: [2, 6],
16: [2, 6],
17: [2, 6],
18: [2, 6],
19: [2, 6],
20: [2, 6],
21: [2, 6],
22: [2, 6],
23: [2, 6],
25: [2, 6],
27: [2, 6],
33: [2, 6]
}, {
5: [2, 7],
6: [2, 7],
7: [2, 7],
8: [2, 7],
9: [2, 7],
10: [2, 7],
11: [2, 7],
12: [2, 7],
13: [2, 7],
14: [1, 27],
15: [2, 7],
16: [2, 7],
17: [2, 7],
18: [2, 7],
19: [2, 7],
20: [2, 7],
21: [2, 7],
22: [2, 7],
23: [2, 7],
25: [2, 7],
27: [2, 7],
33: [2, 7]
}, {
5: [2, 9],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 9],
13: [2, 9],
14: [1, 27],
15: [1, 18],
16: [1, 19],
17: [1, 20],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [2, 9],
23: [2, 9],
25: [2, 9],
27: [2, 9],
33: [1, 26]
}, {
5: [2, 10],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [1, 16],
13: [2, 10],
14: [1, 27],
15: [1, 18],
16: [1, 19],
17: [1, 20],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [2, 10],
23: [2, 10],
25: [2, 10],
27: [2, 10],
33: [1, 26]
}, {
5: [2, 12],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 12],
13: [2, 12],
14: [1, 27],
15: [2, 12],
16: [2, 12],
17: [2, 12],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [2, 12],
23: [2, 12],
25: [2, 12],
27: [2, 12],
33: [2, 12]
}, {
5: [2, 13],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 13],
13: [2, 13],
14: [1, 27],
15: [2, 13],
16: [2, 13],
17: [2, 13],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [2, 13],
23: [2, 13],
25: [2, 13],
27: [2, 13],
33: [2, 13]
}, {
5: [2, 14],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 14],
13: [2, 14],
14: [1, 27],
15: [2, 14],
16: [2, 14],
17: [2, 14],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [2, 14],
23: [2, 14],
25: [2, 14],
27: [2, 14],
33: [2, 14]
}, {
5: [2, 15],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 15],
13: [2, 15],
14: [1, 27],
15: [2, 15],
16: [2, 15],
17: [2, 15],
18: [2, 15],
19: [2, 15],
20: [2, 15],
21: [2, 15],
22: [2, 15],
23: [2, 15],
25: [2, 15],
27: [2, 15],
33: [2, 15]
}, {
5: [2, 16],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 16],
13: [2, 16],
14: [1, 27],
15: [2, 16],
16: [2, 16],
17: [2, 16],
18: [2, 16],
19: [2, 16],
20: [2, 16],
21: [2, 16],
22: [2, 16],
23: [2, 16],
25: [2, 16],
27: [2, 16],
33: [2, 16]
}, {
5: [2, 17],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 17],
13: [2, 17],
14: [1, 27],
15: [2, 17],
16: [2, 17],
17: [2, 17],
18: [2, 17],
19: [2, 17],
20: [2, 17],
21: [2, 17],
22: [2, 17],
23: [2, 17],
25: [2, 17],
27: [2, 17],
33: [2, 17]
}, {
5: [2, 18],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 18],
13: [2, 18],
14: [1, 27],
15: [2, 18],
16: [2, 18],
17: [2, 18],
18: [2, 18],
19: [2, 18],
20: [2, 18],
21: [2, 18],
22: [2, 18],
23: [2, 18],
25: [2, 18],
27: [2, 18],
33: [2, 18]
}, {
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [1, 16],
13: [1, 17],
14: [1, 27],
15: [1, 18],
16: [1, 19],
17: [1, 20],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [1, 25],
23: [1, 58],
33: [1, 26]
}, {
5: [2, 28],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [2, 28],
13: [2, 28],
14: [1, 27],
15: [1, 18],
16: [1, 19],
17: [1, 20],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [2, 28],
23: [2, 28],
25: [2, 28],
27: [2, 28],
33: [2, 28]
}, {
4: 59,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
5: [2, 20],
6: [2, 20],
7: [2, 20],
8: [2, 20],
9: [2, 20],
10: [2, 20],
11: [2, 20],
12: [2, 20],
13: [2, 20],
14: [2, 20],
15: [2, 20],
16: [2, 20],
17: [2, 20],
18: [2, 20],
19: [2, 20],
20: [2, 20],
21: [2, 20],
22: [2, 20],
23: [2, 20],
25: [2, 20],
27: [2, 20],
33: [2, 20]
}, {
4: 60,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
5: [2, 25],
6: [2, 25],
7: [2, 25],
8: [2, 25],
9: [2, 25],
10: [2, 25],
11: [2, 25],
12: [2, 25],
13: [2, 25],
14: [2, 25],
15: [2, 25],
16: [2, 25],
17: [2, 25],
18: [2, 25],
19: [2, 25],
20: [2, 25],
21: [2, 25],
22: [2, 25],
23: [2, 25],
25: [2, 25],
27: [2, 25],
33: [2, 25]
}, {
5: [2, 26],
6: [2, 26],
7: [2, 26],
8: [2, 26],
9: [2, 26],
10: [2, 26],
11: [2, 26],
12: [2, 26],
13: [2, 26],
14: [2, 26],
15: [2, 26],
16: [2, 26],
17: [2, 26],
18: [2, 26],
19: [2, 26],
20: [2, 26],
21: [2, 26],
22: [2, 26],
23: [2, 26],
25: [2, 26],
27: [2, 26],
33: [2, 26]
}, {
25: [1, 61],
27: [1, 62]
}, {
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [1, 16],
13: [1, 17],
14: [1, 27],
15: [1, 18],
16: [1, 19],
17: [1, 20],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [1, 25],
25: [2, 30],
27: [2, 30],
33: [1, 26]
}, {
4: 63,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
5: [2, 29],
6: [2, 29],
7: [2, 29],
8: [2, 29],
9: [2, 29],
10: [2, 29],
11: [2, 29],
12: [2, 29],
13: [2, 29],
14: [2, 29],
15: [2, 29],
16: [2, 29],
17: [2, 29],
18: [2, 29],
19: [2, 29],
20: [2, 29],
21: [2, 29],
22: [2, 29],
23: [2, 29],
25: [2, 29],
27: [2, 29],
33: [2, 29]
}, {
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [1, 16],
13: [1, 17],
14: [1, 27],
15: [1, 18],
16: [1, 19],
17: [1, 20],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [1, 25],
25: [1, 64],
27: [2, 35],
33: [1, 26]
}, {
5: [2, 27],
6: [2, 27],
7: [2, 27],
8: [2, 27],
9: [2, 27],
10: [2, 27],
11: [2, 27],
12: [2, 27],
13: [2, 27],
14: [2, 27],
15: [2, 27],
16: [2, 27],
17: [2, 27],
18: [2, 27],
19: [2, 27],
20: [2, 27],
21: [2, 27],
22: [2, 27],
23: [2, 27],
25: [2, 27],
27: [2, 27],
33: [2, 27]
}, {
4: 65,
7: [1, 3],
14: [1, 4],
24: [1, 5],
28: [1, 6],
29: [1, 7],
30: [1, 8]
}, {
5: [2, 19],
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [1, 16],
13: [1, 17],
14: [1, 27],
15: [1, 18],
16: [1, 19],
17: [1, 20],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [2, 19],
23: [2, 19],
25: [2, 19],
27: [2, 19],
33: [1, 26]
}, {
5: [2, 21],
6: [2, 21],
7: [2, 21],
8: [2, 21],
9: [2, 21],
10: [2, 21],
11: [2, 21],
12: [2, 21],
13: [2, 21],
14: [2, 21],
15: [2, 21],
16: [2, 21],
17: [2, 21],
18: [2, 21],
19: [2, 21],
20: [2, 21],
21: [2, 21],
22: [2, 21],
23: [2, 21],
25: [2, 21],
27: [2, 21],
33: [2, 21]
}, {
6: [1, 10],
7: [1, 11],
8: [1, 12],
9: [1, 13],
10: [1, 14],
11: [1, 15],
12: [1, 16],
13: [1, 17],
14: [1, 27],
15: [1, 18],
16: [1, 19],
17: [1, 20],
18: [1, 21],
19: [1, 22],
20: [1, 23],
21: [1, 24],
22: [1, 25],
25: [2, 31],
27: [2, 31],
33: [1, 26]
}],
defaultActions: {
9: [2, 1]
},
parseError: function parseError(str, hash) {
throw new Error(str);
},
parse: function parse(input) {
var self = this,
stack = [0],
vstack = [null], // semantic value stack
lstack = [], // location stack
table = this.table,
yytext = '',
yylineno = 0,
yyleng = 0,
recovering = 0,
TERROR = 2,
EOF = 1;
//this.reductionCount = this.shiftCount = 0;
this.lexer.setInput(input);
this.lexer.yy = this.yy;
this.yy.lexer = this.lexer;
this.yy.parser = this;
if (typeof this.lexer.yylloc == 'undefined')
this.lexer.yylloc = {};
var yyloc = this.lexer.yylloc;
lstack.push(yyloc);
var ranges = this.lexer.options && this.lexer.options.ranges;
if (typeof this.yy.parseError === 'function')
this.parseError = this.yy.parseError;
function popStack(n) {
stack.length = stack.length - 2 * n;
vstack.length = vstack.length - n;
lstack.length = lstack.length - n;
}
function lex() {
var token;
token = self.lexer.lex() || 1; // $end = 1
// if token isn't its numeric value, convert
if (typeof token !== 'number') {
token = self.symbols_[token] || token;
}
return token;
}
var symbol, preErrorSymbol, state, action, r, yyval = {},
p, len, newState, expected;
while (true) {
// retreive state number from top of stack
state = stack[stack.length - 1];
// use default actions if available
if (this.defaultActions[state]) {
action = this.defaultActions[state];
} else {
if (symbol === null || typeof symbol == 'undefined') {
symbol = lex();
}
// read action for current state and first input
action = table[state] && table[state][symbol];
}
// handle parse error
if (typeof action === 'undefined' || !action.length || !action[0]) {
var errStr = '';
if (!recovering) {
// Report error
expected = [];
for (p in table[state])
if (this.terminals_[p] && p > 2) {
expected.push("'" + this.terminals_[p] + "'");
}
if (this.lexer.showPosition) {
errStr = 'Parse error on line ' + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(', ') + ", got '" + (this.terminals_[symbol] || symbol) + "'";
} else {
errStr = 'Parse error on line ' + (yylineno + 1) + ": Unexpected " +
(symbol == 1 /*EOF*/ ? "end of input" :
("'" + (this.terminals_[symbol] || symbol) + "'"));
}
this.parseError(errStr, {
text: this.lexer.match,
token: this.terminals_[symbol] || symbol,
line: this.lexer.yylineno,
loc: yyloc,
expected: expected
});
}
// just recovered from another error
if (recovering == 3) {
if (symbol == EOF) {
throw new Error(errStr || 'Parsing halted.');
}
// discard current lookahead and grab another
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
yyloc = this.lexer.yylloc;
symbol = lex();
}
// try to recover from error
while (1) {
// check for error recovery rule in this state
if ((TERROR.toString()) in table[state]) {
break;
}
if (state === 0) {
throw new Error(errStr || 'Parsing halted.');
}
popStack(1);
state = stack[stack.length - 1];
}
preErrorSymbol = symbol == 2 ? null : symbol; // save the lookahead token
symbol = TERROR; // insert generic error symbol as new lookahead
state = stack[stack.length - 1];
action = table[state] && table[state][TERROR];
recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
}
// this shouldn't happen, unless resolve defaults are off
if (action[0] instanceof Array && action.length > 1) {
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
}
switch (action[0]) {
case 1: // shift
//this.shiftCount++;
stack.push(symbol);
vstack.push(this.lexer.yytext);
lstack.push(this.lexer.yylloc);
stack.push(action[1]); // push state
symbol = null;
if (!preErrorSymbol) { // normal execution/no error
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
yyloc = this.lexer.yylloc;
if (recovering > 0)
recovering--;
} else { // error just occurred, resume old lookahead f/ before error
symbol = preErrorSymbol;
preErrorSymbol = null;
}
break;
case 2: // reduce
//this.reductionCount++;
len = this.productions_[action[1]][1];
// perform semantic action
yyval.$ = vstack[vstack.length - len]; // default to $$ = $1
// default location, uses first token for firsts, last for lasts
yyval._$ = {
first_line: lstack[lstack.length - (len || 1)].first_line,
last_line: lstack[lstack.length - 1].last_line,
first_column: lstack[lstack.length - (len || 1)].first_column,
last_column: lstack[lstack.length - 1].last_column
};
if (ranges) {
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
}
r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
if (typeof r !== 'undefined') {
return r;
}
// pop off stack
if (len) {
stack = stack.slice(0, -1 * len * 2);
vstack = vstack.slice(0, -1 * len);
lstack = lstack.slice(0, -1 * len);
}
stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
vstack.push(yyval.$);
lstack.push(yyval._$);
// goto new state = table[STATE][NONTERMINAL]
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
stack.push(newState);
break;
case 3: // accept
return true;
}
}
return true;
}
};
var lexer = (function() {
var lexer = ({
EOF: 1,
parseError: function parseError(str, hash) {
if (this.yy.parser) {
this.yy.parser.parseError(str, hash);
} else {
throw new Error(str);
}
},
setInput: function(input) {
this._input = input;
this._more = this._less = this.done = false;
this.yylineno = this.yyleng = 0;
this.yytext = this.matched = this.match = '';
this.conditionStack = ['INITIAL'];
this.yylloc = {
first_line: 1,
first_column: 0,
last_line: 1,
last_column: 0
};
if (this.options.ranges) this.yylloc.range = [0, 0];
this.offset = 0;
return this;
},
input: function() {
var ch = this._input[0];
this.yytext += ch;
this.yyleng++;
this.offset++;
this.match += ch;
this.matched += ch;
var lines = ch.match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno++;
this.yylloc.last_line++;
} else {
this.yylloc.last_column++;
}
if (this.options.ranges) this.yylloc.range[1]++;
this._input = this._input.slice(1);
return ch;
},
unput: function(ch) {
var len = ch.length;
var lines = ch.split(/(?:\r\n?|\n)/g);
this._input = ch + this._input;
this.yytext = this.yytext.substr(0, this.yytext.length - len - 1);
//this.yyleng -= len;
this.offset -= len;
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
this.match = this.match.substr(0, this.match.length - 1);
this.matched = this.matched.substr(0, this.matched.length - 1);
if (lines.length - 1) this.yylineno -= lines.length - 1;
var r = this.yylloc.range;
this.yylloc = {
first_line: this.yylloc.first_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.first_column,
last_column: lines ?
(lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
};
if (this.options.ranges) {
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
}
return this;
},
more: function() {
this._more = true;
return this;
},
less: function(n) {
this.unput(this.match.slice(n));
},
pastInput: function() {
var past = this.matched.substr(0, this.matched.length - this.match.length);
return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
},
upcomingInput: function() {
var next = this.match;
if (next.length < 20) {
next += this._input.substr(0, 20 - next.length);
}
return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
},
showPosition: function() {
var pre = this.pastInput();
var c = new Array(pre.length + 1).join("-");
return pre + this.upcomingInput() + "\n" + c + "^";
},
next: function() {
if (this.done) {
return this.EOF;
}
if (!this._input) this.done = true;
var token,
match,
tempMatch,
index,
lines;
if (!this._more) {
this.yytext = '';
this.match = '';
}
var rules = this._currentRules();
for (var i = 0; i < rules.length; i++) {
tempMatch = this._input.match(this.rules[rules[i]]);
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
match = tempMatch;
index = i;
if (!this.options.flex) break;
}
}
if (match) {
lines = match[0].match(/(?:\r\n?|\n).*/g);
if (lines) this.yylineno += lines.length;
this.yylloc = {
first_line: this.yylloc.last_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.last_column,
last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
};
this.yytext += match[0];
this.match += match[0];
this.matches = match;
this.yyleng = this.yytext.length;
if (this.options.ranges) {
this.yylloc.range = [this.offset, this.offset += this.yyleng];
}
this._more = false;
this._input = this._input.slice(match[0].length);
this.matched += match[0];
token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]);
if (this.done && this._input) this.done = false;
if (token) return token;
else return;
}
if (this._input === "") {
return this.EOF;
} else {
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
text: "",
token: null,
line: this.yylineno
});
}
},
lex: function lex() {
var r = this.next();
if (typeof r !== 'undefined') {
return r;
} else {
return this.lex();
}
},
begin: function begin(condition) {
this.conditionStack.push(condition);
},
popState: function popState() {
return this.conditionStack.pop();
},
_currentRules: function _currentRules() {
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
},
topState: function() {
return this.conditionStack[this.conditionStack.length - 2];
},
pushState: function begin(condition) {
this.begin(condition);
}
});
lexer.options = {};
lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
switch ($avoiding_name_collisions) {
case 0:
return "*";
case 1:
return "/";
case 2:
return "-";
case 3:
return "+";
case 4:
return "^";
case 5:
return "%";
case 6:
return "(";
case 7:
return ")";
case 8:
return ",";
case 9:
return "==";
case 10:
return "!=";
case 11:
return "~=";
case 12:
return ">=";
case 13:
return "<=";
case 14:
return "<";
case 15:
return ">";
case 16:
return "?";
case 17:
return ":";
case 18:
return "and";
case 19:
return "or";
case 20:
return "not";
case 21:
return "in";
case 22:
return "of";
case 23:
break;
case 24:
return "NUMBER";
case 25:
yy_.yytext = JSON.stringify(yy_.yytext);
return "SYMBOL";
case 26:
yy_.yytext = yy.buildString("'", yy_.yytext);
return "SYMBOL";
case 27:
yy_.yytext = yy.buildString('"', yy_.yytext);
return "STRING";
case 28:
return "EOF";
}
};
lexer.rules = [/^(?:\*)/, /^(?:\/)/, /^(?:-)/, /^(?:\+)/, /^(?:\^)/, /^(?:\%)/, /^(?:\()/, /^(?:\))/, /^(?:\,)/, /^(?:==)/, /^(?:\!=)/, /^(?:\~=)/, /^(?:>=)/, /^(?:<=)/, /^(?:<)/, /^(?:>)/, /^(?:\?)/, /^(?:\:)/, /^(?:and[^\w])/, /^(?:or[^\w])/, /^(?:not[^\w])/, /^(?:in[^\w])/, /^(?:of[^\w])/, /^(?:\s+)/, /^(?:[0-9]+(?:\.[0-9]+)?\b)/, /^(?:[a-zA-Z$_][\.a-zA-Z0-9$_]*)/, /^(?:'(?:\\'|\\\\|[^'\\])*')/, /^(?:"(?:\\"|\\\\|[^"\\])*")/, /^(?:$)/];
lexer.conditions = {
"INITIAL": {
"rules": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28],
"inclusive": true
}
};
return lexer;
})();
parser.lexer = lexer;
function Parser() {
this.yy = {};
}
Parser.prototype = parser;
parser.Parser = Parser;
return new Parser;
})();
const parser = _parser;
_parser.Parser;
// the parser is dynamically generated from generateParser.js at compile time
// Shared utility functions
const std =
{
isfn: function(fns, funcName) {
return fns.hasOwnProperty(funcName) && typeof fns[funcName] === "function";
},
unknown: function(funcName) {
throw ReferenceError('Unknown function: ' + funcName + '()');
},
coerceArray: function(value) {
if (Array.isArray(value))
return value;
else
return [value];
},
coerceBoolean: function(value) {
if (typeof value === 'boolean')
return +value;
else
return value;
},
isSubset: function(a, b) {
const A = std.coerceArray(a);
const B = std.coerceArray(b);
return +A.every( val => B.includes(val) );
},
buildString: function(quote, literal)
{
quote = String(quote)[0];
literal = String(literal);
let built = '';
if (literal[0] !== quote || literal[literal.length-1] !== quote)
throw new Error(`Unexpected internal error: String literal doesn't begin/end with the right quotation mark.`);
for (let i = 1; i < literal.length - 1; i++)
{
if (literal[i] === "\\")
{
i++;
if (i >= literal.length - 1) throw new Error(`Unexpected internal error: Unescaped backslash at the end of string literal.`);
if (literal[i] === "\\") built += '\\';
else if (literal[i] === quote) built += quote;
else throw new Error(`Unexpected internal error: Invalid escaped character in string literal: ${literal[i]}`);
}
else if (literal[i] === quote)
{
throw new Error(`Unexpected internal error: String literal contains unescaped quotation mark.`);
}
else
{
built += literal[i];
}
}
return JSON.stringify(built);
}
};
parser.yy = Object.create(std);
/**
* Filtrex provides compileExpression() to compile user expressions to JavaScript.
*
* See https://github.com/joewalnes/filtrex for tutorial, reference and examples.
* MIT License.
*
* Includes Jison by Zachary Carter. See http://jison.org/
*
* -Joe Walnes
*/
function compileExpression(expression, options) {
// Check and coerce arguments
if (arguments.length > 2) throw new TypeError('Too many arguments.');
options = typeof options === "object" ? options : {};
let {extraFunctions, customProp} = options;
for (let key of Object.getOwnPropertyNames(options))
{
if (key !== "extraFunctions" && key !== "customProp") throw new TypeError(`Unknown option: ${key}`);
}
// Functions available to the expression
let functions = {
abs: Math.abs,
ceil: Math.ceil,
floor: Math.floor,
log: Math.log,
max: Math.max,
min: Math.min,
random: Math.random,
round: Math.round,
sqrt: Math.sqrt,
};
if (extraFunctions) {
for (var name in extraFunctions) {
if (extraFunctions.hasOwnProperty(name)) {
functions[name] = extraFunctions[name];
}
}
}
// Compile the expression
let tree = parser.parse(expression);
let js = [];
js.push('return ');
function toJs(node) {
if (Array.isArray(node)) {
node.forEach(toJs);
} else {
js.push(node);
}
}
tree.forEach(toJs);
js.push(';');
// Metaprogramming functions
function prop(name, obj) {
return Object.prototype.hasOwnProperty.call(obj||{}, name) ? obj[name] : undefined;
}
function safeGetter(obj) {
return function get(name) {
return Object.prototype.hasOwnProperty.call(obj||{}, name) ? obj[name] : undefined;
}
}
if (typeof customProp === 'function') {
prop = (name, obj) => std.coerceBoolean(customProp(name, safeGetter(obj), obj));
}
// Patch together and return
let func = new Function('fns', 'std', 'prop', 'data', js.join(''));
return function(data) {
try {
return func(functions, std, prop, data);
}
catch (e)
{
return e;
}
};
}
function applyRowFilters(filters, maxRows = Infinity, rows, columnVariables) {
const filteredRows = [];
const expressions = [];
for (const expression of filters) {
expressions.push(compileExpression(expression));
}
let rowIndex = 1;
for (const row of rows) {
let passesTests = true;
if (rowIndex > maxRows) {
break;
}
for (const expression of expressions) {
if (!evaluateExpression(row, expression, columnVariables)) {
passesTests = false;
break;
}
}
if (passesTests) {
filteredRows.push(row);
}
rowIndex += 1;
}
return filteredRows;
}
function sortRows(sortExpressions, rows, columnVariables) {
const sortedRows = [...rows];
const expressions = [];
for (const expression of sortExpressions) {
expressions.push(compileExpression(expression.expression));
}
for (const expression of sortExpressions.reverse()) {
const sortExpression = compileExpression(expression.expression);
sortedRows.sort((a, b) => {
const aResult = evaluateExpression(a, sortExpression, columnVariables);
const bResult = evaluateExpression(b, sortExpression, columnVariables);
if (aResult < bResult) {
return expression.reversed ? 1 : -1;
}
else if (aResult > bResult) {
return expression.reversed ? -1 : 1;
}
else {
return 0;
}
});
}
return sortedRows;
}
function evaluateExpression(row, expression, columnVariables) {
const extendedRow = Object.assign({}, row);
for (const columnVariable in columnVariables !== null && columnVariables !== void 0 ? columnVariables : {}) {
extendedRow[columnVariable] = row[columnVariables[columnVariable]];
}
return expression(extendedRow);
}
function getCellDisplay(row, expression) {
if (typeof row[expression] === 'string') {
return row[expression];
}
else {
return JSON.stringify(row[expression]);
}
}
function getColumnInfo(column) {
if (typeof column === 'string') {
return {
name: column,
expression: column
};
}
else {
return column;
}
}
function getSortExpression(expression) {
if (typeof expression === 'string') {
return {
expression: expression,
reversed: false
};
}
return expression;
}
function getArrayForArrayOrObject(value) {
if (value === null || value === undefined) {
return [];
}
if (Array.isArray(value)) {
return value;
}
return [value];
}
function getFilteredCsvData(csvSpec, csvData) {
var _a, _b, _c;
const _d = ((_a = csvSpec.csvOptions) !== null && _a !== void 0 ? _a : {}), { cast = true, cast_date = true, trim = true, columns = true, skip_empty_lines = true } = _d, extraOptions = __rest(_d, ["cast", "cast_date", "trim", "columns", "skip_empty_lines"]);
const csvOptions = Object.assign({ cast, trim, columns, skip_empty_lines }, extraOptions);
const parsedCsvData = sync(csvData, csvOptions);
const columnNames = [];
const rowColumns = Object.keys(parsedCsvData[0]);
try {
for (const column of (_b = csvSpec.columns) !== null && _b !== void 0 ? _b : rowColumns) {
const columnInfo = getColumnInfo(column);
// Do not attempt to compile/set the expression value
// if it already exists in our known row columns
if (rowColumns.indexOf(columnInfo.name) === -1) {
const expression = compileExpression(columnInfo.expression);
for (const row of parsedCsvData) {
row[columnInfo.name] = evaluateExpression(row, expression, csvSpec.columnVariables);
}
}
columnNames.push(columnInfo.name);
}
}
catch (e) {
throw new Error(`Error evaluating column expressions: ${e.message}.`);
}
let filteredSortedCsvData = [];
try {
filteredSortedCsvData = sortRows(getArrayForArrayOrObject(csvSpec.sortBy).map(getSortExpression), applyRowFilters(getArrayForArrayOrObject(csvSpec.filter), (_c = csvSpec.maxRows) !== null && _c !== void 0 ? _c : Infinity, parsedCsvData, csvSpec.columnVariables), csvSpec.columnVariables);
}
catch (e) {
throw new Error(`Error evaluating filter expressions: ${e.message}.`);
}
return {
columns: columnNames,
rows: filteredSortedCsvData
};
}
class TableRenderer extends obsidian.MarkdownRenderChild {
constructor(columns, rows, container) {
super(container);
this.columns = columns;
this.rows = rows;
this.container = container;
}
onload() {
return __awaiter(this, void 0, void 0, function* () {
yield this.render();
});
}
render() {
return __awaiter(this, void 0, void 0, function* () {
const tableEl = this.container.createEl('table');
const theadEl = tableEl.createEl('thead');
const headerEl = theadEl.createEl('tr');
const tbodyEl = tableEl.createEl('tbody');
const columnNames = [];
for (const column of this.columns) {
const columnInfo = getColumnInfo(column);
headerEl.createEl('th', { text: columnInfo.name });
columnNames.push(columnInfo.name);
}
for (const row of this.rows) {
const trEl = tbodyEl.createEl('tr');
for (const columnName of columnNames) {
trEl.createEl('td', { text: getCellDisplay(row, columnName) });
}
}
});
}
}
function renderErrorPre(container, error) {
let pre = container.createEl('pre', { cls: ["csv-table", "csv-error"] });
pre.appendText(error);
return pre;
}
class CsvTablePlugin extends obsidian.Plugin {
onload() {
return __awaiter(this, void 0, void 0, function* () {
this.registerMarkdownCodeBlockProcessor("csvtable", (csvSpecString, el, ctx) => __awaiter(this, void 0, void 0, function* () {
try {
let tableSpec = {
source: "", // Assert that this has a proper value below
};
try {
tableSpec = obsidian.parseYaml(csvSpecString);
}
catch (e) {
throw new Error(`Could not parse CSV table spec: ${e.message}`);
}
if (!tableSpec.source) {
throw new Error("Parameter 'source' is required.");
}
const file = this.app.vault.getAbstractFileByPath(tableSpec.source);
if (!(file instanceof obsidian.TFile)) {
throw new Error(`CSV file '${tableSpec.source}' could not be found.`);
}
const csvData = yield this.app.vault.cachedRead(file);
console.log("Cached read success");
const filteredCsvData = getFilteredCsvData(tableSpec, csvData);
ctx.addChild(new TableRenderer(filteredCsvData.columns, filteredCsvData.rows, el));
}
catch (e) {
renderErrorPre(el, e.message);
return;
}
}));
});
}
}
module.exports = CsvTablePlugin;
/* nosourcemap */