@pallasoft/ps-file-components 2.3.0 → 2.4.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 (162) hide show
  1. package/dist/components/ps-file-icon-button.js +1 -1
  2. package/dist/components/ps-file-list.js +1 -1
  3. package/dist/components/ps-file-picker.js +1 -1
  4. package/dist/components/ps-file-search-bar.d.ts +10 -0
  5. package/dist/components/ps-file-search-bar.js +25 -0
  6. package/dist/components/ps-file-viewer-content.js +9 -0
  7. package/dist/components/ps-file-viewer-pane.d.ts +1 -1
  8. package/dist/components/ps-file-viewer-pane.js +26 -2
  9. package/dist/components/ps-file-viewer.js +11 -23
  10. package/dist/components/ps-html-document.d.ts +8 -0
  11. package/dist/components/ps-html-document.js +23 -0
  12. package/dist/components/ps-html-viewer.d.ts +2 -0
  13. package/dist/components/ps-html-viewer.js +17 -0
  14. package/dist/components/ps-image-text-highlights.d.ts +9 -0
  15. package/dist/components/ps-image-text-highlights.js +31 -0
  16. package/dist/components/ps-image-viewer.d.ts +1 -1
  17. package/dist/components/ps-image-viewer.js +11 -2
  18. package/dist/components/ps-pdf-page.js +1 -1
  19. package/dist/components/ps-pdf-viewer.js +6 -2
  20. package/dist/components/ps-sheet-viewer.d.ts +2 -0
  21. package/dist/components/ps-sheet-viewer.js +26 -0
  22. package/dist/components/ps-table-view.d.ts +7 -0
  23. package/dist/components/ps-table-view.js +17 -0
  24. package/dist/components/ps-text-viewer.js +7 -14
  25. package/dist/components/ps-upload-row.js +1 -1
  26. package/dist/components/ps-word-viewer.d.ts +2 -0
  27. package/dist/components/ps-word-viewer.js +17 -0
  28. package/dist/constants/ps-file-kind-icons.js +3 -0
  29. package/dist/constants/ps-file-kind.d.ts +3 -0
  30. package/dist/constants/ps-file-kind.js +3 -0
  31. package/dist/constants/ps-file-type-config.d.ts +6 -1
  32. package/dist/constants/ps-file-type-config.js +16 -2
  33. package/dist/constants/ps-file-viewer-config.d.ts +1 -0
  34. package/dist/constants/ps-file-viewer-config.js +1 -0
  35. package/dist/constants/ps-file-viewer-kinds.d.ts +2 -2
  36. package/dist/constants/ps-file-viewer-kinds.js +17 -2
  37. package/dist/constants/ps-file-viewer-labels.d.ts +3 -0
  38. package/dist/constants/ps-file-viewer-labels.js +3 -0
  39. package/dist/constants/ps-html-sanitize-config.d.ts +8 -0
  40. package/dist/constants/ps-html-sanitize-config.js +26 -0
  41. package/dist/esm/components/ps-file-icon-button.js +1 -1
  42. package/dist/esm/components/ps-file-list.js +1 -1
  43. package/dist/esm/components/ps-file-picker.js +1 -1
  44. package/dist/esm/components/ps-file-search-bar.js +21 -0
  45. package/dist/esm/components/ps-file-viewer-content.js +9 -0
  46. package/dist/esm/components/ps-file-viewer-pane.js +27 -3
  47. package/dist/esm/components/ps-file-viewer.js +13 -25
  48. package/dist/esm/components/ps-html-document.js +19 -0
  49. package/dist/esm/components/ps-html-viewer.js +13 -0
  50. package/dist/esm/components/ps-image-text-highlights.js +27 -0
  51. package/dist/esm/components/ps-image-viewer.js +13 -4
  52. package/dist/esm/components/ps-pdf-page.js +1 -1
  53. package/dist/esm/components/ps-pdf-viewer.js +6 -2
  54. package/dist/esm/components/ps-sheet-viewer.js +22 -0
  55. package/dist/esm/components/ps-table-view.js +13 -0
  56. package/dist/esm/components/ps-text-viewer.js +7 -14
  57. package/dist/esm/components/ps-upload-row.js +1 -1
  58. package/dist/esm/components/ps-word-viewer.js +13 -0
  59. package/dist/esm/constants/ps-file-kind-icons.js +3 -0
  60. package/dist/esm/constants/ps-file-kind.js +3 -0
  61. package/dist/esm/constants/ps-file-type-config.js +16 -2
  62. package/dist/esm/constants/ps-file-viewer-config.js +1 -0
  63. package/dist/esm/constants/ps-file-viewer-kinds.js +17 -2
  64. package/dist/esm/constants/ps-file-viewer-labels.js +3 -0
  65. package/dist/esm/constants/ps-html-sanitize-config.js +23 -0
  66. package/dist/esm/hooks/use-ps-file-search.js +37 -0
  67. package/dist/esm/hooks/use-ps-file-text.js +4 -19
  68. package/dist/esm/hooks/use-ps-find-shortcut.js +23 -0
  69. package/dist/esm/hooks/use-ps-loaded-file.js +19 -0
  70. package/dist/esm/index.js +33 -0
  71. package/dist/esm/models/ps-file-search-state.js +1 -0
  72. package/dist/esm/models/ps-html-highlight-result.js +1 -0
  73. package/dist/esm/models/ps-html-text-node.js +1 -0
  74. package/dist/esm/models/ps-image-match.js +1 -0
  75. package/dist/esm/models/ps-image-text-box.js +1 -0
  76. package/dist/esm/models/ps-image-text-layer.js +1 -0
  77. package/dist/esm/models/ps-image-text-word.js +1 -0
  78. package/dist/esm/models/ps-item-match-part.js +1 -0
  79. package/dist/esm/models/ps-item-match.js +1 -0
  80. package/dist/esm/models/ps-loaded-file-state.js +1 -0
  81. package/dist/esm/models/ps-normalized-text.js +1 -0
  82. package/dist/esm/models/ps-pdf-text-item.js +1 -0
  83. package/dist/esm/models/ps-pdf-viewport-like.js +1 -0
  84. package/dist/esm/models/ps-search-item.js +1 -0
  85. package/dist/esm/models/ps-sheet-data.js +1 -0
  86. package/dist/esm/services/ps-file-fetch-service.js +14 -0
  87. package/dist/esm/services/ps-file-search-service.js +15 -0
  88. package/dist/esm/services/ps-file-type-service.js +12 -1
  89. package/dist/esm/services/ps-html-file-service.js +7 -0
  90. package/dist/esm/services/ps-html-service.js +83 -0
  91. package/dist/esm/services/ps-image-text-service.js +6 -0
  92. package/dist/esm/services/ps-label-service.js +5 -0
  93. package/dist/esm/services/ps-pdf-service.js +39 -16
  94. package/dist/esm/services/ps-sheet-service.js +23 -0
  95. package/dist/esm/services/ps-text-search-service.js +21 -26
  96. package/dist/esm/services/ps-word-service.js +15 -0
  97. package/dist/hooks/use-ps-file-search.d.ts +2 -0
  98. package/dist/hooks/use-ps-file-search.js +41 -0
  99. package/dist/hooks/use-ps-file-text.js +4 -19
  100. package/dist/hooks/use-ps-find-shortcut.d.ts +2 -0
  101. package/dist/hooks/use-ps-find-shortcut.js +27 -0
  102. package/dist/hooks/use-ps-loaded-file.d.ts +2 -0
  103. package/dist/hooks/use-ps-loaded-file.js +23 -0
  104. package/dist/index.d.ts +33 -0
  105. package/dist/index.js +33 -0
  106. package/dist/models/ps-file-search-state.d.ts +13 -0
  107. package/dist/models/ps-file-search-state.js +2 -0
  108. package/dist/models/ps-file-viewer-pane-props.d.ts +3 -1
  109. package/dist/models/ps-html-highlight-result.d.ts +4 -0
  110. package/dist/models/ps-html-highlight-result.js +2 -0
  111. package/dist/models/ps-html-text-node.d.ts +4 -0
  112. package/dist/models/ps-html-text-node.js +2 -0
  113. package/dist/models/ps-image-match.d.ts +7 -0
  114. package/dist/models/ps-image-match.js +2 -0
  115. package/dist/models/ps-image-text-box.d.ts +2 -0
  116. package/dist/models/ps-image-text-box.js +2 -0
  117. package/dist/models/ps-image-text-layer.d.ts +2 -0
  118. package/dist/models/ps-image-text-layer.js +2 -0
  119. package/dist/models/ps-image-text-word.d.ts +2 -0
  120. package/dist/models/ps-image-text-word.js +2 -0
  121. package/dist/models/ps-item-match-part.d.ts +2 -0
  122. package/dist/models/ps-item-match-part.js +2 -0
  123. package/dist/models/ps-item-match.d.ts +2 -0
  124. package/dist/models/ps-item-match.js +2 -0
  125. package/dist/models/ps-loaded-file-state.d.ts +4 -0
  126. package/dist/models/ps-loaded-file-state.js +2 -0
  127. package/dist/models/ps-normalized-text.d.ts +2 -0
  128. package/dist/models/ps-normalized-text.js +2 -0
  129. package/dist/models/ps-pdf-match.d.ts +1 -0
  130. package/dist/models/ps-pdf-text-item.d.ts +7 -0
  131. package/dist/models/ps-pdf-text-item.js +2 -0
  132. package/dist/models/ps-pdf-viewport-like.d.ts +5 -0
  133. package/dist/models/ps-pdf-viewport-like.js +2 -0
  134. package/dist/models/ps-search-item.d.ts +2 -0
  135. package/dist/models/ps-search-item.js +2 -0
  136. package/dist/models/ps-sheet-data.d.ts +4 -0
  137. package/dist/models/ps-sheet-data.js +2 -0
  138. package/dist/models/ps-text-match.d.ts +2 -4
  139. package/dist/models/ps-text-segment.d.ts +2 -5
  140. package/dist/models/ps-viewer-file.d.ts +2 -0
  141. package/dist/services/ps-file-fetch-service.d.ts +5 -0
  142. package/dist/services/ps-file-fetch-service.js +18 -0
  143. package/dist/services/ps-file-search-service.d.ts +5 -0
  144. package/dist/services/ps-file-search-service.js +19 -0
  145. package/dist/services/ps-file-type-service.js +12 -1
  146. package/dist/services/ps-html-file-service.d.ts +3 -0
  147. package/dist/services/ps-html-file-service.js +11 -0
  148. package/dist/services/ps-html-service.d.ts +7 -0
  149. package/dist/services/ps-html-service.js +120 -0
  150. package/dist/services/ps-image-text-service.d.ts +5 -0
  151. package/dist/services/ps-image-text-service.js +10 -0
  152. package/dist/services/ps-label-service.d.ts +3 -0
  153. package/dist/services/ps-label-service.js +9 -0
  154. package/dist/services/ps-pdf-service.d.ts +3 -0
  155. package/dist/services/ps-pdf-service.js +39 -16
  156. package/dist/services/ps-sheet-service.d.ts +5 -0
  157. package/dist/services/ps-sheet-service.js +60 -0
  158. package/dist/services/ps-text-search-service.d.ts +7 -0
  159. package/dist/services/ps-text-search-service.js +21 -26
  160. package/dist/services/ps-word-service.d.ts +3 -0
  161. package/dist/services/ps-word-service.js +52 -0
  162. package/package.json +6 -3
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export interface PsLoadedFileState<T> {
2
+ hasFailed: boolean;
3
+ value: T | null;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import type { TextNormalized } from '@pallasoft/ps-utilities';
2
+ export type PsNormalizedText = TextNormalized;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,6 +1,7 @@
1
1
  export interface PsPdfMatch {
2
2
  height: number;
3
3
  left: number;
4
+ matchIndex: number;
4
5
  pageNumber: number;
5
6
  top: number;
6
7
  width: number;
@@ -0,0 +1,7 @@
1
+ export interface PsPdfTextItem {
2
+ hasEOL: boolean;
3
+ height: number;
4
+ str: string;
5
+ transform: number[];
6
+ width: number;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ export interface PsPdfViewportLike {
2
+ convertToViewportPoint: (x: number, y: number) => number[];
3
+ height: number;
4
+ width: number;
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import type { TextSearchItem } from '@pallasoft/ps-utilities';
2
+ export type PsSearchItem = TextSearchItem;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export interface PsSheetData {
2
+ name: string;
3
+ rows: string[][];
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,2 @@
1
- export interface PsTextMatch {
2
- end: number;
3
- start: number;
4
- }
1
+ import type { TextMatch } from '@pallasoft/ps-utilities';
2
+ export type PsTextMatch = TextMatch;
@@ -1,5 +1,2 @@
1
- export interface PsTextSegment {
2
- isMatch: boolean;
3
- matchIndex: number | null;
4
- text: string;
5
- }
1
+ import type { TextSegment } from '@pallasoft/ps-utilities';
2
+ export type PsTextSegment = TextSegment;
@@ -1,3 +1,4 @@
1
+ import type { PsImageTextLayer } from './ps-image-text-layer';
1
2
  export interface PsViewerFile {
2
3
  contentType: string;
3
4
  createdAt?: string;
@@ -5,5 +6,6 @@ export interface PsViewerFile {
5
6
  id: string;
6
7
  name: string;
7
8
  sizeBytes?: number;
9
+ textLayer?: PsImageTextLayer;
8
10
  url: string;
9
11
  }
@@ -0,0 +1,5 @@
1
+ export declare class PsFileFetchService {
2
+ static response(url: string, signal: AbortSignal): Promise<Response>;
3
+ static text(url: string, signal: AbortSignal): Promise<string>;
4
+ static buffer(url: string, signal: AbortSignal): Promise<ArrayBuffer>;
5
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsFileFetchService = void 0;
4
+ class PsFileFetchService {
5
+ static async response(url, signal) {
6
+ const response = await fetch(url, { credentials: 'include', signal });
7
+ if (!response.ok)
8
+ throw new Error(response.statusText);
9
+ return response;
10
+ }
11
+ static async text(url, signal) {
12
+ return (await PsFileFetchService.response(url, signal)).text();
13
+ }
14
+ static async buffer(url, signal) {
15
+ return (await PsFileFetchService.response(url, signal)).arrayBuffer();
16
+ }
17
+ }
18
+ exports.PsFileFetchService = PsFileFetchService;
@@ -0,0 +1,5 @@
1
+ import { PsFileKind } from '../constants/ps-file-kind';
2
+ export declare class PsFileSearchService {
3
+ static canSearch(kind: PsFileKind, hasTextLayer: boolean): boolean;
4
+ static isFindShortcut(event: KeyboardEvent): boolean;
5
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsFileSearchService = void 0;
4
+ const ps_file_kind_1 = require("../constants/ps-file-kind");
5
+ const ps_file_viewer_kinds_1 = require("../constants/ps-file-viewer-kinds");
6
+ class PsFileSearchService {
7
+ static canSearch(kind, hasTextLayer) {
8
+ if (ps_file_viewer_kinds_1.PsFileViewerKinds.searchable.includes(kind))
9
+ return true;
10
+ return kind === ps_file_kind_1.PsFileKind.image && hasTextLayer;
11
+ }
12
+ static isFindShortcut(event) {
13
+ return ((event.metaKey || event.ctrlKey) &&
14
+ !event.altKey &&
15
+ !event.shiftKey &&
16
+ event.key.toLowerCase() === 'f');
17
+ }
18
+ }
19
+ exports.PsFileSearchService = PsFileSearchService;
@@ -10,10 +10,21 @@ class PsFileTypeService {
10
10
  }
11
11
  static kindOf(contentType, name) {
12
12
  const type = contentType.toLowerCase();
13
+ const extension = PsFileTypeService.extension(name);
13
14
  if (type === 'application/pdf')
14
15
  return ps_file_kind_1.PsFileKind.pdf;
15
16
  if (ps_file_type_config_1.PsFileTypeConfig.csvTypes.includes(type))
16
17
  return ps_file_kind_1.PsFileKind.csv;
18
+ if (type === ps_file_type_config_1.PsFileTypeConfig.excelLegacyType)
19
+ return extension === 'xls' || extension === 'xlsb' ? ps_file_kind_1.PsFileKind.other : ps_file_kind_1.PsFileKind.csv;
20
+ if (ps_file_type_config_1.PsFileTypeConfig.sheetTypes.includes(type))
21
+ return ps_file_kind_1.PsFileKind.sheet;
22
+ if (ps_file_type_config_1.PsFileTypeConfig.wordTypes.includes(type))
23
+ return ps_file_kind_1.PsFileKind.word;
24
+ if (ps_file_type_config_1.PsFileTypeConfig.htmlTypes.includes(type))
25
+ return ps_file_kind_1.PsFileKind.html;
26
+ if (ps_file_type_config_1.PsFileTypeConfig.unsupportedImageTypes.includes(type))
27
+ return ps_file_kind_1.PsFileKind.other;
17
28
  if (type.startsWith('image/'))
18
29
  return ps_file_kind_1.PsFileKind.image;
19
30
  if (type.startsWith('video/'))
@@ -23,7 +34,7 @@ class PsFileTypeService {
23
34
  if (type.startsWith('text/') ||
24
35
  ps_file_type_config_1.PsFileTypeConfig.textTypes.includes(type))
25
36
  return ps_file_kind_1.PsFileKind.text;
26
- const byExtension = ps_file_type_config_1.PsFileTypeConfig.extensionKinds[PsFileTypeService.extension(name)];
37
+ const byExtension = ps_file_type_config_1.PsFileTypeConfig.extensionKinds[extension];
27
38
  return byExtension === undefined ? ps_file_kind_1.PsFileKind.other : byExtension;
28
39
  }
29
40
  static isAccepted(file, accept) {
@@ -0,0 +1,3 @@
1
+ export declare class PsHtmlFileService {
2
+ static load(url: string, signal: AbortSignal): Promise<string>;
3
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsHtmlFileService = void 0;
4
+ const ps_file_fetch_service_1 = require("./ps-file-fetch-service");
5
+ const ps_html_service_1 = require("./ps-html-service");
6
+ class PsHtmlFileService {
7
+ static async load(url, signal) {
8
+ return ps_html_service_1.PsHtmlService.sanitize(await ps_file_fetch_service_1.PsFileFetchService.text(url, signal), false);
9
+ }
10
+ }
11
+ exports.PsHtmlFileService = PsHtmlFileService;
@@ -0,0 +1,7 @@
1
+ import type { PsHtmlHighlightResult } from '../models/ps-html-highlight-result';
2
+ export declare class PsHtmlService {
3
+ static sanitize(html: string, allowImages: boolean): Promise<string>;
4
+ static harden(html: string): string;
5
+ static highlight(html: string, query: string): PsHtmlHighlightResult;
6
+ private static wrap;
7
+ }
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.PsHtmlService = void 0;
37
+ const ps_html_sanitize_config_1 = require("../constants/ps-html-sanitize-config");
38
+ const ps_text_search_service_1 = require("./ps-text-search-service");
39
+ class PsHtmlService {
40
+ static async sanitize(html, allowImages) {
41
+ const library = await Promise.resolve().then(() => __importStar(require('dompurify')));
42
+ const forbidden = [...ps_html_sanitize_config_1.PsHtmlSanitizeConfig.forbiddenTags];
43
+ if (!allowImages)
44
+ forbidden.push(...ps_html_sanitize_config_1.PsHtmlSanitizeConfig.mediaTags);
45
+ const clean = library.default.sanitize(html, {
46
+ FORBID_ATTR: [...ps_html_sanitize_config_1.PsHtmlSanitizeConfig.forbiddenAttributes],
47
+ FORBID_TAGS: forbidden,
48
+ USE_PROFILES: { html: true },
49
+ });
50
+ return PsHtmlService.harden(clean);
51
+ }
52
+ static harden(html) {
53
+ const template = document.createElement('template');
54
+ template.innerHTML = html;
55
+ template.content.querySelectorAll('a').forEach((anchor) => {
56
+ anchor.setAttribute('target', ps_html_sanitize_config_1.PsHtmlSanitizeConfig.anchorTarget);
57
+ anchor.setAttribute('rel', ps_html_sanitize_config_1.PsHtmlSanitizeConfig.anchorRel);
58
+ });
59
+ template.content.querySelectorAll('img').forEach((image) => {
60
+ const source = image.getAttribute('src');
61
+ if (source === null || !source.startsWith('data:'))
62
+ image.remove();
63
+ });
64
+ return template.innerHTML;
65
+ }
66
+ static highlight(html, query) {
67
+ if (query.trim().length === 0)
68
+ return { count: 0, html };
69
+ const template = document.createElement('template');
70
+ template.innerHTML = html;
71
+ const nodes = [];
72
+ const walker = document.createTreeWalker(template.content, NodeFilter.SHOW_TEXT);
73
+ let full = '';
74
+ let previousBlock = null;
75
+ let current = walker.nextNode();
76
+ while (current !== null) {
77
+ const node = current;
78
+ const block = node.parentElement === null
79
+ ? null
80
+ : node.parentElement.closest(ps_html_sanitize_config_1.PsHtmlSanitizeConfig.blockSelector);
81
+ if (nodes.length > 0 && block !== previousBlock)
82
+ full += '\n';
83
+ nodes.push({ node, offset: full.length });
84
+ full += node.data;
85
+ previousBlock = block;
86
+ current = walker.nextNode();
87
+ }
88
+ const matches = ps_text_search_service_1.PsTextSearchService.find(full, query);
89
+ if (matches.length === 0)
90
+ return { count: 0, html };
91
+ nodes.forEach(({ node, offset }) => PsHtmlService.wrap(node, offset, matches));
92
+ return { count: matches.length, html: template.innerHTML };
93
+ }
94
+ static wrap(node, offset, matches) {
95
+ const end = offset + node.data.length;
96
+ const fragment = document.createDocumentFragment();
97
+ let cursor = 0;
98
+ let hasMark = false;
99
+ matches.forEach((match, matchIndex) => {
100
+ const start = Math.max(match.start, offset) - offset;
101
+ const stop = Math.min(match.end, end) - offset;
102
+ if (stop <= start || match.start >= end || match.end <= offset)
103
+ return;
104
+ if (start > cursor)
105
+ fragment.append(node.data.slice(cursor, start));
106
+ const mark = document.createElement('mark');
107
+ mark.setAttribute('data-ps-match', String(matchIndex));
108
+ mark.textContent = node.data.slice(start, stop);
109
+ fragment.append(mark);
110
+ cursor = stop;
111
+ hasMark = true;
112
+ });
113
+ if (!hasMark)
114
+ return;
115
+ if (cursor < node.data.length)
116
+ fragment.append(node.data.slice(cursor));
117
+ node.replaceWith(fragment);
118
+ }
119
+ }
120
+ exports.PsHtmlService = PsHtmlService;
@@ -0,0 +1,5 @@
1
+ import type { PsImageMatch } from '../models/ps-image-match';
2
+ import type { PsImageTextLayer } from '../models/ps-image-text-layer';
3
+ export declare class PsImageTextService {
4
+ static matches(layer: PsImageTextLayer, query: string): PsImageMatch[];
5
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsImageTextService = void 0;
4
+ const ps_utilities_1 = require("@pallasoft/ps-utilities");
5
+ class PsImageTextService {
6
+ static matches(layer, query) {
7
+ return ps_utilities_1.Common.TextLayerService.fractionRects(layer, ps_utilities_1.Common.TextLayerService.phraseMatches(layer, query)).map((rect) => ({ ...rect.box, matchIndex: rect.matchIndex }));
8
+ }
9
+ }
10
+ exports.PsImageTextService = PsImageTextService;
@@ -0,0 +1,3 @@
1
+ export declare class PsLabelService {
2
+ static fill(template: string, values: Record<string, string | number>): string;
3
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsLabelService = void 0;
4
+ class PsLabelService {
5
+ static fill(template, values) {
6
+ return Object.keys(values).reduce((text, key) => text.split(`{${key}}`).join(String(values[key])), template);
7
+ }
8
+ }
9
+ exports.PsLabelService = PsLabelService;
@@ -1,11 +1,14 @@
1
1
  import type { PDFDocumentProxy, PDFPageProxy, RenderTask } from 'pdfjs-dist';
2
2
  import type { PsPdfMatch } from '../models/ps-pdf-match';
3
+ import type { PsPdfTextItem } from '../models/ps-pdf-text-item';
4
+ import type { PsPdfViewportLike } from '../models/ps-pdf-viewport-like';
3
5
  type PdfLibrary = typeof import('pdfjs-dist');
4
6
  export declare class PsPdfService {
5
7
  private static library;
6
8
  static load(workerSrc?: string): Promise<PdfLibrary>;
7
9
  static open(url: string, workerSrc?: string): Promise<PDFDocumentProxy>;
8
10
  static render(page: PDFPageProxy, canvas: HTMLCanvasElement, scale: number, rotation: number): RenderTask;
11
+ static pageMatches(items: PsPdfTextItem[], viewport: PsPdfViewportLike, query: string, pageNumber: number, firstIndex: number): PsPdfMatch[];
9
12
  static search(document: PDFDocumentProxy, query: string, rotation: number): Promise<PsPdfMatch[]>;
10
13
  }
11
14
  export {};
@@ -66,31 +66,54 @@ class PsPdfService {
66
66
  task.promise.catch(() => undefined);
67
67
  return task;
68
68
  }
69
+ static pageMatches(items, viewport, query, pageNumber, firstIndex) {
70
+ const found = ps_text_search_service_1.PsTextSearchService.findInItems(items.map((item) => ({ isBreakAfter: item.hasEOL, text: item.str })), query);
71
+ const rects = [];
72
+ found.forEach((match, offset) => {
73
+ match.parts.forEach((part) => {
74
+ const item = items[part.itemIndex];
75
+ const [x, y] = [item.transform[4], item.transform[5]];
76
+ const height = item.height > 0 ? item.height : Math.hypot(item.transform[2], item.transform[3]);
77
+ const start = x + (item.width * part.start) / item.str.length;
78
+ const end = x + (item.width * part.end) / item.str.length;
79
+ const [x1, y1] = viewport.convertToViewportPoint(start, y);
80
+ const [x2, y2] = viewport.convertToViewportPoint(end, y + height);
81
+ rects.push({
82
+ height: Math.abs(y2 - y1) / viewport.height,
83
+ left: Math.min(x1, x2) / viewport.width,
84
+ matchIndex: firstIndex + offset,
85
+ pageNumber,
86
+ top: Math.min(y1, y2) / viewport.height,
87
+ width: Math.abs(x2 - x1) / viewport.width,
88
+ });
89
+ });
90
+ });
91
+ return rects;
92
+ }
69
93
  static async search(document, query, rotation) {
70
94
  const matches = [];
95
+ let count = 0;
96
+ if (query.trim().length === 0)
97
+ return matches;
71
98
  for (let pageNumber = 1; pageNumber <= document.numPages; pageNumber += 1) {
72
99
  const page = await document.getPage(pageNumber);
73
100
  const viewport = page.getViewport({ rotation: page.rotate + rotation, scale: 1 });
74
101
  const content = await page.getTextContent();
102
+ const items = [];
75
103
  content.items.forEach((item) => {
76
- if (!('str' in item) || item.str.length === 0)
77
- return;
78
- ps_text_search_service_1.PsTextSearchService.find(item.str, query).forEach((found) => {
79
- const [x, y] = [item.transform[4], item.transform[5]];
80
- const height = item.height > 0 ? item.height : Math.hypot(item.transform[2], item.transform[3]);
81
- const start = x + (item.width * found.start) / item.str.length;
82
- const end = x + (item.width * found.end) / item.str.length;
83
- const [x1, y1] = viewport.convertToViewportPoint(start, y);
84
- const [x2, y2] = viewport.convertToViewportPoint(end, y + height);
85
- matches.push({
86
- height: Math.abs(y2 - y1) / viewport.height,
87
- left: Math.min(x1, x2) / viewport.width,
88
- pageNumber,
89
- top: Math.min(y1, y2) / viewport.height,
90
- width: Math.abs(x2 - x1) / viewport.width,
104
+ if ('str' in item)
105
+ items.push({
106
+ hasEOL: item.hasEOL,
107
+ height: item.height,
108
+ str: item.str,
109
+ transform: item.transform,
110
+ width: item.width,
91
111
  });
92
- });
93
112
  });
113
+ const found = PsPdfService.pageMatches(items, viewport, query, pageNumber, count);
114
+ if (found.length > 0)
115
+ count = found[found.length - 1].matchIndex + 1;
116
+ matches.push(...found);
94
117
  }
95
118
  return matches;
96
119
  }
@@ -0,0 +1,5 @@
1
+ import type { PsSheetData } from '../models/ps-sheet-data';
2
+ export declare class PsSheetService {
3
+ static load(url: string, signal: AbortSignal): Promise<PsSheetData[]>;
4
+ static cellText(value: unknown): string;
5
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.PsSheetService = void 0;
37
+ const ps_file_fetch_service_1 = require("./ps-file-fetch-service");
38
+ class PsSheetService {
39
+ static async load(url, signal) {
40
+ const [buffer, library] = await Promise.all([
41
+ ps_file_fetch_service_1.PsFileFetchService.buffer(url, signal),
42
+ Promise.resolve().then(() => __importStar(require('read-excel-file/browser'))),
43
+ ]);
44
+ const sheets = await library.default(buffer);
45
+ return sheets.map((sheet) => ({
46
+ name: sheet.sheet,
47
+ rows: sheet.data.map((row) => row.map((cell) => PsSheetService.cellText(cell))),
48
+ }));
49
+ }
50
+ static cellText(value) {
51
+ if (typeof value === 'string')
52
+ return value;
53
+ if (typeof value === 'number' || typeof value === 'boolean')
54
+ return String(value);
55
+ if (value instanceof Date)
56
+ return Number.isNaN(value.getTime()) ? '' : value.toISOString().slice(0, 10);
57
+ return '';
58
+ }
59
+ }
60
+ exports.PsSheetService = PsSheetService;
@@ -1,6 +1,13 @@
1
+ import type { PsItemMatch } from '../models/ps-item-match';
2
+ import type { PsNormalizedText } from '../models/ps-normalized-text';
3
+ import type { PsSearchItem } from '../models/ps-search-item';
1
4
  import type { PsTextMatch } from '../models/ps-text-match';
2
5
  import type { PsTextSegment } from '../models/ps-text-segment';
3
6
  export declare class PsTextSearchService {
7
+ static normalize(text: string): PsNormalizedText;
4
8
  static find(text: string, query: string): PsTextMatch[];
9
+ static findInItems(items: PsSearchItem[], query: string): PsItemMatch[];
5
10
  static segments(text: string, matches: PsTextMatch[], firstIndex?: number): PsTextSegment[];
11
+ static tableSegments(rows: string[][], query: string): PsTextSegment[][][];
12
+ static countSegments(table: PsTextSegment[][][]): number;
6
13
  }
@@ -1,36 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsTextSearchService = void 0;
4
+ const ps_utilities_1 = require("@pallasoft/ps-utilities");
4
5
  class PsTextSearchService {
6
+ static normalize(text) {
7
+ return ps_utilities_1.Common.TextSearchService.normalize(text);
8
+ }
5
9
  static find(text, query) {
6
- const needle = query.trim().toLowerCase();
7
- if (needle.length === 0)
8
- return [];
9
- const haystack = text.toLowerCase();
10
- const matches = [];
11
- let from = haystack.indexOf(needle);
12
- while (from !== -1) {
13
- matches.push({ end: from + needle.length, start: from });
14
- from = haystack.indexOf(needle, from + needle.length);
15
- }
16
- return matches;
10
+ return ps_utilities_1.Common.TextSearchService.find(text, query);
11
+ }
12
+ static findInItems(items, query) {
13
+ return ps_utilities_1.Common.TextSearchService.findInItems(items, query);
17
14
  }
18
15
  static segments(text, matches, firstIndex = 0) {
19
- const segments = [];
20
- let cursor = 0;
21
- matches.forEach((match, index) => {
22
- if (match.start > cursor)
23
- segments.push({ isMatch: false, matchIndex: null, text: text.slice(cursor, match.start) });
24
- segments.push({
25
- isMatch: true,
26
- matchIndex: firstIndex + index,
27
- text: text.slice(match.start, match.end),
28
- });
29
- cursor = match.end;
30
- });
31
- if (cursor < text.length)
32
- segments.push({ isMatch: false, matchIndex: null, text: text.slice(cursor) });
33
- return segments;
16
+ return ps_utilities_1.Common.TextSearchService.segments(text, matches, firstIndex);
17
+ }
18
+ static tableSegments(rows, query) {
19
+ let offset = 0;
20
+ return rows.map((row) => row.map((cell) => {
21
+ const matches = PsTextSearchService.find(cell, query);
22
+ const segments = PsTextSearchService.segments(cell, matches, offset);
23
+ offset += matches.length;
24
+ return segments;
25
+ }));
26
+ }
27
+ static countSegments(table) {
28
+ return table.reduce((total, row) => total + row.reduce((sum, cell) => sum + cell.filter((part) => part.isMatch).length, 0), 0);
34
29
  }
35
30
  }
36
31
  exports.PsTextSearchService = PsTextSearchService;
@@ -0,0 +1,3 @@
1
+ export declare class PsWordService {
2
+ static load(url: string, signal: AbortSignal): Promise<string>;
3
+ }