Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Tree class to Typescript #67

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules/
coverage/
debug.log
dist
yarn-error.log
.DS_Store
.eslintcache
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
{ "language": "html", "autoFix": true }
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
}
}
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@
"demo/*.json",
"cosmoz-*.js",
"test/data/",
"examples"
"examples",
"dist/*"
],
"scripts": {
"lint": "eslint --cache --ext .js,.html .",
"lint": "tsc && eslint --cache --ext .js,.html .",
"build": "tsc -p tsconfig.build.json",
"start": "wds",
"test": "wtr --coverage",
"test:watch": "wtr --watch",
Expand All @@ -47,6 +49,12 @@
"publishConfig": {
"access": "public"
},
"exports": {
"./cosmoz-tree": "./dist/cosmoz-tree.js",
"./cosmoz-tree.js": "./dist/cosmoz-tree.js",
"./cosmoz-default-tree": "./dist/cosmoz-default-tree.js",
"./cosmoz-default-tree.js": "./dist/cosmoz-default-tree.js"
megheaiulian marked this conversation as resolved.
Show resolved Hide resolved
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
Expand Down
File renamed without changes.
116 changes: 87 additions & 29 deletions cosmoz-tree.js → src/cosmoz-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,27 @@

@demo demo/index.html
*/

export type TreeOptions = {
megheaiulian marked this conversation as resolved.
Show resolved Hide resolved
childProperty?: string;
searchProperty?: string;
pathLocatorSeparator?: string;
pathStringSeparator?: string;
};

export class Tree {
_treeData: object;

_roots: object;

childProperty: string;

searchProperty: string;

pathLocatorSeparator: string;

pathStringSeparator: string;

/**
* @param {Object} treeData (The tree object.)
* @param {Object} options (Tree options.)
Expand All @@ -12,7 +32,7 @@
* @param {String} options.pathStringSeparator ["/"] (The string the path should get separated with.)
* @param {String} options.pathLocatorSeparator ["."] (The string which separates the path segments of a path locator.)
*/
constructor(treeData, options = {}) {
constructor(treeData: object, options: TreeOptions = {}) {
this._treeData = treeData;
this._roots = Object.values(treeData);

Expand All @@ -22,9 +42,9 @@
this.searchProperty = options.searchProperty || 'name';
}

static _sortPathNodes(a, b) {
static _sortPathNodes(a, b): number {

Check failure on line 45 in src/cosmoz-tree.ts

View workflow job for this annotation

GitHub Actions / build / build

Parameter 'a' implicitly has an 'any' type.

Check failure on line 45 in src/cosmoz-tree.ts

View workflow job for this annotation

GitHub Actions / build / build

Parameter 'b' implicitly has an 'any' type.
const undefCounter = (item) => item === undefined,

Check failure on line 46 in src/cosmoz-tree.ts

View workflow job for this annotation

GitHub Actions / build / build

Parameter 'item' implicitly has an 'any' type.
defCounter = (item) => item,

Check failure on line 47 in src/cosmoz-tree.ts

View workflow job for this annotation

GitHub Actions / build / build

Parameter 'item' implicitly has an 'any' type.
aUndefCount = a.filter(undefCounter).length,
bUndefCount = b.filter(undefCounter).length,
aDefCount = a.filter(defCounter).length,
Expand All @@ -33,12 +53,15 @@
if (aUndefCount < bUndefCount) {
return -1;
}

if (aUndefCount > bUndefCount || aDefCount < bDefCount) {
return 1;
}

if (aDefCount > bDefCount) {
return -1;
}

return 0;
}

Expand All @@ -50,10 +73,10 @@
* @param {Array} nodes [this._roots] (The objects the search should be based on.)
*/
getNodeByProperty(
propertyValue,
propertyName = this.searchProperty,
nodes = this._roots,
) {
propertyValue?: string,
propertyName: string = this.searchProperty,
nodes: object = this._roots,
): object | undefined {
if (propertyValue === undefined) {
return;
}
Expand All @@ -69,12 +92,18 @@
* @param {Boolean} exact [true] (If the search should be executed exact or flaw. true wouldn't match "Pet")
* @param {String} propertyName [this.searchProperty] (The name of the property the match should be based on. e.g. "name")
*/
searchNodes(propertyValue, nodes, exact, propertyName = this.searchProperty) {
searchNodes(
propertyValue: string,
nodes,

Check failure on line 97 in src/cosmoz-tree.ts

View workflow job for this annotation

GitHub Actions / build / build

Parameter 'nodes' implicitly has an 'any' type.
exact: boolean | undefined,
propertyName: string = this.searchProperty,
): object[] {
const options = {
propertyName,
exact: exact !== undefined ? exact : true,
firstHitOnly: false,
};

return this._searchNodes(propertyValue, options, nodes);
}

Expand All @@ -85,12 +114,17 @@
* @param {String} propertyName [this.searchProperty] (The name of the property the match should be based on. e.g. "name")
* @param {Object} nodes [this._treeData] (The nodes the search should be based on.)
*/
findNode(propertyValue, propertyName = this.searchProperty, nodes) {
findNode(
propertyValue: string,
propertyName: string = this.searchProperty,
nodes,

Check failure on line 120 in src/cosmoz-tree.ts

View workflow job for this annotation

GitHub Actions / build / build

Parameter 'nodes' implicitly has an 'any' type.
) {
const options = {
propertyName,
exact: true,
firstHitOnly: true,
};

return this._searchNodes(propertyValue, options, nodes).shift();
}

Expand All @@ -104,11 +138,19 @@
* @param {Boolean} options.firstHitOnly [false] (If the search should only return the first found node.)
* @param {Object} nodes [this._roots] (The nodes the search should be based on.)
*/
_searchNodes(propertyValue, options, nodes = this._roots) {
_searchNodes(
propertyValue: string,
options: {
propertyName: string;
exact: boolean;
firstHitOnly: boolean;
},
nodes = this._roots,
) {
const results = [];

for (const node of nodes) {

Check failure on line 152 in src/cosmoz-tree.ts

View workflow job for this annotation

GitHub Actions / build / build

Type 'object' must have a '[Symbol.iterator]()' method that returns an iterator.
const res = this.search(node, propertyValue, options);

Check failure on line 153 in src/cosmoz-tree.ts

View workflow job for this annotation

GitHub Actions / build / build

Argument of type '{ propertyName: string; exact: boolean; firstHitOnly: boolean; }' is not assignable to parameter of type '{ propertyName: string; exact: string; }'.
if (options.firstHitOnly && res.length > 0) {
return res;
}
Expand All @@ -126,9 +168,9 @@
* @param {String} pathLocatorSeparator [this.pathLocatorSeparator] (The string which separates the path. e.g ".")
*/
getNodeByPathLocator(
pathLocator,
pathLocator?: string,
nodeObj = this._treeData,
pathLocatorSeparator = this.pathLocatorSeparator,
pathLocatorSeparator: string = this.pathLocatorSeparator,
) {
if (!pathLocator) {
return this._roots;
Expand All @@ -154,9 +196,9 @@
* @param {String} pathLocatorSeparator [this.pathLocatorSeparator] (The string which separates the path.)
*/
getPathNodes(
pathLocator,
pathLocator?: string,
nodeObj = this._treeData,
pathLocatorSeparator = this.pathLocatorSeparator,
pathLocatorSeparator: string = this.pathLocatorSeparator,
) {
if (!pathLocator) {
return nodeObj;
Expand All @@ -175,9 +217,9 @@
}

_getPathNodes(
pathLocator,
pathLocator: string,
nodeObj = this._treeData,
pathLocatorSeparator = this.pathLocatorSeparator,
pathLocatorSeparator: string = this.pathLocatorSeparator,
) {
const path = pathLocator.split(pathLocatorSeparator),
nodes = this._pathToNodes(path, nodeObj, pathLocatorSeparator);
Expand Down Expand Up @@ -216,10 +258,10 @@
* @param {String} pathLocatorSeparator [this.pathLocatorSeparator] (The string which separates the path segments of pathLocator.)
*/
getPathString(
pathLocator,
pathProperty = this.searchProperty,
pathStringSeparator = this.pathStringSeparator,
pathLocatorSeparator = this.pathLocatorSeparator,
pathLocator: string,
pathProperty: string = this.searchProperty,
pathStringSeparator: string = this.pathStringSeparator,
pathLocatorSeparator: string = this.pathLocatorSeparator,
) {
const pathNodes = this.getPathNodes(
pathLocator,
Expand Down Expand Up @@ -247,11 +289,11 @@
* @param {String} pathLocatorSeparator [this.pathLocatorSeparator] (The string which separates the path. e.g ".")
*/
getPathStringByProperty(
propertyValue,
propertyName = this.searchProperty,
pathProperty = this.searchProperty,
pathStringSeparator = this.pathStringSeparator,
pathLocatorSeparator = this.pathLocatorSeparator,
propertyValue: string,
propertyName: string = this.searchProperty,
pathProperty: string = this.searchProperty,
pathStringSeparator: string = this.pathStringSeparator,
pathLocatorSeparator: string = this.pathLocatorSeparator,
) {
if (propertyValue === undefined) {
return;
Expand Down Expand Up @@ -279,7 +321,7 @@
* @param {Object} node The object to return children from
* @returns {Object|Array} The node's children
*/
getChildren(node) {
getChildren(node: object) {
if (!node || !node[this.childProperty]) {
return [];
}
Expand All @@ -291,7 +333,7 @@
* @param {Object} node The object to get children from
* @returns {Boolean} True if node has children
*/
hasChildren(node) {
hasChildren(node: object): boolean {
if (!node) {
return false;
}
Expand All @@ -312,7 +354,7 @@
* @param {String} propertyName The name of property
* @returns {*} The value of the property
*/
getProperty(node, propertyName) {
getProperty(node: object, propertyName: string) {
if (!node || !propertyName) {
return;
}
Expand All @@ -328,7 +370,14 @@
* @param {String} options.propertyName (The name of the property the match should be based on. e.g. "name")
* @param {Boolean} options.exact [false] (If the search should be executed exact or fuzzy. true wouldn't match "Pet")
*/
nodeConformsSearch(node, propertyValue, options) {
nodeConformsSearch(
node: object,
propertyValue: string,
options?: {
propertyName: string;
exact: boolean;
},
): boolean | undefined {
const property = options ? node[options.propertyName] : undefined;

if (!property) {
Expand All @@ -340,6 +389,7 @@
if (options.exact) {
return property === propertyValue;
}

return property.toLowerCase().indexOf(propertyValue.toLowerCase()) > -1;
}

Expand All @@ -353,7 +403,15 @@
* @param {Boolean} options.exact [false] (If false, the propertyValue is matched fuzzy)
* @param {Array} results (The array search results get added to.) Default: []
*/
search(node, propertyValue, options, results = []) {
search(
node,
propertyValue: string,
options: {
propertyName: string;
exact: string;
},
results = [],
) {
const nodeConforms = this.nodeConformsSearch(node, propertyValue, options),
children = this.getChildren(node);

Expand Down
9 changes: 9 additions & 0 deletions tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"declaration": true,
"noEmit": false
},
"include": ["src"]
}
11 changes: 11 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"noEmit": true,
"module": "esnext",
"moduleResolution": "bundler",
"strict": true,
"target": "esnext",
"allowJs": true
}
}
Loading