diff --git a/package-lock.json b/package-lock.json
index 2853e08..f532bbf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -36,8 +36,7 @@
"ts-node": "^10.9.1",
"tsup": "^7.2.0",
"typedoc": "^0.25.1",
- "typescript": "^5.2.2",
- "underscore": "^1.13.6"
+ "typescript": "^5.2.2"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -9034,12 +9033,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/underscore": {
- "version": "1.13.6",
- "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
- "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
- "dev": true
- },
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
diff --git a/package.json b/package.json
index 4995f60..759a730 100644
--- a/package.json
+++ b/package.json
@@ -84,8 +84,7 @@
"ts-node": "^10.9.1",
"tsup": "^7.2.0",
"typedoc": "^0.25.1",
- "typescript": "^5.2.2",
- "underscore": "^1.13.6"
+ "typescript": "^5.2.2"
},
"keywords": [
"data",
diff --git a/test/performance/data-structures/queue/deque.test.ts b/test/performance/data-structures/queue/deque.test.ts
index 0939ff3..bf76aec 100644
--- a/test/performance/data-structures/queue/deque.test.ts
+++ b/test/performance/data-structures/queue/deque.test.ts
@@ -1,4 +1,4 @@
-import {Deque} from "../../../../src";
+import {Deque} from '../../../../src';
import * as Benchmark from 'benchmark';
export const suite = new Benchmark.Suite();
@@ -16,4 +16,4 @@ suite
deque.push(i);
deque.shift();
}
- })
\ No newline at end of file
+ });
diff --git a/test/performance/data-structures/queue/queue.test.ts b/test/performance/data-structures/queue/queue.test.ts
index 1546ad2..24d21c0 100644
--- a/test/performance/data-structures/queue/queue.test.ts
+++ b/test/performance/data-structures/queue/queue.test.ts
@@ -1,4 +1,4 @@
-import {Queue} from "../../../../src";
+import {Queue} from '../../../../src';
import * as Benchmark from 'benchmark';
@@ -17,4 +17,4 @@ suite
queue.push(i);
queue.shift();
}
- })
\ No newline at end of file
+ });
diff --git a/test/performance/index.ts b/test/performance/index.ts
index bf808d0..29f07b5 100644
--- a/test/performance/index.ts
+++ b/test/performance/index.ts
@@ -2,15 +2,17 @@ import * as Benchmark from 'benchmark';
import * as path from 'path';
import * as fs from 'fs';
import * as fastGlob from 'fast-glob';
-import {numberFix, render} from "./utils";
+import {numberFix, render} from './utils';
const reportDistPath = 'benchmark';
const testDir = path.join(__dirname, 'data-structures');
const testFiles = fastGlob.sync(path.join(testDir, '**', '*.test.ts'));
-const report: { [key: string]: any } = {};
+const report: {[key: string]: any} = {};
-let testFileCount = 0, suiteCount = 0, completedCount = 0;
+let testFileCount = 0,
+ suiteCount = 0,
+ completedCount = 0;
testFiles.forEach((file: string) => {
testFileCount++;
console.log(`testing file ${file}`);
@@ -24,28 +26,30 @@ testFiles.forEach((file: string) => {
console.log(event.target.toString());
});
- suite.on('complete', function (this: Benchmark.Suite) {
- completedCount++;
- console.log('Fastest is ' + this.filter('fastest').map('name'));
- report[testName] = this.map((test: Benchmark) => ({
- 'test name': test.name,
- 'time consumption (ms)': numberFix((test.times.period * 1000), 2),
- 'executions per second': numberFix(test.hz, 2),
- 'executed times': numberFix(test.count, 2),
- 'sample arithmetic mean (secs)': numberFix(test.stats.mean, 2),
- 'sample deviation': numberFix(test.stats.deviation, 2),
- }));
+ suite
+ .on('complete', function (this: Benchmark.Suite) {
+ completedCount++;
+ console.log('Fastest is ' + this.filter('fastest').map('name'));
+ report[testName] = this.map((test: Benchmark) => ({
+ 'test name': test.name,
+ 'time consumption (ms)': numberFix(test.times.period * 1000, 2),
+ 'executions per second': numberFix(test.hz, 2),
+ 'executed times': numberFix(test.count, 2),
+ 'sample arithmetic mean (secs)': numberFix(test.stats.mean, 2),
+ 'sample deviation': numberFix(test.stats.deviation, 2)
+ }));
+ // report[testName] = this;
+ console.log(
+ `test file count: ${testFileCount}. suite count: ${suiteCount}. completed suite count: ${completedCount}`
+ );
+ if (completedCount === suiteCount) {
+ if (!fs.existsSync(reportDistPath)) fs.mkdirSync(reportDistPath, {recursive: true});
- // report[testName] = this;
- console.log(`test file count: ${testFileCount}. suite count: ${suiteCount}. completed suite count: ${completedCount}`)
- if (completedCount === suiteCount) {
- if (!fs.existsSync(reportDistPath)) fs.mkdirSync(reportDistPath, {recursive: true});
-
- const filePath = path.join(reportDistPath, 'report.json');
- const htmlFilePath = path.join(reportDistPath, 'report.html');
- fs.writeFileSync(filePath, JSON.stringify(report, null, 2));
- let html = `
+ const filePath = path.join(reportDistPath, 'report.json');
+ const htmlFilePath = path.join(reportDistPath, 'report.html');
+ fs.writeFileSync(filePath, JSON.stringify(report, null, 2));
+ let html = `
@@ -76,32 +80,32 @@ testFiles.forEach((file: string) => {
- `
- for (const r in report) {
- if (report.hasOwnProperty(r)) {
- html += render(report[r], {
- '<>': 'table',
- 'html': [
- {
- '<>': 'tr',
- 'html': [
- {'<>': 'td', 'html': '${name}'},
- {'<>': 'td', 'html': '${periodMS}'},
- {'<>': 'td', 'html': '${mean}'}
- ]
- }
- ]
- });
+
`;
+ for (const r in report) {
+ if (report.hasOwnProperty(r)) {
+ html += render(report[r], {
+ '<>': 'table',
+ html: [
+ {
+ '<>': 'tr',
+ html: [
+ {'<>': 'td', html: '${name}'},
+ {'<>': 'td', html: '${periodMS}'},
+ {'<>': 'td', html: '${mean}'}
+ ]
+ }
+ ]
+ });
+ }
}
- }
- html += `
+ html += `
`;
- fs.writeFileSync(htmlFilePath, html);
- console.log('Performance test report file generated')
- }
- })
+ fs.writeFileSync(htmlFilePath, html);
+ console.log('Performance test report file generated');
+ }
+ })
.run({async: true});
}
-});
\ No newline at end of file
+});
diff --git a/test/performance/utils/index.ts b/test/performance/utils/index.ts
index a1884f0..feb65e4 100644
--- a/test/performance/utils/index.ts
+++ b/test/performance/utils/index.ts
@@ -1,2 +1,3 @@
export * from './json2html';
-export * from './number';
\ No newline at end of file
+export * from './number';
+export * from './is';
diff --git a/test/performance/utils/is.ts b/test/performance/utils/is.ts
new file mode 100644
index 0000000..2975299
--- /dev/null
+++ b/test/performance/utils/is.ts
@@ -0,0 +1,56 @@
+export const isNumber = (value: any) => {
+ return typeof value === 'number';
+};
+export const isString = (value: any) => {
+ return typeof value === 'string';
+};
+export const isBoolean = (value: any) => {
+ return typeof value === 'boolean';
+};
+export const isDate = (value: any) => {
+ return value instanceof Date;
+};
+export const isNull = (value: any) => {
+ return value === null;
+};
+export const isUndefined = (value: any) => {
+ return typeof value === 'undefined';
+};
+export const isFunction = (value: any) => {
+ return typeof value === 'function';
+};
+export const isObject = (value: any) => {
+ return typeof value === 'object';
+};
+export const isArray = (value: any) => {
+ return Array.isArray(value);
+};
+
+export const isEqual = (objA: any, objB: any): boolean => {
+ if (objA === objB) {
+ return true;
+ }
+
+ if (typeof objA !== 'object' || typeof objB !== 'object' || objA === null || objB === null) {
+ return false;
+ }
+
+ const keysA = Object.keys(objA);
+ const keysB = Object.keys(objB);
+
+ if (keysA.length !== keysB.length) {
+ return false;
+ }
+
+ for (const key of keysA) {
+ if (!keysB.includes(key)) {
+ return false;
+ }
+
+ if (!isEqual(objA[key], objB[key])) {
+ return false;
+ }
+ }
+
+ return true;
+};
diff --git a/test/performance/utils/json2html.ts b/test/performance/utils/json2html.ts
index e7d8bce..7648fe2 100644
--- a/test/performance/utils/json2html.ts
+++ b/test/performance/utils/json2html.ts
@@ -1,43 +1,38 @@
-import * as _ from "underscore";
+import * as _ from './is';
-function toggleJS(options?: { plainHtml?: boolean }): string {
+function toggleJS(options?: {plainHtml?: boolean}): string {
if (options?.plainHtml) {
- return "";
+ return '';
} else {
- return "onclick=\"j2h.toggleVisibility(this);return false\"";
+ return 'onclick="json-to-html.toggleVisibility(this);return false"';
}
}
-function makeLabelDiv(
- options: any,
- level: number,
- keyname: string | number,
- datatype?: string
-): string {
- if (typeof keyname === "number") {
- return `${keyname}
`;
- } else if (typeof keyname === "string") {
- if (datatype === "array") {
+function makeLabelDiv(options: any, level: number, keyname: string | number, datatype?: string): string {
+ if (typeof keyname === 'number') {
+ return `${keyname}
`;
+ } else if (typeof keyname === 'string') {
+ if (datatype === 'array') {
return `${keyname}
`;
- } else if (datatype === "object") {
+ )}>${keyname}`;
+ } else if (datatype === 'object') {
return `${keyname}:
`;
+ )}>${keyname}:`;
} else {
- return `${keyname}:
`;
+ return `${keyname}:
`;
}
} else {
- return "";
+ return '';
}
}
function getContentClass(keyname: string | number): string {
- if (typeof keyname === "string") {
- return "content";
+ if (typeof keyname === 'string') {
+ return 'content';
} else {
- return "";
+ return '';
}
}
@@ -63,7 +58,7 @@ function isLeafValue(val: any): boolean {
_.isDate(val) ||
_.isNull(val) ||
_.isUndefined(val) ||
- _.isNaN(val) ||
+ isNaN(val) ||
_.isFunction(val) ||
!isPlainObject(val)
);
@@ -89,12 +84,12 @@ function isTable(arr: any[]): boolean {
if (arr.length === 0 || !_.isObject(arr[0])) {
return false;
} else {
- let nonCompliant = _.detect(arr, (row) => !isLeafObject(row));
+ let nonCompliant = arr.find(row => !isLeafObject(row));
if (nonCompliant) {
return false;
} else {
- const cols = _.keys(arr[0]);
- nonCompliant = _.detect(arr, (row: object) => !_.isEqual(cols, _.keys(row)));
+ const cols = Object.keys(arr[0]);
+ nonCompliant = arr.find((row: object) => !_.isEqual(cols, Object.keys(row)));
if (nonCompliant) {
return false;
} else {
@@ -106,65 +101,61 @@ function isTable(arr: any[]): boolean {
function drawTable(arr: any[]): string {
function drawRow(headers: string[], rowObj: any): string {
- return (
- "" +
- headers.map((header) => rowObj[header]).join(" | ") +
- " | "
- );
+ return '' + headers.map(header => rowObj[header]).join(' | ') + ' | ';
}
- const cols = _.keys(arr[0]);
- const content = arr.map((rowObj) => drawRow(cols, rowObj));
- const headingHtml = "" + cols.join(" | ") + " |
";
- const contentHtml = "" + content.join("
") + "
";
- return "" + headingHtml + contentHtml + "
";
+ const cols = Object.keys(arr[0]);
+ const content = arr.map(rowObj => drawRow(cols, rowObj));
+ const headingHtml = '' + cols.join(' | ') + ' |
';
+ const contentHtml = '' + content.join('
') + '
';
+ return '' + headingHtml + contentHtml + '
';
}
-function _render(
- name: string,
- data: any,
- options: any,
- level: number,
- altrow: number
-): string {
+function _render(name: string, data: any, options: any, level: number, altrow: number): string {
const contentClass = getContentClass(name);
if (_.isArray(data)) {
- const title = makeLabelDiv(options, level, `${name} (${data.length})`, "array");
+ const title = makeLabelDiv(options, level, `${name} (${data.length})`, 'array');
let subs: string;
if (isTable(data)) {
subs = drawTable(data);
} else {
- subs = "" + data
- .map((val: any, idx: number) => _render(idx.toString(), val, options, level + 1, idx % 2))
- .join("
") + "
";
+ subs =
+ "" +
+ data
+ .map((val: any, idx: number) => _render(idx.toString(), val, options, level + 1, idx % 2))
+ .join("
") +
+ '
';
}
- return `
+ return `
`;
} else if (isLeafValue(data)) {
const title = makeLabelDiv(options, level, name);
if (_.isFunction(data)) {
- return `${title}
-function() can't _render-`;
+ return `${title}
-function() can't _render-`;
} else if (!isPlainObject(data)) {
if (_.isFunction(data.toString)) {
- return `${title}
${data.toString()}`;
+ return `${title}
${data.toString()}`;
} else {
- return `${title}
-instance object, can't render-`;
+ return `${title}
-instance object, can't render-`;
}
} else {
- return `${title}
${data}`;
+ return `${title}
${data}`;
}
} else {
- const title = makeLabelDiv(options, level, name, "object");
+ const title = makeLabelDiv(options, level, name, 'object');
let count = 0;
- const subs = "
" + Object.entries(data)
- .map(([key, val]) => _render(key, val, options, level + 1, count++ % 2))
- .join("
") + "
";
- const inner = `
+ const subs =
+ '
' +
+ Object.entries(data)
+ .map(([key, val]) => _render(key, val, options, level + 1, count++ % 2))
+ .join('
') +
+ '
';
+ const inner = `
`;
- return `${level === 0 ? '
' : ''}
+ return `${level === 0 ? "
" : ''}
${inner}
${level === 0 ? '
' : ''}`;
}
@@ -175,155 +166,155 @@ export function render(json: any, options: any): string {
return `${_render('', json, options, 0, 0)}`;
}
-const head = `
-`;
+// const head = `
+// `;
diff --git a/test/performance/utils/number.ts b/test/performance/utils/number.ts
index f1c3dd4..de6eef4 100644
--- a/test/performance/utils/number.ts
+++ b/test/performance/utils/number.ts
@@ -1,5 +1,4 @@
export function numberFix(number: number, decimalPlaces: number): string {
-
if (number > 10000 || number < 0.001) {
const [mantissa, exponent] = number.toExponential().split('e');
const formattedMantissa = Number(mantissa).toFixed(decimalPlaces);
@@ -7,4 +6,4 @@ export function numberFix(number: number, decimalPlaces: number): string {
} else {
return number.toFixed(decimalPlaces);
}
-}
\ No newline at end of file
+}