Merge pull request #12954 from calixteman/xfa_attrs

XFA -- Add attributes and children in XFAObject
This commit is contained in:
Brendan Dahl 2021-02-03 11:45:45 -08:00 committed by GitHub
commit 0d85de980b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 105 additions and 28 deletions

View File

@ -19,6 +19,7 @@ import {
OptionObject, OptionObject,
StringObject, StringObject,
XFAObject, XFAObject,
XFAObjectArray,
} from "./xfa_object.js"; } from "./xfa_object.js";
const CONFIG_NS_ID = NamespaceIds.config.id; const CONFIG_NS_ID = NamespaceIds.config.id;
@ -31,7 +32,7 @@ class Acrobat extends XFAObject {
this.common = null; this.common = null;
this.validate = null; this.validate = null;
this.validateApprovalSignatures = null; this.validateApprovalSignatures = null;
this.submitUrl = []; this.submitUrl = new XFAObjectArray();
} }
} }
@ -60,7 +61,7 @@ class Config extends XFAObject {
this.acrobat = null; this.acrobat = null;
this.present = null; this.present = null;
this.trace = null; this.trace = null;
this.agent = []; this.agent = new XFAObjectArray();
} }
} }
@ -87,14 +88,14 @@ class Present extends XFAObject {
this.script = null; this.script = null;
this.validate = null; this.validate = null;
this.xdp = null; this.xdp = null;
this.driver = []; this.driver = new XFAObjectArray();
this.labelPrinter = []; this.labelPrinter = new XFAObjectArray();
this.pcl = []; this.pcl = new XFAObjectArray();
this.pdf = []; this.pdf = new XFAObjectArray();
this.ps = []; this.ps = new XFAObjectArray();
this.submitUrl = []; this.submitUrl = new XFAObjectArray();
this.webClient = []; this.webClient = new XFAObjectArray();
this.zpl = []; this.zpl = new XFAObjectArray();
} }
} }

View File

@ -19,6 +19,7 @@ import {
$nodeName, $nodeName,
$onChildCheck, $onChildCheck,
XFAObject, XFAObject,
XFAObjectArray,
} from "./xfa_object.js"; } from "./xfa_object.js";
const XDP_NS_ID = NamespaceIds.xdp.id; const XDP_NS_ID = NamespaceIds.xdp.id;
@ -32,7 +33,7 @@ class Xdp extends XFAObject {
this.connectionSet = null; this.connectionSet = null;
this.datasets = null; this.datasets = null;
this.localeSet = null; this.localeSet = null;
this.stylesheet = []; this.stylesheet = new XFAObjectArray();
this.template = null; this.template = null;
} }

View File

