123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- export const extractTextItems = async (
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- getPage: GetPageType,
- ): Promise<string[]> => {
- const page = await getPage();
- if (!page) return [];
- let textContent = await page.getTextContent({
- normalizeWhitespace: true,
- });
- textContent = textContent.items;
- const strBuf = [];
- for (let j = 0, len = textContent.length; j < len; j += 1) {
- // add whitespace in front if start character is Uppercase
- strBuf.push(textContent[j].str);
- // if (
- // textContent[j].str.match(/^[A-Z]/) &&
- // j > 0 &&
- // textContent[j - 1].str !== ' '
- // ) {
- // strBuf.push(` ${textContent[j].str}`);
- // } else {
- // strBuf.push(textContent[j].str);
- // }
- }
- return strBuf;
- };
- export const convertMatches = (
- queryString: string,
- matchIndex: number,
- textContentItem: string[],
- ): Record<string, { divIdx: number; offset: number }> => {
- let i = 0;
- let iIndex = 0;
- const end = textContentItem.length - 1;
- const queryLen = queryString.length;
- // Loop over the divIdxs.
- while (i !== end && matchIndex >= iIndex + textContentItem[i].length) {
- iIndex += textContentItem[i].length;
- i += 1;
- }
- if (i === textContentItem.length) {
- console.error('Could not find a matching mapping');
- }
- const match: Record<string, { divIdx: number; offset: number }> = {
- begin: {
- divIdx: i,
- offset: matchIndex - iIndex,
- },
- };
- // Calculate the end position.
- // eslint-disable-next-line no-param-reassign
- matchIndex += queryLen;
- // Somewhat the same array as above, but use > instead of >= to get
- // the end position right.
- while (i !== end && matchIndex > iIndex + textContentItem[i].length) {
- iIndex += textContentItem[i].length;
- i += 1;
- }
- match.end = {
- divIdx: i,
- offset: matchIndex - iIndex,
- };
- return match;
- };
- const appendTextToDiv = async (
- domElements: HTMLElement[],
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- getPage: GetPageType,
- divIdx: number,
- fromOffset: number,
- toOffset: number | undefined,
- highlight: boolean,
- id: string,
- queryStr = '',
- ): Promise<void> => {
- const textContentItem = await extractTextItems(getPage);
- const domElement = domElements[divIdx];
- const content = textContentItem[divIdx].substring(fromOffset, toOffset);
- const node = document.createTextNode(
- queryStr ? content.replace(queryStr, '') : content,
- );
- const span = document.createElement('span');
- if (highlight) {
- span.setAttribute('class', id);
- span.style.backgroundColor = 'rgba(255, 211, 0, 0.7)';
- span.appendChild(node);
- domElement.appendChild(span);
- } else {
- domElement.appendChild(node);
- }
- };
- const beginText = async (
- domElements: HTMLElement[],
- getPage: GetPageType,
- begin: { divIdx: number; offset: number },
- queryStr: string,
- ): Promise<void> => {
- const { divIdx } = begin;
- const domElement = domElements[divIdx];
- if (domElement) {
- // eslint-disable-next-line no-param-reassign
- domElement.textContent = '';
- appendTextToDiv(
- domElements,
- getPage,
- divIdx,
- 0,
- begin.offset,
- false,
- '',
- queryStr,
- );
- }
- };
- export const renderMatches = async (
- domElements: HTMLElement[],
- getPage: GetPageType,
- matchIndex: number,
- queryStr: string,
- id: string,
- ): Promise<void> => {
- const textContentItem = await extractTextItems(getPage);
- const { begin, end } = convertMatches(queryStr, matchIndex, textContentItem);
- beginText(domElements, getPage, begin, queryStr);
- if (begin.divIdx === end.divIdx) {
- appendTextToDiv(
- domElements,
- getPage,
- begin.divIdx,
- begin.offset,
- end.offset,
- true,
- id,
- );
- } else {
- for (let i = begin.divIdx; i <= end.divIdx; i += 1) {
- switch (i) {
- case begin.divIdx:
- appendTextToDiv(
- domElements,
- getPage,
- begin.divIdx,
- begin.offset,
- undefined,
- true,
- id,
- );
- break;
- case end.divIdx:
- beginText(
- domElements,
- getPage,
- { divIdx: end.divIdx, offset: 0 },
- queryStr,
- );
- appendTextToDiv(
- domElements,
- getPage,
- end.divIdx,
- 0,
- end.offset,
- true,
- id,
- );
- break;
- default: {
- beginText(domElements, getPage, { divIdx: i, offset: 0 }, queryStr);
- appendTextToDiv(domElements, getPage, i, 0, undefined, true, id);
- break;
- }
- }
- }
- }
- };
|