6 Commits

Author SHA1 Message Date
34d8c86856 1.1.4 2021-10-03 17:37:03 +02:00
d4cea26fb5 fix(core): update 2021-10-03 17:37:03 +02:00
de87e314c0 1.1.3 2021-10-03 17:24:17 +02:00
cddd1163ec fix(core): update 2021-10-03 17:24:17 +02:00
0fb86bc21b 1.1.2 2021-10-03 17:12:03 +02:00
cb5a24320c fix(core): update 2021-10-03 17:12:02 +02:00
16 changed files with 25705 additions and 532 deletions

16
.gitignore vendored
View File

@ -1,6 +1,20 @@
.nogit/
node_modules/
# artifacts
coverage/
public/
pages/
# installs
node_modules/
# caches
.yarn/
.cache/
.rpt2_cache
# builds
dist/
dist_*/
# custom

View File

@ -1,16 +1,16 @@
# gitzone standard
image: hosttoday/ht-docker-node:npmci
# gitzone ci_default
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache:
paths:
- .npmci_cache/
key: "$CI_BUILD_STAGE"
key: '$CI_BUILD_STAGE'
stages:
- security
- test
- release
- metadata
- security
- test
- release
- metadata
# ====================
# security stage
@ -19,56 +19,62 @@ mirror:
stage: security
script:
- npmci git mirror
only:
- tags
tags:
- lossless
- docker
- notpriv
snyk:
auditProductionDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security
script:
- npmci command npm install -g snyk
- npmci command npm install --ignore-scripts
- npmci command snyk test
- npmci npm prepare
- npmci command npm install --production --ignore-scripts
- npmci command npm config set registry https://registry.npmjs.org
- npmci command npm audit --audit-level=high --only=prod --production
tags:
- docker
- notpriv
allow_failure: true
auditDevDependencies:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security
script:
- npmci npm prepare
- npmci command npm install --ignore-scripts
- npmci command npm config set registry https://registry.npmjs.org
- npmci command npm audit --audit-level=high --only=dev
tags:
- docker
allow_failure: true
# ====================
# test stage
# ====================
testLEGACY:
stage: test
script:
- npmci node install legacy
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
allow_failure: true
testLTS:
stage: test
script:
- npmci node install lts
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
testSTABLE:
testStable:
stage: test
script:
- npmci npm prepare
- npmci node install stable
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
testBuild:
stage: test
script:
- npmci npm prepare
- npmci node install stable
- npmci npm install
- npmci command npm run build
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
release:
stage: release
@ -78,6 +84,7 @@ release:
only:
- tags
tags:
- lossless
- docker
- notpriv
@ -86,20 +93,16 @@ release:
# ====================
codequality:
stage: metadata
image: docker:stable
allow_failure: true
services:
- docker:stable-dind
only:
- tags
script:
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- docker run
--env SOURCE_CODE="$PWD"
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
paths: [codeclimate.json]
- npmci command npm install -g tslint typescript
- npmci npm prepare
- npmci npm install
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
tags:
- lossless
- docker
- priv
@ -110,17 +113,20 @@ trigger:
only:
- tags
tags:
- lossless
- docker
- notpriv
pages:
image: hosttoday/ht-docker-node:npmci
stage: metadata
script:
- npmci command npm install -g typedoc typescript
- npmci node install lts
- npmci command npm install -g @gitzone/tsdoc
- npmci npm prepare
- npmci npm install
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/
- npmci command tsdoc
tags:
- lossless
- docker
- notpriv
only:
@ -130,13 +136,3 @@ pages:
paths:
- public
allow_failure: true
windowsCompatibility:
image: stefanscherer/node-windows:10-build-tools
stage: metadata
script:
- npm install & npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- windows
allow_failure: true

11
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "npm test",
"name": "Run npm test",
"request": "launch",
"type": "node-terminal"
}
]
}

26
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"json.schemas": [
{
"fileMatch": ["/npmextra.json"],
"schema": {
"type": "object",
"properties": {
"npmci": {
"type": "object",
"description": "settings for npmci"
},
"gitzone": {
"type": "object",
"description": "settings for gitzone",
"properties": {
"projectType": {
"type": "string",
"enum": ["website", "element", "service", "npm", "wcc"]
}
}
}
}
}
}
]
}

View File

