diff --git a/docs/_coverpage.md b/docs/_coverpage.md
index 1b143cf..9f10d8e 100644
--- a/docs/_coverpage.md
+++ b/docs/_coverpage.md
@@ -1,4 +1,4 @@
-# Barchart Market Data SDK JavaScript 5.9.0
+# Barchart Market Data SDK JavaScript 5.10.0
> Inject real-time market data into your JavaScript applications
diff --git a/example/browser/example.js b/example/browser/example.js
index dd36cfd..48ea5ca 100644
--- a/example/browser/example.js
+++ b/example/browser/example.js
@@ -183,6 +183,7 @@ module.exports = (() => {
connection = new Connection();
connection.setExtendedProfileMode(true);
+ connection.setExtendedQuoteMode(true);
connection.on('events', handleEvents);
connection.connect(hostname, username, password);
};
@@ -504,7 +505,7 @@ module.exports = (() => {
};
const SP_500 = ['ABT', 'ABBV', 'ACN', 'ATVI', 'AYI', 'ADBE', 'AMD', 'AAP', 'AES', 'AET', 'AMG', 'AFL', 'A', 'APD', 'AKAM', 'ALK', 'ALB', 'ARE', 'ALXN', 'ALGN', 'ALLE', 'AGN', 'ADS', 'LNT', 'ALL', 'GOOGL', 'GOOG', 'MO', 'AMZN', 'AEE', 'AAL', 'AEP', 'AXP', 'AIG', 'AMT', 'AWK', 'AMP', 'ABC', 'AME', 'AMGN', 'APH', 'APC', 'ADI', 'ANDV', 'ANSS', 'ANTM', 'AON', 'AOS', 'APA', 'AIV', 'AAPL', 'AMAT', 'ADM', 'ARNC', 'AJG', 'AIZ', 'T', 'ADSK', 'ADP', 'AZO', 'AVB', 'AVY', 'BHGE', 'BLL', 'BAC', 'BK', 'BCR', 'BAX', 'BBT', 'BDX', 'BRK.B', 'BBY', 'BIIB', 'BLK', 'HRB', 'BA', 'BWA', 'BXP', 'BSX', 'BHF', 'BMY', 'AVGO', 'BF.B', 'CHRW', 'CA', 'COG', 'CDNS', 'CPB', 'COF', 'CAH', 'CBOE', 'KMX', 'CCL', 'CAT', 'CBG', 'CBS', 'CELG', 'CNC', 'CNP', 'CTL', 'CERN', 'CF', 'SCHW', 'CHTR', 'CHK', 'CVX', 'CMG', 'CB', 'CHD', 'CI', 'XEC', 'CINF', 'CTAS', 'CSCO', 'C', 'CFG', 'CTXS', 'CLX', 'CME', 'CMS', 'COH', 'KO', 'CTSH', 'CL', 'CMCSA', 'CMA', 'CAG', 'CXO', 'COP', 'ED', 'STZ', 'COO', 'GLW', 'COST', 'COTY', 'CCI', 'CSRA', 'CSX', 'CMI', 'CVS', 'DHI', 'DHR', 'DRI', 'DVA', 'DE', 'DLPH', 'DAL', 'XRAY', 'DVN', 'DLR', 'DFS', 'DISCA', 'DISCK', 'DISH', 'DG', 'DLTR', 'D', 'DOV', 'DWDP', 'DPS', 'DTE', 'DRE', 'DUK', 'DXC', 'ETFC', 'EMN', 'ETN', 'EBAY', 'ECL', 'EIX', 'EW', 'EA', 'EMR', 'ETR', 'EVHC', 'EOG', 'EQT', 'EFX', 'EQIX', 'EQR', 'ESS', 'EL', 'ES', 'RE', 'EXC', 'EXPE', 'EXPD', 'ESRX', 'EXR', 'XOM', 'FFIV', 'FB', 'FAST', 'FRT', 'FDX', 'FIS', 'FITB', 'FE', 'FISV', 'FLIR', 'FLS', 'FLR', 'FMC', 'FL', 'F', 'FTV', 'FBHS', 'BEN', 'FCX', 'GPS', 'GRMN', 'IT', 'GD', 'GE', 'GGP', 'GIS', 'GM', 'GPC', 'GILD', 'GPN', 'GS', 'GT', 'GWW', 'HAL', 'HBI', 'HOG', 'HRS', 'HIG', 'HAS', 'HCA', 'HCP', 'HP', 'HSIC', 'HSY', 'HES', 'HPE', 'HLT', 'HOLX', 'HD', 'HON', 'HRL', 'HST', 'HPQ', 'HUM', 'HBAN', 'IDXX', 'INFO', 'ITW', 'ILMN', 'IR', 'INTC', 'ICE', 'IBM', 'INCY', 'IP', 'IPG', 'IFF', 'INTU', 'ISRG', 'IVZ', 'IRM', 'JEC', 'JBHT', 'SJM', 'JNJ', 'JCI', 'JPM', 'JNPR', 'KSU', 'K', 'KEY', 'KMB', 'KIM', 'KMI', 'KLAC', 'KSS', 'KHC', 'KR', 'LB', 'LLL', 'LH', 'LRCX', 'LEG', 'LEN', 'LUK', 'LLY', 'LNC', 'LKQ', 'LMT', 'L', 'LOW', 'LYB', 'MTB', 'MAC', 'M', 'MRO', 'MPC', 'MAR', 'MMC', 'MLM', 'MAS', 'MA', 'MAT', 'MKC', 'MCD', 'MCK', 'MDT', 'MRK', 'MET', 'MTD', 'MGM', 'KORS', 'MCHP', 'MU', 'MSFT', 'MAA', 'MHK', 'TAP', 'MDLZ', 'MON', 'MNST', 'MCO', 'MS', 'MOS', 'MSI', 'MYL', 'NDAQ', 'NOV', 'NAVI', 'NTAP', 'NFLX', 'NWL', 'NFX', 'NEM', 'NWSA', 'NWS', 'NEE', 'NLSN', 'NKE', 'NI', 'NBL', 'JWN', 'NSC', 'NTRS', 'NOC', 'NCLH', 'NRG', 'NUE', 'NVDA', 'ORLY', 'OXY', 'OMC', 'OKE', 'ORCL', 'PCAR', 'PKG', 'PH', 'PDCO', 'PAYX', 'PYPL', 'PNR', 'PBCT', 'PEP', 'PKI', 'PRGO', 'PFE', 'PCG', 'PM', 'PSX', 'PNW', 'PXD', 'PNC', 'RL', 'PPG', 'PPL', 'PX', 'PCLN', 'PFG', 'PG', 'PGR', 'PLD', 'PRU', 'PEG', 'PSA', 'PHM', 'PVH', 'QRVO', 'PWR', 'QCOM', 'DGX', 'Q', 'RRC', 'RJF', 'RTN', 'O', 'RHT', 'REG', 'REGN', 'RF', 'RSG', 'RMD', 'RHI', 'ROK', 'COL', 'ROP', 'ROST', 'RCL', 'CRM', 'SBAC', 'SCG', 'SLB', 'SNI', 'STX', 'SEE', 'SRE', 'SHW', 'SIG', 'SPG', 'SWKS', 'SLG', 'SNA', 'SO', 'LUV', 'SPGI', 'SWK', 'SBUX', 'STT', 'SRCL', 'SYK', 'STI', 'SYMC', 'SYF', 'SNPS', 'SYY', 'TROW', 'TGT', 'TEL', 'FTI', 'TXN', 'TXT', 'TMO', 'TIF', 'TWX', 'TJX', 'TMK', 'TSS', 'TSCO', 'TDG', 'TRV', 'TRIP', 'FOXA', 'FOX', 'TSN', 'UDR', 'ULTA', 'USB', 'UA', 'UAA', 'UNP', 'UAL', 'UNH', 'UPS', 'URI', 'UTX', 'UHS', 'UNM', 'VFC', 'VLO', 'VAR', 'VTR', 'VRSN', 'VRSK', 'VZ', 'VRTX', 'VIAB', 'V', 'VNO', 'VMC', 'WMT', 'WBA', 'DIS', 'WM', 'WAT', 'WEC', 'WFC', 'HCN', 'WDC', 'WU', 'WRK', 'WY', 'WHR', 'WMB', 'WLTW', 'WYN', 'WYNN', 'XEL', 'XRX', 'XLNX', 'XL', 'XYL', 'YUM', 'ZBH', 'ZION', 'ZTS'];
- const C3 = ['AL79MRM1.C3', 'BSP9WGQ1.C3', 'RA10BGM1.C3'];
+ const C3 = ['AL79MRM1.C3', 'BSP9WGQ1.C3', 'BUT9USM1.C3', 'RA10BGM1.C3'];
const C3_OLD = ['C3:AL79MRM1', 'C3:BSP9WGQ1', 'C3:RA10BGM1'];
const CMDTY = ['SCB001.CP', 'MER001.CP', 'ZCBAUS.CM', 'HOPAW001009.CM', 'AE030UBX.CS', 'UDZZ303N.CS'];
const PLATTS = ['PLATTS:AAWAB00', 'AAWAB00.PT', 'PLATTS:AAXVA00', 'AAXVA00.PT', 'PLATTS:CBAAF00', 'CBAAF00.PT'];
@@ -516,7 +517,7 @@ module.exports = (() => {
});
})();
-},{"./../../../lib/connection/Connection":2,"./../../../lib/meta":19,"./../../../lib/utilities/data/timezones":25,"./../../../lib/utilities/format/decimal":27,"./../../../lib/utilities/format/price":29,"./../../../lib/utilities/format/quote":30}],2:[function(require,module,exports){
+},{"./../../../lib/connection/Connection":2,"./../../../lib/meta":20,"./../../../lib/utilities/data/timezones":26,"./../../../lib/utilities/format/decimal":28,"./../../../lib/utilities/format/price":30,"./../../../lib/utilities/format/quote":31}],2:[function(require,module,exports){
const array = require('@barchart/common-js/lang/array'),
object = require('@barchart/common-js/lang/object');
@@ -524,8 +525,9 @@ const ConnectionBase = require('./ConnectionBase'),
parseMessage = require('./../utilities/parse/ddf/message');
const retrieveExchanges = require('./snapshots/exchanges/retrieveExchanges'),
- retrieveSnapshots = require('./snapshots/quotes/retrieveSnapshots'),
- retrieveProfileExtensions = require('./snapshots/profiles/retrieveProfileExtensions'),
+ retrieveProfileExtensions = require('./snapshots/profiles/retrieveExtensions'),
+ retrieveQuoteSnapshots = require('./snapshots/quotes/retrieveSnapshots'),
+ retrieveQuoteExtensions = require('./snapshots/quotes/retrieveExtensions'),
SymbolParser = require('./../utilities/parsers/SymbolParser');
const WebSocketAdapterFactory = require('./adapter/WebSocketAdapterFactory'),
@@ -585,6 +587,7 @@ module.exports = (() => {
let __reconnectAllowed = false;
let __pollingFrequency = null;
let __extendedProfile = false;
+ let __extendedQuote = false;
let __watchdogToken = null;
let __watchdogAwake = false;
let __exchangeMetadataPromise = null;
@@ -594,6 +597,7 @@ module.exports = (() => {
let __outboundMessages = [];
let __knownConsumerSymbols = {};
let __pendingProfileSymbols = {};
+ let __completedProfileExtensions = [];
const __listeners = {
marketDepth: {},
marketUpdate: {},
@@ -640,6 +644,12 @@ module.exports = (() => {
if (__extendedProfile !== mode) {
__extendedProfile = mode;
}
+ }
+
+ function setExtendedQuoteMode(mode) {
+ if (__extendedQuote !== mode) {
+ __extendedQuote = mode;
+ }
} //
// Functions for connecting to and disconnecting from JERQ, monitoring
// established connections, and handling involuntary disconnects.
@@ -1529,9 +1539,6 @@ module.exports = (() => {
if (!s) {
done = true;
} else {
- //if (s.startsWith('%')) {
- // s = s + '\n';
- //}
let skip = false;
let msgType = 1; // Assume DDF message containing \x03
@@ -1748,13 +1755,22 @@ module.exports = (() => {
}
if (__extendedProfile && (task.id === 'MU_GO' || task.id === 'P_SNAPSHOT')) {
- const symbolsExtended = symbolsUnique.filter(getIsExtendedSymbol);
+ const symbolsExtended = symbolsUnique.filter(getIsExtendedProfileSymbol);
while (symbolsExtended.length > 0) {
const batch = symbolsExtended.splice(0, batchSize);
processExtendedProfiles(batch);
}
}
+
+ if (__extendedQuote && task.id === 'MU_GO') {
+ const symbolsExtended = symbolsUnique.filter(getIsExtendedQuoteSymbol);
+
+ while (symbolsExtended.length > 0) {
+ const batch = symbolsExtended.splice(0, batchSize);
+ processExtendedQuotes(batch);
+ }
+ }
}
}
};
@@ -1856,7 +1872,7 @@ module.exports = (() => {
return;
}
- retrieveSnapshots(symbols, __loginInfo.username, __loginInfo.password).then(quotes => {
+ retrieveQuoteSnapshots(symbols, __loginInfo.username, __loginInfo.password).then(quotes => {
if (__connectionState !== state.authenticated) {
return;
}
@@ -1890,12 +1906,12 @@ module.exports = (() => {
setTimeout(pumpSnapshotRefresh, 3600000);
} //
- // Functions to acquire "extended" profile data not provided through DDF (via JERQ).
+ // Functions to acquire "extended" data not provided through DDF (via JERQ).
//
/**
* Makes requests for "extended" profile data for a batch of symbols to an out-of-band
- * service (i.e. extras).
+ * web service (i.e. extras).
*
* @private
* @param {String[]} symbols
@@ -1907,7 +1923,7 @@ module.exports = (() => {
return;
}
- retrieveProfileExtensions(symbols, __loginInfo.username, __loginInfo.password).then(extensions => {
+ retrieveProfileExtensions(array.difference(symbols, __completedProfileExtensions), __loginInfo.username, __loginInfo.password).then(extensions => {
if (__connectionState !== state.authenticated) {
return;
}
@@ -1921,11 +1937,47 @@ module.exports = (() => {
message.symbol = symbol;
message.type = 'PROFILE_EXTENSION';
updateMarketState(message);
+
+ __completedProfileExtensions.push(symbol);
});
});
}).catch(e => {
__logger.log(`Profiles [ ${__instance} ]: Out-of-band profile extension request failed for [ ${symbols.join()} ].`, e);
});
+ }
+ /**
+ * Makes requests for "extended" quote data for a batch of symbols to an out-of-band
+ * web service (e.g. extras).
+ *
+ * @private
+ * @param {String[]} symbols
+ */
+
+
+ function processExtendedQuotes(symbols) {
+ if (__connectionState !== state.authenticated) {
+ return;
+ }
+
+ retrieveQuoteExtensions(symbols, __loginInfo.username, __loginInfo.password).then(extensions => {
+ if (__connectionState !== state.authenticated) {
+ return;
+ }
+
+ extensions.forEach(extension => {
+ const producerSymbol = extension.symbol;
+ const consumerSymbols = __knownConsumerSymbols[producerSymbol] || [];
+ const compositeSymbols = array.unique([producerSymbol].concat(consumerSymbols));
+ compositeSymbols.forEach(symbol => {
+ const message = Object.assign({}, extension);
+ message.symbol = symbol;
+ message.type = 'QUOTE_EXTENSION';
+ updateMarketState(message);
+ });
+ });
+ }).catch(e => {
+ __logger.log(`Profiles [ ${__instance} ]: Out-of-band quote extension request failed for [ ${symbols.join()} ].`, e);
+ });
} //
// Internal utility functions for querying symbol subscriptions.
//
@@ -2157,9 +2209,23 @@ module.exports = (() => {
*/
- function getIsExtendedSymbol(symbol) {
+ function getIsExtendedProfileSymbol(symbol) {
return SymbolParser.getIsFuture(symbol) || SymbolParser.getIsC3(symbol) || SymbolParser.getIsCmdty(symbol);
}
+ /**
+ * Indicates if some quote information cannot be extracted from JERQ via
+ * DDF messages (which requires an out-of-band effort to get the complete
+ * profile).
+ *
+ * @private
+ * @param {String} symbol
+ * @returns {Boolean}
+ */
+
+
+ function getIsExtendedQuoteSymbol(symbol) {
+ return SymbolParser.getIsFuture(symbol);
+ }
/**
* Breaks an array of symbols into multiple array, each containing no more
* than 250 symbols. Also, symbols are filtered according to a predicate.
@@ -2200,6 +2266,7 @@ module.exports = (() => {
getProducerSymbolCount: getProducerSymbolCount,
setPollingFrequency: setPollingFrequency,
setExtendedProfileMode: setExtendedProfileMode,
+ setExtendedQuoteMode: setExtendedQuoteMode,
handleProfileRequest: handleProfileRequest,
getDiagnosticsController: getDiagnosticsController
};
@@ -2280,6 +2347,10 @@ module.exports = (() => {
return this._internal.setExtendedProfileMode(mode);
}
+ _onExtendedQuoteModeChanged(mode) {
+ return this._internal.setExtendedQuoteMode(mode);
+ }
+
_handleProfileRequest(symbol) {
this._internal.handleProfileRequest(symbol);
}
@@ -2297,7 +2368,7 @@ module.exports = (() => {
return Connection;
})();
-},{"./../logging/LoggerFactory":12,"./../meta":19,"./../utilities/parse/ddf/message":32,"./../utilities/parsers/SymbolParser":35,"./ConnectionBase":3,"./adapter/WebSocketAdapterFactory":5,"./adapter/WebSocketAdapterFactoryForBrowsers":6,"./diagnostics/DiagnosticsControllerBase":7,"./snapshots/exchanges/retrieveExchanges":8,"./snapshots/profiles/retrieveProfileExtensions":9,"./snapshots/quotes/retrieveSnapshots":10,"@barchart/common-js/lang/array":41,"@barchart/common-js/lang/object":44}],3:[function(require,module,exports){
+},{"./../logging/LoggerFactory":13,"./../meta":20,"./../utilities/parse/ddf/message":33,"./../utilities/parsers/SymbolParser":36,"./ConnectionBase":3,"./adapter/WebSocketAdapterFactory":5,"./adapter/WebSocketAdapterFactoryForBrowsers":6,"./diagnostics/DiagnosticsControllerBase":7,"./snapshots/exchanges/retrieveExchanges":8,"./snapshots/profiles/retrieveExtensions":9,"./snapshots/quotes/retrieveExtensions":10,"./snapshots/quotes/retrieveSnapshots":11,"@barchart/common-js/lang/array":42,"@barchart/common-js/lang/object":45}],3:[function(require,module,exports){
const is = require('@barchart/common-js/lang/is');
const MarketState = require('./../marketState/MarketState');
@@ -2323,6 +2394,7 @@ module.exports = (() => {
this._marketState = new MarketState(symbol => this._handleProfileRequest(symbol));
this._pollingFrequency = null;
this._extendedProfileMode = false;
+ this._extendedQuoteMode = false;
this._instance = ++instanceCounter;
}
/**
@@ -2518,10 +2590,9 @@ module.exports = (() => {
return this._pollingFrequency;
}
/**
- * When set to true, additional properties properties become
- * available on {@link Profile} instances (e.g. future contract
- * expiration date). This is accomplished by making additional
- * out-of-band queries to Barchart services.
+ * When set to true, additional properties become available on {@link Profile}
+ * instances (e.g. the "first notice dates" for futures contracts). This is accomplished
+ * by making additional out-of-band queries to web Barchart services.
*
* @public
* @param {Boolean}
@@ -2545,17 +2616,55 @@ module.exports = (() => {
return;
}
/**
- * Indicates if additional {@link Profile} data (e.g. future contract
- * expiration dates) should be loaded (via out-of-band queries).
+ * Indicates if additional {@link Profile} data (e.g. the "first notice dates" for
+ * futures contracts) should be loaded (via out-of-band queries).
*
* @public
- * @returns {boolean}
+ * @returns {Boolean}
*/
getExtendedProfileMode() {
return this._extendedProfileMode;
}
+ /**
+ * When set to true, additional properties become available on {@link Quote} instances
+ * (e.g. "record high price" for futures contracts). This is accomplished by making
+ * additional out-of-band queries to Barchart web services.
+ *
+ * @public
+ * @param {Boolean}
+ */
+
+
+ setExtendedQuoteMode(mode) {
+ if (is.boolean(mode) && this._extendedQuoteMode !== mode) {
+ this._extendedQuoteMode = mode;
+
+ this._onExtendedQuoteModeChanged(this._extendedQuoteMode);
+ }
+ }
+ /**
+ * @protected
+ * @ignore
+ */
+
+
+ _onExtendedQuoteModeChanged(mode) {
+ return;
+ }
+ /**
+ * Indicates if additional {@link Quote} data (e.g. "record high price" for futures
+ * contracts) should be loaded (via out-of-band queries).
+ *
+ * @public
+ * @returns {Boolean}
+ */
+
+
+ getExtendedQuoteMode() {
+ return this._extendedQuoteMode;
+ }
/**
* @protected
* @ignore
@@ -2668,7 +2777,7 @@ module.exports = (() => {
return ConnectionBase;
})();
-},{"./../marketState/MarketState":16,"@barchart/common-js/lang/is":43}],4:[function(require,module,exports){
+},{"./../marketState/MarketState":17,"@barchart/common-js/lang/is":44}],4:[function(require,module,exports){
module.exports = (() => {
'use strict';
/**
@@ -2955,7 +3064,7 @@ module.exports = (() => {
return WebSocketAdapterFactoryForBrowsers;
})();
-},{"./../../logging/LoggerFactory":12,"./WebSocketAdapter":4,"./WebSocketAdapterFactory":5}],7:[function(require,module,exports){
+},{"./../../logging/LoggerFactory":13,"./WebSocketAdapter":4,"./WebSocketAdapterFactory":5}],7:[function(require,module,exports){
const assert = require('@barchart/common-js/lang/assert');
const is = require('@barchart/common-js/lang/is');
@@ -3035,7 +3144,7 @@ module.exports = (() => {
return DiagnosticsControllerBase;
})();
-},{"@barchart/common-js/lang/assert":42,"@barchart/common-js/lang/is":43}],8:[function(require,module,exports){
+},{"@barchart/common-js/lang/assert":43,"@barchart/common-js/lang/is":44}],8:[function(require,module,exports){
const axios = require('axios');
module.exports = (() => {
@@ -3083,7 +3192,7 @@ module.exports = (() => {
return retrieveExchanges;
})();
-},{"axios":46}],9:[function(require,module,exports){
+},{"axios":48}],9:[function(require,module,exports){
const axios = require('axios');
const array = require('@barchart/common-js/lang/array'),
@@ -3109,7 +3218,7 @@ module.exports = (() => {
* @returns {Promise}
*/
- function retrieveProfileExtensions(symbols, username, password) {
+ function retrieveExtensions(symbols, username, password) {
return Promise.resolve().then(() => {
if (logger === null) {
logger = LoggerFactory.getLogger('@barchart/marketdata-api-js');
@@ -3118,13 +3227,13 @@ module.exports = (() => {
assert.argumentIsArray(symbols, 'symbols', String);
const symbolsForOnDemand = symbols.filter(SymbolParser.getIsC3);
const symbolsForExtras = symbols.filter(SymbolParser.getIsFuture);
- return Promise.all([retrieveProfileExtensionsFromExtras(symbolsForExtras), retrieveProfileExtensionsFromOnDemand(symbolsForOnDemand, username, password)]).then(results => {
+ return Promise.all([retrieveExtensionsFromExtras(symbolsForExtras), retrieveExtensionsFromOnDemand(symbolsForOnDemand, username, password)]).then(results => {
return array.flatten(results);
});
});
}
- function retrieveProfileExtensionsFromExtras(symbols) {
+ function retrieveExtensionsFromExtras(symbols) {
return Promise.resolve().then(() => {
if (symbols.length === 0) {
return Promise.resolve([]);
@@ -3164,7 +3273,7 @@ module.exports = (() => {
});
}
- function retrieveProfileExtensionsFromOnDemand(symbols, username, password) {
+ function retrieveExtensionsFromOnDemand(symbols, username, password) {
return Promise.resolve().then(() => {
if (symbols.length === 0) {
return Promise.resolve([]);
@@ -3199,7 +3308,7 @@ module.exports = (() => {
accumulator.push(extension);
} catch (e) {
- logger.warn(`Snapshot: Failed to process symbol`);
+ logger.warn(`Snapshot: Failed to process symbol [ ${JSON.stringify(result)} ]`);
}
return accumulator;
@@ -3244,10 +3353,155 @@ module.exports = (() => {
*/
- return retrieveProfileExtensions;
+ return retrieveExtensions;
+})();
+
+},{"./../../../logging/LoggerFactory":13,"./../../../utilities/parsers/SymbolParser":36,"@barchart/common-js/lang/Day":39,"@barchart/common-js/lang/array":42,"@barchart/common-js/lang/assert":43,"@barchart/common-js/lang/is":44,"axios":48}],10:[function(require,module,exports){
+const axios = require('axios');
+
+const array = require('@barchart/common-js/lang/array'),
+ Day = require('@barchart/common-js/lang/Day'),
+ is = require('@barchart/common-js/lang/is');
+
+const SymbolParser = require('./../../../utilities/parsers/SymbolParser');
+
+module.exports = (() => {
+ 'use strict';
+
+ let logger = null;
+ /**
+ * Executes an HTTP request for a quote snapshot extension(s). A quote
+ * extension contains supplemental quote-related data that is not available
+ * though normal sources (i.e. some data points are not available through
+ * a stream from JERQ).
+ *
+ * An array of quote refresh messages (suitable for processing by
+ * the {@link MarketState#processMessage} function) are returned.
+ *
+ * @function
+ * @ignore
+ * @param {String|Array} symbols
+ * @param {String} username
+ * @param {String} password
+ * @returns {Promise}
+ */
+
+ function retrieveExtensions(symbols, username, password) {
+ return Promise.resolve().then(() => {
+ let symbolsToUse;
+
+ if (is.string(symbols)) {
+ symbolsToUse = [symbols];
+ } else if (Array.isArray(symbols)) {
+ symbolsToUse = symbols;
+ } else {
+ throw new Error('The "symbols" argument must be a string or an array of strings.');
+ }
+
+ if (symbolsToUse.some(s => !is.string(s))) {
+ throw new Error('The "symbols" can only contain strings.');
+ }
+
+ if (!is.string(username)) {
+ throw new Error('The "username" argument must be a string.');
+ }
+
+ if (!is.string(password)) {
+ throw new Error('The "password" argument must be a string.');
+ }
+
+ const extensions = [];
+
+ const getOrCreateExtension = symbol => {
+ let extension = extensions.find(e => e.symbol === symbol);
+
+ if (!extension) {
+ extension = {
+ symbol
+ };
+ extensions.push(extension);
+ }
+
+ return extension;
+ };
+
+ const promises = [];
+ const futuresSymbols = array.unique(symbolsToUse.filter(s => SymbolParser.getIsFuture(s) && SymbolParser.getIsConcrete(s)).sort());
+
+ if (futuresSymbols.length !== 0) {
+ promises.push(retrieveFuturesHiLo(futuresSymbols, username, password).then(results => {
+ results.forEach(result => {
+ if (result.hilo) {
+ const extension = getOrCreateExtension(result.symbol);
+ const hilo = {};
+ hilo.highPrice = result.hilo.highPrice;
+ hilo.highDate = result.hilo.highDate ? Day.parse(result.hilo.highDate) : null;
+ hilo.lowPrice = result.hilo.lowPrice;
+ hilo.lowDate = result.hilo.lowDate ? Day.parse(result.hilo.lowDate) : null;
+ extension.hilo = hilo;
+ }
+ });
+ }));
+ }
+
+ if (promises.length === 0) {
+ return Promise.resolve([]);
+ }
+
+ return Promise.all(promises).then(() => {
+ return extensions;
+ });
+ });
+ }
+ /**
+ * Retrieves all-time highs and lows for specific futures contracts.
+ *
+ * @private
+ * @param symbols
+ * @param username
+ * @param password
+ * @returns {Promise<>}
+ */
+
+
+ function retrieveFuturesHiLo(symbols, username, password) {
+ return Promise.resolve().then(() => {
+ const options = {
+ url: `https://instrument-extensions.aws.barchart.com/v1/futures/hilo?&symbols=${encodeURIComponent(symbols.join())}`,
+ method: 'GET'
+ };
+ return Promise.resolve(axios(options)).then(response => {
+ return response.data || [];
+ });
+ });
+ }
+ /**
+ * Extended quote information.
+ *
+ * @typedef QuoteExtension
+ * @type {Object}
+ * @ignore
+ * @property {String} symbol
+ * @property {QuoteExtensionHiLo=} hilo
+ */
+
+ /**
+ * Extended quote information (for all-time highs and lows).
+ *
+ * @typedef QuoteExtensionHiLo
+ * @type {Object}
+ * @ignore
+ * @property {Number=} highPrice
+ * @property {Day=} highDate
+ * @property {Number=} lowPrice
+ * @property {Day=} lowDate
+ */
+
+
+ return retrieveExtensions;
})();
-},{"./../../../logging/LoggerFactory":12,"./../../../utilities/parsers/SymbolParser":35,"@barchart/common-js/lang/Day":38,"@barchart/common-js/lang/array":41,"@barchart/common-js/lang/assert":42,"@barchart/common-js/lang/is":43,"axios":46}],10:[function(require,module,exports){
+},{"./../../../utilities/parsers/SymbolParser":36,"@barchart/common-js/lang/Day":39,"@barchart/common-js/lang/array":42,"@barchart/common-js/lang/is":44,"axios":48}],11:[function(require,module,exports){
const axios = require('axios');
const array = require('@barchart/common-js/lang/array'),
@@ -3450,7 +3704,7 @@ module.exports = (() => {
return retrieveSnapshots;
})();
-},{"./../../../logging/LoggerFactory":12,"./../../../utilities/convert/baseCodeToUnitCode":20,"./../../../utilities/convert/dateToDayCode":21,"./../../../utilities/convert/dayCodeToNumber":22,"./../../../utilities/parsers/SymbolParser":35,"@barchart/common-js/lang/array":41,"@barchart/common-js/lang/is":43,"axios":46}],11:[function(require,module,exports){
+},{"./../../../logging/LoggerFactory":13,"./../../../utilities/convert/baseCodeToUnitCode":21,"./../../../utilities/convert/dateToDayCode":22,"./../../../utilities/convert/dayCodeToNumber":23,"./../../../utilities/parsers/SymbolParser":36,"@barchart/common-js/lang/array":42,"@barchart/common-js/lang/is":44,"axios":48}],12:[function(require,module,exports){
module.exports = (() => {
'use strict';
/**
@@ -3546,7 +3800,7 @@ module.exports = (() => {
return Logger;
})();
-},{}],12:[function(require,module,exports){
+},{}],13:[function(require,module,exports){
const Logger = require('./Logger'),
LoggerProvider = require('./LoggerProvider');
@@ -3751,7 +4005,7 @@ module.exports = (() => {
return LoggerFactory;
})();
-},{"./Logger":11,"./LoggerProvider":13}],13:[function(require,module,exports){
+},{"./Logger":12,"./LoggerProvider":14}],14:[function(require,module,exports){
module.exports = (() => {
'use strict';
/**
@@ -3788,7 +4042,7 @@ module.exports = (() => {
return LoggerProvider;
})();
-},{}],14:[function(require,module,exports){
+},{}],15:[function(require,module,exports){
const object = require('@barchart/common-js/lang//object');
const LoggerFactory = require('./../logging/LoggerFactory');
@@ -4051,7 +4305,7 @@ module.exports = (() => {
return CumulativeVolume;
})();
-},{"./../logging/LoggerFactory":12,"@barchart/common-js/lang//object":44}],15:[function(require,module,exports){
+},{"./../logging/LoggerFactory":13,"@barchart/common-js/lang//object":45}],16:[function(require,module,exports){
const Timezones = require('@barchart/common-js/lang/Timezones');
module.exports = (() => {
@@ -4129,7 +4383,7 @@ module.exports = (() => {
return Exchange;
})();
-},{"@barchart/common-js/lang/Timezones":40}],16:[function(require,module,exports){
+},{"@barchart/common-js/lang/Timezones":41}],17:[function(require,module,exports){
const is = require('@barchart/common-js/lang/is'),
object = require('@barchart/common-js/lang/object'),
timezone = require('@barchart/common-js/lang/timezone'),
@@ -4175,6 +4429,7 @@ module.exports = (() => {
const _cvol = {};
const _profileCallbacks = {};
const _profileExtensions = {};
+ const _quoteExtensions = {};
let _timestamp;
@@ -4222,6 +4477,20 @@ module.exports = (() => {
return cv;
};
+ const _processQuoteExtension = (quote, extension) => {
+ if (extension.hilo) {
+ const hilo = extension.hilo;
+
+ if (is.number(hilo.highPrice)) {
+ quote.recordHighPrice = Math.max(hilo.highPrice, is.number(quote.highPrice) ? quote.highPrice : Number.MIN_SAFE_INTEGER);
+ }
+
+ if (is.number(hilo.lowPrice)) {
+ quote.recordLowPrice = Math.min(hilo.lowPrice, is.number(quote.lowPrice) ? quote.lowPrice : Number.MAX_SAFE_INTEGER);
+ }
+ }
+ };
+
const _getOrCreateQuote = symbol => {
let quote = _quote[symbol];
@@ -4233,6 +4502,13 @@ module.exports = (() => {
quote = Quote.clone(symbol, producerQuote);
} else {
quote = new Quote(symbol);
+ const extension = _quoteExtensions[symbol];
+
+ if (extension) {
+ _processQuoteExtension(quote, extension);
+
+ delete _quoteExtensions[symbol];
+ }
}
_quote[symbol] = quote;
@@ -4320,6 +4596,18 @@ module.exports = (() => {
return profile;
};
+ const _deriveRecordHighPrice = quote => {
+ if (is.number(quote.highPrice) && is.number(quote.recordHighPrice) && quote.highPrice > quote.recordHighPrice) {
+ quote.recordHighPrice = quote.highPrice;
+ }
+ };
+
+ const _deriveRecordLowPrice = quote => {
+ if (is.number(quote.lowPrice) && is.number(quote.recordLowPrice) && quote.lowPrice < quote.recordLowPrice) {
+ quote.recordLowPrice = quote.lowPrice;
+ }
+ };
+
const _processMessage = message => {
const symbol = message.symbol;
@@ -4370,6 +4658,18 @@ module.exports = (() => {
return;
}
+ if (message.type === 'QUOTE_EXTENSION') {
+ const q = _quote[symbol];
+
+ if (p && q) {
+ _processQuoteExtension(q, message);
+ } else {
+ _quoteExtensions[symbol] = message;
+ }
+
+ return;
+ }
+
if (!p && message.type !== 'REFRESH_QUOTE') {
_logger.warn(`MarketState [ ${_instance} ]: No profile found for [ ${symbol} ]`);
@@ -4426,10 +4726,16 @@ module.exports = (() => {
switch (message.type) {
case 'HIGH':
q.highPrice = message.value;
+
+ _deriveRecordHighPrice(q);
+
break;
case 'LOW':
q.lowPrice = message.value;
+
+ _deriveRecordLowPrice(q);
+
break;
case 'OPEN':
@@ -4439,6 +4745,10 @@ module.exports = (() => {
q.lowPrice = message.value;
q.lastPrice = message.value;
+ _deriveRecordHighPrice(q);
+
+ _deriveRecordLowPrice(q);
+
if (cv && cv.container) {
cv.container.reset();
}
@@ -4466,12 +4776,16 @@ module.exports = (() => {
q.highPrice = undefined;
} else if (message.highPrice) {
q.highPrice = message.highPrice;
+
+ _deriveRecordHighPrice(q);
}
if (message.lowPrice === null) {
q.lowPrice = undefined;
} else if (message.lowPrice) {
q.lowPrice = message.lowPrice;
+
+ _deriveRecordLowPrice(q);
}
if (message.lastPrice === null) {
@@ -4565,6 +4879,11 @@ module.exports = (() => {
q.openPrice = message.openPrice;
q.highPrice = message.highPrice;
q.lowPrice = message.lowPrice;
+
+ _deriveRecordHighPrice(q);
+
+ _deriveRecordLowPrice(q);
+
q.volume = message.volume;
q.openInterest = message.openInterest;
@@ -4902,7 +5221,7 @@ module.exports = (() => {
return MarketState;
})();
-},{"../utilities/parsers/SymbolParser":35,"./../logging/LoggerFactory":12,"./../meta":19,"./../utilities/convert/dayCodeToNumber":22,"./CumulativeVolume":14,"./Exchange":15,"./Profile":17,"./Quote":18,"@barchart/common-js/lang/Timezones":40,"@barchart/common-js/lang/is":43,"@barchart/common-js/lang/object":44,"@barchart/common-js/lang/timezone":45}],17:[function(require,module,exports){
+},{"../utilities/parsers/SymbolParser":36,"./../logging/LoggerFactory":13,"./../meta":20,"./../utilities/convert/dayCodeToNumber":23,"./CumulativeVolume":15,"./Exchange":16,"./Profile":18,"./Quote":19,"@barchart/common-js/lang/Timezones":41,"@barchart/common-js/lang/is":44,"@barchart/common-js/lang/object":45,"@barchart/common-js/lang/timezone":47}],18:[function(require,module,exports){
const SymbolParser = require('./../utilities/parsers/SymbolParser'),
buildPriceFormatter = require('../utilities/format/factories/price');
@@ -5067,7 +5386,7 @@ module.exports = (() => {
return Profile;
})();
-},{"../utilities/format/factories/price":28,"./../utilities/parsers/SymbolParser":35}],18:[function(require,module,exports){
+},{"../utilities/format/factories/price":29,"./../utilities/parsers/SymbolParser":36}],19:[function(require,module,exports){
module.exports = (() => {
'use strict';
/**
@@ -5245,6 +5564,20 @@ module.exports = (() => {
*/
this.lowPrice = null;
+ /**
+ * @property {number|null} recordHighPrice - The all-time highest trade price from current or previous trading sessions.
+ * @public
+ * @readonly
+ */
+
+ this.recordHighPrice = null;
+ /**
+ * @property {number|null} recordLowPrice - The all-time lowest trade price from current or previous trading sessions.
+ * @public
+ * @readonly
+ */
+
+ this.recordLowPrice = null;
/**
* @property {number|null} volume - The quantity traded during the current trading session.
* @public
@@ -5298,16 +5631,16 @@ module.exports = (() => {
return Quote;
})();
-},{}],19:[function(require,module,exports){
+},{}],20:[function(require,module,exports){
module.exports = (() => {
'use strict';
return {
- version: '5.9.0'
+ version: '5.10.0'
};
})();
-},{}],20:[function(require,module,exports){
+},{}],21:[function(require,module,exports){
const is = require('@barchart/common-js/lang/is');
const UnitCode = require('./../data/UnitCode');
@@ -5338,7 +5671,7 @@ module.exports = (() => {
return convertBaseCodeToUnitCode;
})();
-},{"./../data/UnitCode":24,"@barchart/common-js/lang/is":43}],21:[function(require,module,exports){
+},{"./../data/UnitCode":25,"@barchart/common-js/lang/is":44}],22:[function(require,module,exports){
const convertNumberToDayCode = require('./numberToDayCode');
module.exports = (() => {
@@ -5365,7 +5698,7 @@ module.exports = (() => {
return convertDateToDayCode;
})();
-},{"./numberToDayCode":23}],22:[function(require,module,exports){
+},{"./numberToDayCode":24}],23:[function(require,module,exports){
const is = require('@barchart/common-js/lang/is');
module.exports = (() => {
@@ -5399,7 +5732,7 @@ module.exports = (() => {
return convertDayCodeToNumber;
})();
-},{"@barchart/common-js/lang/is":43}],23:[function(require,module,exports){
+},{"@barchart/common-js/lang/is":44}],24:[function(require,module,exports){
const is = require('@barchart/common-js/lang/is');
module.exports = (() => {
@@ -5436,7 +5769,7 @@ module.exports = (() => {
return convertNumberToDayCode;
})();
-},{"@barchart/common-js/lang/is":43}],24:[function(require,module,exports){
+},{"@barchart/common-js/lang/is":44}],25:[function(require,module,exports){
const Enum = require('@barchart/common-js/lang/Enum');
module.exports = (() => {
@@ -5651,7 +5984,7 @@ module.exports = (() => {
return UnitCode;
})();
-},{"@barchart/common-js/lang/Enum":39}],25:[function(require,module,exports){
+},{"@barchart/common-js/lang/Enum":40}],26:[function(require,module,exports){
const timezone = require('@barchart/common-js/lang/timezone');
module.exports = (() => {
@@ -5686,7 +6019,7 @@ module.exports = (() => {
};
})();
-},{"@barchart/common-js/lang/timezone":45}],26:[function(require,module,exports){
+},{"@barchart/common-js/lang/timezone":47}],27:[function(require,module,exports){
module.exports = (() => {
'use strict';
@@ -5720,7 +6053,7 @@ module.exports = (() => {
return formatDate;
})();
-},{}],27:[function(require,module,exports){
+},{}],28:[function(require,module,exports){
const is = require('@barchart/common-js/lang/is');
module.exports = (() => {
@@ -5790,7 +6123,7 @@ module.exports = (() => {
return formatDecimal;
})();
-},{"@barchart/common-js/lang/is":43}],28:[function(require,module,exports){
+},{"@barchart/common-js/lang/is":44}],29:[function(require,module,exports){
const formatPrice = require('./../price');
module.exports = (() => {
@@ -5826,7 +6159,7 @@ module.exports = (() => {
return buildPriceFormatter;
})();
-},{"./../price":29}],29:[function(require,module,exports){
+},{"./../price":30}],30:[function(require,module,exports){
const is = require('@barchart/common-js/lang/is');
const formatDecimal = require('./decimal');
@@ -5927,7 +6260,7 @@ module.exports = (() => {
return formatPrice;
})();
-},{"./../data/UnitCode":24,"./decimal":27,"@barchart/common-js/lang/is":43}],30:[function(require,module,exports){
+},{"./../data/UnitCode":25,"./decimal":28,"@barchart/common-js/lang/is":44}],31:[function(require,module,exports){
const is = require('@barchart/common-js/lang/is');
const formatDate = require('./date'),
@@ -6012,7 +6345,7 @@ module.exports = (() => {
return formatQuoteDateTime;
})();
-},{"./date":26,"./time":31,"@barchart/common-js/lang/Timezones":40,"@barchart/common-js/lang/is":43}],31:[function(require,module,exports){
+},{"./date":27,"./time":32,"@barchart/common-js/lang/Timezones":41,"@barchart/common-js/lang/is":44}],32:[function(require,module,exports){
module.exports = (() => {
'use strict';
@@ -6165,7 +6498,7 @@ module.exports = (() => {
return formatTime;
})();
-},{}],32:[function(require,module,exports){
+},{}],33:[function(require,module,exports){
const xmlDom = require('xmldom');
const parseValue = require('./value'),
@@ -6718,7 +7051,7 @@ module.exports = (() => {
return parseMessage;
})();
-},{"./timestamp":33,"./value":34,"xmldom":76}],33:[function(require,module,exports){
+},{"./timestamp":34,"./value":35,"xmldom":78}],34:[function(require,module,exports){
module.exports = (() => {
'use strict';
/**
@@ -6772,7 +7105,7 @@ module.exports = (() => {
return parseTimestamp;
})();
-},{}],34:[function(require,module,exports){
+},{}],35:[function(require,module,exports){
module.exports = (() => {
'use strict';
@@ -6872,8 +7205,9 @@ module.exports = (() => {
return parseValue;
})();
-},{}],35:[function(require,module,exports){
-const is = require('@barchart/common-js/lang/is');
+},{}],36:[function(require,module,exports){
+const is = require('@barchart/common-js/lang/is'),
+ string = require('@barchart/common-js/lang/string');
module.exports = (() => {
'use strict';
@@ -7209,6 +7543,28 @@ module.exports = (() => {
return formatted;
}
+ /**
+ * Converts an abbreviated futures symbol (with a single digit year) into
+ * a futures symbol with a two digit year. If the symbol is not a futures
+ * contract, a null value is returned.
+ *
+ * @static
+ * @public
+ * @param {String} symbol
+ * @returns {String|null}
+ */
+
+
+ static getFuturesExplicitFormat(symbol) {
+ let explicit = null;
+
+ if (SymbolParser.getIsFuture(symbol) && SymbolParser.getIsConcrete(symbol)) {
+ const parsed = SymbolParser.parseInstrumentType(symbol);
+ explicit = `${parsed.root}${parsed.month}${string.padLeft(Math.floor(parsed.year % 100).toString(), 2, '0')}`;
+ }
+
+ return explicit;
+ }
/**
* Returns true if prices for the symbol should be represented as a percentage; false
* otherwise.
@@ -7538,7 +7894,7 @@ module.exports = (() => {
return SymbolParser;
})();
-},{"@barchart/common-js/lang/is":43}],36:[function(require,module,exports){
+},{"@barchart/common-js/lang/is":44,"@barchart/common-js/lang/string":46}],37:[function(require,module,exports){
const assert = require('./../../lang/assert'),
comparators = require('./comparators');
@@ -7657,7 +8013,7 @@ module.exports = (() => {
return ComparatorBuilder;
})();
-},{"./../../lang/assert":42,"./comparators":37}],37:[function(require,module,exports){
+},{"./../../lang/assert":43,"./comparators":38}],38:[function(require,module,exports){
const assert = require('./../../lang/assert');
module.exports = (() => {
@@ -7752,7 +8108,7 @@ module.exports = (() => {
};
})();
-},{"./../../lang/assert":42}],38:[function(require,module,exports){
+},{"./../../lang/assert":43}],39:[function(require,module,exports){
const assert = require('./assert'),
ComparatorBuilder = require('./../collections/sorting/ComparatorBuilder'),
comparators = require('./../collections/sorting/comparators'),
@@ -8271,7 +8627,7 @@ module.exports = (() => {
return Day;
})();
-},{"./../collections/sorting/ComparatorBuilder":36,"./../collections/sorting/comparators":37,"./assert":42,"./is":43}],39:[function(require,module,exports){
+},{"./../collections/sorting/ComparatorBuilder":37,"./../collections/sorting/comparators":38,"./assert":43,"./is":44}],40:[function(require,module,exports){
const assert = require('./assert');
module.exports = (() => {
@@ -8391,7 +8747,7 @@ module.exports = (() => {
return Enum;
})();
-},{"./assert":42}],40:[function(require,module,exports){
+},{"./assert":43}],41:[function(require,module,exports){
const moment = require('moment-timezone/builds/moment-timezone-with-data-2012-2022');
const Enum = require('./Enum'),
@@ -8533,7 +8889,7 @@ module.exports = (() => {
return Timezones;
})();
-},{"./Enum":39,"./is":43,"./timezone":45,"moment-timezone/builds/moment-timezone-with-data-2012-2022":74}],41:[function(require,module,exports){
+},{"./Enum":40,"./is":44,"./timezone":47,"moment-timezone/builds/moment-timezone-with-data-2012-2022":76}],42:[function(require,module,exports){
const assert = require('./assert'),
is = require('./is');
@@ -9037,7 +9393,7 @@ module.exports = (() => {
}
})();
-},{"./assert":42,"./is":43}],42:[function(require,module,exports){
+},{"./assert":43,"./is":44}],43:[function(require,module,exports){
const is = require('./is');
module.exports = (() => {
@@ -9182,7 +9538,7 @@ module.exports = (() => {
};
})();
-},{"./is":43}],43:[function(require,module,exports){
+},{"./is":44}],44:[function(require,module,exports){
module.exports = (() => {
'use strict';
/**
@@ -9401,7 +9757,7 @@ module.exports = (() => {
};
})();
-},{}],44:[function(require,module,exports){
+},{}],45:[function(require,module,exports){
const array = require('./array'),
is = require('./is');
@@ -9561,7 +9917,133 @@ module.exports = (() => {
return object;
})();
-},{"./array":41,"./is":43}],45:[function(require,module,exports){
+},{"./array":42,"./is":44}],46:[function(require,module,exports){
+const assert = require('./assert'),
+ is = require('./is');
+
+module.exports = (() => {
+ 'use strict';
+
+ const regex = {};
+ regex.camel = {};
+ regex.camel.violations = /\b[A-Z]/g;
+ /**
+ * Utility functions for strings.
+ *
+ * @public
+ * @module lang/string
+ */
+
+ return {
+ /**
+ * Adjusts a string, replacing the first character of each word with an uppercase
+ * character and all subsequent characters in the word with lowercase characters.
+ *
+ * @public
+ * @static
+ * @param {String} s
+ * @returns {String}
+ */
+ startCase(s) {
+ return s.split(' ').reduce((phrase, word) => {
+ if (word.length !== 0) {
+ phrase.push(word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
+ }
+
+ return phrase;
+ }, []).join(' ');
+ },
+
+ /**
+ * Adjust a string to use camel case, where the first letter of each word is replaced
+ * with a lower case character.
+ *
+ * @public
+ * @static
+ * @param {String} s
+ * @returns {String}
+ */
+ camelCase(s) {
+ assert.argumentIsRequired(s, 's', String);
+ return s.replace(regex.camel.violations, m => m.toLocaleLowerCase());
+ },
+
+ /**
+ * If a string exceeds a desired length, it is truncated and a poor man's
+ * ellipsis (i.e. three periods) is appended. Otherwise, the original
+ * string is returned.
+ *
+ * @public
+ * @static
+ * @param {String} s
+ * @param {Number} length
+ * @returns {String}
+ */
+ truncate(s, length) {
+ if (is.string(s) && s.length > length) {
+ return s.substring(0, length) + ' ...';
+ } else {
+ return s;
+ }
+ },
+
+ /**
+ * Adds leading characters to a string, until the string length is a desired size.
+ *
+ * @public
+ * @static
+ * @param {String} s - The string to pad.
+ * @param {Number} length - The desired overall length of the string.
+ * @param {String} character - The character to use for padding.
+ * @returns {String}
+ */
+ padLeft(s, length, character) {
+ assert.argumentIsRequired(s, 's', String);
+ assert.argumentIsRequired(length, 'length', Number);
+ assert.argumentIsRequired(character, 'character', String);
+
+ if (character.length !== 1) {
+ throw new Error('The "character" argument must be one character in length.');
+ }
+
+ return character.repeat(length - s.length) + s;
+ },
+
+ /**
+ * Performs a simple token replacement on a string; where the tokens
+ * are braced numbers (e.g. {0}, {1}, {2}).
+ *
+ * @public
+ * @static
+ * @param {String} s - The string to format (e.g. 'my first name is {0} and my last name is {1}')
+ * @param {Array} data - The replacement data
+ * @returns {String}
+ */
+ format(s, ...data) {
+ assert.argumentIsRequired(s, 's', String);
+ return s.replace(/{(\d+)}/g, (match, i) => {
+ let replacement;
+
+ if (i < data.length) {
+ const item = data[i];
+
+ if (!is.undefined(item) && !is.null(item)) {
+ replacement = item.toString();
+ } else {
+ replacement = match;
+ }
+ } else {
+ replacement = match;
+ }
+
+ return replacement;
+ });
+ }
+
+ };
+})();
+
+},{"./assert":43,"./is":44}],47:[function(require,module,exports){
const moment = require('moment-timezone/builds/moment-timezone-with-data-2012-2022'),
assert = require('./assert');
@@ -9616,9 +10098,9 @@ module.exports = (() => {
};
})();
-},{"./assert":42,"moment-timezone/builds/moment-timezone-with-data-2012-2022":74}],46:[function(require,module,exports){
+},{"./assert":43,"moment-timezone/builds/moment-timezone-with-data-2012-2022":76}],48:[function(require,module,exports){
module.exports = require('./lib/axios');
-},{"./lib/axios":48}],47:[function(require,module,exports){
+},{"./lib/axios":50}],49:[function(require,module,exports){
'use strict';
var utils = require('./../utils');
@@ -9799,7 +10281,7 @@ module.exports = function xhrAdapter(config) {
});
};
-},{"../core/buildFullPath":54,"../core/createError":55,"./../core/settle":59,"./../helpers/buildURL":63,"./../helpers/cookies":65,"./../helpers/isURLSameOrigin":68,"./../helpers/parseHeaders":70,"./../utils":72}],48:[function(require,module,exports){
+},{"../core/buildFullPath":56,"../core/createError":57,"./../core/settle":61,"./../helpers/buildURL":65,"./../helpers/cookies":67,"./../helpers/isURLSameOrigin":70,"./../helpers/parseHeaders":72,"./../utils":74}],50:[function(require,module,exports){
'use strict';
var utils = require('./utils');
@@ -9857,7 +10339,7 @@ module.exports = axios;
// Allow use of default import syntax in TypeScript
module.exports.default = axios;
-},{"./cancel/Cancel":49,"./cancel/CancelToken":50,"./cancel/isCancel":51,"./core/Axios":52,"./core/mergeConfig":58,"./defaults":61,"./helpers/bind":62,"./helpers/isAxiosError":67,"./helpers/spread":71,"./utils":72}],49:[function(require,module,exports){
+},{"./cancel/Cancel":51,"./cancel/CancelToken":52,"./cancel/isCancel":53,"./core/Axios":54,"./core/mergeConfig":60,"./defaults":63,"./helpers/bind":64,"./helpers/isAxiosError":69,"./helpers/spread":73,"./utils":74}],51:[function(require,module,exports){
'use strict';
/**
@@ -9878,7 +10360,7 @@ Cancel.prototype.__CANCEL__ = true;
module.exports = Cancel;
-},{}],50:[function(require,module,exports){
+},{}],52:[function(require,module,exports){
'use strict';
var Cancel = require('./Cancel');
@@ -9937,14 +10419,14 @@ CancelToken.source = function source() {
module.exports = CancelToken;
-},{"./Cancel":49}],51:[function(require,module,exports){
+},{"./Cancel":51}],53:[function(require,module,exports){
'use strict';
module.exports = function isCancel(value) {
return !!(value && value.__CANCEL__);
};
-},{}],52:[function(require,module,exports){
+},{}],54:[function(require,module,exports){
'use strict';
var utils = require('./../utils');
@@ -10041,7 +10523,7 @@ utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
module.exports = Axios;
-},{"../helpers/buildURL":63,"./../utils":72,"./InterceptorManager":53,"./dispatchRequest":56,"./mergeConfig":58}],53:[function(require,module,exports){
+},{"../helpers/buildURL":65,"./../utils":74,"./InterceptorManager":55,"./dispatchRequest":58,"./mergeConfig":60}],55:[function(require,module,exports){
'use strict';
var utils = require('./../utils');
@@ -10095,7 +10577,7 @@ InterceptorManager.prototype.forEach = function forEach(fn) {
module.exports = InterceptorManager;
-},{"./../utils":72}],54:[function(require,module,exports){
+},{"./../utils":74}],56:[function(require,module,exports){
'use strict';
var isAbsoluteURL = require('../helpers/isAbsoluteURL');
@@ -10117,7 +10599,7 @@ module.exports = function buildFullPath(baseURL, requestedURL) {
return requestedURL;
};
-},{"../helpers/combineURLs":64,"../helpers/isAbsoluteURL":66}],55:[function(require,module,exports){
+},{"../helpers/combineURLs":66,"../helpers/isAbsoluteURL":68}],57:[function(require,module,exports){
'use strict';
var enhanceError = require('./enhanceError');
@@ -10137,7 +10619,7 @@ module.exports = function createError(message, config, code, request, response)
return enhanceError(error, config, code, request, response);
};
-},{"./enhanceError":57}],56:[function(require,module,exports){
+},{"./enhanceError":59}],58:[function(require,module,exports){
'use strict';
var utils = require('./../utils');
@@ -10218,7 +10700,7 @@ module.exports = function dispatchRequest(config) {
});
};
-},{"../cancel/isCancel":51,"../defaults":61,"./../utils":72,"./transformData":60}],57:[function(require,module,exports){
+},{"../cancel/isCancel":53,"../defaults":63,"./../utils":74,"./transformData":62}],59:[function(require,module,exports){
'use strict';
/**
@@ -10262,7 +10744,7 @@ module.exports = function enhanceError(error, config, code, request, response) {
return error;
};
-},{}],58:[function(require,module,exports){
+},{}],60:[function(require,module,exports){
'use strict';
var utils = require('../utils');
@@ -10351,7 +10833,7 @@ module.exports = function mergeConfig(config1, config2) {
return config;
};
-},{"../utils":72}],59:[function(require,module,exports){
+},{"../utils":74}],61:[function(require,module,exports){
'use strict';
var createError = require('./createError');
@@ -10378,7 +10860,7 @@ module.exports = function settle(resolve, reject, response) {
}
};
-},{"./createError":55}],60:[function(require,module,exports){
+},{"./createError":57}],62:[function(require,module,exports){
'use strict';
var utils = require('./../utils');
@@ -10400,7 +10882,7 @@ module.exports = function transformData(data, headers, fns) {
return data;
};
-},{"./../utils":72}],61:[function(require,module,exports){
+},{"./../utils":74}],63:[function(require,module,exports){
(function (process){(function (){
'use strict';
@@ -10502,7 +10984,7 @@ utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
module.exports = defaults;
}).call(this)}).call(this,require('_process'))
-},{"./adapters/http":47,"./adapters/xhr":47,"./helpers/normalizeHeaderName":69,"./utils":72,"_process":73}],62:[function(require,module,exports){
+},{"./adapters/http":49,"./adapters/xhr":49,"./helpers/normalizeHeaderName":71,"./utils":74,"_process":75}],64:[function(require,module,exports){
'use strict';
module.exports = function bind(fn, thisArg) {
@@ -10515,7 +10997,7 @@ module.exports = function bind(fn, thisArg) {
};
};
-},{}],63:[function(require,module,exports){
+},{}],65:[function(require,module,exports){
'use strict';
var utils = require('./../utils');
@@ -10587,7 +11069,7 @@ module.exports = function buildURL(url, params, paramsSerializer) {
return url;
};
-},{"./../utils":72}],64:[function(require,module,exports){
+},{"./../utils":74}],66:[function(require,module,exports){
'use strict';
/**
@@ -10603,7 +11085,7 @@ module.exports = function combineURLs(baseURL, relativeURL) {
: baseURL;
};
-},{}],65:[function(require,module,exports){
+},{}],67:[function(require,module,exports){
'use strict';
var utils = require('./../utils');
@@ -10658,7 +11140,7 @@ module.exports = (
})()
);
-},{"./../utils":72}],66:[function(require,module,exports){
+},{"./../utils":74}],68:[function(require,module,exports){
'use strict';
/**
@@ -10674,7 +11156,7 @@ module.exports = function isAbsoluteURL(url) {
return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
};
-},{}],67:[function(require,module,exports){
+},{}],69:[function(require,module,exports){
'use strict';
/**
@@ -10687,7 +11169,7 @@ module.exports = function isAxiosError(payload) {
return (typeof payload === 'object') && (payload.isAxiosError === true);
};
-},{}],68:[function(require,module,exports){
+},{}],70:[function(require,module,exports){
'use strict';
var utils = require('./../utils');
@@ -10757,7 +11239,7 @@ module.exports = (
})()
);
-},{"./../utils":72}],69:[function(require,module,exports){
+},{"./../utils":74}],71:[function(require,module,exports){
'use strict';
var utils = require('../utils');
@@ -10771,7 +11253,7 @@ module.exports = function normalizeHeaderName(headers, normalizedName) {
});
};
-},{"../utils":72}],70:[function(require,module,exports){
+},{"../utils":74}],72:[function(require,module,exports){
'use strict';
var utils = require('./../utils');
@@ -10826,7 +11308,7 @@ module.exports = function parseHeaders(headers) {
return parsed;
};
-},{"./../utils":72}],71:[function(require,module,exports){
+},{"./../utils":74}],73:[function(require,module,exports){
'use strict';
/**
@@ -10855,7 +11337,7 @@ module.exports = function spread(callback) {
};
};
-},{}],72:[function(require,module,exports){
+},{}],74:[function(require,module,exports){
'use strict';
var bind = require('./helpers/bind');
@@ -11208,7 +11690,7 @@ module.exports = {
stripBOM: stripBOM
};
-},{"./helpers/bind":62}],73:[function(require,module,exports){
+},{"./helpers/bind":64}],75:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
@@ -11394,7 +11876,7 @@ process.chdir = function (dir) {
};
process.umask = function() { return 0; };
-},{}],74:[function(require,module,exports){
+},{}],76:[function(require,module,exports){
//! moment-timezone.js
//! version : 0.5.26
//! Copyright (c) JS Foundation and other contributors
@@ -12620,7 +13102,7 @@ process.umask = function() { return 0; };
return moment;
}));
-},{"moment":75}],75:[function(require,module,exports){
+},{"moment":77}],77:[function(require,module,exports){
//! moment.js
;(function (global, factory) {
@@ -17224,7 +17706,7 @@ process.umask = function() { return 0; };
})));
-},{}],76:[function(require,module,exports){
+},{}],78:[function(require,module,exports){
function DOMParser(options){
this.options = options ||{locator:{}};
}
@@ -17479,7 +17961,7 @@ exports.DOMParser = DOMParser;
exports.__DOMHandler = DOMHandler;
//}
-},{"./dom":77,"./entities":78,"./sax":79}],77:[function(require,module,exports){
+},{"./dom":79,"./entities":80,"./sax":81}],79:[function(require,module,exports){
function copy(src,dest){
for(var p in src){
dest[p] = src[p];
@@ -18764,7 +19246,7 @@ try{
exports.XMLSerializer = XMLSerializer;
//}
-},{}],78:[function(require,module,exports){
+},{}],80:[function(require,module,exports){
exports.entityMap = {
lt: '<',
gt: '>',
@@ -19009,7 +19491,7 @@ exports.entityMap = {
diams: "♦"
};
-},{}],79:[function(require,module,exports){
+},{}],81:[function(require,module,exports){
//[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
//[5] Name ::= NameStartChar (NameChar)*
diff --git a/lib/meta.js b/lib/meta.js
index 213cb3b..20f0b0a 100644
--- a/lib/meta.js
+++ b/lib/meta.js
@@ -2,6 +2,6 @@ module.exports = (() => {
'use strict';
return {
- version: '5.9.0'
+ version: '5.10.0'
};
})();
\ No newline at end of file
diff --git a/package.json b/package.json
index 72d9e05..1d712d4 100644
--- a/package.json
+++ b/package.json
@@ -1,77 +1,77 @@
{
- "name": "@barchart/marketdata-api-js",
- "version": "5.9.0",
- "description": "SDK for streaming market data from Barchart.com",
- "author": {
- "name": "Eero Pikat",
- "email": "eero.pikat@barchart.com",
- "url": "https://www.barchart.com"
- },
- "contributors": [
- {
- "name": "Mike Ehrenberg",
- "email": "mike.ehrenberg@barchart.com",
- "url": "https://www.barchart.com"
+ "name": "@barchart/marketdata-api-js",
+ "version": "5.10.0",
+ "description": "SDK for streaming market data from Barchart.com",
+ "author": {
+ "name": "Eero Pikat",
+ "email": "eero.pikat@barchart.com",
+ "url": "https://www.barchart.com"
},
- {
- "name": "Bryan Ingle",
- "email": "bryan.ingle@barchart.com",
- "url": "https://www.barchart.com"
- }
- ],
- "scripts": {
- "test": "gulp test",
- "watch": "gulp watch",
- "docs": "barchart-documentation serve"
- },
- "repository": {
- "type": "git",
- "url": "git+ssh://github.com/barchart/marketdata-api-js.git"
- },
- "keywords": [
- "Barchart",
- "Market",
- "Data",
- "Realtime",
- "Stocks",
- "Futures",
- "Forex"
- ],
- "dependencies": {
- "@barchart/common-js": "^4.10.0",
- "axios": "^0.21.1",
- "ws": "7.4.6",
- "xmldom": "0.6.0"
- },
- "devDependencies": {
- "@babel/core": "^7.6.2",
- "aws-sdk": "^2.546.0",
- "babelify": "^10.0.0",
- "browserify": "^16.5.0",
- "git-get-status": "^1.0.5",
- "glob": "^6.0.1",
- "gulp": "^4.0.2",
- "gulp-awspublish": "^4.0.0",
- "gulp-git": "^2.5.1",
- "gulp-jasmine": "^2.2.1",
- "gulp-jshint": "^2.1.0",
- "gulp-prompt": "^1.2.0",
- "gulp-rename": "^1.4.0",
- "gulp-replace": "^0.5.4",
- "jshint": "^2.10.3",
- "log4js": "^4.4.0",
- "merge-stream": "^2.0.0",
- "uuid": "^8.3.2",
- "vinyl-buffer": "^1.0.1",
- "vinyl-source-stream": "^2.0.0"
- },
- "browserify": {
- "transform": [
- [
- "babelify"
- ]
- ]
- },
- "license": "MIT",
- "private": false
+ "contributors": [
+ {
+ "name": "Mike Ehrenberg",
+ "email": "mike.ehrenberg@barchart.com",
+ "url": "https://www.barchart.com"
+ },
+ {
+ "name": "Bryan Ingle",
+ "email": "bryan.ingle@barchart.com",
+ "url": "https://www.barchart.com"
+ }
+ ],
+ "scripts": {
+ "test": "gulp test",
+ "watch": "gulp watch",
+ "docs": "barchart-documentation serve"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://github.com/barchart/marketdata-api-js.git"
+ },
+ "keywords": [
+ "Barchart",
+ "Market",
+ "Data",
+ "Realtime",
+ "Stocks",
+ "Futures",
+ "Forex"
+ ],
+ "dependencies": {
+ "@barchart/common-js": "^4.10.0",
+ "axios": "^0.21.1",
+ "ws": "7.4.6",
+ "xmldom": "0.6.0"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.6.2",
+ "aws-sdk": "^2.546.0",
+ "babelify": "^10.0.0",
+ "browserify": "^16.5.0",
+ "git-get-status": "^1.0.5",
+ "glob": "^6.0.1",
+ "gulp": "^4.0.2",
+ "gulp-awspublish": "^4.0.0",
+ "gulp-git": "^2.5.1",
+ "gulp-jasmine": "^2.2.1",
+ "gulp-jshint": "^2.1.0",
+ "gulp-prompt": "^1.2.0",
+ "gulp-rename": "^1.4.0",
+ "gulp-replace": "^0.5.4",
+ "jshint": "^2.10.3",
+ "log4js": "^4.4.0",
+ "merge-stream": "^2.0.0",
+ "uuid": "^8.3.2",
+ "vinyl-buffer": "^1.0.1",
+ "vinyl-source-stream": "^2.0.0"
+ },
+ "browserify": {
+ "transform": [
+ [
+ "babelify"
+ ]
+ ]
+ },
+ "license": "MIT",
+ "private": false
}
diff --git a/test/dist/barchart-marketdata-api-tests-5.js b/test/dist/barchart-marketdata-api-tests-5.js
index c820dba..e366d3f 100644
--- a/test/dist/barchart-marketdata-api-tests-5.js
+++ b/test/dist/barchart-marketdata-api-tests-5.js
@@ -2324,7 +2324,7 @@ module.exports = (() => {
return parseMessage;
})();
-},{"./timestamp":24,"./value":25,"xmldom":37}],24:[function(require,module,exports){
+},{"./timestamp":24,"./value":25,"xmldom":38}],24:[function(require,module,exports){
module.exports = (() => {
'use strict';
/**
@@ -2611,7 +2611,8 @@ module.exports = (() => {
})();
},{"./../data/UnitCode":13,"@barchart/common-js/lang/is":32}],27:[function(require,module,exports){
-const is = require('@barchart/common-js/lang/is');
+const is = require('@barchart/common-js/lang/is'),
+ string = require('@barchart/common-js/lang/string');
module.exports = (() => {
'use strict';
@@ -2947,6 +2948,28 @@ module.exports = (() => {
return formatted;
}
+ /**
+ * Converts an abbreviated futures symbol (with a single digit year) into
+ * a futures symbol with a two digit year. If the symbol is not a futures
+ * contract, a null value is returned.
+ *
+ * @static
+ * @public
+ * @param {String} symbol
+ * @returns {String|null}
+ */
+
+
+ static getFuturesExplicitFormat(symbol) {
+ let explicit = null;
+
+ if (SymbolParser.getIsFuture(symbol) && SymbolParser.getIsConcrete(symbol)) {
+ const parsed = SymbolParser.parseInstrumentType(symbol);
+ explicit = `${parsed.root}${parsed.month}${string.padLeft(Math.floor(parsed.year % 100).toString(), 2, '0')}`;
+ }
+
+ return explicit;
+ }
/**
* Returns true if prices for the symbol should be represented as a percentage; false
* otherwise.
@@ -3276,7 +3299,7 @@ module.exports = (() => {
return SymbolParser;
})();
-},{"@barchart/common-js/lang/is":32}],28:[function(require,module,exports){
+},{"@barchart/common-js/lang/is":32,"@barchart/common-js/lang/string":34}],28:[function(require,module,exports){
const assert = require('./assert');
module.exports = (() => {
@@ -3538,7 +3561,7 @@ module.exports = (() => {
return Timezones;
})();
-},{"./Enum":28,"./is":32,"./timezone":34,"moment-timezone/builds/moment-timezone-with-data-2012-2022":35}],30:[function(require,module,exports){
+},{"./Enum":28,"./is":32,"./timezone":35,"moment-timezone/builds/moment-timezone-with-data-2012-2022":36}],30:[function(require,module,exports){
const assert = require('./assert'),
is = require('./is');
@@ -3961,25 +3984,72 @@ module.exports = (() => {
} else if (comparator(item, a[0]) < 0) {
a.unshift(item);
} else {
- a.splice(binarySearch(a, item, comparator, 0, a.length - 1), 0, item);
+ a.splice(binarySearchForInsert(a, item, comparator, 0, a.length - 1), 0, item);
}
return a;
+ },
+
+ /**
+ * Performs a binary search to locate an item within an array.
+ *
+ * @param {*[]} a
+ * @param {*} key
+ * @param {Function} comparator
+ * @param {Number=} start
+ * @param {Number=} end
+ * @returns {*|null}
+ */
+ binarySearch(a, key, comparator, start, end) {
+ assert.argumentIsArray(a, 'a');
+ assert.argumentIsRequired(comparator, 'comparator', Function);
+ assert.argumentIsOptional(start, 'start', Number);
+ assert.argumentIsOptional(end, 'end', Number);
+
+ if (a.length === 0) {
+ return null;
+ }
+
+ return binarySearchForMatch(a, key, comparator, start || 0, end || a.length - 1);
}
};
- function binarySearch(array, item, comparator, start, end) {
+ function binarySearchForMatch(a, key, comparator, start, end) {
+ const size = end - start;
+ const midpointIndex = start + Math.floor(size / 2);
+ const midpointItem = a[midpointIndex];
+ const comparison = comparator(key, midpointItem);
+
+ if (comparison === 0) {
+ return midpointItem;
+ } else if (size < 2) {
+ const finalIndex = a.length - 1;
+ const finalItem = a[finalIndex];
+
+ if (end === finalIndex && comparator(key, finalItem) === 0) {
+ return finalItem;
+ } else {
+ return null;
+ }
+ } else if (comparison > 0) {
+ return binarySearchForMatch(a, key, comparator, midpointIndex, end);
+ } else {
+ return binarySearchForMatch(a, key, comparator, start, midpointIndex);
+ }
+ }
+
+ function binarySearchForInsert(a, item, comparator, start, end) {
const size = end - start;
const midpointIndex = start + Math.floor(size / 2);
- const midpointItem = array[midpointIndex];
+ const midpointItem = a[midpointIndex];
const comparison = comparator(item, midpointItem) > 0;
if (size < 2) {
if (comparison > 0) {
- const finalIndex = array.length - 1;
+ const finalIndex = a.length - 1;
- if (end === finalIndex && comparator(item, array[finalIndex]) > 0) {
+ if (end === finalIndex && comparator(item, a[finalIndex]) > 0) {
return end + 1;
} else {
return end;
@@ -3988,9 +4058,9 @@ module.exports = (() => {
return start;
}
} else if (comparison > 0) {
- return binarySearch(array, item, comparator, midpointIndex, end);
+ return binarySearchForInsert(a, item, comparator, midpointIndex, end);
} else {
- return binarySearch(array, item, comparator, start, midpointIndex);
+ return binarySearchForInsert(a, item, comparator, start, midpointIndex);
}
}
})();
@@ -4520,6 +4590,132 @@ module.exports = (() => {
})();
},{"./array":30,"./is":32}],34:[function(require,module,exports){
+const assert = require('./assert'),
+ is = require('./is');
+
+module.exports = (() => {
+ 'use strict';
+
+ const regex = {};
+ regex.camel = {};
+ regex.camel.violations = /\b[A-Z]/g;
+ /**
+ * Utility functions for strings.
+ *
+ * @public
+ * @module lang/string
+ */
+
+ return {
+ /**
+ * Adjusts a string, replacing the first character of each word with an uppercase
+ * character and all subsequent characters in the word with lowercase characters.
+ *
+ * @public
+ * @static
+ * @param {String} s
+ * @returns {String}
+ */
+ startCase(s) {
+ return s.split(' ').reduce((phrase, word) => {
+ if (word.length !== 0) {
+ phrase.push(word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
+ }
+
+ return phrase;
+ }, []).join(' ');
+ },
+
+ /**
+ * Adjust a string to use camel case, where the first letter of each word is replaced
+ * with a lower case character.
+ *
+ * @public
+ * @static
+ * @param {String} s
+ * @returns {String}
+ */
+ camelCase(s) {
+ assert.argumentIsRequired(s, 's', String);
+ return s.replace(regex.camel.violations, m => m.toLocaleLowerCase());
+ },
+
+ /**
+ * If a string exceeds a desired length, it is truncated and a poor man's
+ * ellipsis (i.e. three periods) is appended. Otherwise, the original
+ * string is returned.
+ *
+ * @public
+ * @static
+ * @param {String} s
+ * @param {Number} length
+ * @returns {String}
+ */
+ truncate(s, length) {
+ if (is.string(s) && s.length > length) {
+ return s.substring(0, length) + ' ...';
+ } else {
+ return s;
+ }
+ },
+
+ /**
+ * Adds leading characters to a string, until the string length is a desired size.
+ *
+ * @public
+ * @static
+ * @param {String} s - The string to pad.
+ * @param {Number} length - The desired overall length of the string.
+ * @param {String} character - The character to use for padding.
+ * @returns {String}
+ */
+ padLeft(s, length, character) {
+ assert.argumentIsRequired(s, 's', String);
+ assert.argumentIsRequired(length, 'length', Number);
+ assert.argumentIsRequired(character, 'character', String);
+
+ if (character.length !== 1) {
+ throw new Error('The "character" argument must be one character in length.');
+ }
+
+ return character.repeat(length - s.length) + s;
+ },
+
+ /**
+ * Performs a simple token replacement on a string; where the tokens
+ * are braced numbers (e.g. {0}, {1}, {2}).
+ *
+ * @public
+ * @static
+ * @param {String} s - The string to format (e.g. 'my first name is {0} and my last name is {1}')
+ * @param {Array} data - The replacement data
+ * @returns {String}
+ */
+ format(s, ...data) {
+ assert.argumentIsRequired(s, 's', String);
+ return s.replace(/{(\d+)}/g, (match, i) => {
+ let replacement;
+
+ if (i < data.length) {
+ const item = data[i];
+
+ if (!is.undefined(item) && !is.null(item)) {
+ replacement = item.toString();
+ } else {
+ replacement = match;
+ }
+ } else {
+ replacement = match;
+ }
+
+ return replacement;
+ });
+ }
+
+ };
+})();
+
+},{"./assert":31,"./is":32}],35:[function(require,module,exports){
const moment = require('moment-timezone/builds/moment-timezone-with-data-2012-2022'),
assert = require('./assert');
@@ -4574,7 +4770,7 @@ module.exports = (() => {
};
})();
-},{"./assert":31,"moment-timezone/builds/moment-timezone-with-data-2012-2022":35}],35:[function(require,module,exports){
+},{"./assert":31,"moment-timezone/builds/moment-timezone-with-data-2012-2022":36}],36:[function(require,module,exports){
//! moment-timezone.js
//! version : 0.5.26
//! Copyright (c) JS Foundation and other contributors
@@ -5800,7 +5996,7 @@ module.exports = (() => {
return moment;
}));
-},{"moment":36}],36:[function(require,module,exports){
+},{"moment":37}],37:[function(require,module,exports){
//! moment.js
;(function (global, factory) {
@@ -10404,267 +10600,262 @@ module.exports = (() => {
})));
-},{}],37:[function(require,module,exports){
-function DOMParser(options){
- this.options = options ||{locator:{}};
-
-}
-DOMParser.prototype.parseFromString = function(source,mimeType){
- var options = this.options;
- var sax = new XMLReader();
- var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
- var errorHandler = options.errorHandler;
- var locator = options.locator;
- var defaultNSMap = options.xmlns||{};
- var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"}
- if(locator){
- domBuilder.setDocumentLocator(locator)
- }
-
- sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
- sax.domBuilder = options.domBuilder || domBuilder;
- if(/\/x?html?$/.test(mimeType)){
- entityMap.nbsp = '\xa0';
- entityMap.copy = '\xa9';
- defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
- }
- defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
- if(source){
- sax.parse(source,defaultNSMap,entityMap);
- }else{
- sax.errorHandler.error("invalid doc source");
- }
- return domBuilder.doc;
-}
-function buildErrorHandler(errorImpl,domBuilder,locator){
- if(!errorImpl){
- if(domBuilder instanceof DOMHandler){
- return domBuilder;
- }
- errorImpl = domBuilder ;
- }
- var errorHandler = {}
- var isCallback = errorImpl instanceof Function;
- locator = locator||{}
- function build(key){
- var fn = errorImpl[key];
- if(!fn && isCallback){
- fn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl;
- }
- errorHandler[key] = fn && function(msg){
- fn('[xmldom '+key+']\t'+msg+_locator(locator));
- }||function(){};
- }
- build('warning');
- build('error');
- build('fatalError');
- return errorHandler;
-}
-
-//console.log('#\n\n\n\n\n\n\n####')
-/**
- * +ContentHandler+ErrorHandler
- * +LexicalHandler+EntityResolver2
- * -DeclHandler-DTDHandler
- *
- * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
- * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
- * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
- */
-function DOMHandler() {
- this.cdata = false;
-}
-function position(locator,node){
- node.lineNumber = locator.lineNumber;
- node.columnNumber = locator.columnNumber;
-}
-/**
- * @see org.xml.sax.ContentHandler#startDocument
- * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
- */
-DOMHandler.prototype = {
- startDocument : function() {
- this.doc = new DOMImplementation().createDocument(null, null, null);
- if (this.locator) {
- this.doc.documentURI = this.locator.systemId;
- }
- },
- startElement:function(namespaceURI, localName, qName, attrs) {
- var doc = this.doc;
- var el = doc.createElementNS(namespaceURI, qName||localName);
- var len = attrs.length;
- appendElement(this, el);
- this.currentElement = el;
-
- this.locator && position(this.locator,el)
- for (var i = 0 ; i < len; i++) {
- var namespaceURI = attrs.getURI(i);
- var value = attrs.getValue(i);
- var qName = attrs.getQName(i);
- var attr = doc.createAttributeNS(namespaceURI, qName);
- this.locator &&position(attrs.getLocator(i),attr);
- attr.value = attr.nodeValue = value;
- el.setAttributeNode(attr)
- }
- },
- endElement:function(namespaceURI, localName, qName) {
- var current = this.currentElement
- var tagName = current.tagName;
- this.currentElement = current.parentNode;
- },
- startPrefixMapping:function(prefix, uri) {
- },
- endPrefixMapping:function(prefix) {
- },
- processingInstruction:function(target, data) {
- var ins = this.doc.createProcessingInstruction(target, data);
- this.locator && position(this.locator,ins)
- appendElement(this, ins);
- },
- ignorableWhitespace:function(ch, start, length) {
- },
- characters:function(chars, start, length) {
- chars = _toString.apply(this,arguments)
- //console.log(chars)
- if(chars){
- if (this.cdata) {
- var charNode = this.doc.createCDATASection(chars);
- } else {
- var charNode = this.doc.createTextNode(chars);
- }
- if(this.currentElement){
- this.currentElement.appendChild(charNode);
- }else if(/^\s*$/.test(chars)){
- this.doc.appendChild(charNode);
- //process xml
- }
- this.locator && position(this.locator,charNode)
- }
- },
- skippedEntity:function(name) {
- },
- endDocument:function() {
- this.doc.normalize();
- },
- setDocumentLocator:function (locator) {
- if(this.locator = locator){// && !('lineNumber' in locator)){
- locator.lineNumber = 0;
- }
- },
- //LexicalHandler
- comment:function(chars, start, length) {
- chars = _toString.apply(this,arguments)
- var comm = this.doc.createComment(chars);
- this.locator && position(this.locator,comm)
- appendElement(this, comm);
- },
-
- startCDATA:function() {
- //used in characters() methods
- this.cdata = true;
- },
- endCDATA:function() {
- this.cdata = false;
- },
-
- startDTD:function(name, publicId, systemId) {
- var impl = this.doc.implementation;
- if (impl && impl.createDocumentType) {
- var dt = impl.createDocumentType(name, publicId, systemId);
- this.locator && position(this.locator,dt)
- appendElement(this, dt);
- }
- },
- /**
- * @see org.xml.sax.ErrorHandler
- * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
- */
- warning:function(error) {
- console.warn('[xmldom warning]\t'+error,_locator(this.locator));
- },
- error:function(error) {
- console.error('[xmldom error]\t'+error,_locator(this.locator));
- },
- fatalError:function(error) {
- console.error('[xmldom fatalError]\t'+error,_locator(this.locator));
- throw error;
- }
-}
-function _locator(l){
- if(l){
- return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
- }
-}
-function _toString(chars,start,length){
- if(typeof chars == 'string'){
- return chars.substr(start,length)
- }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
- if(chars.length >= start+length || start){
- return new java.lang.String(chars,start,length)+'';
- }
- return chars;
- }
-}
-
-/*
- * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
- * used method of org.xml.sax.ext.LexicalHandler:
- * #comment(chars, start, length)
- * #startCDATA()
- * #endCDATA()
- * #startDTD(name, publicId, systemId)
- *
- *
- * IGNORED method of org.xml.sax.ext.LexicalHandler:
- * #endDTD()
- * #startEntity(name)
- * #endEntity(name)
- *
- *
- * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
- * IGNORED method of org.xml.sax.ext.DeclHandler
- * #attributeDecl(eName, aName, type, mode, value)
- * #elementDecl(name, model)
- * #externalEntityDecl(name, publicId, systemId)
- * #internalEntityDecl(name, value)
- * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
- * IGNORED method of org.xml.sax.EntityResolver2
- * #resolveEntity(String name,String publicId,String baseURI,String systemId)
- * #resolveEntity(publicId, systemId)
- * #getExternalSubset(name, baseURI)
- * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
- * IGNORED method of org.xml.sax.DTDHandler
- * #notationDecl(name, publicId, systemId) {};
- * #unparsedEntityDecl(name, publicId, systemId, notationName) {};
- */
-"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
- DOMHandler.prototype[key] = function(){return null}
-})
-
-/* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
-function appendElement (hander,node) {
- if (!hander.currentElement) {
- hander.doc.appendChild(node);
- } else {
- hander.currentElement.appendChild(node);
- }
-}//appendChild and setAttributeNS are preformance key
-
-//if(typeof require == 'function'){
- var XMLReader = require('./sax').XMLReader;
- var DOMImplementation = exports.DOMImplementation = require('./dom').DOMImplementation;
- exports.XMLSerializer = require('./dom').XMLSerializer ;
- exports.DOMParser = DOMParser;
-//}
-
-},{"./dom":38,"./sax":39}],38:[function(require,module,exports){
+},{}],38:[function(require,module,exports){
+function DOMParser(options){
+ this.options = options ||{locator:{}};
+}
+
+DOMParser.prototype.parseFromString = function(source,mimeType){
+ var options = this.options;
+ var sax = new XMLReader();
+ var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
+ var errorHandler = options.errorHandler;
+ var locator = options.locator;
+ var defaultNSMap = options.xmlns||{};
+ var isHTML = /\/x?html?$/.test(mimeType);//mimeType.toLowerCase().indexOf('html') > -1;
+ var entityMap = isHTML?htmlEntity.entityMap:{'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"};
+ if(locator){
+ domBuilder.setDocumentLocator(locator)
+ }
+
+ sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
+ sax.domBuilder = options.domBuilder || domBuilder;
+ if(isHTML){
+ defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
+ }
+ defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
+ if(source && typeof source === 'string'){
+ sax.parse(source,defaultNSMap,entityMap);
+ }else{
+ sax.errorHandler.error("invalid doc source");
+ }
+ return domBuilder.doc;
+}
+function buildErrorHandler(errorImpl,domBuilder,locator){
+ if(!errorImpl){
+ if(domBuilder instanceof DOMHandler){
+ return domBuilder;
+ }
+ errorImpl = domBuilder ;
+ }
+ var errorHandler = {}
+ var isCallback = errorImpl instanceof Function;
+ locator = locator||{}
+ function build(key){
+ var fn = errorImpl[key];
+ if(!fn && isCallback){
+ fn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl;
+ }
+ errorHandler[key] = fn && function(msg){
+ fn('[xmldom '+key+']\t'+msg+_locator(locator));
+ }||function(){};
+ }
+ build('warning');
+ build('error');
+ build('fatalError');
+ return errorHandler;
+}
+
+//console.log('#\n\n\n\n\n\n\n####')
+/**
+ * +ContentHandler+ErrorHandler
+ * +LexicalHandler+EntityResolver2
+ * -DeclHandler-DTDHandler
+ *
+ * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
+ * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
+ * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
+ */
+function DOMHandler() {
+ this.cdata = false;
+}
+function position(locator,node){
+ node.lineNumber = locator.lineNumber;
+ node.columnNumber = locator.columnNumber;
+}
+/**
+ * @see org.xml.sax.ContentHandler#startDocument
+ * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
+ */
+DOMHandler.prototype = {
+ startDocument : function() {
+ this.doc = new DOMImplementation().createDocument(null, null, null);
+ if (this.locator) {
+ this.doc.documentURI = this.locator.systemId;
+ }
+ },
+ startElement:function(namespaceURI, localName, qName, attrs) {
+ var doc = this.doc;
+ var el = doc.createElementNS(namespaceURI, qName||localName);
+ var len = attrs.length;
+ appendElement(this, el);
+ this.currentElement = el;
+
+ this.locator && position(this.locator,el)
+ for (var i = 0 ; i < len; i++) {
+ var namespaceURI = attrs.getURI(i);
+ var value = attrs.getValue(i);
+ var qName = attrs.getQName(i);
+ var attr = doc.createAttributeNS(namespaceURI, qName);
+ this.locator &&position(attrs.getLocator(i),attr);
+ attr.value = attr.nodeValue = value;
+ el.setAttributeNode(attr)
+ }
+ },
+ endElement:function(namespaceURI, localName, qName) {
+ var current = this.currentElement
+ var tagName = current.tagName;
+ this.currentElement = current.parentNode;
+ },
+ startPrefixMapping:function(prefix, uri) {
+ },
+ endPrefixMapping:function(prefix) {
+ },
+ processingInstruction:function(target, data) {
+ var ins = this.doc.createProcessingInstruction(target, data);
+ this.locator && position(this.locator,ins)
+ appendElement(this, ins);
+ },
+ ignorableWhitespace:function(ch, start, length) {
+ },
+ characters:function(chars, start, length) {
+ chars = _toString.apply(this,arguments)
+ //console.log(chars)
+ if(chars){
+ if (this.cdata) {
+ var charNode = this.doc.createCDATASection(chars);
+ } else {
+ var charNode = this.doc.createTextNode(chars);
+ }
+ if(this.currentElement){
+ this.currentElement.appendChild(charNode);
+ }else if(/^\s*$/.test(chars)){
+ this.doc.appendChild(charNode);
+ //process xml
+ }
+ this.locator && position(this.locator,charNode)
+ }
+ },
+ skippedEntity:function(name) {
+ },
+ endDocument:function() {
+ this.doc.normalize();
+ },
+ setDocumentLocator:function (locator) {
+ if(this.locator = locator){// && !('lineNumber' in locator)){
+ locator.lineNumber = 0;
+ }
+ },
+ //LexicalHandler
+ comment:function(chars, start, length) {
+ chars = _toString.apply(this,arguments)
+ var comm = this.doc.createComment(chars);
+ this.locator && position(this.locator,comm)
+ appendElement(this, comm);
+ },
+
+ startCDATA:function() {
+ //used in characters() methods
+ this.cdata = true;
+ },
+ endCDATA:function() {
+ this.cdata = false;
+ },
+
+ startDTD:function(name, publicId, systemId) {
+ var impl = this.doc.implementation;
+ if (impl && impl.createDocumentType) {
+ var dt = impl.createDocumentType(name, publicId, systemId);
+ this.locator && position(this.locator,dt)
+ appendElement(this, dt);
+ }
+ },
+ /**
+ * @see org.xml.sax.ErrorHandler
+ * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
+ */
+ warning:function(error) {
+ console.warn('[xmldom warning]\t'+error,_locator(this.locator));
+ },
+ error:function(error) {
+ console.error('[xmldom error]\t'+error,_locator(this.locator));
+ },
+ fatalError:function(error) {
+ throw new ParseError(error, this.locator);
+ }
+}
+function _locator(l){
+ if(l){
+ return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
+ }
+}
+function _toString(chars,start,length){
+ if(typeof chars == 'string'){
+ return chars.substr(start,length)
+ }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
+ if(chars.length >= start+length || start){
+ return new java.lang.String(chars,start,length)+'';
+ }
+ return chars;
+ }
+}
+
/*
- * DOM Level 2
- * Object DOMException
- * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
- * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
+ * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
+ * used method of org.xml.sax.ext.LexicalHandler:
+ * #comment(chars, start, length)
+ * #startCDATA()
+ * #endCDATA()
+ * #startDTD(name, publicId, systemId)
+ *
+ *
+ * IGNORED method of org.xml.sax.ext.LexicalHandler:
+ * #endDTD()
+ * #startEntity(name)
+ * #endEntity(name)
+ *
+ *
+ * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
+ * IGNORED method of org.xml.sax.ext.DeclHandler
+ * #attributeDecl(eName, aName, type, mode, value)
+ * #elementDecl(name, model)
+ * #externalEntityDecl(name, publicId, systemId)
+ * #internalEntityDecl(name, value)
+ * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
+ * IGNORED method of org.xml.sax.EntityResolver2
+ * #resolveEntity(String name,String publicId,String baseURI,String systemId)
+ * #resolveEntity(publicId, systemId)
+ * #getExternalSubset(name, baseURI)
+ * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
+ * IGNORED method of org.xml.sax.DTDHandler
+ * #notationDecl(name, publicId, systemId) {};
+ * #unparsedEntityDecl(name, publicId, systemId, notationName) {};
*/
+"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
+ DOMHandler.prototype[key] = function(){return null}
+})
+
+/* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
+function appendElement (hander,node) {
+ if (!hander.currentElement) {
+ hander.doc.appendChild(node);
+ } else {
+ hander.currentElement.appendChild(node);
+ }
+}//appendChild and setAttributeNS are preformance key
+
+//if(typeof require == 'function'){
+var htmlEntity = require('./entities');
+var sax = require('./sax');
+var XMLReader = sax.XMLReader;
+var ParseError = sax.ParseError;
+var DOMImplementation = exports.DOMImplementation = require('./dom').DOMImplementation;
+exports.XMLSerializer = require('./dom').XMLSerializer ;
+exports.DOMParser = DOMParser;
+exports.__DOMHandler = DOMHandler;
+//}
+},{"./dom":39,"./entities":40,"./sax":41}],39:[function(require,module,exports){
function copy(src,dest){
for(var p in src){
dest[p] = src[p];
@@ -10676,10 +10867,6 @@ function copy(src,dest){
*/
function _extends(Class,Super){
var pt = Class.prototype;
- if(Object.create){
- var ppt = Object.create(Super.prototype)
- pt.__proto__ = ppt;
- }
if(!(pt instanceof Super)){
function t(){};
t.prototype = Super.prototype;
@@ -10730,7 +10917,12 @@ var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = ((Exce
var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14]="Invalid namespace"),14);
var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15]="Invalid access"),15);
-
+/**
+ * DOM Level 2
+ * Object DOMException
+ * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
+ * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
+ */
function DOMException(code, message) {
if(message instanceof Error){
var error = message;
@@ -11272,6 +11464,21 @@ Document.prototype = {
return rtv;
},
+ getElementsByClassName: function(className) {
+ var pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
+ return new LiveNodeList(this, function(base) {
+ var ls = [];
+ _visitNode(base.documentElement, function(node) {
+ if(node !== base && node.nodeType == ELEMENT_NODE) {
+ if(pattern.test(node.getAttribute('class'))) {
+ ls.push(node);
+ }
+ }
+ });
+ return ls;
+ });
+ },
+
//document factory method:
createElement : function(tagName){
var node = new Element();
@@ -11576,7 +11783,7 @@ XMLSerializer.prototype.serializeToString = function(node,isHtml,nodeFilter){
Node.prototype.toString = nodeSerializeToString;
function nodeSerializeToString(isHtml,nodeFilter){
var buf = [];
- var refNode = this.nodeType == 9?this.documentElement:this;
+ var refNode = this.nodeType == 9 && this.documentElement || this;
var prefix = refNode.prefix;
var uri = refNode.namespaceURI;
@@ -11675,9 +11882,13 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
if (needNamespaceDefine(node,isHTML, visibleNamespaces)) {
var prefix = node.prefix||'';
var uri = node.namespaceURI;
- var ns = prefix ? ' xmlns:' + prefix : " xmlns";
- buf.push(ns, '="' , uri , '"');
- visibleNamespaces.push({ prefix: prefix, namespace:uri });
+ if (uri) {
+ // Avoid empty namespace value like xmlns:ds=""
+ // Empty namespace URL will we produce an invalid XML document
+ var ns = prefix ? ' xmlns:' + prefix : " xmlns";
+ buf.push(ns, '="' , uri , '"');
+ visibleNamespaces.push({ prefix: prefix, namespace:uri });
+ }
}
if(child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)){
@@ -11715,9 +11926,33 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
}
return;
case ATTRIBUTE_NODE:
- return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
+ /**
+ * Well-formedness constraint: No < in Attribute Values
+ * The replacement text of any entity referred to directly or indirectly in an attribute value must not contain a <.
+ * @see https://www.w3.org/TR/xml/#CleanAttrVals
+ * @see https://www.w3.org/TR/xml/#NT-AttValue
+ */
+ return buf.push(' ', node.name, '="', node.value.replace(/[<&"]/g,_xmlEncoder), '"');
case TEXT_NODE:
- return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
+ /**
+ * The ampersand character (&) and the left angle bracket (<) must not appear in their literal form,
+ * except when used as markup delimiters, or within a comment, a processing instruction, or a CDATA section.
+ * If they are needed elsewhere, they must be escaped using either numeric character references or the strings
+ * `&` and `<` respectively.
+ * The right angle bracket (>) may be represented using the string " > ", and must, for compatibility,
+ * be escaped using either `>` or a character reference when it appears in the string `]]>` in content,
+ * when that string is not marking the end of a CDATA section.
+ *
+ * In the content of elements, character data is any string of characters
+ * which does not contain the start-delimiter of any markup
+ * and does not include the CDATA-section-close delimiter, `]]>`.
+ *
+ * @see https://www.w3.org/TR/xml/#NT-CharData
+ */
+ return buf.push(node.data
+ .replace(/[<&]/g,_xmlEncoder)
+ .replace(/]]>/g, ']]>')
+ );
case CDATA_SECTION_NODE:
return buf.push( '');
case COMMENT_NODE:
@@ -11727,13 +11962,13 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
var sysid = node.systemId;
buf.push('');
+ buf.push('>');
}else if(sysid && sysid!='.'){
- buf.push(' SYSTEM "',sysid,'">');
+ buf.push(' SYSTEM ', sysid, '>');
}else{
var sub = node.internalSubset;
if(sub){
@@ -11899,646 +12134,902 @@ try{
}
//if(typeof require == 'function'){
+ exports.Node = Node;
+ exports.DOMException = DOMException;
exports.DOMImplementation = DOMImplementation;
exports.XMLSerializer = XMLSerializer;
//}
-},{}],39:[function(require,module,exports){
-//[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
-//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
-//[5] Name ::= NameStartChar (NameChar)*
-var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF
-var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
-var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
-//var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
-//var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
-
-//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
-//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
-var S_TAG = 0;//tag name offerring
-var S_ATTR = 1;//attr name offerring
-var S_ATTR_SPACE=2;//attr name end and space offer
-var S_EQ = 3;//=space?
-var S_ATTR_NOQUOT_VALUE = 4;//attr value(no quot value only)
-var S_ATTR_END = 5;//attr value end and no space(quot end)
-var S_TAG_SPACE = 6;//(attr value end || tag end ) && (space offer)
-var S_TAG_CLOSE = 7;//closed el
-
-function XMLReader(){
-
-}
-
-XMLReader.prototype = {
- parse:function(source,defaultNSMap,entityMap){
- var domBuilder = this.domBuilder;
- domBuilder.startDocument();
- _copy(defaultNSMap ,defaultNSMap = {})
- parse(source,defaultNSMap,entityMap,
- domBuilder,this.errorHandler);
- domBuilder.endDocument();
- }
-}
-function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
- function fixedFromCharCode(code) {
- // String.prototype.fromCharCode does not supports
- // > 2 bytes unicode chars directly
- if (code > 0xffff) {
- code -= 0x10000;
- var surrogate1 = 0xd800 + (code >> 10)
- , surrogate2 = 0xdc00 + (code & 0x3ff);
-
- return String.fromCharCode(surrogate1, surrogate2);
- } else {
- return String.fromCharCode(code);
- }
- }
- function entityReplacer(a){
- var k = a.slice(1,-1);
- if(k in entityMap){
- return entityMap[k];
- }else if(k.charAt(0) === '#'){
- return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
- }else{
- errorHandler.error('entity not found:'+a);
- return a;
- }
- }
- function appendText(end){//has some bugs
- if(end>start){
- var xt = source.substring(start,end).replace(/?\w+;/g,entityReplacer);
- locator&&position(start);
- domBuilder.characters(xt,0,end-start);
- start = end
- }
- }
- function position(p,m){
- while(p>=lineEnd && (m = linePattern.exec(source))){
- lineStart = m.index;
- lineEnd = lineStart + m[0].length;
- locator.lineNumber++;
- //console.log('line++:',locator,startPos,endPos)
- }
- locator.columnNumber = p-lineStart+1;
- }
- var lineStart = 0;
- var lineEnd = 0;
- var linePattern = /.*(?:\r\n?|\n)|.*$/g
- var locator = domBuilder.locator;
-
- var parseStack = [{currentNSMap:defaultNSMapCopy}]
- var closeMap = {};
- var start = 0;
- while(true){
- try{
- var tagStart = source.indexOf('<',start);
- if(tagStart<0){
- if(!source.substr(start).match(/^\s*$/)){
- var doc = domBuilder.doc;
- var text = doc.createTextNode(source.substr(start));
- doc.appendChild(text);
- domBuilder.currentElement = text;
- }
- return;
- }
- if(tagStart>start){
- appendText(tagStart);
- }
- switch(source.charAt(tagStart+1)){
- case '/':
- var end = source.indexOf('>',tagStart+3);
- var tagName = source.substring(tagStart+2,end);
- var config = parseStack.pop();
- if(end<0){
-
- tagName = source.substring(tagStart+2).replace(/[\s<].*/,'');
- //console.error('#@@@@@@'+tagName)
- errorHandler.error("end tag name: "+tagName+' is not complete:'+config.tagName);
- end = tagStart+1+tagName.length;
- }else if(tagName.match(/\s)){
- tagName = tagName.replace(/[\s<].*/,'');
- errorHandler.error("end tag name: "+tagName+' maybe not complete');
- end = tagStart+1+tagName.length;
- }
- //console.error(parseStack.length,parseStack)
- //console.error(config);
- var localNSMap = config.localNSMap;
- var endMatch = config.tagName == tagName;
- var endIgnoreCaseMach = endMatch || config.tagName&&config.tagName.toLowerCase() == tagName.toLowerCase()
- if(endIgnoreCaseMach){
- domBuilder.endElement(config.uri,config.localName,tagName);
- if(localNSMap){
- for(var prefix in localNSMap){
- domBuilder.endPrefixMapping(prefix) ;
- }
- }
- if(!endMatch){
- errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
- }
- }else{
- parseStack.push(config)
- }
-
- end++;
- break;
- // end elment
- case '?':// ...?>
- locator&&position(tagStart);
- end = parseInstruction(source,tagStart,domBuilder);
- break;
- case '!':// start){
- start = end;
- }else{
- //TODO: 这里有可能sax回退,有位置错误风险
- appendText(Math.max(tagStart,start)+1);
- }
- }
-}
-function copyLocator(f,t){
- t.lineNumber = f.lineNumber;
- t.columnNumber = f.columnNumber;
- return t;
-}
-
-/**
- * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
- * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
- */
-function parseElementStartPart(source,start,el,currentNSMap,entityReplacer,errorHandler){
- var attrName;
- var value;
- var p = ++start;
- var s = S_TAG;//status
- while(true){
- var c = source.charAt(p);
- switch(c){
- case '=':
- if(s === S_ATTR){//attrName
- attrName = source.slice(start,p);
- s = S_EQ;
- }else if(s === S_ATTR_SPACE){
- s = S_EQ;
- }else{
- //fatalError: equal must after attrName or space after attrName
- throw new Error('attribute equal must after attrName');
- }
- break;
- case '\'':
- case '"':
- if(s === S_EQ || s === S_ATTR //|| s == S_ATTR_SPACE
- ){//equal
- if(s === S_ATTR){
- errorHandler.warning('attribute value must after "="')
- attrName = source.slice(start,p)
- }
- start = p+1;
- p = source.indexOf(c,start)
- if(p>0){
- value = source.slice(start,p).replace(/?\w+;/g,entityReplacer);
- el.add(attrName,value,start-1);
- s = S_ATTR_END;
- }else{
- //fatalError: no end quot match
- throw new Error('attribute value no end \''+c+'\' match');
- }
- }else if(s == S_ATTR_NOQUOT_VALUE){
- value = source.slice(start,p).replace(/?\w+;/g,entityReplacer);
- //console.log(attrName,value,start,p)
- el.add(attrName,value,start);
- //console.dir(el)
- errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
- start = p+1;
- s = S_ATTR_END
- }else{
- //fatalError: no equal before
- throw new Error('attribute value must after "="');
- }
- break;
- case '/':
- switch(s){
- case S_TAG:
- el.setTagName(source.slice(start,p));
- case S_ATTR_END:
- case S_TAG_SPACE:
- case S_TAG_CLOSE:
- s =S_TAG_CLOSE;
- el.closed = true;
- case S_ATTR_NOQUOT_VALUE:
- case S_ATTR:
- case S_ATTR_SPACE:
- break;
- //case S_EQ:
- default:
- throw new Error("attribute invalid close char('/')")
- }
- break;
- case ''://end document
- //throw new Error('unexpected end of input')
- errorHandler.error('unexpected end of input');
- if(s == S_TAG){
- el.setTagName(source.slice(start,p));
- }
- return p;
- case '>':
- switch(s){
- case S_TAG:
- el.setTagName(source.slice(start,p));
- case S_ATTR_END:
- case S_TAG_SPACE:
- case S_TAG_CLOSE:
- break;//normal
- case S_ATTR_NOQUOT_VALUE://Compatible state
- case S_ATTR:
- value = source.slice(start,p);
- if(value.slice(-1) === '/'){
- el.closed = true;
- value = value.slice(0,-1)
- }
- case S_ATTR_SPACE:
- if(s === S_ATTR_SPACE){
- value = attrName;
- }
- if(s == S_ATTR_NOQUOT_VALUE){
- errorHandler.warning('attribute "'+value+'" missed quot(")!!');
- el.add(attrName,value.replace(/?\w+;/g,entityReplacer),start)
- }else{
- if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !value.match(/^(?:disabled|checked|selected)$/i)){
- errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
- }
- el.add(value,value,start)
- }
- break;
- case S_EQ:
- throw new Error('attribute value missed!!');
- }
-// console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
- return p;
- /*xml space '\x20' | #x9 | #xD | #xA; */
- case '\u0080':
- c = ' ';
- default:
- if(c<= ' '){//space
- switch(s){
- case S_TAG:
- el.setTagName(source.slice(start,p));//tagName
- s = S_TAG_SPACE;
- break;
- case S_ATTR:
- attrName = source.slice(start,p)
- s = S_ATTR_SPACE;
- break;
- case S_ATTR_NOQUOT_VALUE:
- var value = source.slice(start,p).replace(/?\w+;/g,entityReplacer);
- errorHandler.warning('attribute "'+value+'" missed quot(")!!');
- el.add(attrName,value,start)
- case S_ATTR_END:
- s = S_TAG_SPACE;
- break;
- //case S_TAG_SPACE:
- //case S_EQ:
- //case S_ATTR_SPACE:
- // void();break;
- //case S_TAG_CLOSE:
- //ignore warning
- }
- }else{//not space
-//S_TAG, S_ATTR, S_EQ, S_ATTR_NOQUOT_VALUE
-//S_ATTR_SPACE, S_ATTR_END, S_TAG_SPACE, S_TAG_CLOSE
- switch(s){
- //case S_TAG:void();break;
- //case S_ATTR:void();break;
- //case S_ATTR_NOQUOT_VALUE:void();break;
- case S_ATTR_SPACE:
- var tagName = el.tagName;
- if(currentNSMap[''] !== 'http://www.w3.org/1999/xhtml' || !attrName.match(/^(?:disabled|checked|selected)$/i)){
- errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead2!!')
- }
- el.add(attrName,attrName,start);
- start = p;
- s = S_ATTR;
- break;
- case S_ATTR_END:
- errorHandler.warning('attribute space is required"'+attrName+'"!!')
- case S_TAG_SPACE:
- s = S_ATTR;
- start = p;
- break;
- case S_EQ:
- s = S_ATTR_NOQUOT_VALUE;
- start = p;
- break;
- case S_TAG_CLOSE:
- throw new Error("elements closed character '/' and '>' must be connected to");
- }
- }
- }//end outer switch
- //console.log('p++',p)
- p++;
- }
-}
-/**
- * @return true if has new namespace define
- */
-function appendElement(el,domBuilder,currentNSMap){
- var tagName = el.tagName;
- var localNSMap = null;
- //var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
- var i = el.length;
- while(i--){
- var a = el[i];
- var qName = a.qName;
- var value = a.value;
- var nsp = qName.indexOf(':');
- if(nsp>0){
- var prefix = a.prefix = qName.slice(0,nsp);
- var localName = qName.slice(nsp+1);
- var nsPrefix = prefix === 'xmlns' && localName
- }else{
- localName = qName;
- prefix = null
- nsPrefix = qName === 'xmlns' && ''
- }
- //can not set prefix,because prefix !== ''
- a.localName = localName ;
- //prefix == null for no ns prefix attribute
- if(nsPrefix !== false){//hack!!
- if(localNSMap == null){
- localNSMap = {}
- //console.log(currentNSMap,0)
- _copy(currentNSMap,currentNSMap={})
- //console.log(currentNSMap,1)
- }
- currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
- a.uri = 'http://www.w3.org/2000/xmlns/'
- domBuilder.startPrefixMapping(nsPrefix, value)
- }
- }
- var i = el.length;
- while(i--){
- a = el[i];
- var prefix = a.prefix;
- if(prefix){//no prefix attribute has no namespace
- if(prefix === 'xml'){
- a.uri = 'http://www.w3.org/XML/1998/namespace';
- }if(prefix !== 'xmlns'){
- a.uri = currentNSMap[prefix || '']
-
- //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
- }
- }
- }
- var nsp = tagName.indexOf(':');
- if(nsp>0){
- prefix = el.prefix = tagName.slice(0,nsp);
- localName = el.localName = tagName.slice(nsp+1);
- }else{
- prefix = null;//important!!
- localName = el.localName = tagName;
- }
- //no prefix element has default namespace
- var ns = el.uri = currentNSMap[prefix || ''];
- domBuilder.startElement(ns,localName,tagName,el);
- //endPrefixMapping and startPrefixMapping have not any help for dom builder
- //localNSMap = null
- if(el.closed){
- domBuilder.endElement(ns,localName,tagName);
- if(localNSMap){
- for(prefix in localNSMap){
- domBuilder.endPrefixMapping(prefix)
- }
- }
- }else{
- el.currentNSMap = currentNSMap;
- el.localNSMap = localNSMap;
- //parseStack.push(el);
- return true;
- }
-}
-function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
- if(/^(?:script|textarea)$/i.test(tagName)){
- var elEndStart = source.indexOf(''+tagName+'>',elStartEnd);
- var text = source.substring(elStartEnd+1,elEndStart);
- if(/[&<]/.test(text)){
- if(/^script$/i.test(tagName)){
- //if(!/\]\]>/.test(text)){
- //lexHandler.startCDATA();
- domBuilder.characters(text,0,text.length);
- //lexHandler.endCDATA();
- return elEndStart;
- //}
- }//}else{//text area
- text = text.replace(/?\w+;/g,entityReplacer);
- domBuilder.characters(text,0,text.length);
- return elEndStart;
- //}
-
- }
- }
- return elStartEnd+1;
-}
-function fixSelfClosed(source,elStartEnd,tagName,closeMap){
- //if(tagName in closeMap){
- var pos = closeMap[tagName];
- if(pos == null){
- //console.log(tagName)
- pos = source.lastIndexOf(''+tagName+'>')
- if(pos',start+4);
- //append comment source.substring(4,end)//',start+4);
+ //append comment source.substring(4,end)//