pdf-codec 1.1.5 → 1.2.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/dist/index.cjs CHANGED
@@ -329,7 +329,6 @@ function unfilterScanlines(data, height, bytesPerRow, bpp) {
329
329
  for (let y = 0; y < height; y++) {
330
330
  const filterByte = data[y * stride];
331
331
  if (filterByte === void 0 || !isPngFilterType(filterByte)) throw new Error(`unknown PNG filter type: ${String(filterByte)}`);
332
- const filterType = filterByte;
333
332
  const rowStart = y * stride + 1;
334
333
  const outRowStart = y * bytesPerRow;
335
334
  const prevOutRowStart = y > 0 ? outRowStart - bytesPerRow : void 0;
@@ -338,7 +337,7 @@ function unfilterScanlines(data, height, bytesPerRow, bpp) {
338
337
  const a = x >= bpp ? out[outRowStart + x - bpp] : 0;
339
338
  const b = prevOutRowStart === void 0 ? 0 : out[prevOutRowStart + x];
340
339
  const c = x >= bpp && prevOutRowStart !== void 0 ? out[prevOutRowStart + x - bpp] : 0;
341
- out[outRowStart + x] = raw + predictorValue(filterType, a, b, c) & 255;
340
+ out[outRowStart + x] = raw + predictorValue(filterByte, a, b, c) & 255;
342
341
  }
343
342
  }
344
343
  return out;
@@ -1244,8 +1243,8 @@ function readXrefStreamSection(dict, raw, sink) {
1244
1243
  const entries = /* @__PURE__ */ new Map();
1245
1244
  let rowOffset = 0;
1246
1245
  for (const [start, count] of ranges) for (let i = 0; i < count; i++) {
1247
- const base = rowOffset;
1248
1246
  rowOffset += rowLength;
1247
+ const base = rowOffset - rowLength;
1249
1248
  if (rowLength === 0 || base + rowLength > decoded.bytes.length) {
1250
1249
  sink({
1251
1250
  code: "pdf/xref-entry-invalid",
@@ -1302,17 +1301,17 @@ function findAllKeywordPositions(bytes, needle) {
1302
1301
  function isDigitByte(byte) {
1303
1302
  return byte !== void 0 && byte >= 48 && byte <= 57;
1304
1303
  }
1304
+ function scanBackWhile(bytes, end, predicate) {
1305
+ let i = end;
1306
+ while (i > 0 && predicate(bytes[i - 1])) i--;
1307
+ return i;
1308
+ }
1305
1309
  function scanObjectHeaderBackward(bytes, objKeywordStart) {
1306
- let i = objKeywordStart;
1307
- while (i > 0 && isAsciiWhitespace(bytes[i - 1])) i--;
1308
- const genEnd = i;
1309
- while (i > 0 && isDigitByte(bytes[i - 1])) i--;
1310
- const genStart = i;
1310
+ const genEnd = scanBackWhile(bytes, objKeywordStart, isAsciiWhitespace);
1311
+ const genStart = scanBackWhile(bytes, genEnd, isDigitByte);
1311
1312
  if (genStart === genEnd) return;
1312
- while (i > 0 && isAsciiWhitespace(bytes[i - 1])) i--;
1313
- const numEnd = i;
1314
- while (i > 0 && isDigitByte(bytes[i - 1])) i--;
1315
- const numStart = i;
1313
+ const numEnd = scanBackWhile(bytes, genStart, isAsciiWhitespace);
1314
+ const numStart = scanBackWhile(bytes, numEnd, isDigitByte);
1316
1315
  if (numStart === numEnd) return;
1317
1316
  const decoder = new TextDecoder("latin1");
1318
1317
  return {
@@ -1486,9 +1485,11 @@ function openPdfDocument(bytes, sink) {
1486
1485
  function resolveDict(obj) {
1487
1486
  return asDict(resolve(obj));
1488
1487
  }
1489
- const resolvedRoot = resolveDict(dictGet(xref.trailer, "Root"));
1490
- if (resolvedRoot === void 0 || !isName(dictGet(resolvedRoot, "Type"), "Catalog")) throw new PdfParseError("pdf/no-root", "no resolvable /Root catalog was found, even after cross-reference recovery");
1491
- const catalog = resolvedRoot;
1488
+ function requireCatalog(dict) {
1489
+ if (dict === void 0 || !isName(dictGet(dict, "Type"), "Catalog")) throw new PdfParseError("pdf/no-root", "no resolvable /Root catalog was found, even after cross-reference recovery");
1490
+ return dict;
1491
+ }
1492
+ const catalog = requireCatalog(resolveDict(dictGet(xref.trailer, "Root")));
1492
1493
  function pages() {
1493
1494
  const pagesRoot = resolveDict(dictGet(catalog, "Pages"));
1494
1495
  if (pagesRoot === void 0) return [];
@@ -5264,20 +5265,19 @@ function readPdf(bytes, options) {
5264
5265
  const signal = options?.signal;
5265
5266
  if (!hasPdfHeader(bytes)) throw new PdfParseError("pdf/no-header", "no \"%PDF-\" header found within the first bytes of the file; this does not look like a PDF at all");
5266
5267
  const doc = openPdfDocument(bytes, sink);
5267
- const resolver = doc;
5268
5268
  const fontResolver = createFontResolver({
5269
- resolver,
5269
+ resolver: doc,
5270
5270
  sink
5271
5271
  });
5272
5272
  const images = {};
5273
5273
  const imageIdCache = /* @__PURE__ */ new Map();
5274
5274
  const pages = doc.pages().map((pageDict) => {
5275
5275
  throwIfAborted(signal);
5276
- return readPage(pageDict, resolver, fontResolver, images, imageIdCache, sink);
5276
+ return readPage(pageDict, doc, fontResolver, images, imageIdCache, sink);
5277
5277
  });
5278
5278
  return {
5279
5279
  formatVersion: document_schema_js.LAYOUT_FORMAT_VERSION,
5280
- metadata: readMetadata(doc.trailer, resolver),
5280
+ metadata: readMetadata(doc.trailer, doc),
5281
5281
  pages,
5282
5282
  images
5283
5283
  };
package/dist/index.js CHANGED
@@ -328,7 +328,6 @@ function unfilterScanlines(data, height, bytesPerRow, bpp) {
328
328
  for (let y = 0; y < height; y++) {
329
329
  const filterByte = data[y * stride];
330
330
  if (filterByte === void 0 || !isPngFilterType(filterByte)) throw new Error(`unknown PNG filter type: ${String(filterByte)}`);
331
- const filterType = filterByte;
332
331
  const rowStart = y * stride + 1;
333
332
  const outRowStart = y * bytesPerRow;
334
333
  const prevOutRowStart = y > 0 ? outRowStart - bytesPerRow : void 0;
@@ -337,7 +336,7 @@ function unfilterScanlines(data, height, bytesPerRow, bpp) {
337
336
  const a = x >= bpp ? out[outRowStart + x - bpp] : 0;
338
337
  const b = prevOutRowStart === void 0 ? 0 : out[prevOutRowStart + x];
339
338
  const c = x >= bpp && prevOutRowStart !== void 0 ? out[prevOutRowStart + x - bpp] : 0;
340
- out[outRowStart + x] = raw + predictorValue(filterType, a, b, c) & 255;
339
+ out[outRowStart + x] = raw + predictorValue(filterByte, a, b, c) & 255;
341
340
  }
342
341
  }
343
342
  return out;
@@ -1243,8 +1242,8 @@ function readXrefStreamSection(dict, raw, sink) {
1243
1242
  const entries = /* @__PURE__ */ new Map();
1244
1243
  let rowOffset = 0;
1245
1244
  for (const [start, count] of ranges) for (let i = 0; i < count; i++) {
1246
- const base = rowOffset;
1247
1245
  rowOffset += rowLength;
1246
+ const base = rowOffset - rowLength;
1248
1247
  if (rowLength === 0 || base + rowLength > decoded.bytes.length) {
1249
1248
  sink({
1250
1249
  code: "pdf/xref-entry-invalid",
@@ -1301,17 +1300,17 @@ function findAllKeywordPositions(bytes, needle) {
1301
1300
  function isDigitByte(byte) {
1302
1301
  return byte !== void 0 && byte >= 48 && byte <= 57;
1303
1302
  }
1303
+ function scanBackWhile(bytes, end, predicate) {
1304
+ let i = end;
1305
+ while (i > 0 && predicate(bytes[i - 1])) i--;
1306
+ return i;
1307
+ }
1304
1308
  function scanObjectHeaderBackward(bytes, objKeywordStart) {
1305
- let i = objKeywordStart;
1306
- while (i > 0 && isAsciiWhitespace(bytes[i - 1])) i--;
1307
- const genEnd = i;
1308
- while (i > 0 && isDigitByte(bytes[i - 1])) i--;
1309
- const genStart = i;
1309
+ const genEnd = scanBackWhile(bytes, objKeywordStart, isAsciiWhitespace);
1310
+ const genStart = scanBackWhile(bytes, genEnd, isDigitByte);
1310
1311
  if (genStart === genEnd) return;
1311
- while (i > 0 && isAsciiWhitespace(bytes[i - 1])) i--;
1312
- const numEnd = i;
1313
- while (i > 0 && isDigitByte(bytes[i - 1])) i--;
1314
- const numStart = i;
1312
+ const numEnd = scanBackWhile(bytes, genStart, isAsciiWhitespace);
1313
+ const numStart = scanBackWhile(bytes, numEnd, isDigitByte);
1315
1314
  if (numStart === numEnd) return;
1316
1315
  const decoder = new TextDecoder("latin1");
1317
1316
  return {
@@ -1485,9 +1484,11 @@ function openPdfDocument(bytes, sink) {
1485
1484
  function resolveDict(obj) {
1486
1485
  return asDict(resolve(obj));
1487
1486
  }
1488
- const resolvedRoot = resolveDict(dictGet(xref.trailer, "Root"));
1489
- if (resolvedRoot === void 0 || !isName(dictGet(resolvedRoot, "Type"), "Catalog")) throw new PdfParseError("pdf/no-root", "no resolvable /Root catalog was found, even after cross-reference recovery");
1490
- const catalog = resolvedRoot;
1487
+ function requireCatalog(dict) {
1488
+ if (dict === void 0 || !isName(dictGet(dict, "Type"), "Catalog")) throw new PdfParseError("pdf/no-root", "no resolvable /Root catalog was found, even after cross-reference recovery");
1489
+ return dict;
1490
+ }
1491
+ const catalog = requireCatalog(resolveDict(dictGet(xref.trailer, "Root")));
1491
1492
  function pages() {
1492
1493
  const pagesRoot = resolveDict(dictGet(catalog, "Pages"));
1493
1494
  if (pagesRoot === void 0) return [];
@@ -5263,20 +5264,19 @@ function readPdf(bytes, options) {
5263
5264
  const signal = options?.signal;
5264
5265
  if (!hasPdfHeader(bytes)) throw new PdfParseError("pdf/no-header", "no \"%PDF-\" header found within the first bytes of the file; this does not look like a PDF at all");
5265
5266
  const doc = openPdfDocument(bytes, sink);
5266
- const resolver = doc;
5267
5267
  const fontResolver = createFontResolver({
5268
- resolver,
5268
+ resolver: doc,
5269
5269
  sink
5270
5270
  });
5271
5271
  const images = {};
5272
5272
  const imageIdCache = /* @__PURE__ */ new Map();
5273
5273
  const pages = doc.pages().map((pageDict) => {
5274
5274
  throwIfAborted(signal);
5275
- return readPage(pageDict, resolver, fontResolver, images, imageIdCache, sink);
5275
+ return readPage(pageDict, doc, fontResolver, images, imageIdCache, sink);
5276
5276
  });
5277
5277
  return {
5278
5278
  formatVersion: LAYOUT_FORMAT_VERSION,
5279
- metadata: readMetadata(doc.trailer, resolver),
5279
+ metadata: readMetadata(doc.trailer, doc),
5280
5280
  pages,
5281
5281
  images
5282
5282
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdf-codec",
3
- "version": "1.1.5",
3
+ "version": "1.2.0",
4
4
  "description": "Hand-written, dependency-minimal PDF codec: parses arbitrary real-world PDFs and generates new ones, built on document-schema.js's LayoutDocument pivot and Zod 4 codecs.",
5
5
  "type": "module",
6
6
  "repository": {