@file-viewer/cli 3.0.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.
@@ -0,0 +1,58 @@
1
+ // eslint-disable-next-line no-control-regex -- reject controls before URL parsing
2
+ const INVALID_URL_CHARACTERS = /[\u0000-\u001f\u007f\\]/;
3
+ const isLoopbackHostname = (hostname) => {
4
+ const normalized = hostname.toLowerCase();
5
+ if (normalized === 'localhost' || normalized === '[::1]')
6
+ return true;
7
+ const octets = normalized.split('.');
8
+ return (octets.length === 4 &&
9
+ octets[0] === '127' &&
10
+ octets.every((octet) => /^\d{1,3}$/.test(octet) && Number(octet) <= 255));
11
+ };
12
+ const assertSafeNetworkUrl = (parsed, label) => {
13
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
14
+ throw new Error(`${label} must use HTTPS, or HTTP on a loopback host.`);
15
+ }
16
+ if (parsed.username || parsed.password || parsed.search || parsed.hash) {
17
+ throw new Error(`${label} must not contain credentials, query parameters, or a fragment.`);
18
+ }
19
+ if (parsed.protocol === 'http:' && !isLoopbackHostname(parsed.hostname)) {
20
+ throw new Error(`${label} must use HTTPS unless the host is loopback.`);
21
+ }
22
+ };
23
+ export const normalizeFileViewerAssetBaseUrl = (value) => {
24
+ if (!value)
25
+ return undefined;
26
+ const normalized = value.trim();
27
+ if (!normalized ||
28
+ INVALID_URL_CHARACTERS.test(normalized) ||
29
+ normalized.startsWith('//') ||
30
+ normalized.includes('?') ||
31
+ normalized.includes('#')) {
32
+ throw new Error('Invalid assetBaseUrl. Queries, fragments, protocol-relative URLs, and control characters are not allowed.');
33
+ }
34
+ if (/^https?:\/\//i.test(normalized)) {
35
+ const parsed = new URL(normalized);
36
+ assertSafeNetworkUrl(parsed, 'assetBaseUrl');
37
+ return parsed.href.endsWith('/') ? parsed.href : `${parsed.href}/`;
38
+ }
39
+ if (/^(?:\/(?!\/)|\.\/|\.\.\/)/.test(normalized)) {
40
+ return normalized.endsWith('/') ? normalized : `${normalized}/`;
41
+ }
42
+ throw new Error('assetBaseUrl must be an explicit HTTPS URL, a loopback HTTP URL, or a relative/root URL.');
43
+ };
44
+ export const normalizeFileViewerRegistryUrl = (value) => {
45
+ const normalized = String(value || '').trim();
46
+ if (!normalized || INVALID_URL_CHARACTERS.test(normalized)) {
47
+ throw new Error('Invalid registry URL.');
48
+ }
49
+ let parsed;
50
+ try {
51
+ parsed = new URL(normalized);
52
+ }
53
+ catch {
54
+ throw new Error('Invalid registry URL.');
55
+ }
56
+ assertSafeNetworkUrl(parsed, 'Registry');
57
+ return parsed.href.endsWith('/') ? parsed.href : `${parsed.href}/`;
58
+ };
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@file-viewer/cli",
3
+ "version": "3.0.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "description": "Create or integrate a File Viewer project with framework detection, selectable formats, offline packages, and self-hosted assets.",
7
+ "keywords": [
8
+ "file-viewer",
9
+ "cli",
10
+ "preset",
11
+ "capability",
12
+ "vite",
13
+ "document-preview"
14
+ ],
15
+ "publishConfig": {
16
+ "access": "public",
17
+ "registry": "https://registry.npmjs.org/"
18
+ },
19
+ "author": {
20
+ "name": "Yu Wang",
21
+ "email": "admin@flyfish.dev"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/flyfish-dev/file-viewer.git",
26
+ "directory": "packages/tools/cli"
27
+ },
28
+ "homepage": "https://file-viewer.app/en/cli/",
29
+ "bugs": {
30
+ "url": "https://github.com/flyfish-dev/file-viewer/issues"
31
+ },
32
+ "funding": {
33
+ "type": "individual",
34
+ "url": "https://dev.flyfish.group/donate?source=npm"
35
+ },
36
+ "bin": {
37
+ "file-viewer": "./dist/cli.js",
38
+ "file-viewer-copy-assets": "./dist/copy-assets.js"
39
+ },
40
+ "main": "./dist/index.js",
41
+ "module": "./dist/index.js",
42
+ "types": "./dist/index.d.ts",
43
+ "exports": {
44
+ ".": {
45
+ "types": "./dist/index.d.ts",
46
+ "import": "./dist/index.js",
47
+ "default": "./dist/index.js"
48
+ },
49
+ "./catalog": "./catalog/catalog.json",
50
+ "./cli": "./dist/cli.js",
51
+ "./package.json": "./package.json"
52
+ },
53
+ "files": [
54
+ "dist",
55
+ "catalog",
56
+ "README.md",
57
+ "README.en.md",
58
+ "LICENSE"
59
+ ],
60
+ "dependencies": {
61
+ "@file-viewer/asset-installer": "3.0.0"
62
+ },
63
+ "devDependencies": {
64
+ "@file-viewer/assets-standard": "3.0.0",
65
+ "@types/node": "^25.9.2",
66
+ "typescript": "^6.0.3"
67
+ },
68
+ "engines": {
69
+ "node": ">=20"
70
+ },
71
+ "license": "Apache-2.0",
72
+ "scripts": {
73
+ "stage-catalog": "node scripts/stage-catalog.mjs",
74
+ "verify-catalog": "node scripts/stage-catalog.mjs --check",
75
+ "build": "node scripts/stage-catalog.mjs && tsc -b tsconfig.json && node ../../../scripts/ensure-node-bin.mjs packages/tools/cli/dist/cli.js packages/tools/cli/dist/copy-assets.js && node --test test/*.test.mjs",
76
+ "type-check": "tsc -b tsconfig.json"
77
+ }
78
+ }