@likecoin/epubcheck-ts 0.2.0 → 0.2.2
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/README.md +44 -0
- package/bin/epubcheck.js +172 -0
- package/bin/epubcheck.ts +229 -0
- package/dist/index.cjs +171 -150
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +171 -150
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ A TypeScript port of [EPUBCheck](https://github.com/w3c/epubcheck) - the officia
|
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
|
+
- **CLI and programmatic API**: Use as a command-line tool or integrate into your application
|
|
13
14
|
- **Cross-platform**: Works in Node.js (18+) and modern browsers
|
|
14
15
|
- **Partial EPUB validation**: Currently ~65% of EPUBCheck feature parity
|
|
15
16
|
- **Zero native dependencies**: Pure JavaScript/WebAssembly, no compilation required
|
|
@@ -28,6 +29,49 @@ npm install @likecoin/epubcheck-ts
|
|
|
28
29
|
|
|
29
30
|
## Quick Start
|
|
30
31
|
|
|
32
|
+
### Command Line Interface (CLI)
|
|
33
|
+
|
|
34
|
+
**Quick validation:**
|
|
35
|
+
```bash
|
|
36
|
+
npx @likecoin/epubcheck-ts book.epub
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Or install globally:**
|
|
40
|
+
```bash
|
|
41
|
+
npm install -g @likecoin/epubcheck-ts
|
|
42
|
+
epubcheck-ts book.epub
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**CLI Options:**
|
|
46
|
+
```bash
|
|
47
|
+
epubcheck-ts <file.epub> [options]
|
|
48
|
+
|
|
49
|
+
Options:
|
|
50
|
+
-j, --json <file> Output JSON report to file (use '-' for stdout)
|
|
51
|
+
-q, --quiet Suppress console output (errors only)
|
|
52
|
+
-p, --profile <name> Validation profile (default|dict|edupub|idx|preview)
|
|
53
|
+
-w, --fail-on-warnings Exit with code 1 if warnings are found
|
|
54
|
+
-v, --version Show version information
|
|
55
|
+
-h, --help Show this help message
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Examples:**
|
|
59
|
+
```bash
|
|
60
|
+
# Basic validation
|
|
61
|
+
epubcheck-ts book.epub
|
|
62
|
+
|
|
63
|
+
# Generate JSON report
|
|
64
|
+
epubcheck-ts book.epub --json report.json
|
|
65
|
+
|
|
66
|
+
# Quiet mode for CI/CD
|
|
67
|
+
epubcheck-ts book.epub --quiet --fail-on-warnings
|
|
68
|
+
|
|
69
|
+
# Validate with specific profile
|
|
70
|
+
epubcheck-ts dictionary.epub --profile dict
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Note:** This CLI provides ~65% coverage of Java EPUBCheck features. For complete EPUB 3 conformance testing, use the [official Java EPUBCheck](https://github.com/w3c/epubcheck).
|
|
74
|
+
|
|
31
75
|
### ES Modules (recommended)
|
|
32
76
|
|
|
33
77
|
```typescript
|
package/bin/epubcheck.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { parseArgs } from "node:util";
|
|
4
|
+
import { basename } from "node:path";
|
|
5
|
+
const { EpubCheck, toJSONReport } = await import("../dist/index.js");
|
|
6
|
+
const VERSION = "0.2.2";
|
|
7
|
+
const { values, positionals } = parseArgs({
|
|
8
|
+
options: {
|
|
9
|
+
json: { type: "string", short: "j" },
|
|
10
|
+
quiet: { type: "boolean", short: "q", default: false },
|
|
11
|
+
profile: { type: "string", short: "p" },
|
|
12
|
+
usage: { type: "boolean", short: "u", default: false },
|
|
13
|
+
version: { type: "boolean", short: "v", default: false },
|
|
14
|
+
help: { type: "boolean", short: "h", default: false },
|
|
15
|
+
"fail-on-warnings": { type: "boolean", short: "w", default: false }
|
|
16
|
+
},
|
|
17
|
+
allowPositionals: true,
|
|
18
|
+
strict: false
|
|
19
|
+
});
|
|
20
|
+
if (values.version) {
|
|
21
|
+
console.log(`EPUBCheck-TS v${VERSION}`);
|
|
22
|
+
console.log("TypeScript EPUB validator for Node.js and browsers");
|
|
23
|
+
console.log();
|
|
24
|
+
console.log("Note: This is ~65% feature-complete compared to Java EPUBCheck.");
|
|
25
|
+
console.log("For production validation: https://github.com/w3c/epubcheck");
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
if (values.help || positionals.length === 0) {
|
|
29
|
+
console.log(`EPUBCheck-TS v${VERSION} - EPUB Validator
|
|
30
|
+
|
|
31
|
+
Usage: epubcheck-ts <file.epub> [options]
|
|
32
|
+
|
|
33
|
+
Arguments:
|
|
34
|
+
<file.epub> Path to EPUB file to validate
|
|
35
|
+
|
|
36
|
+
Options:
|
|
37
|
+
-j, --json <file> Output JSON report to file (use '-' for stdout)
|
|
38
|
+
-q, --quiet Suppress console output (errors only)
|
|
39
|
+
-p, --profile <name> Validation profile (default|dict|edupub|idx|preview)
|
|
40
|
+
-u, --usage Include usage messages (best practices)
|
|
41
|
+
-w, --fail-on-warnings Exit with code 1 if warnings are found
|
|
42
|
+
-v, --version Show version information
|
|
43
|
+
-h, --help Show this help message
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
epubcheck-ts book.epub
|
|
47
|
+
epubcheck-ts book.epub --json report.json
|
|
48
|
+
epubcheck-ts book.epub --quiet --fail-on-warnings
|
|
49
|
+
epubcheck-ts book.epub --profile dict
|
|
50
|
+
|
|
51
|
+
Exit Codes:
|
|
52
|
+
0 No errors (or only warnings if --fail-on-warnings not set)
|
|
53
|
+
1 Validation errors found (or warnings with --fail-on-warnings)
|
|
54
|
+
2 Runtime error (file not found, invalid arguments, etc.)
|
|
55
|
+
|
|
56
|
+
Note: This tool provides ~65% coverage of Java EPUBCheck features.
|
|
57
|
+
Missing features: Media Overlays, advanced ARIA checks, encryption/signatures.
|
|
58
|
+
For complete EPUB 3 conformance testing, use: https://github.com/w3c/epubcheck
|
|
59
|
+
|
|
60
|
+
Report issues: https://github.com/likecoin/epubcheck-ts/issues
|
|
61
|
+
`);
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
64
|
+
async function main() {
|
|
65
|
+
const filePath = positionals[0];
|
|
66
|
+
if (!filePath) {
|
|
67
|
+
console.error("Error: No EPUB file specified");
|
|
68
|
+
console.error("Run with --help for usage information");
|
|
69
|
+
process.exit(2);
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
if (!values.quiet) {
|
|
73
|
+
console.log(`Validating: ${basename(filePath)}`);
|
|
74
|
+
console.log();
|
|
75
|
+
}
|
|
76
|
+
const epubData = await readFile(filePath);
|
|
77
|
+
const startTime = Date.now();
|
|
78
|
+
const options = {};
|
|
79
|
+
if (values.profile) {
|
|
80
|
+
options.profile = values.profile;
|
|
81
|
+
}
|
|
82
|
+
if (values.usage) {
|
|
83
|
+
options.includeUsage = true;
|
|
84
|
+
}
|
|
85
|
+
const result = await EpubCheck.validate(epubData, options);
|
|
86
|
+
const elapsedMs = Date.now() - startTime;
|
|
87
|
+
if (values.json !== void 0) {
|
|
88
|
+
const jsonContent = toJSONReport(result);
|
|
89
|
+
if (values.json === "-") {
|
|
90
|
+
if (values.quiet) {
|
|
91
|
+
console.log(jsonContent);
|
|
92
|
+
} else {
|
|
93
|
+
console.log("\nJSON Report:");
|
|
94
|
+
console.log(jsonContent);
|
|
95
|
+
}
|
|
96
|
+
} else if (typeof values.json === "string") {
|
|
97
|
+
await writeFile(values.json, jsonContent, "utf-8");
|
|
98
|
+
if (!values.quiet) {
|
|
99
|
+
console.log(`JSON report written to: ${values.json}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (!values.quiet) {
|
|
104
|
+
const fatal = result.messages.filter((m) => m.severity === "fatal");
|
|
105
|
+
const errors = result.messages.filter((m) => m.severity === "error");
|
|
106
|
+
const warnings = result.messages.filter(
|
|
107
|
+
(m) => m.severity === "warning"
|
|
108
|
+
);
|
|
109
|
+
const info = result.messages.filter((m) => m.severity === "info");
|
|
110
|
+
const usage = result.messages.filter((m) => m.severity === "usage");
|
|
111
|
+
const printMessages = (messages, color, label) => {
|
|
112
|
+
if (messages.length === 0) return;
|
|
113
|
+
for (const msg of messages) {
|
|
114
|
+
const locationStr = msg.location ? ` (${msg.location.path}${msg.location.line !== void 0 ? `:${String(msg.location.line)}` : ""})` : "";
|
|
115
|
+
console.log(`${color}${label}${locationStr}: ${msg.message}\x1B[0m`);
|
|
116
|
+
if (msg.id) {
|
|
117
|
+
console.log(` \x1B[90mID: ${msg.id}\x1B[0m`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
console.log();
|
|
121
|
+
};
|
|
122
|
+
if (fatal.length > 0) {
|
|
123
|
+
printMessages(fatal, "\x1B[31m\x1B[1m", "FATAL");
|
|
124
|
+
}
|
|
125
|
+
if (errors.length > 0) {
|
|
126
|
+
printMessages(errors, "\x1B[31m", "ERROR");
|
|
127
|
+
}
|
|
128
|
+
if (warnings.length > 0) {
|
|
129
|
+
printMessages(warnings, "\x1B[33m", "WARNING");
|
|
130
|
+
}
|
|
131
|
+
if (info.length > 0 && result.messages.length < 20) {
|
|
132
|
+
printMessages(info, "\x1B[36m", "INFO");
|
|
133
|
+
}
|
|
134
|
+
if (usage.length > 0) {
|
|
135
|
+
printMessages(usage, "\x1B[90m", "USAGE");
|
|
136
|
+
}
|
|
137
|
+
console.log("\u2500".repeat(60));
|
|
138
|
+
const summaryColor = result.valid ? "\x1B[32m" : "\x1B[31m";
|
|
139
|
+
const summaryIcon = result.valid ? "\u2713" : "\u2717";
|
|
140
|
+
console.log(
|
|
141
|
+
`${summaryColor}${summaryIcon} ${result.valid ? "Valid EPUB" : "Invalid EPUB"}\x1B[0m`
|
|
142
|
+
);
|
|
143
|
+
console.log();
|
|
144
|
+
console.log(` Errors: ${String(result.errorCount + result.fatalCount)}`);
|
|
145
|
+
console.log(` Warnings: ${String(result.warningCount)}`);
|
|
146
|
+
if (info.length > 0) {
|
|
147
|
+
console.log(` Info: ${String(result.infoCount)}`);
|
|
148
|
+
}
|
|
149
|
+
if (usage.length > 0) {
|
|
150
|
+
console.log(` Usages: ${String(result.usageCount)}`);
|
|
151
|
+
}
|
|
152
|
+
console.log(` Time: ${String(elapsedMs)}ms`);
|
|
153
|
+
console.log();
|
|
154
|
+
if (result.errorCount === 0 && result.fatalCount === 0) {
|
|
155
|
+
console.log(
|
|
156
|
+
"\x1B[90mNote: This validator provides ~65% coverage of Java EPUBCheck.\x1B[0m"
|
|
157
|
+
);
|
|
158
|
+
console.log("\x1B[90mFor complete validation: https://github.com/w3c/epubcheck\x1B[0m");
|
|
159
|
+
console.log();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const shouldFail = result.errorCount > 0 || result.fatalCount > 0 || values["fail-on-warnings"] && result.warningCount > 0;
|
|
163
|
+
process.exit(shouldFail ? 1 : 0);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error("\x1B[31mError:\x1B[0m", error instanceof Error ? error.message : String(error));
|
|
166
|
+
if (error instanceof Error && error.stack && !values.quiet) {
|
|
167
|
+
console.error("\x1B[90m" + error.stack + "\x1B[0m");
|
|
168
|
+
}
|
|
169
|
+
process.exit(2);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
void main();
|
package/bin/epubcheck.ts
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* EPUBCheck-TS CLI
|
|
4
|
+
*
|
|
5
|
+
* A minimalist command-line interface for EPUB validation.
|
|
6
|
+
* For full EPUBCheck features, use the official Java version:
|
|
7
|
+
* https://github.com/w3c/epubcheck
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
11
|
+
import { parseArgs } from 'node:util';
|
|
12
|
+
import { basename } from 'node:path';
|
|
13
|
+
|
|
14
|
+
// Dynamic import to support both ESM and CJS builds
|
|
15
|
+
const { EpubCheck, toJSONReport } = await import('../dist/index.js');
|
|
16
|
+
|
|
17
|
+
const VERSION = '0.2.2';
|
|
18
|
+
|
|
19
|
+
// Parse command line arguments
|
|
20
|
+
const { values, positionals } = parseArgs({
|
|
21
|
+
options: {
|
|
22
|
+
json: { type: 'string', short: 'j' },
|
|
23
|
+
quiet: { type: 'boolean', short: 'q', default: false },
|
|
24
|
+
profile: { type: 'string', short: 'p' },
|
|
25
|
+
usage: { type: 'boolean', short: 'u', default: false },
|
|
26
|
+
version: { type: 'boolean', short: 'v', default: false },
|
|
27
|
+
help: { type: 'boolean', short: 'h', default: false },
|
|
28
|
+
'fail-on-warnings': { type: 'boolean', short: 'w', default: false },
|
|
29
|
+
},
|
|
30
|
+
allowPositionals: true,
|
|
31
|
+
strict: false,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Show version
|
|
35
|
+
if (values.version) {
|
|
36
|
+
console.log(`EPUBCheck-TS v${VERSION}`);
|
|
37
|
+
console.log('TypeScript EPUB validator for Node.js and browsers');
|
|
38
|
+
console.log();
|
|
39
|
+
console.log('Note: This is ~65% feature-complete compared to Java EPUBCheck.');
|
|
40
|
+
console.log('For production validation: https://github.com/w3c/epubcheck');
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Show help
|
|
45
|
+
if (values.help || positionals.length === 0) {
|
|
46
|
+
console.log(`EPUBCheck-TS v${VERSION} - EPUB Validator
|
|
47
|
+
|
|
48
|
+
Usage: epubcheck-ts <file.epub> [options]
|
|
49
|
+
|
|
50
|
+
Arguments:
|
|
51
|
+
<file.epub> Path to EPUB file to validate
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
-j, --json <file> Output JSON report to file (use '-' for stdout)
|
|
55
|
+
-q, --quiet Suppress console output (errors only)
|
|
56
|
+
-p, --profile <name> Validation profile (default|dict|edupub|idx|preview)
|
|
57
|
+
-u, --usage Include usage messages (best practices)
|
|
58
|
+
-w, --fail-on-warnings Exit with code 1 if warnings are found
|
|
59
|
+
-v, --version Show version information
|
|
60
|
+
-h, --help Show this help message
|
|
61
|
+
|
|
62
|
+
Examples:
|
|
63
|
+
epubcheck-ts book.epub
|
|
64
|
+
epubcheck-ts book.epub --json report.json
|
|
65
|
+
epubcheck-ts book.epub --quiet --fail-on-warnings
|
|
66
|
+
epubcheck-ts book.epub --profile dict
|
|
67
|
+
|
|
68
|
+
Exit Codes:
|
|
69
|
+
0 No errors (or only warnings if --fail-on-warnings not set)
|
|
70
|
+
1 Validation errors found (or warnings with --fail-on-warnings)
|
|
71
|
+
2 Runtime error (file not found, invalid arguments, etc.)
|
|
72
|
+
|
|
73
|
+
Note: This tool provides ~65% coverage of Java EPUBCheck features.
|
|
74
|
+
Missing features: Media Overlays, advanced ARIA checks, encryption/signatures.
|
|
75
|
+
For complete EPUB 3 conformance testing, use: https://github.com/w3c/epubcheck
|
|
76
|
+
|
|
77
|
+
Report issues: https://github.com/likecoin/epubcheck-ts/issues
|
|
78
|
+
`);
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Main validation logic
|
|
83
|
+
async function main(): Promise<void> {
|
|
84
|
+
const filePath = positionals[0];
|
|
85
|
+
|
|
86
|
+
if (!filePath) {
|
|
87
|
+
console.error('Error: No EPUB file specified');
|
|
88
|
+
console.error('Run with --help for usage information');
|
|
89
|
+
process.exit(2);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
// Read EPUB file
|
|
94
|
+
if (!values.quiet) {
|
|
95
|
+
console.log(`Validating: ${basename(filePath)}`);
|
|
96
|
+
console.log();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const epubData = await readFile(filePath);
|
|
100
|
+
|
|
101
|
+
// Validate
|
|
102
|
+
const startTime = Date.now();
|
|
103
|
+
const options: {
|
|
104
|
+
profile?: 'default' | 'dict' | 'edupub' | 'idx' | 'preview';
|
|
105
|
+
includeUsage?: boolean;
|
|
106
|
+
} = {};
|
|
107
|
+
if (values.profile) {
|
|
108
|
+
options.profile = values.profile as 'default' | 'dict' | 'edupub' | 'idx' | 'preview';
|
|
109
|
+
}
|
|
110
|
+
if (values.usage) {
|
|
111
|
+
options.includeUsage = true;
|
|
112
|
+
}
|
|
113
|
+
const result = await EpubCheck.validate(epubData, options);
|
|
114
|
+
const elapsedMs = Date.now() - startTime;
|
|
115
|
+
|
|
116
|
+
// Output JSON report if requested
|
|
117
|
+
if (values.json !== undefined) {
|
|
118
|
+
const jsonContent = toJSONReport(result); // Already stringified
|
|
119
|
+
|
|
120
|
+
if (values.json === '-') {
|
|
121
|
+
// Output to stdout - suppress other output
|
|
122
|
+
if (values.quiet) {
|
|
123
|
+
console.log(jsonContent);
|
|
124
|
+
} else {
|
|
125
|
+
// If not quiet, output after other messages
|
|
126
|
+
console.log('\nJSON Report:');
|
|
127
|
+
console.log(jsonContent);
|
|
128
|
+
}
|
|
129
|
+
} else if (typeof values.json === 'string') {
|
|
130
|
+
await writeFile(values.json, jsonContent, 'utf-8');
|
|
131
|
+
if (!values.quiet) {
|
|
132
|
+
console.log(`JSON report written to: ${values.json}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Console output (unless quiet mode)
|
|
138
|
+
if (!values.quiet) {
|
|
139
|
+
// Group messages by severity
|
|
140
|
+
const fatal = result.messages.filter((m: { severity: string }) => m.severity === 'fatal');
|
|
141
|
+
const errors = result.messages.filter((m: { severity: string }) => m.severity === 'error');
|
|
142
|
+
const warnings = result.messages.filter(
|
|
143
|
+
(m: { severity: string }) => m.severity === 'warning',
|
|
144
|
+
);
|
|
145
|
+
const info = result.messages.filter((m: { severity: string }) => m.severity === 'info');
|
|
146
|
+
const usage = result.messages.filter((m: { severity: string }) => m.severity === 'usage');
|
|
147
|
+
|
|
148
|
+
// Print messages with colors
|
|
149
|
+
const printMessages = (
|
|
150
|
+
messages: typeof result.messages,
|
|
151
|
+
color: string,
|
|
152
|
+
label: string,
|
|
153
|
+
): void => {
|
|
154
|
+
if (messages.length === 0) return;
|
|
155
|
+
|
|
156
|
+
for (const msg of messages) {
|
|
157
|
+
const locationStr = msg.location
|
|
158
|
+
? ` (${msg.location.path}${msg.location.line !== undefined ? `:${String(msg.location.line)}` : ''})`
|
|
159
|
+
: '';
|
|
160
|
+
console.log(`${color}${label}${locationStr}: ${msg.message}\x1b[0m`);
|
|
161
|
+
if (msg.id) {
|
|
162
|
+
console.log(` \x1b[90mID: ${msg.id}\x1b[0m`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
console.log();
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
if (fatal.length > 0) {
|
|
169
|
+
printMessages(fatal, '\x1b[31m\x1b[1m', 'FATAL');
|
|
170
|
+
}
|
|
171
|
+
if (errors.length > 0) {
|
|
172
|
+
printMessages(errors, '\x1b[31m', 'ERROR');
|
|
173
|
+
}
|
|
174
|
+
if (warnings.length > 0) {
|
|
175
|
+
printMessages(warnings, '\x1b[33m', 'WARNING');
|
|
176
|
+
}
|
|
177
|
+
if (info.length > 0 && result.messages.length < 20) {
|
|
178
|
+
// Only show info if total messages is small
|
|
179
|
+
printMessages(info, '\x1b[36m', 'INFO');
|
|
180
|
+
}
|
|
181
|
+
if (usage.length > 0) {
|
|
182
|
+
printMessages(usage, '\x1b[90m', 'USAGE');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Summary
|
|
186
|
+
console.log('─'.repeat(60));
|
|
187
|
+
const summaryColor = result.valid ? '\x1b[32m' : '\x1b[31m';
|
|
188
|
+
const summaryIcon = result.valid ? '✓' : '✗';
|
|
189
|
+
console.log(
|
|
190
|
+
`${summaryColor}${summaryIcon} ${result.valid ? 'Valid EPUB' : 'Invalid EPUB'}\x1b[0m`,
|
|
191
|
+
);
|
|
192
|
+
console.log();
|
|
193
|
+
console.log(` Errors: ${String(result.errorCount + result.fatalCount)}`);
|
|
194
|
+
console.log(` Warnings: ${String(result.warningCount)}`);
|
|
195
|
+
if (info.length > 0) {
|
|
196
|
+
console.log(` Info: ${String(result.infoCount)}`);
|
|
197
|
+
}
|
|
198
|
+
if (usage.length > 0) {
|
|
199
|
+
console.log(` Usages: ${String(result.usageCount)}`);
|
|
200
|
+
}
|
|
201
|
+
console.log(` Time: ${String(elapsedMs)}ms`);
|
|
202
|
+
console.log();
|
|
203
|
+
|
|
204
|
+
// Show limitation notice if there were no major errors
|
|
205
|
+
if (result.errorCount === 0 && result.fatalCount === 0) {
|
|
206
|
+
console.log(
|
|
207
|
+
'\x1b[90mNote: This validator provides ~65% coverage of Java EPUBCheck.\x1b[0m',
|
|
208
|
+
);
|
|
209
|
+
console.log('\x1b[90mFor complete validation: https://github.com/w3c/epubcheck\x1b[0m');
|
|
210
|
+
console.log();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Determine exit code
|
|
215
|
+
const shouldFail =
|
|
216
|
+
result.errorCount > 0 ||
|
|
217
|
+
result.fatalCount > 0 ||
|
|
218
|
+
(values['fail-on-warnings'] && result.warningCount > 0);
|
|
219
|
+
process.exit(shouldFail ? 1 : 0);
|
|
220
|
+
} catch (error) {
|
|
221
|
+
console.error('\x1b[31mError:\x1b[0m', error instanceof Error ? error.message : String(error));
|
|
222
|
+
if (error instanceof Error && error.stack && !values.quiet) {
|
|
223
|
+
console.error('\x1b[90m' + error.stack + '\x1b[0m');
|
|
224
|
+
}
|
|
225
|
+
process.exit(2);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
void main();
|