mirror of
https://github.com/foliojs/pdfkit.git
synced 2025-12-08 20:15:54 +00:00
128 lines
3.0 KiB
JavaScript
128 lines
3.0 KiB
JavaScript
/*
|
|
PDFStructureElement - represents an element in the PDF logical structure tree
|
|
By Ben Schmidt
|
|
*/
|
|
|
|
import PDFStructureContent from "./structure_content";
|
|
|
|
class PDFStructureElement {
|
|
constructor(document, type, options = {}, children = null) {
|
|
this.document = document;
|
|
|
|
this._ended = false;
|
|
this._flushed = false;
|
|
this.dictionary = document.ref({
|
|
// Type: "StructElem",
|
|
S: type
|
|
});
|
|
|
|
const data = this.dictionary.data;
|
|
|
|
if (Array.isArray(options)) {
|
|
children = options;
|
|
options = {};
|
|
}
|
|
|
|
if (typeof options.title !== 'undefined') {
|
|
data.T = new String(options.title);
|
|
}
|
|
if (typeof options.lang !== 'undefined') {
|
|
data.Lang = new String(options.lang);
|
|
}
|
|
if (typeof options.alt !== 'undefined') {
|
|
data.Alt = new String(options.alt);
|
|
}
|
|
if (typeof options.expanded !== 'undefined') {
|
|
data.E = new String(options.expanded);
|
|
}
|
|
if (typeof options.actual !== 'undefined') {
|
|
data.ActualText = new String(options.actual);
|
|
}
|
|
|
|
this.structElemChildren = [];
|
|
|
|
if (children) {
|
|
children.forEach((child) => this.add(child));
|
|
this.end();
|
|
}
|
|
}
|
|
|
|
add(child) {
|
|
if (this._ended) {
|
|
throw new Error(`Cannot add child to already-ended structure element`);
|
|
}
|
|
|
|
if (!this.dictionary.data.K) {
|
|
this.dictionary.data.K = [];
|
|
}
|
|
|
|
if (!(child instanceof PDFStructureElement || child instanceof PDFStructureContent)) {
|
|
throw new Error(`Invalid structure element child`);
|
|
}
|
|
|
|
if (child instanceof PDFStructureElement) {
|
|
child.setParent(this.dictionary);
|
|
this.structElemChildren.push(child);
|
|
this.dictionary.data.K.push(child.dictionary);
|
|
}
|
|
|
|
if (child instanceof PDFStructureContent) {
|
|
child.refs.forEach(({ pageRef, mcid }) => {
|
|
if (!this.dictionary.data.Pg) {
|
|
this.dictionary.data.Pg = pageRef;
|
|
}
|
|
|
|
if (this.dictionary.data.Pg === pageRef) {
|
|
this.dictionary.data.K.push(mcid);
|
|
} else {
|
|
this.dictionary.data.K.push({
|
|
Type: "MCR",
|
|
Pg: pageRef,
|
|
MCID: mcid
|
|
});
|
|
}
|
|
|
|
const pageStructParents = this.document.getStructParentTree()
|
|
.get(pageRef.data.StructParents);
|
|
pageStructParents[mcid] = this.dictionary;
|
|
});
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
setParent(parentRef) {
|
|
this.dictionary.data.P = parentRef;
|
|
|
|
if (this._ended) {
|
|
this._flush();
|
|
}
|
|
}
|
|
|
|
end() {
|
|
if (this._ended) {
|
|
return;
|
|
}
|
|
|
|
this.structElemChildren.forEach((child) => child.end());
|
|
|
|
this._ended = true;
|
|
|
|
if (this.dictionary.data.P) {
|
|
this._flush();
|
|
}
|
|
}
|
|
|
|
_flush() {
|
|
this.dictionary.end();
|
|
|
|
// free memory used by children; the dictionary itself may still be
|
|
// referenced by a parent structure element or root, but we can
|
|
// at least trim the tree here
|
|
this.structElemChildren = [];
|
|
this.dictionary.data.K = null;
|
|
}
|
|
}
|
|
|
|
export default PDFStructureElement;
|