@ -1,4 +1,15 @@
{
"gitzone": {
"projectType": "npm",
"module": {
"githost": "gitlab.com",
"gitscope": "pushrocks",
"gitrepo": "smartfuzzy",
"shortDescription": "search things easily",
"npmPackagename": "@pushrocks/smartfuzzy",
"license": "MIT"
}
},
"npmci": {
"npmGlobalTools": [],
"npmAccessLevel": "public"

25848
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
{
"name": "@pushrocks/smartfuzzy",
"version": "1.1.1",
"version": "1.1.4",
"private": false,
"description": "fuzzy match strings against word dictionaries/arrays",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"main": "dist_ts/index.js",
"typings": "dist_ts/index.d.ts",
"author": "Lossless GmbH",
"license": "MIT",
"scripts": {
@ -13,14 +13,30 @@
"build": "(tsbuild)"
},
"devDependencies": {
"@gitzone/tsbuild": "^2.0.22",
"@gitzone/tstest": "^1.0.15",
"@pushrocks/tapbundle": "^3.0.5",
"@types/node": "^10.7.1"
"@gitzone/tsbuild": "^2.1.27",
"@gitzone/tstest": "^1.0.57",
"@pushrocks/tapbundle": "^3.2.14",
"@types/node": "^16.10.2"
},
"dependencies": {
"@types/leven": "^2.1.1",
"fuse.js": "^3.2.1",
"leven": "^2.1.0"
}
"@pushrocks/smartpromise": "^3.1.6",
"@tsclass/tsclass": "^3.0.33",
"fuse.js": "^6.4.6",
"leven": "^3.1.0"
},
"browserslist": [
"last 1 chrome versions"
],
"files": [
"ts/**/*",
"ts_web/**/*",
"dist/**/*",
"dist_*/**/*",
"dist_ts/**/*",
"dist_ts_web/**/*",
"assets/**/*",
"cli.js",
"npmextra.json",
"readme.md"
]
}

View File

@ -0,0 +1,34 @@
import { expect, tap } from '@pushrocks/tapbundle';
import * as tsclass from '@tsclass/tsclass';
import * as smartfuzzy from '../ts/index';
tap.test('should sort objects', async () => {
const articleArray: tsclass.content.IArticle[] = [
{
title: 'Berlin has a ambivalent history',
content: 'it is known that Berlin has an interesting history',
author: null,
tags: ['city', 'Europe', 'hello'],
timestamp: Date.now(),
featuredImageUrl: null,
url: null,
},
{
title: 'Washington is a great city',
content: 'it is known that Washington is one of the greatest cities in the world',
author: null,
tags: ['city', 'USA', 'hello'],
timestamp: Date.now(),
featuredImageUrl: null,
url: null,
},
];
const testArticleSearch = new smartfuzzy.ArticleSearch(articleArray);
const result = await testArticleSearch.search('USA');
console.log(result);
console.log(result[0].matches);
});
tap.start();

21
test/test.objectsorter.ts Normal file
View File

@ -0,0 +1,21 @@
import { expect, tap } from '@pushrocks/tapbundle';
import * as smartfuzzy from '../ts/index';
tap.test('should sort objects', async () => {
class Car {
constructor(public brand: string) {}
}
let testObjectSorter: smartfuzzy.ObjectSorter<Car>;
testObjectSorter = new smartfuzzy.ObjectSorter([
new Car('BMW'),
new Car('Mercedes Benz'),
new Car('Volvo'),
]);
const result = testObjectSorter.sort('Volvo', ['brand']);
console.log(result);
});
tap.start();

View File

@ -8,7 +8,7 @@ tap.test('should create an instance of Smartfuzzy', async () => {
'Sony',
'Deutsche Bahn',
'Apple Inc.',
"Trader Joe's"
"Trader Joe's",
]);
expect(testSmartfuzzy).to.be.instanceof(smartfuzzy.Smartfuzzy);
});
@ -23,21 +23,4 @@ tap.test('should get closest match', async () => {
console.log(result);
});
tap.test('should sort objects', async () => {
class Car {
constructor(public brand: string) {}
}
let testObjectSorter: smartfuzzy.ObjectSorter<Car>;
testObjectSorter = new smartfuzzy.ObjectSorter([
new Car('BMW'),
new Car('Mercedes Benz'),
new Car('Volvo')
]);
const result = testObjectSorter.sort('Volvo', ['brand']);
console.log(result);
});
tap.start();

View File

@ -1,2 +1,3 @@
export * from './smartfuzzy.articlesearch';
export * from './smartfuzzy.classes.smartfuzzy';
export * from './smartfuzzy.classes.objectsorter';

View File

