Add the possibility to collect Javascript actions
This commit is contained in:
parent
fd1d9cc85f
commit
71ecc3129b
@ -14,12 +14,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
AnnotationActionEventType,
|
||||||
AnnotationBorderStyleType,
|
AnnotationBorderStyleType,
|
||||||
AnnotationFieldFlag,
|
AnnotationFieldFlag,
|
||||||
AnnotationFlag,
|
AnnotationFlag,
|
||||||
AnnotationReplyType,
|
AnnotationReplyType,
|
||||||
AnnotationType,
|
AnnotationType,
|
||||||
assert,
|
assert,
|
||||||
|
bytesToString,
|
||||||
escapeString,
|
escapeString,
|
||||||
getModificationDate,
|
getModificationDate,
|
||||||
isString,
|
isString,
|
||||||
@ -30,7 +32,15 @@ import {
|
|||||||
warn,
|
warn,
|
||||||
} from "../shared/util.js";
|
} from "../shared/util.js";
|
||||||
import { Catalog, FileSpec, ObjectLoader } from "./obj.js";
|
import { Catalog, FileSpec, ObjectLoader } from "./obj.js";
|
||||||
import { Dict, isDict, isName, isRef, isStream, Name } from "./primitives.js";
|
import {
|
||||||
|
Dict,
|
||||||
|
isDict,
|
||||||
|
isName,
|
||||||
|
isRef,
|
||||||
|
isStream,
|
||||||
|
Name,
|
||||||
|
RefSet,
|
||||||
|
} from "./primitives.js";
|
||||||
import { ColorSpace } from "./colorspace.js";
|
import { ColorSpace } from "./colorspace.js";
|
||||||
import { getInheritableProperty } from "./core_utils.js";
|
import { getInheritableProperty } from "./core_utils.js";
|
||||||
import { OperatorList } from "./operator_list.js";
|
import { OperatorList } from "./operator_list.js";
|
||||||
@ -569,6 +579,20 @@ class Annotation {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get field data for usage in JS sandbox.
|
||||||
|
*
|
||||||
|
* Field object is defined here:
|
||||||
|
* https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/js_api_reference.pdf#page=16
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @memberof Annotation
|
||||||
|
* @returns {Object | null}
|
||||||
|
*/
|
||||||
|
getFieldObject() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the annotation.
|
* Reset the annotation.
|
||||||
*
|
*
|
||||||
@ -903,6 +927,7 @@ class WidgetAnnotation extends Annotation {
|
|||||||
|
|
||||||
data.annotationType = AnnotationType.WIDGET;
|
data.annotationType = AnnotationType.WIDGET;
|
||||||
data.fieldName = this._constructFieldName(dict);
|
data.fieldName = this._constructFieldName(dict);
|
||||||
|
data.actions = this._collectActions(params.xref, dict);
|
||||||
|
|
||||||
const fieldValue = getInheritableProperty({
|
const fieldValue = getInheritableProperty({
|
||||||
dict,
|
dict,
|
||||||
@ -937,6 +962,7 @@ class WidgetAnnotation extends Annotation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY);
|
data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY);
|
||||||
|
data.hidden = this.hasFieldFlag(AnnotationFieldFlag.HIDDEN);
|
||||||
|
|
||||||
// Hide signatures because we cannot validate them, and unset the fieldValue
|
// Hide signatures because we cannot validate them, and unset the fieldValue
|
||||||
// since it's (most likely) a `Dict` which is non-serializable and will thus
|
// since it's (most likely) a `Dict` which is non-serializable and will thus
|
||||||
@ -944,6 +970,7 @@ class WidgetAnnotation extends Annotation {
|
|||||||
if (data.fieldType === "Sig") {
|
if (data.fieldType === "Sig") {
|
||||||
data.fieldValue = null;
|
data.fieldValue = null;
|
||||||
this.setFlags(AnnotationFlag.HIDDEN);
|
this.setFlags(AnnotationFlag.HIDDEN);
|
||||||
|
data.hidden = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1366,6 +1393,87 @@ class WidgetAnnotation extends Annotation {
|
|||||||
}
|
}
|
||||||
return localResources || Dict.empty;
|
return localResources || Dict.empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_collectJS(entry, xref, list, parents) {
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent = null;
|
||||||
|
if (isRef(entry)) {
|
||||||
|
if (parents.has(entry)) {
|
||||||
|
// If we've already found entry then we've a cycle.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parent = entry;
|
||||||
|
parents.put(parent);
|
||||||
|
entry = xref.fetch(entry);
|
||||||
|
}
|
||||||
|
if (Array.isArray(entry)) {
|
||||||
|
for (const element of entry) {
|
||||||
|
this._collectJS(element, xref, list, parents);
|
||||||
|
}
|
||||||
|
} else if (entry instanceof Dict) {
|
||||||
|
if (isName(entry.get("S"), "JavaScript") && entry.has("JS")) {
|
||||||
|
const js = entry.get("JS");
|
||||||
|
let code;
|
||||||
|
if (isStream(js)) {
|
||||||
|
code = bytesToString(js.getBytes());
|
||||||
|
} else {
|
||||||
|
code = js;
|
||||||
|
}
|
||||||
|
code = stringToPDFString(code);
|
||||||
|
if (code) {
|
||||||
|
list.push(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._collectJS(entry.getRaw("Next"), xref, list, parents);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
parents.remove(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_collectActions(xref, dict) {
|
||||||
|
const actions = Object.create(null);
|
||||||
|
if (dict.has("AA")) {
|
||||||
|
const additionalActions = dict.get("AA");
|
||||||
|
for (const key of additionalActions.getKeys()) {
|
||||||
|
if (key in AnnotationActionEventType) {
|
||||||
|
const actionDict = additionalActions.getRaw(key);
|
||||||
|
const parents = new RefSet();
|
||||||
|
const list = [];
|
||||||
|
this._collectJS(actionDict, xref, list, parents);
|
||||||
|
if (list.length > 0) {
|
||||||
|
actions[AnnotationActionEventType[key]] = list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Collect the Action if any (we may have one on pushbutton)
|
||||||
|
if (dict.has("A")) {
|
||||||
|
const actionDict = dict.get("A");
|
||||||
|
const parents = new RefSet();
|
||||||
|
const list = [];
|
||||||
|
this._collectJS(actionDict, xref, list, parents);
|
||||||
|
if (list.length > 0) {
|
||||||
|
actions.Action = list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFieldObject() {
|
||||||
|
if (this.data.fieldType === "Sig") {
|
||||||
|
return {
|
||||||
|
id: this.data.id,
|
||||||
|
value: null,
|
||||||
|
type: "signature",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextWidgetAnnotation extends WidgetAnnotation {
|
class TextWidgetAnnotation extends WidgetAnnotation {
|
||||||
@ -1516,6 +1624,23 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
|||||||
|
|
||||||
return chunks;
|
return chunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFieldObject() {
|
||||||
|
return {
|
||||||
|
id: this.data.id,
|
||||||
|
value: this.data.fieldValue,
|
||||||
|
multiline: this.data.multiLine,
|
||||||
|
password: this.hasFieldFlag(AnnotationFieldFlag.PASSWORD),
|
||||||
|
charLimit: this.data.maxLen,
|
||||||
|
comb: this.data.comb,
|
||||||
|
editable: !this.data.readOnly,
|
||||||
|
hidden: this.data.hidden,
|
||||||
|
name: this.data.fieldName,
|
||||||
|
rect: this.data.rect,
|
||||||
|
actions: this.data.actions,
|
||||||
|
type: "text",
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ButtonWidgetAnnotation extends WidgetAnnotation {
|
class ButtonWidgetAnnotation extends WidgetAnnotation {
|
||||||
@ -1793,6 +1918,28 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||||||
docBaseUrl: params.pdfManager.docBaseUrl,
|
docBaseUrl: params.pdfManager.docBaseUrl,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFieldObject() {
|
||||||
|
let type = "button";
|
||||||
|
let value = null;
|
||||||
|
if (this.data.checkBox) {
|
||||||
|
type = "checkbox";
|
||||||
|
value = this.data.fieldValue && this.data.fieldValue !== "Off";
|
||||||
|
} else if (this.data.radioButton) {
|
||||||
|
type = "radiobutton";
|
||||||
|
value = this.data.fieldValue === this.data.buttonValue;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: this.data.id,
|
||||||
|
value,
|
||||||
|
editable: !this.data.readOnly,
|
||||||
|
name: this.data.fieldName,
|
||||||
|
rect: this.data.rect,
|
||||||
|
hidden: this.data.hidden,
|
||||||
|
actions: this.data.actions,
|
||||||
|
type,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChoiceWidgetAnnotation extends WidgetAnnotation {
|
class ChoiceWidgetAnnotation extends WidgetAnnotation {
|
||||||
@ -1843,6 +1990,23 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
|
|||||||
this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT);
|
this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT);
|
||||||
this._hasText = true;
|
this._hasText = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFieldObject() {
|
||||||
|
const type = this.data.combo ? "combobox" : "listbox";
|
||||||
|
const value =
|
||||||
|
this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : null;
|
||||||
|
return {
|
||||||
|
id: this.data.id,
|
||||||
|
value,
|
||||||
|
editable: !this.data.readOnly,
|
||||||
|
name: this.data.fieldName,
|
||||||
|
rect: this.data.rect,
|
||||||
|
multipleSelection: this.data.multiSelect,
|
||||||
|
hidden: this.data.hidden,
|
||||||
|
actions: this.data.actions,
|
||||||
|
type,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextAnnotation extends MarkupAnnotation {
|
class TextAnnotation extends MarkupAnnotation {
|
||||||
|
@ -708,7 +708,7 @@ class PDFDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get formInfo() {
|
get formInfo() {
|
||||||
const formInfo = { hasAcroForm: false, hasXfa: false };
|
const formInfo = { hasAcroForm: false, hasXfa: false, fields: null };
|
||||||
const acroForm = this.catalog.acroForm;
|
const acroForm = this.catalog.acroForm;
|
||||||
if (!acroForm) {
|
if (!acroForm) {
|
||||||
return shadow(this, "formInfo", formInfo);
|
return shadow(this, "formInfo", formInfo);
|
||||||
@ -736,6 +736,9 @@ class PDFDocument {
|
|||||||
const hasOnlyDocumentSignatures =
|
const hasOnlyDocumentSignatures =
|
||||||
!!(sigFlags & 0x1) && this._hasOnlyDocumentSignatures(fields);
|
!!(sigFlags & 0x1) && this._hasOnlyDocumentSignatures(fields);
|
||||||
formInfo.hasAcroForm = hasFields && !hasOnlyDocumentSignatures;
|
formInfo.hasAcroForm = hasFields && !hasOnlyDocumentSignatures;
|
||||||
|
if (hasFields) {
|
||||||
|
formInfo.fields = fields;
|
||||||
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (ex instanceof MissingDataException) {
|
if (ex instanceof MissingDataException) {
|
||||||
throw ex;
|
throw ex;
|
||||||
@ -935,6 +938,73 @@ class PDFDocument {
|
|||||||
? this.catalog.cleanup(manuallyTriggered)
|
? this.catalog.cleanup(manuallyTriggered)
|
||||||
: clearPrimitiveCaches();
|
: clearPrimitiveCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_collectFieldObjects(name, fieldRef, promises) {
|
||||||
|
const field = this.xref.fetchIfRef(fieldRef);
|
||||||
|
if (field.has("T")) {
|
||||||
|
const partName = stringToPDFString(field.get("T"));
|
||||||
|
if (name === "") {
|
||||||
|
name = partName;
|
||||||
|
} else {
|
||||||
|
name = `${name}.${partName}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(name in promises)) {
|
||||||
|
promises.set(name, []);
|
||||||
|
}
|
||||||
|
promises.get(name).push(
|
||||||
|
AnnotationFactory.create(
|
||||||
|
this.xref,
|
||||||
|
fieldRef,
|
||||||
|
this.pdfManager,
|
||||||
|
this._localIdFactory
|
||||||
|
)
|
||||||
|
.then(annotation => annotation.getFieldObject())
|
||||||
|
.catch(function (reason) {
|
||||||
|
warn(`_collectFieldObjects: "${reason}".`);
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (field.has("Kids")) {
|
||||||
|
const kids = field.get("Kids");
|
||||||
|
for (const kid of kids) {
|
||||||
|
this._collectFieldObjects(name, kid, promises);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get fieldObjects() {
|
||||||
|
const formInfo = this.formInfo;
|
||||||
|
if (!formInfo.fields) {
|
||||||
|
return shadow(this, "fieldObjects", Promise.resolve(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
const allFields = Object.create(null);
|
||||||
|
const fieldPromises = new Map();
|
||||||
|
for (const fieldRef of formInfo.fields) {
|
||||||
|
this._collectFieldObjects("", fieldRef, fieldPromises);
|
||||||
|
}
|
||||||
|
|
||||||
|
const allPromises = [];
|
||||||
|
for (const [name, promises] of fieldPromises.entries()) {
|
||||||
|
allPromises.push(
|
||||||
|
Promise.all(promises).then(fields => {
|
||||||
|
fields = fields.filter(field => field !== null);
|
||||||
|
if (fields.length > 0) {
|
||||||
|
allFields[name] = fields;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shadow(
|
||||||
|
this,
|
||||||
|
"fieldObjects",
|
||||||
|
Promise.all(allPromises).then(() => allFields)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Page, PDFDocument };
|
export { Page, PDFDocument };
|
||||||
|
@ -516,6 +516,10 @@ class WorkerMessageHandler {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
handler.on("GetFieldObjects", function (data) {
|
||||||
|
return pdfManager.ensureDoc("fieldObjects");
|
||||||
|
});
|
||||||
|
|
||||||
handler.on("SaveDocument", function ({
|
handler.on("SaveDocument", function ({
|
||||||
numPages,
|
numPages,
|
||||||
annotationStorage,
|
annotationStorage,
|
||||||
|
@ -876,6 +876,14 @@ class PDFDocumentProxy {
|
|||||||
saveDocument(annotationStorage) {
|
saveDocument(annotationStorage) {
|
||||||
return this._transport.saveDocument(annotationStorage);
|
return this._transport.saveDocument(annotationStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Promise<Array<Object>>} A promise that is resolved with an
|
||||||
|
* {Array<Object>} containing field data for the JS sandbox.
|
||||||
|
*/
|
||||||
|
getFieldObjects() {
|
||||||
|
return this._transport.getFieldObjects();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2549,6 +2557,10 @@ class WorkerTransport {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFieldObjects() {
|
||||||
|
return this.messageHandler.sendWithPromise("GetFieldObjects", null);
|
||||||
|
}
|
||||||
|
|
||||||
getDestinations() {
|
getDestinations() {
|
||||||
return this.messageHandler.sendWithPromise("GetDestinations", null);
|
return this.messageHandler.sendWithPromise("GetDestinations", null);
|
||||||
}
|
}
|
||||||
|
@ -144,6 +144,28 @@ const AnnotationBorderStyleType = {
|
|||||||
UNDERLINE: 5,
|
UNDERLINE: 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const AnnotationActionEventType = {
|
||||||
|
E: "MouseEnter",
|
||||||
|
X: "MouseExit",
|
||||||
|
D: "MouseDown",
|
||||||
|
U: "MouseUp",
|
||||||
|
Fo: "Focus",
|
||||||
|
Bl: "Blur",
|
||||||
|
PO: "PageOpen",
|
||||||
|
PC: "PageClose",
|
||||||
|
PV: "PageVisible",
|
||||||
|
PI: "PageInvisible",
|
||||||
|
K: "Keystroke",
|
||||||
|
F: "Format",
|
||||||
|
V: "Validate",
|
||||||
|
C: "Calculate",
|
||||||
|
WC: "WillClose",
|
||||||
|
WS: "WillSave",
|
||||||
|
DS: "DidSave",
|
||||||
|
WP: "WillPrint",
|
||||||
|
DP: "DidPrint",
|
||||||
|
};
|
||||||
|
|
||||||
const StreamType = {
|
const StreamType = {
|
||||||
UNKNOWN: "UNKNOWN",
|
UNKNOWN: "UNKNOWN",
|
||||||
FLATE: "FLATE",
|
FLATE: "FLATE",
|
||||||
@ -971,6 +993,7 @@ export {
|
|||||||
OPS,
|
OPS,
|
||||||
VerbosityLevel,
|
VerbosityLevel,
|
||||||
UNSUPPORTED_FEATURES,
|
UNSUPPORTED_FEATURES,
|
||||||
|
AnnotationActionEventType,
|
||||||
AnnotationBorderStyleType,
|
AnnotationBorderStyleType,
|
||||||
AnnotationFieldFlag,
|
AnnotationFieldFlag,
|
||||||
AnnotationFlag,
|
AnnotationFlag,
|
||||||
|
@ -298,6 +298,7 @@ describe("annotation", function () {
|
|||||||
expect(annotation.hasFlag(AnnotationFlag.NOZOOM)).toEqual(true);
|
expect(annotation.hasFlag(AnnotationFlag.NOZOOM)).toEqual(true);
|
||||||
expect(annotation.hasFlag(AnnotationFlag.PRINT)).toEqual(true);
|
expect(annotation.hasFlag(AnnotationFlag.PRINT)).toEqual(true);
|
||||||
expect(annotation.hasFlag(AnnotationFlag.READONLY)).toEqual(false);
|
expect(annotation.hasFlag(AnnotationFlag.READONLY)).toEqual(false);
|
||||||
|
expect(annotation.hasFlag(AnnotationFlag.HIDDEN)).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be viewable and not printable by default", function () {
|
it("should be viewable and not printable by default", function () {
|
||||||
@ -1433,6 +1434,7 @@ describe("annotation", function () {
|
|||||||
expect(data.textAlignment).toEqual(null);
|
expect(data.textAlignment).toEqual(null);
|
||||||
expect(data.maxLen).toEqual(null);
|
expect(data.maxLen).toEqual(null);
|
||||||
expect(data.readOnly).toEqual(false);
|
expect(data.readOnly).toEqual(false);
|
||||||
|
expect(data.hidden).toEqual(false);
|
||||||
expect(data.multiLine).toEqual(false);
|
expect(data.multiLine).toEqual(false);
|
||||||
expect(data.comb).toEqual(false);
|
expect(data.comb).toEqual(false);
|
||||||
done();
|
done();
|
||||||
@ -1457,6 +1459,7 @@ describe("annotation", function () {
|
|||||||
expect(data.textAlignment).toEqual(null);
|
expect(data.textAlignment).toEqual(null);
|
||||||
expect(data.maxLen).toEqual(null);
|
expect(data.maxLen).toEqual(null);
|
||||||
expect(data.readOnly).toEqual(false);
|
expect(data.readOnly).toEqual(false);
|
||||||
|
expect(data.hidden).toEqual(false);
|
||||||
expect(data.multiLine).toEqual(false);
|
expect(data.multiLine).toEqual(false);
|
||||||
expect(data.comb).toEqual(false);
|
expect(data.comb).toEqual(false);
|
||||||
done();
|
done();
|
||||||
@ -1484,6 +1487,7 @@ describe("annotation", function () {
|
|||||||
expect(data.textAlignment).toEqual(1);
|
expect(data.textAlignment).toEqual(1);
|
||||||
expect(data.maxLen).toEqual(20);
|
expect(data.maxLen).toEqual(20);
|
||||||
expect(data.readOnly).toEqual(true);
|
expect(data.readOnly).toEqual(true);
|
||||||
|
expect(data.hidden).toEqual(false);
|
||||||
expect(data.multiLine).toEqual(true);
|
expect(data.multiLine).toEqual(true);
|
||||||
done();
|
done();
|
||||||
}, done.fail);
|
}, done.fail);
|
||||||
@ -1863,6 +1867,92 @@ describe("annotation", function () {
|
|||||||
done();
|
done();
|
||||||
}, done.fail);
|
}, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should get field object for usage in JS sandbox", function (done) {
|
||||||
|
const textWidgetRef = Ref.get(123, 0);
|
||||||
|
const xDictRef = Ref.get(141, 0);
|
||||||
|
const dDictRef = Ref.get(262, 0);
|
||||||
|
const next0Ref = Ref.get(314, 0);
|
||||||
|
const next1Ref = Ref.get(271, 0);
|
||||||
|
const next2Ref = Ref.get(577, 0);
|
||||||
|
const next00Ref = Ref.get(413, 0);
|
||||||
|
const xDict = new Dict();
|
||||||
|
const dDict = new Dict();
|
||||||
|
const next0Dict = new Dict();
|
||||||
|
const next1Dict = new Dict();
|
||||||
|
const next2Dict = new Dict();
|
||||||
|
const next00Dict = new Dict();
|
||||||
|
|
||||||
|
const xref = new XRefMock([
|
||||||
|
{ ref: textWidgetRef, data: textWidgetDict },
|
||||||
|
{ ref: xDictRef, data: xDict },
|
||||||
|
{ ref: dDictRef, data: dDict },
|
||||||
|
{ ref: next0Ref, data: next0Dict },
|
||||||
|
{ ref: next00Ref, data: next00Dict },
|
||||||
|
{ ref: next1Ref, data: next1Dict },
|
||||||
|
{ ref: next2Ref, data: next2Dict },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const JS = Name.get("JavaScript");
|
||||||
|
const additionalActionsDict = new Dict();
|
||||||
|
const eDict = new Dict();
|
||||||
|
eDict.set("JS", "hello()");
|
||||||
|
eDict.set("S", JS);
|
||||||
|
additionalActionsDict.set("E", eDict);
|
||||||
|
|
||||||
|
// Test the cycle detection here
|
||||||
|
xDict.set("JS", "world()");
|
||||||
|
xDict.set("S", JS);
|
||||||
|
xDict.set("Next", [next0Ref, next1Ref, next2Ref, xDictRef]);
|
||||||
|
|
||||||
|
next0Dict.set("JS", "olleh()");
|
||||||
|
next0Dict.set("S", JS);
|
||||||
|
next0Dict.set("Next", next00Ref);
|
||||||
|
|
||||||
|
next00Dict.set("JS", "foo()");
|
||||||
|
next00Dict.set("S", JS);
|
||||||
|
next00Dict.set("Next", next0Ref);
|
||||||
|
|
||||||
|
next1Dict.set("JS", "dlrow()");
|
||||||
|
next1Dict.set("S", JS);
|
||||||
|
next1Dict.set("Next", xDictRef);
|
||||||
|
|
||||||
|
next2Dict.set("JS", "oof()");
|
||||||
|
next2Dict.set("S", JS);
|
||||||
|
|
||||||
|
dDict.set("JS", "bar()");
|
||||||
|
dDict.set("S", JS);
|
||||||
|
dDict.set("Next", dDictRef);
|
||||||
|
additionalActionsDict.set("D", dDictRef);
|
||||||
|
|
||||||
|
additionalActionsDict.set("X", xDictRef);
|
||||||
|
textWidgetDict.set("AA", additionalActionsDict);
|
||||||
|
|
||||||
|
partialEvaluator.xref = xref;
|
||||||
|
|
||||||
|
AnnotationFactory.create(
|
||||||
|
xref,
|
||||||
|
textWidgetRef,
|
||||||
|
pdfManagerMock,
|
||||||
|
idFactoryMock
|
||||||
|
)
|
||||||
|
.then(annotation => {
|
||||||
|
return annotation.getFieldObject();
|
||||||
|
})
|
||||||
|
.then(object => {
|
||||||
|
const actions = object.actions;
|
||||||
|
expect(actions.MouseEnter).toEqual(["hello()"]);
|
||||||
|
expect(actions.MouseExit).toEqual([
|
||||||
|
"world()",
|
||||||
|
"olleh()",
|
||||||
|
"foo()",
|
||||||
|
"dlrow()",
|
||||||
|
"oof()",
|
||||||
|
]);
|
||||||
|
expect(actions.MouseDown).toEqual(["bar()"]);
|
||||||
|
done();
|
||||||
|
}, done.fail);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("ButtonWidgetAnnotation", function () {
|
describe("ButtonWidgetAnnotation", function () {
|
||||||
@ -2524,7 +2614,11 @@ describe("annotation", function () {
|
|||||||
it("should handle push buttons", function (done) {
|
it("should handle push buttons", function (done) {
|
||||||
const buttonWidgetRef = Ref.get(124, 0);
|
const buttonWidgetRef = Ref.get(124, 0);
|
||||||
buttonWidgetDict.set("Ff", AnnotationFieldFlag.PUSHBUTTON);
|
buttonWidgetDict.set("Ff", AnnotationFieldFlag.PUSHBUTTON);
|
||||||
buttonWidgetDict.set("A", "whatever");
|
|
||||||
|
const actionDict = new Dict();
|
||||||
|
actionDict.set("S", Name.get("JavaScript"));
|
||||||
|
actionDict.set("JS", "do_something();");
|
||||||
|
buttonWidgetDict.set("A", actionDict);
|
||||||
|
|
||||||
const xref = new XRefMock([
|
const xref = new XRefMock([
|
||||||
{ ref: buttonWidgetRef, data: buttonWidgetDict },
|
{ ref: buttonWidgetRef, data: buttonWidgetDict },
|
||||||
@ -2538,6 +2632,7 @@ describe("annotation", function () {
|
|||||||
).then(({ data }) => {
|
).then(({ data }) => {
|
||||||
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
|
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
|
||||||
expect(data.pushButton).toEqual(true);
|
expect(data.pushButton).toEqual(true);
|
||||||
|
expect(data.actions.Action).toEqual(["do_something();"]);
|
||||||
done();
|
done();
|
||||||
}, done.fail);
|
}, done.fail);
|
||||||
});
|
});
|
||||||
@ -2779,6 +2874,7 @@ describe("annotation", function () {
|
|||||||
).then(({ data }) => {
|
).then(({ data }) => {
|
||||||
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
|
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
|
||||||
expect(data.readOnly).toEqual(false);
|
expect(data.readOnly).toEqual(false);
|
||||||
|
expect(data.hidden).toEqual(false);
|
||||||
expect(data.combo).toEqual(false);
|
expect(data.combo).toEqual(false);
|
||||||
expect(data.multiSelect).toEqual(false);
|
expect(data.multiSelect).toEqual(false);
|
||||||
done();
|
done();
|
||||||
@ -2801,6 +2897,7 @@ describe("annotation", function () {
|
|||||||
).then(({ data }) => {
|
).then(({ data }) => {
|
||||||
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
|
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
|
||||||
expect(data.readOnly).toEqual(false);
|
expect(data.readOnly).toEqual(false);
|
||||||
|
expect(data.hidden).toEqual(false);
|
||||||
expect(data.combo).toEqual(false);
|
expect(data.combo).toEqual(false);
|
||||||
expect(data.multiSelect).toEqual(false);
|
expect(data.multiSelect).toEqual(false);
|
||||||
done();
|
done();
|
||||||
@ -2828,6 +2925,7 @@ describe("annotation", function () {
|
|||||||
).then(({ data }) => {
|
).then(({ data }) => {
|
||||||
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
|
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
|
||||||
expect(data.readOnly).toEqual(true);
|
expect(data.readOnly).toEqual(true);
|
||||||
|
expect(data.hidden).toEqual(false);
|
||||||
expect(data.combo).toEqual(true);
|
expect(data.combo).toEqual(true);
|
||||||
expect(data.multiSelect).toEqual(true);
|
expect(data.multiSelect).toEqual(true);
|
||||||
done();
|
done();
|
||||||
|
@ -63,6 +63,7 @@ describe("document", function () {
|
|||||||
expect(pdfDocument.formInfo).toEqual({
|
expect(pdfDocument.formInfo).toEqual({
|
||||||
hasAcroForm: false,
|
hasAcroForm: false,
|
||||||
hasXfa: false,
|
hasXfa: false,
|
||||||
|
fields: null,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -75,6 +76,7 @@ describe("document", function () {
|
|||||||
expect(pdfDocument.formInfo).toEqual({
|
expect(pdfDocument.formInfo).toEqual({
|
||||||
hasAcroForm: false,
|
hasAcroForm: false,
|
||||||
hasXfa: false,
|
hasXfa: false,
|
||||||
|
fields: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
acroForm.set("XFA", ["foo", "bar"]);
|
acroForm.set("XFA", ["foo", "bar"]);
|
||||||
@ -82,6 +84,7 @@ describe("document", function () {
|
|||||||
expect(pdfDocument.formInfo).toEqual({
|
expect(pdfDocument.formInfo).toEqual({
|
||||||
hasAcroForm: false,
|
hasAcroForm: false,
|
||||||
hasXfa: true,
|
hasXfa: true,
|
||||||
|
fields: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
acroForm.set("XFA", new StringStream(""));
|
acroForm.set("XFA", new StringStream(""));
|
||||||
@ -89,6 +92,7 @@ describe("document", function () {
|
|||||||
expect(pdfDocument.formInfo).toEqual({
|
expect(pdfDocument.formInfo).toEqual({
|
||||||
hasAcroForm: false,
|
hasAcroForm: false,
|
||||||
hasXfa: false,
|
hasXfa: false,
|
||||||
|
fields: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
acroForm.set("XFA", new StringStream("non-empty"));
|
acroForm.set("XFA", new StringStream("non-empty"));
|
||||||
@ -96,6 +100,7 @@ describe("document", function () {
|
|||||||
expect(pdfDocument.formInfo).toEqual({
|
expect(pdfDocument.formInfo).toEqual({
|
||||||
hasAcroForm: false,
|
hasAcroForm: false,
|
||||||
hasXfa: true,
|
hasXfa: true,
|
||||||
|
fields: null,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -108,6 +113,7 @@ describe("document", function () {
|
|||||||
expect(pdfDocument.formInfo).toEqual({
|
expect(pdfDocument.formInfo).toEqual({
|
||||||
hasAcroForm: false,
|
hasAcroForm: false,
|
||||||
hasXfa: false,
|
hasXfa: false,
|
||||||
|
fields: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
acroForm.set("Fields", ["foo", "bar"]);
|
acroForm.set("Fields", ["foo", "bar"]);
|
||||||
@ -115,6 +121,7 @@ describe("document", function () {
|
|||||||
expect(pdfDocument.formInfo).toEqual({
|
expect(pdfDocument.formInfo).toEqual({
|
||||||
hasAcroForm: true,
|
hasAcroForm: true,
|
||||||
hasXfa: false,
|
hasXfa: false,
|
||||||
|
fields: ["foo", "bar"],
|
||||||
});
|
});
|
||||||
|
|
||||||
// If the first bit of the `SigFlags` entry is set and the `Fields` array
|
// If the first bit of the `SigFlags` entry is set and the `Fields` array
|
||||||
@ -125,6 +132,7 @@ describe("document", function () {
|
|||||||
expect(pdfDocument.formInfo).toEqual({
|
expect(pdfDocument.formInfo).toEqual({
|
||||||
hasAcroForm: true,
|
hasAcroForm: true,
|
||||||
hasXfa: false,
|
hasXfa: false,
|
||||||
|
fields: ["foo", "bar"],
|
||||||
});
|
});
|
||||||
|
|
||||||
const annotationDict = new Dict();
|
const annotationDict = new Dict();
|
||||||
@ -147,6 +155,7 @@ describe("document", function () {
|
|||||||
expect(pdfDocument.formInfo).toEqual({
|
expect(pdfDocument.formInfo).toEqual({
|
||||||
hasAcroForm: false,
|
hasAcroForm: false,
|
||||||
hasXfa: false,
|
hasXfa: false,
|
||||||
|
fields: null,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user