@internetarchive/radio-player 0.0.4-alpha.1 → 0.1.1-alpha.1

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 (69) hide show
  1. package/LICENSE +661 -661
  2. package/README.md +142 -142
  3. package/index.d.ts +15 -15
  4. package/index.js +28 -28
  5. package/lib/src/assets/img/left.d.ts +2 -2
  6. package/lib/src/assets/img/left.js +15 -15
  7. package/lib/src/assets/img/right.d.ts +2 -2
  8. package/lib/src/assets/img/right.js +15 -15
  9. package/lib/src/models/music-zone.d.ts +12 -12
  10. package/lib/src/models/music-zone.js +15 -15
  11. package/lib/src/models/radio-player-config.d.ts +26 -26
  12. package/lib/src/models/radio-player-config.js +27 -27
  13. package/lib/src/radio-player.d.ts +589 -589
  14. package/lib/src/radio-player.js +1337 -1338
  15. package/lib/src/radio-player.js.map +1 -1
  16. package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-backend.d.ts +82 -82
  17. package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-backend.js +107 -107
  18. package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-delegate.d.ts +9 -0
  19. package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-delegate.js +1 -0
  20. package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-delegate.js.map +1 -0
  21. package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-response.d.ts +48 -48
  22. package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-response.js +58 -58
  23. package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-service-interface.d.ts +16 -16
  24. package/lib/src/search-handler/search-backends/full-text-search-backend/full-text-search-service-interface.js +1 -1
  25. package/lib/src/search-handler/search-backends/local-search-backend/local-search-backend.d.ts +27 -27
  26. package/lib/src/search-handler/search-backends/local-search-backend/local-search-backend.js +42 -42
  27. package/lib/src/search-handler/search-backends/search-backend-interface.d.ts +9 -9
  28. package/lib/src/search-handler/search-backends/search-backend-interface.js +1 -1
  29. package/lib/src/search-handler/search-handler-interface.d.ts +17 -17
  30. package/lib/src/search-handler/search-handler-interface.js +1 -1
  31. package/lib/src/search-handler/search-handler.d.ts +83 -83
  32. package/lib/src/search-handler/search-handler.js +177 -177
  33. package/lib/src/search-handler/search-helper.d.ts +12 -12
  34. package/lib/src/search-handler/search-helper.js +22 -22
  35. package/lib/src/search-handler/search-index.d.ts +53 -0
  36. package/lib/src/search-handler/search-index.js +118 -0
  37. package/lib/src/search-handler/search-index.js.map +1 -0
  38. package/lib/src/search-handler/search-models.d.ts +45 -45
  39. package/lib/src/search-handler/search-models.js +49 -49
  40. package/lib/src/search-handler/transcript-index-interface.d.ts +38 -38
  41. package/lib/src/search-handler/transcript-index-interface.js +1 -1
  42. package/lib/src/search-handler/transcript-index.d.ts +53 -53
  43. package/lib/src/search-handler/transcript-index.js +80 -80
  44. package/lib/src/search-results-switcher.d.ts +58 -58
  45. package/lib/src/search-results-switcher.js +133 -133
  46. package/package.json +93 -93
  47. package/src/assets/img/left.ts +17 -17
  48. package/src/assets/img/right.ts +17 -17
  49. package/src/models/music-zone.ts +17 -17
  50. package/src/models/radio-player-config.ts +47 -47
  51. package/src/radio-player.ts +1398 -1402
  52. package/src/search-handler/search-backends/full-text-search-backend/full-text-search-backend.ts +140 -140
  53. package/src/search-handler/search-backends/full-text-search-backend/full-text-search-response.ts +110 -110
  54. package/src/search-handler/search-backends/full-text-search-backend/full-text-search-service-interface.ts +17 -17
  55. package/src/search-handler/search-backends/local-search-backend/local-search-backend.ts +50 -50
  56. package/src/search-handler/search-backends/search-backend-interface.ts +10 -10
  57. package/src/search-handler/search-handler-interface.ts +18 -18
  58. package/src/search-handler/search-handler.ts +217 -217
  59. package/src/search-handler/search-helper.ts +25 -25
  60. package/src/search-handler/search-models.ts +69 -69
  61. package/src/search-handler/transcript-index-interface.ts +42 -42
  62. package/src/search-handler/transcript-index.ts +93 -93
  63. package/src/search-results-switcher.ts +131 -131
  64. package/lib/demo/full-text-search-service.d.ts +0 -14
  65. package/lib/demo/full-text-search-service.js +0 -34
  66. package/lib/demo/full-text-search-service.js.map +0 -1
  67. package/lib/demo/radio-player-controller.d.ts +0 -41
  68. package/lib/demo/radio-player-controller.js +0 -200
  69. package/lib/demo/radio-player-controller.js.map +0 -1