@ -0,0 +1,65 @@
import * as plugins from './smartfuzzy.plugins';
/**
* an article search that searches articles in a weighted manner
*/
export class ArticleSearch {
public articles: plugins.tsclass.content.IArticle[] = [];
public needsUpdate: boolean = false;
private readyDeferred = plugins.smartpromise.defer();
private fuse: plugins.fuseJs<plugins.tsclass.content.IArticle>;
constructor(articleArrayArg?: plugins.tsclass.content.IArticle[]) {
this.fuse = new plugins.fuseJs(this.articles);
this.readyDeferred.resolve();
if (articleArrayArg) {
for (const article of articleArrayArg) {
this.addArticle(article);
}
}
}
/**
* allows adding an article
*/
addArticle(articleArg: plugins.tsclass.content.IArticle) {
this.articles.push(articleArg);
this.needsUpdate = true;
}
/**
* allows searching an article
*/
public async search(searchStringArg: string) {
if (this.needsUpdate) {
const oldDeferred = this.readyDeferred;
this.readyDeferred = plugins.smartpromise.defer();
this.needsUpdate = false;
if (oldDeferred.status !== 'fulfilled') {
this.readyDeferred.promise.then(oldDeferred.resolve);
}
this.fuse = new plugins.fuseJs(this.articles, {
keys: [
{
name: 'title',
weight: 3,
},
{
name: 'tags',
weight: 2,
},
{
name: 'content',
weight: 1,
},
],
includeMatches: true,
});
this.readyDeferred.resolve();
} else {
await this.readyDeferred.promise;
}
return this.fuse.search(searchStringArg);
}
}

View File

@ -3,12 +3,11 @@ import * as plugins from './smartfuzzy.plugins';
export class ObjectSorter<T> {
public objectDictionary: T[];
constructor(objectDictionaryArg: T[] = []) {
this.objectDictionary = objectDictionaryArg;
}
sort(stringArg: string, objectKeysArg: string[]): T[] {
sort(stringArg: string, objectKeysArg: string[]): plugins.fuseJs.FuseResult<T>[] {
const fuseOptions = {
shouldSort: true,
threshold: 0.6,
@ -16,11 +15,10 @@ export class ObjectSorter<T> {
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: objectKeysArg
keys: objectKeysArg,
};
const fuse = new plugins.fuseJs(this.objectDictionary, fuseOptions);
const fuse = new plugins.fuseJs<T>(this.objectDictionary, fuseOptions);
const result = fuse.search(stringArg);
return result;
}
}

View File

@ -26,7 +26,7 @@ export class Smartfuzzy {
* returns the closest match for a given string
* @param stringArg
*/
getChangeScoreForString(stringArg): TDictionaryMap {
getChangeScoreForString(stringArg: string): TDictionaryMap {
const dictionaryMap: TDictionaryMap = {};
for (const wordArg of this.dictionary) {
dictionaryMap[wordArg] = plugins.leven(stringArg, wordArg);
@ -38,7 +38,7 @@ export class Smartfuzzy {
const fuseDictionary: { name: string }[] = [];
for (const wordArg of this.dictionary) {
fuseDictionary.push({
name: wordArg
name: wordArg,
});
}
const fuseOptions = {
@ -48,13 +48,13 @@ export class Smartfuzzy {
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: ['name']
keys: ['name'],
};
const fuse = new plugins.fuseJs(fuseDictionary, fuseOptions);
const fuzzyResult = fuse.search(stringArg);
let closestMatch: string = null;
if(fuzzyResult.length > 0) {
closestMatch = fuzzyResult[0].name;
if (fuzzyResult.length > 0) {
closestMatch = fuzzyResult[0].item.name;
}
return closestMatch;
}

View File

@ -1,4 +1,15 @@
import leven = require('leven');
const fuseJs = require('fuse.js');
// @pushrocks scope
import * as smartpromise from '@pushrocks/smartpromise';
export { smartpromise };
// @tsclass scope
import * as tsclass from '@tsclass/tsclass';
export { tsclass };
// third party scope
import leven from 'leven';
import fuseJs from 'fuse.js';
export { leven, fuseJs };

View File

@ -1,7 +1,17 @@
{
"extends": ["tslint:latest", "tslint-config-prettier"],
"rules": {
"semicolon": [true, "always"]
"semicolon": [true, "always"],
"no-console": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"member-ordering": {
"options":{
"order": [
"static-method"
]
}
}
},
"defaultSeverity": "warning"
}