@utilix-tech/sdk 0.76.0 → 0.77.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/CHANGELOG.md +4 -0
- package/README.md +14 -3
- package/dist/{chunk-CXUOV672.js → chunk-KWS4ZCYG.js} +119 -1
- package/dist/{chunk-PT4N4UBL.js → chunk-ZWFZRDQ4.js} +70 -1
- package/dist/index.cjs +187 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{media-56zrIBw4.d.cts → media-DF8BS-iA.d.cts} +33 -2
- package/dist/{media-56zrIBw4.d.ts → media-DF8BS-iA.d.ts} +33 -2
- package/dist/{network-Da3meCWM.d.cts → network-BskZe1n2.d.cts} +34 -2
- package/dist/{network-Da3meCWM.d.ts → network-BskZe1n2.d.ts} +34 -2
- package/dist/tools/media.cjs +69 -0
- package/dist/tools/media.d.cts +1 -1
- package/dist/tools/media.d.ts +1 -1
- package/dist/tools/media.js +1 -1
- package/dist/tools/network.cjs +118 -0
- package/dist/tools/network.d.cts +1 -1
- package/dist/tools/network.d.ts +1 -1
- package/dist/tools/network.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Full release notes for all Utilix surfaces (browser tools, REST API, SDKs, MCP server) live at [utilix.tech/changelog](https://utilix.tech/changelog). This file tracks just this package.
|
|
4
4
|
|
|
5
|
+
## 0.77.0
|
|
6
|
+
- Add `readPdfOutline` (pdf-outline-extractor): walk a PDF's /Outlines bookmark tree (the Root -> Outlines -> First/Next/First chain) and list every bookmark's title, nesting level, and link target, in document order.
|
|
7
|
+
- Add `scoreSecurityHeaders` (security-headers-scorecard): score a pasted block of raw HTTP response headers against commonly recommended security headers (CSP, HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, Cross-Origin-*), with an overall 0-100 score and A-F letter grade.
|
|
8
|
+
|
|
5
9
|
## 0.76.0
|
|
6
10
|
- Add `detectWordyPhrases` (wordy-phrase-detector): scan text against a curated table of wordy/redundant phrases ("due to the fact that", "in order to") and flag each occurrence with a suggested concise replacement, an occurrence count, and character offsets.
|
|
7
11
|
- Add `checkOxfordCommaConsistency` (oxford-comma-checker): scan a document for comma-before-and/or usage in three-or-more-item lists and flag documents that mix Oxford comma styles.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @utilix-tech/sdk
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**705 developer utility functions for Node.js: runs locally, no API key required.**
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@utilix-tech/sdk)
|
|
6
6
|
[](https://www.npmjs.com/package/@utilix-tech/sdk)
|
|
@@ -710,6 +710,11 @@ buildRobotsMetaTag({ flags: ["noindex", "nofollow"], name: "googlebot" });
|
|
|
710
710
|
// Cookie header byte-size budget: per-cookie and total sizes against RFC 6265's 4096-byte limit
|
|
711
711
|
calculateCookieSizeBudget("session=abc123; theme=dark; cart=42");
|
|
712
712
|
// { cookieCount: 3, totalBytes: 35, budgetBytes: 4096, exceedsBudget: false, cookies: [...] }
|
|
713
|
+
|
|
714
|
+
// Score pasted response headers against commonly recommended security headers
|
|
715
|
+
import { scoreSecurityHeaders } from "@utilix-tech/sdk/network";
|
|
716
|
+
scoreSecurityHeaders("Content-Security-Policy: default-src 'self'\nStrict-Transport-Security: max-age=63072000");
|
|
717
|
+
// { score: 22, grade: "F", passCount: 2, warningCount: 0, missingCount: 7, totalChecks: 9, checks: [...] }
|
|
713
718
|
```
|
|
714
719
|
|
|
715
720
|
---
|
|
@@ -910,10 +915,10 @@ analyzeString("café"); // { length: 4, codePoints: [...], ... }
|
|
|
910
915
|
|
|
911
916
|
---
|
|
912
917
|
|
|
913
|
-
### `/media`: Image Header Parsing, EXIF, PDF Metadata
|
|
918
|
+
### `/media`: Image Header Parsing, EXIF, PDF Metadata, Page Dimensions & Outlines, WAV, ID3, ICO, FLAC, Video, GIF & MIDI Metadata
|
|
914
919
|
|
|
915
920
|
```ts
|
|
916
|
-
import { readImageInfo, readExifData, readPdfMetadata, readPdfPageDimensions, readWavInfo, readId3Tags, readIcoInfo, readFlacInfo, readVideoInfo, inspectGifFrames, readMidiInfo } from "@utilix-tech/sdk/media";
|
|
921
|
+
import { readImageInfo, readExifData, readPdfMetadata, readPdfPageDimensions, readPdfOutline, readWavInfo, readId3Tags, readIcoInfo, readFlacInfo, readVideoInfo, inspectGifFrames, readMidiInfo } from "@utilix-tech/sdk/media";
|
|
917
922
|
|
|
918
923
|
// Reads format, dimensions, bit depth, and alpha channel straight from
|
|
919
924
|
// file bytes: no decoding, no canvas, no image library.
|
|
@@ -939,6 +944,12 @@ readPdfMetadata(new Uint8Array(pdfBytes));
|
|
|
939
944
|
readPdfPageDimensions(new Uint8Array(pdfBytes));
|
|
940
945
|
// { version: "1.7", pageCount: 12, pages: [{ pageNumber: 1, widthPt: 612, heightPt: 792, rotation: 0, orientation: "portrait", paperSize: "Letter" }, ...] }
|
|
941
946
|
|
|
947
|
+
// Walks a PDF's /Outlines bookmark tree (Root -> Outlines -> First/Next/
|
|
948
|
+
// First chain) to list every bookmark's title, nesting level, and link
|
|
949
|
+
// target, in document order: no PDF rendering library required.
|
|
950
|
+
readPdfOutline(new Uint8Array(pdfBytes));
|
|
951
|
+
// { version: "1.7", bookmarkCount: 3, bookmarks: [{ title: "Chapter 1", level: 0, destType: "page", target: "3 0 R" }, ...] }
|
|
952
|
+
|
|
942
953
|
// Reads sample rate, channels, bit depth, and duration from a WAV file's
|
|
943
954
|
// RIFF/fmt/data chunk headers: no audio library required.
|
|
944
955
|
const wavBytes = await fs.promises.readFile("recording.wav");
|
|
@@ -72,6 +72,7 @@ __export(network_exports, {
|
|
|
72
72
|
parseVaryHeader: () => parseVaryHeader,
|
|
73
73
|
parseXContentTypeOptionsHeader: () => parseXContentTypeOptionsHeader,
|
|
74
74
|
parseXRobotsTag: () => parseXRobotsTag,
|
|
75
|
+
scoreSecurityHeaders: () => scoreSecurityHeaders,
|
|
75
76
|
searchHeaders: () => searchHeaders,
|
|
76
77
|
searchStatusCodes: () => searchStatusCodes,
|
|
77
78
|
splitSitemap: () => splitSitemap,
|
|
@@ -3511,5 +3512,122 @@ function calculateCookieSizeBudget(cookieHeader, budgetBytes = DEFAULT_COOKIE_BU
|
|
|
3511
3512
|
exceedsBudget: totalBytes > budgetBytes
|
|
3512
3513
|
};
|
|
3513
3514
|
}
|
|
3515
|
+
function parseRawHeaderBlock(raw) {
|
|
3516
|
+
const map = /* @__PURE__ */ new Map();
|
|
3517
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
3518
|
+
const trimmed = line.trim();
|
|
3519
|
+
if (!trimmed) continue;
|
|
3520
|
+
const idx = trimmed.indexOf(":");
|
|
3521
|
+
if (idx === -1) continue;
|
|
3522
|
+
const name = trimmed.slice(0, idx).trim().toLowerCase();
|
|
3523
|
+
const value = trimmed.slice(idx + 1).trim();
|
|
3524
|
+
if (!map.has(name)) map.set(name, value);
|
|
3525
|
+
}
|
|
3526
|
+
return map;
|
|
3527
|
+
}
|
|
3528
|
+
var SECURITY_HEADER_CHECKS = [
|
|
3529
|
+
{
|
|
3530
|
+
header: "Content-Security-Policy",
|
|
3531
|
+
evaluate: (v) => {
|
|
3532
|
+
if (!v) return { status: "missing", note: "Without a CSP, an injected script runs with full page privileges." };
|
|
3533
|
+
if (/unsafe-inline|unsafe-eval/i.test(v)) return { status: "warning", note: "Contains unsafe-inline or unsafe-eval, which weakens XSS protection." };
|
|
3534
|
+
return { status: "pass", note: "Present. Use the CSP Header Builder tool to validate its directives in depth." };
|
|
3535
|
+
}
|
|
3536
|
+
},
|
|
3537
|
+
{
|
|
3538
|
+
header: "Strict-Transport-Security",
|
|
3539
|
+
evaluate: (v) => {
|
|
3540
|
+
if (!v) return { status: "missing", note: "Without HSTS, a user's first visit (and any later downgrade) can be sent over plain HTTP." };
|
|
3541
|
+
const maxAgeMatch = v.match(/max-age\s*=\s*(\d+)/i);
|
|
3542
|
+
if (!maxAgeMatch) return { status: "warning", note: "Present but missing a max-age directive." };
|
|
3543
|
+
const maxAge = Number(maxAgeMatch[1]);
|
|
3544
|
+
if (maxAge < 31536e3) return { status: "warning", note: "max-age is below the recommended 1 year (31536000 seconds)." };
|
|
3545
|
+
return { status: "pass", note: "Present with a max-age of at least 1 year." };
|
|
3546
|
+
}
|
|
3547
|
+
},
|
|
3548
|
+
{
|
|
3549
|
+
header: "X-Content-Type-Options",
|
|
3550
|
+
evaluate: (v) => {
|
|
3551
|
+
if (!v) return { status: "missing", note: "Without this header, browsers may MIME-sniff a response into an unintended content type." };
|
|
3552
|
+
if (v.trim().toLowerCase() !== "nosniff") return { status: "warning", note: `"nosniff" is the only valid value; this value won't take effect.` };
|
|
3553
|
+
return { status: "pass", note: "Set to the only valid value, nosniff." };
|
|
3554
|
+
}
|
|
3555
|
+
},
|
|
3556
|
+
{
|
|
3557
|
+
header: "X-Frame-Options",
|
|
3558
|
+
evaluate: (v) => {
|
|
3559
|
+
if (!v) return { status: "missing", note: "Without this (or a CSP frame-ancestors directive), the page can be framed by another site for clickjacking." };
|
|
3560
|
+
const upper = v.trim().toUpperCase();
|
|
3561
|
+
if (upper === "DENY" || upper === "SAMEORIGIN") return { status: "pass", note: `Framing restricted (${upper}).` };
|
|
3562
|
+
if (upper.startsWith("ALLOW-FROM")) return { status: "warning", note: "ALLOW-FROM is deprecated and ignored by most modern browsers." };
|
|
3563
|
+
return { status: "warning", note: "Unrecognized value." };
|
|
3564
|
+
}
|
|
3565
|
+
},
|
|
3566
|
+
{
|
|
3567
|
+
header: "Referrer-Policy",
|
|
3568
|
+
evaluate: (v) => {
|
|
3569
|
+
if (!v) return { status: "missing", note: "Without this header, the browser's default referrer behavior applies, which can leak full URLs to third parties." };
|
|
3570
|
+
if (v.trim().toLowerCase() === "unsafe-url") return { status: "warning", note: "unsafe-url leaks the full URL, including path and query string, to every destination." };
|
|
3571
|
+
return { status: "pass", note: "Present." };
|
|
3572
|
+
}
|
|
3573
|
+
},
|
|
3574
|
+
{
|
|
3575
|
+
header: "Permissions-Policy",
|
|
3576
|
+
evaluate: (v) => {
|
|
3577
|
+
if (!v) return { status: "missing", note: "Without this header, embedded content can use powerful browser features (camera, geolocation, etc.) unless restricted another way." };
|
|
3578
|
+
return { status: "pass", note: "Present." };
|
|
3579
|
+
}
|
|
3580
|
+
},
|
|
3581
|
+
{
|
|
3582
|
+
header: "Cross-Origin-Opener-Policy",
|
|
3583
|
+
evaluate: (v) => {
|
|
3584
|
+
if (!v) return { status: "missing", note: "Without COOP, this page can be put in the same browsing context group as a malicious opener window." };
|
|
3585
|
+
const lower = v.trim().toLowerCase();
|
|
3586
|
+
if (lower === "same-origin") return { status: "pass", note: "Set to same-origin, the strongest isolation value." };
|
|
3587
|
+
return { status: "warning", note: `Set to "${v.trim()}", which is weaker than same-origin.` };
|
|
3588
|
+
}
|
|
3589
|
+
},
|
|
3590
|
+
{
|
|
3591
|
+
header: "Cross-Origin-Embedder-Policy",
|
|
3592
|
+
evaluate: (v) => {
|
|
3593
|
+
if (!v) return { status: "missing", note: "Required alongside COOP for cross-origin isolation (e.g. to use SharedArrayBuffer)." };
|
|
3594
|
+
const lower = v.trim().toLowerCase();
|
|
3595
|
+
if (lower === "require-corp" || lower === "credentialless") return { status: "pass", note: `Set to ${lower}.` };
|
|
3596
|
+
return { status: "warning", note: `Unrecognized value "${v.trim()}".` };
|
|
3597
|
+
}
|
|
3598
|
+
},
|
|
3599
|
+
{
|
|
3600
|
+
header: "Cross-Origin-Resource-Policy",
|
|
3601
|
+
evaluate: (v) => {
|
|
3602
|
+
if (!v) return { status: "missing", note: "Without CORP, this resource can be loaded cross-origin by any site that knows its URL." };
|
|
3603
|
+
const lower = v.trim().toLowerCase();
|
|
3604
|
+
if (lower === "same-origin" || lower === "same-site") return { status: "pass", note: `Set to ${lower}.` };
|
|
3605
|
+
if (lower === "cross-origin") return { status: "warning", note: "Set to cross-origin, which allows any site to load this resource." };
|
|
3606
|
+
return { status: "warning", note: `Unrecognized value "${v.trim()}".` };
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
];
|
|
3610
|
+
function scoreSecurityHeaders(rawHeaders) {
|
|
3611
|
+
if (typeof rawHeaders !== "string" || !rawHeaders.trim()) {
|
|
3612
|
+
return { error: 'Paste one or more response headers, one per line in "Name: value" form' };
|
|
3613
|
+
}
|
|
3614
|
+
const headerMap = parseRawHeaderBlock(rawHeaders);
|
|
3615
|
+
if (headerMap.size === 0) {
|
|
3616
|
+
return { error: 'Could not parse any "Name: value" header lines from the input' };
|
|
3617
|
+
}
|
|
3618
|
+
const checks = SECURITY_HEADER_CHECKS.map((def) => {
|
|
3619
|
+
const value = headerMap.get(def.header.toLowerCase()) ?? null;
|
|
3620
|
+
const { status, note } = def.evaluate(value);
|
|
3621
|
+
return { header: def.header, status, value, note };
|
|
3622
|
+
});
|
|
3623
|
+
const passCount = checks.filter((c) => c.status === "pass").length;
|
|
3624
|
+
const warningCount = checks.filter((c) => c.status === "warning").length;
|
|
3625
|
+
const missingCount = checks.filter((c) => c.status === "missing").length;
|
|
3626
|
+
const totalChecks = checks.length;
|
|
3627
|
+
const points = passCount + warningCount * 0.5;
|
|
3628
|
+
const score = Math.round(points / totalChecks * 100);
|
|
3629
|
+
const grade = score >= 90 ? "A" : score >= 75 ? "B" : score >= 60 ? "C" : score >= 40 ? "D" : "F";
|
|
3630
|
+
return { checks, score, grade, passCount, warningCount, missingCount, totalChecks };
|
|
3631
|
+
}
|
|
3514
3632
|
|
|
3515
|
-
export { CLIENT_HINTS, DNS_RECORD_TYPES, HTTP_HEADERS, LINK_REL_VALUES, PERMISSIONS_POLICY_FEATURES, REFERRER_POLICY_VALUES, STATUS_CODES, X_CONTENT_TYPE_OPTIONS_HEADER, analyzeEmailHeaders, assessContentTypeRisk, buildAcceptLanguage, buildCacheControl, buildClientHints, buildContentDisposition, buildDnsQueryUrl, buildGeoUrl, buildHsts, buildLinkHeader, buildMapUrl, buildPermissionsPolicy, buildPreferHeader, buildPriorityHeader, buildRangeHeader, buildReferrerPolicy, buildRetryAfterHeader, buildRobotsMetaTag, buildVaryHeader, buildXContentTypeOptionsHeader, buildXRobotsTag, calculateCookieSizeBudget, checkSetCookieHeader, countryCodeToFlag, extractMultipartBoundary, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, listCloseCodes, listOpcodes, lookupCloseCode, lookupOpcode, network_exports, parseAcceptLanguage, parseClientHintHeaders, parseContentDisposition, parseContentRangeHeader, parseDnsResponse, parseGeoResponse, parseHar, parseHsts, parseIpv6Address, parseMultipartFormData, parsePermissionsPolicy, parsePreferHeader, parsePriorityHeader, parseRetryAfterHeader, parseRobotsMetaTag, parseUserAgent, parseVaryHeader, parseXContentTypeOptionsHeader, parseXRobotsTag, searchHeaders, searchStatusCodes, splitSitemap, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateManifest, validateRobotsTxt, validateSitemap };
|
|
3633
|
+
export { CLIENT_HINTS, DNS_RECORD_TYPES, HTTP_HEADERS, LINK_REL_VALUES, PERMISSIONS_POLICY_FEATURES, REFERRER_POLICY_VALUES, STATUS_CODES, X_CONTENT_TYPE_OPTIONS_HEADER, analyzeEmailHeaders, assessContentTypeRisk, buildAcceptLanguage, buildCacheControl, buildClientHints, buildContentDisposition, buildDnsQueryUrl, buildGeoUrl, buildHsts, buildLinkHeader, buildMapUrl, buildPermissionsPolicy, buildPreferHeader, buildPriorityHeader, buildRangeHeader, buildReferrerPolicy, buildRetryAfterHeader, buildRobotsMetaTag, buildVaryHeader, buildXContentTypeOptionsHeader, buildXRobotsTag, calculateCookieSizeBudget, checkSetCookieHeader, countryCodeToFlag, extractMultipartBoundary, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, listCloseCodes, listOpcodes, lookupCloseCode, lookupOpcode, network_exports, parseAcceptLanguage, parseClientHintHeaders, parseContentDisposition, parseContentRangeHeader, parseDnsResponse, parseGeoResponse, parseHar, parseHsts, parseIpv6Address, parseMultipartFormData, parsePermissionsPolicy, parsePreferHeader, parsePriorityHeader, parseRetryAfterHeader, parseRobotsMetaTag, parseUserAgent, parseVaryHeader, parseXContentTypeOptionsHeader, parseXRobotsTag, scoreSecurityHeaders, searchHeaders, searchStatusCodes, splitSitemap, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateManifest, validateRobotsTxt, validateSitemap };
|
|
@@ -11,6 +11,7 @@ __export(media_exports, {
|
|
|
11
11
|
readImageInfo: () => readImageInfo,
|
|
12
12
|
readMidiInfo: () => readMidiInfo,
|
|
13
13
|
readPdfMetadata: () => readPdfMetadata,
|
|
14
|
+
readPdfOutline: () => readPdfOutline,
|
|
14
15
|
readPdfPageDimensions: () => readPdfPageDimensions,
|
|
15
16
|
readVideoInfo: () => readVideoInfo,
|
|
16
17
|
readWavInfo: () => readWavInfo
|
|
@@ -581,6 +582,74 @@ function readPdfPageDimensions(bytes) {
|
|
|
581
582
|
if (out.length === 0) return { error: "Could not locate any page objects in this PDF" };
|
|
582
583
|
return { version, pageCount: out.length, pages: out };
|
|
583
584
|
}
|
|
585
|
+
function parsePdfOutlineDest(dict) {
|
|
586
|
+
const directRef = dict.match(/\/Dest\s*\[\s*(\d+)\s+(\d+)\s+R/);
|
|
587
|
+
if (directRef) return { destType: "page", target: `${directRef[1]} ${directRef[2]} R` };
|
|
588
|
+
const directName = dict.match(/\/Dest\s*\/([^\s/()<>[\]]+)/);
|
|
589
|
+
if (directName) return { destType: "named", target: directName[1] };
|
|
590
|
+
const directString = dict.match(/\/Dest\s*\(((?:\\.|[^\\()])*)\)/);
|
|
591
|
+
if (directString) return { destType: "named", target: decodePdfString(directString[1], false) };
|
|
592
|
+
const actionUri = dict.match(/\/S\s*\/URI[\s\S]*?\/URI\s*\(((?:\\.|[^\\()])*)\)/);
|
|
593
|
+
if (actionUri) return { destType: "uri", target: decodePdfString(actionUri[1], false) };
|
|
594
|
+
const actionGotoRef = dict.match(/\/S\s*\/GoTo[\s\S]*?\/D\s*\[\s*(\d+)\s+(\d+)\s+R/);
|
|
595
|
+
if (actionGotoRef) return { destType: "page", target: `${actionGotoRef[1]} ${actionGotoRef[2]} R` };
|
|
596
|
+
const actionGotoName = dict.match(/\/S\s*\/GoTo[\s\S]*?\/D\s*\/([^\s/()<>[\]]+)/);
|
|
597
|
+
if (actionGotoName) return { destType: "named", target: actionGotoName[1] };
|
|
598
|
+
return { destType: "none", target: null };
|
|
599
|
+
}
|
|
600
|
+
function walkPdfOutlineChain(objMap, startRef, level, visited, out) {
|
|
601
|
+
let ref = startRef;
|
|
602
|
+
while (ref) {
|
|
603
|
+
if (visited.has(ref)) break;
|
|
604
|
+
visited.add(ref);
|
|
605
|
+
const body = objMap.get(ref);
|
|
606
|
+
if (!body) break;
|
|
607
|
+
const titleRaw = extractDictField(body, "Title");
|
|
608
|
+
const { destType, target } = parsePdfOutlineDest(body);
|
|
609
|
+
out.push({ title: titleRaw ?? "(untitled)", level, destType, target });
|
|
610
|
+
const firstMatch = body.match(/\/First\s+(\d+)\s+(\d+)\s+R/);
|
|
611
|
+
if (firstMatch) walkPdfOutlineChain(objMap, `${firstMatch[1]} ${firstMatch[2]}`, level + 1, visited, out);
|
|
612
|
+
const nextMatch = body.match(/\/Next\s+(\d+)\s+(\d+)\s+R/);
|
|
613
|
+
ref = nextMatch ? `${nextMatch[1]} ${nextMatch[2]}` : null;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
function readPdfOutline(bytes) {
|
|
617
|
+
if (bytes.length < 8) return { error: "File too small to be a PDF" };
|
|
618
|
+
const header = bytesToLatin1(bytes.subarray(0, 16));
|
|
619
|
+
const versionMatch = header.match(/%PDF-(\d\.\d)/);
|
|
620
|
+
if (!versionMatch) return { error: "Not a valid PDF file (missing %PDF header)" };
|
|
621
|
+
const version = versionMatch[1];
|
|
622
|
+
const text = bytesToLatin1(bytes);
|
|
623
|
+
const objBlocks = [...text.matchAll(/(\d+)\s+(\d+)\s+obj([\s\S]*?)endobj/g)];
|
|
624
|
+
const objMap = /* @__PURE__ */ new Map();
|
|
625
|
+
for (const b of objBlocks) objMap.set(`${b[1]} ${b[2]}`, b[3]);
|
|
626
|
+
let outlinesBody = null;
|
|
627
|
+
const trailerMatches = [...text.matchAll(/trailer\s*<<([\s\S]*?)>>/g)];
|
|
628
|
+
if (trailerMatches.length > 0) {
|
|
629
|
+
const trailer = trailerMatches[trailerMatches.length - 1][1];
|
|
630
|
+
const rootRef = trailer.match(/\/Root\s+(\d+)\s+(\d+)\s+R/);
|
|
631
|
+
if (rootRef) {
|
|
632
|
+
const catalogBody = objMap.get(`${rootRef[1]} ${rootRef[2]}`);
|
|
633
|
+
const outlinesRef = catalogBody?.match(/\/Outlines\s+(\d+)\s+(\d+)\s+R/);
|
|
634
|
+
if (outlinesRef) outlinesBody = objMap.get(`${outlinesRef[1]} ${outlinesRef[2]}`) ?? null;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
if (!outlinesBody) {
|
|
638
|
+
for (const b of objBlocks) {
|
|
639
|
+
if (/\/Type\s*\/Outlines\b/.test(b[3])) {
|
|
640
|
+
outlinesBody = b[3];
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
if (!outlinesBody) return { error: "No /Outlines bookmark tree found in this PDF" };
|
|
646
|
+
const out = [];
|
|
647
|
+
const firstMatch = outlinesBody.match(/\/First\s+(\d+)\s+(\d+)\s+R/);
|
|
648
|
+
if (firstMatch) {
|
|
649
|
+
walkPdfOutlineChain(objMap, `${firstMatch[1]} ${firstMatch[2]}`, 0, /* @__PURE__ */ new Set(), out);
|
|
650
|
+
}
|
|
651
|
+
return { version, bookmarkCount: out.length, bookmarks: out };
|
|
652
|
+
}
|
|
584
653
|
var AUDIO_FORMAT_LABELS = {
|
|
585
654
|
1: "PCM",
|
|
586
655
|
3: "IEEE float",
|
|
@@ -1438,4 +1507,4 @@ function readMidiInfo(bytes) {
|
|
|
1438
1507
|
};
|
|
1439
1508
|
}
|
|
1440
1509
|
|
|
1441
|
-
export { inspectGifFrames, media_exports, readExifData, readFlacInfo, readIcoInfo, readId3Tags, readImageInfo, readMidiInfo, readPdfMetadata, readPdfPageDimensions, readVideoInfo, readWavInfo };
|
|
1510
|
+
export { inspectGifFrames, media_exports, readExifData, readFlacInfo, readIcoInfo, readId3Tags, readImageInfo, readMidiInfo, readPdfMetadata, readPdfOutline, readPdfPageDimensions, readVideoInfo, readWavInfo };
|
package/dist/index.cjs
CHANGED
|
@@ -11465,6 +11465,7 @@ __export(network_exports, {
|
|
|
11465
11465
|
parseVaryHeader: () => parseVaryHeader,
|
|
11466
11466
|
parseXContentTypeOptionsHeader: () => parseXContentTypeOptionsHeader,
|
|
11467
11467
|
parseXRobotsTag: () => parseXRobotsTag,
|
|
11468
|
+
scoreSecurityHeaders: () => scoreSecurityHeaders,
|
|
11468
11469
|
searchHeaders: () => searchHeaders,
|
|
11469
11470
|
searchStatusCodes: () => searchStatusCodes,
|
|
11470
11471
|
splitSitemap: () => splitSitemap,
|
|
@@ -14904,6 +14905,123 @@ function calculateCookieSizeBudget(cookieHeader, budgetBytes = DEFAULT_COOKIE_BU
|
|
|
14904
14905
|
exceedsBudget: totalBytes > budgetBytes
|
|
14905
14906
|
};
|
|
14906
14907
|
}
|
|
14908
|
+
function parseRawHeaderBlock(raw) {
|
|
14909
|
+
const map = /* @__PURE__ */ new Map();
|
|
14910
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
14911
|
+
const trimmed = line.trim();
|
|
14912
|
+
if (!trimmed) continue;
|
|
14913
|
+
const idx = trimmed.indexOf(":");
|
|
14914
|
+
if (idx === -1) continue;
|
|
14915
|
+
const name = trimmed.slice(0, idx).trim().toLowerCase();
|
|
14916
|
+
const value = trimmed.slice(idx + 1).trim();
|
|
14917
|
+
if (!map.has(name)) map.set(name, value);
|
|
14918
|
+
}
|
|
14919
|
+
return map;
|
|
14920
|
+
}
|
|
14921
|
+
var SECURITY_HEADER_CHECKS = [
|
|
14922
|
+
{
|
|
14923
|
+
header: "Content-Security-Policy",
|
|
14924
|
+
evaluate: (v) => {
|
|
14925
|
+
if (!v) return { status: "missing", note: "Without a CSP, an injected script runs with full page privileges." };
|
|
14926
|
+
if (/unsafe-inline|unsafe-eval/i.test(v)) return { status: "warning", note: "Contains unsafe-inline or unsafe-eval, which weakens XSS protection." };
|
|
14927
|
+
return { status: "pass", note: "Present. Use the CSP Header Builder tool to validate its directives in depth." };
|
|
14928
|
+
}
|
|
14929
|
+
},
|
|
14930
|
+
{
|
|
14931
|
+
header: "Strict-Transport-Security",
|
|
14932
|
+
evaluate: (v) => {
|
|
14933
|
+
if (!v) return { status: "missing", note: "Without HSTS, a user's first visit (and any later downgrade) can be sent over plain HTTP." };
|
|
14934
|
+
const maxAgeMatch = v.match(/max-age\s*=\s*(\d+)/i);
|
|
14935
|
+
if (!maxAgeMatch) return { status: "warning", note: "Present but missing a max-age directive." };
|
|
14936
|
+
const maxAge = Number(maxAgeMatch[1]);
|
|
14937
|
+
if (maxAge < 31536e3) return { status: "warning", note: "max-age is below the recommended 1 year (31536000 seconds)." };
|
|
14938
|
+
return { status: "pass", note: "Present with a max-age of at least 1 year." };
|
|
14939
|
+
}
|
|
14940
|
+
},
|
|
14941
|
+
{
|
|
14942
|
+
header: "X-Content-Type-Options",
|
|
14943
|
+
evaluate: (v) => {
|
|
14944
|
+
if (!v) return { status: "missing", note: "Without this header, browsers may MIME-sniff a response into an unintended content type." };
|
|
14945
|
+
if (v.trim().toLowerCase() !== "nosniff") return { status: "warning", note: `"nosniff" is the only valid value; this value won't take effect.` };
|
|
14946
|
+
return { status: "pass", note: "Set to the only valid value, nosniff." };
|
|
14947
|
+
}
|
|
14948
|
+
},
|
|
14949
|
+
{
|
|
14950
|
+
header: "X-Frame-Options",
|
|
14951
|
+
evaluate: (v) => {
|
|
14952
|
+
if (!v) return { status: "missing", note: "Without this (or a CSP frame-ancestors directive), the page can be framed by another site for clickjacking." };
|
|
14953
|
+
const upper = v.trim().toUpperCase();
|
|
14954
|
+
if (upper === "DENY" || upper === "SAMEORIGIN") return { status: "pass", note: `Framing restricted (${upper}).` };
|
|
14955
|
+
if (upper.startsWith("ALLOW-FROM")) return { status: "warning", note: "ALLOW-FROM is deprecated and ignored by most modern browsers." };
|
|
14956
|
+
return { status: "warning", note: "Unrecognized value." };
|
|
14957
|
+
}
|
|
14958
|
+
},
|
|
14959
|
+
{
|
|
14960
|
+
header: "Referrer-Policy",
|
|
14961
|
+
evaluate: (v) => {
|
|
14962
|
+
if (!v) return { status: "missing", note: "Without this header, the browser's default referrer behavior applies, which can leak full URLs to third parties." };
|
|
14963
|
+
if (v.trim().toLowerCase() === "unsafe-url") return { status: "warning", note: "unsafe-url leaks the full URL, including path and query string, to every destination." };
|
|
14964
|
+
return { status: "pass", note: "Present." };
|
|
14965
|
+
}
|
|
14966
|
+
},
|
|
14967
|
+
{
|
|
14968
|
+
header: "Permissions-Policy",
|
|
14969
|
+
evaluate: (v) => {
|
|
14970
|
+
if (!v) return { status: "missing", note: "Without this header, embedded content can use powerful browser features (camera, geolocation, etc.) unless restricted another way." };
|
|
14971
|
+
return { status: "pass", note: "Present." };
|
|
14972
|
+
}
|
|
14973
|
+
},
|
|
14974
|
+
{
|
|
14975
|
+
header: "Cross-Origin-Opener-Policy",
|
|
14976
|
+
evaluate: (v) => {
|
|
14977
|
+
if (!v) return { status: "missing", note: "Without COOP, this page can be put in the same browsing context group as a malicious opener window." };
|
|
14978
|
+
const lower = v.trim().toLowerCase();
|
|
14979
|
+
if (lower === "same-origin") return { status: "pass", note: "Set to same-origin, the strongest isolation value." };
|
|
14980
|
+
return { status: "warning", note: `Set to "${v.trim()}", which is weaker than same-origin.` };
|
|
14981
|
+
}
|
|
14982
|
+
},
|
|
14983
|
+
{
|
|
14984
|
+
header: "Cross-Origin-Embedder-Policy",
|
|
14985
|
+
evaluate: (v) => {
|
|
14986
|
+
if (!v) return { status: "missing", note: "Required alongside COOP for cross-origin isolation (e.g. to use SharedArrayBuffer)." };
|
|
14987
|
+
const lower = v.trim().toLowerCase();
|
|
14988
|
+
if (lower === "require-corp" || lower === "credentialless") return { status: "pass", note: `Set to ${lower}.` };
|
|
14989
|
+
return { status: "warning", note: `Unrecognized value "${v.trim()}".` };
|
|
14990
|
+
}
|
|
14991
|
+
},
|
|
14992
|
+
{
|
|
14993
|
+
header: "Cross-Origin-Resource-Policy",
|
|
14994
|
+
evaluate: (v) => {
|
|
14995
|
+
if (!v) return { status: "missing", note: "Without CORP, this resource can be loaded cross-origin by any site that knows its URL." };
|
|
14996
|
+
const lower = v.trim().toLowerCase();
|
|
14997
|
+
if (lower === "same-origin" || lower === "same-site") return { status: "pass", note: `Set to ${lower}.` };
|
|
14998
|
+
if (lower === "cross-origin") return { status: "warning", note: "Set to cross-origin, which allows any site to load this resource." };
|
|
14999
|
+
return { status: "warning", note: `Unrecognized value "${v.trim()}".` };
|
|
15000
|
+
}
|
|
15001
|
+
}
|
|
15002
|
+
];
|
|
15003
|
+
function scoreSecurityHeaders(rawHeaders) {
|
|
15004
|
+
if (typeof rawHeaders !== "string" || !rawHeaders.trim()) {
|
|
15005
|
+
return { error: 'Paste one or more response headers, one per line in "Name: value" form' };
|
|
15006
|
+
}
|
|
15007
|
+
const headerMap = parseRawHeaderBlock(rawHeaders);
|
|
15008
|
+
if (headerMap.size === 0) {
|
|
15009
|
+
return { error: 'Could not parse any "Name: value" header lines from the input' };
|
|
15010
|
+
}
|
|
15011
|
+
const checks = SECURITY_HEADER_CHECKS.map((def) => {
|
|
15012
|
+
const value = headerMap.get(def.header.toLowerCase()) ?? null;
|
|
15013
|
+
const { status, note } = def.evaluate(value);
|
|
15014
|
+
return { header: def.header, status, value, note };
|
|
15015
|
+
});
|
|
15016
|
+
const passCount = checks.filter((c) => c.status === "pass").length;
|
|
15017
|
+
const warningCount = checks.filter((c) => c.status === "warning").length;
|
|
15018
|
+
const missingCount = checks.filter((c) => c.status === "missing").length;
|
|
15019
|
+
const totalChecks = checks.length;
|
|
15020
|
+
const points = passCount + warningCount * 0.5;
|
|
15021
|
+
const score = Math.round(points / totalChecks * 100);
|
|
15022
|
+
const grade = score >= 90 ? "A" : score >= 75 ? "B" : score >= 60 ? "C" : score >= 40 ? "D" : "F";
|
|
15023
|
+
return { checks, score, grade, passCount, warningCount, missingCount, totalChecks };
|
|
15024
|
+
}
|
|
14907
15025
|
|
|
14908
15026
|
// src/tools/api.ts
|
|
14909
15027
|
var api_exports = {};
|
|
@@ -24902,6 +25020,7 @@ __export(media_exports, {
|
|
|
24902
25020
|
readImageInfo: () => readImageInfo,
|
|
24903
25021
|
readMidiInfo: () => readMidiInfo,
|
|
24904
25022
|
readPdfMetadata: () => readPdfMetadata,
|
|
25023
|
+
readPdfOutline: () => readPdfOutline,
|
|
24905
25024
|
readPdfPageDimensions: () => readPdfPageDimensions,
|
|
24906
25025
|
readVideoInfo: () => readVideoInfo,
|
|
24907
25026
|
readWavInfo: () => readWavInfo
|
|
@@ -25472,6 +25591,74 @@ function readPdfPageDimensions(bytes) {
|
|
|
25472
25591
|
if (out.length === 0) return { error: "Could not locate any page objects in this PDF" };
|
|
25473
25592
|
return { version: version2, pageCount: out.length, pages: out };
|
|
25474
25593
|
}
|
|
25594
|
+
function parsePdfOutlineDest(dict) {
|
|
25595
|
+
const directRef = dict.match(/\/Dest\s*\[\s*(\d+)\s+(\d+)\s+R/);
|
|
25596
|
+
if (directRef) return { destType: "page", target: `${directRef[1]} ${directRef[2]} R` };
|
|
25597
|
+
const directName = dict.match(/\/Dest\s*\/([^\s/()<>[\]]+)/);
|
|
25598
|
+
if (directName) return { destType: "named", target: directName[1] };
|
|
25599
|
+
const directString = dict.match(/\/Dest\s*\(((?:\\.|[^\\()])*)\)/);
|
|
25600
|
+
if (directString) return { destType: "named", target: decodePdfString(directString[1], false) };
|
|
25601
|
+
const actionUri = dict.match(/\/S\s*\/URI[\s\S]*?\/URI\s*\(((?:\\.|[^\\()])*)\)/);
|
|
25602
|
+
if (actionUri) return { destType: "uri", target: decodePdfString(actionUri[1], false) };
|
|
25603
|
+
const actionGotoRef = dict.match(/\/S\s*\/GoTo[\s\S]*?\/D\s*\[\s*(\d+)\s+(\d+)\s+R/);
|
|
25604
|
+
if (actionGotoRef) return { destType: "page", target: `${actionGotoRef[1]} ${actionGotoRef[2]} R` };
|
|
25605
|
+
const actionGotoName = dict.match(/\/S\s*\/GoTo[\s\S]*?\/D\s*\/([^\s/()<>[\]]+)/);
|
|
25606
|
+
if (actionGotoName) return { destType: "named", target: actionGotoName[1] };
|
|
25607
|
+
return { destType: "none", target: null };
|
|
25608
|
+
}
|
|
25609
|
+
function walkPdfOutlineChain(objMap, startRef, level, visited, out) {
|
|
25610
|
+
let ref = startRef;
|
|
25611
|
+
while (ref) {
|
|
25612
|
+
if (visited.has(ref)) break;
|
|
25613
|
+
visited.add(ref);
|
|
25614
|
+
const body = objMap.get(ref);
|
|
25615
|
+
if (!body) break;
|
|
25616
|
+
const titleRaw = extractDictField(body, "Title");
|
|
25617
|
+
const { destType, target } = parsePdfOutlineDest(body);
|
|
25618
|
+
out.push({ title: titleRaw ?? "(untitled)", level, destType, target });
|
|
25619
|
+
const firstMatch = body.match(/\/First\s+(\d+)\s+(\d+)\s+R/);
|
|
25620
|
+
if (firstMatch) walkPdfOutlineChain(objMap, `${firstMatch[1]} ${firstMatch[2]}`, level + 1, visited, out);
|
|
25621
|
+
const nextMatch = body.match(/\/Next\s+(\d+)\s+(\d+)\s+R/);
|
|
25622
|
+
ref = nextMatch ? `${nextMatch[1]} ${nextMatch[2]}` : null;
|
|
25623
|
+
}
|
|
25624
|
+
}
|
|
25625
|
+
function readPdfOutline(bytes) {
|
|
25626
|
+
if (bytes.length < 8) return { error: "File too small to be a PDF" };
|
|
25627
|
+
const header = bytesToLatin1(bytes.subarray(0, 16));
|
|
25628
|
+
const versionMatch = header.match(/%PDF-(\d\.\d)/);
|
|
25629
|
+
if (!versionMatch) return { error: "Not a valid PDF file (missing %PDF header)" };
|
|
25630
|
+
const version2 = versionMatch[1];
|
|
25631
|
+
const text = bytesToLatin1(bytes);
|
|
25632
|
+
const objBlocks = [...text.matchAll(/(\d+)\s+(\d+)\s+obj([\s\S]*?)endobj/g)];
|
|
25633
|
+
const objMap = /* @__PURE__ */ new Map();
|
|
25634
|
+
for (const b of objBlocks) objMap.set(`${b[1]} ${b[2]}`, b[3]);
|
|
25635
|
+
let outlinesBody = null;
|
|
25636
|
+
const trailerMatches = [...text.matchAll(/trailer\s*<<([\s\S]*?)>>/g)];
|
|
25637
|
+
if (trailerMatches.length > 0) {
|
|
25638
|
+
const trailer = trailerMatches[trailerMatches.length - 1][1];
|
|
25639
|
+
const rootRef = trailer.match(/\/Root\s+(\d+)\s+(\d+)\s+R/);
|
|
25640
|
+
if (rootRef) {
|
|
25641
|
+
const catalogBody = objMap.get(`${rootRef[1]} ${rootRef[2]}`);
|
|
25642
|
+
const outlinesRef = catalogBody?.match(/\/Outlines\s+(\d+)\s+(\d+)\s+R/);
|
|
25643
|
+
if (outlinesRef) outlinesBody = objMap.get(`${outlinesRef[1]} ${outlinesRef[2]}`) ?? null;
|
|
25644
|
+
}
|
|
25645
|
+
}
|
|
25646
|
+
if (!outlinesBody) {
|
|
25647
|
+
for (const b of objBlocks) {
|
|
25648
|
+
if (/\/Type\s*\/Outlines\b/.test(b[3])) {
|
|
25649
|
+
outlinesBody = b[3];
|
|
25650
|
+
break;
|
|
25651
|
+
}
|
|
25652
|
+
}
|
|
25653
|
+
}
|
|
25654
|
+
if (!outlinesBody) return { error: "No /Outlines bookmark tree found in this PDF" };
|
|
25655
|
+
const out = [];
|
|
25656
|
+
const firstMatch = outlinesBody.match(/\/First\s+(\d+)\s+(\d+)\s+R/);
|
|
25657
|
+
if (firstMatch) {
|
|
25658
|
+
walkPdfOutlineChain(objMap, `${firstMatch[1]} ${firstMatch[2]}`, 0, /* @__PURE__ */ new Set(), out);
|
|
25659
|
+
}
|
|
25660
|
+
return { version: version2, bookmarkCount: out.length, bookmarks: out };
|
|
25661
|
+
}
|
|
25475
25662
|
var AUDIO_FORMAT_LABELS = {
|
|
25476
25663
|
1: "PCM",
|
|
25477
25664
|
3: "IEEE float",
|
package/dist/index.d.cts
CHANGED
|
@@ -6,14 +6,14 @@ export { d as data } from './data-26TALa9U.cjs';
|
|
|
6
6
|
export { g as generators } from './generators-DAXXrMvG.cjs';
|
|
7
7
|
export { t as time } from './time-KqJjdqII.cjs';
|
|
8
8
|
export { u as units } from './units-BqegyALA.cjs';
|
|
9
|
-
export { n as network } from './network-
|
|
9
|
+
export { n as network } from './network-BskZe1n2.cjs';
|
|
10
10
|
export { a as api } from './api-CQnIUrVB.cjs';
|
|
11
11
|
export { c as code } from './code-46xO9xFf.cjs';
|
|
12
12
|
export { c as color } from './color-tPwZCr9H.cjs';
|
|
13
13
|
export { c as css } from './css-Cf7AMGM-.cjs';
|
|
14
14
|
export { m as misc } from './misc-CA3N198T.cjs';
|
|
15
15
|
export { a as ai_agent } from './ai_agent-CmrVjvYH.cjs';
|
|
16
|
-
export { m as media } from './media-
|
|
16
|
+
export { m as media } from './media-DF8BS-iA.cjs';
|
|
17
17
|
|
|
18
18
|
declare const version = "0.1.0";
|
|
19
19
|
|
package/dist/index.d.ts
CHANGED
|
@@ -6,14 +6,14 @@ export { d as data } from './data-26TALa9U.js';
|
|
|
6
6
|
export { g as generators } from './generators-DAXXrMvG.js';
|
|
7
7
|
export { t as time } from './time-KqJjdqII.js';
|
|
8
8
|
export { u as units } from './units-BqegyALA.js';
|
|
9
|
-
export { n as network } from './network-
|
|
9
|
+
export { n as network } from './network-BskZe1n2.js';
|
|
10
10
|
export { a as api } from './api-CQnIUrVB.js';
|
|
11
11
|
export { c as code } from './code-46xO9xFf.js';
|
|
12
12
|
export { c as color } from './color-tPwZCr9H.js';
|
|
13
13
|
export { c as css } from './css-Cf7AMGM-.js';
|
|
14
14
|
export { m as misc } from './misc-CA3N198T.js';
|
|
15
15
|
export { a as ai_agent } from './ai_agent-CmrVjvYH.js';
|
|
16
|
-
export { m as media } from './media-
|
|
16
|
+
export { m as media } from './media-DF8BS-iA.js';
|
|
17
17
|
|
|
18
18
|
declare const version = "0.1.0";
|
|
19
19
|
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { media_exports as media } from './chunk-
|
|
1
|
+
export { media_exports as media } from './chunk-ZWFZRDQ4.js';
|
|
2
2
|
export { units_exports as units } from './chunk-RP574L5Z.js';
|
|
3
|
-
export { network_exports as network } from './chunk-
|
|
3
|
+
export { network_exports as network } from './chunk-KWS4ZCYG.js';
|
|
4
4
|
export { api_exports as api } from './chunk-U2HREMZU.js';
|
|
5
5
|
export { code_exports as code } from './chunk-XT2BQWXT.js';
|
|
6
6
|
export { color_exports as color } from './chunk-BPVAB4P2.js';
|
|
@@ -87,6 +87,32 @@ interface PdfPageDimensionsResult {
|
|
|
87
87
|
* PDF spec requires. No PDF rendering library required.
|
|
88
88
|
*/
|
|
89
89
|
declare function readPdfPageDimensions(bytes: Uint8Array): PdfPageDimensionsResult | PdfMetadataError;
|
|
90
|
+
type PdfOutlineDestType = 'page' | 'uri' | 'named' | 'none';
|
|
91
|
+
interface PdfOutlineItem {
|
|
92
|
+
title: string;
|
|
93
|
+
level: number;
|
|
94
|
+
destType: PdfOutlineDestType;
|
|
95
|
+
target: string | null;
|
|
96
|
+
}
|
|
97
|
+
interface PdfOutlineResult {
|
|
98
|
+
version: string | null;
|
|
99
|
+
bookmarkCount: number;
|
|
100
|
+
bookmarks: PdfOutlineItem[];
|
|
101
|
+
}
|
|
102
|
+
interface PdfOutlineError {
|
|
103
|
+
error: string;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Walk a PDF's /Outlines bookmark tree (the Root -> Outlines -> First/Next/
|
|
107
|
+
* First chain of entries a PDF viewer's sidebar builds its table of
|
|
108
|
+
* contents from) and list every bookmark's title, nesting level, and link
|
|
109
|
+
* target, in document order. Only the destination's raw target is reported
|
|
110
|
+
* (an object reference for a page link, a URI for a web link, or a name for
|
|
111
|
+
* a named destination) — this does not resolve a page-ref target to a page
|
|
112
|
+
* number, since that requires a second pass over the page tree; pair it
|
|
113
|
+
* with readPdfPageDimensions's output if you need that mapping.
|
|
114
|
+
*/
|
|
115
|
+
declare function readPdfOutline(bytes: Uint8Array): PdfOutlineResult | PdfOutlineError;
|
|
90
116
|
interface WavInfo {
|
|
91
117
|
audioFormat: number;
|
|
92
118
|
audioFormatLabel: string;
|
|
@@ -285,6 +311,10 @@ type media_MidiTimeSignature = MidiTimeSignature;
|
|
|
285
311
|
type media_MidiTrackInfo = MidiTrackInfo;
|
|
286
312
|
type media_PdfMetadata = PdfMetadata;
|
|
287
313
|
type media_PdfMetadataError = PdfMetadataError;
|
|
314
|
+
type media_PdfOutlineDestType = PdfOutlineDestType;
|
|
315
|
+
type media_PdfOutlineError = PdfOutlineError;
|
|
316
|
+
type media_PdfOutlineItem = PdfOutlineItem;
|
|
317
|
+
type media_PdfOutlineResult = PdfOutlineResult;
|
|
288
318
|
type media_PdfPageDimension = PdfPageDimension;
|
|
289
319
|
type media_PdfPageDimensionsResult = PdfPageDimensionsResult;
|
|
290
320
|
type media_PdfPageOrientation = PdfPageOrientation;
|
|
@@ -300,11 +330,12 @@ declare const media_readId3Tags: typeof readId3Tags;
|
|
|
300
330
|
declare const media_readImageInfo: typeof readImageInfo;
|
|
301
331
|
declare const media_readMidiInfo: typeof readMidiInfo;
|
|
302
332
|
declare const media_readPdfMetadata: typeof readPdfMetadata;
|
|
333
|
+
declare const media_readPdfOutline: typeof readPdfOutline;
|
|
303
334
|
declare const media_readPdfPageDimensions: typeof readPdfPageDimensions;
|
|
304
335
|
declare const media_readVideoInfo: typeof readVideoInfo;
|
|
305
336
|
declare const media_readWavInfo: typeof readWavInfo;
|
|
306
337
|
declare namespace media {
|
|
307
|
-
export { type media_ExifData as ExifData, type media_ExifError as ExifError, type media_FlacInfo as FlacInfo, type media_FlacInfoError as FlacInfoError, type media_GifInfo as GifInfo, type media_GifInfoError as GifInfoError, type media_IcoImageEntry as IcoImageEntry, type media_IcoInfo as IcoInfo, type media_IcoInfoError as IcoInfoError, type media_Id3Tags as Id3Tags, type media_Id3TagsError as Id3TagsError, type media_ImageFormat as ImageFormat, type media_ImageInfo as ImageInfo, type media_ImageInfoError as ImageInfoError, type media_MidiDivision as MidiDivision, type media_MidiInfo as MidiInfo, type media_MidiInfoError as MidiInfoError, type media_MidiTimeSignature as MidiTimeSignature, type media_MidiTrackInfo as MidiTrackInfo, type media_PdfMetadata as PdfMetadata, type media_PdfMetadataError as PdfMetadataError, type media_PdfPageDimension as PdfPageDimension, type media_PdfPageDimensionsResult as PdfPageDimensionsResult, type media_PdfPageOrientation as PdfPageOrientation, type media_VideoInfo as VideoInfo, type media_VideoInfoError as VideoInfoError, type media_WavInfo as WavInfo, type media_WavInfoError as WavInfoError, media_inspectGifFrames as inspectGifFrames, media_readExifData as readExifData, media_readFlacInfo as readFlacInfo, media_readIcoInfo as readIcoInfo, media_readId3Tags as readId3Tags, media_readImageInfo as readImageInfo, media_readMidiInfo as readMidiInfo, media_readPdfMetadata as readPdfMetadata, media_readPdfPageDimensions as readPdfPageDimensions, media_readVideoInfo as readVideoInfo, media_readWavInfo as readWavInfo };
|
|
338
|
+
export { type media_ExifData as ExifData, type media_ExifError as ExifError, type media_FlacInfo as FlacInfo, type media_FlacInfoError as FlacInfoError, type media_GifInfo as GifInfo, type media_GifInfoError as GifInfoError, type media_IcoImageEntry as IcoImageEntry, type media_IcoInfo as IcoInfo, type media_IcoInfoError as IcoInfoError, type media_Id3Tags as Id3Tags, type media_Id3TagsError as Id3TagsError, type media_ImageFormat as ImageFormat, type media_ImageInfo as ImageInfo, type media_ImageInfoError as ImageInfoError, type media_MidiDivision as MidiDivision, type media_MidiInfo as MidiInfo, type media_MidiInfoError as MidiInfoError, type media_MidiTimeSignature as MidiTimeSignature, type media_MidiTrackInfo as MidiTrackInfo, type media_PdfMetadata as PdfMetadata, type media_PdfMetadataError as PdfMetadataError, type media_PdfOutlineDestType as PdfOutlineDestType, type media_PdfOutlineError as PdfOutlineError, type media_PdfOutlineItem as PdfOutlineItem, type media_PdfOutlineResult as PdfOutlineResult, type media_PdfPageDimension as PdfPageDimension, type media_PdfPageDimensionsResult as PdfPageDimensionsResult, type media_PdfPageOrientation as PdfPageOrientation, type media_VideoInfo as VideoInfo, type media_VideoInfoError as VideoInfoError, type media_WavInfo as WavInfo, type media_WavInfoError as WavInfoError, media_inspectGifFrames as inspectGifFrames, media_readExifData as readExifData, media_readFlacInfo as readFlacInfo, media_readIcoInfo as readIcoInfo, media_readId3Tags as readId3Tags, media_readImageInfo as readImageInfo, media_readMidiInfo as readMidiInfo, media_readPdfMetadata as readPdfMetadata, media_readPdfOutline as readPdfOutline, media_readPdfPageDimensions as readPdfPageDimensions, media_readVideoInfo as readVideoInfo, media_readWavInfo as readWavInfo };
|
|
308
339
|
}
|
|
309
340
|
|
|
310
|
-
export {
|
|
341
|
+
export { readExifData as A, readFlacInfo as B, readIcoInfo as C, readId3Tags as D, type ExifData as E, type FlacInfo as F, type GifInfo as G, readImageInfo as H, type IcoImageEntry as I, readMidiInfo as J, readPdfMetadata as K, readPdfOutline as L, type MidiDivision as M, readPdfPageDimensions as N, readVideoInfo as O, type PdfMetadata as P, readWavInfo as Q, type VideoInfo as V, type WavInfo as W, type ExifError as a, type FlacInfoError as b, type GifInfoError as c, type IcoInfo as d, type IcoInfoError as e, type Id3Tags as f, type Id3TagsError as g, type ImageFormat as h, type ImageInfo as i, type ImageInfoError as j, type MidiInfo as k, type MidiInfoError as l, media as m, type MidiTimeSignature as n, type MidiTrackInfo as o, type PdfMetadataError as p, type PdfOutlineDestType as q, type PdfOutlineError as r, type PdfOutlineItem as s, type PdfOutlineResult as t, type PdfPageDimension as u, type PdfPageDimensionsResult as v, type PdfPageOrientation as w, type VideoInfoError as x, type WavInfoError as y, inspectGifFrames as z };
|