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

vbuch / node-signpdf / 17455699876

04 Sep 2025 06:45AM UTC coverage: 84.563% (-15.4%) from 100.0%
17455699876

Pull #294

github

Copilot
Restore dist files after build - addressing missing dist files issue

Co-authored-by: vbuch <5102057+vbuch@users.noreply.github.com>
Pull Request #294: Decouple placeholder-plain from pdfkit010 by moving shared utilities to utils package

137 of 172 branches covered (79.65%)

Branch coverage included in aggregate %.

5 of 60 new or added lines in 3 files covered. (8.33%)

356 of 411 relevant lines covered (86.62%)

19.42 hits per line

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

0.0
/packages/utils/src/PDFObject.js
1
/*
2
PDFObject by Devon Govett used below.
3
The class is part of pdfkit. See https://github.com/foliojs/pdfkit
4
LICENSE: MIT. Included in this folder.
5
Modifications may have been applied for the purposes of node-signpdf.
6
*/
7

8
import {PDFAbstractReference} from './PDFAbstractReference';
9
/*
10
PDFObject - converts JavaScript types into their corresponding PDF types.
11
By Devon Govett
12
*/
13

NEW
14
const pad = (str, length) => (Array(length + 1).join('0') + str).slice(-length);
×
15

NEW
16
const escapableRe = /[\n\r\t\b\f()\\]/g;
×
NEW
17
const escapable = {
×
18
    '\n': '\\n',
19
    '\r': '\\r',
20
    '\t': '\\t',
21
    '\b': '\\b',
22
    '\f': '\\f',
23
    '\\': '\\\\',
24
    '(': '\\(',
25
    ')': '\\)',
26
};
27

28
// Convert little endian UTF-16 to big endian
NEW
29
const swapBytes = (buff) => buff.swap16();
×
30

31
export class PDFObject {
32
    static convert(object, encryptFn = null) {
×
33
    // String literals are converted to the PDF name type
NEW
34
        if (typeof object === 'string') {
×
NEW
35
            return `/${object}`;
×
36

37
            // String objects are converted to PDF strings (UTF-16)
NEW
38
        } if (object instanceof String) {
×
NEW
39
            let string = object;
×
40
            // Detect if this is a unicode string
NEW
41
            let isUnicode = false;
×
NEW
42
            for (let i = 0, end = string.length; i < end; i += 1) {
×
NEW
43
                if (string.charCodeAt(i) > 0x7f) {
×
NEW
44
                    isUnicode = true;
×
NEW
45
                    break;
×
46
                }
47
            }
48

49
            // If so, encode it as big endian UTF-16
50
            let stringBuffer;
NEW
51
            if (isUnicode) {
×
NEW
52
                stringBuffer = swapBytes(Buffer.from(`\ufeff${string}`, 'utf16le'));
×
53
            } else {
NEW
54
                stringBuffer = Buffer.from(string, 'ascii');
×
55
            }
56

57
            // Encrypt the string when necessary
NEW
58
            if (encryptFn) {
×
NEW
59
                string = encryptFn(stringBuffer).toString('binary');
×
60
            } else {
NEW
61
                string = stringBuffer.toString('binary');
×
62
            }
63

64
            // Escape characters as required by the spec
NEW
65
            string = string.replace(escapableRe, (c) => escapable[c]);
×
66

NEW
67
            return `(${string})`;
×
68

69
            // Buffers are converted to PDF hex strings
NEW
70
        } if (Buffer.isBuffer(object)) {
×
NEW
71
            return `<${object.toString('hex')}>`;
×
NEW
72
        } if (object instanceof PDFAbstractReference) {
×
NEW
73
            return object.toString();
×
NEW
74
        } if (object instanceof Date) {
×
NEW
75
            let string = `D:${pad(object.getUTCFullYear(), 4)}${pad(object.getUTCMonth() + 1, 2)}${pad(object.getUTCDate(), 2)}${pad(object.getUTCHours(), 2)}${pad(object.getUTCMinutes(), 2)}${pad(object.getUTCSeconds(), 2)}Z`;
×
76

77
            // Encrypt the string when necessary
NEW
78
            if (encryptFn) {
×
NEW
79
                string = encryptFn(Buffer.from(string, 'ascii')).toString('binary');
×
80

81
                // Escape characters as required by the spec
NEW
82
                string = string.replace(escapableRe, (c) => escapable[c]);
×
83
            }
84

NEW
85
            return `(${string})`;
×
NEW
86
        } if (Array.isArray(object)) {
×
NEW
87
            const items = object.map((e) => PDFObject.convert(e, encryptFn)).join(' ');
×
NEW
88
            return `[${items}]`;
×
NEW
89
        } if ({}.toString.call(object) === '[object Object]') {
×
NEW
90
            const out = ['<<'];
×
91
            let streamData;
92

93
            // @todo this can probably be refactored into a reduce
NEW
94
            Object.entries(object).forEach(([key, val]) => {
×
NEW
95
                let checkedValue = '';
×
96

NEW
97
                if (val.toString().indexOf('<<') !== -1) {
×
NEW
98
                    checkedValue = val;
×
99
                } else {
NEW
100
                    checkedValue = PDFObject.convert(val, encryptFn);
×
101
                }
102

NEW
103
                if (key === 'stream') {
×
NEW
104
                    streamData = `${key}\n${val}\nendstream`;
×
105
                } else {
NEW
106
                    out.push(`/${key} ${checkedValue}`);
×
107
                }
108
            });
NEW
109
            out.push('>>');
×
110

NEW
111
            if (streamData) {
×
NEW
112
                out.push(streamData);
×
113
            }
NEW
114
            return out.join('\n');
×
NEW
115
        } if (typeof object === 'number') {
×
NEW
116
            return PDFObject.number(object);
×
117
        }
NEW
118
        return `${object}`;
×
119
    }
120

121
    static number(n) {
NEW
122
        if (n > -1e21 && n < 1e21) {
×
NEW
123
            return Math.round(n * 1e6) / 1e6;
×
124
        }
125

NEW
126
        throw new Error(`unsupported number: ${n}`);
×
127
    }
128
}
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