Skip to content

Commit 81040cc

Browse files
committed
XFA - Add support for prototypes
- specifications: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.364.2157&rep=rep1&type=pdf#page=225&zoom=auto,-207,784 - add a clone method on nodes in order to be able to clone a proto; - support ids in template namespace; - prevent from cycle when applying protos.
1 parent 4619b1b commit 81040cc

File tree

5 files changed

+412
-17
lines changed

5 files changed

+412
-17
lines changed

src/core/xfa/builder.js

+25-5
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,37 @@
1414
*/
1515

1616
import { $buildXFAObject, NamespaceIds } from "./namespaces.js";
17-
import { $cleanup, $onChild, XFAObject } from "./xfa_object.js";
17+
import {
18+
$cleanup,
19+
$finalize,
20+
$onChild,
21+
$resolvePrototypes,
22+
XFAObject,
23+
} from "./xfa_object.js";
1824
import { NamespaceSetUp } from "./setup.js";
25+
import { Template } from "./template.js";
1926
import { UnknownNamespace } from "./unknown.js";
2027
import { warn } from "../../shared/util.js";
2128

29+
const _ids = Symbol();
30+
2231
class Root extends XFAObject {
23-
constructor() {
32+
constructor(ids) {
2433
super(-1, "root", Object.create(null));
2534
this.element = null;
35+
this[_ids] = ids;
2636
}
2737

2838
[$onChild](child) {
2939
this.element = child;
40+
return true;
41+
}
42+
43+
[$finalize]() {
44+
super[$finalize]();
45+
if (this.element.template instanceof Template) {
46+
this.element.template[$resolvePrototypes](this[_ids]);
47+
}
3048
}
3149
}
3250

@@ -35,7 +53,9 @@ class Empty extends XFAObject {
3553
super(-1, "", Object.create(null));
3654
}
3755

38-
[$onChild](_) {}
56+
[$onChild](_) {
57+
return false;
58+
}
3959
}
4060

4161
class Builder {
@@ -51,8 +71,8 @@ class Builder {
5171
this._currentNamespace = new UnknownNamespace(++this._nextNsId);
5272
}
5373

54-
buildRoot() {
55-
return new Root();
74+
buildRoot(ids) {
75+
return new Root(ids);
5676
}
5777

5878
build({ nsPrefix, name, attributes, namespace, prefixes }) {

src/core/xfa/parser.js

+11-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* limitations under the License.
1414
*/
1515

16-
import { $clean, $finalize, $onChild, $onText } from "./xfa_object.js";
16+
import { $clean, $finalize, $onChild, $onText, $setId } from "./xfa_object.js";
1717
import { XMLParserBase, XMLParserErrorCode } from "../xml_parser.js";
1818
import { Builder } from "./builder.js";
1919
import { warn } from "../../shared/util.js";
@@ -23,7 +23,8 @@ class XFAParser extends XMLParserBase {
2323
super();
2424
this._builder = new Builder();
2525
this._stack = [];
26-
this._current = this._builder.buildRoot();
26+
this._ids = new Map();
27+
this._current = this._builder.buildRoot(this._ids);
2728
this._errorCode = XMLParserErrorCode.NoError;
2829
this._whiteRegex = /^\s+$/;
2930
}
@@ -35,6 +36,8 @@ class XFAParser extends XMLParserBase {
3536
return undefined;
3637
}
3738

39+
this._current[$finalize]();
40+
3841
return this._current.element;
3942
}
4043

@@ -101,7 +104,9 @@ class XFAParser extends XMLParserBase {
101104
if (isEmpty) {
102105
// No children: just push the node into its parent.
103106
node[$finalize]();
104-
this._current[$onChild](node);
107+
if (this._current[$onChild](node)) {
108+
node[$setId](this._ids);
109+
}
105110
node[$clean](this._builder);
106111
return;
107112
}
@@ -114,7 +119,9 @@ class XFAParser extends XMLParserBase {
114119
const node = this._current;
115120
node[$finalize]();
116121
this._current = this._stack.pop();
117-
this._current[$onChild](node);
122+
if (this._current[$onChild](node)) {
123+
node[$setId](this._ids);
124+
}
118125
node[$clean](this._builder);
119126
}
120127

src/core/xfa/template.js

+15-5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
$namespaceId,
2222
$nodeName,
2323
$onChild,
24+
$setSetAttributes,
2425
ContentObject,
2526
Option01,
2627
OptionObject,
@@ -1071,9 +1072,15 @@ class ExData extends ContentObject {
10711072
child[$namespaceId] === NamespaceIds.xhtml.id
10721073
) {
10731074
this[$content] = child;
1074-
} else if (this.contentType === "text/xml") {
1075+
return true;
1076+
}
1077+
1078+
if (this.contentType === "text/xml") {
10751079
this[$content] = child;
1080+
return true;
10761081
}
1082+
1083+
return false;
10771084
}
10781085
}
10791086

@@ -2531,9 +2538,10 @@ class Text extends ContentObject {
25312538
[$onChild](child) {
25322539
if (child[$namespaceId] === NamespaceIds.xhtml.id) {
25332540
this[$content] = child;
2534-
} else {
2535-
warn(`XFA - Invalid content in Text: ${child[$nodeName]}.`);
2541+
return true;
25362542
}
2543+
warn(`XFA - Invalid content in Text: ${child[$nodeName]}.`);
2544+
return false;
25372545
}
25382546
}
25392547

@@ -2757,7 +2765,9 @@ class Variables extends XFAObject {
27572765
class TemplateNamespace {
27582766
static [$buildXFAObject](name, attributes) {
27592767
if (TemplateNamespace.hasOwnProperty(name)) {
2760-
return TemplateNamespace[name](attributes);
2768+
const node = TemplateNamespace[name](attributes);
2769+
node[$setSetAttributes](attributes);
2770+
return node;
27612771
}
27622772
return undefined;
27632773
}
@@ -3215,4 +3225,4 @@ class TemplateNamespace {
32153225
}
32163226
}
32173227

3218-
export { TemplateNamespace };
3228+
export { Template, TemplateNamespace };

0 commit comments

Comments
 (0)