Cleanup / simplify code

This commit is contained in:
Luiz Américo Pereira Câmara 2025-04-12 12:43:17 -03:00
parent c5606d40e7
commit 15087ea8c3
10 changed files with 141 additions and 105 deletions

View File

@ -64,17 +64,17 @@ class PDFDocument extends stream.Readable {
const Pages = this.ref({
Type: 'Pages',
Count: 0,
Kids: []
Kids: [],
});
const Names = this.ref({
Dests: new PDFNameTree()
Dests: new PDFNameTree(),
});
this._root = this.ref({
Type: 'Catalog',
Pages,
Names
Names,
});
if (this.options.lang) {
@ -100,7 +100,7 @@ class PDFDocument extends stream.Readable {
this.info = {
Producer: 'PDFKit',
Creator: 'PDFKit',
CreationDate: new Date()
CreationDate: new Date(),
};
if (this.options.info) {
@ -112,7 +112,7 @@ class PDFDocument extends stream.Readable {
if (this.options.displayTitle) {
this._root.data.ViewerPreferences = this.ref({
DisplayDocTitle: true
DisplayDocTitle: true,
});
}
@ -188,7 +188,7 @@ class PDFDocument extends stream.Readable {
throw new Error(
`switchToPage(${n}) out of bounds, current buffer covers pages ${
this._pageBufferStart
} to ${this._pageBufferStart + this._pageBuffer.length - 1}`
} to ${this._pageBufferStart + this._pageBuffer.length - 1}`,
);
}
@ -222,7 +222,7 @@ class PDFDocument extends stream.Readable {
if (!this._root.data.Names.data.EmbeddedFiles) {
// disabling /Limits for this tree fixes attachments not showing in Adobe Reader
this._root.data.Names.data.EmbeddedFiles = new PDFNameTree({
limits: false
limits: false,
});
}
@ -236,7 +236,7 @@ class PDFDocument extends stream.Readable {
}
let data = {
JS: new String(js),
S: 'JavaScript'
S: 'JavaScript',
};
this._root.data.Names.data.JavaScript.add(name, data);
}
@ -257,7 +257,7 @@ class PDFDocument extends stream.Readable {
}
this.push(data);
return (this._offset += data.length);
this._offset += data.length;
}
addContent(data) {
@ -269,7 +269,7 @@ class PDFDocument extends stream.Readable {
this._offsets[ref.id - 1] = ref.offset;
if (--this._waiting === 0 && this._ended) {
this._finalize();
return (this._ended = false);
this._ended = false;
}
}
@ -319,9 +319,9 @@ class PDFDocument extends stream.Readable {
}
if (this._waiting === 0) {
return this._finalize();
this._finalize();
} else {
return (this._ended = true);
this._ended = true;
}
}
@ -342,7 +342,7 @@ class PDFDocument extends stream.Readable {
Size: this._offsets.length + 1,
Root: this._root,
Info: this._info,
ID: [this._id, this._id]
ID: [this._id, this._id],
};
if (this._security) {
trailer.Encrypt = this._security.dictionary;
@ -356,7 +356,7 @@ class PDFDocument extends stream.Readable {
this._write('%%EOF');
// end the stream
return this.push(null);
this.push(null);
}
toString() {
@ -364,7 +364,7 @@ class PDFDocument extends stream.Readable {
}
}
const mixin = methods => {
const mixin = (methods) => {
Object.assign(PDFDocument.prototype, methods);
};

View File

@ -21,17 +21,14 @@ class PDFFont {
}
this.embed();
return (this.embedded = true);
this.embedded = true;
}
embed() {
throw new Error('Must be implemented by subclasses');
}
lineHeight(size, includeGap) {
if (includeGap == null) {
includeGap = false;
}
lineHeight(size, includeGap = false) {
const gap = includeGap ? this.lineGap : 0;
return ((this.ascender + gap - this.descender) / 1000) * size;
}

View File

@ -11,11 +11,19 @@ class LineWrapper extends EventEmitter {
this.document = document;
this.horizontalScaling = options.horizontalScaling || 100;
this.indent = ((options.indent || 0) * this.horizontalScaling) / 100;
this.characterSpacing = ((options.characterSpacing || 0) * this.horizontalScaling) / 100;
this.wordSpacing = ((options.wordSpacing === 0) * this.horizontalScaling) / 100;
this.characterSpacing =
((options.characterSpacing || 0) * this.horizontalScaling) / 100;
this.wordSpacing =
((options.wordSpacing === 0) * this.horizontalScaling) / 100;
this.columns = options.columns || 1;
this.columnGap = ((options.columnGap != null ? options.columnGap : 18) * this.horizontalScaling) / 100; // 1/4 inch
this.lineWidth = (((options.width * this.horizontalScaling) / 100) - (this.columnGap * (this.columns - 1))) / this.columns;
this.columnGap =
((options.columnGap != null ? options.columnGap : 18) *
this.horizontalScaling) /
100; // 1/4 inch
this.lineWidth =
((options.width * this.horizontalScaling) / 100 -
this.columnGap * (this.columns - 1)) /
this.columns;
this.spaceLeft = this.lineWidth;
this.startX = this.document.x;
this.startY = this.document.y;
@ -33,7 +41,7 @@ class LineWrapper extends EventEmitter {
}
// handle paragraph indents
this.on('firstLine', options => {
this.on('firstLine', (options) => {
// if this is the first line of the text segment, and
// we're continuing where we left off, indent that much
// otherwise use the user specified indent option
@ -48,27 +56,27 @@ class LineWrapper extends EventEmitter {
}
// otherwise we start the next line without indent
return this.once('line', () => {
this.once('line', () => {
this.document.x -= indent;
this.lineWidth += indent;
if (options.continued && !this.continuedX) {
this.continuedX = this.indent;
}
if (!options.continued) {
return (this.continuedX = 0);
this.continuedX = 0;
}
});
});
// handle left aligning last lines of paragraphs
this.on('lastLine', options => {
this.on('lastLine', (options) => {
const { align } = options;
if (align === 'justify') {
options.align = 'left';
}
this.lastLine = true;
return this.once('line', () => {
this.once('line', () => {
this.document.y += options.paragraphGap || 0;
options.align = align;
return (this.lastLine = false);
@ -102,7 +110,7 @@ class LineWrapper extends EventEmitter {
var shouldContinue;
let word = text.slice(
(last != null ? last.position : undefined) || 0,
bk.position
bk.position,
);
let w =
wordWidths[word] != null
@ -178,7 +186,8 @@ class LineWrapper extends EventEmitter {
this.indent = (options.indent * this.horizontalScaling) / 100;
}
if (options.characterSpacing != null) {
this.characterSpacing = (options.characterSpacing * this.horizontalScaling) / 100;
this.characterSpacing =
(options.characterSpacing * this.horizontalScaling) / 100;
}
if (options.wordSpacing != null) {
this.wordSpacing = (options.wordSpacing * this.horizontalScaling) / 100;
@ -319,9 +328,9 @@ class LineWrapper extends EventEmitter {
this.continuedX = 0;
}
this.continuedX += options.textWidth || 0;
return (this.document.y = y);
this.document.y = y;
} else {
return (this.document.x = this.startX);
this.document.x = this.startX;
}
}

View File

@ -12,7 +12,7 @@ export default {
this._opacityRegistry = {};
this._opacityCount = 0;
this._patternCount = 0;
return (this._gradCount = 0);
this._gradCount = 0;
},
_normalizeColor(color) {
@ -21,7 +21,7 @@ export default {
if (color.length === 4) {
color = color.replace(
/#([0-9A-F])([0-9A-F])([0-9A-F])/i,
'#$1$1$2$2$3$3'
'#$1$1$2$2$3$3',
);
}
const hex = parseInt(color.slice(1), 16);
@ -36,10 +36,10 @@ export default {
if (Array.isArray(color)) {
// RGB
if (color.length === 3) {
color = color.map(part => part / 255);
color = color.map((part) => part / 255);
// CMYK
} else if (color.length === 4) {
color = color.map(part => part / 100);
color = color.map((part) => part / 100);
}
return color;
}
@ -181,7 +181,7 @@ export default {
const color = new SpotColor(this, name, C, M, Y, K);
this.spotColors[name] = color;
return this;
}
},
};
var namedColors = {
@ -331,5 +331,5 @@ var namedColors = {
white: [255, 255, 255],
whitesmoke: [245, 245, 245],
yellow: [255, 255, 0],
yellowgreen: [154, 205, 50]
yellowgreen: [154, 205, 50],
};

View File

@ -3,23 +3,29 @@ import { CM_TO_IN, IN_TO_PT, MM_TO_CM, PC_TO_PT, PX_TO_IN } from '../utils';
const isEqualFont = (font1, font2) => {
// compare font checksum
if (font1.font._tables?.head?.checkSumAdjustment !== font2.font._tables?.head?.checkSumAdjustment) {
if (
font1.font._tables?.head?.checkSumAdjustment !==
font2.font._tables?.head?.checkSumAdjustment
) {
return false;
}
// compare font name table
if (JSON.stringify(font1.font._tables?.name?.records) !== JSON.stringify(font2.font._tables?.name?.records)) {
if (
JSON.stringify(font1.font._tables?.name?.records) !==
JSON.stringify(font2.font._tables?.name?.records)
) {
return false;
}
return true;
}
};
export default {
initFonts(
defaultFont = 'Helvetica',
defaultFontFamily = null,
defaultFontSize = 12
defaultFontSize = 12,
) {
// Lookup table for embedded fonts
this._fontFamilies = {};
@ -80,7 +86,10 @@ export default {
// check for existing font familes with the same name already in the PDF
// useful if the font was passed as a buffer
if ((font = this._fontFamilies[this._font.name]) && isEqualFont(this._font, font)) {
if (
(font = this._fontFamilies[this._font.name]) &&
isEqualFont(this._font, font)
) {
this._font = font;
return this;
}
@ -103,16 +112,13 @@ export default {
},
currentLineHeight(includeGap) {
if (includeGap == null) {
includeGap = false;
}
return this._font.lineHeight(this._fontSize, includeGap);
},
registerFont(name, src, family) {
this._registeredFonts[name] = {
src,
family
family,
};
return this;
@ -128,7 +134,12 @@ export default {
*
* @returns number
*/
sizeToPoint(size, defaultValue = 0, page = this.page, percentageWidth = undefined) {
sizeToPoint(
size,
defaultValue = 0,
page = this.page,
percentageWidth = undefined,
) {
if (!percentageWidth) percentageWidth = this._fontSize;
if (typeof defaultValue !== 'number')
defaultValue = this.sizeToPoint(defaultValue);
@ -137,7 +148,7 @@ export default {
if (typeof size === 'boolean') return Number(size);
const match = String(size).match(
/((\d+)?(\.\d+)?)(em|in|px|cm|mm|pc|ex|ch|rem|vw|vh|vmin|vmax|%|pt)?/
/((\d+)?(\.\d+)?)(em|in|px|cm|mm|pc|ex|ch|rem|vw|vh|vmin|vmax|%|pt)?/,
);
if (!match) throw new Error(`Unsupported size '${size}'`);
let multiplier;
@ -190,5 +201,5 @@ export default {
}
return multiplier * Number(match[1]);
}
},
};

View File

@ -3,7 +3,7 @@ import PDFImage from '../image';
export default {
initImages() {
this._imageRegistry = {};
return (this._imageCount = 0);
this._imageCount = 0;
},
image(src, x, y, options = {}) {
@ -146,7 +146,8 @@ export default {
originX = x;
originY = y;
[wTransform, hTransform] = [h, w];
wTransform = h;
hTransform = w;
yTransform -= hTransform;
rotateAngle = 90;
@ -156,8 +157,8 @@ export default {
originX = x;
originY = y;
[wTransform, hTransform] = [h, w];
hTransform = -hTransform;
wTransform = h;
hTransform = -w;
rotateAngle = 90;
break;
@ -166,10 +167,9 @@ export default {
originX = x;
originY = y;
[wTransform, hTransform] = [h, w];
hTransform = -hTransform;
wTransform = -wTransform;
xTransform -= wTransform;
hTransform = -w;
wTransform = -h;
xTransform += h;
rotateAngle = 90;
break;
@ -178,10 +178,10 @@ export default {
originX = x;
originY = y;
[wTransform, hTransform] = [h, w];
hTransform = -hTransform;
xTransform -= wTransform;
yTransform -= hTransform;
wTransform = h;
hTransform = -w;
xTransform -= h;
yTransform += w;
rotateAngle = -90;
break;

View File

@ -2,7 +2,7 @@ import PDFOutline from '../outline';
export default {
initOutline() {
return (this.outline = new PDFOutline(this, null, null, null));
this.outline = new PDFOutline(this, null, null, null);
},
endOutline() {
@ -11,5 +11,5 @@ export default {
this._root.data.Outlines = this.outline.dictionary;
return (this._root.data.PageMode = 'UseOutlines');
}
}
},
};

View File

@ -10,7 +10,7 @@ export default {
// Current coordinates
this.x = 0;
this.y = 0;
return (this._lineGap = 0);
this._lineGap = 0;
},
lineGap(_lineGap) {
@ -47,8 +47,11 @@ export default {
const addStructure = () => {
if (options.structParent) {
options.structParent.add(this.struct(options.structType || 'P',
[this.markStructureContent(options.structType || 'P')]));
options.structParent.add(
this.struct(options.structType || 'P', [
this.markStructureContent(options.structType || 'P'),
]),
);
}
};
@ -91,7 +94,12 @@ export default {
widthOfString(string, options = {}) {
const horizontalScaling = options.horizontalScaling || 100;
return ((this._font.widthOfString(string, this._fontSize, options.features) + (options.characterSpacing || 0) * (string.length - 1)) * horizontalScaling) / 100;
return (
((this._font.widthOfString(string, this._fontSize, options.features) +
(options.characterSpacing || 0) * (string.length - 1)) *
horizontalScaling) /
100
);
},
/**
@ -122,7 +130,7 @@ export default {
if (options.width) {
let wrapper = new LineWrapper(this, options);
wrapper.on('line', (text, options) => {
this.y+=lineHeight;
this.y += lineHeight;
text = text.replace(/\n/g, '');
if (text.length) {
@ -234,7 +242,7 @@ export default {
const lineGap = options.lineGap || this._lineGap || 0;
this._text(text, this.x, this.y, options, () => {
return (this.y += this.currentLineHeight(true) + lineGap);
this.y += this.currentLineHeight(true) + lineGap;
});
const height = this.y - y;
@ -324,8 +332,11 @@ export default {
}
if (item && (labelType || bodyType)) {
item.add(this.struct(labelType || bodyType,
[this.markStructureContent(labelType || bodyType)]));
item.add(
this.struct(labelType || bodyType, [
this.markStructureContent(labelType || bodyType),
]),
);
}
switch (listType) {
case 'bullet':
@ -340,7 +351,9 @@ export default {
}
if (item && labelType && bodyType) {
item.add(this.struct(bodyType, [this.markStructureContent(bodyType)]));
item.add(
this.struct(bodyType, [this.markStructureContent(bodyType)]),
);
}
if (item && item !== options.structParent) {
item.end();
@ -350,19 +363,18 @@ export default {
wrapper.on('sectionStart', () => {
const pos = indent + itemIndent * (level - 1);
this.x += pos;
return (wrapper.lineWidth -= pos);
wrapper.lineWidth -= pos;
});
wrapper.on('sectionEnd', () => {
const pos = indent + itemIndent * (level - 1);
this.x -= pos;
return (wrapper.lineWidth += pos);
wrapper.lineWidth += pos;
});
wrapper.wrap(listItem, options);
};
for (let i = 0; i < items.length; i++) {
drawListItem.call(this, items[i], i);
}
@ -426,9 +438,9 @@ export default {
const lineGap = options.lineGap || this._lineGap || 0;
if (!wrapper) {
return (this.x += this.widthOfString(text, options));
this.x += this.widthOfString(text, options);
} else {
return (this.y += this.currentLineHeight(true) + lineGap);
this.y += this.currentLineHeight(true) + lineGap;
}
},
@ -465,7 +477,7 @@ export default {
wordSpacing = Math.max(
0,
(options.lineWidth - textWidth) / Math.max(1, words.length - 1) -
spaceWidth
spaceWidth,
);
break;
}
@ -533,7 +545,7 @@ export default {
this._fontSize < 10 ? 0.5 : Math.floor(this._fontSize / 10);
this.lineWidth(lineWidth);
let lineY = (y + this.currentLineHeight()) - lineWidth
let lineY = y + this.currentLineHeight() - lineWidth;
this.moveTo(x, lineY);
this.lineTo(x + renderedWidth, lineY);
this.stroke();
@ -621,7 +633,7 @@ export default {
for (let word of words) {
const [encodedWord, positionsWord] = this._font.encode(
word,
options.features
options.features,
);
encoded = encoded.concat(encodedWord);
positions = positions.concat(positionsWord);
@ -647,7 +659,7 @@ export default {
let hadOffset = false;
// Adds a segment of text to the TJ command buffer
const addSegment = cur => {
const addSegment = (cur) => {
if (last < cur) {
const hex = encoded.slice(last, cur).join('');
const advance =
@ -655,16 +667,16 @@ export default {
commands.push(`<${hex}> ${number(-advance)}`);
}
return (last = cur);
last = cur;
};
// Flushes the current TJ commands to the output stream
const flush = i => {
const flush = (i) => {
addSegment(i);
if (commands.length > 0) {
this.addContent(`[${commands.join(' ')}] TJ`);
return (commands.length = 0);
commands.length = 0;
}
};
@ -679,8 +691,8 @@ export default {
// Move the text position and flush just the current character
this.addContent(
`1 0 0 1 ${number(x + pos.xOffset * scale)} ${number(
y + pos.yOffset * scale
)} Tm`
y + pos.yOffset * scale,
)} Tm`,
);
flush(i + 1);
@ -708,6 +720,6 @@ export default {
this.addContent('ET');
// restore flipped coordinate system
return this.restore();
}
this.restore();
},
};

View File

@ -9,7 +9,7 @@ const KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0);
export default {
initVector() {
this._ctm = [1, 0, 0, 1, 0, 0]; // current transformation matrix
return (this._ctmStack = []);
this._ctmStack = [];
},
save() {
@ -34,7 +34,7 @@ export default {
_CAP_STYLES: {
BUTT: 0,
ROUND: 1,
SQUARE: 2
SQUARE: 2,
},
lineCap(c) {
@ -47,7 +47,7 @@ export default {
_JOIN_STYLES: {
MITER: 0,
ROUND: 1,
BEVEL: 2
BEVEL: 2,
},
lineJoin(j) {
@ -67,12 +67,12 @@ export default {
length = [length, options.space || length];
}
const valid = length.every(x => Number.isFinite(x) && x > 0);
const valid = length.every((x) => Number.isFinite(x) && x > 0);
if (!valid) {
throw new Error(
`dash(${JSON.stringify(originalLength)}, ${JSON.stringify(
options
)}) invalid, lengths must be numeric and greater than zero`
options,
)}) invalid, lengths must be numeric and greater than zero`,
);
}
@ -95,20 +95,20 @@ export default {
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
return this.addContent(
`${number(cp1x)} ${number(cp1y)} ${number(cp2x)} ${number(cp2y)} ${number(
x
)} ${number(y)} c`
x,
)} ${number(y)} c`,
);
},
quadraticCurveTo(cpx, cpy, x, y) {
return this.addContent(
`${number(cpx)} ${number(cpy)} ${number(x)} ${number(y)} v`
`${number(cpx)} ${number(cpy)} ${number(x)} ${number(y)} v`,
);
},
rect(x, y, w, h) {
return this.addContent(
`${number(x)} ${number(y)} ${number(w)} ${number(h)} re`
`${number(x)} ${number(y)} ${number(w)} ${number(h)} re`,
);
},
@ -289,7 +289,14 @@ export default {
transform(m11, m12, m21, m22, dx, dy) {
// keep track of the current transformation matrix
if (m11 === 1 && m12 === 0 && m21 === 0 && m22 === 1 && dx === 0 && dy === 0) {
if (
m11 === 1 &&
m12 === 0 &&
m21 === 0 &&
m22 === 1 &&
dx === 0 &&
dy === 0
) {
// Ignore identity transforms
return this;
}
@ -302,7 +309,7 @@ export default {
m[4] = m0 * dx + m2 * dy + m4;
m[5] = m1 * dx + m3 * dy + m5;
const values = [m11, m12, m21, m22, dx, dy].map(v => number(v)).join(' ');
const values = [m11, m12, m21, m22, dx, dy].map((v) => number(v)).join(' ');
return this.addContent(`${values} cm`);
},
@ -346,5 +353,5 @@ export default {
}
return this.transform(xFactor, 0, 0, yFactor, x, y);
}
},
};

View File

@ -31,7 +31,7 @@ class PDFReference extends PDFAbstractReference {
this.buffer.push(chunk);
this.data.Length += chunk.length;
if (this.compress) {
return (this.data.Filter = 'FlateDecode');
this.data.Filter = 'FlateDecode';
}
}
@ -39,7 +39,7 @@ class PDFReference extends PDFAbstractReference {
if (chunk) {
this.write(chunk);
}
return this.finalize();
this.finalize();
}
finalize() {