@pallasoft/ps-file-components 2.2.0 → 2.4.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.
- package/dist/components/ps-file-list.d.ts +2 -1
- package/dist/components/ps-file-list.js +2 -2
- package/dist/components/ps-file-search-bar.d.ts +10 -0
- package/dist/components/ps-file-search-bar.js +25 -0
- package/dist/components/ps-file-viewer-content.js +9 -0
- package/dist/components/ps-file-viewer-pane.d.ts +1 -1
- package/dist/components/ps-file-viewer-pane.js +26 -2
- package/dist/components/ps-file-viewer.js +11 -23
- package/dist/components/ps-html-document.d.ts +8 -0
- package/dist/components/ps-html-document.js +23 -0
- package/dist/components/ps-html-viewer.d.ts +2 -0
- package/dist/components/ps-html-viewer.js +17 -0
- package/dist/components/ps-image-text-highlights.d.ts +9 -0
- package/dist/components/ps-image-text-highlights.js +31 -0
- package/dist/components/ps-image-viewer.d.ts +1 -1
- package/dist/components/ps-image-viewer.js +11 -2
- package/dist/components/ps-pdf-page.js +1 -1
- package/dist/components/ps-pdf-viewer.js +6 -2
- package/dist/components/ps-sheet-viewer.d.ts +2 -0
- package/dist/components/ps-sheet-viewer.js +26 -0
- package/dist/components/ps-table-view.d.ts +7 -0
- package/dist/components/ps-table-view.js +17 -0
- package/dist/components/ps-text-viewer.js +7 -14
- package/dist/components/ps-word-viewer.d.ts +2 -0
- package/dist/components/ps-word-viewer.js +17 -0
- package/dist/constants/ps-file-kind-icons.js +3 -0
- package/dist/constants/ps-file-kind.d.ts +3 -0
- package/dist/constants/ps-file-kind.js +3 -0
- package/dist/constants/ps-file-list-labels.d.ts +1 -0
- package/dist/constants/ps-file-list-labels.js +1 -0
- package/dist/constants/ps-file-type-config.d.ts +6 -1
- package/dist/constants/ps-file-type-config.js +16 -2
- package/dist/constants/ps-file-viewer-config.d.ts +1 -0
- package/dist/constants/ps-file-viewer-config.js +1 -0
- package/dist/constants/ps-file-viewer-kinds.d.ts +2 -2
- package/dist/constants/ps-file-viewer-kinds.js +17 -2
- package/dist/constants/ps-file-viewer-labels.d.ts +3 -0
- package/dist/constants/ps-file-viewer-labels.js +3 -0
- package/dist/constants/ps-html-sanitize-config.d.ts +8 -0
- package/dist/constants/ps-html-sanitize-config.js +26 -0
- package/dist/esm/components/ps-file-list.js +2 -2
- package/dist/esm/components/ps-file-search-bar.js +21 -0
- package/dist/esm/components/ps-file-viewer-content.js +9 -0
- package/dist/esm/components/ps-file-viewer-pane.js +27 -3
- package/dist/esm/components/ps-file-viewer.js +13 -25
- package/dist/esm/components/ps-html-document.js +19 -0
- package/dist/esm/components/ps-html-viewer.js +13 -0
- package/dist/esm/components/ps-image-text-highlights.js +27 -0
- package/dist/esm/components/ps-image-viewer.js +13 -4
- package/dist/esm/components/ps-pdf-page.js +1 -1
- package/dist/esm/components/ps-pdf-viewer.js +6 -2
- package/dist/esm/components/ps-sheet-viewer.js +22 -0
- package/dist/esm/components/ps-table-view.js +13 -0
- package/dist/esm/components/ps-text-viewer.js +7 -14
- package/dist/esm/components/ps-word-viewer.js +13 -0
- package/dist/esm/constants/ps-file-kind-icons.js +3 -0
- package/dist/esm/constants/ps-file-kind.js +3 -0
- package/dist/esm/constants/ps-file-list-labels.js +1 -0
- package/dist/esm/constants/ps-file-type-config.js +16 -2
- package/dist/esm/constants/ps-file-viewer-config.js +1 -0
- package/dist/esm/constants/ps-file-viewer-kinds.js +17 -2
- package/dist/esm/constants/ps-file-viewer-labels.js +3 -0
- package/dist/esm/constants/ps-html-sanitize-config.js +23 -0
- package/dist/esm/hooks/use-ps-file-search.js +37 -0
- package/dist/esm/hooks/use-ps-file-text.js +4 -19
- package/dist/esm/hooks/use-ps-find-shortcut.js +23 -0
- package/dist/esm/hooks/use-ps-loaded-file.js +19 -0
- package/dist/esm/index.js +33 -0
- package/dist/esm/models/ps-file-search-state.js +1 -0
- package/dist/esm/models/ps-html-highlight-result.js +1 -0
- package/dist/esm/models/ps-html-text-node.js +1 -0
- package/dist/esm/models/ps-image-match.js +1 -0
- package/dist/esm/models/ps-image-text-box.js +1 -0
- package/dist/esm/models/ps-image-text-layer.js +1 -0
- package/dist/esm/models/ps-image-text-word.js +1 -0
- package/dist/esm/models/ps-item-match-part.js +1 -0
- package/dist/esm/models/ps-item-match.js +1 -0
- package/dist/esm/models/ps-loaded-file-state.js +1 -0
- package/dist/esm/models/ps-normalized-text.js +1 -0
- package/dist/esm/models/ps-pdf-text-item.js +1 -0
- package/dist/esm/models/ps-pdf-viewport-like.js +1 -0
- package/dist/esm/models/ps-search-item.js +1 -0
- package/dist/esm/models/ps-sheet-data.js +1 -0
- package/dist/esm/services/ps-file-fetch-service.js +14 -0
- package/dist/esm/services/ps-file-search-service.js +15 -0
- package/dist/esm/services/ps-file-type-service.js +12 -1
- package/dist/esm/services/ps-html-file-service.js +7 -0
- package/dist/esm/services/ps-html-service.js +83 -0
- package/dist/esm/services/ps-image-text-service.js +28 -0
- package/dist/esm/services/ps-label-service.js +5 -0
- package/dist/esm/services/ps-pdf-service.js +39 -16
- package/dist/esm/services/ps-sheet-service.js +23 -0
- package/dist/esm/services/ps-text-search-service.js +70 -5
- package/dist/esm/services/ps-word-service.js +15 -0
- package/dist/hooks/use-ps-file-search.d.ts +2 -0
- package/dist/hooks/use-ps-file-search.js +41 -0
- package/dist/hooks/use-ps-file-text.js +4 -19
- package/dist/hooks/use-ps-find-shortcut.d.ts +2 -0
- package/dist/hooks/use-ps-find-shortcut.js +27 -0
- package/dist/hooks/use-ps-loaded-file.d.ts +2 -0
- package/dist/hooks/use-ps-loaded-file.js +23 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +33 -0
- package/dist/models/ps-file-search-state.d.ts +13 -0
- package/dist/models/ps-file-search-state.js +2 -0
- package/dist/models/ps-file-viewer-pane-props.d.ts +3 -1
- package/dist/models/ps-html-highlight-result.d.ts +4 -0
- package/dist/models/ps-html-highlight-result.js +2 -0
- package/dist/models/ps-html-text-node.d.ts +4 -0
- package/dist/models/ps-html-text-node.js +2 -0
- package/dist/models/ps-image-match.d.ts +7 -0
- package/dist/models/ps-image-match.js +2 -0
- package/dist/models/ps-image-text-box.d.ts +6 -0
- package/dist/models/ps-image-text-box.js +2 -0
- package/dist/models/ps-image-text-layer.d.ts +6 -0
- package/dist/models/ps-image-text-layer.js +2 -0
- package/dist/models/ps-image-text-word.d.ts +5 -0
- package/dist/models/ps-image-text-word.js +2 -0
- package/dist/models/ps-item-match-part.d.ts +5 -0
- package/dist/models/ps-item-match-part.js +2 -0
- package/dist/models/ps-item-match.d.ts +4 -0
- package/dist/models/ps-item-match.js +2 -0
- package/dist/models/ps-loaded-file-state.d.ts +4 -0
- package/dist/models/ps-loaded-file-state.js +2 -0
- package/dist/models/ps-normalized-text.d.ts +5 -0
- package/dist/models/ps-normalized-text.js +2 -0
- package/dist/models/ps-pdf-match.d.ts +1 -0
- package/dist/models/ps-pdf-text-item.d.ts +7 -0
- package/dist/models/ps-pdf-text-item.js +2 -0
- package/dist/models/ps-pdf-viewport-like.d.ts +5 -0
- package/dist/models/ps-pdf-viewport-like.js +2 -0
- package/dist/models/ps-search-item.d.ts +4 -0
- package/dist/models/ps-search-item.js +2 -0
- package/dist/models/ps-sheet-data.d.ts +4 -0
- package/dist/models/ps-sheet-data.js +2 -0
- package/dist/models/ps-viewer-file.d.ts +2 -0
- package/dist/services/ps-file-fetch-service.d.ts +5 -0
- package/dist/services/ps-file-fetch-service.js +18 -0
- package/dist/services/ps-file-search-service.d.ts +5 -0
- package/dist/services/ps-file-search-service.js +19 -0
- package/dist/services/ps-file-type-service.js +12 -1
- package/dist/services/ps-html-file-service.d.ts +3 -0
- package/dist/services/ps-html-file-service.js +11 -0
- package/dist/services/ps-html-service.d.ts +7 -0
- package/dist/services/ps-html-service.js +120 -0
- package/dist/services/ps-image-text-service.d.ts +5 -0
- package/dist/services/ps-image-text-service.js +32 -0
- package/dist/services/ps-label-service.d.ts +3 -0
- package/dist/services/ps-label-service.js +9 -0
- package/dist/services/ps-pdf-service.d.ts +3 -0
- package/dist/services/ps-pdf-service.js +39 -16
- package/dist/services/ps-sheet-service.d.ts +5 -0
- package/dist/services/ps-sheet-service.js +60 -0
- package/dist/services/ps-text-search-service.d.ts +7 -0
- package/dist/services/ps-text-search-service.js +70 -5
- package/dist/services/ps-word-service.d.ts +3 -0
- package/dist/services/ps-word-service.js +52 -0
- package/package.json +5 -2
|
@@ -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,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,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[
|
|
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,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,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsImageTextService = void 0;
|
|
4
|
+
const ps_text_search_service_1 = require("./ps-text-search-service");
|
|
5
|
+
class PsImageTextService {
|
|
6
|
+
static matches(layer, query) {
|
|
7
|
+
if (layer.width <= 0 || layer.height <= 0)
|
|
8
|
+
return [];
|
|
9
|
+
const items = layer.words.map((word, index) => ({
|
|
10
|
+
isBreakAfter: index < layer.words.length - 1,
|
|
11
|
+
text: word.text,
|
|
12
|
+
}));
|
|
13
|
+
const rects = [];
|
|
14
|
+
ps_text_search_service_1.PsTextSearchService.findInItems(items, query).forEach((match, matchIndex) => {
|
|
15
|
+
match.parts.forEach((part) => {
|
|
16
|
+
const word = layer.words[part.itemIndex];
|
|
17
|
+
const length = word.text.length;
|
|
18
|
+
const left = word.box.left + (word.box.width * part.start) / length;
|
|
19
|
+
const width = (word.box.width * (part.end - part.start)) / length;
|
|
20
|
+
rects.push({
|
|
21
|
+
height: word.box.height / layer.height,
|
|
22
|
+
left: left / layer.width,
|
|
23
|
+
matchIndex,
|
|
24
|
+
top: word.box.top / layer.height,
|
|
25
|
+
width: width / layer.width,
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
return rects;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.PsImageTextService = PsImageTextService;
|
|
@@ -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 (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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,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,20 +1,73 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PsTextSearchService = void 0;
|
|
4
|
+
const whitespace = /\s/u;
|
|
5
|
+
const marks = /\p{M}/gu;
|
|
4
6
|
class PsTextSearchService {
|
|
7
|
+
static normalize(text) {
|
|
8
|
+
const starts = [];
|
|
9
|
+
const ends = [];
|
|
10
|
+
let folded = '';
|
|
11
|
+
let isAfterSpace = false;
|
|
12
|
+
let index = 0;
|
|
13
|
+
while (index < text.length) {
|
|
14
|
+
const char = String.fromCodePoint(text.codePointAt(index));
|
|
15
|
+
const next = index + char.length;
|
|
16
|
+
if (whitespace.test(char)) {
|
|
17
|
+
if (!isAfterSpace) {
|
|
18
|
+
folded += ' ';
|
|
19
|
+
starts.push(index);
|
|
20
|
+
ends.push(next);
|
|
21
|
+
}
|
|
22
|
+
isAfterSpace = true;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
const plain = char.toLowerCase().normalize('NFD').replace(marks, '');
|
|
26
|
+
for (let at = 0; at < plain.length; at += 1) {
|
|
27
|
+
folded += plain[at];
|
|
28
|
+
starts.push(index);
|
|
29
|
+
ends.push(next);
|
|
30
|
+
}
|
|
31
|
+
isAfterSpace = false;
|
|
32
|
+
}
|
|
33
|
+
index = next;
|
|
34
|
+
}
|
|
35
|
+
return { ends, starts, text: folded };
|
|
36
|
+
}
|
|
5
37
|
static find(text, query) {
|
|
6
|
-
const needle = query.trim().
|
|
38
|
+
const needle = PsTextSearchService.normalize(query.trim()).text;
|
|
7
39
|
if (needle.length === 0)
|
|
8
40
|
return [];
|
|
9
|
-
const haystack =
|
|
41
|
+
const haystack = PsTextSearchService.normalize(text);
|
|
10
42
|
const matches = [];
|
|
11
|
-
let from = haystack.indexOf(needle);
|
|
43
|
+
let from = haystack.text.indexOf(needle);
|
|
12
44
|
while (from !== -1) {
|
|
13
|
-
matches.push({
|
|
14
|
-
|
|
45
|
+
matches.push({
|
|
46
|
+
end: haystack.ends[from + needle.length - 1],
|
|
47
|
+
start: haystack.starts[from],
|
|
48
|
+
});
|
|
49
|
+
from = haystack.text.indexOf(needle, from + needle.length);
|
|
15
50
|
}
|
|
16
51
|
return matches;
|
|
17
52
|
}
|
|
53
|
+
static findInItems(items, query) {
|
|
54
|
+
const offsets = [];
|
|
55
|
+
let joined = '';
|
|
56
|
+
items.forEach((item) => {
|
|
57
|
+
offsets.push(joined.length);
|
|
58
|
+
joined += item.isBreakAfter ? `${item.text} ` : item.text;
|
|
59
|
+
});
|
|
60
|
+
return PsTextSearchService.find(joined, query).map((match) => {
|
|
61
|
+
const parts = [];
|
|
62
|
+
items.forEach((item, itemIndex) => {
|
|
63
|
+
const start = Math.max(match.start, offsets[itemIndex]) - offsets[itemIndex];
|
|
64
|
+
const end = Math.min(match.end, offsets[itemIndex] + item.text.length) - offsets[itemIndex];
|
|
65
|
+
if (end > start)
|
|
66
|
+
parts.push({ end, itemIndex, start });
|
|
67
|
+
});
|
|
68
|
+
return { parts };
|
|
69
|
+
});
|
|
70
|
+
}
|
|
18
71
|
static segments(text, matches, firstIndex = 0) {
|
|
19
72
|
const segments = [];
|
|
20
73
|
let cursor = 0;
|
|
@@ -32,5 +85,17 @@ class PsTextSearchService {
|
|
|
32
85
|
segments.push({ isMatch: false, matchIndex: null, text: text.slice(cursor) });
|
|
33
86
|
return segments;
|
|
34
87
|
}
|
|
88
|
+
static tableSegments(rows, query) {
|
|
89
|
+
let offset = 0;
|
|
90
|
+
return rows.map((row) => row.map((cell) => {
|
|
91
|
+
const matches = PsTextSearchService.find(cell, query);
|
|
92
|
+
const segments = PsTextSearchService.segments(cell, matches, offset);
|
|
93
|
+
offset += matches.length;
|
|
94
|
+
return segments;
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
static countSegments(table) {
|
|
98
|
+
return table.reduce((total, row) => total + row.reduce((sum, cell) => sum + cell.filter((part) => part.isMatch).length, 0), 0);
|
|
99
|
+
}
|
|
35
100
|
}
|
|
36
101
|
exports.PsTextSearchService = PsTextSearchService;
|