From 6e9310bb4e891b5f15de0118193f8604a87b7e0a Mon Sep 17 00:00:00 2001 From: ruedap Date: Sun, 30 Aug 2020 09:51:26 +0900 Subject: [PATCH 1/6] build(npm): Improve npm script name --- .github/workflows/test.yml | 4 ++-- package.json | 17 ++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c5b1e59d..4449f3ca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,5 +21,5 @@ jobs: - name: Build run: npm run build - - name: Cmd - run: npm run cmd + - name: Test command + run: npm run test:cmd diff --git a/package.json b/package.json index 9b1ecc87..72908836 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "engines": { "node": "12.x" }, - "description": "You can incrementally search for Font Awesome icons and paste it to front most app.", + "description": "You can incrementally search for Bootstrap Icons and paste it to front most app.", "scripts": { "clean": "rimraf ./dist && mkdirp ./dist && cpx './assets/{icons/*,icon.png,info.plist}' ./dist", "compile": "webpack", @@ -13,15 +13,15 @@ "build": "npm run clean && npm run compile && npm run package && npm run compress", "build:open": "npm run build && npm run open", "open": "open ./dist/Bootstrap-Icons.alfredworkflow", - "cmd:find": "./dist/bootstrap-icons-workflow --find bootstrap", - "cmd:put:svg": "./dist/bootstrap-icons-workflow --put-svg bootstrap", - "cmd:put:name": "./dist/bootstrap-icons-workflow --put-name bootstrap", - "cmd:put:url": "./dist/bootstrap-icons-workflow --put-url bootstrap", - "cmd:put": "npm run cmd:put:svg && npm run cmd:put:name && npm run cmd:put:url", - "cmd": "npm run cmd:find && npm run cmd:put", "exec": "npm run clean && npm run compile && node ./dist/index.js", "test": "jest", "test:watch": "jest --watchAll", + "test:cmd:find": "./dist/bootstrap-icons-workflow --find bootstrap", + "test:cmd:put:svg": "./dist/bootstrap-icons-workflow --put-svg bootstrap", + "test:cmd:put:name": "./dist/bootstrap-icons-workflow --put-name bootstrap", + "test:cmd:put:url": "./dist/bootstrap-icons-workflow --put-url bootstrap", + "test:cmd:put": "npm run test:cmd:put:svg && npm run test:cmd:put:name && npm run test:cmd:put:url", + "test:cmd": "npm run test:cmd:find && npm run test:cmd:put", "fmt": "prettier --write .", "lint": "eslint . --ext 'ts,js'", "lint:fix": "eslint . --fix --ext 'ts,js'", @@ -34,8 +34,7 @@ "type": "git", "url": "git+https://github.com/ruedap/alfred-bootstrap-icons-workflow.git" }, - "keywords": [], - "author": "", + "author": "ruedap", "license": "MIT", "bugs": { "url": "https://github.com/ruedap/alfred-bootstrap-icons-workflow/issues" From d1e404c2afc32ee90662ebd0677ffaa8cede4802 Mon Sep 17 00:00:00 2001 From: ruedap Date: Sun, 30 Aug 2020 11:18:18 +0900 Subject: [PATCH 2/6] improvement(src): Improve search key --- src/index.ts | 5 +- src/search.test.ts | 268 ++++++++++++++++++++++++++++++--------------- src/search.ts | 13 ++- 3 files changed, 190 insertions(+), 96 deletions(-) diff --git a/src/index.ts b/src/index.ts index 5dcb51d9..53e21d50 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,11 +19,10 @@ const output = (str: string): void => { const main = (): void => { const args = getArgs(); const list = getAllIconsObject(); - const keys = ["name", "search.terms"]; if (includesFlag(args, FLAG.FIND)) { const query = getFlagArgs(args, FLAG.FIND); - const searchResult = search(list, keys, query); + const searchResult = search(list, query); output(toJson(searchResult)); return; } @@ -50,7 +49,7 @@ const main = (): void => { } // NOTE: No flags - output(toJson(search(list, keys, ""))); + output(toJson(search(list, ""))); }; main(); diff --git a/src/search.test.ts b/src/search.test.ts index c4343972..ea994889 100644 --- a/src/search.test.ts +++ b/src/search.test.ts @@ -1,7 +1,7 @@ -import { TIconObject } from "./assets/icons_object"; +import { getAllIconsObject, TIconObject } from "./assets/icons_object"; import { search, toJson } from "./search"; -const LIST_1: TIconObject = { +const EXAMPLE_LIST_1: TIconObject = { name: "aaabbb", title: "AAABBB", categories: ["111", "222"], @@ -11,7 +11,7 @@ const LIST_1: TIconObject = { }, }; -const LIST_2: TIconObject = { +const EXAMPLE_LIST_2: TIconObject = { name: "bbbccc", title: "BBBCCC", categories: ["222", "444"], @@ -21,7 +21,7 @@ const LIST_2: TIconObject = { }, }; -const LIST_3: TIconObject = { +const EXAMPLE_LIST_3: TIconObject = { name: "cccddd", title: "CCCDDD", categories: ["333", "666"], @@ -31,100 +31,188 @@ const LIST_3: TIconObject = { }, }; -const LIST: TIconObject[] = [LIST_1, LIST_2, LIST_3]; +const EXAMPLE_LIST: TIconObject[] = [ + EXAMPLE_LIST_1, + EXAMPLE_LIST_2, + EXAMPLE_LIST_3, +]; -const KEYS = ["name", "title", "categories", "tags"]; +const ACTUAL_LIST = getAllIconsObject(); describe("search()", () => { - test("empty query", () => { - const query = ""; - const actual = search(LIST, KEYS, query); - const expected = [ - { - item: LIST_1, - refIndex: 0, - score: 0, - }, - { - item: LIST_2, - refIndex: 1, - score: 0, - }, - { - item: LIST_3, - refIndex: 2, - score: 0, - }, - ]; + describe("example list", () => { + test("empty query", () => { + const query = ""; + const actual = search(EXAMPLE_LIST, query); + const expected = [ + { + item: EXAMPLE_LIST_1, + refIndex: 0, + score: 0, + }, + { + item: EXAMPLE_LIST_2, + refIndex: 1, + score: 0, + }, + { + item: EXAMPLE_LIST_3, + refIndex: 2, + score: 0, + }, + ]; - expect(actual.length).toBe(3); - expect(actual).toStrictEqual(expected); - }); + expect(actual.length).toBe(3); + expect(actual).toStrictEqual(expected); + }); - test("name key", () => { - const query = "BBB"; - const actual = search(LIST, KEYS, query); - const expected = [ - { - item: LIST_2, - refIndex: 1, - score: 0.000001, - }, - { - item: LIST_1, - refIndex: 0, - score: 0.0009, - }, - ]; + test("name key", () => { + const query = "BBB"; + const actual = search(EXAMPLE_LIST, query); + const expected = [ + { + item: EXAMPLE_LIST_2, + refIndex: 1, + score: 0.00006309573444801936, + }, + { + item: EXAMPLE_LIST_1, + refIndex: 0, + score: 0.007378528457548093, + }, + ]; - expect(actual.length).toBe(2); - expect(actual).toStrictEqual(expected); - }); + expect(actual.length).toBe(2); + expect(actual).toStrictEqual(expected); + }); - test("categories key", () => { - const query = "22"; - const actual = search(LIST, KEYS, query); - const expected = [ - { - item: LIST_1, - refIndex: 0, - score: 0.0005, - }, - { - item: LIST_2, - refIndex: 1, - score: 0.0005, - }, - ]; + test("categories key", () => { + const query = "22"; + const actual = search(EXAMPLE_LIST, query); + const expected = [ + { + item: EXAMPLE_LIST_1, + refIndex: 0, + score: 0.1022565182563573, + }, + { + item: EXAMPLE_LIST_2, + refIndex: 1, + score: 0.1022565182563573, + }, + ]; - expect(actual.length).toBe(2); - expect(actual).toStrictEqual(expected); + expect(actual.length).toBe(2); + expect(actual).toStrictEqual(expected); + }); + + test("tags key", () => { + const query = "200"; + const actual = search(EXAMPLE_LIST, query); + const expected = [ + { + item: EXAMPLE_LIST_1, + refIndex: 0, + score: 0.00001448090456013047, + }, + { + item: EXAMPLE_LIST_2, + refIndex: 1, + score: 0.00001448090456013047, + }, + { + item: EXAMPLE_LIST_3, + refIndex: 2, + score: 0.5172818579717865, + }, + ]; + + expect(actual.length).toBe(3); + // FIXME: Is this correct? + expect(actual).toStrictEqual(expected); + }); }); - test("tags key", () => { - const query = "200"; - const actual = search(LIST, KEYS, query); - const expected = [ - { - item: LIST_1, - refIndex: 0, - score: 7.401486830834377e-17, - }, - { - item: LIST_2, - refIndex: 1, - score: 7.401486830834377e-17, - }, - { - item: LIST_3, - refIndex: 2, - score: 0.1111111111111111, - }, - ]; + describe("actual list", () => { + test("name key", () => { + const query = "bootstrap-reboot"; + const actual = search(ACTUAL_LIST, query); + const expected = [ + { + item: { + name: "bootstrap-reboot", + title: "Bootstrap Reboot", + categories: ["Bootstrap"], + tags: ["bootstrap"], + svg: { + raw: + '"\\n \\n"', + }, + }, + refIndex: 158, + score: 1.7028485066985596e-12, + }, + { + item: { + name: "bootstrap", + title: "Bootstrap", + categories: ["Bootstrap"], + tags: ["bootstrap"], + svg: { + raw: + '"\\n \\n \\n"', + }, + }, + refIndex: 159, + score: 0.19140625, + }, + { + item: { + name: "bootstrap-fill", + title: "Bootstrap fill", + categories: ["Bootstrap"], + tags: ["bootstrap"], + svg: { + raw: + '"\\n \\n"', + }, + }, + refIndex: 157, + score: 0.20357702451072787, + }, + { + item: { + categories: ["Misc"], + name: "bookmark-heart-fill", + svg: { + raw: + '"\\n \\n"', + }, + tags: ["reading", "book"], + title: "Bookmark heart fill", + }, + refIndex: 145, + score: 0.6684759217372512, + }, + { + item: { + categories: ["Misc"], + name: "bookmark-heart", + svg: { + raw: + '"\\n \\n \\n"', + }, + tags: ["reading", "book"], + title: "Bookmark heart", + }, + refIndex: 146, + score: 0.6684759217372512, + }, + ]; - expect(actual.length).toBe(3); - // FIXME: Is this correct? - expect(actual).toStrictEqual(expected); + expect(actual.length).toBe(5); + expect(actual).toStrictEqual(expected); + }); }); }); @@ -132,17 +220,17 @@ describe("toJson()", () => { test("3 results", () => { const searchResult = [ { - item: LIST_1, + item: EXAMPLE_LIST_1, refIndex: 0, score: 7.401486830834377e-17, }, { - item: LIST_2, + item: EXAMPLE_LIST_2, refIndex: 1, score: 7.401486830834377e-17, }, { - item: LIST_3, + item: EXAMPLE_LIST_3, refIndex: 2, score: 0.1111111111111111, }, diff --git a/src/search.ts b/src/search.ts index bd8840da..79296285 100644 --- a/src/search.ts +++ b/src/search.ts @@ -9,10 +9,17 @@ type TSearchResult = Readonly<{ score: number; }>; +const DEFAULT_KEYS = [ + { name: "name", weight: 0.7 }, + { name: "title", weight: 0.7 }, + { name: "categories", weight: 0.3 }, + { name: "tags", weight: 0.3 }, +]; + export const search = ( list: TIconObject[], - keys: string[], - query: string + query: string, + keys?: string[] ): TSearchResult[] => { if (!query) { return list.map((item, i) => { @@ -27,7 +34,7 @@ export const search = ( const options = { includeScore: true, useExtendedSearch: true, - keys: keys, + keys: keys ?? DEFAULT_KEYS, } as const; const fuse = new Fuse(list, options, undefined); From 7b2afc60e3fcb8ea82cedaba5638e328624d06ca Mon Sep 17 00:00:00 2001 From: ruedap Date: Sun, 30 Aug 2020 11:25:42 +0900 Subject: [PATCH 3/6] improvement(src): Remove uid from response item for exact search results --- src/alfred/response.ts | 4 +++- src/icons.test.ts | 4 +--- src/icons.ts | 1 - src/search.test.ts | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/alfred/response.ts b/src/alfred/response.ts index 55b874e7..e5721a05 100644 --- a/src/alfred/response.ts +++ b/src/alfred/response.ts @@ -19,7 +19,9 @@ type TText = Readonly<{ }>; export type TResponseItem = Readonly<{ - uid: string; + // NOTE: If you would like Alfred to always show the results in the order you return them from your script, exclude the UID field. + // https://www.alfredapp.com/help/workflows/inputs/script-filter/json/ + uid?: string; title: string; subtitle: string; arg: string; // recommended diff --git a/src/icons.test.ts b/src/icons.test.ts index c8497850..14709f27 100644 --- a/src/icons.test.ts +++ b/src/icons.test.ts @@ -14,7 +14,6 @@ test("toResponseItem()", () => { const actual = toResponseItem(iconObject); const expected = { - uid: "bootstrap", title: "bootstrap", subtitle: "Paste SVG code", arg: "bootstrap", @@ -27,9 +26,8 @@ test("getAllIcons()", () => { const allIcons = getAllIcons(); expect(allIcons.items.length).toBe(1120); - const actual = allIcons.items.find((icon) => icon.uid === "bootstrap"); + const actual = allIcons.items.find((icon) => icon.arg === "bootstrap"); const expected = { - uid: "bootstrap", title: "bootstrap", subtitle: "Paste SVG code", arg: "bootstrap", diff --git a/src/icons.ts b/src/icons.ts index 43ae1bde..62420ddb 100644 --- a/src/icons.ts +++ b/src/icons.ts @@ -3,7 +3,6 @@ import { getAllIconsObject, TIconObject } from "./assets/icons_object"; export const toResponseItem = (iconObject: TIconObject): TResponseItem => { return { - uid: iconObject.name, title: iconObject.name, subtitle: `Paste SVG code`, arg: iconObject.name, diff --git a/src/search.test.ts b/src/search.test.ts index ea994889..562c1e4d 100644 --- a/src/search.test.ts +++ b/src/search.test.ts @@ -237,7 +237,7 @@ describe("toJson()", () => { ]; const actual = toJson(searchResult); const expected = - '{"items":[{"uid":"aaabbb","title":"aaabbb","subtitle":"Paste SVG code","arg":"aaabbb","icon":{"path":"./icons/aaabbb.png"}},{"uid":"bbbccc","title":"bbbccc","subtitle":"Paste SVG code","arg":"bbbccc","icon":{"path":"./icons/bbbccc.png"}},{"uid":"cccddd","title":"cccddd","subtitle":"Paste SVG code","arg":"cccddd","icon":{"path":"./icons/cccddd.png"}}]}'; + '{"items":[{"title":"aaabbb","subtitle":"Paste SVG code","arg":"aaabbb","icon":{"path":"./icons/aaabbb.png"}},{"title":"bbbccc","subtitle":"Paste SVG code","arg":"bbbccc","icon":{"path":"./icons/bbbccc.png"}},{"title":"cccddd","subtitle":"Paste SVG code","arg":"cccddd","icon":{"path":"./icons/cccddd.png"}}]}'; expect(actual).toStrictEqual(expected); }); From 80c357a6cf48a247aaf294d72360808c7d8aa548 Mon Sep 17 00:00:00 2001 From: ruedap Date: Sun, 30 Aug 2020 12:10:28 +0900 Subject: [PATCH 4/6] docs(readme): Update images in README --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 21766ffc..d11bebf1 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ You can incrementally search for [Bootstrap Icons](https://icons.getbootstrap.com/) and paste it to front most app. -screencast +screencast ## Installation @@ -18,7 +18,6 @@ The current supported version is **Bootstrap Icons 1.0.0**. Previous versions ar There are a few ways to allow such programs to run. See: https://github.com/ruedap/alfred-bootstrap-icons-workflow/issues/1 - ## Usage **Keyword** `bi`: Search through [Bootstrap Icons](https://icons.getbootstrap.com/). @@ -41,7 +40,7 @@ See: https://github.com/ruedap/alfred-bootstrap-icons-workflow/issues/1 **Disable pasting**: Turn off "Automatically paste to front most app" in Workflow's Preferences. -Disable pasting +Disable pasting ## Development From 25eabb8c7604316deea92ddf125b0cd3151fb59a Mon Sep 17 00:00:00 2001 From: ruedap Date: Sun, 30 Aug 2020 12:15:56 +0900 Subject: [PATCH 5/6] chore(release): Bump version to 1.0.0.1 --- assets/info.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/info.plist b/assets/info.plist index e6952b04..e23ce081 100644 --- a/assets/info.plist +++ b/assets/info.plist @@ -3,9 +3,9 @@ name - Bootstrap Icons 1.0.0.0 + Bootstrap Icons 1.0.0.1 version - 1.0.0.0 + 1.0.0.1 webaddress https://github.com/ruedap/alfred-bootstrap-icons-workflow readme From da3ebe04a42307b05a0ab062fd117172487b3e73 Mon Sep 17 00:00:00 2001 From: ruedap Date: Sun, 30 Aug 2020 12:22:00 +0900 Subject: [PATCH 6/6] docs(src): Remove unnecessary comment --- src/search.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/search.test.ts b/src/search.test.ts index 562c1e4d..67a160e0 100644 --- a/src/search.test.ts +++ b/src/search.test.ts @@ -128,7 +128,6 @@ describe("search()", () => { ]; expect(actual.length).toBe(3); - // FIXME: Is this correct? expect(actual).toStrictEqual(expected); }); });