@likecoin/epubcheck-ts 0.3.9 → 0.5.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/README.md +36 -23
- package/bin/epubcheck.js +173 -40
- package/bin/epubcheck.ts +225 -50
- package/dist/index.cjs +8710 -6629
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +511 -394
- package/dist/index.d.ts +511 -394
- package/dist/index.js +8710 -6631
- package/dist/index.js.map +1 -1
- package/package.json +21 -5
package/README.md
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
# epubcheck-ts
|
|
2
2
|
|
|
3
|
-
A TypeScript
|
|
3
|
+
Validate EPUB files in Node.js and the browser. A TypeScript implementation of [EPUBCheck](https://github.com/w3c/epubcheck).
|
|
4
4
|
|
|
5
5
|
[](https://github.com/likecoin/epubcheck-ts/actions/workflows/ci.yml)
|
|
6
6
|
[](https://www.npmjs.com/package/@likecoin/epubcheck-ts)
|
|
7
7
|
[](./LICENSE)
|
|
8
8
|
|
|
9
|
-
> **
|
|
9
|
+
> **Status**: 93% feature parity with Java EPUBCheck (1061 tests passing, 74 skipped). See [PROJECT_STATUS.md](./PROJECT_STATUS.md) for details. For full EPUB 3 conformance testing, use the official [Java EPUBCheck](https://github.com/w3c/epubcheck).
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
|
-
- **CLI and
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **Tree-shakable**: ESM with proper exports for optimal bundling
|
|
13
|
+
- **CLI and API** — Use as a CLI tool (`npx @likecoin/epubcheck-ts book.epub`) or import as a library
|
|
14
|
+
- **Browser support** — Works in Node.js 18+ and modern browsers via pure JS + WASM
|
|
15
|
+
- **No native dependencies** — No Java, no compilation — `npm install` and go
|
|
16
|
+
- **TypeScript** — Full type definitions included
|
|
17
|
+
- **Tree-shakable** — ESM with proper exports for minimal bundle impact
|
|
19
18
|
|
|
20
19
|
## Try it Online
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
Live demo at **[likecoin.github.io/epubcheck-ts](https://likecoin.github.io/epubcheck-ts/)** — validate EPUB files in the browser without uploading to any server.
|
|
23
22
|
|
|
24
23
|
## Installation
|
|
25
24
|
|
|
@@ -50,7 +49,13 @@ Options:
|
|
|
50
49
|
-j, --json <file> Output JSON report to file (use '-' for stdout)
|
|
51
50
|
-q, --quiet Suppress console output (errors only)
|
|
52
51
|
-p, --profile <name> Validation profile (default|dict|edupub|idx|preview)
|
|
52
|
+
-u, --usage Include usage messages (best practices)
|
|
53
|
+
-f, --fatal Show only fatal errors
|
|
54
|
+
-e, --error Show fatal errors and errors
|
|
55
|
+
--warn Show fatal errors, errors, and warnings
|
|
56
|
+
-c, --customMessages <file> Override message severities (TSV: ID<tab>SEVERITY)
|
|
53
57
|
-w, --fail-on-warnings Exit with code 1 if warnings are found
|
|
58
|
+
-l, --listChecks List all message IDs and severities
|
|
54
59
|
-v, --version Show version information
|
|
55
60
|
-h, --help Show this help message
|
|
56
61
|
```
|
|
@@ -68,9 +73,14 @@ epubcheck-ts book.epub --quiet --fail-on-warnings
|
|
|
68
73
|
|
|
69
74
|
# Validate with specific profile
|
|
70
75
|
epubcheck-ts dictionary.epub --profile dict
|
|
71
|
-
```
|
|
72
76
|
|
|
73
|
-
|
|
77
|
+
# Show only errors (hide warnings/info)
|
|
78
|
+
epubcheck-ts book.epub --error
|
|
79
|
+
|
|
80
|
+
# Enable suppressed accessibility checks
|
|
81
|
+
printf "ACC-004\tWARNING\nACC-005\tWARNING\n" > overrides.txt
|
|
82
|
+
epubcheck-ts book.epub -c overrides.txt
|
|
83
|
+
```
|
|
74
84
|
|
|
75
85
|
### ES Modules (recommended)
|
|
76
86
|
|
|
@@ -181,6 +191,9 @@ interface EpubCheckOptions {
|
|
|
181
191
|
|
|
182
192
|
/** Locale for messages (default: 'en') */
|
|
183
193
|
locale?: string;
|
|
194
|
+
|
|
195
|
+
/** Custom message severity overrides (message ID → severity) */
|
|
196
|
+
customMessages?: Map<string, MessageSeverity>;
|
|
184
197
|
}
|
|
185
198
|
```
|
|
186
199
|
|
|
@@ -266,20 +279,20 @@ This library is a TypeScript port of the Java-based [EPUBCheck](https://github.c
|
|
|
266
279
|
|
|
267
280
|
| Component | Status | Completeness | Notes |
|
|
268
281
|
|-----------|--------|--------------|-------|
|
|
269
|
-
| OCF Container |
|
|
270
|
-
| Package Document (OPF) | 🟢 Complete | ~
|
|
271
|
-
| Content Documents |
|
|
272
|
-
| Navigation Document | 🟢 Complete | ~
|
|
273
|
-
| Schema Validation | 🟡 Partial | ~
|
|
274
|
-
| CSS | 🟡 Partial | ~
|
|
275
|
-
| Cross-reference Validation | 🟢 Complete | ~
|
|
276
|
-
| Accessibility Checks |
|
|
277
|
-
| Media Overlays |
|
|
282
|
+
| OCF Container | 🟢 Complete | ~92% | ZIP structure, mimetype, container.xml, encryption.xml obfuscation |
|
|
283
|
+
| Package Document (OPF) | 🟢 Complete | ~92% | Metadata, manifest, spine, collections, Schematron-equivalent checks |
|
|
284
|
+
| Content Documents | 🟢 Complete | ~93% | XHTML structure, CSS url(), @import, SVG, entities, title, SSML, XML version |
|
|
285
|
+
| Navigation Document | 🟢 Complete | ~95% | Nav content model, landmarks, labels, reading order, hidden, nested-ol |
|
|
286
|
+
| Schema Validation | 🟡 Partial | ~55% | RelaxNG for OPF/container; XHTML/SVG disabled (libxml2 limitation) |
|
|
287
|
+
| CSS | 🟡 Partial | ~85% | @font-face, @import, url() extraction, position, forbidden properties, alt style tags |
|
|
288
|
+
| Cross-reference Validation | 🟢 Complete | ~92% | Reference tracking, fragments, fallbacks, remote resources, cross-document features |
|
|
289
|
+
| Accessibility Checks | 🟢 Complete | ~71% | 12/17 ACC checks: table, image alt, hyperlink, MathML, SVG, epub:type, OPF metadata |
|
|
290
|
+
| Media Overlays | 🟡 Partial | ~70% | SMIL structure, timing, audio, OPF metadata, duration validation |
|
|
278
291
|
| Media Validation | ❌ Not Started | 0% | Planned |
|
|
279
292
|
|
|
280
293
|
Legend: 🟢 Complete | 🟡 Partial | 🔴 Basic | ❌ Not Started
|
|
281
294
|
|
|
282
|
-
**Overall Progress: ~
|
|
295
|
+
**Overall Progress: ~93% of Java EPUBCheck features**
|
|
283
296
|
|
|
284
297
|
See [PROJECT_STATUS.md](./PROJECT_STATUS.md) for detailed comparison.
|
|
285
298
|
|
|
@@ -364,13 +377,13 @@ Legend: ✅ Implemented
|
|
|
364
377
|
| Aspect | epubcheck-ts | EPUBCheck (Java) |
|
|
365
378
|
|--------|--------------|------------------|
|
|
366
379
|
| Runtime | Node.js / Browser | JVM |
|
|
367
|
-
| Feature Parity | ~
|
|
380
|
+
| Feature Parity | ~93% | 100% |
|
|
368
381
|
| Bundle Size | ~450KB JS + ~1.6MB WASM | ~15MB |
|
|
369
382
|
| Installation | `npm install` | Download JAR |
|
|
370
383
|
| Integration | Native JS/TS | CLI or Java API |
|
|
371
384
|
| Performance | Comparable | Baseline |
|
|
372
385
|
|
|
373
|
-
|
|
386
|
+
See [PROJECT_STATUS.md](./PROJECT_STATUS.md) for detailed feature comparison.
|
|
374
387
|
|
|
375
388
|
## Contributing
|
|
376
389
|
|
package/bin/epubcheck.js
CHANGED
|
@@ -1,28 +1,60 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
3
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.
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
4
|
+
import { basename, join, relative, sep } from "node:path";
|
|
5
|
+
const { EpubCheck, EPUB_VERSIONS, toJSONReport } = await import("../dist/index.js");
|
|
6
|
+
const VERSION = "0.5.0";
|
|
7
|
+
const VALID_MODES = /* @__PURE__ */ new Set([
|
|
8
|
+
"exp",
|
|
9
|
+
"opf",
|
|
10
|
+
"xhtml",
|
|
11
|
+
"svg",
|
|
12
|
+
"nav",
|
|
13
|
+
"mo"
|
|
14
|
+
]);
|
|
15
|
+
let values;
|
|
16
|
+
let positionals;
|
|
17
|
+
try {
|
|
18
|
+
({ values, positionals } = parseArgs({
|
|
19
|
+
options: {
|
|
20
|
+
json: { type: "string", short: "j" },
|
|
21
|
+
quiet: { type: "boolean", short: "q", default: false },
|
|
22
|
+
profile: { type: "string", short: "p" },
|
|
23
|
+
mode: { type: "string", short: "m" },
|
|
24
|
+
"epub-version": { type: "string", short: "v" },
|
|
25
|
+
usage: { type: "boolean", short: "u", default: false },
|
|
26
|
+
fatal: { type: "boolean", short: "f", default: false },
|
|
27
|
+
error: { type: "boolean", short: "e", default: false },
|
|
28
|
+
warn: { type: "boolean", short: "w", default: false },
|
|
29
|
+
info: { type: "boolean", short: "i", default: false },
|
|
30
|
+
customMessages: { type: "string", short: "c" },
|
|
31
|
+
version: { type: "boolean", short: "V", default: false },
|
|
32
|
+
help: { type: "boolean", short: "h", default: false },
|
|
33
|
+
"fail-on-warnings": { type: "boolean", default: false },
|
|
34
|
+
failonwarnings: { type: "boolean", default: false },
|
|
35
|
+
listChecks: { type: "boolean", short: "l", default: false }
|
|
36
|
+
},
|
|
37
|
+
allowPositionals: true,
|
|
38
|
+
strict: true
|
|
39
|
+
}));
|
|
40
|
+
} catch (err) {
|
|
41
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
42
|
+
console.error(`\x1B[31mError:\x1B[0m ${message}`);
|
|
43
|
+
const unsupportedJavaFlags = ["--out", "-o", "--xmp", "-x", "--save", "--locale"];
|
|
44
|
+
const matched = unsupportedJavaFlags.find((f) => message.includes(f));
|
|
45
|
+
if (matched) {
|
|
46
|
+
console.error(
|
|
47
|
+
`\x1B[90mNote: ${matched} is a Java EPUBCheck flag that epubcheck-ts does not yet support.\x1B[0m`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
console.error("Run with --help for usage information");
|
|
51
|
+
process.exit(2);
|
|
52
|
+
}
|
|
21
53
|
if (values.version) {
|
|
22
54
|
console.log(`EPUBCheck-TS v${VERSION}`);
|
|
23
55
|
console.log("TypeScript EPUB validator for Node.js and browsers");
|
|
24
56
|
console.log();
|
|
25
|
-
console.log("Note: This is ~
|
|
57
|
+
console.log("Note: This is ~93% feature-complete compared to Java EPUBCheck.");
|
|
26
58
|
console.log("For production validation: https://github.com/w3c/epubcheck");
|
|
27
59
|
process.exit(0);
|
|
28
60
|
}
|
|
@@ -35,65 +67,165 @@ if (values.listChecks) {
|
|
|
35
67
|
if (values.help || positionals.length === 0) {
|
|
36
68
|
console.log(`EPUBCheck-TS v${VERSION} - EPUB Validator
|
|
37
69
|
|
|
38
|
-
Usage: epubcheck-ts <file
|
|
70
|
+
Usage: epubcheck-ts <file> [options]
|
|
39
71
|
|
|
40
72
|
Arguments:
|
|
41
|
-
<file
|
|
73
|
+
<file> Path to EPUB file, directory, or single file to validate
|
|
42
74
|
|
|
43
75
|
Options:
|
|
44
76
|
-j, --json <file> Output JSON report to file (use '-' for stdout)
|
|
45
77
|
-q, --quiet Suppress console output (errors only)
|
|
46
78
|
-p, --profile <name> Validation profile (default|dict|edupub|idx|preview)
|
|
79
|
+
-m, --mode <type> Validation mode: exp (expanded directory), opf, xhtml, svg, nav, mo
|
|
80
|
+
-v, --epub-version <ver> EPUB version for single-file mode (2|2.0|3|3.0|3.1|3.2|3.3)
|
|
47
81
|
-u, --usage Include usage messages (best practices)
|
|
48
|
-
-
|
|
82
|
+
-f, --fatal Show only fatal errors
|
|
83
|
+
-e, --error Show fatal errors and errors
|
|
84
|
+
-w, --warn Show fatal errors, errors, and warnings
|
|
85
|
+
-i, --info Show fatal, error, warning, and info messages
|
|
86
|
+
-c, --customMessages <file> Override message severities (TSV: ID\\tSEVERITY)
|
|
87
|
+
--fail-on-warnings Exit with code 1 if warnings are found
|
|
88
|
+
(also accepts --failonwarnings for Java compatibility)
|
|
49
89
|
-l, --listChecks List all message IDs and severities
|
|
50
|
-
-
|
|
90
|
+
-V, --version Show version information
|
|
51
91
|
-h, --help Show this help message
|
|
52
92
|
|
|
93
|
+
Modes:
|
|
94
|
+
--mode exp Validate an expanded (unpacked) EPUB directory
|
|
95
|
+
--mode opf -v 3.0 Validate a standalone OPF package document
|
|
96
|
+
--mode xhtml -v 3.0 Validate a standalone XHTML content document
|
|
97
|
+
--mode svg -v 3.0 Validate a standalone SVG content document
|
|
98
|
+
--mode nav -v 3.0 Validate a standalone Navigation Document (EPUB 3 only)
|
|
99
|
+
--mode mo -v 3.0 Validate a standalone SMIL media overlay document
|
|
100
|
+
|
|
53
101
|
Examples:
|
|
54
102
|
epubcheck-ts book.epub
|
|
55
103
|
epubcheck-ts book.epub --json report.json
|
|
56
104
|
epubcheck-ts book.epub --quiet --fail-on-warnings
|
|
57
105
|
epubcheck-ts book.epub --profile dict
|
|
106
|
+
epubcheck-ts ./unpacked-epub/ --mode exp
|
|
107
|
+
epubcheck-ts chapter.xhtml --mode xhtml -v 3.0
|
|
108
|
+
epubcheck-ts package.opf --mode opf -v 3.0
|
|
109
|
+
epubcheck-ts image.svg --mode svg -v 3.0
|
|
110
|
+
epubcheck-ts nav.xhtml --mode nav -v 3.0
|
|
111
|
+
epubcheck-ts overlay.smil --mode mo -v 3.0
|
|
58
112
|
|
|
59
113
|
Exit Codes:
|
|
60
114
|
0 No errors (or only warnings if --fail-on-warnings not set)
|
|
61
115
|
1 Validation errors found (or warnings with --fail-on-warnings)
|
|
62
116
|
2 Runtime error (file not found, invalid arguments, etc.)
|
|
63
117
|
|
|
64
|
-
Note: This tool provides ~88% coverage of Java EPUBCheck features.
|
|
65
|
-
Missing features: Media Overlays, advanced ARIA checks, encryption/signatures.
|
|
66
|
-
For complete EPUB 3 conformance testing, use: https://github.com/w3c/epubcheck
|
|
67
|
-
|
|
68
118
|
Report issues: https://github.com/likecoin/epubcheck-ts/issues
|
|
69
119
|
`);
|
|
70
120
|
process.exit(0);
|
|
71
121
|
}
|
|
122
|
+
async function readDirectoryFiles(dirPath) {
|
|
123
|
+
const files = /* @__PURE__ */ new Map();
|
|
124
|
+
async function walk(dir) {
|
|
125
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
126
|
+
for (const entry of entries) {
|
|
127
|
+
const fullPath = join(dir, entry.name);
|
|
128
|
+
if (entry.isDirectory()) {
|
|
129
|
+
await walk(fullPath);
|
|
130
|
+
} else if (entry.isFile()) {
|
|
131
|
+
const relPath = relative(dirPath, fullPath).split(sep).join("/");
|
|
132
|
+
const data = await readFile(fullPath);
|
|
133
|
+
files.set(relPath, data);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
await walk(dirPath);
|
|
138
|
+
return files;
|
|
139
|
+
}
|
|
72
140
|
async function main() {
|
|
73
141
|
const filePath = positionals[0];
|
|
74
142
|
if (!filePath) {
|
|
75
|
-
console.error("Error: No
|
|
143
|
+
console.error("Error: No file specified");
|
|
76
144
|
console.error("Run with --help for usage information");
|
|
77
145
|
process.exit(2);
|
|
78
146
|
}
|
|
147
|
+
const mode = values.mode;
|
|
148
|
+
if (mode && !VALID_MODES.has(mode)) {
|
|
149
|
+
console.error(`Error: Invalid mode "${mode}". Valid modes: ${[...VALID_MODES].join(", ")}`);
|
|
150
|
+
process.exit(2);
|
|
151
|
+
}
|
|
152
|
+
const rawVersion = values["epub-version"];
|
|
153
|
+
const epubVersion = rawVersion === "2" ? "2.0" : rawVersion === "3" ? "3.0" : rawVersion;
|
|
154
|
+
if (epubVersion && !EPUB_VERSIONS.includes(epubVersion)) {
|
|
155
|
+
console.error(
|
|
156
|
+
`Error: Invalid EPUB version "${epubVersion}". Valid versions: ${EPUB_VERSIONS.join(", ")}`
|
|
157
|
+
);
|
|
158
|
+
process.exit(2);
|
|
159
|
+
}
|
|
160
|
+
if (mode && mode !== "exp" && !epubVersion) {
|
|
161
|
+
console.error(`Error: --epub-version (-v) is required when using --mode ${mode}`);
|
|
162
|
+
process.exit(2);
|
|
163
|
+
}
|
|
79
164
|
try {
|
|
80
165
|
if (!values.quiet) {
|
|
81
166
|
console.log(`Validating: ${basename(filePath)}`);
|
|
82
167
|
console.log();
|
|
83
168
|
}
|
|
84
|
-
const epubData = await readFile(filePath);
|
|
85
|
-
const startTime = Date.now();
|
|
86
169
|
const options = {};
|
|
87
170
|
if (values.profile) {
|
|
88
171
|
options.profile = values.profile;
|
|
89
172
|
}
|
|
173
|
+
if (epubVersion) {
|
|
174
|
+
options.version = epubVersion;
|
|
175
|
+
}
|
|
176
|
+
if (mode) {
|
|
177
|
+
options.mode = mode;
|
|
178
|
+
}
|
|
90
179
|
if (values.usage) {
|
|
91
180
|
options.includeUsage = true;
|
|
92
181
|
}
|
|
93
|
-
|
|
182
|
+
if (typeof values.customMessages === "string") {
|
|
183
|
+
const { parseCustomMessages } = await import("../dist/index.js");
|
|
184
|
+
const cmContent = await readFile(values.customMessages, "utf-8");
|
|
185
|
+
options.customMessages = parseCustomMessages(cmContent);
|
|
186
|
+
}
|
|
187
|
+
const startTime = Date.now();
|
|
188
|
+
let result;
|
|
189
|
+
let effectiveMode = mode;
|
|
190
|
+
if (!mode || mode === "exp") {
|
|
191
|
+
const fileStat = await stat(filePath);
|
|
192
|
+
if (fileStat.isDirectory()) {
|
|
193
|
+
effectiveMode = "exp";
|
|
194
|
+
} else if (mode === "exp") {
|
|
195
|
+
console.error("Error: --mode exp requires a directory path");
|
|
196
|
+
process.exit(2);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (effectiveMode === "exp") {
|
|
200
|
+
const files = await readDirectoryFiles(filePath);
|
|
201
|
+
result = await EpubCheck.validateExpanded(files, options);
|
|
202
|
+
} else if (effectiveMode === "opf" || effectiveMode === "xhtml" || effectiveMode === "svg" || effectiveMode === "nav" || effectiveMode === "mo") {
|
|
203
|
+
const fileData = await readFile(filePath);
|
|
204
|
+
result = await EpubCheck.validateSingleFile(fileData, basename(filePath), options);
|
|
205
|
+
} else {
|
|
206
|
+
const epubData = await readFile(filePath);
|
|
207
|
+
result = await EpubCheck.validate(epubData, options, basename(filePath));
|
|
208
|
+
}
|
|
94
209
|
const elapsedMs = Date.now() - startTime;
|
|
210
|
+
const severityRank = {
|
|
211
|
+
fatal: 0,
|
|
212
|
+
error: 1,
|
|
213
|
+
warning: 2,
|
|
214
|
+
info: 3,
|
|
215
|
+
usage: 4
|
|
216
|
+
};
|
|
217
|
+
let maxRank = 4;
|
|
218
|
+
if (values.fatal) maxRank = 0;
|
|
219
|
+
else if (values.error) maxRank = 1;
|
|
220
|
+
else if (values.warn) maxRank = 2;
|
|
221
|
+
else if (values.info) maxRank = 3;
|
|
222
|
+
const isFiltered = values.fatal || values.error || values.warn || values.info;
|
|
223
|
+
const displayMessages = result.messages.filter(
|
|
224
|
+
(m) => severityRank[m.severity] <= maxRank
|
|
225
|
+
);
|
|
95
226
|
if (values.json !== void 0) {
|
|
96
|
-
const
|
|
227
|
+
const filteredResult = isFiltered ? { ...result, messages: displayMessages } : result;
|
|
228
|
+
const jsonContent = toJSONReport(filteredResult);
|
|
97
229
|
if (values.json === "-") {
|
|
98
230
|
if (values.quiet) {
|
|
99
231
|
console.log(jsonContent);
|
|
@@ -109,11 +241,11 @@ async function main() {
|
|
|
109
241
|
}
|
|
110
242
|
}
|
|
111
243
|
if (!values.quiet) {
|
|
112
|
-
const fatal =
|
|
113
|
-
const errors =
|
|
114
|
-
const warnings =
|
|
115
|
-
const info =
|
|
116
|
-
const usage =
|
|
244
|
+
const fatal = displayMessages.filter((m) => m.severity === "fatal");
|
|
245
|
+
const errors = displayMessages.filter((m) => m.severity === "error");
|
|
246
|
+
const warnings = displayMessages.filter((m) => m.severity === "warning");
|
|
247
|
+
const info = displayMessages.filter((m) => m.severity === "info");
|
|
248
|
+
const usage = displayMessages.filter((m) => m.severity === "usage");
|
|
117
249
|
const printMessages = (messages, color, label) => {
|
|
118
250
|
if (messages.length === 0) return;
|
|
119
251
|
for (const msg of messages) {
|
|
@@ -134,7 +266,7 @@ async function main() {
|
|
|
134
266
|
if (warnings.length > 0) {
|
|
135
267
|
printMessages(warnings, "\x1B[33m", "WARNING");
|
|
136
268
|
}
|
|
137
|
-
if (info.length > 0 &&
|
|
269
|
+
if (info.length > 0 && displayMessages.length < 20) {
|
|
138
270
|
printMessages(info, "\x1B[36m", "INFO");
|
|
139
271
|
}
|
|
140
272
|
if (usage.length > 0) {
|
|
@@ -159,13 +291,14 @@ async function main() {
|
|
|
159
291
|
console.log();
|
|
160
292
|
if (result.errorCount === 0 && result.fatalCount === 0) {
|
|
161
293
|
console.log(
|
|
162
|
-
"\x1B[90mNote: This validator provides ~
|
|
294
|
+
"\x1B[90mNote: This validator provides ~93% coverage of Java EPUBCheck.\x1B[0m"
|
|
163
295
|
);
|
|
164
296
|
console.log("\x1B[90mFor complete validation: https://github.com/w3c/epubcheck\x1B[0m");
|
|
165
297
|
console.log();
|
|
166
298
|
}
|
|
167
299
|
}
|
|
168
|
-
const
|
|
300
|
+
const failOnWarnings = values["fail-on-warnings"] || values.failonwarnings;
|
|
301
|
+
const shouldFail = result.errorCount > 0 || result.fatalCount > 0 || failOnWarnings && result.warningCount > 0;
|
|
169
302
|
process.exit(shouldFail ? 1 : 0);
|
|
170
303
|
} catch (error) {
|
|
171
304
|
console.error("\x1B[31mError:\x1B[0m", error instanceof Error ? error.message : String(error));
|