@internetarchive/collection-browser 2.7.14 → 2.8.1-alpha-webdev7002.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/.editorconfig +29 -29
  2. package/.husky/pre-commit +4 -4
  3. package/LICENSE +661 -661
  4. package/README.md +83 -83
  5. package/dist/index.d.ts +4 -1
  6. package/dist/index.js +3 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/src/collection-browser.d.ts +2 -2
  9. package/dist/src/collection-browser.js +10 -6
  10. package/dist/src/collection-browser.js.map +1 -1
  11. package/dist/src/collection-facets/smart-facets/heuristics/{browser-language-heuristic.d.ts → browser-language/browser-language-heuristic.d.ts} +1 -1
  12. package/dist/src/collection-facets/smart-facets/heuristics/browser-language/browser-language-heuristic.js.map +1 -0
  13. package/dist/src/collection-facets/smart-facets/heuristics/index.d.ts +3 -0
  14. package/dist/src/collection-facets/smart-facets/heuristics/index.js +4 -0
  15. package/dist/src/collection-facets/smart-facets/heuristics/index.js.map +1 -0
  16. package/dist/src/collection-facets/smart-facets/heuristics/{query-keywords-heuristic.d.ts → query-keywords/query-keywords-heuristic.d.ts} +1 -2
  17. package/dist/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-heuristic.js +14 -0
  18. package/dist/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-heuristic.js.map +1 -0
  19. package/dist/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-map.d.ts +6 -0
  20. package/dist/src/collection-facets/smart-facets/heuristics/{query-keywords-heuristic.js → query-keywords/query-keywords-map.js} +7 -17
  21. package/dist/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-map.js.map +1 -0
  22. package/dist/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-entity-map.d.ts +9 -0
  23. package/dist/src/collection-facets/smart-facets/heuristics/{wikidata-heuristic.js → wikidata/wikidata-entity-map.js} +9 -49
  24. package/dist/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-entity-map.js.map +1 -0
  25. package/dist/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.d.ts +21 -0
  26. package/dist/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.js +75 -0
  27. package/dist/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.js.map +1 -0
  28. package/dist/src/collection-facets/smart-facets/models.d.ts +4 -0
  29. package/dist/src/collection-facets/smart-facets/models.js.map +1 -1
  30. package/dist/src/collection-facets/smart-facets/smart-facet-heuristics.d.ts +2 -2
  31. package/dist/src/collection-facets/smart-facets/smart-facet-heuristics.js +9 -7
  32. package/dist/src/collection-facets/smart-facets/smart-facet-heuristics.js.map +1 -1
  33. package/dist/src/data-source/collection-browser-data-source-interface.d.ts +5 -0
  34. package/dist/src/data-source/collection-browser-data-source-interface.js.map +1 -1
  35. package/dist/src/data-source/collection-browser-data-source.d.ts +9 -0
  36. package/dist/src/data-source/collection-browser-data-source.js +12 -1
  37. package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
  38. package/dist/test/collection-browser.test.js +18 -0
  39. package/dist/test/collection-browser.test.js.map +1 -1
  40. package/dist/test/data-source/collection-browser-data-source.test.js +10 -0
  41. package/dist/test/data-source/collection-browser-data-source.test.js.map +1 -1
  42. package/index.ts +15 -1
  43. package/local.archive.org.cert +86 -86
  44. package/local.archive.org.key +27 -27
  45. package/package.json +1 -1
  46. package/renovate.json +6 -6
  47. package/src/collection-browser.ts +13 -6
  48. package/src/collection-facets/smart-facets/heuristics/{browser-language-heuristic.ts → browser-language/browser-language-heuristic.ts} +1 -1
  49. package/src/collection-facets/smart-facets/heuristics/index.ts +3 -0
  50. package/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-heuristic.ts +17 -0
  51. package/src/collection-facets/smart-facets/heuristics/query-keywords/query-keywords-map.ts +36 -0
  52. package/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-entity-map.ts +134 -0
  53. package/src/collection-facets/smart-facets/heuristics/wikidata/wikidata-heuristic.ts +89 -0
  54. package/src/collection-facets/smart-facets/models.ts +4 -0
  55. package/src/collection-facets/smart-facets/smart-facet-heuristics.ts +13 -8
  56. package/src/data-source/collection-browser-data-source-interface.ts +6 -0
  57. package/src/data-source/collection-browser-data-source.ts +14 -1
  58. package/test/collection-browser.test.ts +24 -0
  59. package/test/data-source/collection-browser-data-source.test.ts +14 -0
  60. package/web-dev-server.config.mjs +30 -30
  61. package/web-test-runner.config.mjs +41 -41
  62. package/dist/src/collection-facets/smart-facets/heuristics/browser-language-heuristic.js.map +0 -1
  63. package/dist/src/collection-facets/smart-facets/heuristics/query-keywords-heuristic.js.map +0 -1
  64. package/dist/src/collection-facets/smart-facets/heuristics/wikidata-heuristic.d.ts +0 -5
  65. package/dist/src/collection-facets/smart-facets/heuristics/wikidata-heuristic.js.map +0 -1
  66. package/src/collection-facets/smart-facets/heuristics/query-keywords-heuristic.ts +0 -55
  67. package/src/collection-facets/smart-facets/heuristics/wikidata-heuristic.ts +0 -191
  68. /package/dist/src/collection-facets/smart-facets/heuristics/{browser-language-heuristic.js → browser-language/browser-language-heuristic.js} +0 -0
