@likecoin/epubcheck-ts 0.3.1 → 0.3.3
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 +1 -1
- package/bin/epubcheck.js +1 -1
- package/bin/epubcheck.ts +1 -1
- package/dist/index.cjs +220 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +220 -33
- package/dist/index.js.map +1 -1
- package/package.json +3 -14
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ A TypeScript port of [EPUBCheck](https://github.com/w3c/epubcheck) - the officia
|
|
|
6
6
|
[](https://www.npmjs.com/package/@likecoin/epubcheck-ts)
|
|
7
7
|
[](./LICENSE)
|
|
8
8
|
|
|
9
|
-
> **Note**: This library is primarily developed for internal use at [3ook.com](https://3ook.com/about) and is built with AI-assisted development. While it has comprehensive test coverage (
|
|
9
|
+
> **Note**: This library is primarily developed for internal use at [3ook.com](https://3ook.com/about) and is built with AI-assisted development. While it has comprehensive test coverage (505 tests) and ~70% feature parity with Java EPUBCheck, it may not be suitable for mission-critical production workloads. For production environments requiring full EPUB validation, consider using the official [Java EPUBCheck](https://github.com/w3c/epubcheck). Contributions and feedback are welcome!
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
package/bin/epubcheck.js
CHANGED
|
@@ -3,7 +3,7 @@ import { readFile, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
4
|
import { basename } from "node:path";
|
|
5
5
|
const { EpubCheck, toJSONReport } = await import("../dist/index.js");
|
|
6
|
-
const VERSION = "0.3.
|
|
6
|
+
const VERSION = "0.3.3";
|
|
7
7
|
const { values, positionals } = parseArgs({
|
|
8
8
|
options: {
|
|
9
9
|
json: { type: "string", short: "j" },
|
package/bin/epubcheck.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { basename } from 'node:path';
|
|
|
14
14
|
// Dynamic import to support both ESM and CJS builds
|
|
15
15
|
const { EpubCheck, toJSONReport } = await import('../dist/index.js');
|
|
16
16
|
|
|
17
|
-
const VERSION = '0.3.
|
|
17
|
+
const VERSION = '0.3.3';
|
|
18
18
|
|
|
19
19
|
// Parse command line arguments
|
|
20
20
|
const { values, positionals } = parseArgs({
|
package/dist/index.cjs
CHANGED
|
@@ -1758,9 +1758,27 @@ var ContentValidator = class {
|
|
|
1758
1758
|
} else if (item.mediaType === "text/css" && refValidator) {
|
|
1759
1759
|
const fullPath = opfDir ? `${opfDir}/${item.href}` : item.href;
|
|
1760
1760
|
this.validateCSSDocument(context, fullPath, opfDir, refValidator);
|
|
1761
|
+
} else if (item.mediaType === "image/svg+xml" && registry) {
|
|
1762
|
+
const fullPath = opfDir ? `${opfDir}/${item.href}` : item.href;
|
|
1763
|
+
this.extractSVGIDs(context, fullPath, registry);
|
|
1761
1764
|
}
|
|
1762
1765
|
}
|
|
1763
1766
|
}
|
|
1767
|
+
extractSVGIDs(context, path, registry) {
|
|
1768
|
+
const svgData = context.files.get(path);
|
|
1769
|
+
if (!svgData) {
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
const svgContent = new TextDecoder().decode(svgData);
|
|
1773
|
+
let doc;
|
|
1774
|
+
try {
|
|
1775
|
+
doc = libxml2Wasm.XmlDocument.fromString(svgContent);
|
|
1776
|
+
this.extractAndRegisterIDs(path, doc.root, registry);
|
|
1777
|
+
} catch {
|
|
1778
|
+
} finally {
|
|
1779
|
+
doc?.dispose();
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1764
1782
|
validateCSSDocument(context, path, opfDir, refValidator) {
|
|
1765
1783
|
const cssData = context.files.get(path);
|
|
1766
1784
|
if (!cssData) {
|
|
@@ -1958,9 +1976,11 @@ var ContentValidator = class {
|
|
|
1958
1976
|
this.extractAndRegisterIDs(path, root, registry);
|
|
1959
1977
|
}
|
|
1960
1978
|
if (refValidator && opfDir !== void 0) {
|
|
1961
|
-
this.extractAndRegisterHyperlinks(path, root, opfDir, refValidator);
|
|
1979
|
+
this.extractAndRegisterHyperlinks(context, path, root, opfDir, refValidator);
|
|
1962
1980
|
this.extractAndRegisterStylesheets(path, root, opfDir, refValidator);
|
|
1963
1981
|
this.extractAndRegisterImages(path, root, opfDir, refValidator);
|
|
1982
|
+
this.extractAndRegisterMathMLAltimg(path, root, opfDir, refValidator);
|
|
1983
|
+
this.extractAndRegisterScripts(path, root, opfDir, refValidator);
|
|
1964
1984
|
this.extractAndRegisterCiteAttributes(path, root, opfDir, refValidator);
|
|
1965
1985
|
this.extractAndRegisterMediaElements(path, root, opfDir, refValidator);
|
|
1966
1986
|
}
|
|
@@ -2000,8 +2020,8 @@ var ContentValidator = class {
|
|
|
2000
2020
|
}
|
|
2001
2021
|
}
|
|
2002
2022
|
checkNavDocument(context, path, doc, root) {
|
|
2003
|
-
const
|
|
2004
|
-
if (
|
|
2023
|
+
const navElements = root.find(".//html:nav", { html: "http://www.w3.org/1999/xhtml" });
|
|
2024
|
+
if (navElements.length === 0) {
|
|
2005
2025
|
pushMessage(context.messages, {
|
|
2006
2026
|
id: MessageId.NAV_001,
|
|
2007
2027
|
message: "Navigation document must have a nav element",
|
|
@@ -2009,20 +2029,28 @@ var ContentValidator = class {
|
|
|
2009
2029
|
});
|
|
2010
2030
|
return;
|
|
2011
2031
|
}
|
|
2012
|
-
|
|
2013
|
-
|
|
2032
|
+
let tocNav;
|
|
2033
|
+
let tocEpubTypeValue = "";
|
|
2034
|
+
for (const nav of navElements) {
|
|
2035
|
+
if (!("attrs" in nav)) continue;
|
|
2036
|
+
const epubTypeAttr = nav.attrs.find(
|
|
2037
|
+
(attr) => attr.name === "type" && attr.prefix === "epub" && attr.namespaceUri === "http://www.idpf.org/2007/ops"
|
|
2038
|
+
);
|
|
2039
|
+
if (epubTypeAttr?.value.includes("toc")) {
|
|
2040
|
+
tocNav = nav;
|
|
2041
|
+
tocEpubTypeValue = epubTypeAttr.value;
|
|
2042
|
+
break;
|
|
2043
|
+
}
|
|
2014
2044
|
}
|
|
2015
|
-
|
|
2016
|
-
(attr) => attr.name === "type" && attr.prefix === "epub" && attr.namespaceUri === "http://www.idpf.org/2007/ops"
|
|
2017
|
-
);
|
|
2018
|
-
if (!epubTypeAttr?.value.includes("toc")) {
|
|
2045
|
+
if (!tocNav) {
|
|
2019
2046
|
pushMessage(context.messages, {
|
|
2020
2047
|
id: MessageId.NAV_001,
|
|
2021
2048
|
message: 'Navigation document nav element must have epub:type="toc"',
|
|
2022
2049
|
location: { path }
|
|
2023
2050
|
});
|
|
2051
|
+
return;
|
|
2024
2052
|
}
|
|
2025
|
-
const ol =
|
|
2053
|
+
const ol = tocNav.get(".//html:ol", { html: "http://www.w3.org/1999/xhtml" });
|
|
2026
2054
|
if (!ol) {
|
|
2027
2055
|
pushMessage(context.messages, {
|
|
2028
2056
|
id: MessageId.NAV_002,
|
|
@@ -2030,7 +2058,7 @@ var ContentValidator = class {
|
|
|
2030
2058
|
location: { path }
|
|
2031
2059
|
});
|
|
2032
2060
|
}
|
|
2033
|
-
this.checkNavRemoteLinks(context, path, root,
|
|
2061
|
+
this.checkNavRemoteLinks(context, path, root, tocEpubTypeValue);
|
|
2034
2062
|
}
|
|
2035
2063
|
checkNavRemoteLinks(context, path, root, epubTypeValue) {
|
|
2036
2064
|
const navTypes = epubTypeValue.split(/\s+/);
|
|
@@ -2425,12 +2453,20 @@ var ContentValidator = class {
|
|
|
2425
2453
|
}
|
|
2426
2454
|
}
|
|
2427
2455
|
}
|
|
2428
|
-
extractAndRegisterHyperlinks(path, root, opfDir, refValidator) {
|
|
2456
|
+
extractAndRegisterHyperlinks(context, path, root, opfDir, refValidator) {
|
|
2429
2457
|
const docDir = path.includes("/") ? path.substring(0, path.lastIndexOf("/")) : "";
|
|
2430
2458
|
const links = root.find(".//html:a[@href]", { html: "http://www.w3.org/1999/xhtml" });
|
|
2431
2459
|
for (const link of links) {
|
|
2432
2460
|
const href = this.getAttribute(link, "href");
|
|
2433
|
-
if (
|
|
2461
|
+
if (href === null) continue;
|
|
2462
|
+
if (href.trim() === "") {
|
|
2463
|
+
pushMessage(context.messages, {
|
|
2464
|
+
id: MessageId.HTM_045,
|
|
2465
|
+
message: "Encountered empty href",
|
|
2466
|
+
location: { path, line: link.line }
|
|
2467
|
+
});
|
|
2468
|
+
continue;
|
|
2469
|
+
}
|
|
2434
2470
|
const line = link.line;
|
|
2435
2471
|
if (href.startsWith("http://") || href.startsWith("https://")) {
|
|
2436
2472
|
continue;
|
|
@@ -2438,6 +2474,9 @@ var ContentValidator = class {
|
|
|
2438
2474
|
if (href.startsWith("mailto:") || href.startsWith("tel:")) {
|
|
2439
2475
|
continue;
|
|
2440
2476
|
}
|
|
2477
|
+
if (href.includes("#epubcfi(")) {
|
|
2478
|
+
continue;
|
|
2479
|
+
}
|
|
2441
2480
|
if (href.startsWith("#")) {
|
|
2442
2481
|
const targetResource2 = path;
|
|
2443
2482
|
const fragment = href.slice(1);
|
|
@@ -2570,7 +2609,8 @@ var ContentValidator = class {
|
|
|
2570
2609
|
const docDir = path.includes("/") ? path.substring(0, path.lastIndexOf("/")) : "";
|
|
2571
2610
|
const images = root.find(".//html:img[@src]", { html: "http://www.w3.org/1999/xhtml" });
|
|
2572
2611
|
for (const img of images) {
|
|
2573
|
-
const
|
|
2612
|
+
const imgElem = img;
|
|
2613
|
+
const src = this.getAttribute(imgElem, "src");
|
|
2574
2614
|
if (!src) continue;
|
|
2575
2615
|
const line = img.line;
|
|
2576
2616
|
if (src.startsWith("http://") || src.startsWith("https://")) {
|
|
@@ -2580,15 +2620,26 @@ var ContentValidator = class {
|
|
|
2580
2620
|
type: "image" /* IMAGE */,
|
|
2581
2621
|
location: { path, line }
|
|
2582
2622
|
});
|
|
2583
|
-
|
|
2623
|
+
} else {
|
|
2624
|
+
const resolvedPath = this.resolveRelativePath(docDir, src, opfDir);
|
|
2625
|
+
const hashIndex = resolvedPath.indexOf("#");
|
|
2626
|
+
const targetResource = hashIndex >= 0 ? resolvedPath.slice(0, hashIndex) : resolvedPath;
|
|
2627
|
+
const fragment = hashIndex >= 0 ? resolvedPath.slice(hashIndex + 1) : void 0;
|
|
2628
|
+
const ref = {
|
|
2629
|
+
url: src,
|
|
2630
|
+
targetResource,
|
|
2631
|
+
type: "image" /* IMAGE */,
|
|
2632
|
+
location: { path, line }
|
|
2633
|
+
};
|
|
2634
|
+
if (fragment) {
|
|
2635
|
+
ref.fragment = fragment;
|
|
2636
|
+
}
|
|
2637
|
+
refValidator.addReference(ref);
|
|
2638
|
+
}
|
|
2639
|
+
const srcset = this.getAttribute(imgElem, "srcset");
|
|
2640
|
+
if (srcset) {
|
|
2641
|
+
this.parseSrcset(srcset, docDir, opfDir, path, line, refValidator);
|
|
2584
2642
|
}
|
|
2585
|
-
const resolvedPath = this.resolveRelativePath(docDir, src, opfDir);
|
|
2586
|
-
refValidator.addReference({
|
|
2587
|
-
url: src,
|
|
2588
|
-
targetResource: resolvedPath,
|
|
2589
|
-
type: "image" /* IMAGE */,
|
|
2590
|
-
location: { path, line }
|
|
2591
|
-
});
|
|
2592
2643
|
}
|
|
2593
2644
|
let svgImages = [];
|
|
2594
2645
|
try {
|
|
@@ -2618,12 +2669,19 @@ var ContentValidator = class {
|
|
|
2618
2669
|
continue;
|
|
2619
2670
|
}
|
|
2620
2671
|
const resolvedPath = this.resolveRelativePath(docDir, href, opfDir);
|
|
2621
|
-
|
|
2672
|
+
const hashIndex = resolvedPath.indexOf("#");
|
|
2673
|
+
const targetResource = hashIndex >= 0 ? resolvedPath.slice(0, hashIndex) : resolvedPath;
|
|
2674
|
+
const fragment = hashIndex >= 0 ? resolvedPath.slice(hashIndex + 1) : void 0;
|
|
2675
|
+
const svgImgRef = {
|
|
2622
2676
|
url: href,
|
|
2623
|
-
targetResource
|
|
2677
|
+
targetResource,
|
|
2624
2678
|
type: "image" /* IMAGE */,
|
|
2625
2679
|
location: { path, line }
|
|
2626
|
-
}
|
|
2680
|
+
};
|
|
2681
|
+
if (fragment) {
|
|
2682
|
+
svgImgRef.fragment = fragment;
|
|
2683
|
+
}
|
|
2684
|
+
refValidator.addReference(svgImgRef);
|
|
2627
2685
|
}
|
|
2628
2686
|
const videos = root.find(".//html:video[@poster]", { html: "http://www.w3.org/1999/xhtml" });
|
|
2629
2687
|
for (const video of videos) {
|
|
@@ -2648,6 +2706,58 @@ var ContentValidator = class {
|
|
|
2648
2706
|
});
|
|
2649
2707
|
}
|
|
2650
2708
|
}
|
|
2709
|
+
extractAndRegisterMathMLAltimg(path, root, opfDir, refValidator) {
|
|
2710
|
+
const docDir = path.includes("/") ? path.substring(0, path.lastIndexOf("/")) : "";
|
|
2711
|
+
const mathElements = root.find(".//math:math[@altimg]", {
|
|
2712
|
+
math: "http://www.w3.org/1998/Math/MathML"
|
|
2713
|
+
});
|
|
2714
|
+
for (const mathElem of mathElements) {
|
|
2715
|
+
const altimg = this.getAttribute(mathElem, "altimg");
|
|
2716
|
+
if (!altimg) continue;
|
|
2717
|
+
const line = mathElem.line;
|
|
2718
|
+
if (altimg.startsWith("http://") || altimg.startsWith("https://")) {
|
|
2719
|
+
refValidator.addReference({
|
|
2720
|
+
url: altimg,
|
|
2721
|
+
targetResource: altimg,
|
|
2722
|
+
type: "image" /* IMAGE */,
|
|
2723
|
+
location: { path, line }
|
|
2724
|
+
});
|
|
2725
|
+
continue;
|
|
2726
|
+
}
|
|
2727
|
+
const resolvedPath = this.resolveRelativePath(docDir, altimg, opfDir);
|
|
2728
|
+
refValidator.addReference({
|
|
2729
|
+
url: altimg,
|
|
2730
|
+
targetResource: resolvedPath,
|
|
2731
|
+
type: "image" /* IMAGE */,
|
|
2732
|
+
location: { path, line }
|
|
2733
|
+
});
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
extractAndRegisterScripts(path, root, opfDir, refValidator) {
|
|
2737
|
+
const docDir = path.includes("/") ? path.substring(0, path.lastIndexOf("/")) : "";
|
|
2738
|
+
const scripts = root.find(".//html:script[@src]", { html: "http://www.w3.org/1999/xhtml" });
|
|
2739
|
+
for (const script of scripts) {
|
|
2740
|
+
const src = this.getAttribute(script, "src");
|
|
2741
|
+
if (!src) continue;
|
|
2742
|
+
const line = script.line;
|
|
2743
|
+
if (src.startsWith("http://") || src.startsWith("https://")) {
|
|
2744
|
+
refValidator.addReference({
|
|
2745
|
+
url: src,
|
|
2746
|
+
targetResource: src,
|
|
2747
|
+
type: "generic" /* GENERIC */,
|
|
2748
|
+
location: { path, line }
|
|
2749
|
+
});
|
|
2750
|
+
continue;
|
|
2751
|
+
}
|
|
2752
|
+
const resolvedPath = this.resolveRelativePath(docDir, src, opfDir);
|
|
2753
|
+
refValidator.addReference({
|
|
2754
|
+
url: src,
|
|
2755
|
+
targetResource: resolvedPath,
|
|
2756
|
+
type: "generic" /* GENERIC */,
|
|
2757
|
+
location: { path, line }
|
|
2758
|
+
});
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2651
2761
|
/**
|
|
2652
2762
|
* Extract cite attribute references from blockquote, q, ins, del elements
|
|
2653
2763
|
* These need to be validated as RSC-007 if the referenced resource is missing
|
|
@@ -2773,6 +2883,30 @@ var ContentValidator = class {
|
|
|
2773
2883
|
});
|
|
2774
2884
|
}
|
|
2775
2885
|
}
|
|
2886
|
+
const iframeElements = root.find(".//html:iframe[@src]", {
|
|
2887
|
+
html: "http://www.w3.org/1999/xhtml"
|
|
2888
|
+
});
|
|
2889
|
+
for (const iframe of iframeElements) {
|
|
2890
|
+
const src = this.getAttribute(iframe, "src");
|
|
2891
|
+
if (!src) continue;
|
|
2892
|
+
const line = iframe.line;
|
|
2893
|
+
if (src.startsWith("http://") || src.startsWith("https://")) {
|
|
2894
|
+
refValidator.addReference({
|
|
2895
|
+
url: src,
|
|
2896
|
+
targetResource: src,
|
|
2897
|
+
type: "generic" /* GENERIC */,
|
|
2898
|
+
location: line !== void 0 ? { path, line } : { path }
|
|
2899
|
+
});
|
|
2900
|
+
} else {
|
|
2901
|
+
const resolvedPath = this.resolveRelativePath(docDir, src, opfDir);
|
|
2902
|
+
refValidator.addReference({
|
|
2903
|
+
url: src,
|
|
2904
|
+
targetResource: resolvedPath,
|
|
2905
|
+
type: "generic" /* GENERIC */,
|
|
2906
|
+
location: line !== void 0 ? { path, line } : { path }
|
|
2907
|
+
});
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2776
2910
|
const trackElements = root.find(".//html:track[@src]", {
|
|
2777
2911
|
html: "http://www.w3.org/1999/xhtml"
|
|
2778
2912
|
});
|
|
@@ -2798,6 +2932,32 @@ var ContentValidator = class {
|
|
|
2798
2932
|
}
|
|
2799
2933
|
}
|
|
2800
2934
|
}
|
|
2935
|
+
parseSrcset(srcset, docDir, opfDir, path, line, refValidator) {
|
|
2936
|
+
const entries = srcset.split(",");
|
|
2937
|
+
for (const entry of entries) {
|
|
2938
|
+
const trimmed = entry.trim();
|
|
2939
|
+
if (!trimmed) continue;
|
|
2940
|
+
const url = trimmed.split(/\s+/)[0];
|
|
2941
|
+
if (!url) continue;
|
|
2942
|
+
const location = line !== void 0 ? { path, line } : { path };
|
|
2943
|
+
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
2944
|
+
refValidator.addReference({
|
|
2945
|
+
url,
|
|
2946
|
+
targetResource: url,
|
|
2947
|
+
type: "image" /* IMAGE */,
|
|
2948
|
+
location
|
|
2949
|
+
});
|
|
2950
|
+
} else {
|
|
2951
|
+
const resolvedPath = this.resolveRelativePath(docDir, url, opfDir);
|
|
2952
|
+
refValidator.addReference({
|
|
2953
|
+
url,
|
|
2954
|
+
targetResource: resolvedPath,
|
|
2955
|
+
type: "image" /* IMAGE */,
|
|
2956
|
+
location
|
|
2957
|
+
});
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2801
2961
|
resolveRelativePath(docDir, href, _opfDir) {
|
|
2802
2962
|
const hrefWithoutFragment = href.split("#")[0] ?? href;
|
|
2803
2963
|
const fragment = href.includes("#") ? href.split("#")[1] : "";
|
|
@@ -4204,6 +4364,17 @@ var OPFValidator = class {
|
|
|
4204
4364
|
if (href.startsWith("#")) {
|
|
4205
4365
|
continue;
|
|
4206
4366
|
}
|
|
4367
|
+
const isRemote = /^[a-zA-Z][a-zA-Z0-9+\-.]*:/.test(href);
|
|
4368
|
+
if (isRemote) {
|
|
4369
|
+
continue;
|
|
4370
|
+
}
|
|
4371
|
+
if (!link.mediaType) {
|
|
4372
|
+
pushMessage(context.messages, {
|
|
4373
|
+
id: MessageId.OPF_093,
|
|
4374
|
+
message: 'The "media-type" attribute is required for linked resources located in the EPUB container',
|
|
4375
|
+
location: { path: opfPath }
|
|
4376
|
+
});
|
|
4377
|
+
}
|
|
4207
4378
|
const resolvedPath = resolvePath(opfDir, basePath);
|
|
4208
4379
|
const resolvedPathDecoded = basePathDecoded !== basePath ? resolvePath(opfDir, basePathDecoded) : resolvedPath;
|
|
4209
4380
|
const fileExists = context.files.has(resolvedPath) || context.files.has(resolvedPathDecoded);
|
|
@@ -4297,10 +4468,10 @@ var OPFValidator = class {
|
|
|
4297
4468
|
}
|
|
4298
4469
|
if (this.packageDoc.version !== "2.0" && item.properties) {
|
|
4299
4470
|
for (const prop of item.properties) {
|
|
4300
|
-
if (!ITEM_PROPERTIES.has(prop)
|
|
4471
|
+
if (!ITEM_PROPERTIES.has(prop)) {
|
|
4301
4472
|
pushMessage(context.messages, {
|
|
4302
|
-
id: MessageId.
|
|
4303
|
-
message: `
|
|
4473
|
+
id: MessageId.OPF_027,
|
|
4474
|
+
message: `Undefined property: "${prop}"`,
|
|
4304
4475
|
location: { path: opfPath }
|
|
4305
4476
|
});
|
|
4306
4477
|
}
|
|
@@ -4838,11 +5009,19 @@ var ReferenceValidator = class {
|
|
|
4838
5009
|
}
|
|
4839
5010
|
if (isDataURL(url)) {
|
|
4840
5011
|
if (this.version.startsWith("3.")) {
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
5012
|
+
const forbiddenDataUrlTypes = [
|
|
5013
|
+
"hyperlink" /* HYPERLINK */,
|
|
5014
|
+
"nav-toc-link" /* NAV_TOC_LINK */,
|
|
5015
|
+
"nav-pagelist-link" /* NAV_PAGELIST_LINK */,
|
|
5016
|
+
"cite" /* CITE */
|
|
5017
|
+
];
|
|
5018
|
+
if (forbiddenDataUrlTypes.includes(reference.type)) {
|
|
5019
|
+
pushMessage(context.messages, {
|
|
5020
|
+
id: MessageId.RSC_029,
|
|
5021
|
+
message: "Data URLs are not allowed in this context",
|
|
5022
|
+
location: reference.location
|
|
5023
|
+
});
|
|
5024
|
+
}
|
|
4846
5025
|
}
|
|
4847
5026
|
return;
|
|
4848
5027
|
}
|
|
@@ -4982,6 +5161,14 @@ var ReferenceValidator = class {
|
|
|
4982
5161
|
});
|
|
4983
5162
|
return;
|
|
4984
5163
|
}
|
|
5164
|
+
if (reference.type === "image" /* IMAGE */ && resource?.mimeType !== "image/svg+xml") {
|
|
5165
|
+
pushMessage(context.messages, {
|
|
5166
|
+
id: MessageId.RSC_009,
|
|
5167
|
+
message: `Fragment identifier used on a non-SVG image resource: ${resourcePath}#${fragment}`,
|
|
5168
|
+
location: reference.location
|
|
5169
|
+
});
|
|
5170
|
+
return;
|
|
5171
|
+
}
|
|
4985
5172
|
if (resource?.mimeType === "image/svg+xml") {
|
|
4986
5173
|
const hasSVGView = fragment.includes("svgView(") || fragment.includes("viewBox(");
|
|
4987
5174
|
if (hasSVGView && reference.type === "hyperlink" /* HYPERLINK */) {
|