Fix File
•
/
home
/
sportsfe...
/
httpdocs
/
wp-conte...
/
plugins
/
embedpre...
/
assets
/
pdf
/
build
•
File:
pdf.worker.js
•
Content:
e = d; d = c; c = b; b = a; tmp3.assign(t1); tmp3.add(t2); a = tmp3; } h0.add(a); h1.add(b); h2.add(c); h3.add(d); h4.add(e); h5.add(f); h6.add(g); h7.add(h); } let result; if (!mode384) { result = new Uint8Array(64); h0.copyTo(result, 0); h1.copyTo(result, 8); h2.copyTo(result, 16); h3.copyTo(result, 24); h4.copyTo(result, 32); h5.copyTo(result, 40); h6.copyTo(result, 48); h7.copyTo(result, 56); } else { result = new Uint8Array(48); h0.copyTo(result, 0); h1.copyTo(result, 8); h2.copyTo(result, 16); h3.copyTo(result, 24); h4.copyTo(result, 32); h5.copyTo(result, 40); } return result; } return hash; }(); function calculateSHA384(data, offset, length) { return calculateSHA512(data, offset, length, true); } class NullCipher { decryptBlock(data) { return data; } encrypt(data) { return data; } } class AESBaseCipher { constructor() { if (this.constructor === AESBaseCipher) { unreachable("Cannot initialize AESBaseCipher."); } this._s = new Uint8Array([0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]); this._inv_s = new Uint8Array([0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]); this._mix = new Uint32Array([0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); this._mixCol = new Uint8Array(256); for (let i = 0; i < 256; i++) { this._mixCol[i] = i < 128 ? i << 1 : i << 1 ^ 0x1b; } this.buffer = new Uint8Array(16); this.bufferPosition = 0; } _expandKey(cipherKey) { unreachable("Cannot call `_expandKey` on the base class"); } _decrypt(input, key) { let t, u, v; const state = new Uint8Array(16); state.set(input); for (let j = 0, k = this._keySize; j < 16; ++j, ++k) { state[j] ^= key[k]; } for (let i = this._cyclesOfRepetition - 1; i >= 1; --i) { t = state[13]; state[13] = state[9]; state[9] = state[5]; state[5] = state[1]; state[1] = t; t = state[14]; u = state[10]; state[14] = state[6]; state[10] = state[2]; state[6] = t; state[2] = u; t = state[15]; u = state[11]; v = state[7]; state[15] = state[3]; state[11] = t; state[7] = u; state[3] = v; for (let j = 0; j < 16; ++j) { state[j] = this._inv_s[state[j]]; } for (let j = 0, k = i * 16; j < 16; ++j, ++k) { state[j] ^= key[k]; } for (let j = 0; j < 16; j += 4) { const s0 = this._mix[state[j]]; const s1 = this._mix[state[j + 1]]; const s2 = this._mix[state[j + 2]]; const s3 = this._mix[state[j + 3]]; t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8; state[j] = t >>> 24 & 0xff; state[j + 1] = t >> 16 & 0xff; state[j + 2] = t >> 8 & 0xff; state[j + 3] = t & 0xff; } } t = state[13]; state[13] = state[9]; state[9] = state[5]; state[5] = state[1]; state[1] = t; t = state[14]; u = state[10]; state[14] = state[6]; state[10] = state[2]; state[6] = t; state[2] = u; t = state[15]; u = state[11]; v = state[7]; state[15] = state[3]; state[11] = t; state[7] = u; state[3] = v; for (let j = 0; j < 16; ++j) { state[j] = this._inv_s[state[j]]; state[j] ^= key[j]; } return state; } _encrypt(input, key) { const s = this._s; let t, u, v; const state = new Uint8Array(16); state.set(input); for (let j = 0; j < 16; ++j) { state[j] ^= key[j]; } for (let i = 1; i < this._cyclesOfRepetition; i++) { for (let j = 0; j < 16; ++j) { state[j] = s[state[j]]; } v = state[1]; state[1] = state[5]; state[5] = state[9]; state[9] = state[13]; state[13] = v; v = state[2]; u = state[6]; state[2] = state[10]; state[6] = state[14]; state[10] = v; state[14] = u; v = state[3]; u = state[7]; t = state[11]; state[3] = state[15]; state[7] = v; state[11] = u; state[15] = t; for (let j = 0; j < 16; j += 4) { const s0 = state[j + 0]; const s1 = state[j + 1]; const s2 = state[j + 2]; const s3 = state[j + 3]; t = s0 ^ s1 ^ s2 ^ s3; state[j + 0] ^= t ^ this._mixCol[s0 ^ s1]; state[j + 1] ^= t ^ this._mixCol[s1 ^ s2]; state[j + 2] ^= t ^ this._mixCol[s2 ^ s3]; state[j + 3] ^= t ^ this._mixCol[s3 ^ s0]; } for (let j = 0, k = i * 16; j < 16; ++j, ++k) { state[j] ^= key[k]; } } for (let j = 0; j < 16; ++j) { state[j] = s[state[j]]; } v = state[1]; state[1] = state[5]; state[5] = state[9]; state[9] = state[13]; state[13] = v; v = state[2]; u = state[6]; state[2] = state[10]; state[6] = state[14]; state[10] = v; state[14] = u; v = state[3]; u = state[7]; t = state[11]; state[3] = state[15]; state[7] = v; state[11] = u; state[15] = t; for (let j = 0, k = this._keySize; j < 16; ++j, ++k) { state[j] ^= key[k]; } return state; } _decryptBlock2(data, finalize) { const sourceLength = data.length; let buffer = this.buffer, bufferLength = this.bufferPosition; const result = []; let iv = this.iv; for (let i = 0; i < sourceLength; ++i) { buffer[bufferLength] = data[i]; ++bufferLength; if (bufferLength < 16) { continue; } const plain = this._decrypt(buffer, this._key); for (let j = 0; j < 16; ++j) { plain[j] ^= iv[j]; } iv = buffer; result.push(plain); buffer = new Uint8Array(16); bufferLength = 0; } this.buffer = buffer; this.bufferLength = bufferLength; this.iv = iv; if (result.length === 0) { return new Uint8Array(0); } let outputLength = 16 * result.length; if (finalize) { const lastBlock = result.at(-1); let psLen = lastBlock[15]; if (psLen <= 16) { for (let i = 15, ii = 16 - psLen; i >= ii; --i) { if (lastBlock[i] !== psLen) { psLen = 0; break; } } outputLength -= psLen; result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); } } const output = new Uint8Array(outputLength); for (let i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { output.set(result[i], j); } return output; } decryptBlock(data, finalize, iv = null) { const sourceLength = data.length; const buffer = this.buffer; let bufferLength = this.bufferPosition; if (iv) { this.iv = iv; } else { for (let i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) { buffer[bufferLength] = data[i]; } if (bufferLength < 16) { this.bufferLength = bufferLength; return new Uint8Array(0); } this.iv = buffer; data = data.subarray(16); } this.buffer = new Uint8Array(16); this.bufferLength = 0; this.decryptBlock = this._decryptBlock2; return this.decryptBlock(data, finalize); } encrypt(data, iv) { const sourceLength = data.length; let buffer = this.buffer, bufferLength = this.bufferPosition; const result = []; if (!iv) { iv = new Uint8Array(16); } for (let i = 0; i < sourceLength; ++i) { buffer[bufferLength] = data[i]; ++bufferLength; if (bufferLength < 16) { continue; } for (let j = 0; j < 16; ++j) { buffer[j] ^= iv[j]; } const cipher = this._encrypt(buffer, this._key); iv = cipher; result.push(cipher); buffer = new Uint8Array(16); bufferLength = 0; } this.buffer = buffer; this.bufferLength = bufferLength; this.iv = iv; if (result.length === 0) { return new Uint8Array(0); } const outputLength = 16 * result.length; const output = new Uint8Array(outputLength); for (let i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { output.set(result[i], j); } return output; } } class AES128Cipher extends AESBaseCipher { constructor(key) { super(); this._cyclesOfRepetition = 10; this._keySize = 160; this._rcon = new Uint8Array([0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d]); this._key = this._expandKey(key); } _expandKey(cipherKey) { const b = 176; const s = this._s; const rcon = this._rcon; const result = new Uint8Array(b); result.set(cipherKey); for (let j = 16, i = 1; j < b; ++i) { let t1 = result[j - 3]; let t2 = result[j - 2]; let t3 = result[j - 1]; let t4 = result[j - 4]; t1 = s[t1]; t2 = s[t2]; t3 = s[t3]; t4 = s[t4]; t1 ^= rcon[i]; for (let n = 0; n < 4; ++n) { result[j] = t1 ^= result[j - 16]; j++; result[j] = t2 ^= result[j - 16]; j++; result[j] = t3 ^= result[j - 16]; j++; result[j] = t4 ^= result[j - 16]; j++; } } return result; } } class AES256Cipher extends AESBaseCipher { constructor(key) { super(); this._cyclesOfRepetition = 14; this._keySize = 224; this._key = this._expandKey(key); } _expandKey(cipherKey) { const b = 240; const s = this._s; const result = new Uint8Array(b); result.set(cipherKey); let r = 1; let t1, t2, t3, t4; for (let j = 32, i = 1; j < b; ++i) { if (j % 32 === 16) { t1 = s[t1]; t2 = s[t2]; t3 = s[t3]; t4 = s[t4]; } else if (j % 32 === 0) { t1 = result[j - 3]; t2 = result[j - 2]; t3 = result[j - 1]; t4 = result[j - 4]; t1 = s[t1]; t2 = s[t2]; t3 = s[t3]; t4 = s[t4]; t1 ^= r; if ((r <<= 1) >= 256) { r = (r ^ 0x1b) & 0xff; } } for (let n = 0; n < 4; ++n) { result[j] = t1 ^= result[j - 32]; j++; result[j] = t2 ^= result[j - 32]; j++; result[j] = t3 ^= result[j - 32]; j++; result[j] = t4 ^= result[j - 32]; j++; } } return result; } } class PDF17 { checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) { const hashData = new Uint8Array(password.length + 56); hashData.set(password, 0); hashData.set(ownerValidationSalt, password.length); hashData.set(userBytes, password.length + ownerValidationSalt.length); const result = calculateSHA256(hashData, 0, hashData.length); return isArrayEqual(result, ownerPassword); } checkUserPassword(password, userValidationSalt, userPassword) { const hashData = new Uint8Array(password.length + 8); hashData.set(password, 0); hashData.set(userValidationSalt, password.length); const result = calculateSHA256(hashData, 0, hashData.length); return isArrayEqual(result, userPassword); } getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) { const hashData = new Uint8Array(password.length + 56); hashData.set(password, 0); hashData.set(ownerKeySalt, password.length); hashData.set(userBytes, password.length + ownerKeySalt.length); const key = calculateSHA256(hashData, 0, hashData.length); const cipher = new AES256Cipher(key); return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16)); } getUserKey(password, userKeySalt, userEncryption) { const hashData = new Uint8Array(password.length + 8); hashData.set(password, 0); hashData.set(userKeySalt, password.length); const key = calculateSHA256(hashData, 0, hashData.length); const cipher = new AES256Cipher(key); return cipher.decryptBlock(userEncryption, false, new Uint8Array(16)); } } class PDF20 { _hash(password, input, userBytes) { let k = calculateSHA256(input, 0, input.length).subarray(0, 32); let e = [0]; let i = 0; while (i < 64 || e.at(-1) > i - 32) { const combinedLength = password.length + k.length + userBytes.length, combinedArray = new Uint8Array(combinedLength); let writeOffset = 0; combinedArray.set(password, writeOffset); writeOffset += password.length; combinedArray.set(k, writeOffset); writeOffset += k.length; combinedArray.set(userBytes, writeOffset); const k1 = new Uint8Array(combinedLength * 64); for (let j = 0, pos = 0; j < 64; j++, pos += combinedLength) { k1.set(combinedArray, pos); } const cipher = new AES128Cipher(k.subarray(0, 16)); e = cipher.encrypt(k1, k.subarray(16, 32)); const remainder = e.slice(0, 16).reduce((a, b) => a + b, 0) % 3; if (remainder === 0) { k = calculateSHA256(e, 0, e.length); } else if (remainder === 1) { k = calculateSHA384(e, 0, e.length); } else if (remainder === 2) { k = calculateSHA512(e, 0, e.length); } i++; } return k.subarray(0, 32); } checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) { const hashData = new Uint8Array(password.length + 56); hashData.set(password, 0); hashData.set(ownerValidationSalt, password.length); hashData.set(userBytes, password.length + ownerValidationSalt.length); const result = this._hash(password, hashData, userBytes); return isArrayEqual(result, ownerPassword); } checkUserPassword(password, userValidationSalt, userPassword) { const hashData = new Uint8Array(password.length + 8); hashData.set(password, 0); hashData.set(userValidationSalt, password.length); const result = this._hash(password, hashData, []); return isArrayEqual(result, userPassword); } getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) { const hashData = new Uint8Array(password.length + 56); hashData.set(password, 0); hashData.set(ownerKeySalt, password.length); hashData.set(userBytes, password.length + ownerKeySalt.length); const key = this._hash(password, hashData, userBytes); const cipher = new AES256Cipher(key); return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16)); } getUserKey(password, userKeySalt, userEncryption) { const hashData = new Uint8Array(password.length + 8); hashData.set(password, 0); hashData.set(userKeySalt, password.length); const key = this._hash(password, hashData, []); const cipher = new AES256Cipher(key); return cipher.decryptBlock(userEncryption, false, new Uint8Array(16)); } } class CipherTransform { constructor(stringCipherConstructor, streamCipherConstructor) { this.StringCipherConstructor = stringCipherConstructor; this.StreamCipherConstructor = streamCipherConstructor; } createStream(stream, length) { const cipher = new this.StreamCipherConstructor(); return new DecryptStream(stream, length, function cipherTransformDecryptStream(data, finalize) { return cipher.decryptBlock(data, finalize); }); } decryptString(s) { const cipher = new this.StringCipherConstructor(); let data = stringToBytes(s); data = cipher.decryptBlock(data, true); return bytesToString(data); } encryptString(s) { const cipher = new this.StringCipherConstructor(); if (cipher instanceof AESBaseCipher) { const strLen = s.length; const pad = 16 - strLen % 16; s += String.fromCharCode(pad).repeat(pad); const iv = new Uint8Array(16); if (typeof crypto !== "undefined") { crypto.getRandomValues(iv); } else { for (let i = 0; i < 16; i++) { iv[i] = Math.floor(256 * Math.random()); } } let data = stringToBytes(s); data = cipher.encrypt(data, iv); const buf = new Uint8Array(16 + data.length); buf.set(iv); buf.set(data, 16); return bytesToString(buf); } let data = stringToBytes(s); data = cipher.encrypt(data); return bytesToString(data); } } class CipherTransformFactory { static #defaultPasswordBytes = new Uint8Array([0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a]); #createEncryptionKey20(revision, password, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms) { if (password) { const passwordLength = Math.min(127, password.length); password = password.subarray(0, passwordLength); } else { password = []; } const pdfAlgorithm = revision === 6 ? new PDF20() : new PDF17(); if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, userPassword)) { return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption); } else if (password.length && pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, uBytes, ownerPassword)) { return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption); } return null; } #prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) { const hashDataSize = 40 + ownerPassword.length + fileId.length; const hashData = new Uint8Array(hashDataSize); let i = 0, j, n; if (password) { n = Math.min(32, password.length); for (; i < n; ++i) { hashData[i] = password[i]; } } j = 0; while (i < 32) { hashData[i++] = CipherTransformFactory.#defaultPasswordBytes[j++]; } for (j = 0, n = ownerPassword.length; j < n; ++j) { hashData[i++] = ownerPassword[j]; } hashData[i++] = flags & 0xff; hashData[i++] = flags >> 8 & 0xff; hashData[i++] = flags >> 16 & 0xff; hashData[i++] = flags >>> 24 & 0xff; for (j = 0, n = fileId.length; j < n; ++j) { hashData[i++] = fileId[j]; } if (revision >= 4 && !encryptMetadata) { hashData[i++] = 0xff; hashData[i++] = 0xff; hashData[i++] = 0xff; hashData[i++] = 0xff; } let hash = calculateMD5(hashData, 0, i); const keyLengthInBytes = keyLength >> 3; if (revision >= 3) { for (j = 0; j < 50; ++j) { hash = calculateMD5(hash, 0, keyLengthInBytes); } } const encryptionKey = hash.subarray(0, keyLengthInBytes); let cipher, checkData; if (revision >= 3) { for (i = 0; i < 32; ++i) { hashData[i] = CipherTransformFactory.#defaultPasswordBytes[i]; } for (j = 0, n = fileId.length; j < n; ++j) { hashData[i++] = fileId[j]; } cipher = new ARCFourCipher(encryptionKey); checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i)); n = encryptionKey.length; const derivedKey = new Uint8Array(n); for (j = 1; j <= 19; ++j) { for (let k = 0; k < n; ++k) { derivedKey[k] = encryptionKey[k] ^ j; } cipher = new ARCFourCipher(derivedKey); checkData = cipher.encryptBlock(checkData); } for (j = 0, n = checkData.length; j < n; ++j) { if (userPassword[j] !== checkData[j]) { return null; } } } else { cipher = new ARCFourCipher(encryptionKey); checkData = cipher.encryptBlock(CipherTransformFactory.#defaultPasswordBytes); for (j = 0, n = checkData.length; j < n; ++j) { if (userPassword[j] !== checkData[j]) { return null; } } } return encryptionKey; } #decodeUserPassword(password, ownerPassword, revision, keyLength) { const hashData = new Uint8Array(32); let i = 0; const n = Math.min(32, password.length); for (; i < n; ++i) { hashData[i] = password[i]; } let j = 0; while (i < 32) { hashData[i++] = CipherTransformFactory.#defaultPasswordBytes[j++]; } let hash = calculateMD5(hashData, 0, i); const keyLengthInBytes = keyLength >> 3; if (revision >= 3) { for (j = 0; j < 50; ++j) { hash = calculateMD5(hash, 0, hash.length); } } let cipher, userPassword; if (revision >= 3) { userPassword = ownerPassword; const derivedKey = new Uint8Array(keyLengthInBytes); for (j = 19; j >= 0; j--) { for (let k = 0; k < keyLengthInBytes; ++k) { derivedKey[k] = hash[k] ^ j; } cipher = new ARCFourCipher(derivedKey); userPassword = cipher.encryptBlock(userPassword); } } else { cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes)); userPassword = cipher.encryptBlock(ownerPassword); } return userPassword; } #buildObjectKey(num, gen, encryptionKey, isAes = false) { const key = new Uint8Array(encryptionKey.length + 9); const n = encryptionKey.length; let i; for (i = 0; i < n; ++i) { key[i] = encryptionKey[i]; } key[i++] = num & 0xff; key[i++] = num >> 8 & 0xff; key[i++] = num >> 16 & 0xff; key[i++] = gen & 0xff; key[i++] = gen >> 8 & 0xff; if (isAes) { key[i++] = 0x73; key[i++] = 0x41; key[i++] = 0x6c; key[i++] = 0x54; } const hash = calculateMD5(key, 0, i); return hash.subarray(0, Math.min(encryptionKey.length + 5, 16)); } #buildCipherConstructor(cf, name, num, gen, key) { if (!(name instanceof Name)) { throw new FormatError("Invalid crypt filter name."); } const self = this; const cryptFilter = cf.get(name.name); const cfm = cryptFilter?.get("CFM"); if (!cfm || cfm.name === "None") { return function () { return new NullCipher(); }; } if (cfm.name === "V2") { return function () { return new ARCFourCipher(self.#buildObjectKey(num, gen, key, false)); }; } if (cfm.name === "AESV2") { return function () { return new AES128Cipher(self.#buildObjectKey(num, gen, key, true)); }; } if (cfm.name === "AESV3") { return function () { return new AES256Cipher(key); }; } throw new FormatError("Unknown crypto method"); } constructor(dict, fileId, password) { const filter = dict.get("Filter"); if (!isName(filter, "Standard")) { throw new FormatError("unknown encryption method"); } this.filterName = filter.name; this.dict = dict; const algorithm = dict.get("V"); if (!Number.isInteger(algorithm) || algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5) { throw new FormatError("unsupported encryption algorithm"); } this.algorithm = algorithm; let keyLength = dict.get("Length"); if (!keyLength) { if (algorithm <= 3) { keyLength = 40; } else { const cfDict = dict.get("CF"); const streamCryptoName = dict.get("StmF"); if (cfDict instanceof Dict && streamCryptoName instanceof Name) { cfDict.suppressEncryption = true; const handlerDict = cfDict.get(streamCryptoName.name); keyLength = handlerDict?.get("Length") || 128; if (keyLength < 40) { keyLength <<= 3; } } } } if (!Number.isInteger(keyLength) || keyLength < 40 || keyLength % 8 !== 0) { throw new FormatError("invalid key length"); } const ownerBytes = stringToBytes(dict.get("O")), userBytes = stringToBytes(dict.get("U")); const ownerPassword = ownerBytes.subarray(0, 32); const userPassword = userBytes.subarray(0, 32); const flags = dict.get("P"); const revision = dict.get("R"); const encryptMetadata = (algorithm === 4 || algorithm === 5) && dict.get("EncryptMetadata") !== false; this.encryptMetadata = encryptMetadata; const fileIdBytes = stringToBytes(fileId); let passwordBytes; if (password) { if (revision === 6) { try { password = utf8StringToString(password); } catch { warn("CipherTransformFactory: Unable to convert UTF8 encoded password."); } } passwordBytes = stringToBytes(password); } let encryptionKey; if (algorithm !== 5) { encryptionKey = this.#prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata); } else { const ownerValidationSalt = ownerBytes.subarray(32, 40); const ownerKeySalt = ownerBytes.subarray(40, 48); const uBytes = userBytes.subarray(0, 48); const userValidationSalt = userBytes.subarray(32, 40); const userKeySalt = userBytes.subarray(40, 48); const ownerEncryption = stringToBytes(dict.get("OE")); const userEncryption = stringToBytes(dict.get("UE")); const perms = stringToBytes(dict.get("Perms")); encryptionKey = this.#createEncryptionKey20(revision, passwordBytes, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms); } if (!encryptionKey && !password) { throw new PasswordException("No password given", PasswordResponses.NEED_PASSWORD); } else if (!encryptionKey && password) { const decodedPassword = this.#decodeUserPassword(passwordBytes, ownerPassword, revision, keyLength); encryptionKey = this.#prepareKeyData(fileIdBytes, decodedPassword, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata); } if (!encryptionKey) { throw new PasswordException("Incorrect Password", PasswordResponses.INCORRECT_PASSWORD); } this.encryptionKey = encryptionKey; if (algorithm >= 4) { const cf = dict.get("CF"); if (cf instanceof Dict) { cf.suppressEncryption = true; } this.cf = cf; this.stmf = dict.get("StmF") || Name.get("Identity"); this.strf = dict.get("StrF") || Name.get("Identity"); this.eff = dict.get("EFF") || this.stmf; } } createCipherTransform(num, gen) { if (this.algorithm === 4 || this.algorithm === 5) { return new CipherTransform(this.#buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey), this.#buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey)); } const key = this.#buildObjectKey(num, gen, this.encryptionKey, false); const cipherConstructor = function () { return new ARCFourCipher(key); }; return new CipherTransform(cipherConstructor, cipherConstructor); } } ;// CONCATENATED MODULE: ./src/core/writer.js async function writeObject(ref, obj, buffer, { encrypt = null }) { const transform = encrypt?.createCipherTransform(ref.num, ref.gen); buffer.push(`${ref.num} ${ref.gen} obj\n`); if (obj instanceof Dict) { await writeDict(obj, buffer, transform); } else if (obj instanceof BaseStream) { await writeStream(obj, buffer, transform); } else if (Array.isArray(obj) || ArrayBuffer.isView(obj)) { await writeArray(obj, buffer, transform); } buffer.push("\nendobj\n"); } async function writeDict(dict, buffer, transform) { buffer.push("<<"); for (const key of dict.getKeys()) { buffer.push(` /${escapePDFName(key)} `); await writeValue(dict.getRaw(key), buffer, transform); } buffer.push(">>"); } async function writeStream(stream, buffer, transform) { let bytes = stream.getBytes(); const { dict } = stream; const [filter, params] = await Promise.all([dict.getAsync("Filter"), dict.getAsync("DecodeParms")]); const filterZero = Array.isArray(filter) ? await dict.xref.fetchIfRefAsync(filter[0]) : filter; const isFilterZeroFlateDecode = isName(filterZero, "FlateDecode"); const MIN_LENGTH_FOR_COMPRESSING = 256; if (bytes.length >= MIN_LENGTH_FOR_COMPRESSING || isFilterZeroFlateDecode) { try { const cs = new CompressionStream("deflate"); const writer = cs.writable.getWriter(); writer.write(bytes); writer.close(); const buf = await new Response(cs.readable).arrayBuffer(); bytes = new Uint8Array(buf); let newFilter, newParams; if (!filter) { newFilter = Name.get("FlateDecode"); } else if (!isFilterZeroFlateDecode) { newFilter = Array.isArray(filter) ? [Name.get("FlateDecode"), ...filter] : [Name.get("FlateDecode"), filter]; if (params) { newParams = Array.isArray(params) ? [null, ...params] : [null, params]; } } if (newFilter) { dict.set("Filter", newFilter); } if (newParams) { dict.set("DecodeParms", newParams); } } catch (ex) { info(`writeStream - cannot compress data: "${ex}".`); } } let string = bytesToString(bytes); if (transform) { string = transform.encryptString(string); } dict.set("Length", string.length); await writeDict(dict, buffer, transform); buffer.push(" stream\n", string, "\nendstream"); } async function writeArray(array, buffer, transform) { buffer.push("["); let first = true; for (const val of array) { if (!first) { buffer.push(" "); } else { first = false; } await writeValue(val, buffer, transform); } buffer.push("]"); } async function writeValue(value, buffer, transform) { if (value instanceof Name) { buffer.push(`/${escapePDFName(value.name)}`); } else if (value instanceof Ref) { buffer.push(`${value.num} ${value.gen} R`); } else if (Array.isArray(value) || ArrayBuffer.isView(value)) { await writeArray(value, buffer, transform); } else if (typeof value === "string") { if (transform) { value = transform.encryptString(value); } buffer.push(`(${escapeString(value)})`); } else if (typeof value === "number") { buffer.push(numberToString(value)); } else if (typeof value === "boolean") { buffer.push(value.toString()); } else if (value instanceof Dict) { await writeDict(value, buffer, transform); } else if (value instanceof BaseStream) { await writeStream(value, buffer, transform); } else if (value === null) { buffer.push("null"); } else { warn(`Unhandled value in writer: ${typeof value}, please file a bug.`); } } function writeInt(number, size, offset, buffer) { for (let i = size + offset - 1; i > offset - 1; i--) { buffer[i] = number & 0xff; number >>= 8; } return offset + size; } function writeString(string, offset, buffer) { for (let i = 0, len = string.length; i < len; i++) { buffer[offset + i] = string.charCodeAt(i) & 0xff; } } function computeMD5(filesize, xrefInfo) { const time = Math.floor(Date.now() / 1000); const filename = xrefInfo.filename || ""; const md5Buffer = [time.toString(), filename, filesize.toString()]; let md5BufferLen = md5Buffer.reduce((a, str) => a + str.length, 0); for (const value of Object.values(xrefInfo.info)) { md5Buffer.push(value); md5BufferLen += value.length; } const array = new Uint8Array(md5BufferLen); let offset = 0; for (const str of md5Buffer) { writeString(str, offset, array); offset += str.length; } return bytesToString(calculateMD5(array)); } function writeXFADataForAcroform(str, newRefs) { const xml = new SimpleXMLParser({ hasAttributes: true }).parseFromString(str); for (const { xfa } of newRefs) { if (!xfa) { continue; } const { path, value } = xfa; if (!path) { continue; } const nodePath = parseXFAPath(path); let node = xml.documentElement.searchNode(nodePath, 0); if (!node && nodePath.length > 1) { node = xml.documentElement.searchNode([nodePath.at(-1)], 0); } if (node) { node.childNodes = Array.isArray(value) ? value.map(val => new SimpleDOMNode("value", val)) : [new SimpleDOMNode("#text", value)]; } else { warn(`Node not found for path: ${path}`); } } const buffer = []; xml.documentElement.dump(buffer); return buffer.join(""); } async function updateAcroform({ xref, acroForm, acroFormRef, hasXfa, hasXfaDatasetsEntry, xfaDatasetsRef, needAppearances, newRefs }) { if (hasXfa && !hasXfaDatasetsEntry && !xfaDatasetsRef) { warn("XFA - Cannot save it"); } if (!needAppearances && (!hasXfa || !xfaDatasetsRef || hasXfaDatasetsEntry)) { return; } const dict = acroForm.clone(); if (hasXfa && !hasXfaDatasetsEntry) { const newXfa = acroForm.get("XFA").slice(); newXfa.splice(2, 0, "datasets"); newXfa.splice(3, 0, xfaDatasetsRef); dict.set("XFA", newXfa); } if (needAppearances) { dict.set("NeedAppearances", true); } const buffer = []; await writeObject(acroFormRef, dict, buffer, xref); newRefs.push({ ref: acroFormRef, data: buffer.join("") }); } function updateXFA({ xfaData, xfaDatasetsRef, newRefs, xref }) { if (xfaData === null) { const datasets = xref.fetchIfRef(xfaDatasetsRef); xfaData = writeXFADataForAcroform(datasets.getString(), newRefs); } const encrypt = xref.encrypt; if (encrypt) { const transform = encrypt.createCipherTransform(xfaDatasetsRef.num, xfaDatasetsRef.gen); xfaData = transform.encryptString(xfaData); } const data = `${xfaDatasetsRef.num} ${xfaDatasetsRef.gen} obj\n` + `<< /Type /EmbeddedFile /Length ${xfaData.length}>>\nstream\n` + xfaData + "\nendstream\nendobj\n"; newRefs.push({ ref: xfaDatasetsRef, data }); } async function getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer) { buffer.push("xref\n"); const indexes = getIndexes(newRefs); let indexesPosition = 0; for (const { ref, data } of newRefs) { if (ref.num === indexes[indexesPosition]) { buffer.push(`${indexes[indexesPosition]} ${indexes[indexesPosition + 1]}\n`); indexesPosition += 2; } if (data !== null) { buffer.push(`${baseOffset.toString().padStart(10, "0")} ${Math.min(ref.gen, 0xffff).toString().padStart(5, "0")} n\r\n`); baseOffset += data.length; } else { buffer.push(`0000000000 ${Math.min(ref.gen + 1, 0xffff).toString().padStart(5, "0")} f\r\n`); } } computeIDs(baseOffset, xrefInfo, newXref); buffer.push("trailer\n"); await writeDict(newXref, buffer); buffer.push("\nstartxref\n", baseOffset.toString(), "\n%%EOF\n"); } function getIndexes(newRefs) { const indexes = []; for (const { ref } of newRefs) { if (ref.num === indexes.at(-2) + indexes.at(-1)) { indexes[indexes.length - 1] += 1; } else { indexes.push(ref.num, 1); } } return indexes; } async function getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer) { const xrefTableData = []; let maxOffset = 0; let maxGen = 0; for (const { ref, data } of newRefs) { let gen; maxOffset = Math.max(maxOffset, baseOffset); if (data !== null) { gen = Math.min(ref.gen, 0xffff); xrefTableData.push([1, baseOffset, gen]); baseOffset += data.length; } else { gen = Math.min(ref.gen + 1, 0xffff); xrefTableData.push([0, 0, gen]); } maxGen = Math.max(maxGen, gen); } newXref.set("Index", getIndexes(newRefs)); const offsetSize = getSizeInBytes(maxOffset); const maxGenSize = getSizeInBytes(maxGen); const sizes = [1, offsetSize, maxGenSize]; newXref.set("W", sizes); computeIDs(baseOffset, xrefInfo, newXref); const structSize = sizes.reduce((a, x) => a + x, 0); const data = new Uint8Array(structSize * xrefTableData.length); const stream = new Stream(data); stream.dict = newXref; let offset = 0; for (const [type, objOffset, gen] of xrefTableData) { offset = writeInt(type, sizes[0], offset, data); offset = writeInt(objOffset, sizes[1], offset, data); offset = writeInt(gen, sizes[2], offset, data); } await writeObject(xrefInfo.newRef, stream, buffer, {}); buffer.push("startxref\n", baseOffset.toString(), "\n%%EOF\n"); } function computeIDs(baseOffset, xrefInfo, newXref) { if (Array.isArray(xrefInfo.fileIds) && xrefInfo.fileIds.length > 0) { const md5 = computeMD5(baseOffset, xrefInfo); newXref.set("ID", [xrefInfo.fileIds[0], md5]); } } function getTrailerDict(xrefInfo, newRefs, useXrefStream) { const newXref = new Dict(null); newXref.set("Prev", xrefInfo.startXRef); const refForXrefTable = xrefInfo.newRef; if (useXrefStream) { newRefs.push({ ref: refForXrefTable, data: "" }); newXref.set("Size", refForXrefTable.num + 1); newXref.set("Type", Name.get("XRef")); } else { newXref.set("Size", refForXrefTable.num); } if (xrefInfo.rootRef !== null) { newXref.set("Root", xrefInfo.rootRef); } if (xrefInfo.infoRef !== null) { newXref.set("Info", xrefInfo.infoRef); } if (xrefInfo.encryptRef !== null) { newXref.set("Encrypt", xrefInfo.encryptRef); } return newXref; } async function incrementalUpdate({ originalData, xrefInfo, newRefs, xref = null, hasXfa = false, xfaDatasetsRef = null, hasXfaDatasetsEntry = false, needAppearances, acroFormRef = null, acroForm = null, xfaData = null, useXrefStream = false }) { await updateAcroform({ xref, acroForm, acroFormRef, hasXfa, hasXfaDatasetsEntry, xfaDatasetsRef, needAppearances, newRefs }); if (hasXfa) { updateXFA({ xfaData, xfaDatasetsRef, newRefs, xref }); } const buffer = []; let baseOffset = originalData.length; const lastByte = originalData.at(-1); if (lastByte !== 0x0a && lastByte !== 0x0d) { buffer.push("\n"); baseOffset += 1; } const newXref = getTrailerDict(xrefInfo, newRefs, useXrefStream); newRefs = newRefs.sort((a, b) => a.ref.num - b.ref.num); for (const { data } of newRefs) { if (data !== null) { buffer.push(data); } } await (useXrefStream ? getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer) : getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer)); const totalLength = buffer.reduce((a, str) => a + str.length, originalData.length); const array = new Uint8Array(totalLength); array.set(originalData); let offset = originalData.length; for (const str of buffer) { writeString(str, offset, array); offset += str.length; } return array; } ;// CONCATENATED MODULE: ./src/core/struct_tree.js const MAX_DEPTH = 40; const StructElementType = { PAGE_CONTENT: 1, STREAM_CONTENT: 2, OBJECT: 3, ANNOTATION: 4, ELEMENT: 5 }; class StructTreeRoot { constructor(rootDict, rootRef) { this.dict = rootDict; this.ref = rootRef instanceof Ref ? rootRef : null; this.roleMap = new Map(); this.structParentIds = null; } init() { this.readRoleMap(); } #addIdToPage(pageRef, id, type) { if (!(pageRef instanceof Ref) || id < 0) { return; } this.structParentIds ||= new RefSetCache(); let ids = this.structParentIds.get(pageRef); if (!ids) { ids = []; this.structParentIds.put(pageRef, ids); } ids.push([id, type]); } addAnnotationIdToPage(pageRef, id) { this.#addIdToPage(pageRef, id, StructElementType.ANNOTATION); } readRoleMap() { const roleMapDict = this.dict.get("RoleMap"); if (!(roleMapDict instanceof Dict)) { return; } roleMapDict.forEach((key, value) => { if (!(value instanceof Name)) { return; } this.roleMap.set(key, value.name); }); } static async canCreateStructureTree({ catalogRef, pdfManager, newAnnotationsByPage }) { if (!(catalogRef instanceof Ref)) { warn("Cannot save the struct tree: no catalog reference."); return false; } let nextKey = 0; let hasNothingToUpdate = true; for (const [pageIndex, elements] of newAnnotationsByPage) { const { ref: pageRef } = await pdfManager.getPage(pageIndex); if (!(pageRef instanceof Ref)) { warn(`Cannot save the struct tree: page ${pageIndex} has no ref.`); hasNothingToUpdate = true; break; } for (const element of elements) { if (element.accessibilityData?.type) { element.parentTreeId = nextKey++; hasNothingToUpdate = false; } } } if (hasNothingToUpdate) { for (const elements of newAnnotationsByPage.values()) { for (const element of elements) { delete element.parentTreeId; } } return false; } return true; } static async createStructureTree({ newAnnotationsByPage, xref, catalogRef, pdfManager, newRefs }) { const root = pdfManager.catalog.cloneDict(); const cache = new RefSetCache(); cache.put(catalogRef, root); const structTreeRootRef = xref.getNewTemporaryRef(); root.set("StructTreeRoot", structTreeRootRef); const structTreeRoot = new Dict(xref); structTreeRoot.set("Type", Name.get("StructTreeRoot")); const parentTreeRef = xref.getNewTemporaryRef(); structTreeRoot.set("ParentTree", parentTreeRef); const kids = []; structTreeRoot.set("K", kids); cache.put(structTreeRootRef, structTreeRoot); const parentTree = new Dict(xref); const nums = []; parentTree.set("Nums", nums); const nextKey = await this.#writeKids({ newAnnotationsByPage, structTreeRootRef, kids, nums, xref, pdfManager, cache }); structTreeRoot.set("ParentTreeNextKey", nextKey); cache.put(parentTreeRef, parentTree); const buffer = []; for (const [ref, obj] of cache.items()) { buffer.length = 0; await writeObject(ref, obj, buffer, xref); newRefs.push({ ref, data: buffer.join("") }); } } async canUpdateStructTree({ pdfManager, xref, newAnnotationsByPage }) { if (!this.ref) { warn("Cannot update the struct tree: no root reference."); return false; } let nextKey = this.dict.get("ParentTreeNextKey"); if (!Number.isInteger(nextKey) || nextKey < 0) { warn("Cannot update the struct tree: invalid next key."); return false; } const parentTree = this.dict.get("ParentTree"); if (!(parentTree instanceof Dict)) { warn("Cannot update the struct tree: ParentTree isn't a dict."); return false; } const nums = parentTree.get("Nums"); if (!Array.isArray(nums)) { warn("Cannot update the struct tree: nums isn't an array."); return false; } const numberTree = new NumberTree(parentTree, xref); for (const pageIndex of newAnnotationsByPage.keys()) { const { pageDict } = await pdfManager.getPage(pageIndex); if (!pageDict.has("StructParents")) { continue; } const id = pageDict.get("StructParents"); if (!Number.isInteger(id) || !Array.isArray(numberTree.get(id))) { warn(`Cannot save the struct tree: page ${pageIndex} has a wrong id.`); return false; } } let hasNothingToUpdate = true; for (const [pageIndex, elements] of newAnnotationsByPage) { const { pageDict } = await pdfManager.getPage(pageIndex); StructTreeRoot.#collectParents({ elements, xref: this.dict.xref, pageDict, numberTree }); for (const element of elements) { if (element.accessibilityData?.type) { element.parentTreeId = nextKey++; hasNothingToUpdate = false; } } } if (hasNothingToUpdate) { for (const elements of newAnnotationsByPage.values()) { for (const element of elements) { delete element.parentTreeId; delete element.structTreeParent; } } return false; } return true; } async updateStructureTree({ newAnnotationsByPage, pdfManager, newRefs }) { const xref = this.dict.xref; const structTreeRoot = this.dict.clone(); const structTreeRootRef = this.ref; const cache = new RefSetCache(); cache.put(structTreeRootRef, structTreeRoot); let parentTreeRef = structTreeRoot.getRaw("ParentTree"); let parentTree; if (parentTreeRef instanceof Ref) { parentTree = xref.fetch(parentTreeRef); } else { parentTree = parentTreeRef; parentTreeRef = xref.getNewTemporaryRef(); structTreeRoot.set("ParentTree", parentTreeRef); } parentTree = parentTree.clone(); cache.put(parentTreeRef, parentTree); let nums = parentTree.getRaw("Nums"); let numsRef = null; if (nums instanceof Ref) { numsRef = nums; nums = xref.fetch(numsRef); } nums = nums.slice(); if (!numsRef) { parentTree.set("Nums", nums); } const newNextkey = await StructTreeRoot.#writeKids({ newAnnotationsByPage, structTreeRootRef, kids: null, nums, xref, pdfManager, cache }); structTreeRoot.set("ParentTreeNextKey", newNextkey); if (numsRef) { cache.put(numsRef, nums); } const buffer = []; for (const [ref, obj] of cache.items()) { buffer.length = 0; await writeObject(ref, obj, buffer, xref); newRefs.push({ ref, data: buffer.join("") }); } } static async #writeKids({ newAnnotationsByPage, structTreeRootRef, kids, nums, xref, pdfManager, cache }) { const objr = Name.get("OBJR"); let nextKey = -Infinity; for (const [pageIndex, elements] of newAnnotationsByPage) { const { ref: pageRef } = await pdfManager.getPage(pageIndex); const isPageRef = pageRef instanceof Ref; for (const { accessibilityData, ref, parentTreeId, structTreeParent } of elements) { if (!accessibilityData?.type) { continue; } const { type, title, lang, alt, expanded, actualText } = accessibilityData; nextKey = Math.max(nextKey, parentTreeId); const tagRef = xref.getNewTemporaryRef(); const tagDict = new Dict(xref); tagDict.set("S", Name.get(type)); if (title) { tagDict.set("T", title); } if (lang) { tagDict.set("Lang", lang); } if (alt) { tagDict.set("Alt", alt); } if (expanded) { tagDict.set("E", expanded); } if (actualText) { tagDict.set("ActualText", actualText); } await this.#updateParentTag({ structTreeParent, tagDict, newTagRef: tagRef, structTreeRootRef, fallbackKids: kids, xref, cache }); const objDict = new Dict(xref); tagDict.set("K", objDict); objDict.set("Type", objr); if (isPageRef) { objDict.set("Pg", pageRef); } objDict.set("Obj", ref); cache.put(tagRef, tagDict); nums.push(parentTreeId, tagRef); } } return nextKey + 1; } static #collectParents({ elements, xref, pageDict, numberTree }) { const idToElements = new Map(); for (const element of elements) { if (element.structTreeParentId) { const id = parseInt(element.structTreeParentId.split("_mc")[1], 10); let elems = idToElements.get(id); if (!elems) { elems = []; idToElements.set(id, elems); } elems.push(element); } } const id = pageDict.get("StructParents"); if (!Number.isInteger(id)) { return; } const parentArray = numberTree.get(id); const updateElement = (kid, pageKid, kidRef) => { const elems = idToElements.get(kid); if (elems) { const parentRef = pageKid.getRaw("P"); const parentDict = xref.fetchIfRef(parentRef); if (parentRef instanceof Ref && parentDict instanceof Dict) { const params = { ref: kidRef, dict: pageKid }; for (const element of elems) { element.structTreeParent = params; } } return true; } return false; }; for (const kidRef of parentArray) { if (!(kidRef instanceof Ref)) { continue; } const pageKid = xref.fetch(kidRef); const k = pageKid.get("K"); if (Number.isInteger(k)) { updateElement(k, pageKid, kidRef); continue; } if (!Array.isArray(k)) { continue; } for (let kid of k) { kid = xref.fetchIfRef(kid); if (Number.isInteger(kid) && updateElement(kid, pageKid, kidRef)) { break; } if (!(kid instanceof Dict)) { continue; } if (!isName(kid.get("Type"), "MCR")) { break; } const mcid = kid.get("MCID"); if (Number.isInteger(mcid) && updateElement(mcid, pageKid, kidRef)) { break; } } } } static async #updateParentTag({ structTreeParent, tagDict, newTagRef, structTreeRootRef, fallbackKids, xref, cache }) { let ref = null; let parentRef; if (structTreeParent) { ({ ref } = structTreeParent); parentRef = structTreeParent.dict.getRaw("P") || structTreeRootRef; } else { parentRef = structTreeRootRef; } tagDict.set("P", parentRef); const parentDict = xref.fetchIfRef(parentRef); if (!parentDict) { fallbackKids.push(newTagRef); return; } let cachedParentDict = cache.get(parentRef); if (!cachedParentDict) { cachedParentDict = parentDict.clone(); cache.put(parentRef, cachedParentDict); } const parentKidsRaw = cachedParentDict.getRaw("K"); let cachedParentKids = parentKidsRaw instanceof Ref ? cache.get(parentKidsRaw) : null; if (!cachedParentKids) { cachedParentKids = xref.fetchIfRef(parentKidsRaw); cachedParentKids = Array.isArray(cachedParentKids) ? cachedParentKids.slice() : [parentKidsRaw]; const parentKidsRef = xref.getNewTemporaryRef(); cachedParentDict.set("K", parentKidsRef); cache.put(parentKidsRef, cachedParentKids); } const index = cachedParentKids.indexOf(ref); cachedParentKids.splice(index >= 0 ? index + 1 : cachedParentKids.length, 0, newTagRef); } } class StructElementNode { constructor(tree, dict) { this.tree = tree; this.dict = dict; this.kids = []; this.parseKids(); } get role() { const nameObj = this.dict.get("S"); const name = nameObj instanceof Name ? nameObj.name : ""; const { root } = this.tree; if (root.roleMap.has(name)) { return root.roleMap.get(name); } return name; } parseKids() { let pageObjId = null; const objRef = this.dict.getRaw("Pg"); if (objRef instanceof Ref) { pageObjId = objRef.toString(); } const kids = this.dict.get("K"); if (Array.isArray(kids)) { for (const kid of kids) { const element = this.parseKid(pageObjId, kid); if (element) { this.kids.push(element); } } } else { const element = this.parseKid(pageObjId, kids); if (element) { this.kids.push(element); } } } parseKid(pageObjId, kid) { if (Number.isInteger(kid)) { if (this.tree.pageDict.objId !== pageObjId) { return null; } return new StructElement({ type: StructElementType.PAGE_CONTENT, mcid: kid, pageObjId }); } let kidDict = null; if (kid instanceof Ref) { kidDict = this.dict.xref.fetch(kid); } else if (kid instanceof Dict) { kidDict = kid; } if (!kidDict) { return null; } const pageRef = kidDict.getRaw("Pg"); if (pageRef instanceof Ref) { pageObjId = pageRef.toString(); } const type = kidDict.get("Type") instanceof Name ? kidDict.get("Type").name : null; if (type === "MCR") { if (this.tree.pageDict.objId !== pageObjId) { return null; } const kidRef = kidDict.getRaw("Stm"); return new StructElement({ type: StructElementType.STREAM_CONTENT, refObjId: kidRef instanceof Ref ? kidRef.toString() : null, pageObjId, mcid: kidDict.get("MCID") }); } if (type === "OBJR") { if (this.tree.pageDict.objId !== pageObjId) { return null; } const kidRef = kidDict.getRaw("Obj"); return new StructElement({ type: StructElementType.OBJECT, refObjId: kidRef instanceof Ref ? kidRef.toString() : null, pageObjId }); } return new StructElement({ type: StructElementType.ELEMENT, dict: kidDict }); } } class StructElement { constructor({ type, dict = null, mcid = null, pageObjId = null, refObjId = null }) { this.type = type; this.dict = dict; this.mcid = mcid; this.pageObjId = pageObjId; this.refObjId = refObjId; this.parentNode = null; } } class StructTreePage { constructor(structTreeRoot, pageDict) { this.root = structTreeRoot; this.rootDict = structTreeRoot ? structTreeRoot.dict : null; this.pageDict = pageDict; this.nodes = []; } parse(pageRef) { if (!this.root || !this.rootDict) { return; } const parentTree = this.rootDict.get("ParentTree"); if (!parentTree) { return; } const id = this.pageDict.get("StructParents"); const ids = pageRef instanceof Ref && this.root.structParentIds?.get(pageRef); if (!Number.isInteger(id) && !ids) { return; } const map = new Map(); const numberTree = new NumberTree(parentTree, this.rootDict.xref); if (Number.isInteger(id)) { const parentArray = numberTree.get(id); if (Array.isArray(parentArray)) { for (const ref of parentArray) { if (ref instanceof Ref) { this.addNode(this.rootDict.xref.fetch(ref), map); } } } } if (!ids) { return; } for (const [elemId, type] of ids) { const obj = numberTree.get(elemId); if (obj) { const elem = this.addNode(this.rootDict.xref.fetchIfRef(obj), map); if (elem?.kids?.length === 1 && elem.kids[0].type === StructElementType.OBJECT) { elem.kids[0].type = type; } } } } addNode(dict, map, level = 0) { if (level > MAX_DEPTH) { warn("StructTree MAX_DEPTH reached."); return null; } if (map.has(dict)) { return map.get(dict); } const element = new StructElementNode(this, dict); map.set(dict, element); const parent = dict.get("P"); if (!parent || isName(parent.get("Type"), "StructTreeRoot")) { if (!this.addTopLevelNode(dict, element)) { map.delete(dict); } return element; } const parentNode = this.addNode(parent, map, level + 1); if (!parentNode) { return element; } let save = false; for (const kid of parentNode.kids) { if (kid.type === StructElementType.ELEMENT && kid.dict === dict) { kid.parentNode = element; save = true; } } if (!save) { map.delete(dict); } return element; } addTopLevelNode(dict, element) { const obj = this.rootDict.get("K"); if (!obj) { return false; } if (obj instanceof Dict) { if (obj.objId !== dict.objId) { return false; } this.nodes[0] = element; return true; } if (!Array.isArray(obj)) { return true; } let save = false; for (let i = 0; i < obj.length; i++) { const kidRef = obj[i]; if (kidRef?.toString() === dict.objId) { this.nodes[i] = element; save = true; } } return save; } get serializable() { function nodeToSerializable(node, parent, level = 0) { if (level > MAX_DEPTH) { warn("StructTree too deep to be fully serialized."); return; } const obj = Object.create(null); obj.role = node.role; obj.children = []; parent.children.push(obj); const alt = node.dict.get("Alt"); if (typeof alt === "string") { obj.alt = stringToPDFString(alt); } const lang = node.dict.get("Lang"); if (typeof lang === "string") { obj.lang = stringToPDFString(lang); } for (const kid of node.kids) { const kidElement = kid.type === StructElementType.ELEMENT ? kid.parentNode : null; if (kidElement) { nodeToSerializable(kidElement, obj, level + 1); continue; } else if (kid.type === StructElementType.PAGE_CONTENT || kid.type === StructElementType.STREAM_CONTENT) { obj.children.push({ type: "content", id: `p${kid.pageObjId}_mc${kid.mcid}` }); } else if (kid.type === StructElementType.OBJECT) { obj.children.push({ type: "object", id: kid.refObjId }); } else if (kid.type === StructElementType.ANNOTATION) { obj.children.push({ type: "annotation", id: `${AnnotationPrefix}${kid.refObjId}` }); } } } const root = Object.create(null); root.children = []; root.role = "Root"; for (const child of this.nodes) { if (!child) { continue; } nodeToSerializable(child, root); } return root; } } ;// CONCATENATED MODULE: ./src/core/catalog.js function isValidExplicitDest(dest) { if (!Array.isArray(dest) || dest.length < 2) { return false; } const [page, zoom, ...args] = dest; if (!(page instanceof Ref) && !Number.isInteger(page)) { return false; } if (!(zoom instanceof Name)) { return false; } let allowNull = true; switch (zoom.name) { case "XYZ": if (args.length !== 3) { return false; } break; case "Fit": case "FitB": return args.length === 0; case "FitH": case "FitBH": case "FitV": case "FitBV": if (args.length !== 1) { return false; } break; case "FitR": if (args.length !== 4) { return false; } allowNull = false; break; default: return false; } for (const arg of args) { if (!(typeof arg === "number" || allowNull && arg === null)) { return false; } } return true; } function fetchDest(dest) { if (dest instanceof Dict) { dest = dest.get("D"); } return isValidExplicitDest(dest) ? dest : null; } function fetchRemoteDest(action) { let dest = action.get("D"); if (dest) { if (dest instanceof Name) { dest = dest.name; } if (typeof dest === "string") { return stringToPDFString(dest); } else if (isValidExplicitDest(dest)) { return JSON.stringify(dest); } } return null; } class Catalog { constructor(pdfManager, xref) { this.pdfManager = pdfManager; this.xref = xref; this._catDict = xref.getCatalogObj(); if (!(this._catDict instanceof Dict)) { throw new FormatError("Catalog object is not a dictionary."); } this.toplevelPagesDict; this._actualNumPages = null; this.fontCache = new RefSetCache(); this.builtInCMapCache = new Map(); this.standardFontDataCache = new Map(); this.globalImageCache = new GlobalImageCache(); this.pageKidsCountCache = new RefSetCache(); this.pageIndexCache = new RefSetCache(); this.nonBlendModesSet = new RefSet(); this.systemFontCache = new Map(); } cloneDict() { return this._catDict.clone(); } get version() { const version = this._catDict.get("Version"); if (version instanceof Name) { if (PDF_VERSION_REGEXP.test(version.name)) { return shadow(this, "version", version.name); } warn(`Invalid PDF catalog version: ${version.name}`); } return shadow(this, "version", null); } get lang() { const lang = this._catDict.get("Lang"); return shadow(this, "lang", lang && typeof lang === "string" ? stringToPDFString(lang) : null); } get needsRendering() { const needsRendering = this._catDict.get("NeedsRendering"); return shadow(this, "needsRendering", typeof needsRendering === "boolean" ? needsRendering : false); } get collection() { let collection = null; try { const obj = this._catDict.get("Collection"); if (obj instanceof Dict && obj.size > 0) { collection = obj; } } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } info("Cannot fetch Collection entry; assuming no collection is present."); } return shadow(this, "collection", collection); } get acroForm() { let acroForm = null; try { const obj = this._catDict.get("AcroForm"); if (obj instanceof Dict && obj.size > 0) { acroForm = obj; } } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } info("Cannot fetch AcroForm entry; assuming no forms are present."); } return shadow(this, "acroForm", acroForm); } get acroFormRef() { const value = this._catDict.getRaw("AcroForm"); return shadow(this, "acroFormRef", value instanceof Ref ? value : null); } get metadata() { const streamRef = this._catDict.getRaw("Metadata"); if (!(streamRef instanceof Ref)) { return shadow(this, "metadata", null); } let metadata = null; try { const stream = this.xref.fetch(streamRef, !this.xref.encrypt?.encryptMetadata); if (stream instanceof BaseStream && stream.dict instanceof Dict) { const type = stream.dict.get("Type"); const subtype = stream.dict.get("Subtype"); if (isName(type, "Metadata") && isName(subtype, "XML")) { const data = stringToUTF8String(stream.getString()); if (data) { metadata = new MetadataParser(data).serializable; } } } } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } info(`Skipping invalid Metadata: "${ex}".`); } return shadow(this, "metadata", metadata); } get markInfo() { let markInfo = null; try { markInfo = this._readMarkInfo(); } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } warn("Unable to read mark info."); } return shadow(this, "markInfo", markInfo); } _readMarkInfo() { const obj = this._catDict.get("MarkInfo"); if (!(obj instanceof Dict)) { return null; } const markInfo = { Marked: false, UserProperties: false, Suspects: false }; for (const key in markInfo) { const value = obj.get(key); if (typeof value === "boolean") { markInfo[key] = value; } } return markInfo; } get structTreeRoot() { let structTree = null; try { structTree = this._readStructTreeRoot(); } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } warn("Unable read to structTreeRoot info."); } return shadow(this, "structTreeRoot", structTree); } _readStructTreeRoot() { const rawObj = this._catDict.getRaw("StructTreeRoot"); const obj = this.xref.fetchIfRef(rawObj); if (!(obj instanceof Dict)) { return null; } const root = new StructTreeRoot(obj, rawObj); root.init(); return root; } get toplevelPagesDict() { const pagesObj = this._catDict.get("Pages"); if (!(pagesObj instanceof Dict)) { throw new FormatError("Invalid top-level pages dictionary."); } return shadow(this, "toplevelPagesDict", pagesObj); } get documentOutline() { let obj = null; try { obj = this._readDocumentOutline(); } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } warn("Unable to read document outline."); } return shadow(this, "documentOutline", obj); } _readDocumentOutline() { let obj = this._catDict.get("Outlines"); if (!(obj instanceof Dict)) { return null; } obj = obj.getRaw("First"); if (!(obj instanceof Ref)) { return null; } const root = { items: [] }; const queue = [{ obj, parent: root }]; const processed = new RefSet(); processed.put(obj); const xref = this.xref, blackColor = new Uint8ClampedArray(3); while (queue.length > 0) { const i = queue.shift(); const outlineDict = xref.fetchIfRef(i.obj); if (outlineDict === null) { continue; } if (!outlineDict.has("Title")) { warn("Invalid outline item encountered."); } const data = { url: null, dest: null, action: null }; Catalog.parseDestDictionary({ destDict: outlineDict, resultObj: data, docBaseUrl: this.baseUrl, docAttachments: this.attachments }); const title = outlineDict.get("Title"); const flags = outlineDict.get("F") || 0; const color = outlineDict.getArray("C"); const count = outlineDict.get("Count"); let rgbColor = blackColor; if (isNumberArray(color, 3) && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) { rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0); } const outlineItem = { action: data.action, attachment: data.attachment, dest: data.dest, url: data.url, unsafeUrl: data.unsafeUrl, newWindow: data.newWindow, setOCGState: data.setOCGState, title: typeof title === "string" ? stringToPDFString(title) : "", color: rgbColor, count: Number.isInteger(count) ? count : undefined, bold: !!(flags & 2), italic: !!(flags & 1), items: [] }; i.parent.items.push(outlineItem); obj = outlineDict.getRaw("First"); if (obj instanceof Ref && !processed.has(obj)) { queue.push({ obj, parent: outlineItem }); processed.put(obj); } obj = outlineDict.getRaw("Next"); if (obj instanceof Ref && !processed.has(obj)) { queue.push({ obj, parent: i.parent }); processed.put(obj); } } return root.items.length > 0 ? root.items : null; } get permissions() { let permissions = null; try { permissions = this._readPermissions(); } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } warn("Unable to read permissions."); } return shadow(this, "permissions", permissions); } _readPermissions() { const encrypt = this.xref.trailer.get("Encrypt"); if (!(encrypt instanceof Dict)) { return null; } let flags = encrypt.get("P"); if (typeof flags !== "number") { return null; } flags += 2 ** 32; const permissions = []; for (const key in PermissionFlag) { const value = PermissionFlag[key]; if (flags & value) { permissions.push(value); } } return permissions; } get optionalContentConfig() { let config = null; try { const properties = this._catDict.get("OCProperties"); if (!properties) { return shadow(this, "optionalContentConfig", null); } const defaultConfig = properties.get("D"); if (!defaultConfig) { return shadow(this, "optionalContentConfig", null); } const groupsData = properties.get("OCGs"); if (!Array.isArray(groupsData)) { return shadow(this, "optionalContentConfig", null); } const groups = []; const groupRefs = new RefSet(); for (const groupRef of groupsData) { if (!(groupRef instanceof Ref) || groupRefs.has(groupRef)) { continue; } groupRefs.put(groupRef); groups.push(this.#readOptionalContentGroup(groupRef)); } config = this.#readOptionalContentConfig(defaultConfig, groupRefs); config.groups = groups; } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } warn(`Unable to read optional content config: ${ex}`); } return shadow(this, "optionalContentConfig", config); } #readOptionalContentGroup(groupRef) { const group = this.xref.fetch(groupRef); const obj = { id: groupRef.toString(), name: null, intent: null, usage: { print: null, view: null } }; const name = group.get("Name"); if (typeof name === "string") { obj.name = stringToPDFString(name); } let intent = group.getArray("Intent"); if (!Array.isArray(intent)) { intent = [intent]; } if (intent.every(i => i instanceof Name)) { obj.intent = intent.map(i => i.name); } const usage = group.get("Usage"); if (!(usage instanceof Dict)) { return obj; } const usageObj = obj.usage; const print = usage.get("Print"); if (print instanceof Dict) { const printState = print.get("PrintState"); if (printState instanceof Name) { switch (printState.name) { case "ON": case "OFF": usageObj.print = { printState: printState.name }; } } } const view = usage.get("View"); if (view instanceof Dict) { const viewState = view.get("ViewState"); if (viewState instanceof Name) { switch (viewState.name) { case "ON": case "OFF": usageObj.view = { viewState: viewState.name }; } } } return obj; } #readOptionalContentConfig(config, contentGroupRefs) { function parseOnOff(refs) { const onParsed = []; if (Array.isArray(refs)) { for (const value of refs) { if (!(value instanceof Ref)) { continue; } if (contentGroupRefs.has(value)) { onParsed.push(value.toString()); } } } return onParsed; } function parseOrder(refs, nestedLevels = 0) { if (!Array.isArray(refs)) { return null; } const order = []; for (const value of refs) { if (value instanceof Ref && contentGroupRefs.has(value)) { parsedOrderRefs.put(value); order.push(value.toString()); continue; } const nestedOrder = parseNestedOrder(value, nestedLevels); if (nestedOrder) { order.push(nestedOrder); } } if (nestedLevels > 0) { return order; } const hiddenGroups = []; for (const groupRef of contentGroupRefs) { if (parsedOrderRefs.has(groupRef)) { continue; } hiddenGroups.push(groupRef.toString()); } if (hiddenGroups.length) { order.push({ name: null, order: hiddenGroups }); } return order; } function parseNestedOrder(ref, nestedLevels) { if (++nestedLevels > MAX_NESTED_LEVELS) { warn("parseNestedOrder - reached MAX_NESTED_LEVELS."); return null; } const value = xref.fetchIfRef(ref); if (!Array.isArray(value)) { return null; } const nestedName = xref.fetchIfRef(value[0]); if (typeof nestedName !== "string") { return null; } const nestedOrder = parseOrder(value.slice(1), nestedLevels); if (!nestedOrder || !nestedOrder.length) { return null; } return { name: stringToPDFString(nestedName), order: nestedOrder }; } const xref = this.xref, parsedOrderRefs = new RefSet(), MAX_NESTED_LEVELS = 10; return { name: typeof config.get("Name") === "string" ? stringToPDFString(config.get("Name")) : null, creator: typeof config.get("Creator") === "string" ? stringToPDFString(config.get("Creator")) : null, baseState: config.get("BaseState") instanceof Name ? config.get("BaseState").name : null, on: parseOnOff(config.get("ON")), off: parseOnOff(config.get("OFF")), order: parseOrder(config.get("Order")), groups: null }; } setActualNumPages(num = null) { this._actualNumPages = num; } get hasActualNumPages() { return this._actualNumPages !== null; } get _pagesCount() { const obj = this.toplevelPagesDict.get("Count"); if (!Number.isInteger(obj)) { throw new FormatError("Page count in top-level pages dictionary is not an integer."); } return shadow(this, "_pagesCount", obj); } get numPages() { return this.hasActualNumPages ? this._actualNumPages : this._pagesCount; } get destinations() { const obj = this._readDests(), dests = Object.create(null); if (obj instanceof NameTree) { for (const [key, value] of obj.getAll()) { const dest = fetchDest(value); if (dest) { dests[stringToPDFString(key)] = dest; } } } else if (obj instanceof Dict) { obj.forEach(function (key, value) { const dest = fetchDest(value); if (dest) { dests[key] = dest; } }); } return shadow(this, "destinations", dests); } getDestination(id) { const obj = this._readDests(); if (obj instanceof NameTree) { const dest = fetchDest(obj.get(id)); if (dest) { return dest; } const allDest = this.destinations[id]; if (allDest) { warn(`Found "${id}" at an incorrect position in the NameTree.`); return allDest; } } else if (obj instanceof Dict) { const dest = fetchDest(obj.get(id)); if (dest) { return dest; } } return null; } _readDests() { const obj = this._catDict.get("Names"); if (obj?.has("Dests")) { return new NameTree(obj.getRaw("Dests"), this.xref); } else if (this._catDict.has("Dests")) { return this._catDict.get("Dests"); } return undefined; } get pageLabels() { let obj = null; try { obj = this._readPageLabels(); } catch (ex) { if (ex instanceof MissingDataException) { throw ex; } warn("Unable to read page labels."); } return shadow(this, "pageLabels", obj); } _readPageLabels() { const obj = this._catDict.getRaw("PageLabels"); if (!obj) { return null; } const pageLabels = new Array(this.numPages); let style = null, prefix = ""; const numberTree = new NumberTree(obj, this.xref); const nums = numberTree.getAll(); let currentLabel = "", currentIndex = 1; for (let i = 0, ii = this.numPages; i < ii; i++) { const labelDict = nums.get(i); if (labelDict !== undefined) { if (!(labelDict instanceof Dict)) { throw new FormatError("PageLabel is not a dictionary."); } if (labelDict.has("Type") && !isName(labelDict.get("Type"), "PageLabel")) { throw new FormatError("Invalid type in PageLabel dictionary."); } if (labelDict.has("S")) { const s = labelDict.get("S"); if (!(s instanceof Name)) { throw new FormatError("Invalid style in PageLabel dictionary."); } style = s.name; } else { style = null; } if (labelDict.has("P")) { const p = labelDict.get("P"); if (typeof p !== "string") { throw new FormatError("Invalid prefix in PageLabel dictionary."); } prefix = stringToPDFString(p); } else { prefix = ""; } if (labelDict.has("St")) { const st = labelDict.get("St"); if (!(Number.isInteger(st) && st >= 1)) { throw new FormatError("Invalid start in PageLabel dictionary."); } currentIndex = st; } else { currentIndex = 1; } } switch (style) { case "D": currentLabel = currentIndex; break; case "R": case "r": currentLabel = toRomanNumerals(currentIndex, style === "r"); break; case "A": case "a": const LIMIT = 26; const A_UPPER_CASE = 0x41, A_LOWER_CASE = 0x61; const baseCharCode = style === "a" ? A_LOWER_CASE : A_UPPER_CASE; const letterIndex = currentIndex - 1; const character = String.fromCharCode(baseCharCode + letterIndex % LIMIT); currentLabel = character.repeat(Math.floor(letterIndex / LIMIT) + 1); break; default: if (style) { throw new FormatError(`Invalid style "${style}" in PageLabel dictionary.`); } currentLabel = ""; } pageLabels[i] = prefix + currentLabel; currentIndex++; } return pageLabels; } get pageLayout() { const obj = this._catDict.get("PageLayout"); let pageLayout = ""; if (obj instanceof Name) { switch (obj.name) { case "SinglePage": case "OneColumn": case "TwoColumnLeft": case "TwoColumnRight": case "TwoPageLeft": case "TwoPageRight": pageLayout = obj.name; } } return shadow(this, "pageLayout", pageLayout); } get pageMode() { const obj = this._catDict.get("PageMode"); let pageMode = "UseNone"; if (obj instanceof Name) { switch (obj.name) { case "UseNone": case "UseOutlines": case "UseThumbs": case "FullScreen": case "UseOC": case "UseAttachments": pageMode = obj.name; } } return shadow(this, "pageMode", pageMode); } get viewerPreferences() { const obj = this._catDict.get("ViewerPreferences"); if (!(obj instanceof Dict)) { return shadow(this, "viewerPreferences", null); } let prefs = null; for (const key of obj.getKeys()) { const value = obj.get(key); let prefValue; switch (key) { case "HideToolbar": case "HideMenubar": case "HideWindowUI": case "FitWindow": case "CenterWindow": case "DisplayDocTitle": case "PickTrayByPDFSize": if (typeof value === "boolean") { prefValue = value; } break; case "NonFullScreenPageMode": if (value instanceof Name) { switch (value.name) { case "UseNone": case "UseOutlines": case "UseThumbs": case "UseOC": prefValue = value.name; break; default: prefValue = "UseNone"; } } break; case "Direction": if (value instanceof Name) { switch (value.name) { case "L2R": case "R2L": prefValue = value.name; break; default: prefValue = "L2R"; } } break; case "ViewArea": case "ViewClip": case "PrintArea": case "PrintClip": if (value instanceof Name) { switch (value.name) { case "MediaBox": case "CropBox": case "BleedBox": case "TrimBox": case "ArtBox": prefValue = value.name; break; default: prefValue = "CropBox"; } } break; case "PrintScaling": if (value instanceof Name) { switch (value.name) { case "None": case "AppDefault": prefValue = value.name; break; default: prefValue = "AppDefault"; } } break; case "Duplex": if (value instanceof Name) { switch (value.name) { case "Simplex": case "DuplexFlipShortEdge": case "DuplexFlipLongEdge": prefValue = value.name; break; default: prefValue = "None"; } } break; case "PrintPageRange": if (Array.isArray(value) && value.length % 2 === 0) { const isValid = value.every((page, i, arr) => Number.isInteger(page) && page > 0 && (i === 0 || page >= arr[i - 1]) && page <= this.numPages); if (isValid) { prefValue = value; } } break; case "NumCopies": if (Number.isInteger(value) && value > 0) { prefValue = value; } break; default: warn(`Ignoring non-standard key in ViewerPreferences: ${key}.`); continue; } if (prefValue === undefined) { warn(`Bad value, for key "${key}", in ViewerPreferences: ${value}.`); continue; } if (!prefs) { prefs = Object.create(null); } prefs[key] = prefValue; } return shadow(this, "viewerPreferences", prefs); } get openAction() { const obj = this._catDict.get("OpenAction"); const openAction = Object.create(null); if (obj instanceof Dict) { const destDict = new Dict(this.xref); destDict.set("A", obj); const resultObj = { url: null, dest: null, action: null }; Catalog.parseDestDictionary({ destDict, resultObj }); if (Array.isArray(resultObj.dest)) { openAction.dest = resultObj.dest; } else if (resultObj.action) { openAction.action = resultObj.action; } } else if (Array.isArray(obj)) { openAction.dest = obj; } return shadow(this, "openAction", objectSize(openAction) > 0 ? openAction : null); } get attachments() { const obj = this._catDict.get("Names"); let attachments = null; if (obj instanceof Dict && obj.has("EmbeddedFiles")) { const nameTree = new NameTree(obj.getRaw("EmbeddedFiles"), this.xref); for (const [key, value] of nameTree.getAll()) { const fs = new FileSpec(value, this.xref); if (!attachments) { attachments = Object.create(null); } attachments[stringToPDFString(key)] = fs.serializable; } } return shadow(this, "attachments", attachments); } get xfaImages() { const obj = this._catDict.get("Names"); let xfaImages = null; if (obj instanceof Dict && obj.has("XFAImages")) { const nameTree = new NameTree(obj.getRaw("XFAImages"), this.xref); for (const [key, value] of nameTree.getAll()) { if (!xfaImages) { xfaImages = new Dict(this.xref); } xfaImages.set(stringToPDFString(key), value); } } return shadow(this, "xfaImages", xfaImages); } _collectJavaScript() { const obj = this._catDict.get("Names"); let javaScript = null; function appendIfJavaScriptDict(name, jsDict) { if (!(jsDict instanceof Dict)) { return; } if (!isName(jsDict.get("S"), "JavaScript")) { return; } let js = jsDict.get("JS"); if (js instanceof BaseStream) { js = js.getString(); } else if (typeof js !== "string") { return; } js = stringToPDFString(js).replaceAll("\x00", ""); if (js) { (javaScript ||= new Map()).set(name, js); } } if (obj instanceof Dict && obj.has("JavaScript")) { const nameTree = new NameTree(obj.getRaw("JavaScript"), this.xref); for (const [key, value] of nameTree.getAll()) { appendIfJavaScriptDict(stringToPDFString(key), value); } } const openAction = this._catDict.get("OpenAction"); if (openAction) { appendIfJavaScriptDict("OpenAction", openAction); } return javaScript; } get jsActions() { const javaScript = this._collectJavaScript(); let actions = collectActions(this.xref, this._catDict, DocumentActionEventType); if (javaScript) { actions ||= Object.create(null); for (const [key, val] of javaScript) { if (key in actions) { actions[key].push(val); } else { actions[key] = [val]; } } } return shadow(this, "jsActions", actions); } async fontFallback(id, handler) { const translatedFonts = await Promise.all(this.fontCache); for (const translatedFont of translatedFonts) { if (translatedFont.loadedName === id) { translatedFont.fallback(handler); return; } } } async cleanup(manuallyTriggered = false) { clearGlobalCaches(); this.globalImageCache.clear(manuallyTriggered); this.pageKidsCountCache.clear(); this.pageIndexCache.clear(); this.nonBlendModesSet.clear(); const translatedFonts = await Promise.all(this.fontCache); for (const { dict } of translatedFonts) { delete dict.cacheKey; } this.fontCache.clear(); this.builtInCMapCache.clear(); this.standardFontDataCache.clear(); this.systemFontCache.clear(); } async getPageDict(pageIndex) { const nodesToVisit = [this.toplevelPagesDict]; const visitedNodes = new RefSet(); const pagesRef = this._catDict.getRaw("Pages"); if (pagesRef instanceof Ref) { visitedNodes.put(pagesRef); } const xref = this.xref, pageKidsCountCache = this.pageKidsCountCache, pageIndexCache = this.pageIndexCache; let currentPageIndex = 0; while (nodesToVisit.length) { const currentNode = nodesToVisit.pop(); if (currentNode instanceof Ref) { const count = pageKidsCountCache.get(currentNode); if (count >= 0 && currentPageIndex + count <= pageIndex) { currentPageIndex += count; continue; } if (visitedNodes.has(currentNode)) { throw new FormatError("Pages tree contains circular reference."); } visitedNodes.put(currentNode); const obj = await xref.fetchAsync(currentNode); if (obj instanceof Dict) { let type = obj.getRaw("Type"); if (type instanceof Ref) { type = await xref.fetchAsync(type); } if (isName(type, "Page") || !obj.has("Kids")) { if (!pageKidsCountCache.has(currentNode)) { pageKidsCountCache.put(currentNode, 1); } if (!pageIndexCache.has(currentNode)) { pageIndexCache.put(currentNode, currentPageIndex); } if (currentPageIndex === pageIndex) { return [obj, currentNode]; } currentPageIndex++; continue; } } nodesToVisit.push(obj); continue; } if (!(currentNode instanceof Dict)) { throw new FormatError("Page dictionary kid reference points to wrong type of object."); } const { objId } = currentNode; let count = currentNode.getRaw("Count"); if (count instanceof Ref) { count = await xref.fetchAsync(count); } if (Number.isInteger(count) && count >= 0) { if (objId && !pageKidsCountCache.has(objId)) { pageKidsCountCache.put(objId, count); } if (currentPageIndex + count <= pageIndex) { currentPageIndex += count; continue; } } let kids = currentNode.getRaw("Kids"); if (kids instanceof Ref) { kids = await xref.fetchAsync(kids); } if (!Array.isArray(kids)) { let type = currentNode.getRaw("Type"); if (type instanceof Ref) { type = await xref.fetchAsync(type); } if (isName(type, "Page") || !currentNode.has("Kids")) { if (currentPageIndex === pageIndex) { return [currentNode, null]; } currentPageIndex++; continue; } throw new FormatError("Page dictionary kids object is not an array."); } for (let last = kids.length - 1; last >= 0; last--) { nodesToVisit.push(kids[last]); } } throw new Error(`Page index ${pageIndex} not found.`); } async getAllPageDicts(recoveryMode = false) { const { ignoreErrors } = this.pdfManager.evaluatorOptions; const queue = [{ currentNode: this.toplevelPagesDict, posInKids: 0 }]; const visitedNodes = new RefSet(); const pagesRef = this._catDict.getRaw("Pages"); if (pagesRef instanceof Ref) { visitedNodes.put(pagesRef); } const map = new Map(), xref = this.xref, pageIndexCache = this.pageIndexCache; let pageIndex = 0; function addPageDict(pageDict, pageRef) { if (pageRef && !pageIndexCache.has(pageRef)) { pageIndexCache.put(pageRef, pageIndex); } map.set(pageIndex++, [pageDict, pageRef]); } function addPageError(error) { if (error instanceof XRefEntryException && !recoveryMode) { throw error; } if (recoveryMode && ignoreErrors && pageIndex === 0) { warn(`getAllPageDicts - Skipping invalid first page: "${error}".`); error = Dict.empty; } map.set(pageIndex++, [error, null]); } while (queue.length > 0) { const queueItem = queue.at(-1); const { currentNode, posInKids } = queueItem; let kids = currentNode.getRaw("Kids"); if (kids instanceof Ref) { try { kids = await xref.fetchAsync(kids); } catch (ex) { addPageError(ex); break; } } if (!Array.isArray(kids)) { addPageError(new FormatError("Page dictionary kids object is not an array.")); break; } if (posInKids >= kids.length) { queue.pop(); continue; } const kidObj = kids[posInKids]; let obj; if (kidObj instanceof Ref) { if (visitedNodes.has(kidObj)) { addPageError(new FormatError("Pages tree contains circular reference.")); break; } visitedNodes.put(kidObj); try { obj = await xref.fetchAsync(kidObj); } catch (ex) { addPageError(ex); break; } } else { obj = kidObj; } if (!(obj instanceof Dict)) { addPageError(new FormatError("Page dictionary kid reference points to wrong type of object.")); break; } let type = obj.getRaw("Type"); if (type instanceof Ref) { try { type = await xref.fetchAsync(type); } catch (ex) { addPageError(ex); break; } } if (isName(type, "Page") || !obj.has("Kids")) { addPageDict(obj, kidObj instanceof Ref ? kidObj : null); } else { queue.push({ currentNode: obj, posInKids: 0 }); } queueItem.posInKids++; } return map; } getPageIndex(pageRef) { const cachedPageIndex = this.pageIndexCache.get(pageRef); if (cachedPageIndex !== undefined) { return Promise.resolve(cachedPageIndex); } const xref = this.xref; function pagesBeforeRef(kidRef) { let total = 0, parentRef; return xref.fetchAsync(kidRef).then(function (node) { if (isRefsEqual(kidRef, pageRef) && !isDict(node, "Page") && !(node instanceof Dict && !node.has("Type") && node.has("Contents"))) { throw new FormatError("The reference does not point to a /Page dictionary."); } if (!node) { return null; } if (!(node instanceof Dict)) { throw new FormatError("Node must be a dictionary."); } parentRef = node.getRaw("Parent"); return node.getAsync("Parent"); }).then(function (parent) { if (!parent) { return null; } if (!(parent instanceof Dict)) { throw new FormatError("Parent must be a dictionary."); } return parent.getAsync("Kids"); }).then(function (kids) { if (!kids) { return null; } const kidPromises = []; let found = false; for (const kid of kids) { if (!(kid instanceof Ref)) { throw new FormatError("Kid must be a reference."); } if (isRefsEqual(kid, kidRef)) { found = true; break; } kidPromises.push(xref.fetchAsync(kid).then(function (obj) { if (!(obj instanceof Dict)) { throw new FormatError("Kid node must be a dictionary."); } if (obj.has("Count")) { total += obj.get("Count"); } else { total++; } })); } if (!found) { throw new FormatError("Kid reference not found in parent's kids."); } return Promise.all(kidPromises).then(function () { return [total, parentRef]; }); }); } let total = 0; const next = ref => pagesBeforeRef(ref).then(args => { if (!args) { this.pageIndexCache.put(pageRef, total); return total; } const [count, parentRef] = args; total += count; return next(parentRef); }); return next(pageRef); } get baseUrl() { const uri = this._catDict.get("URI"); if (uri instanceof Dict) { const base = uri.get("Base"); if (typeof base === "string") { const absoluteUrl = createValidAbsoluteUrl(base, null, { tryConvertEncoding: true }); if (absoluteUrl) { return shadow(this, "baseUrl", absoluteUrl.href); } } } return shadow(this, "baseUrl", this.pdfManager.docBaseUrl); } static parseDestDictionary({ destDict, resultObj, docBaseUrl = null, docAttachments = null }) { if (!(destDict instanceof Dict)) { warn("parseDestDictionary: `destDict` must be a dictionary."); return; } let action = destDict.get("A"), url, dest; if (!(action instanceof Dict)) { if (destDict.has("Dest")) { action = destDict.get("Dest"); } else { action = destDict.get("AA"); if (action instanceof Dict) { if (action.has("D")) { action = action.get("D"); } else if (action.has("U")) { action = action.get("U"); } } } } if (action instanceof Dict) { const actionType = action.get("S"); if (!(actionType instanceof Name)) { warn("parseDestDictionary: Invalid type in Action dictionary."); return; } const actionName = actionType.name; switch (actionName) { case "ResetForm": const flags = action.get("Flags"); const include = ((typeof flags === "number" ? flags : 0) & 1) === 0; const fields = []; const refs = []; for (const obj of action.get("Fields") || []) { if (obj instanceof Ref) { refs.push(obj.toString()); } else if (typeof obj === "string") { fields.push(stringToPDFString(obj)); } } resultObj.resetForm = { fields, refs, include }; break; case "URI": url = action.get("URI"); if (url instanceof Name) { url = "/" + url.name; } break; case "GoTo": dest = action.get("D"); break; case "Launch": case "GoToR": const urlDict = action.get("F"); if (urlDict instanceof Dict) { const fs = new FileSpec(urlDict, null, true); const { rawFilename } = fs.serializable; url = rawFilename; } else if (typeof urlDict === "string") { url = urlDict; } const remoteDest = fetchRemoteDest(action); if (remoteDest && typeof url === "string") { url = url.split("#", 1)[0] + "#" + remoteDest; } const newWindow = action.get("NewWindow"); if (typeof newWindow === "boolean") { resultObj.newWindow = newWindow; } break; case "GoToE": const target = action.get("T"); let attachment; if (docAttachments && target instanceof Dict) { const relationship = target.get("R"); const name = target.get("N"); if (isName(relationship, "C") && typeof name === "string") { attachment = docAttachments[stringToPDFString(name)]; } } if (attachment) { resultObj.attachment = attachment; const attachmentDest = fetchRemoteDest(action); if (attachmentDest) { resultObj.attachmentDest = attachmentDest; } } else { warn(`parseDestDictionary - unimplemented "GoToE" action.`); } break; case "Named": const namedAction = action.get("N"); if (namedAction instanceof Name) { resultObj.action = namedAction.name; } break; case "SetOCGState": const state = action.get("State"); const preserveRB = action.get("PreserveRB"); if (!Array.isArray(state) || state.length === 0) { break; } const stateArr = []; for (const elem of state) { if (elem instanceof Name) { switch (elem.name) { case "ON": case "OFF": case "Toggle": stateArr.push(elem.name); break; } } else if (elem instanceof Ref) { stateArr.push(elem.toString()); } } if (stateArr.length !== state.length) { break; } resultObj.setOCGState = { state: stateArr, preserveRB: typeof preserveRB === "boolean" ? preserveRB : true }; break; case "JavaScript": const jsAction = action.get("JS"); let js; if (jsAction instanceof BaseStream) { js = jsAction.getString(); } else if (typeof jsAction === "string") { js = jsAction; } const jsURL = js && recoverJsURL(stringToPDFString(js)); if (jsURL) { url = jsURL.url; resultObj.newWindow = jsURL.newWindow; break; } default: if (actionName === "JavaScript" || actionName === "SubmitForm") { break; } warn(`parseDestDictionary - unsupported action: "${actionName}".`); break; } } else if (destDict.has("Dest")) { dest = destDict.get("Dest"); } if (typeof url === "string") { const absoluteUrl = createValidAbsoluteUrl(url, docBaseUrl, { addDefaultProtocol: true, tryConvertEncoding: true }); if (absoluteUrl) { resultObj.url = absoluteUrl.href; } resultObj.unsafeUrl = url; } if (dest) { if (dest instanceof Name) { dest = dest.name; } if (typeof dest === "string") { resultObj.dest = stringToPDFString(dest); } else if (isValidExplicitDest(dest)) { resultObj.dest = dest; } } } } ;// CONCATENATED MODULE: ./src/core/object_loader.js function mayHaveChildren(value) { return value instanceof Ref || value instanceof Dict || value instanceof BaseStream || Array.isArray(value); } function addChildren(node, nodesToVisit) { if (node instanceof Dict) { node = node.getRawValues(); } else if (node instanceof BaseStream) { node = node.dict.getRawValues(); } else if (!Array.isArray(node)) { return; } for (const rawValue of node) { if (mayHaveChildren(rawValue)) { nodesToVisit.push(rawValue); } } } class ObjectLoader { constructor(dict, keys, xref) { this.dict = dict; this.keys = keys; this.xref = xref; this.refSet = null; } async load() { if (this.xref.stream.isDataLoaded) { return undefined; } const { keys, dict } = this; this.refSet = new RefSet(); const nodesToVisit = []; for (const key of keys) { const rawValue = dict.getRaw(key); if (rawValue !== undefined) { nodesToVisit.push(rawValue); } } return this._walk(nodesToVisit); } async _walk(nodesToVisit) { const nodesToRevisit = []; const pendingRequests = []; while (nodesToVisit.length) { let currentNode = nodesToVisit.pop(); if (currentNode instanceof Ref) { if (this.refSet.has(currentNode)) { continue; } try { this.refSet.put(currentNode); currentNode = this.xref.fetch(currentNode); } catch (ex) { if (!(ex instanceof MissingDataException)) { warn(`ObjectLoader._walk - requesting all data: "${ex}".`); this.refSet = null; const { manager } = this.xref.stream; return manager.requestAllChunks(); } nodesToRevisit.push(currentNode); pendingRequests.push({ begin: ex.begin, end: ex.end }); } } if (currentNode instanceof BaseStream) { const baseStreams = currentNode.getBaseStreams(); if (baseStreams) { let foundMissingData = false; for (const stream of baseStreams) { if (stream.isDataLoaded) { continue; } foundMissingData = true; pendingRequests.push({ begin: stream.start, end: stream.end }); } if (foundMissingData) { nodesToRevisit.push(currentNode); } } } addChildren(currentNode, nodesToVisit); } if (pendingRequests.length) { await this.xref.stream.manager.requestRanges(pendingRequests); for (const node of nodesToRevisit) { if (node instanceof Ref) { this.refSet.remove(node); } } return this._walk(nodesToRevisit); } this.refSet = null; return undefined; } } ;// CONCATENATED MODULE: ./src/core/xfa/symbol_utils.js const $acceptWhitespace = Symbol(); const $addHTML = Symbol(); const $appendChild = Symbol(); const $childrenToHTML = Symbol(); const $clean = Symbol(); const $cleanPage = Symbol(); const $cleanup = Symbol(); const $clone = Symbol(); const $consumed = Symbol(); const $content = Symbol("content"); const $data = Symbol("data"); const $dump = Symbol(); const $extra = Symbol("extra"); const $finalize = Symbol(); const $flushHTML = Symbol(); const $getAttributeIt = Symbol(); const $getAttributes = Symbol(); const $getAvailableSpace = Symbol(); const $getChildrenByClass = Symbol(); const $getChildrenByName = Symbol(); const $getChildrenByNameIt = Symbol(); const $getDataValue = Symbol(); const $getExtra = Symbol(); const $getRealChildrenByNameIt = Symbol(); const $getChildren = Symbol(); const $getContainedChildren = Symbol(); const $getNextPage = Symbol(); const $getSubformParent = Symbol(); const $getParent = Symbol(); const $getTemplateRoot = Symbol(); const $globalData = Symbol(); const $hasSettableValue = Symbol(); const $ids = Symbol(); const $indexOf = Symbol(); const $insertAt = Symbol(); const $isCDATAXml = Symbol(); const $isBindable = Symbol(); const $isDataValue = Symbol(); const $isDescendent = Symbol(); const $isNsAgnostic = Symbol(); const $isSplittable = Symbol(); const $isThereMoreWidth = Symbol(); const $isTransparent = Symbol(); const $isUsable = Symbol(); const $lastAttribute = Symbol(); const $namespaceId = Symbol("namespaceId"); const $nodeName = Symbol("nodeName"); const $nsAttributes = Symbol(); const $onChild = Symbol(); const $onChildCheck = Symbol(); const $onText = Symbol(); const $pushGlyphs = Symbol(); const $popPara = Symbol(); const $pushPara = Symbol(); const $removeChild = Symbol(); const $root = Symbol("root"); const $resolvePrototypes = Symbol(); const $searchNode = Symbol(); const $setId = Symbol(); const $setSetAttributes = Symbol(); const $setValue = Symbol(); const $tabIndex = Symbol(); const $text = Symbol(); const $toPages = Symbol(); const $toHTML = Symbol(); const $toString = Symbol(); const $toStyle = Symbol(); const $uid = Symbol("uid"); ;// CONCATENATED MODULE: ./src/core/xfa/namespaces.js const $buildXFAObject = Symbol(); const NamespaceIds = { config: { id: 0, check: ns => ns.startsWith("http://www.xfa.org/schema/xci/") }, connectionSet: { id: 1, check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-connection-set/") }, datasets: { id: 2, check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-data/") }, form: { id: 3, check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-form/") }, localeSet: { id: 4, check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-locale-set/") }, pdf: { id: 5, check: ns => ns === "http://ns.adobe.com/xdp/pdf/" }, signature: { id: 6, check: ns => ns === "http://www.w3.org/2000/09/xmldsig#" }, sourceSet: { id: 7, check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-source-set/") }, stylesheet: { id: 8, check: ns => ns === "http://www.w3.org/1999/XSL/Transform" }, template: { id: 9, check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-template/") }, xdc: { id: 10, check: ns => ns.startsWith("http://www.xfa.org/schema/xdc/") }, xdp: { id: 11, check: ns => ns === "http://ns.adobe.com/xdp/" }, xfdf: { id: 12, check: ns => ns === "http://ns.adobe.com/xfdf/" }, xhtml: { id: 13, check: ns => ns === "http://www.w3.org/1999/xhtml" }, xmpmeta: { id: 14, check: ns => ns === "http://ns.adobe.com/xmpmeta/" } }; ;// CONCATENATED MODULE: ./src/core/xfa/utils.js const dimConverters = { pt: x => x, cm: x => x / 2.54 * 72, mm: x => x / (10 * 2.54) * 72, in: x => x * 72, px: x => x }; const measurementPattern = /([+-]?\d+\.?\d*)(.*)/; function stripQuotes(str) { if (str.startsWith("'") || str.startsWith('"')) { return str.slice(1, -1); } return str; } function getInteger({ data, defaultValue, validate }) { if (!data) { return defaultValue; } data = data.trim(); const n = parseInt(data, 10); if (!isNaN(n) && validate(n)) { return n; } return defaultValue; } function getFloat({ data, defaultValue, validate }) { if (!data) { return defaultValue; } data = data.trim(); const n = parseFloat(data); if (!isNaN(n) && validate(n)) { return n; } return defaultValue; } function getKeyword({ data, defaultValue, validate }) { if (!data) { return defaultValue; } data = data.trim(); if (validate(data)) { return data; } return defaultValue; } function getStringOption(data, options) { return getKeyword({ data, defaultValue: options[0], validate: k => options.includes(k) }); } function getMeasurement(str, def = "0") { def ||= "0"; if (!str) { return getMeasurement(def); } const match = str.trim().match(measurementPattern); if (!match) { return getMeasurement(def); } const [, valueStr, unit] = match; const value = parseFloat(valueStr); if (isNaN(value)) { return getMeasurement(def); } if (value === 0) { return 0; } const conv = dimConverters[unit]; if (conv) { return conv(value); } return value; } function getRatio(data) { if (!data) { return { num: 1, den: 1 }; } const ratio = data.trim().split(/\s*:\s*/).map(x => parseFloat(x)).filter(x => !isNaN(x)); if (ratio.length === 1) { ratio.push(1); } if (ratio.length === 0) { return { num: 1, den: 1 }; } const [num, den] = ratio; return { num, den }; } function getRelevant(data) { if (!data) { return []; } return data.trim().split(/\s+/).map(e => ({ excluded: e[0] === "-", viewname: e.substring(1) })); } function getColor(data, def = [0, 0, 0]) { let [r, g, b] = def; if (!data) { return { r, g, b }; } const color = data.trim().split(/\s*,\s*/).map(c => Math.min(Math.max(0, parseInt(c.trim(), 10)), 255)).map(c => isNaN(c) ? 0 : c); if (color.length < 3) { return { r, g, b }; } [r, g, b] = color; return { r, g, b }; } function getBBox(data) { const def = -1; if (!data) { return { x: def, y: def, width: def, height: def }; } const bbox = data.trim().split(/\s*,\s*/).map(m => getMeasurement(m, "-1")); if (bbox.length < 4 || bbox[2] < 0 || bbox[3] < 0) { return { x: def, y: def, width: def, height: def }; } const [x, y, width, height] = bbox; return { x, y, width, height }; } class HTMLResult { static get FAILURE() { return shadow(this, "FAILURE", new HTMLResult(false, null, null, null)); } static get EMPTY() { return shadow(this, "EMPTY", new HTMLResult(true, null, null, null)); } constructor(success, html, bbox, breakNode) { this.success = success; this.html = html; this.bbox = bbox; this.breakNode = breakNode; } isBreak() { return !!this.breakNode; } static breakNode(node) { return new HTMLResult(false, null, null, node); } static success(html, bbox = null) { return new HTMLResult(true, html, bbox, null); } } ;// CONCATENATED MODULE: ./src/core/xfa/fonts.js class FontFinder { constructor(pdfFonts) { this.fonts = new Map(); this.cache = new Map(); this.warned = new Set(); this.defaultFont = null; this.add(pdfFonts); } add(pdfFonts, reallyMissingFonts = null) { for (const pdfFont of pdfFonts) { this.addPdfFont(pdfFont); } for (const pdfFont of this.fonts.values()) { if (!pdfFont.regular) { pdfFont.regular = pdfFont.italic || pdfFont.bold || pdfFont.bolditalic; } } if (!reallyMissingFonts || reallyMissingFonts.size === 0) { return; } const myriad = this.fonts.get("PdfJS-Fallback-PdfJS-XFA"); for (const missing of reallyMissingFonts) { this.fonts.set(missing, myriad); } } addPdfFont(pdfFont) { const cssFontInfo = pdfFont.cssFontInfo; const name = cssFontInfo.fontFamily; let font = this.fonts.get(name); if (!font) { font = Object.create(null); this.fonts.set(name, font); if (!this.defaultFont) { this.defaultFont = font; } } let property = ""; const fontWeight = parseFloat(cssFontInfo.fontWeight); if (parseFloat(cssFontInfo.italicAngle) !== 0) { property = fontWeight >= 700 ? "bolditalic" : "italic"; } else if (fontWeight >= 700) { property = "bold"; } if (!property) { if (pdfFont.name.includes("Bold") || pdfFont.psName?.includes("Bold")) { property = "bold"; } if (pdfFont.name.includes("Italic") || pdfFont.name.endsWith("It") || pdfFont.psName?.includes("Italic") || pdfFont.psName?.endsWith("It")) { property += "italic"; } } if (!property) { property = "regular"; } font[property] = pdfFont; } getDefault() { return this.defaultFont; } find(fontName, mustWarn = true) { let font = this.fonts.get(fontName) || this.cache.get(fontName); if (font) { return font; } const pattern = /,|-|_| |bolditalic|bold|italic|regular|it/gi; let name = fontName.replaceAll(pattern, ""); font = this.fonts.get(name); if (font) { this.cache.set(fontName, font); return font; } name = name.toLowerCase(); const maybe = []; for (const [family, pdfFont] of this.fonts.entries()) { if (family.replaceAll(pattern, "").toLowerCase().startsWith(name)) { maybe.push(pdfFont); } } if (maybe.length === 0) { for (const [, pdfFont] of this.fonts.entries()) { if (pdfFont.regular.name?.replaceAll(pattern, "").toLowerCase().startsWith(name)) { maybe.push(pdfFont); } } } if (maybe.length === 0) { name = name.replaceAll(/psmt|mt/gi, ""); for (const [family, pdfFont] of this.fonts.entries()) { if (family.replaceAll(pattern, "").toLowerCase().startsWith(name)) { maybe.push(pdfFont); } } } if (maybe.length === 0) { for (const pdfFont of this.fonts.values()) { if (pdfFont.regular.name?.replaceAll(pattern, "").toLowerCase().startsWith(name)) { maybe.push(pdfFont); } } } if (maybe.length >= 1) { if (maybe.length !== 1 && mustWarn) { warn(`XFA - Too many choices to guess the correct font: ${fontName}`); } this.cache.set(fontName, maybe[0]); return maybe[0]; } if (mustWarn && !this.warned.has(fontName)) { this.warned.add(fontName); warn(`XFA - Cannot find the font: ${fontName}`); } return null; } } function selectFont(xfaFont, typeface) { if (xfaFont.posture === "italic") { if (xfaFont.weight === "bold") { return typeface.bolditalic; } return typeface.italic; } else if (xfaFont.weight === "bold") { return typeface.bold; } return typeface.regular; } function fonts_getMetrics(xfaFont, real = false) { let pdfFont = null; if (xfaFont) { const name = stripQuotes(xfaFont.typeface); const typeface = xfaFont[$globalData].fontFinder.find(name); pdfFont = selectFont(xfaFont, typeface); } if (!pdfFont) { return { lineHeight: 12, lineGap: 2, lineNoGap: 10 }; } const size = xfaFont.size || 10; const lineHeight = pdfFont.lineHeight ? Math.max(real ? 0 : 1.2, pdfFont.lineHeight) : 1.2; const lineGap = pdfFont.lineGap === undefined ? 0.2 : pdfFont.lineGap; return { lineHeight: lineHeight * size, lineGap: lineGap * size, lineNoGap: Math.max(1, lineHeight - lineGap) * size }; } ;// CONCATENATED MODULE: ./src/core/xfa/text.js const WIDTH_FACTOR = 1.02; class FontInfo { constructor(xfaFont, margin, lineHeight, fontFinder) { this.lineHeight = lineHeight; this.paraMargin = margin || { top: 0, bottom: 0, left: 0, right: 0 }; if (!xfaFont) { [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); return; } this.xfaFont = { typeface: xfaFont.typeface, posture: xfaFont.posture, weight: xfaFont.weight, size: xfaFont.size, letterSpacing: xfaFont.letterSpacing }; const typeface = fontFinder.find(xfaFont.typeface); if (!typeface) { [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); return; } this.pdfFont = selectFont(xfaFont, typeface); if (!this.pdfFont) { [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); } } defaultFont(fontFinder) { const font = fontFinder.find("Helvetica", false) || fontFinder.find("Myriad Pro", false) || fontFinder.find("Arial", false) || fontFinder.getDefault(); if (font?.regular) { const pdfFont = font.regular; const info = pdfFont.cssFontInfo; const xfaFont = { typeface: info.fontFamily, posture: "normal", weight: "normal", size: 10, letterSpacing: 0 }; return [pdfFont, xfaFont]; } const xfaFont = { typeface: "Courier", posture: "normal", weight: "normal", size: 10, letterSpacing: 0 }; return [null, xfaFont]; } } class FontSelector { constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder) { this.fontFinder = fontFinder; this.stack = [new FontInfo(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder)]; } pushData(xfaFont, margin, lineHeight) { const lastFont = this.stack.at(-1); for (const name of ["typeface", "posture", "weight", "size", "letterSpacing"]) { if (!xfaFont[name]) { xfaFont[name] = lastFont.xfaFont[name]; } } for (const name of ["top", "bottom", "left", "right"]) { if (isNaN(margin[name])) { margin[name] = lastFont.paraMargin[name]; } } const fontInfo = new FontInfo(xfaFont, margin, lineHeight || lastFont.lineHeight, this.fontFinder); if (!fontInfo.pdfFont) { fontInfo.pdfFont = lastFont.pdfFont; } this.stack.push(fontInfo); } popFont() { this.stack.pop(); } topFont() { return this.stack.at(-1); } } class TextMeasure { constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts) { this.glyphs = []; this.fontSelector = new FontSelector(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts); this.extraHeight = 0; } pushData(xfaFont, margin, lineHeight) { this.fontSelector.pushData(xfaFont, margin, lineHeight); } popFont(xfaFont) { return this.fontSelector.popFont(); } addPara() { const lastFont = this.fontSelector.topFont(); this.extraHeight += lastFont.paraMargin.top + lastFont.paraMargin.bottom; } addString(str) { if (!str) { return; } const lastFont = this.fontSelector.topFont(); const fontSize = lastFont.xfaFont.size; if (lastFont.pdfFont) { const letterSpacing = lastFont.xfaFont.letterSpacing; const pdfFont = lastFont.pdfFont; const fontLineHeight = pdfFont.lineHeight || 1.2; const lineHeight = lastFont.lineHeight || Math.max(1.2, fontLineHeight) * fontSize; const lineGap = pdfFont.lineGap === undefined ? 0.2 : pdfFont.lineGap; const noGap = fontLineHeight - lineGap; const firstLineHeight = Math.max(1, noGap) * fontSize; const scale = fontSize / 1000; const fallbackWidth = pdfFont.defaultWidth || pdfFont.charsToGlyphs(" ")[0].width; for (const line of str.split(/[\u2029\n]/)) { const encodedLine = pdfFont.encodeString(line).join(""); const glyphs = pdfFont.charsToGlyphs(encodedLine); for (const glyph of glyphs) { const width = glyph.width || fallbackWidth; this.glyphs.push([width * scale + letterSpacing, lineHeight, firstLineHeight, glyph.unicode, false]); } this.glyphs.push([0, 0, 0, "\n", true]); } this.glyphs.pop(); return; } for (const line of str.split(/[\u2029\n]/)) { for (const char of line.split("")) { this.glyphs.push([fontSize, 1.2 * fontSize, fontSize, char, false]); } this.glyphs.push([0, 0, 0, "\n", true]); } this.glyphs.pop(); } compute(maxWidth) { let lastSpacePos = -1, lastSpaceWidth = 0, width = 0, height = 0, currentLineWidth = 0, currentLineHeight = 0; let isBroken = false; let isFirstLine = true; for (let i = 0, ii = this.glyphs.length; i < ii; i++) { const [glyphWidth, lineHeight, firstLineHeight, char, isEOL] = this.glyphs[i]; const isSpace = char === " "; const glyphHeight = isFirstLine ? firstLineHeight : lineHeight; if (isEOL) { width = Math.max(width, currentLineWidth); currentLineWidth = 0; height += currentLineHeight; currentLineHeight = glyphHeight; lastSpacePos = -1; lastSpaceWidth = 0; isFirstLine = false; continue; } if (isSpace) { if (currentLineWidth + glyphWidth > maxWidth) { width = Math.max(width, currentLineWidth); currentLineWidth = 0; height += currentLineHeight; currentLineHeight = glyphHeight; lastSpacePos = -1; lastSpaceWidth = 0; isBroken = true; isFirstLine = false; } else { currentLineHeight = Math.max(glyphHeight, currentLineHeight); lastSpaceWidth = currentLineWidth; currentLineWidth += glyphWidth; lastSpacePos = i; } continue; } if (currentLineWidth + glyphWidth > maxWidth) { height += currentLineHeight; currentLineHeight = glyphHeight; if (lastSpacePos !== -1) { i = lastSpacePos; width = Math.max(width, lastSpaceWidth); currentLineWidth = 0; lastSpacePos = -1; lastSpaceWidth = 0; } else { width = Math.max(width, currentLineWidth); currentLineWidth = glyphWidth; } isBroken = true; isFirstLine = false; continue; } currentLineWidth += glyphWidth; currentLineHeight = Math.max(glyphHeight, currentLineHeight); } width = Math.max(width, currentLineWidth); height += currentLineHeight + this.extraHeight; return { width: WIDTH_FACTOR * width, height, isBroken }; } } ;// CONCATENATED MODULE: ./src/core/xfa/som.js const namePattern = /^[^.[]+/; const indexPattern = /^[^\]]+/; const operators = { dot: 0, dotDot: 1, dotHash: 2, dotBracket: 3, dotParen: 4 }; const shortcuts = new Map([["$data", (root, current) => root.datasets ? root.datasets.data : root], ["$record", (root, current) => (root.datasets ? root.datasets.data : root)[$getChildren]()[0]], ["$template", (root, current) => root.template], ["$connectionSet", (root, current) => root.connectionSet], ["$form", (root, current) => root.form], ["$layout", (root, current) => root.layout], ["$host", (root, current) => root.host], ["$dataWindow", (root, current) => root.dataWindow], ["$event", (root, current) => root.event], ["!", (root, current) => root.datasets], ["$xfa", (root, current) => root], ["xfa", (root, current) => root], ["$", (root, current) => current]]); const somCache = new WeakMap(); function parseIndex(index) { index = index.trim(); if (index === "*") { return Infinity; } return parseInt(index, 10) || 0; } function parseExpression(expr, dotDotAllowed, noExpr = true) { let match = expr.match(namePattern); if (!match) { return null; } let [name] = match; const parsed = [{ name, cacheName: "." + name, index: 0, js: null, formCalc: null, operator: operators.dot }]; let pos = name.length; while (pos < expr.length) { const spos = pos; const char = expr.charAt(pos++); if (char === "[") { match = expr.slice(pos).match(indexPattern); if (!match) { warn("XFA - Invalid index in SOM expression"); return null; } parsed.at(-1).index = parseIndex(match[0]); pos += match[0].length + 1; continue; } let operator; switch (expr.charAt(pos)) { case ".": if (!dotDotAllowed) { return null; } pos++; operator = operators.dotDot; break; case "#": pos++; operator = operators.dotHash; break; case "[": if (noExpr) { warn("XFA - SOM expression contains a FormCalc subexpression which is not supported for now."); return null; } operator = operators.dotBracket; break; case "(": if (noExpr) { warn("XFA - SOM expression contains a JavaScript subexpression which is not supported for now."); return null; } operator = operators.dotParen; break; default: operator = operators.dot; break; } match = expr.slice(pos).match(namePattern); if (!match) { break; } [name] = match; pos += name.length; parsed.push({ name, cacheName: expr.slice(spos, pos), operator, index: 0, js: null, formCalc: null }); } return parsed; } function searchNode(root, container, expr, dotDotAllowed = true, useCache = true) { const parsed = parseExpression(expr, dotDotAllowed); if (!parsed) { return null; } const fn = shortcuts.get(parsed[0].name); let i = 0; let isQualified; if (fn) { isQualified = true; root = [fn(root, container)]; i = 1; } else { isQualified = container === null; root = [container || root]; } for (let ii = parsed.length; i < ii; i++) { const { name, cacheName, operator, index } = parsed[i]; const nodes = []; for (const node of root) { if (!node.isXFAObject) { continue; } let children, cached; if (useCache) { cached = somCache.get(node); if (!cached) { cached = new Map(); somCache.set(node, cached); } children = cached.get(cacheName); } if (!children) { switch (operator) { case operators.dot: children = node[$getChildrenByName](name, false); break; case operators.dotDot: children = node[$getChildrenByName](name, true); break; case operators.dotHash: children = node[$getChildrenByClass](name); children = children.isXFAObjectArray ? children.children : [children]; break; default: break; } if (useCache) { cached.set(cacheName, children); } } if (children.length > 0) { nodes.push(children); } } if (nodes.length === 0 && !isQualified && i === 0) { const parent = container[$getParent](); container = parent; if (!container) { return null; } i = -1; root = [container]; continue; } root = isFinite(index) ? nodes.filter(node => index < node.length).map(node => node[index]) : nodes.flat(); } if (root.length === 0) { return null; } return root; } function createDataNode(root, container, expr) { const parsed = parseExpression(expr); if (!parsed) { return null; } if (parsed.some(x => x.operator === operators.dotDot)) { return null; } const fn = shortcuts.get(parsed[0].name); let i = 0; if (fn) { root = fn(root, container); i = 1; } else { root = container || root; } for (let ii = parsed.length; i < ii; i++) { const { name, operator, index } = parsed[i]; if (!isFinite(index)) { parsed[i].index = 0; return root.createNodes(parsed.slice(i)); } let children; switch (operator) { case operators.dot: children = root[$getChildrenByName](name, false); break; case operators.dotDot: children = root[$getChildrenByName](name, true); break; case operators.dotHash: children = root[$getChildrenByClass](name); children = children.isXFAObjectArray ? children.children : [children]; break; default: break; } if (children.length === 0) { return root.createNodes(parsed.slice(i)); } if (index < children.length) { const child = children[index]; if (!child.isXFAObject) { warn(`XFA - Cannot create a node.`); return null; } root = child; } else { parsed[i].index = index - children.length; return root.createNodes(parsed.slice(i)); } } return null; } ;// CONCATENATED MODULE: ./src/core/xfa/xfa_object.js const _applyPrototype = Symbol(); const _attributes = Symbol(); const _attributeNames = Symbol(); const _children = Symbol("_children"); const _cloneAttribute = Symbol(); const _dataValue = Symbol(); const _defaultValue = Symbol(); const _filteredChildrenGenerator = Symbol(); const _getPrototype = Symbol(); const _getUnsetAttributes = Symbol(); const _hasChildren = Symbol(); const _max = Symbol(); const _options = Symbol(); const _parent = Symbol("parent"); const _resolvePrototypesHelper = Symbol(); const _setAttributes = Symbol(); const _validator = Symbol(); let uid = 0; const NS_DATASETS = NamespaceIds.datasets.id; class XFAObject { constructor(nsId, name, hasChildren = false) { this[$namespaceId] = nsId; this[$nodeName] = name; this[_hasChildren] = hasChildren; this[_parent] = null; this[_children] = []; this[$uid] = `${name}${uid++}`; this[$globalData] = null; } get isXFAObject() { return true; } get isXFAObjectArray() { return false; } createNodes(path) { let root = this, node = null; for (const { name, index } of path) { for (let i = 0, ii = isFinite(index) ? index : 0; i <= ii; i++) { const nsId = root[$namespaceId] === NS_DATASETS ? -1 : root[$namespaceId]; node = new XmlObject(nsId, name); root[$appendChild](node); } root = node; } return node; } [$onChild](child) { if (!this[_hasChildren] || !this[$onChildCheck](child)) { return false; } const name = child[$nodeName]; const node = this[name]; if (node instanceof XFAObjectArray) { if (node.push(child)) { this[$appendChild](child); return true; } } else { if (node !== null) { this[$removeChild](node); } this[name] = child; this[$appendChild](child); return true; } let id = ""; if (this.id) { id = ` (id: ${this.id})`; } else if (this.name) { id = ` (name: ${this.name} ${this.h.value})`; } warn(`XFA - node "${this[$nodeName]}"${id} has already enough "${name}"!`); return false; } [$onChildCheck](child) { return this.hasOwnProperty(child[$nodeName]) && child[$namespaceId] === this[$namespaceId]; } [$isNsAgnostic]() { return false; } [$acceptWhitespace]() { return false; } [$isCDATAXml]() { return false; } [$isBindable]() { return false; } [$popPara]() { if (this.para) { this[$getTemplateRoot]()[$extra].paraStack.pop(); } } [$pushPara]() { this[$getTemplateRoot]()[$extra].paraStack.push(this.para); } [$setId](ids) { if (this.id && this[$namespaceId] === NamespaceIds.template.id) { ids.set(this.id, this); } } [$getTemplateRoot]() { return this[$globalData].template; } [$isSplittable]() { return false; } [$isThereMoreWidth]() { return false; } [$appendChild](child) { child[_parent] = this; this[_children].push(child); if (!child[$globalData] && this[$globalData]) { child[$globalData] = this[$globalData]; } } [$removeChild](child) { const i = this[_children].indexOf(child); this[_children].splice(i, 1); } [$hasSettableValue]() { return this.hasOwnProperty("value"); } [$setValue](_) {} [$onText](_) {} [$finalize]() {} [$clean](builder) { delete this[_hasChildren]; if (this[$cleanup]) { builder.clean(this[$cleanup]); delete this[$cleanup]; } } [$indexOf](child) { return this[_children].indexOf(child); } [$insertAt](i, child) { child[_parent] = this; this[_children].splice(i, 0, child); if (!child[$globalData] && this[$globalData]) { child[$globalData] = this[$globalData]; } } [$isTransparent]() { return !this.name; } [$lastAttribute]() { return ""; } [$text]() { if (this[_children].length === 0) { return this[$content]; } return this[_children].map(c => c[$text]()).join(""); } get [_attributeNames]() { const proto = Object.getPrototypeOf(this); if (!proto._attributes) { const attributes = proto._attributes = new Set(); for (const name of Object.getOwnPropertyNames(this)) { if (this[name] === null || this[name] instanceof XFAObject || this[name] instanceof XFAObjectArray) { break; } attributes.add(name); } } return shadow(this, _attributeNames, proto._attributes); } [$isDescendent](parent) { let node = this; while (node) { if (node === parent) { return true; } node = node[$getParent](); } return false; } [$getParent]() { return this[_parent]; } [$getSubformParent]() { return this[$getParent](); } [$getChildren](name = null) { if (!name) { return this[_children]; } return this[name]; } [$dump]() { const dumped = Object.create(null); if (this[$content]) { dumped.$content = this[$content]; } for (const name of Object.getOwnPropertyNames(this)) { const value = this[name]; if (value === null) { continue; } if (value instanceof XFAObject) { dumped[name] = value[$dump](); } else if (value instanceof XFAObjectArray) { if (!value.isEmpty()) { dumped[name] = value.dump(); } } else { dumped[name] = value; } } return dumped; } [$toStyle]() { return null; } [$toHTML]() { return HTMLResult.EMPTY; } *[$getContainedChildren]() { for (const node of this[$getChildren]()) { yield node; } } *[_filteredChildrenGenerator](filter, include) { for (const node of this[$getContainedChildren]()) { if (!filter || include === filter.has(node[$nodeName])) { const availableSpace = this[$getAvailableSpace](); const res = node[$toHTML](availableSpace); if (!res.success) { this[$extra].failingNode = node; } yield res; } } } [$flushHTML]() { return null; } [$addHTML](html, bbox) { this[$extra].children.push(html); } [$getAvailableSpace]() {} [$childrenToHTML]({ filter = null, include = true }) { if (!this[$extra].generator) { this[$extra].generator = this[_filteredChildrenGenerator](filter, include); } else { const availableSpace = this[$getAvailableSpace](); const res = this[$extra].failingNode[$toHTML](availableSpace); if (!res.success) { return res; } if (res.html) { this[$addHTML](res.html, res.bbox); } delete this[$extra].failingNode; } while (true) { const gen = this[$extra].generator.next(); if (gen.done) { break; } const res = gen.value; if (!res.success) { return res; } if (res.html) { this[$addHTML](res.html, res.bbox); } } this[$extra].generator = null; return HTMLResult.EMPTY; } [$setSetAttributes](attributes) { this[_setAttributes] = new Set(Object.keys(attributes)); } [_getUnsetAttributes](protoAttributes) { const allAttr = this[_attributeNames]; const setAttr = this[_setAttributes]; return [...protoAttributes].filter(x => allAttr.has(x) && !setAttr.has(x)); } [$resolvePrototypes](ids, ancestors = new Set()) { for (const child of this[_children]) { child[_resolvePrototypesHelper](ids, ancestors); } } [_resolvePrototypesHelper](ids, ancestors) { const proto = this[_getPrototype](ids, ancestors); if (proto) { this[_applyPrototype](proto, ids, ancestors); } else { this[$resolvePrototypes](ids, ancestors); } } [_getPrototype](ids, ancestors) { const { use, usehref } = this; if (!use && !usehref) { return null; } let proto = null; let somExpression = null; let id = null; let ref = use; if (usehref) { ref = usehref; if (usehref.startsWith("#som(") && usehref.endsWith(")")) { somExpression = usehref.slice("#som(".length, -1); } else if (usehref.startsWith(".#som(") && usehref.endsWith(")")) { somExpression = usehref.slice(".#som(".length, -1); } else if (usehref.startsWith("#")) { id = usehref.slice(1); } else if (usehref.startsWith(".#")) { id = usehref.slice(2); } } else if (use.startsWith("#")) { id = use.slice(1); } else { somExpression = use; } this.use = this.usehref = ""; if (id) { proto = ids.get(id); } else { proto = searchNode(ids.get($root), this, somExpression, true, false); if (proto) { proto = proto[0]; } } if (!proto) { warn(`XFA - Invalid prototype reference: ${ref}.`); return null; } if (proto[$nodeName] !== this[$nodeName]) { warn(`XFA - Incompatible prototype: ${proto[$nodeName]} !== ${this[$nodeName]}.`); return null; } if (ancestors.has(proto)) { warn(`XFA - Cycle detected in prototypes use.`); return null; } ancestors.add(proto); const protoProto = proto[_getPrototype](ids, ancestors); if (protoProto) { proto[_applyPrototype](protoProto, ids, ancestors); } proto[$resolvePrototypes](ids, ancestors); ancestors.delete(proto); return proto; } [_applyPrototype](proto, ids, ancestors) { if (ancestors.has(proto)) { warn(`XFA - Cycle detected in prototypes use.`); return; } if (!this[$content] && proto[$content]) { this[$content] = proto[$content]; } const newAncestors = new Set(ancestors); newAncestors.add(proto); for (const unsetAttrName of this[_getUnsetAttributes](proto[_setAttributes])) { this[unsetAttrName] = proto[unsetAttrName]; if (this[_setAttributes]) { this[_setAttributes].add(unsetAttrName); } } for (const name of Object.getOwnPropertyNames(this)) { if (this[_attributeNames].has(name)) { continue; } const value = this[name]; const protoValue = proto[name]; if (value instanceof XFAObjectArray) { for (const child of value[_children]) { child[_resolvePrototypesHelper](ids, ancestors); } for (let i = value[_children].length, ii = protoValue[_children].length; i < ii; i++) { const child = proto[_children][i][$clone](); if (value.push(child)) { child[_parent] = this; this[_children].push(child); child[_resolvePrototypesHelper](ids, ancestors); } else { break; } } continue; } if (value !== null) { value[$resolvePrototypes](ids, ancestors); if (protoValue) { value[_applyPrototype](protoValue, ids, ancestors); } continue; } if (protoValue !== null) { const child = protoValue[$clone](); child[_parent] = this; this[name] = child; this[_children].push(child); child[_resolvePrototypesHelper](ids, ancestors); } } } static [_cloneAttribute](obj) { if (Array.isArray(obj)) { return obj.map(x => XFAObject[_cloneAttribute](x)); } if (typeof obj === "object" && obj !== null) { return Object.assign({}, obj); } return obj; } [$clone]() { const clone = Object.create(Object.getPrototypeOf(this)); for (const $symbol of Object.getOwnPropertySymbols(this)) { try { clone[$symbol] = this[$symbol]; } catch { shadow(clone, $symbol, this[$symbol]); } } clone[$uid] = `${clone[$nodeName]}${uid++}`; clone[_children] = []; for (const name of Object.getOwnPropertyNames(this)) { if (this[_attributeNames].has(name)) { clone[name] = XFAObject[_cloneAttribute](this[name]); continue; } const value = this[name]; clone[name] = value instanceof XFAObjectArray ? new XFAObjectArray(value[_max]) : null; } for (const child of this[_children]) { const name = child[$nodeName]; const clonedChild = child[$clone](); clone[_children].push(clonedChild); clonedChild[_parent] = clone; if (clone[name] === null) { clone[name] = clonedChild; } else { clone[name][_children].push(clonedChild); } } return clone; } [$getChildren](name = null) { if (!name) { return this[_children]; } return this[_children].filter(c => c[$nodeName] === name); } [$getChildrenByClass](name) { return this[name]; } [$getChildrenByName](name, allTransparent, first = true) { return Array.from(this[$getChildrenByNameIt](name, allTransparent, first)); } *[$getChildrenByNameIt](name, allTransparent, first = true) { if (name === "parent") { yield this[_parent]; return; } for (const child of this[_children]) { if (child[$nodeName] === name) { yield child; } if (child.name === name) { yield child; } if (allTransparent || child[$isTransparent]()) { yield* child[$getChildrenByNameIt](name, allTransparent, false); } } if (first && this[_attributeNames].has(name)) { yield new XFAAttribute(this, name, this[name]); } } } class XFAObjectArray { constructor(max = Infinity) { this[_max] = max; this[_children] = []; } get isXFAObject() { return false; } get isXFAObjectArray() { return true; } push(child) { const len = this[_children].length; if (len <= this[_max]) { this[_children].push(child); return true; } warn(`XFA - node "${child[$nodeName]}" accepts no more than ${this[_max]} children`); return false; } isEmpty() { return this[_children].length === 0; } dump() { return this[_children].length === 1 ? this[_children][0][$dump]() : this[_children].map(x => x[$dump]()); } [$clone]() { const clone = new XFAObjectArray(this[_max]); clone[_children] = this[_children].map(c => c[$clone]()); return clone; } get children() { return this[_children]; } clear() { this[_children].length = 0; } } class XFAAttribute { constructor(node, name, value) { this[_parent] = node; this[$nodeName] = name; this[$content] = value; this[$consumed] = false; this[$uid] = `attribute${uid++}`; } [$getParent]() { return this[_parent]; } [$isDataValue]() { return true; } [$getDataValue]() { return this[$content].trim(); } [$setValue](value) { value = value.value || ""; this[$content] = value.toString(); } [$text]() { return this[$content]; } [$isDescendent](parent) { return this[_parent] === parent || this[_parent][$isDescendent](parent); } } class XmlObject extends XFAObject { constructor(nsId, name, attributes = {}) { super(nsId, name); this[$content] = ""; this[_dataValue] = null; if (name !== "#text") { const map = new Map(); this[_attributes] = map; for (const [attrName, value] of Object.entries(attributes)) { map.set(attrName, new XFAAttribute(this, attrName, value)); } if (attributes.hasOwnProperty($nsAttributes)) { const dataNode = attributes[$nsAttributes].xfa.dataNode; if (dataNode !== undefined) { if (dataNode === "dataGroup") { this[_dataValue] = false; } else if (dataNode === "dataValue") { this[_dataValue] = true; } } } } this[$consumed] = false; } [$toString](buf) { const tagName = this[$nodeName]; if (tagName === "#text") { buf.push(encodeToXmlString(this[$content])); return; } const utf8TagName = utf8StringToString(tagName); const prefix = this[$namespaceId] === NS_DATASETS ? "xfa:" : ""; buf.push(`<${prefix}${utf8TagName}`); for (const [name, value] of this[_attributes].entries()) { const utf8Name = utf8StringToString(name); buf.push(` ${utf8Name}="${encodeToXmlString(value[$content])}"`); } if (this[_dataValue] !== null) { if (this[_dataValue]) { buf.push(` xfa:dataNode="dataValue"`); } else { buf.push(` xfa:dataNode="dataGroup"`); } } if (!this[$content] && this[_children].length === 0) { buf.push("/>"); return; } buf.push(">"); if (this[$content]) { if (typeof this[$content] === "string") { buf.push(encodeToXmlString(this[$content])); } else { this[$content][$toString](buf); } } else { for (const child of this[_children]) { child[$toString](buf); } } buf.push(`</${prefix}${utf8TagName}>`); } [$onChild](child) { if (this[$content]) { const node = new XmlObject(this[$namespaceId], "#text"); this[$appendChild](node); node[$content] = this[$content]; this[$content] = ""; } this[$appendChild](child); return true; } [$onText](str) { this[$content] += str; } [$finalize]() { if (this[$content] && this[_children].length > 0) { const node = new XmlObject(this[$namespaceId], "#text"); this[$appendChild](node); node[$content] = this[$content]; delete this[$content]; } } [$toHTML]() { if (this[$nodeName] === "#text") { return HTMLResult.success({ name: "#text", value: this[$content] }); } return HTMLResult.EMPTY; } [$getChildren](name = null) { if (!name) { return this[_children]; } return this[_children].filter(c => c[$nodeName] === name); } [$getAttributes]() { return this[_attributes]; } [$getChildrenByClass](name) { const value = this[_attributes].get(name); if (value !== undefined) { return value; } return this[$getChildren](name); } *[$getChildrenByNameIt](name, allTransparent) { const value = this[_attributes].get(name); if (value) { yield value; } for (const child of this[_children]) { if (child[$nodeName] === name) { yield child; } if (allTransparent) { yield* child[$getChildrenByNameIt](name, allTransparent); } } } *[$getAttributeIt](name, skipConsumed) { const value = this[_attributes].get(name); if (value && (!skipConsumed || !value[$consumed])) { yield value; } for (const child of this[_children]) { yield* child[$getAttributeIt](name, skipConsumed); } } *[$getRealChildrenByNameIt](name, allTransparent, skipConsumed) { for (const child of this[_children]) { if (child[$nodeName] === name && (!skipConsumed || !child[$consumed])) { yield child; } if (allTransparent) { yield* child[$getRealChildrenByNameIt](name, allTransparent, skipConsumed); } } } [$isDataValue]() { if (this[_dataValue] === null) { return this[_children].length === 0 || this[_children][0][$namespaceId] === NamespaceIds.xhtml.id; } return this[_dataValue]; } [$getDataValue]() { if (this[_dataValue] === null) { if (this[_children].length === 0) { return this[$content].trim(); } if (this[_children][0][$namespaceId] === NamespaceIds.xhtml.id) { return this[_children][0][$text]().trim(); } return null; } return this[$content].trim(); } [$setValue](value) { value = value.value || ""; this[$content] = value.toString(); } [$dump](hasNS = false) { const dumped = Object.create(null); if (hasNS) { dumped.$ns = this[$namespaceId]; } if (this[$content]) { dumped.$content = this[$content]; } dumped.$name = this[$nodeName]; dumped.children = []; for (const child of this[_children]) { dumped.children.push(child[$dump](hasNS)); } dumped.attributes = Object.create(null); for (const [name, value] of this[_attributes]) { dumped.attributes[name] = value[$content]; } return dumped; } } class ContentObject extends XFAObject { constructor(nsId, name) { super(nsId, name); this[$content] = ""; } [$onText](text) { this[$content] += text; } [$finalize]() {} } class OptionObject extends ContentObject { constructor(nsId, name, options) { super(nsId, name); this[_options] = options; } [$finalize]() { this[$content] = getKeyword({ data: this[$content], defaultValue: this[_options][0], validate: k => this[_options].includes(k) }); } [$clean](builder) { super[$clean](builder); delete this[_options]; } } class StringObject extends ContentObject { [$finalize]() { this[$content] = this[$content].trim(); } } class IntegerObject extends ContentObject { constructor(nsId, name, defaultValue, validator) { super(nsId, name); this[_defaultValue] = defaultValue; this[_validator] = validator; } [$finalize]() { this[$content] = getInteger({ data: this[$content], defaultValue: this[_defaultValue], validate: this[_validator] }); } [$clean](builder) { super[$clean](builder); delete this[_defaultValue]; delete this[_validator]; } } class Option01 extends IntegerObject { constructor(nsId, name) { super(nsId, name, 0, n => n === 1); } } class Option10 extends IntegerObject { constructor(nsId, name) { super(nsId, name, 1, n => n === 0); } } ;// CONCATENATED MODULE: ./src/core/xfa/html_utils.js function measureToString(m) { if (typeof m === "string") { return "0px"; } return Number.isInteger(m) ? `${m}px` : `${m.toFixed(2)}px`; } const converters = { anchorType(node, style) { const parent = node[$getSubformParent](); if (!parent || parent.layout && parent.layout !== "position") { return; } if (!("transform" in style)) { style.transform = ""; } switch (node.anchorType) { case "bottomCenter": style.transform += "translate(-50%, -100%)"; break; case "bottomLeft": style.transform += "translate(0,-100%)"; break; case "bottomRight": style.transform += "translate(-100%,-100%)"; break; case "middleCenter": style.transform += "translate(-50%,-50%)"; break; case "middleLeft": style.transform += "translate(0,-50%)"; break; case "middleRight": style.transform += "translate(-100%,-50%)"; break; case "topCenter": style.transform += "translate(-50%,0)"; break; case "topRight": style.transform += "translate(-100%,0)"; break; } }, dimensions(node, style) { const parent = node[$getSubformParent](); let width = node.w; const height = node.h; if (parent.layout?.includes("row")) { const extra = parent[$extra]; const colSpan = node.colSpan; let w; if (colSpan === -1) { w = extra.columnWidths.slice(extra.currentColumn).reduce((a, x) => a + x, 0); extra.currentColumn = 0; } else { w = extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan).reduce((a, x) => a + x, 0); extra.currentColumn = (extra.currentColumn + node.colSpan) % extra.columnWidths.length; } if (!isNaN(w)) { width = node.w = w; } } style.width = width !== "" ? measureToString(width) : "auto"; style.height = height !== "" ? measureToString(height) : "auto"; }, position(node, style) { const parent = node[$getSubformParent](); if (parent?.layout && parent.layout !== "position") { return; } style.position = "absolute"; style.left = measureToString(node.x); style.top = measureToString(node.y); }, rotate(node, style) { if (node.rotate) { if (!("transform" in style)) { style.transform = ""; } style.transform += `rotate(-${node.rotate}deg)`; style.transformOrigin = "top left"; } }, presence(node, style) { switch (node.presence) { case "invisible": style.visibility = "hidden"; break; case "hidden": case "inactive": style.display = "none"; break; } }, hAlign(node, style) { if (node[$nodeName] === "para") { switch (node.hAlign) { case "justifyAll": style.textAlign = "justify-all"; break; case "radix": style.textAlign = "left"; break; default: style.textAlign = node.hAlign; } } else { switch (node.hAlign) { case "left": style.alignSelf = "start"; break; case "center": style.alignSelf = "center"; break; case "right": style.alignSelf = "end"; break; } } }, margin(node, style) { if (node.margin) { style.margin = node.margin[$toStyle]().margin; } } }; function setMinMaxDimensions(node, style) { const parent = node[$getSubformParent](); if (parent.layout === "position") { if (node.minW > 0) { style.minWidth = measureToString(node.minW); } if (node.maxW > 0) { style.maxWidth = measureToString(node.maxW); } if (node.minH > 0) { style.minHeight = measureToString(node.minH); } if (node.maxH > 0) { style.maxHeight = measureToString(node.maxH); } } } function layoutText(text, xfaFont, margin, lineHeight, fontFinder, width) { const measure = new TextMeasure(xfaFont, margin, lineHeight, fontFinder); if (typeof text === "string") { measure.addString(text); } else { text[$pushGlyphs](measure); } return measure.compute(width); } function layoutNode(node, availableSpace) { let height = null; let width = null; let isBroken = false; if ((!node.w || !node.h) && node.value) { let marginH = 0; let marginV = 0; if (node.margin) { marginH = node.margin.leftInset + node.margin.rightInset; marginV = node.margin.topInset + node.margin.bottomInset; } let lineHeight = null; let margin = null; if (node.para) { margin = Object.create(null); lineHeight = node.para.lineHeight === "" ? null : node.para.lineHeight; margin.top = node.para.spaceAbove === "" ? 0 : node.para.spaceAbove; margin.bottom = node.para.spaceBelow === "" ? 0 : node.para.spaceBelow; margin.left = node.para.marginLeft === "" ? 0 : node.para.marginLeft; margin.right = node.para.marginRight === "" ? 0 : node.para.marginRight; } let font = node.font; if (!font) { const root = node[$getTemplateRoot](); let parent = node[$getParent](); while (parent && parent !== root) { if (parent.font) { font = parent.font; break; } parent = parent[$getParent](); } } const maxWidth = (node.w || availableSpace.width) - marginH; const fontFinder = node[$globalData].fontFinder; if (node.value.exData && node.value.exData[$content] && node.value.exData.contentType === "text/html") { const res = layoutText(node.value.exData[$content], font, margin, lineHeight, fontFinder, maxWidth); width = res.width; height = res.height; isBroken = res.isBroken; } else { const text = node.value[$text](); if (text) { const res = layoutText(text, font, margin, lineHeight, fontFinder, maxWidth); width = res.width; height = res.height; isBroken = res.isBroken; } } if (width !== null && !node.w) { width += marginH; } if (height !== null && !node.h) { height += marginV; } } return { w: width, h: height, isBroken }; } function computeBbox(node, html, availableSpace) { let bbox; if (node.w !== "" && node.h !== "") { bbox = [node.x, node.y, node.w, node.h]; } else { if (!availableSpace) { return null; } let width = node.w; if (width === "") { if (node.maxW === 0) { const parent = node[$getSubformParent](); width = parent.layout === "position" && parent.w !== "" ? 0 : node.minW; } else { width = Math.min(node.maxW, availableSpace.width); } html.attributes.style.width = measureToString(width); } let height = node.h; if (height === "") { if (node.maxH === 0) { const parent = node[$getSubformParent](); height = parent.layout === "position" && parent.h !== "" ? 0 : node.minH; } else { height = Math.min(node.maxH, availableSpace.height); } html.attributes.style.height = measureToString(height); } bbox = [node.x, node.y, width, height]; } return bbox; } function fixDimensions(node) { const parent = node[$getSubformParent](); if (parent.layout?.includes("row")) { const extra = parent[$extra]; const colSpan = node.colSpan; let width; if (colSpan === -1) { width = extra.columnWidths.slice(extra.currentColumn).reduce((a, w) => a + w, 0); } else { width = extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan).reduce((a, w) => a + w, 0); } if (!isNaN(width)) { node.w = width; } } if (parent.layout && parent.layout !== "position") { node.x = node.y = 0; } if (node.layout === "table") { if (node.w === "" && Array.isArray(node.columnWidths)) { node.w = node.columnWidths.reduce((a, x) => a + x, 0); } } } function layoutClass(node) { switch (node.layout) { case "position": return "xfaPosition"; case "lr-tb": return "xfaLrTb"; case "rl-row": return "xfaRlRow"; case "rl-tb": return "xfaRlTb"; case "row": return "xfaRow"; case "table": return "xfaTable"; case "tb": return "xfaTb"; default: return "xfaPosition"; } } function toStyle(node, ...names) { const style = Object.create(null); for (const name of names) { const value = node[name]; if (value === null) { continue; } if (converters.hasOwnProperty(name)) { converters[name](node, style); continue; } if (value instanceof XFAObject) { const newStyle = value[$toStyle](); if (newStyle) { Object.assign(style, newStyle); } else { warn(`(DEBUG) - XFA - style for ${name} not implemented yet`); } } } return style; } function createWrapper(node, html) { const { attributes } = html; const { style } = attributes; const wrapper = { name: "div", attributes: { class: ["xfaWrapper"], style: Object.create(null) }, children: [] }; attributes.class.push("xfaWrapped"); if (node.border) { const { widths, insets } = node.border[$extra]; let width, height; let top = insets[0]; let left = insets[3]; const insetsH = insets[0] + insets[2]; const insetsW = insets[1] + insets[3]; switch (node.border.hand) { case "even": top -= widths[0] / 2; left -= widths[3] / 2; width = `calc(100% + ${(widths[1] + widths[3]) / 2 - insetsW}px)`; height = `calc(100% + ${(widths[0] + widths[2]) / 2 - insetsH}px)`; break; case "left": top -= widths[0]; left -= widths[3]; width = `calc(100% + ${widths[1] + widths[3] - insetsW}px)`; height = `calc(100% + ${widths[0] + widths[2] - insetsH}px)`; break; case "right": width = insetsW ? `calc(100% - ${insetsW}px)` : "100%"; height = insetsH ? `calc(100% - ${insetsH}px)` : "100%"; break; } const classNames = ["xfaBorder"]; if (isPrintOnly(node.border)) { classNames.push("xfaPrintOnly"); } const border = { name: "div", attributes: { class: classNames, style: { top: `${top}px`, left: `${left}px`, width, height } }, children: [] }; for (const key of ["border", "borderWidth", "borderColor", "borderRadius", "borderStyle"]) { if (style[key] !== undefined) { border.attributes.style[key] = style[key]; delete style[key]; } } wrapper.children.push(border, html); } else { wrapper.children.push(html); } for (const key of ["background", "backgroundClip", "top", "left", "width", "height", "minWidth", "minHeight", "maxWidth", "maxHeight", "transform", "transformOrigin", "visibility"]) { if (style[key] !== undefined) { wrapper.attributes.style[key] = style[key]; delete style[key]; } } wrapper.attributes.style.position = style.position === "absolute" ? "absolute" : "relative"; delete style.position; if (style.alignSelf) { wrapper.attributes.style.alignSelf = style.alignSelf; delete style.alignSelf; } return wrapper; } function fixTextIndent(styles) { const indent = getMeasurement(styles.textIndent, "0px"); if (indent >= 0) { return; } const align = styles.textAlign === "right" ? "right" : "left"; const name = "padding" + (align === "left" ? "Left" : "Right"); const padding = getMeasurement(styles[name], "0px"); styles[name] = `${padding - indent}px`; } function setAccess(node, classNames) { switch (node.access) { case "nonInteractive": classNames.push("xfaNonInteractive"); break; case "readOnly": classNames.push("xfaReadOnly"); break; case "protected": classNames.push("xfaDisabled"); break; } } function isPrintOnly(node) { return node.relevant.length > 0 && !node.relevant[0].excluded && node.relevant[0].viewname === "print"; } function getCurrentPara(node) { const stack = node[$getTemplateRoot]()[$extra].paraStack; return stack.length ? stack.at(-1) : null; } function setPara(node, nodeStyle, value) { if (value.attributes.class?.includes("xfaRich")) { if (nodeStyle) { if (node.h === "") { nodeStyle.height = "auto"; } if (node.w === "") { nodeStyle.width = "auto"; } } const para = getCurrentPara(node); if (para) { const valueStyle = value.attributes.style; valueStyle.display = "flex"; valueStyle.flexDirection = "column"; switch (para.vAlign) { case "top": valueStyle.justifyContent = "start"; break; case "bottom": valueStyle.justifyContent = "end"; break; case "middle": valueStyle.justifyContent = "center"; break; } const paraStyle = para[$toStyle](); for (const [key, val] of Object.entries(paraStyle)) { if (!(key in valueStyle)) { valueStyle[key] = val; } } } } } function setFontFamily(xfaFont, node, fontFinder, style) { if (!fontFinder) { delete style.fontFamily; return; } const name = stripQuotes(xfaFont.typeface); style.fontFamily = `"${name}"`; const typeface = fontFinder.find(name); if (typeface) { const { fontFamily } = typeface.regular.cssFontInfo; if (fontFamily !== name) { style.fontFamily = `"${fontFamily}"`; } const para = getCurrentPara(node); if (para && para.lineHeight !== "") { return; } if (style.lineHeight) { return; } const pdfFont = selectFont(xfaFont, typeface); if (pdfFont) { style.lineHeight = Math.max(1.2, pdfFont.lineHeight); } } } function fixURL(str) { const absoluteUrl = createValidAbsoluteUrl(str, null, { addDefaultProtocol: true, tryConvertEncoding: true }); return absoluteUrl ? absoluteUrl.href : null; } ;// CONCATENATED MODULE: ./src/core/xfa/layout.js function createLine(node, children) { return { name: "div", attributes: { class: [node.layout === "lr-tb" ? "xfaLr" : "xfaRl"] }, children }; } function flushHTML(node) { if (!node[$extra]) { return null; } const attributes = node[$extra].attributes; const html = { name: "div", attributes, children: node[$extra].children }; if (node[$extra].failingNode) { const htmlFromFailing = node[$extra].failingNode[$flushHTML](); if (htmlFromFailing) { if (node.layout.endsWith("-tb")) { html.children.push(createLine(node, [htmlFromFailing])); } else { html.children.push(htmlFromFailing); } } } if (html.children.length === 0) { return null; } return html; } function addHTML(node, html, bbox) { const extra = node[$extra]; const availableSpace = extra.availableSpace; const [x, y, w, h] = bbox; switch (node.layout) { case "position": { extra.width = Math.max(extra.width, x + w); extra.height = Math.max(extra.height, y + h); extra.children.push(html); break; } case "lr-tb": case "rl-tb": if (!extra.line || extra.attempt === 1) { extra.line = createLine(node, []); extra.children.push(extra.line); extra.numberInLine = 0; } extra.numberInLine += 1; extra.line.children.push(html); if (extra.attempt === 0) { extra.currentWidth += w; extra.height = Math.max(extra.height, extra.prevHeight + h); } else { extra.currentWidth = w; extra.prevHeight = extra.height; extra.height += h; extra.attempt = 0; } extra.width = Math.max(extra.width, extra.currentWidth); break; case "rl-row": case "row": { extra.children.push(html); extra.width += w; extra.height = Math.max(extra.height, h); const height = measureToString(extra.height); for (const child of extra.children) { child.attributes.style.height = height; } break; } case "table": { extra.width = Math.min(availableSpace.width, Math.max(extra.width, w)); extra.height += h; extra.children.push(html); break; } case "tb": { extra.width = Math.min(availableSpace.width, Math.max(extra.width, w)); extra.height += h; extra.children.push(html); break; } } } function getAvailableSpace(node) { const availableSpace = node[$extra].availableSpace; const marginV = node.margin ? node.margin.topInset + node.margin.bottomInset : 0; const marginH = node.margin ? node.margin.leftInset + node.margin.rightInset : 0; switch (node.layout) { case "lr-tb": case "rl-tb": if (node[$extra].attempt === 0) { return { width: availableSpace.width - marginH - node[$extra].currentWidth, height: availableSpace.height - marginV - node[$extra].prevHeight }; } return { width: availableSpace.width - marginH, height: availableSpace.height - marginV - node[$extra].height }; case "rl-row": case "row": const width = node[$extra].columnWidths.slice(node[$extra].currentColumn).reduce((a, x) => a + x); return { width, height: availableSpace.height - marginH }; case "table": case "tb": return { width: availableSpace.width - marginH, height: availableSpace.height - marginV - node[$extra].height }; case "position": default: return availableSpace; } } function getTransformedBBox(node) { let w = node.w === "" ? NaN : node.w; let h = node.h === "" ? NaN : node.h; let [centerX, centerY] = [0, 0]; switch (node.anchorType || "") { case "bottomCenter": [centerX, centerY] = [w / 2, h]; break; case "bottomLeft": [centerX, centerY] = [0, h]; break; case "bottomRight": [centerX, centerY] = [w, h]; break; case "middleCenter": [centerX, centerY] = [w / 2, h / 2]; break; case "middleLeft": [centerX, centerY] = [0, h / 2]; break; case "middleRight": [centerX, centerY] = [w, h / 2]; break; case "topCenter": [centerX, centerY] = [w / 2, 0]; break; case "topRight": [centerX, centerY] = [w, 0]; break; } let x, y; switch (node.rotate || 0) { case 0: [x, y] = [-centerX, -centerY]; break; case 90: [x, y] = [-centerY, centerX]; [w, h] = [h, -w]; break; case 180: [x, y] = [centerX, centerY]; [w, h] = [-w, -h]; break; case 270: [x, y] = [centerY, -centerX]; [w, h] = [-h, w]; break; } return [node.x + x + Math.min(0, w), node.y + y + Math.min(0, h), Math.abs(w), Math.abs(h)]; } function checkDimensions(node, space) { if (node[$getTemplateRoot]()[$extra].firstUnsplittable === null) { return true; } if (node.w === 0 || node.h === 0) { return true; } const ERROR = 2; const parent = node[$getSubformParent](); const attempt = parent[$extra]?.attempt || 0; const [, y, w, h] = getTransformedBBox(node); switch (parent.layout) { case "lr-tb": case "rl-tb": if (attempt === 0) { if (!node[$getTemplateRoot]()[$extra].noLayoutFailure) { if (node.h !== "" && Math.round(h - space.height) > ERROR) { return false; } if (node.w !== "") { if (Math.round(w - space.width) <= ERROR) { return true; } if (parent[$extra].numberInLine === 0) { return space.height > ERROR; } return false; } return space.width > ERROR; } if (node.w !== "") { return Math.round(w - space.width) <= ERROR; } return space.width > ERROR; } if (node[$getTemplateRoot]()[$extra].noLayoutFailure) { return true; } if (node.h !== "" && Math.round(h - space.height) > ERROR) { return false; } if (node.w === "" || Math.round(w - space.width) <= ERROR) { return space.height > ERROR; } if (parent[$isThereMoreWidth]()) { return false; } return space.height > ERROR; case "table": case "tb": if (node[$getTemplateRoot]()[$extra].noLayoutFailure) { return true; } if (node.h !== "" && !node[$isSplittable]()) { return Math.round(h - space.height) <= ERROR; } if (node.w === "" || Math.round(w - space.width) <= ERROR) { return space.height > ERROR; } if (parent[$isThereMoreWidth]()) { return false; } return space.height > ERROR; case "position": if (node[$getTemplateRoot]()[$extra].noLayoutFailure) { return true; } if (node.h === "" || Math.round(h + y - space.height) <= ERROR) { return true; } const area = node[$getTemplateRoot]()[$extra].currentContentArea; return h + y > area.h; case "rl-row": case "row": if (node[$getTemplateRoot]()[$extra].noLayoutFailure) { return true; } if (node.h !== "") { return Math.round(h - space.height) <= ERROR; } return true; default: return true; } } ;// CONCATENATED MODULE: ./src/core/xfa/template.js const TEMPLATE_NS_ID = NamespaceIds.template.id; const SVG_NS = "http://www.w3.org/2000/svg"; const MAX_ATTEMPTS_FOR_LRTB_LAYOUT = 2; const MAX_EMPTY_PAGES = 3; const DEFAULT_TAB_INDEX = 5000; const HEADING_PATTERN = /^H(\d+)$/; const MIMES = new Set(["image/gif", "image/jpeg", "image/jpg", "image/pjpeg", "image/png", "image/apng", "image/x-png", "image/bmp", "image/x-ms-bmp", "image/tiff", "image/tif", "application/octet-stream"]); const IMAGES_HEADERS = [[[0x42, 0x4d], "image/bmp"], [[0xff, 0xd8, 0xff], "image/jpeg"], [[0x49, 0x49, 0x2a, 0x00], "image/tiff"], [[0x4d, 0x4d, 0x00, 0x2a], "image/tiff"], [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61], "image/gif"], [[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], "image/png"]]; function getBorderDims(node) { if (!node || !node.border) { return { w: 0, h: 0 }; } const borderExtra = node.border[$getExtra](); if (!borderExtra) { return { w: 0, h: 0 }; } return { w: borderExtra.widths[0] + borderExtra.widths[2] + borderExtra.insets[0] + borderExtra.insets[2], h: borderExtra.widths[1] + borderExtra.widths[3] + borderExtra.insets[1] + borderExtra.insets[3] }; } function hasMargin(node) { return node.margin && (node.margin.topInset || node.margin.rightInset || node.margin.bottomInset || node.margin.leftInset); } function _setValue(templateNode, value) { if (!templateNode.value) { const nodeValue = new Value({}); templateNode[$appendChild](nodeValue); templateNode.value = nodeValue; } templateNode.value[$setValue](value); } function* getContainedChildren(node) { for (const child of node[$getChildren]()) { if (child instanceof SubformSet) { yield* child[$getContainedChildren](); continue; } yield child; } } function isRequired(node) { return node.validate?.nullTest === "error"; } function setTabIndex(node) { while (node) { if (!node.traversal) { node[$tabIndex] = node[$getParent]()[$tabIndex]; return; } if (node[$tabIndex]) { return; } let next = null; for (const child of node.traversal[$getChildren]()) { if (child.operation === "next") { next = child; break; } } if (!next || !next.ref) { node[$tabIndex] = node[$getParent]()[$tabIndex]; return; } const root = node[$getTemplateRoot](); node[$tabIndex] = ++root[$tabIndex]; const ref = root[$searchNode](next.ref, node); if (!ref) { return; } node = ref[0]; } } function applyAssist(obj, attributes) { const assist = obj.assist; if (assist) { const assistTitle = assist[$toHTML](); if (assistTitle) { attributes.title = assistTitle; } const role = assist.role; const match = role.match(HEADING_PATTERN); if (match) { const ariaRole = "heading"; const ariaLevel = match[1]; attributes.role = ariaRole; attributes["aria-level"] = ariaLevel; } } if (obj.layout === "table") { attributes.role = "table"; } else if (obj.layout === "row") { attributes.role = "row"; } else { const parent = obj[$getParent](); if (parent.layout === "row") { attributes.role = parent.assist?.role === "TH" ? "columnheader" : "cell"; } } } function ariaLabel(obj) { if (!obj.assist) { return null; } const assist = obj.assist; if (assist.speak && assist.speak[$content] !== "") { return assist.speak[$content]; } if (assist.toolTip) { return assist.toolTip[$content]; } return null; } function valueToHtml(value) { return HTMLResult.success({ name: "div", attributes: { class: ["xfaRich"], style: Object.create(null) }, children: [{ name: "span", attributes: { style: Object.create(null) }, value }] }); } function setFirstUnsplittable(node) { const root = node[$getTemplateRoot](); if (root[$extra].firstUnsplittable === null) { root[$extra].firstUnsplittable = node; root[$extra].noLayoutFailure = true; } } function unsetFirstUnsplittable(node) { const root = node[$getTemplateRoot](); if (root[$extra].firstUnsplittable === node) { root[$extra].noLayoutFailure = false; } } function handleBreak(node) { if (node[$extra]) { return false; } node[$extra] = Object.create(null); if (node.targetType === "auto") { return false; } const root = node[$getTemplateRoot](); let target = null; if (node.target) { target = root[$searchNode](node.target, node[$getParent]()); if (!target) { return false; } target = target[0]; } const { currentPageArea, currentContentArea } = root[$extra]; if (node.targetType === "pageArea") { if (!(target instanceof PageArea)) { target = null; } if (node.startNew) { node[$extra].target = target || currentPageArea; return true; } else if (target && target !== currentPageArea) { node[$extra].target = target; return true; } return false; } if (!(target instanceof ContentArea)) { target = null; } const pageArea = target && target[$getParent](); let index; let nextPageArea = pageArea; if (node.startNew) { if (target) { const contentAreas = pageArea.contentArea.children; const indexForCurrent = contentAreas.indexOf(currentContentArea); const indexForTarget = contentAreas.indexOf(target); if (indexForCurrent !== -1 && indexForCurrent < indexForTarget) { nextPageArea = null; } index = indexForTarget - 1; } else { index = currentPageArea.contentArea.children.indexOf(currentContentArea); } } else if (target && target !== currentContentArea) { const contentAreas = pageArea.contentArea.children; index = contentAreas.indexOf(target) - 1; nextPageArea = pageArea === currentPageArea ? null : pageArea; } else { return false; } node[$extra].target = nextPageArea; node[$extra].index = index; return true; } function handleOverflow(node, extraNode, space) { const root = node[$getTemplateRoot](); const saved = root[$extra].noLayoutFailure; const savedMethod = extraNode[$getSubformParent]; extraNode[$getSubformParent] = () => node; root[$extra].noLayoutFailure = true; const res = extraNode[$toHTML](space); node[$addHTML](res.html, res.bbox); root[$extra].noLayoutFailure = saved; extraNode[$getSubformParent] = savedMethod; } class AppearanceFilter extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "appearanceFilter"); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Arc extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "arc", true); this.circular = getInteger({ data: attributes.circular, defaultValue: 0, validate: x => x === 1 }); this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); this.id = attributes.id || ""; this.startAngle = getFloat({ data: attributes.startAngle, defaultValue: 0, validate: x => true }); this.sweepAngle = getFloat({ data: attributes.sweepAngle, defaultValue: 360, validate: x => true }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.edge = null; this.fill = null; } [$toHTML]() { const edge = this.edge || new Edge({}); const edgeStyle = edge[$toStyle](); const style = Object.create(null); if (this.fill?.presence === "visible") { Object.assign(style, this.fill[$toStyle]()); } else { style.fill = "transparent"; } style.strokeWidth = measureToString(edge.presence === "visible" ? edge.thickness : 0); style.stroke = edgeStyle.color; let arc; const attributes = { xmlns: SVG_NS, style: { width: "100%", height: "100%", overflow: "visible" } }; if (this.sweepAngle === 360) { arc = { name: "ellipse", attributes: { xmlns: SVG_NS, cx: "50%", cy: "50%", rx: "50%", ry: "50%", style } }; } else { const startAngle = this.startAngle * Math.PI / 180; const sweepAngle = this.sweepAngle * Math.PI / 180; const largeArc = this.sweepAngle > 180 ? 1 : 0; const [x1, y1, x2, y2] = [50 * (1 + Math.cos(startAngle)), 50 * (1 - Math.sin(startAngle)), 50 * (1 + Math.cos(startAngle + sweepAngle)), 50 * (1 - Math.sin(startAngle + sweepAngle))]; arc = { name: "path", attributes: { xmlns: SVG_NS, d: `M ${x1} ${y1} A 50 50 0 ${largeArc} 0 ${x2} ${y2}`, vectorEffect: "non-scaling-stroke", style } }; Object.assign(attributes, { viewBox: "0 0 100 100", preserveAspectRatio: "none" }); } const svg = { name: "svg", children: [arc], attributes }; const parent = this[$getParent]()[$getParent](); if (hasMargin(parent)) { return HTMLResult.success({ name: "div", attributes: { style: { display: "inline", width: "100%", height: "100%" } }, children: [svg] }); } svg.attributes.style.position = "absolute"; return HTMLResult.success(svg); } } class Area extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "area", true); this.colSpan = getInteger({ data: attributes.colSpan, defaultValue: 1, validate: n => n >= 1 || n === -1 }); this.id = attributes.id || ""; this.name = attributes.name || ""; this.relevant = getRelevant(attributes.relevant); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.x = getMeasurement(attributes.x, "0pt"); this.y = getMeasurement(attributes.y, "0pt"); this.desc = null; this.extras = null; this.area = new XFAObjectArray(); this.draw = new XFAObjectArray(); this.exObject = new XFAObjectArray(); this.exclGroup = new XFAObjectArray(); this.field = new XFAObjectArray(); this.subform = new XFAObjectArray(); this.subformSet = new XFAObjectArray(); } *[$getContainedChildren]() { yield* getContainedChildren(this); } [$isTransparent]() { return true; } [$isBindable]() { return true; } [$addHTML](html, bbox) { const [x, y, w, h] = bbox; this[$extra].width = Math.max(this[$extra].width, x + w); this[$extra].height = Math.max(this[$extra].height, y + h); this[$extra].children.push(html); } [$getAvailableSpace]() { return this[$extra].availableSpace; } [$toHTML](availableSpace) { const style = toStyle(this, "position"); const attributes = { style, id: this[$uid], class: ["xfaArea"] }; if (isPrintOnly(this)) { attributes.class.push("xfaPrintOnly"); } if (this.name) { attributes.xfaName = this.name; } const children = []; this[$extra] = { children, width: 0, height: 0, availableSpace }; const result = this[$childrenToHTML]({ filter: new Set(["area", "draw", "field", "exclGroup", "subform", "subformSet"]), include: true }); if (!result.success) { if (result.isBreak()) { return result; } delete this[$extra]; return HTMLResult.FAILURE; } style.width = measureToString(this[$extra].width); style.height = measureToString(this[$extra].height); const html = { name: "div", attributes, children }; const bbox = [this.x, this.y, this[$extra].width, this[$extra].height]; delete this[$extra]; return HTMLResult.success(html, bbox); } } class Assist extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "assist", true); this.id = attributes.id || ""; this.role = attributes.role || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.speak = null; this.toolTip = null; } [$toHTML]() { return this.toolTip?.[$content] || null; } } class Barcode extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "barcode", true); this.charEncoding = getKeyword({ data: attributes.charEncoding ? attributes.charEncoding.toLowerCase() : "", defaultValue: "", validate: k => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/) }); this.checksum = getStringOption(attributes.checksum, ["none", "1mod10", "1mod10_1mod11", "2mod10", "auto"]); this.dataColumnCount = getInteger({ data: attributes.dataColumnCount, defaultValue: -1, validate: x => x >= 0 }); this.dataLength = getInteger({ data: attributes.dataLength, defaultValue: -1, validate: x => x >= 0 }); this.dataPrep = getStringOption(attributes.dataPrep, ["none", "flateCompress"]); this.dataRowCount = getInteger({ data: attributes.dataRowCount, defaultValue: -1, validate: x => x >= 0 }); this.endChar = attributes.endChar || ""; this.errorCorrectionLevel = getInteger({ data: attributes.errorCorrectionLevel, defaultValue: -1, validate: x => x >= 0 && x <= 8 }); this.id = attributes.id || ""; this.moduleHeight = getMeasurement(attributes.moduleHeight, "5mm"); this.moduleWidth = getMeasurement(attributes.moduleWidth, "0.25mm"); this.printCheckDigit = getInteger({ data: attributes.printCheckDigit, defaultValue: 0, validate: x => x === 1 }); this.rowColumnRatio = getRatio(attributes.rowColumnRatio); this.startChar = attributes.startChar || ""; this.textLocation = getStringOption(attributes.textLocation, ["below", "above", "aboveEmbedded", "belowEmbedded", "none"]); this.truncate = getInteger({ data: attributes.truncate, defaultValue: 0, validate: x => x === 1 }); this.type = getStringOption(attributes.type ? attributes.type.toLowerCase() : "", ["aztec", "codabar", "code2of5industrial", "code2of5interleaved", "code2of5matrix", "code2of5standard", "code3of9", "code3of9extended", "code11", "code49", "code93", "code128", "code128a", "code128b", "code128c", "code128sscc", "datamatrix", "ean8", "ean8add2", "ean8add5", "ean13", "ean13add2", "ean13add5", "ean13pwcd", "fim", "logmars", "maxicode", "msi", "pdf417", "pdf417macro", "plessey", "postauscust2", "postauscust3", "postausreplypaid", "postausstandard", "postukrm4scc", "postusdpbc", "postusimb", "postusstandard", "postus5zip", "qrcode", "rfid", "rss14", "rss14expanded", "rss14limited", "rss14stacked", "rss14stackedomni", "rss14truncated", "telepen", "ucc128", "ucc128random", "ucc128sscc", "upca", "upcaadd2", "upcaadd5", "upcapwcd", "upce", "upceadd2", "upceadd5", "upcean2", "upcean5", "upsmaxicode"]); this.upsMode = getStringOption(attributes.upsMode, ["usCarrier", "internationalCarrier", "secureSymbol", "standardSymbol"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.wideNarrowRatio = getRatio(attributes.wideNarrowRatio); this.encrypt = null; this.extras = null; } } class Bind extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "bind", true); this.match = getStringOption(attributes.match, ["once", "dataRef", "global", "none"]); this.ref = attributes.ref || ""; this.picture = null; } } class BindItems extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "bindItems"); this.connection = attributes.connection || ""; this.labelRef = attributes.labelRef || ""; this.ref = attributes.ref || ""; this.valueRef = attributes.valueRef || ""; } } class Bookend extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "bookend"); this.id = attributes.id || ""; this.leader = attributes.leader || ""; this.trailer = attributes.trailer || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class BooleanElement extends Option01 { constructor(attributes) { super(TEMPLATE_NS_ID, "boolean"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$toHTML](availableSpace) { return valueToHtml(this[$content] === 1 ? "1" : "0"); } } class Border extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "border", true); this.break = getStringOption(attributes.break, ["close", "open"]); this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); this.id = attributes.id || ""; this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); this.relevant = getRelevant(attributes.relevant); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.corner = new XFAObjectArray(4); this.edge = new XFAObjectArray(4); this.extras = null; this.fill = null; this.margin = null; } [$getExtra]() { if (!this[$extra]) { const edges = this.edge.children.slice(); if (edges.length < 4) { const defaultEdge = edges.at(-1) || new Edge({}); for (let i = edges.length; i < 4; i++) { edges.push(defaultEdge); } } const widths = edges.map(edge => edge.thickness); const insets = [0, 0, 0, 0]; if (this.margin) { insets[0] = this.margin.topInset; insets[1] = this.margin.rightInset; insets[2] = this.margin.bottomInset; insets[3] = this.margin.leftInset; } this[$extra] = { widths, insets, edges }; } return this[$extra]; } [$toStyle]() { const { edges } = this[$getExtra](); const edgeStyles = edges.map(node => { const style = node[$toStyle](); style.color ||= "#000000"; return style; }); const style = Object.create(null); if (this.margin) { Object.assign(style, this.margin[$toStyle]()); } if (this.fill?.presence === "visible") { Object.assign(style, this.fill[$toStyle]()); } if (this.corner.children.some(node => node.radius !== 0)) { const cornerStyles = this.corner.children.map(node => node[$toStyle]()); if (cornerStyles.length === 2 || cornerStyles.length === 3) { const last = cornerStyles.at(-1); for (let i = cornerStyles.length; i < 4; i++) { cornerStyles.push(last); } } style.borderRadius = cornerStyles.map(s => s.radius).join(" "); } switch (this.presence) { case "invisible": case "hidden": style.borderStyle = ""; break; case "inactive": style.borderStyle = "none"; break; default: style.borderStyle = edgeStyles.map(s => s.style).join(" "); break; } style.borderWidth = edgeStyles.map(s => s.width).join(" "); style.borderColor = edgeStyles.map(s => s.color).join(" "); return style; } } class Break extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "break", true); this.after = getStringOption(attributes.after, ["auto", "contentArea", "pageArea", "pageEven", "pageOdd"]); this.afterTarget = attributes.afterTarget || ""; this.before = getStringOption(attributes.before, ["auto", "contentArea", "pageArea", "pageEven", "pageOdd"]); this.beforeTarget = attributes.beforeTarget || ""; this.bookendLeader = attributes.bookendLeader || ""; this.bookendTrailer = attributes.bookendTrailer || ""; this.id = attributes.id || ""; this.overflowLeader = attributes.overflowLeader || ""; this.overflowTarget = attributes.overflowTarget || ""; this.overflowTrailer = attributes.overflowTrailer || ""; this.startNew = getInteger({ data: attributes.startNew, defaultValue: 0, validate: x => x === 1 }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; } } class BreakAfter extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "breakAfter", true); this.id = attributes.id || ""; this.leader = attributes.leader || ""; this.startNew = getInteger({ data: attributes.startNew, defaultValue: 0, validate: x => x === 1 }); this.target = attributes.target || ""; this.targetType = getStringOption(attributes.targetType, ["auto", "contentArea", "pageArea"]); this.trailer = attributes.trailer || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.script = null; } } class BreakBefore extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "breakBefore", true); this.id = attributes.id || ""; this.leader = attributes.leader || ""; this.startNew = getInteger({ data: attributes.startNew, defaultValue: 0, validate: x => x === 1 }); this.target = attributes.target || ""; this.targetType = getStringOption(attributes.targetType, ["auto", "contentArea", "pageArea"]); this.trailer = attributes.trailer || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.script = null; } [$toHTML](availableSpace) { this[$extra] = {}; return HTMLResult.FAILURE; } } class Button extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "button", true); this.highlight = getStringOption(attributes.highlight, ["inverted", "none", "outline", "push"]); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; } [$toHTML](availableSpace) { const parent = this[$getParent](); const grandpa = parent[$getParent](); const htmlButton = { name: "button", attributes: { id: this[$uid], class: ["xfaButton"], style: {} }, children: [] }; for (const event of grandpa.event.children) { if (event.activity !== "click" || !event.script) { continue; } const jsURL = recoverJsURL(event.script[$content]); if (!jsURL) { continue; } const href = fixURL(jsURL.url); if (!href) { continue; } htmlButton.children.push({ name: "a", attributes: { id: "link" + this[$uid], href, newWindow: jsURL.newWindow, class: ["xfaLink"], style: {} }, children: [] }); } return HTMLResult.success(htmlButton); } } class Calculate extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "calculate", true); this.id = attributes.id || ""; this.override = getStringOption(attributes.override, ["disabled", "error", "ignore", "warning"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.message = null; this.script = null; } } class Caption extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "caption", true); this.id = attributes.id || ""; this.placement = getStringOption(attributes.placement, ["left", "bottom", "inline", "right", "top"]); this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); this.reserve = Math.ceil(getMeasurement(attributes.reserve)); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.font = null; this.margin = null; this.para = null; this.value = null; } [$setValue](value) { _setValue(this, value); } [$getExtra](availableSpace) { if (!this[$extra]) { let { width, height } = availableSpace; switch (this.placement) { case "left": case "right": case "inline": width = this.reserve <= 0 ? width : this.reserve; break; case "top": case "bottom": height = this.reserve <= 0 ? height : this.reserve; break; } this[$extra] = layoutNode(this, { width, height }); } return this[$extra]; } [$toHTML](availableSpace) { if (!this.value) { return HTMLResult.EMPTY; } this[$pushPara](); const value = this.value[$toHTML](availableSpace).html; if (!value) { this[$popPara](); return HTMLResult.EMPTY; } const savedReserve = this.reserve; if (this.reserve <= 0) { const { w, h } = this[$getExtra](availableSpace); switch (this.placement) { case "left": case "right": case "inline": this.reserve = w; break; case "top": case "bottom": this.reserve = h; break; } } const children = []; if (typeof value === "string") { children.push({ name: "#text", value }); } else { children.push(value); } const style = toStyle(this, "font", "margin", "visibility"); switch (this.placement) { case "left": case "right": if (this.reserve > 0) { style.width = measureToString(this.reserve); } break; case "top": case "bottom": if (this.reserve > 0) { style.height = measureToString(this.reserve); } break; } setPara(this, null, value); this[$popPara](); this.reserve = savedReserve; return HTMLResult.success({ name: "div", attributes: { style, class: ["xfaCaption"] }, children }); } } class Certificate extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "certificate"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Certificates extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "certificates", true); this.credentialServerPolicy = getStringOption(attributes.credentialServerPolicy, ["optional", "required"]); this.id = attributes.id || ""; this.url = attributes.url || ""; this.urlPolicy = attributes.urlPolicy || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.encryption = null; this.issuers = null; this.keyUsage = null; this.oids = null; this.signing = null; this.subjectDNs = null; } } class CheckButton extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "checkButton", true); this.id = attributes.id || ""; this.mark = getStringOption(attributes.mark, ["default", "check", "circle", "cross", "diamond", "square", "star"]); this.shape = getStringOption(attributes.shape, ["square", "round"]); this.size = getMeasurement(attributes.size, "10pt"); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.border = null; this.extras = null; this.margin = null; } [$toHTML](availableSpace) { const style = toStyle("margin"); const size = measureToString(this.size); style.width = style.height = size; let type; let className; let groupId; const field = this[$getParent]()[$getParent](); const items = field.items.children.length && field.items.children[0][$toHTML]().html || []; const exportedValue = { on: (items[0] !== undefined ? items[0] : "on").toString(), off: (items[1] !== undefined ? items[1] : "off").toString() }; const value = field.value?.[$text]() || "off"; const checked = value === exportedValue.on || undefined; const container = field[$getSubformParent](); const fieldId = field[$uid]; let dataId; if (container instanceof ExclGroup) { groupId = container[$uid]; type = "radio"; className = "xfaRadio"; dataId = container[$data]?.[$uid] || container[$uid]; } else { type = "checkbox"; className = "xfaCheckbox"; dataId = field[$data]?.[$uid] || field[$uid]; } const input = { name: "input", attributes: { class: [className], style, fieldId, dataId, type, checked, xfaOn: exportedValue.on, xfaOff: exportedValue.off, "aria-label": ariaLabel(field), "aria-required": false } }; if (groupId) { input.attributes.name = groupId; } if (isRequired(field)) { input.attributes["aria-required"] = true; input.attributes.required = true; } return HTMLResult.success({ name: "label", attributes: { class: ["xfaLabel"] }, children: [input] }); } } class ChoiceList extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "choiceList", true); this.commitOn = getStringOption(attributes.commitOn, ["select", "exit"]); this.id = attributes.id || ""; this.open = getStringOption(attributes.open, ["userControl", "always", "multiSelect", "onEntry"]); this.textEntry = getInteger({ data: attributes.textEntry, defaultValue: 0, validate: x => x === 1 }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.border = null; this.extras = null; this.margin = null; } [$toHTML](availableSpace) { const style = toStyle(this, "border", "margin"); const ui = this[$getParent](); const field = ui[$getParent](); const fontSize = field.font?.size || 10; const optionStyle = { fontSize: `calc(${fontSize}px * var(--scale-factor))` }; const children = []; if (field.items.children.length > 0) { const items = field.items; let displayedIndex = 0; let saveIndex = 0; if (items.children.length === 2) { displayedIndex = items.children[0].save; saveIndex = 1 - displayedIndex; } const displayed = items.children[displayedIndex][$toHTML]().html; const values = items.children[saveIndex][$toHTML]().html; let selected = false; const value = field.value?.[$text]() || ""; for (let i = 0, ii = displayed.length; i < ii; i++) { const option = { name: "option", attributes: { value: values[i] || displayed[i], style: optionStyle }, value: displayed[i] }; if (values[i] === value) { option.attributes.selected = selected = true; } children.push(option); } if (!selected) { children.splice(0, 0, { name: "option", attributes: { hidden: true, selected: true }, value: " " }); } } const selectAttributes = { class: ["xfaSelect"], fieldId: field[$uid], dataId: field[$data]?.[$uid] || field[$uid], style, "aria-label": ariaLabel(field), "aria-required": false }; if (isRequired(field)) { selectAttributes["aria-required"] = true; selectAttributes.required = true; } if (this.open === "multiSelect") { selectAttributes.multiple = true; } return HTMLResult.success({ name: "label", attributes: { class: ["xfaLabel"] }, children: [{ name: "select", children, attributes: selectAttributes }] }); } } class Color extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "color", true); this.cSpace = getStringOption(attributes.cSpace, ["SRGB"]); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.value = attributes.value ? getColor(attributes.value) : ""; this.extras = null; } [$hasSettableValue]() { return false; } [$toStyle]() { return this.value ? Util.makeHexColor(this.value.r, this.value.g, this.value.b) : null; } } class Comb extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "comb"); this.id = attributes.id || ""; this.numberOfCells = getInteger({ data: attributes.numberOfCells, defaultValue: 0, validate: x => x >= 0 }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Connect extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "connect", true); this.connection = attributes.connection || ""; this.id = attributes.id || ""; this.ref = attributes.ref || ""; this.usage = getStringOption(attributes.usage, ["exportAndImport", "exportOnly", "importOnly"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.picture = null; } } class ContentArea extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "contentArea", true); this.h = getMeasurement(attributes.h); this.id = attributes.id || ""; this.name = attributes.name || ""; this.relevant = getRelevant(attributes.relevant); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.w = getMeasurement(attributes.w); this.x = getMeasurement(attributes.x, "0pt"); this.y = getMeasurement(attributes.y, "0pt"); this.desc = null; this.extras = null; } [$toHTML](availableSpace) { const left = measureToString(this.x); const top = measureToString(this.y); const style = { left, top, width: measureToString(this.w), height: measureToString(this.h) }; const classNames = ["xfaContentarea"]; if (isPrintOnly(this)) { classNames.push("xfaPrintOnly"); } return HTMLResult.success({ name: "div", children: [], attributes: { style, class: classNames, id: this[$uid] } }); } } class Corner extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "corner", true); this.id = attributes.id || ""; this.inverted = getInteger({ data: attributes.inverted, defaultValue: 0, validate: x => x === 1 }); this.join = getStringOption(attributes.join, ["square", "round"]); this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); this.radius = getMeasurement(attributes.radius); this.stroke = getStringOption(attributes.stroke, ["solid", "dashDot", "dashDotDot", "dashed", "dotted", "embossed", "etched", "lowered", "raised"]); this.thickness = getMeasurement(attributes.thickness, "0.5pt"); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.color = null; this.extras = null; } [$toStyle]() { const style = toStyle(this, "visibility"); style.radius = measureToString(this.join === "square" ? 0 : this.radius); return style; } } class DateElement extends ContentObject { constructor(attributes) { super(TEMPLATE_NS_ID, "date"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$finalize]() { const date = this[$content].trim(); this[$content] = date ? new Date(date) : null; } [$toHTML](availableSpace) { return valueToHtml(this[$content] ? this[$content].toString() : ""); } } class DateTime extends ContentObject { constructor(attributes) { super(TEMPLATE_NS_ID, "dateTime"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$finalize]() { const date = this[$content].trim(); this[$content] = date ? new Date(date) : null; } [$toHTML](availableSpace) { return valueToHtml(this[$content] ? this[$content].toString() : ""); } } class DateTimeEdit extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "dateTimeEdit", true); this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); this.id = attributes.id || ""; this.picker = getStringOption(attributes.picker, ["host", "none"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.border = null; this.comb = null; this.extras = null; this.margin = null; } [$toHTML](availableSpace) { const style = toStyle(this, "border", "font", "margin"); const field = this[$getParent]()[$getParent](); const html = { name: "input", attributes: { type: "text", fieldId: field[$uid], dataId: field[$data]?.[$uid] || field[$uid], class: ["xfaTextfield"], style, "aria-label": ariaLabel(field), "aria-required": false } }; if (isRequired(field)) { html.attributes["aria-required"] = true; html.attributes.required = true; } return HTMLResult.success({ name: "label", attributes: { class: ["xfaLabel"] }, children: [html] }); } } class Decimal extends ContentObject { constructor(attributes) { super(TEMPLATE_NS_ID, "decimal"); this.fracDigits = getInteger({ data: attributes.fracDigits, defaultValue: 2, validate: x => true }); this.id = attributes.id || ""; this.leadDigits = getInteger({ data: attributes.leadDigits, defaultValue: -1, validate: x => true }); this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$finalize]() { const number = parseFloat(this[$content].trim()); this[$content] = isNaN(number) ? null : number; } [$toHTML](availableSpace) { return valueToHtml(this[$content] !== null ? this[$content].toString() : ""); } } class DefaultUi extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "defaultUi", true); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; } } class Desc extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "desc", true); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.boolean = new XFAObjectArray(); this.date = new XFAObjectArray(); this.dateTime = new XFAObjectArray(); this.decimal = new XFAObjectArray(); this.exData = new XFAObjectArray(); this.float = new XFAObjectArray(); this.image = new XFAObjectArray(); this.integer = new XFAObjectArray(); this.text = new XFAObjectArray(); this.time = new XFAObjectArray(); } } class DigestMethod extends OptionObject { constructor(attributes) { super(TEMPLATE_NS_ID, "digestMethod", ["", "SHA1", "SHA256", "SHA512", "RIPEMD160"]); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class DigestMethods extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "digestMethods", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.digestMethod = new XFAObjectArray(); } } class Draw extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "draw", true); this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); this.colSpan = getInteger({ data: attributes.colSpan, defaultValue: 1, validate: n => n >= 1 || n === -1 }); this.h = attributes.h ? getMeasurement(attributes.h) : ""; this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); this.id = attributes.id || ""; this.locale = attributes.locale || ""; this.maxH = getMeasurement(attributes.maxH, "0pt"); this.maxW = getMeasurement(attributes.maxW, "0pt"); this.minH = getMeasurement(attributes.minH, "0pt"); this.minW = getMeasurement(attributes.minW, "0pt"); this.name = attributes.name || ""; this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); this.relevant = getRelevant(attributes.relevant); this.rotate = getInteger({ data: attributes.rotate, defaultValue: 0, validate: x => x % 90 === 0 }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.w = attributes.w ? getMeasurement(attributes.w) : ""; this.x = getMeasurement(attributes.x, "0pt"); this.y = getMeasurement(attributes.y, "0pt"); this.assist = null; this.border = null; this.caption = null; this.desc = null; this.extras = null; this.font = null; this.keep = null; this.margin = null; this.para = null; this.traversal = null; this.ui = null; this.value = null; this.setProperty = new XFAObjectArray(); } [$setValue](value) { _setValue(this, value); } [$toHTML](availableSpace) { setTabIndex(this); if (this.presence === "hidden" || this.presence === "inactive") { return HTMLResult.EMPTY; } fixDimensions(this); this[$pushPara](); const savedW = this.w; const savedH = this.h; const { w, h, isBroken } = layoutNode(this, availableSpace); if (w && this.w === "") { if (isBroken && this[$getSubformParent]()[$isThereMoreWidth]()) { this[$popPara](); return HTMLResult.FAILURE; } this.w = w; } if (h && this.h === "") { this.h = h; } setFirstUnsplittable(this); if (!checkDimensions(this, availableSpace)) { this.w = savedW; this.h = savedH; this[$popPara](); return HTMLResult.FAILURE; } unsetFirstUnsplittable(this); const style = toStyle(this, "font", "hAlign", "dimensions", "position", "presence", "rotate", "anchorType", "border", "margin"); setMinMaxDimensions(this, style); if (style.margin) { style.padding = style.margin; delete style.margin; } const classNames = ["xfaDraw"]; if (this.font) { classNames.push("xfaFont"); } if (isPrintOnly(this)) { classNames.push("xfaPrintOnly"); } const attributes = { style, id: this[$uid], class: classNames }; if (this.name) { attributes.xfaName = this.name; } const html = { name: "div", attributes, children: [] }; applyAssist(this, attributes); const bbox = computeBbox(this, html, availableSpace); const value = this.value ? this.value[$toHTML](availableSpace).html : null; if (value === null) { this.w = savedW; this.h = savedH; this[$popPara](); return HTMLResult.success(createWrapper(this, html), bbox); } html.children.push(value); setPara(this, style, value); this.w = savedW; this.h = savedH; this[$popPara](); return HTMLResult.success(createWrapper(this, html), bbox); } } class Edge extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "edge", true); this.cap = getStringOption(attributes.cap, ["square", "butt", "round"]); this.id = attributes.id || ""; this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); this.stroke = getStringOption(attributes.stroke, ["solid", "dashDot", "dashDotDot", "dashed", "dotted", "embossed", "etched", "lowered", "raised"]); this.thickness = getMeasurement(attributes.thickness, "0.5pt"); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.color = null; this.extras = null; } [$toStyle]() { const style = toStyle(this, "visibility"); Object.assign(style, { linecap: this.cap, width: measureToString(this.thickness), color: this.color ? this.color[$toStyle]() : "#000000", style: "" }); if (this.presence !== "visible") { style.style = "none"; } else { switch (this.stroke) { case "solid": style.style = "solid"; break; case "dashDot": style.style = "dashed"; break; case "dashDotDot": style.style = "dashed"; break; case "dashed": style.style = "dashed"; break; case "dotted": style.style = "dotted"; break; case "embossed": style.style = "ridge"; break; case "etched": style.style = "groove"; break; case "lowered": style.style = "inset"; break; case "raised": style.style = "outset"; break; } } return style; } } class Encoding extends OptionObject { constructor(attributes) { super(TEMPLATE_NS_ID, "encoding", ["adbe.x509.rsa_sha1", "adbe.pkcs7.detached", "adbe.pkcs7.sha1"]); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Encodings extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "encodings", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.encoding = new XFAObjectArray(); } } class Encrypt extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "encrypt", true); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.certificate = null; } } class EncryptData extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "encryptData", true); this.id = attributes.id || ""; this.operation = getStringOption(attributes.operation, ["encrypt", "decrypt"]); this.target = attributes.target || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.filter = null; this.manifest = null; } } class Encryption extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "encryption", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.certificate = new XFAObjectArray(); } } class EncryptionMethod extends OptionObject { constructor(attributes) { super(TEMPLATE_NS_ID, "encryptionMethod", ["", "AES256-CBC", "TRIPLEDES-CBC", "AES128-CBC", "AES192-CBC"]); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class EncryptionMethods extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "encryptionMethods", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.encryptionMethod = new XFAObjectArray(); } } class Event extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "event", true); this.activity = getStringOption(attributes.activity, ["click", "change", "docClose", "docReady", "enter", "exit", "full", "indexChange", "initialize", "mouseDown", "mouseEnter", "mouseExit", "mouseUp", "postExecute", "postOpen", "postPrint", "postSave", "postSign", "postSubmit", "preExecute", "preOpen", "prePrint", "preSave", "preSign", "preSubmit", "ready", "validationState"]); this.id = attributes.id || ""; this.listen = getStringOption(attributes.listen, ["refOnly", "refAndDescendents"]); this.name = attributes.name || ""; this.ref = attributes.ref || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.encryptData = null; this.execute = null; this.script = null; this.signData = null; this.submit = null; } } class ExData extends ContentObject { constructor(attributes) { super(TEMPLATE_NS_ID, "exData"); this.contentType = attributes.contentType || ""; this.href = attributes.href || ""; this.id = attributes.id || ""; this.maxLength = getInteger({ data: attributes.maxLength, defaultValue: -1, validate: x => x >= -1 }); this.name = attributes.name || ""; this.rid = attributes.rid || ""; this.transferEncoding = getStringOption(attributes.transferEncoding, ["none", "base64", "package"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$isCDATAXml]() { return this.contentType === "text/html"; } [$onChild](child) { if (this.contentType === "text/html" && child[$namespaceId] === NamespaceIds.xhtml.id) { this[$content] = child; return true; } if (this.contentType === "text/xml") { this[$content] = child; return true; } return false; } [$toHTML](availableSpace) { if (this.contentType !== "text/html" || !this[$content]) { return HTMLResult.EMPTY; } return this[$content][$toHTML](availableSpace); } } class ExObject extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "exObject", true); this.archive = attributes.archive || ""; this.classId = attributes.classId || ""; this.codeBase = attributes.codeBase || ""; this.codeType = attributes.codeType || ""; this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.boolean = new XFAObjectArray(); this.date = new XFAObjectArray(); this.dateTime = new XFAObjectArray(); this.decimal = new XFAObjectArray(); this.exData = new XFAObjectArray(); this.exObject = new XFAObjectArray(); this.float = new XFAObjectArray(); this.image = new XFAObjectArray(); this.integer = new XFAObjectArray(); this.text = new XFAObjectArray(); this.time = new XFAObjectArray(); } } class ExclGroup extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "exclGroup", true); this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); this.accessKey = attributes.accessKey || ""; this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); this.colSpan = getInteger({ data: attributes.colSpan, defaultValue: 1, validate: n => n >= 1 || n === -1 }); this.h = attributes.h ? getMeasurement(attributes.h) : ""; this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); this.id = attributes.id || ""; this.layout = getStringOption(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]); this.maxH = getMeasurement(attributes.maxH, "0pt"); this.maxW = getMeasurement(attributes.maxW, "0pt"); this.minH = getMeasurement(attributes.minH, "0pt"); this.minW = getMeasurement(attributes.minW, "0pt"); this.name = attributes.name || ""; this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); this.relevant = getRelevant(attributes.relevant); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.w = attributes.w ? getMeasurement(attributes.w) : ""; this.x = getMeasurement(attributes.x, "0pt"); this.y = getMeasurement(attributes.y, "0pt"); this.assist = null; this.bind = null; this.border = null; this.calculate = null; this.caption = null; this.desc = null; this.extras = null; this.margin = null; this.para = null; this.traversal = null; this.validate = null; this.connect = new XFAObjectArray(); this.event = new XFAObjectArray(); this.field = new XFAObjectArray(); this.setProperty = new XFAObjectArray(); } [$isBindable]() { return true; } [$hasSettableValue]() { return true; } [$setValue](value) { for (const field of this.field.children) { if (!field.value) { const nodeValue = new Value({}); field[$appendChild](nodeValue); field.value = nodeValue; } field.value[$setValue](value); } } [$isThereMoreWidth]() { return this.layout.endsWith("-tb") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth](); } [$isSplittable]() { const parent = this[$getSubformParent](); if (!parent[$isSplittable]()) { return false; } if (this[$extra]._isSplittable !== undefined) { return this[$extra]._isSplittable; } if (this.layout === "position" || this.layout.includes("row")) { this[$extra]._isSplittable = false; return false; } if (parent.layout?.endsWith("-tb") && parent[$extra].numberInLine !== 0) { return false; } this[$extra]._isSplittable = true; return true; } [$flushHTML]() { return flushHTML(this); } [$addHTML](html, bbox) { addHTML(this, html, bbox); } [$getAvailableSpace]() { return getAvailableSpace(this); } [$toHTML](availableSpace) { setTabIndex(this); if (this.presence === "hidden" || this.presence === "inactive" || this.h === 0 || this.w === 0) { return HTMLResult.EMPTY; } fixDimensions(this); const children = []; const attributes = { id: this[$uid], class: [] }; setAccess(this, attributes.class); if (!this[$extra]) { this[$extra] = Object.create(null); } Object.assign(this[$extra], { children, attributes, attempt: 0, line: null, numberInLine: 0, availableSpace: { width: Math.min(this.w || Infinity, availableSpace.width), height: Math.min(this.h || Infinity, availableSpace.height) }, width: 0, height: 0, prevHeight: 0, currentWidth: 0 }); const isSplittable = this[$isSplittable](); if (!isSplittable) { setFirstUnsplittable(this); } if (!checkDimensions(this, availableSpace)) { return HTMLResult.FAILURE; } const filter = new Set(["field"]); if (this.layout.includes("row")) { const columnWidths = this[$getSubformParent]().columnWidths; if (Array.isArray(columnWidths) && columnWidths.length > 0) { this[$extra].columnWidths = columnWidths; this[$extra].currentColumn = 0; } } const style = toStyle(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign"); const classNames = ["xfaExclgroup"]; const cl = layoutClass(this); if (cl) { classNames.push(cl); } if (isPrintOnly(this)) { classNames.push("xfaPrintOnly"); } attributes.style = style; attributes.class = classNames; if (this.name) { attributes.xfaName = this.name; } this[$pushPara](); const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb"; const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1; for (; this[$extra].attempt < maxRun; this[$extra].attempt++) { if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) { this[$extra].numberInLine = 0; } const result = this[$childrenToHTML]({ filter, include: true }); if (result.success) { break; } if (result.isBreak()) { this[$popPara](); return result; } if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !this[$getTemplateRoot]()[$extra].noLayoutFailure) { this[$extra].attempt = maxRun; break; } } this[$popPara](); if (!isSplittable) { unsetFirstUnsplittable(this); } if (this[$extra].attempt === maxRun) { if (!isSplittable) { delete this[$extra]; } return HTMLResult.FAILURE; } let marginH = 0; let marginV = 0; if (this.margin) { marginH = this.margin.leftInset + this.margin.rightInset; marginV = this.margin.topInset + this.margin.bottomInset; } const width = Math.max(this[$extra].width + marginH, this.w || 0); const height = Math.max(this[$extra].height + marginV, this.h || 0); const bbox = [this.x, this.y, width, height]; if (this.w === "") { style.width = measureToString(width); } if (this.h === "") { style.height = measureToString(height); } const html = { name: "div", attributes, children }; applyAssist(this, attributes); delete this[$extra]; return HTMLResult.success(createWrapper(this, html), bbox); } } class Execute extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "execute"); this.connection = attributes.connection || ""; this.executeType = getStringOption(attributes.executeType, ["import", "remerge"]); this.id = attributes.id || ""; this.runAt = getStringOption(attributes.runAt, ["client", "both", "server"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Extras extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "extras", true); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.boolean = new XFAObjectArray(); this.date = new XFAObjectArray(); this.dateTime = new XFAObjectArray(); this.decimal = new XFAObjectArray(); this.exData = new XFAObjectArray(); this.extras = new XFAObjectArray(); this.float = new XFAObjectArray(); this.image = new XFAObjectArray(); this.integer = new XFAObjectArray(); this.text = new XFAObjectArray(); this.time = new XFAObjectArray(); } } class Field extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "field", true); this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); this.accessKey = attributes.accessKey || ""; this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); this.colSpan = getInteger({ data: attributes.colSpan, defaultValue: 1, validate: n => n >= 1 || n === -1 }); this.h = attributes.h ? getMeasurement(attributes.h) : ""; this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); this.id = attributes.id || ""; this.locale = attributes.locale || ""; this.maxH = getMeasurement(attributes.maxH, "0pt"); this.maxW = getMeasurement(attributes.maxW, "0pt"); this.minH = getMeasurement(attributes.minH, "0pt"); this.minW = getMeasurement(attributes.minW, "0pt"); this.name = attributes.name || ""; this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); this.relevant = getRelevant(attributes.relevant); this.rotate = getInteger({ data: attributes.rotate, defaultValue: 0, validate: x => x % 90 === 0 }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.w = attributes.w ? getMeasurement(attributes.w) : ""; this.x = getMeasurement(attributes.x, "0pt"); this.y = getMeasurement(attributes.y, "0pt"); this.assist = null; this.bind = null; this.border = null; this.calculate = null; this.caption = null; this.desc = null; this.extras = null; this.font = null; this.format = null; this.items = new XFAObjectArray(2); this.keep = null; this.margin = null; this.para = null; this.traversal = null; this.ui = null; this.validate = null; this.value = null; this.bindItems = new XFAObjectArray(); this.connect = new XFAObjectArray(); this.event = new XFAObjectArray(); this.setProperty = new XFAObjectArray(); } [$isBindable]() { return true; } [$setValue](value) { _setValue(this, value); } [$toHTML](availableSpace) { setTabIndex(this); if (!this.ui) { this.ui = new Ui({}); this.ui[$globalData] = this[$globalData]; this[$appendChild](this.ui); let node; switch (this.items.children.length) { case 0: node = new TextEdit({}); this.ui.textEdit = node; break; case 1: node = new CheckButton({}); this.ui.checkButton = node; break; case 2: node = new ChoiceList({}); this.ui.choiceList = node; break; } this.ui[$appendChild](node); } if (!this.ui || this.presence === "hidden" || this.presence === "inactive" || this.h === 0 || this.w === 0) { return HTMLResult.EMPTY; } if (this.caption) { delete this.caption[$extra]; } this[$pushPara](); const caption = this.caption ? this.caption[$toHTML](availableSpace).html : null; const savedW = this.w; const savedH = this.h; let marginH = 0; let marginV = 0; if (this.margin) { marginH = this.margin.leftInset + this.margin.rightInset; marginV = this.margin.topInset + this.margin.bottomInset; } let borderDims = null; if (this.w === "" || this.h === "") { let width = null; let height = null; let uiW = 0; let uiH = 0; if (this.ui.checkButton) { uiW = uiH = this.ui.checkButton.size; } else { const { w, h } = layoutNode(this, availableSpace); if (w !== null) { uiW = w; uiH = h; } else { uiH = fonts_getMetrics(this.font, true).lineNoGap; } } borderDims = getBorderDims(this.ui[$getExtra]()); uiW += borderDims.w; uiH += borderDims.h; if (this.caption) { const { w, h, isBroken } = this.caption[$getExtra](availableSpace); if (isBroken && this[$getSubformParent]()[$isThereMoreWidth]()) { this[$popPara](); return HTMLResult.FAILURE; } width = w; height = h; switch (this.caption.placement) { case "left": case "right": case "inline": width += uiW; break; case "top": case "bottom": height += uiH; break; } } else { width = uiW; height = uiH; } if (width && this.w === "") { width += marginH; this.w = Math.min(this.maxW <= 0 ? Infinity : this.maxW, this.minW + 1 < width ? width : this.minW); } if (height && this.h === "") { height += marginV; this.h = Math.min(this.maxH <= 0 ? Infinity : this.maxH, this.minH + 1 < height ? height : this.minH); } } this[$popPara](); fixDimensions(this); setFirstUnsplittable(this); if (!checkDimensions(this, availableSpace)) { this.w = savedW; this.h = savedH; this[$popPara](); return HTMLResult.FAILURE; } unsetFirstUnsplittable(this); const style = toStyle(this, "font", "dimensions", "position", "rotate", "anchorType", "presence", "margin", "hAlign"); setMinMaxDimensions(this, style); const classNames = ["xfaField"]; if (this.font) { classNames.push("xfaFont"); } if (isPrintOnly(this)) { classNames.push("xfaPrintOnly"); } const attributes = { style, id: this[$uid], class: classNames }; if (style.margin) { style.padding = style.margin; delete style.margin; } setAccess(this, classNames); if (this.name) { attributes.xfaName = this.name; } const children = []; const html = { name: "div", attributes, children }; applyAssist(this, attributes); const borderStyle = this.border ? this.border[$toStyle]() : null; const bbox = computeBbox(this, html, availableSpace); const ui = this.ui[$toHTML]().html; if (!ui) { Object.assign(style, borderStyle); return HTMLResult.success(createWrapper(this, html), bbox); } if (this[$tabIndex]) { if (ui.children?.[0]) { ui.children[0].attributes.tabindex = this[$tabIndex]; } else { ui.attributes.tabindex = this[$tabIndex]; } } if (!ui.attributes.style) { ui.attributes.style = Object.create(null); } let aElement = null; if (this.ui.button) { if (ui.children.length === 1) { [aElement] = ui.children.splice(0, 1); } Object.assign(ui.attributes.style, borderStyle); } else { Object.assign(style, borderStyle); } children.push(ui); if (this.value) { if (this.ui.imageEdit) { ui.children.push(this.value[$toHTML]().html); } else if (!this.ui.button) { let value = ""; if (this.value.exData) { value = this.value.exData[$text](); } else if (this.value.text) { value = this.value.text[$getExtra](); } else { const htmlValue = this.value[$toHTML]().html; if (htmlValue !== null) { value = htmlValue.children[0].value; } } if (this.ui.textEdit && this.value.text?.maxChars) { ui.children[0].attributes.maxLength = this.value.text.maxChars; } if (value) { if (this.ui.numericEdit) { value = parseFloat(value); value = isNaN(value) ? "" : value.toString(); } if (ui.children[0].name === "textarea") { ui.children[0].attributes.textContent = value; } else { ui.children[0].attributes.value = value; } } } } if (!this.ui.imageEdit && ui.children?.[0] && this.h) { borderDims = borderDims || getBorderDims(this.ui[$getExtra]()); let captionHeight = 0; if (this.caption && ["top", "bottom"].includes(this.caption.placement)) { captionHeight = this.caption.reserve; if (captionHeight <= 0) { captionHeight = this.caption[$getExtra](availableSpace).h; } const inputHeight = this.h - captionHeight - marginV - borderDims.h; ui.children[0].attributes.style.height = measureToString(inputHeight); } else { ui.children[0].attributes.style.height = "100%"; } } if (aElement) { ui.children.push(aElement); } if (!caption) { if (ui.attributes.class) { ui.attributes.class.push("xfaLeft"); } this.w = savedW; this.h = savedH; return HTMLResult.success(createWrapper(this, html), bbox); } if (this.ui.button) { if (style.padding) { delete style.padding; } if (caption.name === "div") { caption.name = "span"; } ui.children.push(caption); return HTMLResult.success(html, bbox); } else if (this.ui.checkButton) { caption.attributes.class[0] = "xfaCaptionForCheckButton"; } if (!ui.attributes.class) { ui.attributes.class = []; } ui.children.splice(0, 0, caption); switch (this.caption.placement) { case "left": ui.attributes.class.push("xfaLeft"); break; case "right": ui.attributes.class.push("xfaRight"); break; case "top": ui.attributes.class.push("xfaTop"); break; case "bottom": ui.attributes.class.push("xfaBottom"); break; case "inline": ui.attributes.class.push("xfaLeft"); break; } this.w = savedW; this.h = savedH; return HTMLResult.success(createWrapper(this, html), bbox); } } class Fill extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "fill", true); this.id = attributes.id || ""; this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.color = null; this.extras = null; this.linear = null; this.pattern = null; this.radial = null; this.solid = null; this.stipple = null; } [$toStyle]() { const parent = this[$getParent](); const grandpa = parent[$getParent](); const ggrandpa = grandpa[$getParent](); const style = Object.create(null); let propName = "color"; let altPropName = propName; if (parent instanceof Border) { propName = "background-color"; altPropName = "background"; if (ggrandpa instanceof Ui) { style.backgroundColor = "white"; } } if (parent instanceof Rectangle || parent instanceof Arc) { propName = altPropName = "fill"; style.fill = "white"; } for (const name of Object.getOwnPropertyNames(this)) { if (name === "extras" || name === "color") { continue; } const obj = this[name]; if (!(obj instanceof XFAObject)) { continue; } const color = obj[$toStyle](this.color); if (color) { style[color.startsWith("#") ? propName : altPropName] = color; } return style; } if (this.color?.value) { const color = this.color[$toStyle](); style[color.startsWith("#") ? propName : altPropName] = color; } return style; } } class Filter extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "filter", true); this.addRevocationInfo = getStringOption(attributes.addRevocationInfo, ["", "required", "optional", "none"]); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.version = getInteger({ data: this.version, defaultValue: 5, validate: x => x >= 1 && x <= 5 }); this.appearanceFilter = null; this.certificates = null; this.digestMethods = null; this.encodings = null; this.encryptionMethods = null; this.handler = null; this.lockDocument = null; this.mdp = null; this.reasons = null; this.timeStamp = null; } } class Float extends ContentObject { constructor(attributes) { super(TEMPLATE_NS_ID, "float"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$finalize]() { const number = parseFloat(this[$content].trim()); this[$content] = isNaN(number) ? null : number; } [$toHTML](availableSpace) { return valueToHtml(this[$content] !== null ? this[$content].toString() : ""); } } class template_Font extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "font", true); this.baselineShift = getMeasurement(attributes.baselineShift); this.fontHorizontalScale = getFloat({ data: attributes.fontHorizontalScale, defaultValue: 100, validate: x => x >= 0 }); this.fontVerticalScale = getFloat({ data: attributes.fontVerticalScale, defaultValue: 100, validate: x => x >= 0 }); this.id = attributes.id || ""; this.kerningMode = getStringOption(attributes.kerningMode, ["none", "pair"]); this.letterSpacing = getMeasurement(attributes.letterSpacing, "0"); this.lineThrough = getInteger({ data: attributes.lineThrough, defaultValue: 0, validate: x => x === 1 || x === 2 }); this.lineThroughPeriod = getStringOption(attributes.lineThroughPeriod, ["all", "word"]); this.overline = getInteger({ data: attributes.overline, defaultValue: 0, validate: x => x === 1 || x === 2 }); this.overlinePeriod = getStringOption(attributes.overlinePeriod, ["all", "word"]); this.posture = getStringOption(attributes.posture, ["normal", "italic"]); this.size = getMeasurement(attributes.size, "10pt"); this.typeface = attributes.typeface || "Courier"; this.underline = getInteger({ data: attributes.underline, defaultValue: 0, validate: x => x === 1 || x === 2 }); this.underlinePeriod = getStringOption(attributes.underlinePeriod, ["all", "word"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.weight = getStringOption(attributes.weight, ["normal", "bold"]); this.extras = null; this.fill = null; } [$clean](builder) { super[$clean](builder); this[$globalData].usedTypefaces.add(this.typeface); } [$toStyle]() { const style = toStyle(this, "fill"); const color = style.color; if (color) { if (color === "#000000") { delete style.color; } else if (!color.startsWith("#")) { style.background = color; style.backgroundClip = "text"; style.color = "transparent"; } } if (this.baselineShift) { style.verticalAlign = measureToString(this.baselineShift); } style.fontKerning = this.kerningMode === "none" ? "none" : "normal"; style.letterSpacing = measureToString(this.letterSpacing); if (this.lineThrough !== 0) { style.textDecoration = "line-through"; if (this.lineThrough === 2) { style.textDecorationStyle = "double"; } } if (this.overline !== 0) { style.textDecoration = "overline"; if (this.overline === 2) { style.textDecorationStyle = "double"; } } style.fontStyle = this.posture; style.fontSize = measureToString(0.99 * this.size); setFontFamily(this, this, this[$globalData].fontFinder, style); if (this.underline !== 0) { style.textDecoration = "underline"; if (this.underline === 2) { style.textDecorationStyle = "double"; } } style.fontWeight = this.weight; return style; } } class Format extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "format", true); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.picture = null; } } class Handler extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "handler"); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Hyphenation extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "hyphenation"); this.excludeAllCaps = getInteger({ data: attributes.excludeAllCaps, defaultValue: 0, validate: x => x === 1 }); this.excludeInitialCap = getInteger({ data: attributes.excludeInitialCap, defaultValue: 0, validate: x => x === 1 }); this.hyphenate = getInteger({ data: attributes.hyphenate, defaultValue: 0, validate: x => x === 1 }); this.id = attributes.id || ""; this.pushCharacterCount = getInteger({ data: attributes.pushCharacterCount, defaultValue: 3, validate: x => x >= 0 }); this.remainCharacterCount = getInteger({ data: attributes.remainCharacterCount, defaultValue: 3, validate: x => x >= 0 }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.wordCharacterCount = getInteger({ data: attributes.wordCharacterCount, defaultValue: 7, validate: x => x >= 0 }); } } class Image extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "image"); this.aspect = getStringOption(attributes.aspect, ["fit", "actual", "height", "none", "width"]); this.contentType = attributes.contentType || ""; this.href = attributes.href || ""; this.id = attributes.id || ""; this.name = attributes.name || ""; this.transferEncoding = getStringOption(attributes.transferEncoding, ["base64", "none", "package"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$toHTML]() { if (this.contentType && !MIMES.has(this.contentType.toLowerCase())) { return HTMLResult.EMPTY; } let buffer = this[$globalData].images && this[$globalData].images.get(this.href); if (!buffer && (this.href || !this[$content])) { return HTMLResult.EMPTY; } if (!buffer && this.transferEncoding === "base64") { buffer = stringToBytes(atob(this[$content])); } if (!buffer) { return HTMLResult.EMPTY; } if (!this.contentType) { for (const [header, type] of IMAGES_HEADERS) { if (buffer.length > header.length && header.every((x, i) => x === buffer[i])) { this.contentType = type; break; } } if (!this.contentType) { return HTMLResult.EMPTY; } } const blob = new Blob([buffer], { type: this.contentType }); let style; switch (this.aspect) { case "fit": case "actual": break; case "height": style = { height: "100%", objectFit: "fill" }; break; case "none": style = { width: "100%", height: "100%", objectFit: "fill" }; break; case "width": style = { width: "100%", objectFit: "fill" }; break; } const parent = this[$getParent](); return HTMLResult.success({ name: "img", attributes: { class: ["xfaImage"], style, src: URL.createObjectURL(blob), alt: parent ? ariaLabel(parent[$getParent]()) : null } }); } } class ImageEdit extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "imageEdit", true); this.data = getStringOption(attributes.data, ["link", "embed"]); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.border = null; this.extras = null; this.margin = null; } [$toHTML](availableSpace) { if (this.data === "embed") { return HTMLResult.success({ name: "div", children: [], attributes: {} }); } return HTMLResult.EMPTY; } } class Integer extends ContentObject { constructor(attributes) { super(TEMPLATE_NS_ID, "integer"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$finalize]() { const number = parseInt(this[$content].trim(), 10); this[$content] = isNaN(number) ? null : number; } [$toHTML](availableSpace) { return valueToHtml(this[$content] !== null ? this[$content].toString() : ""); } } class Issuers extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "issuers", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.certificate = new XFAObjectArray(); } } class Items extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "items", true); this.id = attributes.id || ""; this.name = attributes.name || ""; this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); this.ref = attributes.ref || ""; this.save = getInteger({ data: attributes.save, defaultValue: 0, validate: x => x === 1 }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.boolean = new XFAObjectArray(); this.date = new XFAObjectArray(); this.dateTime = new XFAObjectArray(); this.decimal = new XFAObjectArray(); this.exData = new XFAObjectArray(); this.float = new XFAObjectArray(); this.image = new XFAObjectArray(); this.integer = new XFAObjectArray(); this.text = new XFAObjectArray(); this.time = new XFAObjectArray(); } [$toHTML]() { const output = []; for (const child of this[$getChildren]()) { output.push(child[$text]()); } return HTMLResult.success(output); } } class Keep extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "keep", true); this.id = attributes.id || ""; const options = ["none", "contentArea", "pageArea"]; this.intact = getStringOption(attributes.intact, options); this.next = getStringOption(attributes.next, options); this.previous = getStringOption(attributes.previous, options); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; } } class KeyUsage extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "keyUsage"); const options = ["", "yes", "no"]; this.crlSign = getStringOption(attributes.crlSign, options); this.dataEncipherment = getStringOption(attributes.dataEncipherment, options); this.decipherOnly = getStringOption(attributes.decipherOnly, options); this.digitalSignature = getStringOption(attributes.digitalSignature, options); this.encipherOnly = getStringOption(attributes.encipherOnly, options); this.id = attributes.id || ""; this.keyAgreement = getStringOption(attributes.keyAgreement, options); this.keyCertSign = getStringOption(attributes.keyCertSign, options); this.keyEncipherment = getStringOption(attributes.keyEncipherment, options); this.nonRepudiation = getStringOption(attributes.nonRepudiation, options); this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Line extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "line", true); this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); this.id = attributes.id || ""; this.slope = getStringOption(attributes.slope, ["\\", "/"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.edge = null; } [$toHTML]() { const parent = this[$getParent]()[$getParent](); const edge = this.edge || new Edge({}); const edgeStyle = edge[$toStyle](); const style = Object.create(null); const thickness = edge.presence === "visible" ? edge.thickness : 0; style.strokeWidth = measureToString(thickness); style.stroke = edgeStyle.color; let x1, y1, x2, y2; let width = "100%"; let height = "100%"; if (parent.w <= thickness) { [x1, y1, x2, y2] = ["50%", 0, "50%", "100%"]; width = style.strokeWidth; } else if (parent.h <= thickness) { [x1, y1, x2, y2] = [0, "50%", "100%", "50%"]; height = style.strokeWidth; } else if (this.slope === "\\") { [x1, y1, x2, y2] = [0, 0, "100%", "100%"]; } else { [x1, y1, x2, y2] = [0, "100%", "100%", 0]; } const line = { name: "line", attributes: { xmlns: SVG_NS, x1, y1, x2, y2, style } }; const svg = { name: "svg", children: [line], attributes: { xmlns: SVG_NS, width, height, style: { overflow: "visible" } } }; if (hasMargin(parent)) { return HTMLResult.success({ name: "div", attributes: { style: { display: "inline", width: "100%", height: "100%" } }, children: [svg] }); } svg.attributes.style.position = "absolute"; return HTMLResult.success(svg); } } class Linear extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "linear", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["toRight", "toBottom", "toLeft", "toTop"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.color = null; this.extras = null; } [$toStyle](startColor) { startColor = startColor ? startColor[$toStyle]() : "#FFFFFF"; const transf = this.type.replace(/([RBLT])/, " $1").toLowerCase(); const endColor = this.color ? this.color[$toStyle]() : "#000000"; return `linear-gradient(${transf}, ${startColor}, ${endColor})`; } } class LockDocument extends ContentObject { constructor(attributes) { super(TEMPLATE_NS_ID, "lockDocument"); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$finalize]() { this[$content] = getStringOption(this[$content], ["auto", "0", "1"]); } } class Manifest extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "manifest", true); this.action = getStringOption(attributes.action, ["include", "all", "exclude"]); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.ref = new XFAObjectArray(); } } class Margin extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "margin", true); this.bottomInset = getMeasurement(attributes.bottomInset, "0"); this.id = attributes.id || ""; this.leftInset = getMeasurement(attributes.leftInset, "0"); this.rightInset = getMeasurement(attributes.rightInset, "0"); this.topInset = getMeasurement(attributes.topInset, "0"); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; } [$toStyle]() { return { margin: measureToString(this.topInset) + " " + measureToString(this.rightInset) + " " + measureToString(this.bottomInset) + " " + measureToString(this.leftInset) }; } } class Mdp extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "mdp"); this.id = attributes.id || ""; this.permissions = getInteger({ data: attributes.permissions, defaultValue: 2, validate: x => x === 1 || x === 3 }); this.signatureType = getStringOption(attributes.signatureType, ["filler", "author"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Medium extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "medium"); this.id = attributes.id || ""; this.imagingBBox = getBBox(attributes.imagingBBox); this.long = getMeasurement(attributes.long); this.orientation = getStringOption(attributes.orientation, ["portrait", "landscape"]); this.short = getMeasurement(attributes.short); this.stock = attributes.stock || ""; this.trayIn = getStringOption(attributes.trayIn, ["auto", "delegate", "pageFront"]); this.trayOut = getStringOption(attributes.trayOut, ["auto", "delegate"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Message extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "message", true); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.text = new XFAObjectArray(); } } class NumericEdit extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "numericEdit", true); this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.border = null; this.comb = null; this.extras = null; this.margin = null; } [$toHTML](availableSpace) { const style = toStyle(this, "border", "font", "margin"); const field = this[$getParent]()[$getParent](); const html = { name: "input", attributes: { type: "text", fieldId: field[$uid], dataId: field[$data]?.[$uid] || field[$uid], class: ["xfaTextfield"], style, "aria-label": ariaLabel(field), "aria-required": false } }; if (isRequired(field)) { html.attributes["aria-required"] = true; html.attributes.required = true; } return HTMLResult.success({ name: "label", attributes: { class: ["xfaLabel"] }, children: [html] }); } } class Occur extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "occur", true); this.id = attributes.id || ""; this.initial = attributes.initial !== "" ? getInteger({ data: attributes.initial, defaultValue: "", validate: x => true }) : ""; this.max = attributes.max !== "" ? getInteger({ data: attributes.max, defaultValue: 1, validate: x => true }) : ""; this.min = attributes.min !== "" ? getInteger({ data: attributes.min, defaultValue: 1, validate: x => true }) : ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; } [$clean]() { const parent = this[$getParent](); const originalMin = this.min; if (this.min === "") { this.min = parent instanceof PageArea || parent instanceof PageSet ? 0 : 1; } if (this.max === "") { if (originalMin === "") { this.max = parent instanceof PageArea || parent instanceof PageSet ? -1 : 1; } else { this.max = this.min; } } if (this.max !== -1 && this.max < this.min) { this.max = this.min; } if (this.initial === "") { this.initial = parent instanceof Template ? 1 : this.min; } } } class Oid extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "oid"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Oids extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "oids", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.oid = new XFAObjectArray(); } } class Overflow extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "overflow"); this.id = attributes.id || ""; this.leader = attributes.leader || ""; this.target = attributes.target || ""; this.trailer = attributes.trailer || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$getExtra]() { if (!this[$extra]) { const parent = this[$getParent](); const root = this[$getTemplateRoot](); const target = root[$searchNode](this.target, parent); const leader = root[$searchNode](this.leader, parent); const trailer = root[$searchNode](this.trailer, parent); this[$extra] = { target: target?.[0] || null, leader: leader?.[0] || null, trailer: trailer?.[0] || null, addLeader: false, addTrailer: false }; } return this[$extra]; } } class PageArea extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "pageArea", true); this.blankOrNotBlank = getStringOption(attributes.blankOrNotBlank, ["any", "blank", "notBlank"]); this.id = attributes.id || ""; this.initialNumber = getInteger({ data: attributes.initialNumber, defaultValue: 1, validate: x => true }); this.name = attributes.name || ""; this.numbered = getInteger({ data: attributes.numbered, defaultValue: 1, validate: x => true }); this.oddOrEven = getStringOption(attributes.oddOrEven, ["any", "even", "odd"]); this.pagePosition = getStringOption(attributes.pagePosition, ["any", "first", "last", "only", "rest"]); this.relevant = getRelevant(attributes.relevant); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.desc = null; this.extras = null; this.medium = null; this.occur = null; this.area = new XFAObjectArray(); this.contentArea = new XFAObjectArray(); this.draw = new XFAObjectArray(); this.exclGroup = new XFAObjectArray(); this.field = new XFAObjectArray(); this.subform = new XFAObjectArray(); } [$isUsable]() { if (!this[$extra]) { this[$extra] = { numberOfUse: 0 }; return true; } return !this.occur || this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max; } [$cleanPage]() { delete this[$extra]; } [$getNextPage]() { if (!this[$extra]) { this[$extra] = { numberOfUse: 0 }; } const parent = this[$getParent](); if (parent.relation === "orderedOccurrence") { if (this[$isUsable]()) { this[$extra].numberOfUse += 1; return this; } } return parent[$getNextPage](); } [$getAvailableSpace]() { return this[$extra].space || { width: 0, height: 0 }; } [$toHTML]() { if (!this[$extra]) { this[$extra] = { numberOfUse: 1 }; } const children = []; this[$extra].children = children; const style = Object.create(null); if (this.medium && this.medium.short && this.medium.long) { style.width = measureToString(this.medium.short); style.height = measureToString(this.medium.long); this[$extra].space = { width: this.medium.short, height: this.medium.long }; if (this.medium.orientation === "landscape") { const x = style.width; style.width = style.height; style.height = x; this[$extra].space = { width: this.medium.long, height: this.medium.short }; } } else { warn("XFA - No medium specified in pageArea: please file a bug."); } this[$childrenToHTML]({ filter: new Set(["area", "draw", "field", "subform"]), include: true }); this[$childrenToHTML]({ filter: new Set(["contentArea"]), include: true }); return HTMLResult.success({ name: "div", children, attributes: { class: ["xfaPage"], id: this[$uid], style, xfaName: this.name } }); } } class PageSet extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "pageSet", true); this.duplexImposition = getStringOption(attributes.duplexImposition, ["longEdge", "shortEdge"]); this.id = attributes.id || ""; this.name = attributes.name || ""; this.relation = getStringOption(attributes.relation, ["orderedOccurrence", "duplexPaginated", "simplexPaginated"]); this.relevant = getRelevant(attributes.relevant); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; this.occur = null; this.pageArea = new XFAObjectArray(); this.pageSet = new XFAObjectArray(); } [$cleanPage]() { for (const page of this.pageArea.children) { page[$cleanPage](); } for (const page of this.pageSet.children) { page[$cleanPage](); } } [$isUsable]() { return !this.occur || this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max; } [$getNextPage]() { if (!this[$extra]) { this[$extra] = { numberOfUse: 1, pageIndex: -1, pageSetIndex: -1 }; } if (this.relation === "orderedOccurrence") { if (this[$extra].pageIndex + 1 < this.pageArea.children.length) { this[$extra].pageIndex += 1; const pageArea = this.pageArea.children[this[$extra].pageIndex]; return pageArea[$getNextPage](); } if (this[$extra].pageSetIndex + 1 < this.pageSet.children.length) { this[$extra].pageSetIndex += 1; return this.pageSet.children[this[$extra].pageSetIndex][$getNextPage](); } if (this[$isUsable]()) { this[$extra].numberOfUse += 1; this[$extra].pageIndex = -1; this[$extra].pageSetIndex = -1; return this[$getNextPage](); } const parent = this[$getParent](); if (parent instanceof PageSet) { return parent[$getNextPage](); } this[$cleanPage](); return this[$getNextPage](); } const pageNumber = this[$getTemplateRoot]()[$extra].pageNumber; const parity = pageNumber % 2 === 0 ? "even" : "odd"; const position = pageNumber === 0 ? "first" : "rest"; let page = this.pageArea.children.find(p => p.oddOrEven === parity && p.pagePosition === position); if (page) { return page; } page = this.pageArea.children.find(p => p.oddOrEven === "any" && p.pagePosition === position); if (page) { return page; } page = this.pageArea.children.find(p => p.oddOrEven === "any" && p.pagePosition === "any"); if (page) { return page; } return this.pageArea.children[0]; } } class Para extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "para", true); this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); this.id = attributes.id || ""; this.lineHeight = attributes.lineHeight ? getMeasurement(attributes.lineHeight, "0pt") : ""; this.marginLeft = attributes.marginLeft ? getMeasurement(attributes.marginLeft, "0pt") : ""; this.marginRight = attributes.marginRight ? getMeasurement(attributes.marginRight, "0pt") : ""; this.orphans = getInteger({ data: attributes.orphans, defaultValue: 0, validate: x => x >= 0 }); this.preserve = attributes.preserve || ""; this.radixOffset = attributes.radixOffset ? getMeasurement(attributes.radixOffset, "0pt") : ""; this.spaceAbove = attributes.spaceAbove ? getMeasurement(attributes.spaceAbove, "0pt") : ""; this.spaceBelow = attributes.spaceBelow ? getMeasurement(attributes.spaceBelow, "0pt") : ""; this.tabDefault = attributes.tabDefault ? getMeasurement(this.tabDefault) : ""; this.tabStops = (attributes.tabStops || "").trim().split(/\s+/).map((x, i) => i % 2 === 1 ? getMeasurement(x) : x); this.textIndent = attributes.textIndent ? getMeasurement(attributes.textIndent, "0pt") : ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.vAlign = getStringOption(attributes.vAlign, ["top", "bottom", "middle"]); this.widows = getInteger({ data: attributes.widows, defaultValue: 0, validate: x => x >= 0 }); this.hyphenation = null; } [$toStyle]() { const style = toStyle(this, "hAlign"); if (this.marginLeft !== "") { style.paddingLeft = measureToString(this.marginLeft); } if (this.marginRight !== "") { style.paddingight = measureToString(this.marginRight); } if (this.spaceAbove !== "") { style.paddingTop = measureToString(this.spaceAbove); } if (this.spaceBelow !== "") { style.paddingBottom = measureToString(this.spaceBelow); } if (this.textIndent !== "") { style.textIndent = measureToString(this.textIndent); fixTextIndent(style); } if (this.lineHeight > 0) { style.lineHeight = measureToString(this.lineHeight); } if (this.tabDefault !== "") { style.tabSize = measureToString(this.tabDefault); } if (this.tabStops.length > 0) {} if (this.hyphenatation) { Object.assign(style, this.hyphenatation[$toStyle]()); } return style; } } class PasswordEdit extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "passwordEdit", true); this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); this.id = attributes.id || ""; this.passwordChar = attributes.passwordChar || "*"; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.border = null; this.extras = null; this.margin = null; } } class template_Pattern extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "pattern", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["crossHatch", "crossDiagonal", "diagonalLeft", "diagonalRight", "horizontal", "vertical"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.color = null; this.extras = null; } [$toStyle](startColor) { startColor = startColor ? startColor[$toStyle]() : "#FFFFFF"; const endColor = this.color ? this.color[$toStyle]() : "#000000"; const width = 5; const cmd = "repeating-linear-gradient"; const colors = `${startColor},${startColor} ${width}px,${endColor} ${width}px,${endColor} ${2 * width}px`; switch (this.type) { case "crossHatch": return `${cmd}(to top,${colors}) ${cmd}(to right,${colors})`; case "crossDiagonal": return `${cmd}(45deg,${colors}) ${cmd}(-45deg,${colors})`; case "diagonalLeft": return `${cmd}(45deg,${colors})`; case "diagonalRight": return `${cmd}(-45deg,${colors})`; case "horizontal": return `${cmd}(to top,${colors})`; case "vertical": return `${cmd}(to right,${colors})`; } return ""; } } class Picture extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "picture"); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Proto extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "proto", true); this.appearanceFilter = new XFAObjectArray(); this.arc = new XFAObjectArray(); this.area = new XFAObjectArray(); this.assist = new XFAObjectArray(); this.barcode = new XFAObjectArray(); this.bindItems = new XFAObjectArray(); this.bookend = new XFAObjectArray(); this.boolean = new XFAObjectArray(); this.border = new XFAObjectArray(); this.break = new XFAObjectArray(); this.breakAfter = new XFAObjectArray(); this.breakBefore = new XFAObjectArray(); this.button = new XFAObjectArray(); this.calculate = new XFAObjectArray(); this.caption = new XFAObjectArray(); this.certificate = new XFAObjectArray(); this.certificates = new XFAObjectArray(); this.checkButton = new XFAObjectArray(); this.choiceList = new XFAObjectArray(); this.color = new XFAObjectArray(); this.comb = new XFAObjectArray(); this.connect = new XFAObjectArray(); this.contentArea = new XFAObjectArray(); this.corner = new XFAObjectArray(); this.date = new XFAObjectArray(); this.dateTime = new XFAObjectArray(); this.dateTimeEdit = new XFAObjectArray(); this.decimal = new XFAObjectArray(); this.defaultUi = new XFAObjectArray(); this.desc = new XFAObjectArray(); this.digestMethod = new XFAObjectArray(); this.digestMethods = new XFAObjectArray(); this.draw = new XFAObjectArray(); this.edge = new XFAObjectArray(); this.encoding = new XFAObjectArray(); this.encodings = new XFAObjectArray(); this.encrypt = new XFAObjectArray(); this.encryptData = new XFAObjectArray(); this.encryption = new XFAObjectArray(); this.encryptionMethod = new XFAObjectArray(); this.encryptionMethods = new XFAObjectArray(); this.event = new XFAObjectArray(); this.exData = new XFAObjectArray(); this.exObject = new XFAObjectArray(); this.exclGroup = new XFAObjectArray(); this.execute = new XFAObjectArray(); this.extras = new XFAObjectArray(); this.field = new XFAObjectArray(); this.fill = new XFAObjectArray(); this.filter = new XFAObjectArray(); this.float = new XFAObjectArray(); this.font = new XFAObjectArray(); this.format = new XFAObjectArray(); this.handler = new XFAObjectArray(); this.hyphenation = new XFAObjectArray(); this.image = new XFAObjectArray(); this.imageEdit = new XFAObjectArray(); this.integer = new XFAObjectArray(); this.issuers = new XFAObjectArray(); this.items = new XFAObjectArray(); this.keep = new XFAObjectArray(); this.keyUsage = new XFAObjectArray(); this.line = new XFAObjectArray(); this.linear = new XFAObjectArray(); this.lockDocument = new XFAObjectArray(); this.manifest = new XFAObjectArray(); this.margin = new XFAObjectArray(); this.mdp = new XFAObjectArray(); this.medium = new XFAObjectArray(); this.message = new XFAObjectArray(); this.numericEdit = new XFAObjectArray(); this.occur = new XFAObjectArray(); this.oid = new XFAObjectArray(); this.oids = new XFAObjectArray(); this.overflow = new XFAObjectArray(); this.pageArea = new XFAObjectArray(); this.pageSet = new XFAObjectArray(); this.para = new XFAObjectArray(); this.passwordEdit = new XFAObjectArray(); this.pattern = new XFAObjectArray(); this.picture = new XFAObjectArray(); this.radial = new XFAObjectArray(); this.reason = new XFAObjectArray(); this.reasons = new XFAObjectArray(); this.rectangle = new XFAObjectArray(); this.ref = new XFAObjectArray(); this.script = new XFAObjectArray(); this.setProperty = new XFAObjectArray(); this.signData = new XFAObjectArray(); this.signature = new XFAObjectArray(); this.signing = new XFAObjectArray(); this.solid = new XFAObjectArray(); this.speak = new XFAObjectArray(); this.stipple = new XFAObjectArray(); this.subform = new XFAObjectArray(); this.subformSet = new XFAObjectArray(); this.subjectDN = new XFAObjectArray(); this.subjectDNs = new XFAObjectArray(); this.submit = new XFAObjectArray(); this.text = new XFAObjectArray(); this.textEdit = new XFAObjectArray(); this.time = new XFAObjectArray(); this.timeStamp = new XFAObjectArray(); this.toolTip = new XFAObjectArray(); this.traversal = new XFAObjectArray(); this.traverse = new XFAObjectArray(); this.ui = new XFAObjectArray(); this.validate = new XFAObjectArray(); this.value = new XFAObjectArray(); this.variables = new XFAObjectArray(); } } class Radial extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "radial", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["toEdge", "toCenter"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.color = null; this.extras = null; } [$toStyle](startColor) { startColor = startColor ? startColor[$toStyle]() : "#FFFFFF"; const endColor = this.color ? this.color[$toStyle]() : "#000000"; const colors = this.type === "toEdge" ? `${startColor},${endColor}` : `${endColor},${startColor}`; return `radial-gradient(circle at center, ${colors})`; } } class Reason extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "reason"); this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Reasons extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "reasons", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.reason = new XFAObjectArray(); } } class Rectangle extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "rectangle", true); this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.corner = new XFAObjectArray(4); this.edge = new XFAObjectArray(4); this.fill = null; } [$toHTML]() { const edge = this.edge.children.length ? this.edge.children[0] : new Edge({}); const edgeStyle = edge[$toStyle](); const style = Object.create(null); if (this.fill?.presence === "visible") { Object.assign(style, this.fill[$toStyle]()); } else { style.fill = "transparent"; } style.strokeWidth = measureToString(edge.presence === "visible" ? edge.thickness : 0); style.stroke = edgeStyle.color; const corner = this.corner.children.length ? this.corner.children[0] : new Corner({}); const cornerStyle = corner[$toStyle](); const rect = { name: "rect", attributes: { xmlns: SVG_NS, width: "100%", height: "100%", x: 0, y: 0, rx: cornerStyle.radius, ry: cornerStyle.radius, style } }; const svg = { name: "svg", children: [rect], attributes: { xmlns: SVG_NS, style: { overflow: "visible" }, width: "100%", height: "100%" } }; const parent = this[$getParent]()[$getParent](); if (hasMargin(parent)) { return HTMLResult.success({ name: "div", attributes: { style: { display: "inline", width: "100%", height: "100%" } }, children: [svg] }); } svg.attributes.style.position = "absolute"; return HTMLResult.success(svg); } } class RefElement extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "ref"); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Script extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "script"); this.binding = attributes.binding || ""; this.contentType = attributes.contentType || ""; this.id = attributes.id || ""; this.name = attributes.name || ""; this.runAt = getStringOption(attributes.runAt, ["client", "both", "server"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class SetProperty extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "setProperty"); this.connection = attributes.connection || ""; this.ref = attributes.ref || ""; this.target = attributes.target || ""; } } class SignData extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "signData", true); this.id = attributes.id || ""; this.operation = getStringOption(attributes.operation, ["sign", "clear", "verify"]); this.ref = attributes.ref || ""; this.target = attributes.target || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.filter = null; this.manifest = null; } } class Signature extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "signature", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["PDF1.3", "PDF1.6"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.border = null; this.extras = null; this.filter = null; this.manifest = null; this.margin = null; } } class Signing extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "signing", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.certificate = new XFAObjectArray(); } } class Solid extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "solid", true); this.id = attributes.id || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.extras = null; } [$toStyle](startColor) { return startColor ? startColor[$toStyle]() : "#FFFFFF"; } } class Speak extends StringObject { constructor(attributes) { super(TEMPLATE_NS_ID, "speak"); this.disable = getInteger({ data: attributes.disable, defaultValue: 0, validate: x => x === 1 }); this.id = attributes.id || ""; this.priority = getStringOption(attributes.priority, ["custom", "caption", "name", "toolTip"]); this.rid = attributes.rid || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } } class Stipple extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "stipple", true); this.id = attributes.id || ""; this.rate = getInteger({ data: attributes.rate, defaultValue: 50, validate: x => x >= 0 && x <= 100 }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.color = null; this.extras = null; } [$toStyle](bgColor) { const alpha = this.rate / 100; return Util.makeHexColor(Math.round(bgColor.value.r * (1 - alpha) + this.value.r * alpha), Math.round(bgColor.value.g * (1 - alpha) + this.value.g * alpha), Math.round(bgColor.value.b * (1 - alpha) + this.value.b * alpha)); } } class Subform extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "subform", true); this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); this.allowMacro = getInteger({ data: attributes.allowMacro, defaultValue: 0, validate: x => x === 1 }); this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); this.colSpan = getInteger({ data: attributes.colSpan, defaultValue: 1, validate: n => n >= 1 || n === -1 }); this.columnWidths = (attributes.columnWidths || "").trim().split(/\s+/).map(x => x === "-1" ? -1 : getMeasurement(x)); this.h = attributes.h ? getMeasurement(attributes.h) : ""; this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); this.id = attributes.id || ""; this.layout = getStringOption(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]); this.locale = attributes.locale || ""; this.maxH = getMeasurement(attributes.maxH, "0pt"); this.maxW = getMeasurement(attributes.maxW, "0pt"); this.mergeMode = getStringOption(attributes.mergeMode, ["consumeData", "matchTemplate"]); this.minH = getMeasurement(attributes.minH, "0pt"); this.minW = getMeasurement(attributes.minW, "0pt"); this.name = attributes.name || ""; this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); this.relevant = getRelevant(attributes.relevant); this.restoreState = getStringOption(attributes.restoreState, ["manual", "auto"]); this.scope = getStringOption(attributes.scope, ["name", "none"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.w = attributes.w ? getMeasurement(attributes.w) : ""; this.x = getMeasurement(attributes.x, "0pt"); this.y = getMeasurement(attributes.y, "0pt"); this.assist = null; this.bind = null; this.bookend = null; this.border = null; this.break = null; this.calculate = null; this.desc = null; this.extras = null; this.keep = null; this.margin = null; this.occur = null; this.overflow = null; this.pageSet = null; this.para = null; this.traversal = null; this.validate = null; this.variables = null; this.area = new XFAObjectArray(); this.breakAfter = new XFAObjectArray(); this.breakBefore = new XFAObjectArray(); this.connect = new XFAObjectArray(); this.draw = new XFAObjectArray(); this.event = new XFAObjectArray(); this.exObject = new XFAObjectArray(); this.exclGroup = new XFAObjectArray(); this.field = new XFAObjectArray(); this.proto = new XFAObjectArray(); this.setProperty = new XFAObjectArray(); this.subform = new XFAObjectArray(); this.subformSet = new XFAObjectArray(); } [$getSubformParent]() { const parent = this[$getParent](); if (parent instanceof SubformSet) { return parent[$getSubformParent](); } return parent; } [$isBindable]() { return true; } [$isThereMoreWidth]() { return this.layout.endsWith("-tb") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth](); } *[$getContainedChildren]() { yield* getContainedChildren(this); } [$flushHTML]() { return flushHTML(this); } [$addHTML](html, bbox) { addHTML(this, html, bbox); } [$getAvailableSpace]() { return getAvailableSpace(this); } [$isSplittable]() { const parent = this[$getSubformParent](); if (!parent[$isSplittable]()) { return false; } if (this[$extra]._isSplittable !== undefined) { return this[$extra]._isSplittable; } if (this.layout === "position" || this.layout.includes("row")) { this[$extra]._isSplittable = false; return false; } if (this.keep && this.keep.intact !== "none") { this[$extra]._isSplittable = false; return false; } if (parent.layout?.endsWith("-tb") && parent[$extra].numberInLine !== 0) { return false; } this[$extra]._isSplittable = true; return true; } [$toHTML](availableSpace) { setTabIndex(this); if (this.break) { if (this.break.after !== "auto" || this.break.afterTarget !== "") { const node = new BreakAfter({ targetType: this.break.after, target: this.break.afterTarget, startNew: this.break.startNew.toString() }); node[$globalData] = this[$globalData]; this[$appendChild](node); this.breakAfter.push(node); } if (this.break.before !== "auto" || this.break.beforeTarget !== "") { const node = new BreakBefore({ targetType: this.break.before, target: this.break.beforeTarget, startNew: this.break.startNew.toString() }); node[$globalData] = this[$globalData]; this[$appendChild](node); this.breakBefore.push(node); } if (this.break.overflowTarget !== "") { const node = new Overflow({ target: this.break.overflowTarget, leader: this.break.overflowLeader, trailer: this.break.overflowTrailer }); node[$globalData] = this[$globalData]; this[$appendChild](node); this.overflow.push(node); } this[$removeChild](this.break); this.break = null; } if (this.presence === "hidden" || this.presence === "inactive") { return HTMLResult.EMPTY; } if (this.breakBefore.children.length > 1 || this.breakAfter.children.length > 1) { warn("XFA - Several breakBefore or breakAfter in subforms: please file a bug."); } if (this.breakBefore.children.length >= 1) { const breakBefore = this.breakBefore.children[0]; if (handleBreak(breakBefore)) { return HTMLResult.breakNode(breakBefore); } } if (this[$extra]?.afterBreakAfter) { return HTMLResult.EMPTY; } fixDimensions(this); const children = []; const attributes = { id: this[$uid], class: [] }; setAccess(this, attributes.class); if (!this[$extra]) { this[$extra] = Object.create(null); } Object.assign(this[$extra], { children, line: null, attributes, attempt: 0, numberInLine: 0, availableSpace: { width: Math.min(this.w || Infinity, availableSpace.width), height: Math.min(this.h || Infinity, availableSpace.height) }, width: 0, height: 0, prevHeight: 0, currentWidth: 0 }); const root = this[$getTemplateRoot](); const savedNoLayoutFailure = root[$extra].noLayoutFailure; const isSplittable = this[$isSplittable](); if (!isSplittable) { setFirstUnsplittable(this); } if (!checkDimensions(this, availableSpace)) { return HTMLResult.FAILURE; } const filter = new Set(["area", "draw", "exclGroup", "field", "subform", "subformSet"]); if (this.layout.includes("row")) { const columnWidths = this[$getSubformParent]().columnWidths; if (Array.isArray(columnWidths) && columnWidths.length > 0) { this[$extra].columnWidths = columnWidths; this[$extra].currentColumn = 0; } } const style = toStyle(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign"); const classNames = ["xfaSubform"]; const cl = layoutClass(this); if (cl) { classNames.push(cl); } attributes.style = style; attributes.class = classNames; if (this.name) { attributes.xfaName = this.name; } if (this.overflow) { const overflowExtra = this.overflow[$getExtra](); if (overflowExtra.addLeader) { overflowExtra.addLeader = false; handleOverflow(this, overflowExtra.leader, availableSpace); } } this[$pushPara](); const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb"; const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1; for (; this[$extra].attempt < maxRun; this[$extra].attempt++) { if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) { this[$extra].numberInLine = 0; } const result = this[$childrenToHTML]({ filter, include: true }); if (result.success) { break; } if (result.isBreak()) { this[$popPara](); return result; } if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !root[$extra].noLayoutFailure) { this[$extra].attempt = maxRun; break; } } this[$popPara](); if (!isSplittable) { unsetFirstUnsplittable(this); } root[$extra].noLayoutFailure = savedNoLayoutFailure; if (this[$extra].attempt === maxRun) { if (this.overflow) { this[$getTemplateRoot]()[$extra].overflowNode = this.overflow; } if (!isSplittable) { delete this[$extra]; } return HTMLResult.FAILURE; } if (this.overflow) { const overflowExtra = this.overflow[$getExtra](); if (overflowExtra.addTrailer) { overflowExtra.addTrailer = false; handleOverflow(this, overflowExtra.trailer, availableSpace); } } let marginH = 0; let marginV = 0; if (this.margin) { marginH = this.margin.leftInset + this.margin.rightInset; marginV = this.margin.topInset + this.margin.bottomInset; } const width = Math.max(this[$extra].width + marginH, this.w || 0); const height = Math.max(this[$extra].height + marginV, this.h || 0); const bbox = [this.x, this.y, width, height]; if (this.w === "") { style.width = measureToString(width); } if (this.h === "") { style.height = measureToString(height); } if ((style.width === "0px" || style.height === "0px") && children.length === 0) { return HTMLResult.EMPTY; } const html = { name: "div", attributes, children }; applyAssist(this, attributes); const result = HTMLResult.success(createWrapper(this, html), bbox); if (this.breakAfter.children.length >= 1) { const breakAfter = this.breakAfter.children[0]; if (handleBreak(breakAfter)) { this[$extra].afterBreakAfter = result; return HTMLResult.breakNode(breakAfter); } } delete this[$extra]; return result; } } class SubformSet extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "subformSet", true); this.id = attributes.id || ""; this.name = attributes.name || ""; this.relation = getStringOption(attributes.relation, ["ordered", "choice", "unordered"]); this.relevant = getRelevant(attributes.relevant); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.bookend = null; this.break = null; this.desc = null; this.extras = null; this.occur = null; this.overflow = null; this.breakAfter = new XFAObjectArray(); this.breakBefore = new XFAObjectArray(); this.subform = new XFAObjectArray(); this.subformSet = new XFAObjectArray(); } *[$getContainedChildren]() { yield* getContainedChildren(this); } [$getSubformParent]() { let parent = this[$getParent](); while (!(parent instanceof Subform)) { parent = parent[$getParent](); } return parent; } [$isBindable]() { return true; } } class SubjectDN extends ContentObject { constructor(attributes) { super(TEMPLATE_NS_ID, "subjectDN"); this.delimiter = attributes.delimiter || ","; this.id = attributes.id || ""; this.name = attributes.name || ""; this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; } [$finalize]() { this[$content] = new Map(this[$content].split(this.delimiter).map(kv => { kv = kv.split("=", 2); kv[0] = kv[0].trim(); return kv; })); } } class SubjectDNs extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "subjectDNs", true); this.id = attributes.id || ""; this.type = getStringOption(attributes.type, ["optional", "required"]); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.subjectDN = new XFAObjectArray(); } } class Submit extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "submit", true); this.embedPDF = getInteger({ data: attributes.embedPDF, defaultValue: 0, validate: x => x === 1 }); this.format = getStringOption(attributes.format, ["xdp", "formdata", "pdf", "urlencoded", "xfd", "xml"]); this.id = attributes.id || ""; this.target = attributes.target || ""; this.textEncoding = getKeyword({ data: attributes.textEncoding ? attributes.textEncoding.toLowerCase() : "", defaultValue: "", validate: k => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/) }); this.use = attributes.use || ""; this.usehref = attributes.usehref || ""; this.xdpContent = attributes.xdpContent || ""; this.encrypt = null; this.encryptData = new XFAObjectArray(); this.signData = new XFAObjectArray(); } } class Template extends XFAObject { constructor(attributes) { super(TEMPLATE_NS_ID, "template", true); this.baseProfile = getStringOption(attributes.baseProfile, ["full", "interactiveForms"]); this.extras = null; this.subform = new XFAObjectArray(); } [$finalize]() { if (this.subform.children.length === 0) { warn("XFA - No subforms in template node."); } if (this.subform.children.length >= 2) { warn("XFA - Several subforms in template node: please file a bug."); } this[$tabIndex] = DEFAULT_TAB_INDEX; } [$isSplittable]() { return true; } [$searchNode](expr, container) { if (expr.startsWith("#")) { return [this[$ids].get(expr.slice(1))]; } return searchNode(this, container, expr, true, true); }
•
Search:
•
Replace:
1
2
3
4
5
6
7
Function
Edit by line
Download
Information
Rename
Copy
Move
Delete
Chmod
List