UNPKG

5.15 kBJavaScriptView Raw
1/**
2 * @licstart The following is the entire license notice for the
3 * JavaScript code in this page
4 *
5 * Copyright 2022 Mozilla Foundation
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * @licend The above is the entire license notice for the
20 * JavaScript code in this page
21 */
22"use strict";
23
24Object.defineProperty(exports, "__esModule", {
25 value: true
26});
27exports.XFAParser = void 0;
28
29var _xfa_object = require("./xfa_object.js");
30
31var _xml_parser = require("../xml_parser.js");
32
33var _builder = require("./builder.js");
34
35var _util = require("../../shared/util.js");
36
37class XFAParser extends _xml_parser.XMLParserBase {
38 constructor(rootNameSpace = null, richText = false) {
39 super();
40 this._builder = new _builder.Builder(rootNameSpace);
41 this._stack = [];
42 this._globalData = {
43 usedTypefaces: new Set()
44 };
45 this._ids = new Map();
46 this._current = this._builder.buildRoot(this._ids);
47 this._errorCode = _xml_parser.XMLParserErrorCode.NoError;
48 this._whiteRegex = /^\s+$/;
49 this._nbsps = /\xa0+/g;
50 this._richText = richText;
51 }
52
53 parse(data) {
54 this.parseXml(data);
55
56 if (this._errorCode !== _xml_parser.XMLParserErrorCode.NoError) {
57 return undefined;
58 }
59
60 this._current[_xfa_object.$finalize]();
61
62 return this._current.element;
63 }
64
65 onText(text) {
66 text = text.replace(this._nbsps, match => match.slice(1) + " ");
67
68 if (this._richText || this._current[_xfa_object.$acceptWhitespace]()) {
69 this._current[_xfa_object.$onText](text, this._richText);
70
71 return;
72 }
73
74 if (this._whiteRegex.test(text)) {
75 return;
76 }
77
78 this._current[_xfa_object.$onText](text.trim());
79 }
80
81 onCdata(text) {
82 this._current[_xfa_object.$onText](text);
83 }
84
85 _mkAttributes(attributes, tagName) {
86 let namespace = null;
87 let prefixes = null;
88 const attributeObj = Object.create({});
89
90 for (const {
91 name,
92 value
93 } of attributes) {
94 if (name === "xmlns") {
95 if (!namespace) {
96 namespace = value;
97 } else {
98 (0, _util.warn)(`XFA - multiple namespace definition in <${tagName}>`);
99 }
100 } else if (name.startsWith("xmlns:")) {
101 const prefix = name.substring("xmlns:".length);
102
103 if (!prefixes) {
104 prefixes = [];
105 }
106
107 prefixes.push({
108 prefix,
109 value
110 });
111 } else {
112 const i = name.indexOf(":");
113
114 if (i === -1) {
115 attributeObj[name] = value;
116 } else {
117 let nsAttrs = attributeObj[_xfa_object.$nsAttributes];
118
119 if (!nsAttrs) {
120 nsAttrs = attributeObj[_xfa_object.$nsAttributes] = Object.create(null);
121 }
122
123 const [ns, attrName] = [name.slice(0, i), name.slice(i + 1)];
124 let attrs = nsAttrs[ns];
125
126 if (!attrs) {
127 attrs = nsAttrs[ns] = Object.create(null);
128 }
129
130 attrs[attrName] = value;
131 }
132 }
133 }
134
135 return [namespace, prefixes, attributeObj];
136 }
137
138 _getNameAndPrefix(name, nsAgnostic) {
139 const i = name.indexOf(":");
140
141 if (i === -1) {
142 return [name, null];
143 }
144
145 return [name.substring(i + 1), nsAgnostic ? "" : name.substring(0, i)];
146 }
147
148 onBeginElement(tagName, attributes, isEmpty) {
149 const [namespace, prefixes, attributesObj] = this._mkAttributes(attributes, tagName);
150
151 const [name, nsPrefix] = this._getNameAndPrefix(tagName, this._builder.isNsAgnostic());
152
153 const node = this._builder.build({
154 nsPrefix,
155 name,
156 attributes: attributesObj,
157 namespace,
158 prefixes
159 });
160
161 node[_xfa_object.$globalData] = this._globalData;
162
163 if (isEmpty) {
164 node[_xfa_object.$finalize]();
165
166 if (this._current[_xfa_object.$onChild](node)) {
167 node[_xfa_object.$setId](this._ids);
168 }
169
170 node[_xfa_object.$clean](this._builder);
171
172 return;
173 }
174
175 this._stack.push(this._current);
176
177 this._current = node;
178 }
179
180 onEndElement(name) {
181 const node = this._current;
182
183 if (node[_xfa_object.$isCDATAXml]() && typeof node[_xfa_object.$content] === "string") {
184 const parser = new XFAParser();
185 parser._globalData = this._globalData;
186 const root = parser.parse(node[_xfa_object.$content]);
187 node[_xfa_object.$content] = null;
188
189 node[_xfa_object.$onChild](root);
190 }
191
192 node[_xfa_object.$finalize]();
193
194 this._current = this._stack.pop();
195
196 if (this._current[_xfa_object.$onChild](node)) {
197 node[_xfa_object.$setId](this._ids);
198 }
199
200 node[_xfa_object.$clean](this._builder);
201 }
202
203 onError(code) {
204 this._errorCode = code;
205 }
206
207}
208
209exports.XFAParser = XFAParser;
\No newline at end of file