@ -14,7 +14,7 @@
*/ */
import { getInteger, getKeyword } from "./utils.js"; import { getInteger, getKeyword } from "./utils.js";
import { warn } from "../../shared/util.js"; import { shadow, warn } from "../../shared/util.js";
// We use these symbols to avoid name conflict between tags // We use these symbols to avoid name conflict between tags
// and properties/methods names. // and properties/methods names.
@ -23,15 +23,22 @@ const $cleanup = Symbol();
const $content = Symbol("content"); const $content = Symbol("content");
const $dump = Symbol(); const $dump = Symbol();
const $finalize = Symbol(); const $finalize = Symbol();
const $getChildren = Symbol();
const $isTransparent = Symbol(); const $isTransparent = Symbol();
const $lastAttribute = Symbol();
const $namespaceId = Symbol("namespaceId"); const $namespaceId = Symbol("namespaceId");
const $nodeName = Symbol("nodeName"); const $nodeName = Symbol("nodeName");
const $onChild = Symbol(); const $onChild = Symbol();
const $onChildCheck = Symbol(); const $onChildCheck = Symbol();
const $onText = Symbol(); const $onText = Symbol();
const $text = Symbol();
const _attributes = Symbol();
const _attributeNames = Symbol();
const _children = Symbol();
const _defaultValue = Symbol(); const _defaultValue = Symbol();
const _hasChildren = Symbol(); const _hasChildren = Symbol();
const _max = Symbol();
const _options = Symbol(); const _options = Symbol();
const _parent = Symbol(); const _parent = Symbol();
const _validator = Symbol(); const _validator = Symbol();
@ -42,6 +49,7 @@ class XFAObject {
this[$nodeName] = name; this[$nodeName] = name;
this[_hasChildren] = hasChildren; this[_hasChildren] = hasChildren;
this[_parent] = null; this[_parent] = null;
this[_children] = [];
} }
[$onChild](child) { [$onChild](child) {
@ -51,12 +59,15 @@ class XFAObject {
const name = child[$nodeName]; const name = child[$nodeName];
const node = this[name]; const node = this[name];
if (Array.isArray(node)) { if (node instanceof XFAObjectArray) {
node.push(child); if (node.push(child)) {
child[_parent] = this; child[_parent] = this;
this[_children].push(child);
}
} else if (node === null) { } else if (node === null) {
this[name] = child; this[name] = child;
child[_parent] = this; child[_parent] = this;
this[_children].push(child);
} else { } else {
warn(`XFA - node "${this[$nodeName]}" accepts only one child: ${name}`); warn(`XFA - node "${this[$nodeName]}" accepts only one child: ${name}`);
} }
@ -85,6 +96,37 @@ class XFAObject {
return this.name === ""; return this.name === "";
} }
[$lastAttribute]() {
return "";
}
get [_attributeNames]() {
// Lazily get attributes names
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);
}
[$getChildren](name = null) {
if (!name) {
return this[_children];
}
return this[_children].filter(c => c[$nodeName] === name);
}
[$dump]() { [$dump]() {
const dumped = Object.create(null); const dumped = Object.create(null);
if (this[$content]) { if (this[$content]) {
@ -93,17 +135,14 @@ class XFAObject {
for (const name of Object.getOwnPropertyNames(this)) { for (const name of Object.getOwnPropertyNames(this)) {
const value = this[name]; const value = this[name];
if (value === null || (Array.isArray(value) && value.length === 0)) { if (value === null) {
continue; continue;
} }
if (value instanceof XFAObject) { if (value instanceof XFAObject) {
dumped[name] = value[$dump](); dumped[name] = value[$dump]();
} else if (Array.isArray(value)) { } else if (value instanceof XFAObjectArray) {
if (value[0] instanceof XFAObject) { if (!value.isEmpty()) {
dumped[name] = dumped[name] = value.dump();
value.length === 1 ? value[0][$dump]() : value.map(x => x[$dump]());
} else {
dumped[name] = value;
} }
} else { } else {
dumped[name] = value; dumped[name] = value;
@ -114,13 +153,41 @@ class XFAObject {
} }
} }
class XFAObjectArray {
constructor(max = Infinity) {
this[_max] = max;
this[_children] = [];
}
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]());
}
}
class XmlObject extends XFAObject { class XmlObject extends XFAObject {
constructor(nsId, name, attributes = Object.create(null)) { constructor(nsId, name, attributes = Object.create(null)) {
super(nsId, name); super(nsId, name);
this[$content] = ""; this[$content] = "";
if (name !== "#text") { if (name !== "#text") {
this.attributes = attributes; this[_attributes] = attributes;
this.children = [];
} }
} }
@ -129,9 +196,9 @@ class XmlObject extends XFAObject {
const node = new XmlObject(this[$namespaceId], "#text"); const node = new XmlObject(this[$namespaceId], "#text");
node[$content] = this[$content]; node[$content] = this[$content];
this[$content] = ""; this[$content] = "";
this.children.push(node); this[_children].push(node);
} }
this.children.push(child); this[_children].push(child);
} }
[$onText](str) { [$onText](str) {
@ -139,13 +206,20 @@ class XmlObject extends XFAObject {
} }
[$finalize]() { [$finalize]() {
if (this[$content] && this.children.length > 0) { if (this[$content] && this[_children].length > 0) {
const node = new XmlObject(this[$namespaceId], "#text"); const node = new XmlObject(this[$namespaceId], "#text");
node[$content] = this[$content]; node[$content] = this[$content];
this.children.push(node); this[_children].push(node);
delete this[$content]; delete this[$content];
} }
} }
[$text]() {
if (this[_children].length === 0) {
return this[$content];
}
return this[_children].map(c => c[$text]()).join("");
}
} }
class ContentObject extends XFAObject { class ContentObject extends XFAObject {
@ -240,5 +314,6 @@ export {
OptionObject, OptionObject,
StringObject, StringObject,
XFAObject, XFAObject,
XFAObjectArray,
XmlObject, XmlObject,
}; };