@@ -0,0 +1,89 @@
1
+ import type { SmartQueryHeuristic, SmartFacet } from '../../models';
2
+ import { WIKIDATA_ENTITIES } from './wikidata-entity-map';
3
+
4
+ // If wikidata describes the top query result as X, recommend facet Y, e.g.:
5
+ // X Y
6
+ // written work mt:texts
7
+ // film mt:movies
8
+ // author mt:texts and creator:<query>
9
+ // filmmaker mt:movies and creator:<query>
10
+ // photographer mt:image and creator:<query>
11
+ // visual artist mt:image and creator:<query>
12
+ // etc.
13
+ export class WikidataHeuristic implements SmartQueryHeuristic {
14
+ private readonly WIKIDATA_BASE_URL = 'https://www.wikidata.org/w/api.php';
15
+
16
+ private readonly WIKIDATA_DEFAULT_ARGS =
17
+ '?action=wbsearchentities&format=json&language=en&uselang=en&origin=*&type=item&limit=5';
18
+
19
+ /**
20
+ * Returns the full URL for a Wikidata search for the given query
21
+ * @param query The query to search for
22
+ */
23
+ private getWikidataURL(query: string): string {
24
+ const urlQuery = encodeURIComponent(query);
25
+ return `${this.WIKIDATA_BASE_URL}${this.WIKIDATA_DEFAULT_ARGS}&search=${urlQuery}`;
26
+ }
27
+
28
+ /**
29
+ * Replaces query placeholders with an actual query string, within a collection of smart facets
30
+ * @param smartFacets The array of smart facets
31
+ * @param query The query string to replace placeholders with
32
+ * @returns A new array of smart facets with all query placeholders replaced
33
+ */
34
+ private replaceQueryPlaceholders(
35
+ smartFacets: SmartFacet[],
36
+ query: string,
37
+ ): SmartFacet[] {
38
+ return smartFacets.map(
39
+ smartFacet =>
40
+ ({
41
+ // Replace placeholders within the smart facet label
42
+ label: smartFacet.label?.replace('__QUERY', query),
43
+ // Replace placeholders within the facets themselves (buckets & display text)
44
+ facets: smartFacet.facets.map(facet => {
45
+ const replaced = {
46
+ ...facet,
47
+ bucketKey: facet.bucketKey.replace('__QUERY', query),
48
+ };
49
+
50
+ if (facet.displayText) {
51
+ replaced.displayText = replaced.displayText?.replace(
52
+ '__QUERY',
53
+ query,
54
+ );
55
+ }
56
+
57
+ return replaced;
58
+ }),
59
+ }) as SmartFacet,
60
+ );
61
+ }
62
+
63
+ /**
64
+ * @inheritdoc
65
+ */
66
+ async getRecommendedFacets(query: string): Promise<SmartFacet[]> {
67
+ const recommendations: SmartFacet[] = [];
68
+
69
+ try {
70
+ const wikidataURL = this.getWikidataURL(query);
71
+ const wikidataResponse = await fetch(wikidataURL);
72
+ const searchResults = await wikidataResponse.json();
73
+
74
+ for (const [keyword, facets] of Object.entries(WIKIDATA_ENTITIES)) {
75
+ const keywordRegex = new RegExp(`\\b${keyword}\\b`);
76
+ if (keywordRegex.test(searchResults.search[0]?.description)) {
77
+ const entityName = searchResults.search[0].label;
78
+ recommendations.push(
79
+ ...this.replaceQueryPlaceholders(facets, entityName),
80
+ );
81
+ }
82
+ }
83
+
84
+ return recommendations;
85
+ } catch (err) {
86
+ return [];
87
+ }
88
+ }
89
+ }
@@ -28,5 +28,9 @@ export interface SmartFacetEvent {
28
28
  export type KeywordFacetMap = Record<string, SmartFacet[]>;
29
29
 
30
30
  export interface SmartQueryHeuristic {
31
+ /**
32
+ * Resolves to a recommended set of facets to apply for the given query
33
+ * @param query The search query to recommend facets for
34
+ */
31
35
  getRecommendedFacets(query: string): Promise<SmartFacet[]>;
32
36
  }
@@ -1,19 +1,24 @@
1
1
  import { dedupe } from './dedupe';
2
- import { BrowserLanguageHeuristic } from './heuristics/browser-language-heuristic';
3
- import { QueryKeywordsHeuristic } from './heuristics/query-keywords-heuristic';
4
- import { WikidataHeuristic } from './heuristics/wikidata-heuristic';
2
+ import { BrowserLanguageHeuristic } from './heuristics/browser-language/browser-language-heuristic';
3
+ import { QueryKeywordsHeuristic } from './heuristics/query-keywords/query-keywords-heuristic';
4
+ import { WikidataHeuristic } from './heuristics/wikidata/wikidata-heuristic';
5
5
  import type { SmartFacet, SmartQueryHeuristic } from './models';
6
6
 
7
7
  export class SmartQueryHeuristicGroup implements SmartQueryHeuristic {
8
- private static readonly HEURISTICS = [
8
+ // Avoid collapsing the array onto one line
9
+ // prettier-ignore
10
+ private static readonly DEFAULT_HEURISTICS: (new () => SmartQueryHeuristic)[] = [
9
11
  QueryKeywordsHeuristic,
10
12
  WikidataHeuristic,
11
- BrowserLanguageHeuristic,
13
+ BrowserLanguageHeuristic
12
14
  ];
13
15
 
14
- async getRecommendedFacets(query: string): Promise<SmartFacet[]> {
15
- const promises = SmartQueryHeuristicGroup.HEURISTICS.map(HeuristicCtor =>
16
- new HeuristicCtor().getRecommendedFacets(query),
16
+ async getRecommendedFacets(
17
+ query: string,
18
+ heuristics = SmartQueryHeuristicGroup.DEFAULT_HEURISTICS
19
+ ): Promise<SmartFacet[]> {
20
+ const promises = heuristics.map(HeuristicCtor =>
21
+ new HeuristicCtor().getRecommendedFacets(query)
17
22
  );
18
23
 
19
24
  return dedupe((await Promise.all(promises)).flat());
@@ -254,6 +254,12 @@ export interface CollectionBrowserDataSourceInterface
254
254
  */
255
255
  setPageSize(pageSize: number): void;
256
256
 
257
+ /**
258
+ * Sets the total number of pages that should be batched together on each initial fetch.
259
+ * @param pages How many initial pages to batch
260
+ */
261
+ setNumInitialPages(numPages: number): void;
262
+
257
263
  /**
258
264
  * Sets the total result count for this data source to the given value.
259
265
  * @param count The number of total results to set
@@ -49,6 +49,12 @@ export class CollectionBrowserDataSource
49
49
  */
50
50
  private numTileModels = 0;
51
51
 
52
+ /**
53
+ * How many consecutive pages should be batched together on the initial page fetch.
54
+ * Defaults to 2 pages.
55
+ */
56
+ private numInitialPages = 2;
57
+
52
58
  /**
53
59
  * A set of fetch IDs that are valid for the current query state
54
60
  */
@@ -360,6 +366,13 @@ export class CollectionBrowserDataSource
360
366
  this.pageSize = pageSize;
361
367
  }
362
368
 
369
+ /**
370
+ * @inheritdoc
371
+ */
372
+ setNumInitialPages(numPages: number): void {
373
+ this.numInitialPages = numPages;
374
+ }
375
+
363
376
  /**
364
377
  * @inheritdoc
365
378
  */
@@ -997,7 +1010,7 @@ export class CollectionBrowserDataSource
997
1010
  private async doInitialPageFetch(): Promise<void> {
998
1011
  this.setSearchResultsLoading(true);
999
1012
  // Try to batch 2 initial page requests when possible
1000
- await this.fetchPage(this.host.initialPageNumber, 2);
1013
+ await this.fetchPage(this.host.initialPageNumber, this.numInitialPages);
1001
1014
  }
1002
1015
 
1003
1016
  /**
@@ -1830,6 +1830,30 @@ describe('Collection Browser', () => {
1830
1830
  expect(el.dataSource.uncheckedTileModels.length).to.equal(2);
1831
1831
  });
1832
1832
 
1833
+ it('emits event when manage view state changes', async () => {
1834
+ const spy = sinon.spy();
1835
+ const searchService = new MockSearchService();
1836
+ const el = await fixture<CollectionBrowser>(
1837
+ html`<collection-browser
1838
+ .searchService=${searchService}
1839
+ .baseNavigationUrl=${''}
1840
+ @manageModeChanged=${spy}
1841
+ ></collection-browser>`,
1842
+ );
1843
+
1844
+ el.isManageView = true;
1845
+ await el.updateComplete;
1846
+
1847
+ expect(spy.callCount).to.equal(1);
1848
+ expect(spy.args[0][0]?.detail).to.be.true;
1849
+
1850
+ el.isManageView = false;
1851
+ await el.updateComplete;
1852
+
1853
+ expect(spy.callCount).to.equal(2);
1854
+ expect(spy.args[1][0]?.detail).to.be.false;
1855
+ });
1856
+
1833
1857
  it('emits event when item removal requested', async () => {
1834
1858
  const spy = sinon.spy();
1835
1859
  const searchService = new MockSearchService();
@@ -101,6 +101,20 @@ describe('Collection Browser Data Source', () => {
101
101
  expect(pageFetchSpy.callCount).to.equal(0);
102
102
  });
103
103
 
104
+ it('can set its initial page batch size', async () => {
105
+ host.searchService = new MockSearchService();
106
+
107
+ const pageFetchSpy = sinon.spy();
108
+ const dataSource = new CollectionBrowserDataSource(host);
109
+ dataSource.setNumInitialPages(10);
110
+ dataSource.fetchPage = pageFetchSpy;
111
+
112
+ dataSource.handleQueryChange();
113
+
114
+ // Uses specified number of initial pages
115
+ expect(pageFetchSpy.args[0][1]).to.equal(10);
116
+ });
117
+
104
118
  it('refreshes prefix filter counts', () => {
105
119
  const dataSource = new CollectionBrowserDataSource(host);
106
120
  dataSource.addPage(1, dataPage);
@@ -1,30 +1,30 @@
1
- // import { hmrPlugin, presets } from '@open-wc/dev-server-hmr';
2
-
3
- /** Use Hot Module replacement by adding --hmr to the start command */
4
- const hmr = process.argv.includes('--hmr');
5
-
6
- export default /** @type {import('@web/dev-server').DevServerConfig} */ ({
7
- nodeResolve: true,
8
- open: '/',
9
- watch: !hmr,
10
-
11
- /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
12
- // esbuildTarget: 'auto'
13
-
14
- /** Set appIndex to enable SPA routing */
15
- // appIndex: 'demo/index.html',
16
-
17
- /** Confgure bare import resolve plugin */
18
- // nodeResolve: {
19
- // exportConditions: ['browser', 'development']
20
- // },
21
-
22
- plugins: [
23
- /** Use Hot Module Replacement by uncommenting. Requires @open-wc/dev-server-hmr plugin */
24
- // hmr && hmrPlugin({ exclude: ['**/*/node_modules/**/*'], presets: [presets.litElement] }),
25
- ],
26
-
27
- http2: true,
28
- sslCert: './local.archive.org.cert',
29
- sslKey: './local.archive.org.key',
30
- });
1
+ // import { hmrPlugin, presets } from '@open-wc/dev-server-hmr';
2
+
3
+ /** Use Hot Module replacement by adding --hmr to the start command */
4
+ const hmr = process.argv.includes('--hmr');
5
+
6
+ export default /** @type {import('@web/dev-server').DevServerConfig} */ ({
7
+ nodeResolve: true,
8
+ open: '/',
9
+ watch: !hmr,
10
+
11
+ /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
12
+ // esbuildTarget: 'auto'
13
+
14
+ /** Set appIndex to enable SPA routing */
15
+ // appIndex: 'demo/index.html',
16
+
17
+ /** Confgure bare import resolve plugin */
18
+ // nodeResolve: {
19
+ // exportConditions: ['browser', 'development']
20
+ // },
21
+
22
+ plugins: [
23
+ /** Use Hot Module Replacement by uncommenting. Requires @open-wc/dev-server-hmr plugin */
24
+ // hmr && hmrPlugin({ exclude: ['**/*/node_modules/**/*'], presets: [presets.litElement] }),
25
+ ],
26
+
27
+ http2: true,
28
+ sslCert: './local.archive.org.cert',
29
+ sslKey: './local.archive.org.key',
30
+ });
@@ -1,41 +1,41 @@
1
- // import { playwrightLauncher } from '@web/test-runner-playwright';
2
-
3
- const filteredLogs = ['Running in dev mode', 'lit-html is in dev mode'];
4
-
5
- export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({
6
- /** Test files to run */
7
- files: 'dist/test/**/*.test.js',
8
-
9
- /** Resolve bare module imports */
10
- nodeResolve: {
11
- exportConditions: ['browser', 'development'],
12
- },
13
-
14
- /** Filter out lit dev mode logs */
15
- filterBrowserLogs(log) {
16
- for (const arg of log.args) {
17
- if (typeof arg === 'string' && filteredLogs.some(l => arg.includes(l))) {
18
- return false;
19
- }
20
- }
21
- return true;
22
- },
23
-
24
- /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
25
- // esbuildTarget: 'auto',
26
-
27
- /** Amount of browsers to run concurrently */
28
- // concurrentBrowsers: 2,
29
-
30
- /** Amount of test files per browser to test concurrently */
31
- // concurrency: 1,
32
-
33
- /** Browsers to run tests on */
34
- // browsers: [
35
- // playwrightLauncher({ product: 'chromium' }),
36
- // playwrightLauncher({ product: 'firefox' }),
37
- // playwrightLauncher({ product: 'webkit' }),
38
- // ],
39
-
40
- // See documentation for all available options
41
- });
1
+ // import { playwrightLauncher } from '@web/test-runner-playwright';
2
+
3
+ const filteredLogs = ['Running in dev mode', 'lit-html is in dev mode'];
4
+
5
+ export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({
6
+ /** Test files to run */
7
+ files: 'dist/test/**/*.test.js',
8
+
9
+ /** Resolve bare module imports */
10
+ nodeResolve: {
11
+ exportConditions: ['browser', 'development'],
12
+ },
13
+
14
+ /** Filter out lit dev mode logs */
15
+ filterBrowserLogs(log) {
16
+ for (const arg of log.args) {
17
+ if (typeof arg === 'string' && filteredLogs.some(l => arg.includes(l))) {
18
+ return false;
19
+ }
20
+ }
21
+ return true;
22
+ },
23
+
24
+ /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
25
+ // esbuildTarget: 'auto',
26
+
27
+ /** Amount of browsers to run concurrently */
28
+ // concurrentBrowsers: 2,
29
+
30
+ /** Amount of test files per browser to test concurrently */
31
+ // concurrency: 1,
32
+
33
+ /** Browsers to run tests on */
34
+ // browsers: [
35
+ // playwrightLauncher({ product: 'chromium' }),
36
+ // playwrightLauncher({ product: 'firefox' }),
37
+ // playwrightLauncher({ product: 'webkit' }),
38
+ // ],
39
+
40
+ // See documentation for all available options
41
+ });
@@ -1 +0,0 @@
1
- {"version":3,"file":"browser-language-heuristic.js","sourceRoot":"","sources":["../../../../../src/collection-facets/smart-facets/heuristics/browser-language-heuristic.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,wBAAwB;IACnC,KAAK,CAAC,oBAAoB;QACxB,MAAM,mBAAmB,GAAG,SAAS,CAAC,QAAQ,CAAC;QAC/C,MAAM,YAAY,GAChB,wBAAwB,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,CAAC;QACvE,IAAI,CAAC,YAAY;YAAE,OAAO,EAAE,CAAC;QAE7B,OAAO;YACL;gBACE,MAAM,EAAE;oBACN;wBACE,SAAS,EAAE,UAAU;wBACrB,SAAS,EAAE,YAAY;qBACxB;iBACF;aACF;SACF,CAAC;IACJ,CAAC;IAEO,MAAM,CAAC,sBAAsB,CAAC,QAAgB;QACpD,mEAAmE;QACnE,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;IAC9E,CAAC;CACF","sourcesContent":["import type { SmartQueryHeuristic, SmartFacet } from '../models';\n\nexport class BrowserLanguageHeuristic implements SmartQueryHeuristic {\n async getRecommendedFacets(): Promise<SmartFacet[]> {\n const browserLanguageCode = navigator.language;\n const languageName =\n BrowserLanguageHeuristic.getLanguageDisplayName(browserLanguageCode);\n if (!languageName) return [];\n\n return [\n {\n facets: [\n {\n facetType: 'language',\n bucketKey: languageName,\n },\n ],\n },\n ];\n }\n\n private static getLanguageDisplayName(langCode: string): string | undefined {\n // Strip off any script/region/variant codes for greater generality\n const languageOnly = langCode.split('-')[0];\n return new Intl.DisplayNames(['en'], { type: 'language' }).of(languageOnly);\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"query-keywords-heuristic.js","sourceRoot":"","sources":["../../../../../src/collection-facets/smart-facets/heuristics/query-keywords-heuristic.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n SmartQueryHeuristic,\n KeywordFacetMap,\n SmartFacet,\n} from '../models';\n\n// If the query contains X word but Y facet isn't selected, recommend facet Y\nexport class QueryKeywordsHeuristic implements SmartQueryHeuristic {\n private static readonly KEYWORDS: KeywordFacetMap = {\n text: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],\n book: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],\n pdf: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],\n epub: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],\n audio: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],\n song: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],\n music: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],\n listen: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],\n podcast: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],\n radio: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],\n stream: [\n { facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] },\n { facets: [{ facetType: 'mediatype', bucketKey: 'movies' }] },\n ],\n video: [{ facets: [{ facetType: 'mediatype', bucketKey: 'movies' }] }],\n movie: [{ facets: [{ facetType: 'mediatype', bucketKey: 'movies' }] }],\n film: [{ facets: [{ facetType: 'mediatype', bucketKey: 'movies' }] }],\n image: [{ facets: [{ facetType: 'mediatype', bucketKey: 'image' }] }],\n photo: [{ facets: [{ facetType: 'mediatype', bucketKey: 'image' }] }],\n picture: [{ facets: [{ facetType: 'mediatype', bucketKey: 'image' }] }],\n software: [{ facets: [{ facetType: 'mediatype', bucketKey: 'software' }] }],\n app: [{ facets: [{ facetType: 'mediatype', bucketKey: 'software' }] }],\n program: [{ facets: [{ facetType: 'mediatype', bucketKey: 'software' }] }],\n game: [{ facets: [{ facetType: 'mediatype', bucketKey: 'software' }] }],\n etree: [{ facets: [{ facetType: 'mediatype', bucketKey: 'etree' }] }],\n concert: [{ facets: [{ facetType: 'mediatype', bucketKey: 'etree' }] }],\n 'live music': [\n { facets: [{ facetType: 'mediatype', bucketKey: 'etree' }] },\n ],\n dataset: [{ facets: [{ facetType: 'mediatype', bucketKey: 'data' }] }],\n };\n\n async getRecommendedFacets(query: string): Promise<SmartFacet[]> {\n const recommendations: SmartFacet[] = [];\n\n for (const [keyword, facets] of Object.entries(\n QueryKeywordsHeuristic.KEYWORDS,\n )) {\n if (query.includes(keyword)) {\n recommendations.push(...facets);\n }\n }\n\n return recommendations;\n }\n}\n"]}
@@ -1,5 +0,0 @@
1
- import type { SmartQueryHeuristic, SmartFacet } from '../models';
2
- export declare class WikidataHeuristic implements SmartQueryHeuristic {
3
- private static readonly ENTITIES;
4
- getRecommendedFacets(query: string): Promise<SmartFacet[]>;
5
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"wikidata-heuristic.js","sourceRoot":"","sources":["../../../../../src/collection-facets/smart-facets/heuristics/wikidata-heuristic.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n SmartQueryHeuristic,\n KeywordFacetMap,\n SmartFacet,\n} from '../models';\n\n// If wikidata describes the top query result as X, recommend facet Y, e.g.:\n// X Y\n// written work mt:texts\n// film mt:movies\n// author mt:texts and creator:<query>\n// filmmaker mt:movies and creator:<query>\n// photographer mt:image and creator:<query>\n// visual artist mt:image and creator:<query>\n// etc.\nexport class WikidataHeuristic implements SmartQueryHeuristic {\n private static readonly ENTITIES: KeywordFacetMap = {\n 'written work': [\n { facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] },\n ],\n literature: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],\n book: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],\n novel: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],\n filmmaker: [\n {\n label: 'Films by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'movies' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n author: [\n {\n label: 'Writing by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'texts' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n writer: [\n {\n label: 'Writing by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'texts' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n poet: [\n {\n label: 'Writing by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'texts' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n photographer: [\n {\n label: 'Images by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'image' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n painter: [\n {\n label: 'Images by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'image' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n 'visual artist': [\n {\n label: 'Images by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'image' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n 'graphic artist': [\n {\n label: 'Images by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'image' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n singer: [\n {\n label: 'Music by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'audio' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n songwriter: [\n {\n label: 'Music by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'audio' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n musician: [\n {\n label: 'Music by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'audio' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n composer: [\n {\n label: 'Music by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'audio' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n pianist: [\n {\n label: 'Music by __QUERY',\n facets: [\n { facetType: 'mediatype', bucketKey: 'audio' },\n { facetType: 'creator', bucketKey: '__QUERY' },\n ],\n },\n ],\n };\n\n async getRecommendedFacets(query: string): Promise<SmartFacet[]> {\n const recommendations: SmartFacet[] = [];\n\n try {\n const urlQuery = encodeURIComponent(query);\n\n const wikidataResponse = await fetch(\n `https://www.wikidata.org/w/api.php?action=wbsearchentities&search=${urlQuery}&format=json&language=en&uselang=en&origin=*&type=item&limit=5`,\n );\n const searchResults = await wikidataResponse.json();\n\n for (const [keyword, facets] of Object.entries(\n WikidataHeuristic.ENTITIES,\n )) {\n const keywordRegex = new RegExp(`\\\\b${keyword}\\\\b`);\n if (keywordRegex.test(searchResults.search[0]?.description)) {\n const entityName = searchResults.search[0].label;\n recommendations.push(\n ...facets.map(\n sf =>\n ({\n label: sf.label?.replace('__QUERY', entityName),\n facets: sf.facets.map(f => {\n const replaced = {\n ...f,\n bucketKey: f.bucketKey.replace('__QUERY', query),\n };\n\n if (f.displayText) {\n replaced.displayText = replaced.displayText?.replace(\n '__QUERY',\n entityName,\n );\n }\n\n return replaced;\n }),\n }) as SmartFacet,\n ),\n );\n }\n }\n\n return recommendations;\n } catch {\n return [];\n }\n }\n}\n"]}
@@ -1,55 +0,0 @@
1
- import type {
2
- SmartQueryHeuristic,
3
- KeywordFacetMap,
4
- SmartFacet,
5
- } from '../models';
6
-
7
- // If the query contains X word but Y facet isn't selected, recommend facet Y
8
- export class QueryKeywordsHeuristic implements SmartQueryHeuristic {
9
- private static readonly KEYWORDS: KeywordFacetMap = {
10
- text: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],
11
- book: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],
12
- pdf: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],
13
- epub: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],
14
- audio: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],
15
- song: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],
16
- music: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],
17
- listen: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],
18
- podcast: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],
19
- radio: [{ facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] }],
20
- stream: [
21
- { facets: [{ facetType: 'mediatype', bucketKey: 'audio' }] },
22
- { facets: [{ facetType: 'mediatype', bucketKey: 'movies' }] },
23
- ],
24
- video: [{ facets: [{ facetType: 'mediatype', bucketKey: 'movies' }] }],
25
- movie: [{ facets: [{ facetType: 'mediatype', bucketKey: 'movies' }] }],
26
- film: [{ facets: [{ facetType: 'mediatype', bucketKey: 'movies' }] }],
27
- image: [{ facets: [{ facetType: 'mediatype', bucketKey: 'image' }] }],
28
- photo: [{ facets: [{ facetType: 'mediatype', bucketKey: 'image' }] }],
29
- picture: [{ facets: [{ facetType: 'mediatype', bucketKey: 'image' }] }],
30
- software: [{ facets: [{ facetType: 'mediatype', bucketKey: 'software' }] }],
31
- app: [{ facets: [{ facetType: 'mediatype', bucketKey: 'software' }] }],
32
- program: [{ facets: [{ facetType: 'mediatype', bucketKey: 'software' }] }],
33
- game: [{ facets: [{ facetType: 'mediatype', bucketKey: 'software' }] }],
34
- etree: [{ facets: [{ facetType: 'mediatype', bucketKey: 'etree' }] }],
35
- concert: [{ facets: [{ facetType: 'mediatype', bucketKey: 'etree' }] }],
36
- 'live music': [
37
- { facets: [{ facetType: 'mediatype', bucketKey: 'etree' }] },
38
- ],
39
- dataset: [{ facets: [{ facetType: 'mediatype', bucketKey: 'data' }] }],
40
- };
41
-
42
- async getRecommendedFacets(query: string): Promise<SmartFacet[]> {
43
- const recommendations: SmartFacet[] = [];
44
-
45
- for (const [keyword, facets] of Object.entries(
46
- QueryKeywordsHeuristic.KEYWORDS,
47
- )) {
48
- if (query.includes(keyword)) {
49
- recommendations.push(...facets);
50
- }
51
- }
52
-
53
- return recommendations;
54
- }
55
- }