@@ -1,18 +1,18 @@
1
- import { TranscriptConfig } from '@internetarchive/transcript-view';
2
-
3
- /**
4
- * Interface for defining Search Handler objects.
5
- *
6
- * Search Handlers are injected into the Radio Player to do the actual search work.
7
- */
8
- export interface SearchHandlerInterface {
9
- /**
10
- * Execute a search and return a `Promise` containing a `TranscriptConfig` that
11
- * has been modified to include the search results.
12
- *
13
- * @param {string} query
14
- * @returns {Promise<TranscriptConfig>}
15
- * @memberof SearchHandlerInterface
16
- */
17
- search(query: string): Promise<TranscriptConfig>;
18
- }
1
+ import { TranscriptConfig } from '@internetarchive/transcript-view';
2
+
3
+ /**
4
+ * Interface for defining Search Handler objects.
5
+ *
6
+ * Search Handlers are injected into the Radio Player to do the actual search work.
7
+ */
8
+ export interface SearchHandlerInterface {
9
+ /**
10
+ * Execute a search and return a `Promise` containing a `TranscriptConfig` that
11
+ * has been modified to include the search results.
12
+ *
13
+ * @param {string} query
14
+ * @returns {Promise<TranscriptConfig>}
15
+ * @memberof SearchHandlerInterface
16
+ */
17
+ search(query: string): Promise<TranscriptConfig>;
18
+ }
@@ -1,217 +1,217 @@
1
- import { TranscriptConfig, TranscriptEntryConfig } from '@internetarchive/transcript-view';
2
- import { Range, TranscriptEntryRange, SearchResult } from './search-models';
3
- import { SearchHelper } from './search-helper';
4
- import { SearchBackendInterface } from './search-backends/search-backend-interface';
5
- import { TranscriptIndexInterface } from './transcript-index-interface';
6
- import { SearchHandlerInterface } from './search-handler-interface';
7
-
8
- /**
9
- * This is the main entrypoint into transcript searching. It has a single
10
- * public method as defined by `SearchHandlerInterface`: `search(term: string)`,
11
- * that returns a `Promise<TranscriptConfig>` with a search-modified transcript.
12
- * This means the original transcript entries get merged with search results since
13
- * search results can span across transcript entries.
14
- *
15
- * It offloads the searching work to a `SearchBackendInterface` object that
16
- * is responsible for returning the search result `Range` objects based on some
17
- * backend search like the `LocalSearchBackend` or `FullTextSearchBackend`.
18
- *
19
- * It also uses a `TranscriptIndexInterface` object that is responsible for indexing
20
- * the transcipt to make reassembly much more efficient.
21
- */
22
- export class SearchHandler implements SearchHandlerInterface {
23
- /**
24
- * The SearchBackend used to executes searches.
25
- *
26
- * @private
27
- * @type {SearchBackendInterface}
28
- * @memberof SearchHandler
29
- */
30
- private searchBackend: SearchBackendInterface;
31
-
32
- /**
33
- * The TranscriptIndex to help with reassembly of the transcript.
34
- *
35
- * @private
36
- * @type {TranscriptIndexInterface}
37
- * @memberof SearchHandler
38
- */
39
- private transcriptIndex: TranscriptIndexInterface;
40
-
41
- constructor(searchBackend: SearchBackendInterface, transcriptIndex: TranscriptIndexInterface) {
42
- this.searchBackend = searchBackend;
43
- this.transcriptIndex = transcriptIndex;
44
- }
45
-
46
- /**
47
- * This is the main method in here. It takes a search term and returns a TranscriptConfig
48
- * that has been modified to insert the search results.
49
- *
50
- * @param {string} query
51
- * @returns {TranscriptConfig}
52
- * @memberof SearchHandler
53
- */
54
- async search(query: string): Promise<TranscriptConfig> {
55
- const searchSeparatedTranscript = await this.getSearchSeparatedTranscript(query);
56
- const newTranscriptEntries: TranscriptEntryConfig[] = [];
57
-
58
- let searchResultIndex = 0;
59
- let entryIdentifier = 1;
60
-
61
- searchSeparatedTranscript.forEach((entry) => {
62
- // If we encounter a match, just create a new transcript entry from it and append it.
63
- // We don't care if it crosses over multiple transcript entries since we want one match,
64
- // not multiple broken up by transcript entry.
65
- if (entry.isSearchMatch) {
66
- // find the closest source transcript to this entry
67
- const startEntry = this.transcriptIndex.getTranscriptEntryAt(entry.range.startIndex);
68
- if (!startEntry) {
69
- return;
70
- }
71
-
72
- const { range } = entry;
73
- const { endIndex } = range;
74
- const endEntry = this.transcriptIndex.getTranscriptEntryAt(endIndex) || startEntry;
75
- const newTranscriptEntry = this.createBlankTranscriptEntryConfig(startEntry.entry);
76
- newTranscriptEntry.searchMatchIndex = searchResultIndex;
77
- searchResultIndex += 1;
78
- newTranscriptEntry.rawText = entry.text;
79
- newTranscriptEntry.id = entryIdentifier;
80
- entryIdentifier += 1;
81
- newTranscriptEntry.end = endEntry.entry.end;
82
- newTranscriptEntries.push(newTranscriptEntry);
83
- return;
84
- }
85
-
86
- // Next loop through all of the source transcript entries to find the ones that intersect
87
- // with this search result. If it intersects, we take the intersected characters from the
88
- // merged transcript and make a new entry from that.
89
- this.transcriptIndex.transcriptEntryRanges.forEach((indexMap: TranscriptEntryRange) => {
90
- const intersection = SearchHelper.getIntersection(entry.range, indexMap.range);
91
- if (!intersection || intersection.length === 0) {
92
- return;
93
- }
94
-
95
- const newTranscriptEntry = this.createBlankTranscriptEntryConfig(indexMap.entry);
96
- const text = this.transcriptIndex.mergedTranscript.substring(
97
- intersection.startIndex,
98
- intersection.endIndex,
99
- );
100
- newTranscriptEntry.rawText = text.trim();
101
- newTranscriptEntry.id = entryIdentifier;
102
- entryIdentifier += 1;
103
- newTranscriptEntries.push(newTranscriptEntry);
104
- });
105
- });
106
-
107
- const newTranscript = new TranscriptConfig(newTranscriptEntries);
108
-
109
- return new Promise(resolve => resolve(newTranscript));
110
- }
111
-
112
- /**
113
- * Copy a transcript entry but leave the text and search result index empty.
114
- *
115
- * @private
116
- * @param {TranscriptEntryConfig} sourceTranscriptConfig
117
- * @returns {TranscriptEntryConfig}
118
- * @memberof SearchHandler
119
- */
120
- /* eslint-disable-next-line class-methods-use-this */
121
- private createBlankTranscriptEntryConfig(
122
- sourceTranscriptConfig: TranscriptEntryConfig,
123
- ): TranscriptEntryConfig {
124
- return new TranscriptEntryConfig(
125
- sourceTranscriptConfig.id,
126
- sourceTranscriptConfig.start,
127
- sourceTranscriptConfig.end,
128
- '',
129
- sourceTranscriptConfig.isMusic,
130
- );
131
- }
132
-
133
- /**
134
- * Search the full transcript and split up by search results and non-results. For instance,
135
- * if the full transcript is `foo bar baz boop bump snap pop` and you search for `bump`,
136
- * you'll get an array of 3 results back:
137
- * 1. `foo bar baz boop `
138
- * 2. `bump` <-- the match
139
- * 3. ` snap pop`
140
- *
141
- * This is helpful when rebuilding the transcript later to be able to identify search results.
142
- *
143
- * @private
144
- * @param {string} query
145
- * @returns {SearchResult[]}
146
- * @memberof SearchHandler
147
- */
148
- async getSearchSeparatedTranscript(query: string): Promise<SearchResult[]> {
149
- const searchRanges: Range[] = await this.searchBackend.getSearchRanges(query);
150
- const { mergedTranscript } = this.transcriptIndex;
151
-
152
- // if there's no search results, just return a single SearchResult that is the full
153
- // transcript marked as not a match.
154
- if (searchRanges.length === 0) {
155
- const range = new Range(0, mergedTranscript.length);
156
- return new Promise(resolve => resolve([new SearchResult(range, mergedTranscript, false)]));
157
- }
158
-
159
-
160
- // Sort the search range results from start to end
161
- // The search engine may return results in any order but while processing the results here,
162
- // we are going from start to finish. If the search results are out of order, it rebuilds
163
- // incorrect blocks of search results.
164
- searchRanges.sort((a: Range, b: Range) => (a.startIndex - b.startIndex));
165
-
166
- const transcriptEntries: SearchResult[] = [];
167
- let startIndex = 0;
168
-
169
- // Loop through all of the search result ranges and construct an array
170
- // of SearchResult entries.
171
- // For instance, if the full transcript is `foo bar baz boop bump snip snap`
172
- // and you search for `baz`, we'll only have a single search range: Range(8, 11).
173
- // We then take the text leading up to that range and store it as the "non result"
174
- // so we now have Range(0, 7) and Range(8, 11).
175
- // If there were more search results, we would continue from index 12 to build
176
- // the next range to the next match.
177
- // Finally once all the matches are finished, tack on the remaining text to the end.
178
- searchRanges.forEach((searchRange) => {
179
- // first find the "non-result" range, which is the current `startIndex` up to
180
- // `range.startIndex` (the start of the search result)
181
- const nonResultRange = new Range(startIndex, searchRange.startIndex);
182
- const nonResultEntry = this.getSearchResult(nonResultRange, false);
183
- transcriptEntries.push(nonResultEntry);
184
-
185
- // get the search result match from the merged transcript
186
- // using the current search range
187
- const searchResultEntry = this.getSearchResult(searchRange, true);
188
- transcriptEntries.push(searchResultEntry);
189
-
190
- startIndex = searchRange.endIndex;
191
- });
192
-
193
- // add any remaining characters as the last final entry in the results
194
- const finalResultRange = new Range(startIndex, mergedTranscript.length);
195
- const finalResultEntry = this.getSearchResult(finalResultRange, false);
196
- transcriptEntries.push(finalResultEntry);
197
-
198
- return new Promise(resolve => resolve(transcriptEntries));
199
- }
200
-
201
- /**
202
- * Generate a SearchResult entry from a given Range and annotate it
203
- * with whether or not it is a search result match
204
- *
205
- * @private
206
- * @param {Range} range
207
- * @param {boolean} isSearchResult
208
- * @returns {SearchResult}
209
- * @memberof SearchHandler
210
- */
211
- private getSearchResult(range: Range, isSearchResult: boolean): SearchResult {
212
- const { mergedTranscript } = this.transcriptIndex;
213
- const text = mergedTranscript.substring(range.startIndex, range.endIndex);
214
- const searchResult = new SearchResult(range, text, isSearchResult);
215
- return searchResult;
216
- }
217
- }
1
+ import { TranscriptConfig, TranscriptEntryConfig } from '@internetarchive/transcript-view';
2
+ import { Range, TranscriptEntryRange, SearchResult } from './search-models';
3
+ import { SearchHelper } from './search-helper';
4
+ import { SearchBackendInterface } from './search-backends/search-backend-interface';
5
+ import { TranscriptIndexInterface } from './transcript-index-interface';
6
+ import { SearchHandlerInterface } from './search-handler-interface';
7
+
8
+ /**
9
+ * This is the main entrypoint into transcript searching. It has a single
10
+ * public method as defined by `SearchHandlerInterface`: `search(term: string)`,
11
+ * that returns a `Promise<TranscriptConfig>` with a search-modified transcript.
12
+ * This means the original transcript entries get merged with search results since
13
+ * search results can span across transcript entries.
14
+ *
15
+ * It offloads the searching work to a `SearchBackendInterface` object that
16
+ * is responsible for returning the search result `Range` objects based on some
17
+ * backend search like the `LocalSearchBackend` or `FullTextSearchBackend`.
18
+ *
19
+ * It also uses a `TranscriptIndexInterface` object that is responsible for indexing
20
+ * the transcipt to make reassembly much more efficient.
21
+ */
22
+ export class SearchHandler implements SearchHandlerInterface {
23
+ /**
24
+ * The SearchBackend used to executes searches.
25
+ *
26
+ * @private
27
+ * @type {SearchBackendInterface}
28
+ * @memberof SearchHandler
29
+ */
30
+ private searchBackend: SearchBackendInterface;
31
+
32
+ /**
33
+ * The TranscriptIndex to help with reassembly of the transcript.
34
+ *
35
+ * @private
36
+ * @type {TranscriptIndexInterface}
37
+ * @memberof SearchHandler
38
+ */
39
+ private transcriptIndex: TranscriptIndexInterface;
40
+
41
+ constructor(searchBackend: SearchBackendInterface, transcriptIndex: TranscriptIndexInterface) {
42
+ this.searchBackend = searchBackend;
43
+ this.transcriptIndex = transcriptIndex;
44
+ }
45
+
46
+ /**
47
+ * This is the main method in here. It takes a search term and returns a TranscriptConfig
48
+ * that has been modified to insert the search results.
49
+ *
50
+ * @param {string} query
51
+ * @returns {TranscriptConfig}
52
+ * @memberof SearchHandler
53
+ */
54
+ async search(query: string): Promise<TranscriptConfig> {
55
+ const searchSeparatedTranscript = await this.getSearchSeparatedTranscript(query);
56
+ const newTranscriptEntries: TranscriptEntryConfig[] = [];
57
+
58
+ let searchResultIndex = 0;
59
+ let entryIdentifier = 1;
60
+
61
+ searchSeparatedTranscript.forEach((entry) => {
62
+ // If we encounter a match, just create a new transcript entry from it and append it.
63
+ // We don't care if it crosses over multiple transcript entries since we want one match,
64
+ // not multiple broken up by transcript entry.
65
+ if (entry.isSearchMatch) {
66
+ // find the closest source transcript to this entry
67
+ const startEntry = this.transcriptIndex.getTranscriptEntryAt(entry.range.startIndex);
68
+ if (!startEntry) {
69
+ return;
70
+ }
71
+
72
+ const { range } = entry;
73
+ const { endIndex } = range;
74
+ const endEntry = this.transcriptIndex.getTranscriptEntryAt(endIndex) || startEntry;
75
+ const newTranscriptEntry = this.createBlankTranscriptEntryConfig(startEntry.entry);
76
+ newTranscriptEntry.searchMatchIndex = searchResultIndex;
77
+ searchResultIndex += 1;
78
+ newTranscriptEntry.rawText = entry.text;
79
+ newTranscriptEntry.id = entryIdentifier;
80
+ entryIdentifier += 1;
81
+ newTranscriptEntry.end = endEntry.entry.end;
82
+ newTranscriptEntries.push(newTranscriptEntry);
83
+ return;
84
+ }
85
+
86
+ // Next loop through all of the source transcript entries to find the ones that intersect
87
+ // with this search result. If it intersects, we take the intersected characters from the
88
+ // merged transcript and make a new entry from that.
89
+ this.transcriptIndex.transcriptEntryRanges.forEach((indexMap: TranscriptEntryRange) => {
90
+ const intersection = SearchHelper.getIntersection(entry.range, indexMap.range);
91
+ if (!intersection || intersection.length === 0) {
92
+ return;
93
+ }
94
+
95
+ const newTranscriptEntry = this.createBlankTranscriptEntryConfig(indexMap.entry);
96
+ const text = this.transcriptIndex.mergedTranscript.substring(
97
+ intersection.startIndex,
98
+ intersection.endIndex,
99
+ );
100
+ newTranscriptEntry.rawText = text.trim();
101
+ newTranscriptEntry.id = entryIdentifier;
102
+ entryIdentifier += 1;
103
+ newTranscriptEntries.push(newTranscriptEntry);
104
+ });
105
+ });
106
+
107
+ const newTranscript = new TranscriptConfig(newTranscriptEntries);
108
+
109
+ return new Promise(resolve => resolve(newTranscript));
110
+ }
111
+
112
+ /**
113
+ * Copy a transcript entry but leave the text and search result index empty.
114
+ *
115
+ * @private
116
+ * @param {TranscriptEntryConfig} sourceTranscriptConfig
117
+ * @returns {TranscriptEntryConfig}
118
+ * @memberof SearchHandler
119
+ */
120
+ /* eslint-disable-next-line class-methods-use-this */
121
+ private createBlankTranscriptEntryConfig(
122
+ sourceTranscriptConfig: TranscriptEntryConfig,
123
+ ): TranscriptEntryConfig {
124
+ return new TranscriptEntryConfig(
125
+ sourceTranscriptConfig.id,
126
+ sourceTranscriptConfig.start,
127
+ sourceTranscriptConfig.end,
128
+ '',
129
+ sourceTranscriptConfig.isMusic,
130
+ );
131
+ }
132
+
133
+ /**
134
+ * Search the full transcript and split up by search results and non-results. For instance,
135
+ * if the full transcript is `foo bar baz boop bump snap pop` and you search for `bump`,
136
+ * you'll get an array of 3 results back:
137
+ * 1. `foo bar baz boop `
138
+ * 2. `bump` <-- the match
139
+ * 3. ` snap pop`
140
+ *
141
+ * This is helpful when rebuilding the transcript later to be able to identify search results.
142
+ *
143
+ * @private
144
+ * @param {string} query
145
+ * @returns {SearchResult[]}
146
+ * @memberof SearchHandler
147
+ */
148
+ async getSearchSeparatedTranscript(query: string): Promise<SearchResult[]> {
149
+ const searchRanges: Range[] = await this.searchBackend.getSearchRanges(query);
150
+ const { mergedTranscript } = this.transcriptIndex;
151
+
152
+ // if there's no search results, just return a single SearchResult that is the full
153
+ // transcript marked as not a match.
154
+ if (searchRanges.length === 0) {
155
+ const range = new Range(0, mergedTranscript.length);
156
+ return new Promise(resolve => resolve([new SearchResult(range, mergedTranscript, false)]));
157
+ }
158
+
159
+
160
+ // Sort the search range results from start to end
161
+ // The search engine may return results in any order but while processing the results here,
162
+ // we are going from start to finish. If the search results are out of order, it rebuilds
163
+ // incorrect blocks of search results.
164
+ searchRanges.sort((a: Range, b: Range) => (a.startIndex - b.startIndex));
165
+
166
+ const transcriptEntries: SearchResult[] = [];
167
+ let startIndex = 0;
168
+
169
+ // Loop through all of the search result ranges and construct an array
170
+ // of SearchResult entries.
171
+ // For instance, if the full transcript is `foo bar baz boop bump snip snap`
172
+ // and you search for `baz`, we'll only have a single search range: Range(8, 11).
173
+ // We then take the text leading up to that range and store it as the "non result"
174
+ // so we now have Range(0, 7) and Range(8, 11).
175
+ // If there were more search results, we would continue from index 12 to build
176
+ // the next range to the next match.
177
+ // Finally once all the matches are finished, tack on the remaining text to the end.
178
+ searchRanges.forEach((searchRange) => {
179
+ // first find the "non-result" range, which is the current `startIndex` up to
180
+ // `range.startIndex` (the start of the search result)
181
+ const nonResultRange = new Range(startIndex, searchRange.startIndex);
182
+ const nonResultEntry = this.getSearchResult(nonResultRange, false);
183
+ transcriptEntries.push(nonResultEntry);
184
+
185
+ // get the search result match from the merged transcript
186
+ // using the current search range
187
+ const searchResultEntry = this.getSearchResult(searchRange, true);
188
+ transcriptEntries.push(searchResultEntry);
189
+
190
+ startIndex = searchRange.endIndex;
191
+ });
192
+
193
+ // add any remaining characters as the last final entry in the results
194
+ const finalResultRange = new Range(startIndex, mergedTranscript.length);
195
+ const finalResultEntry = this.getSearchResult(finalResultRange, false);
196
+ transcriptEntries.push(finalResultEntry);
197
+
198
+ return new Promise(resolve => resolve(transcriptEntries));
199
+ }
200
+
201
+ /**
202
+ * Generate a SearchResult entry from a given Range and annotate it
203
+ * with whether or not it is a search result match
204
+ *
205
+ * @private
206
+ * @param {Range} range
207
+ * @param {boolean} isSearchResult
208
+ * @returns {SearchResult}
209
+ * @memberof SearchHandler
210
+ */
211
+ private getSearchResult(range: Range, isSearchResult: boolean): SearchResult {
212
+ const { mergedTranscript } = this.transcriptIndex;
213
+ const text = mergedTranscript.substring(range.startIndex, range.endIndex);
214
+ const searchResult = new SearchResult(range, text, isSearchResult);
215
+ return searchResult;
216
+ }
217
+ }
@@ -1,25 +1,25 @@
1
- import { Range } from './search-models';
2
-
3
- export class SearchHelper {
4
- /**
5
- * Get the intersection of two ranges and return a range or undefined if they do not intersect
6
- *
7
- * @param range1
8
- * @param range2
9
- *
10
- * @returns Range|undefined
11
- */
12
- static getIntersection(range1: Range, range2: Range): Range | undefined {
13
- // get the range with the smaller starting point (min) and greater start (max)
14
- const minRange: Range = range1.startIndex < range2.startIndex ? range1 : range2;
15
- const maxRange = minRange === range1 ? range2 : range1;
16
-
17
- // min ends before max starts -> no intersection
18
- if (minRange.endIndex < maxRange.startIndex) {
19
- return undefined; // the ranges don't intersect
20
- }
21
-
22
- const endIndex = minRange.endIndex < maxRange.endIndex ? minRange.endIndex : maxRange.endIndex;
23
- return new Range(maxRange.startIndex, endIndex);
24
- }
25
- }
1
+ import { Range } from './search-models';
2
+
3
+ export class SearchHelper {
4
+ /**
5
+ * Get the intersection of two ranges and return a range or undefined if they do not intersect
6
+ *
7
+ * @param range1
8
+ * @param range2
9
+ *
10
+ * @returns Range|undefined
11
+ */
12
+ static getIntersection(range1: Range, range2: Range): Range | undefined {
13
+ // get the range with the smaller starting point (min) and greater start (max)
14
+ const minRange: Range = range1.startIndex < range2.startIndex ? range1 : range2;
15
+ const maxRange = minRange === range1 ? range2 : range1;
16
+
17
+ // min ends before max starts -> no intersection
18
+ if (minRange.endIndex < maxRange.startIndex) {
19
+ return undefined; // the ranges don't intersect
20
+ }
21
+
22
+ const endIndex = minRange.endIndex < maxRange.endIndex ? minRange.endIndex : maxRange.endIndex;
23
+ return new Range(maxRange.startIndex, endIndex);
24
+ }
25
+ }
@@ -1,69 +1,69 @@
1
- import { TranscriptEntryConfig } from '@internetarchive/transcript-view';
2
-
3
- /**
4
- * A model to store the start and end indices for a given context.
5
- * This is used for augmenting the source transcript entries (`TranscriptEntryRange`)
6
- * as well as the search result entries (`SearchResult`) below.
7
- *
8
- * @class Range
9
- */
10
- class Range {
11
- startIndex: number;
12
-
13
- endIndex: number;
14
-
15
- get length(): number {
16
- return Math.abs(this.endIndex - this.startIndex);
17
- }
18
-
19
- constructor(startIndex: number, endIndex: number) {
20
- this.startIndex = startIndex;
21
- this.endIndex = endIndex;
22
- }
23
- }
24
-
25
- /**
26
- * This class augments the transcript entry with the range of the characters
27
- * in the merged transcript. This is useful for more rapidly splitting up and
28
- * restoring the transcript entries from the transforms that happen during the search.
29
- *
30
- * @class TranscriptIndexMap
31
- */
32
- class TranscriptEntryRange {
33
- entry: TranscriptEntryConfig;
34
-
35
- range: Range;
36
-
37
- constructor(entry: TranscriptEntryConfig, range: Range) {
38
- this.entry = entry;
39
- this.range = range;
40
- }
41
- }
42
-
43
- /**
44
- * The first step in converting the search results back to a usable transcript
45
- * is to break up the overall merged transcript into search results and non-search-results
46
- * sections. This will allow us to more easily break it up into its original transcript
47
- * chunks in a subsequent process.
48
- *
49
- * This class is a container to hold those chunks. They each have a start and end index
50
- * from their spot in the merged transcript, the text from that chunk, and whether that
51
- * chunk was a search match or just regular text.
52
- *
53
- * @class SearchSeparatedTranscriptEntry
54
- */
55
- class SearchResult {
56
- range: Range;
57
-
58
- text: string;
59
-
60
- isSearchMatch: boolean;
61
-
62
- constructor(range: Range, text: string, isSearchMatch: boolean) {
63
- this.range = range;
64
- this.text = text;
65
- this.isSearchMatch = isSearchMatch;
66
- }
67
- }
68
-
69
- export { Range, TranscriptEntryRange, SearchResult };
1
+ import { TranscriptEntryConfig } from '@internetarchive/transcript-view';
2
+
3
+ /**
4
+ * A model to store the start and end indices for a given context.
5
+ * This is used for augmenting the source transcript entries (`TranscriptEntryRange`)
6
+ * as well as the search result entries (`SearchResult`) below.
7
+ *
8
+ * @class Range
9
+ */
10
+ class Range {
11
+ startIndex: number;
12
+
13
+ endIndex: number;
14
+
15
+ get length(): number {
16
+ return Math.abs(this.endIndex - this.startIndex);
17
+ }
18
+
19
+ constructor(startIndex: number, endIndex: number) {
20
+ this.startIndex = startIndex;
21
+ this.endIndex = endIndex;
22
+ }
23
+ }
24
+
25
+ /**
26
+ * This class augments the transcript entry with the range of the characters
27
+ * in the merged transcript. This is useful for more rapidly splitting up and
28
+ * restoring the transcript entries from the transforms that happen during the search.
29
+ *
30
+ * @class TranscriptIndexMap
31
+ */
32
+ class TranscriptEntryRange {
33
+ entry: TranscriptEntryConfig;
34
+
35
+ range: Range;
36
+
37
+ constructor(entry: TranscriptEntryConfig, range: Range) {
38
+ this.entry = entry;
39
+ this.range = range;
40
+ }
41
+ }
42
+
43
+ /**
44
+ * The first step in converting the search results back to a usable transcript
45
+ * is to break up the overall merged transcript into search results and non-search-results
46
+ * sections. This will allow us to more easily break it up into its original transcript
47
+ * chunks in a subsequent process.
48
+ *
49
+ * This class is a container to hold those chunks. They each have a start and end index
50
+ * from their spot in the merged transcript, the text from that chunk, and whether that
51
+ * chunk was a search match or just regular text.
52
+ *
53
+ * @class SearchSeparatedTranscriptEntry
54
+ */
55
+ class SearchResult {
56
+ range: Range;
57
+
58
+ text: string;
59
+
60
+ isSearchMatch: boolean;
61
+
62
+ constructor(range: Range, text: string, isSearchMatch: boolean) {
63
+ this.range = range;
64
+ this.text = text;
65
+ this.isSearchMatch = isSearchMatch;
66
+ }
67
+ }
68
+
69
+ export { Range, TranscriptEntryRange, SearchResult };