/* 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 */