• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

adnsistemas / pdf-lib / #18

24 Mar 2026 08:15PM UTC coverage: 74.286% (+0.3%) from 74.001%
#18

push

David N. Abdala
Documentation change

2569 of 3981 branches covered (64.53%)

Branch coverage included in aggregate %.

7372 of 9401 relevant lines covered (78.42%)

297170.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.27
/src/core/objects/PDFName.ts
1
import { PrivateConstructorError } from '../errors';
54✔
2
import PDFObject from './PDFObject';
54✔
3
import CharCodes from '../syntax/CharCodes';
54✔
4
import { IsIrregular } from '../syntax/Irregular';
54✔
5
import {
54✔
6
  charFromHexCode,
7
  copyStringIntoBuffer,
8
  toCharCode,
9
  toHexString,
10
} from '../../utils';
11
import { PDFClasses } from '../../api/objects';
54✔
12

13
const decodeName = (name: string) =>
54✔
14
  name.replace(/#([\dABCDEF]{2})/g, (_, hex) => charFromHexCode(hex));
1,872,264✔
15

16
const isRegularChar = (charCode: number) =>
54✔
17
  charCode >= CharCodes.ExclamationPoint &&
46,586✔
18
  charCode <= CharCodes.Tilde &&
19
  !IsIrregular[charCode];
20

21
const ENFORCER = {};
54✔
22
const pool = new Map<string, PDFName>();
54✔
23

24
class PDFName extends PDFObject {
25
  static className = () => PDFClasses.PDFName;
3,220,727✔
26
  myClass(): PDFClasses {
27
    return PDFClasses.PDFName;
3,223,430✔
28
  }
29
  static of = (name: string): PDFName => {
54✔
30
    const decodedValue = decodeName(name);
1,872,264✔
31

32
    let instance = pool.get(decodedValue);
1,872,264✔
33
    if (!instance) {
1,872,264✔
34
      instance = new PDFName(ENFORCER, decodedValue);
6,990✔
35
      pool.set(decodedValue, instance);
6,990✔
36
    }
37

38
    return instance;
1,872,264✔
39
  };
40

41
  /* tslint:disable member-ordering */
42
  static readonly Length = PDFName.of('Length');
54✔
43
  static readonly FlateDecode = PDFName.of('FlateDecode');
54✔
44
  static readonly Resources = PDFName.of('Resources');
54✔
45
  static readonly Font = PDFName.of('Font');
54✔
46
  static readonly XObject = PDFName.of('XObject');
54✔
47
  static readonly ExtGState = PDFName.of('ExtGState');
54✔
48
  static readonly Contents = PDFName.of('Contents');
54✔
49
  static readonly Type = PDFName.of('Type');
54✔
50
  static readonly Parent = PDFName.of('Parent');
54✔
51
  static readonly MediaBox = PDFName.of('MediaBox');
54✔
52
  static readonly Page = PDFName.of('Page');
54✔
53
  static readonly Annots = PDFName.of('Annots');
54✔
54
  static readonly TrimBox = PDFName.of('TrimBox');
54✔
55
  static readonly ArtBox = PDFName.of('ArtBox');
54✔
56
  static readonly BleedBox = PDFName.of('BleedBox');
54✔
57
  static readonly CropBox = PDFName.of('CropBox');
54✔
58
  static readonly Rotate = PDFName.of('Rotate');
54✔
59
  static readonly Title = PDFName.of('Title');
54✔
60
  static readonly Author = PDFName.of('Author');
54✔
61
  static readonly Subject = PDFName.of('Subject');
54✔
62
  static readonly Creator = PDFName.of('Creator');
54✔
63
  static readonly Keywords = PDFName.of('Keywords');
54✔
64
  static readonly Producer = PDFName.of('Producer');
54✔
65
  static readonly CreationDate = PDFName.of('CreationDate');
54✔
66
  static readonly ModDate = PDFName.of('ModDate');
54✔
67
  /* tslint:enable member-ordering */
68

69
  private readonly encodedName: string;
70

71
  private constructor(enforcer: any, name: string) {
72
    if (enforcer !== ENFORCER) throw new PrivateConstructorError('PDFName');
6,991✔
73
    super();
6,990✔
74

75
    let encodedName = '/';
6,990✔
76
    for (let idx = 0, len = name.length; idx < len; idx++) {
6,990✔
77
      const character = name[idx];
46,586✔
78
      const code = toCharCode(character);
46,586✔
79
      encodedName += isRegularChar(code) ? character : `#${toHexString(code)}`;
46,586✔
80
    }
81

82
    this.encodedName = encodedName;
6,990✔
83
  }
84

85
  asBytes(): Uint8Array {
86
    const bytes: number[] = [];
68✔
87

88
    let hex = '';
68✔
89
    let escaped = false;
68✔
90

91
    const pushByte = (byte?: number) => {
68✔
92
      if (byte !== undefined) bytes.push(byte);
441✔
93
      escaped = false;
441✔
94
    };
95

96
    for (let idx = 1, len = this.encodedName.length; idx < len; idx++) {
68✔
97
      const char = this.encodedName[idx];
469✔
98
      const byte = toCharCode(char);
469✔
99
      const nextChar = this.encodedName[idx + 1];
469✔
100
      if (!escaped) {
469✔
101
        if (byte === CharCodes.Hash) escaped = true;
441✔
102
        else pushByte(byte);
427✔
103
      } else {
104
        if (
28!
105
          (byte >= CharCodes.Zero && byte <= CharCodes.Nine) ||
56!
106
          (byte >= CharCodes.a && byte <= CharCodes.f) ||
107
          (byte >= CharCodes.A && byte <= CharCodes.F)
108
        ) {
109
          hex += char;
28✔
110
          if (
28✔
111
            hex.length === 2 ||
42✔
112
            !(
113
              (nextChar >= '0' && nextChar <= '9') ||
28!
114
              (nextChar >= 'a' && nextChar <= 'f') ||
115
              (nextChar >= 'A' && nextChar <= 'F')
116
            )
117
          ) {
118
            pushByte(parseInt(hex, 16));
14✔
119
            hex = '';
14✔
120
          }
121
        } else {
122
          pushByte(byte);
×
123
        }
124
      }
125
    }
126

127
    return new Uint8Array(bytes);
68✔
128
  }
129

130
  // TODO: This should probably use `utf8Decode()`
131
  // TODO: Polyfill Array.from?
132
  decodeText(): string {
133
    const bytes = this.asBytes();
68✔
134
    return String.fromCharCode(...Array.from(bytes));
68✔
135
  }
136

137
  asString(): string {
138
    return this.encodedName;
114✔
139
  }
140

141
  /** @deprecated in favor of [[PDFName.asString]] */
142
  value(): string {
143
    return this.encodedName;
×
144
  }
145

146
  clone(): PDFName {
147
    return this;
145✔
148
  }
149

150
  toString(): string {
151
    return this.encodedName;
285✔
152
  }
153

154
  sizeInBytes(): number {
155
    return this.encodedName.length;
16,847✔
156
  }
157

158
  copyBytesInto(buffer: Uint8Array, offset: number): number {
159
    copyStringIntoBuffer(this.encodedName, buffer, offset);
16,266✔
160
    return this.encodedName.length;
16,266✔
161
  }
162
}
163

164
export default PDFName;
54✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc