@cantoo/pdf-lib
Version:
Create and modify PDF files with JavaScript
159 lines • 6.96 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.findLastMatch = exports.parseDate = exports.breakTextIntoLines = exports.charSplit = exports.charAtIndex = exports.mergeLines = exports.lineSplit = exports.isNewlineChar = exports.newlineChars = exports.escapedNewlineChars = exports.cleanText = exports.escapeRegExp = exports.addRandomSuffix = exports.copyStringIntoBuffer = exports.stringAsByteArray = exports.padStart = exports.charFromHexCode = exports.charFromCode = exports.toHexString = exports.toHexStringOfMinLength = exports.toCodePoint = exports.toCharCode = void 0;
const toCharCode = (character) => character.charCodeAt(0);
exports.toCharCode = toCharCode;
const toCodePoint = (character) => character.codePointAt(0);
exports.toCodePoint = toCodePoint;
const toHexStringOfMinLength = (num, minLength) => (0, exports.padStart)(num.toString(16), minLength, '0').toUpperCase();
exports.toHexStringOfMinLength = toHexStringOfMinLength;
const toHexString = (num) => (0, exports.toHexStringOfMinLength)(num, 2);
exports.toHexString = toHexString;
const charFromCode = (code) => String.fromCharCode(code);
exports.charFromCode = charFromCode;
const charFromHexCode = (hex) => (0, exports.charFromCode)(parseInt(hex, 16));
exports.charFromHexCode = charFromHexCode;
const padStart = (value, length, padChar) => {
let padding = '';
for (let idx = 0, len = length - value.length; idx < len; idx++) {
padding += padChar;
}
return padding + value;
};
exports.padStart = padStart;
const stringAsByteArray = (str) => {
const buffer = new Uint8Array(str.length);
(0, exports.copyStringIntoBuffer)(str, buffer, 0);
return buffer;
};
exports.stringAsByteArray = stringAsByteArray;
const copyStringIntoBuffer = (str, buffer, offset) => {
const length = str.length;
for (let idx = 0; idx < length; idx++) {
buffer[offset++] = str.charCodeAt(idx);
}
return length;
};
exports.copyStringIntoBuffer = copyStringIntoBuffer;
const addRandomSuffix = (prefix, suffixLength = 4) => `${prefix}-${Math.floor(Math.random() * Math.pow(10, suffixLength))}`;
exports.addRandomSuffix = addRandomSuffix;
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
exports.escapeRegExp = escapeRegExp;
const cleanText = (text) => text.replace(/\t|\u0085|\u2028|\u2029/g, ' ').replace(/[\b\v]/g, '');
exports.cleanText = cleanText;
exports.escapedNewlineChars = ['\\n', '\\f', '\\r', '\\u000B'];
exports.newlineChars = ['\n', '\f', '\r', '\u000B'];
// eslint-disable-next-line no-control-regex
const isNewlineChar = (text) => /^[\n\f\r\u000B]$/.test(text);
exports.isNewlineChar = isNewlineChar;
// eslint-disable-next-line no-control-regex
const lineSplit = (text) => text.split(/[\n\f\r\u000B]/);
exports.lineSplit = lineSplit;
const mergeLines = (text) =>
// eslint-disable-next-line no-control-regex
text.replace(/[\n\f\r\u000B]/g, ' ');
exports.mergeLines = mergeLines;
// JavaScript's String.charAt() method doesn work on strings containing UTF-16
// characters (with high and low surrogate pairs), such as 💩 (poo emoji). This
// `charAtIndex()` function does.
//
// Credit: https://github.com/mathiasbynens/String.prototype.at/blob/master/at.js#L14-L48
const charAtIndex = (text, index) => {
// Get the first code unit and code unit value
const cuFirst = text.charCodeAt(index);
let cuSecond;
const nextIndex = index + 1;
let length = 1;
if (
// Check if it's the start of a surrogate pair.
cuFirst >= 0xd800 &&
cuFirst <= 0xdbff && // high surrogate
text.length > nextIndex // there is a next code unit
) {
cuSecond = text.charCodeAt(nextIndex);
if (cuSecond >= 0xdc00 && cuSecond <= 0xdfff)
length = 2; // low surrogate
}
return [text.slice(index, index + length), length];
};
exports.charAtIndex = charAtIndex;
const charSplit = (text) => {
const chars = [];
for (let idx = 0, len = text.length; idx < len;) {
const [c, cLen] = (0, exports.charAtIndex)(text, idx);
chars.push(c);
idx += cLen;
}
return chars;
};
exports.charSplit = charSplit;
const buildWordBreakRegex = (wordBreaks) => {
const newlineCharUnion = exports.escapedNewlineChars.join('|');
const escapedRules = ['$'];
for (let idx = 0, len = wordBreaks.length; idx < len; idx++) {
const wordBreak = wordBreaks[idx];
if ((0, exports.isNewlineChar)(wordBreak)) {
throw new TypeError(`\`wordBreak\` must not include ${newlineCharUnion}`);
}
escapedRules.push(wordBreak === '' ? '.' : (0, exports.escapeRegExp)(wordBreak));
}
const breakRules = escapedRules.join('|');
return new RegExp(`(${newlineCharUnion})|((.*?)(${breakRules}))`, 'gm');
};
const breakTextIntoLines = (text, wordBreaks, maxWidth, computeWidthOfText) => {
const regex = buildWordBreakRegex(wordBreaks);
const words = (0, exports.cleanText)(text).match(regex);
let currLine = '';
let currWidth = 0;
const lines = [];
const pushCurrLine = () => {
if (currLine !== '')
lines.push(currLine);
currLine = '';
currWidth = 0;
};
for (let idx = 0, len = words.length; idx < len; idx++) {
const word = words[idx];
if ((0, exports.isNewlineChar)(word)) {
pushCurrLine();
}
else {
const width = computeWidthOfText(word);
if (currWidth + width > maxWidth)
pushCurrLine();
currLine += word;
currWidth += width;
}
}
pushCurrLine();
return lines;
};
exports.breakTextIntoLines = breakTextIntoLines;
// See section "7.9.4 Dates" of the PDF specification
const dateRegex = /^D:(\d\d\d\d)(\d\d)?(\d\d)?(\d\d)?(\d\d)?(\d\d)?([+\-Z])?(\d\d)?'?(\d\d)?'?$/;
const parseDate = (dateStr) => {
const match = dateStr.match(dateRegex);
if (!match)
return undefined;
const [, year, month = '01', day = '01', hours = '00', mins = '00', secs = '00', offsetSign = 'Z', offsetHours = '00', offsetMins = '00',] = match;
// http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
const tzOffset = offsetSign === 'Z' ? 'Z' : `${offsetSign}${offsetHours}:${offsetMins}`;
const date = new Date(`${year}-${month}-${day}T${hours}:${mins}:${secs}${tzOffset}`);
return date;
};
exports.parseDate = parseDate;
const findLastMatch = (value, regex) => {
var _a;
let position = 0;
let lastMatch;
while (position < value.length) {
const match = value.substring(position).match(regex);
if (!match)
return { match: lastMatch, pos: position };
lastMatch = match;
position += ((_a = match.index) !== null && _a !== void 0 ? _a : 0) + match[0].length;
}
return { match: lastMatch, pos: position };
};
exports.findLastMatch = findLastMatch;
//# sourceMappingURL=strings.js.map