plist 2.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.travis.yml +12 -21
- package/History.md +34 -2
- package/LICENSE +1 -1
- package/Makefile +1 -2
- package/README.md +56 -28
- package/dist/plist-build.js +2025 -3175
- package/dist/plist-parse.js +1261 -1019
- package/dist/plist.js +2922 -3885
- package/lib/parse.js +98 -35
- package/package.json +10 -7
package/lib/parse.js
CHANGED
|
@@ -10,6 +10,11 @@ var DOMParser = require('xmldom').DOMParser;
|
|
|
10
10
|
|
|
11
11
|
exports.parse = parse;
|
|
12
12
|
|
|
13
|
+
var TEXT_NODE = 3;
|
|
14
|
+
var CDATA_NODE = 4;
|
|
15
|
+
var COMMENT_NODE = 8;
|
|
16
|
+
|
|
17
|
+
|
|
13
18
|
/**
|
|
14
19
|
* We ignore raw text (usually whitespace), <!-- xml comments -->,
|
|
15
20
|
* and raw CDATA nodes.
|
|
@@ -20,11 +25,34 @@ exports.parse = parse;
|
|
|
20
25
|
*/
|
|
21
26
|
|
|
22
27
|
function shouldIgnoreNode (node) {
|
|
23
|
-
return node.nodeType ===
|
|
24
|
-
|| node.nodeType ===
|
|
25
|
-
|| node.nodeType ===
|
|
28
|
+
return node.nodeType === TEXT_NODE
|
|
29
|
+
|| node.nodeType === COMMENT_NODE
|
|
30
|
+
|| node.nodeType === CDATA_NODE;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Check if the node is empty. Some plist file has such node:
|
|
35
|
+
* <key />
|
|
36
|
+
* this node shoud be ignored.
|
|
37
|
+
*
|
|
38
|
+
* @see https://github.com/TooTallNate/plist.js/issues/66
|
|
39
|
+
* @param {Element} node
|
|
40
|
+
* @returns {Boolean}
|
|
41
|
+
* @api private
|
|
42
|
+
*/
|
|
43
|
+
function isEmptyNode(node){
|
|
44
|
+
if(!node.childNodes || node.childNodes.length === 0) {
|
|
45
|
+
return true;
|
|
46
|
+
} else {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
26
49
|
}
|
|
27
50
|
|
|
51
|
+
function invariant(test, message) {
|
|
52
|
+
if (!test) {
|
|
53
|
+
throw new Error(message);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
28
56
|
|
|
29
57
|
/**
|
|
30
58
|
* Parses a Plist XML string. Returns an Object.
|
|
@@ -36,9 +64,10 @@ function shouldIgnoreNode (node) {
|
|
|
36
64
|
|
|
37
65
|
function parse (xml) {
|
|
38
66
|
var doc = new DOMParser().parseFromString(xml);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
67
|
+
invariant(
|
|
68
|
+
doc.documentElement.nodeName === 'plist',
|
|
69
|
+
'malformed document. First element should be <plist>'
|
|
70
|
+
);
|
|
42
71
|
var plist = parsePlistXML(doc.documentElement);
|
|
43
72
|
|
|
44
73
|
// the root <plist> node gets interpreted as an Array,
|
|
@@ -57,41 +86,59 @@ function parse (xml) {
|
|
|
57
86
|
*/
|
|
58
87
|
|
|
59
88
|
function parsePlistXML (node) {
|
|
60
|
-
var i, new_obj, key, val, new_arr, res,
|
|
89
|
+
var i, new_obj, key, val, new_arr, res, counter, type;
|
|
61
90
|
|
|
62
91
|
if (!node)
|
|
63
92
|
return null;
|
|
64
93
|
|
|
65
94
|
if (node.nodeName === 'plist') {
|
|
66
95
|
new_arr = [];
|
|
96
|
+
if (isEmptyNode(node)) {
|
|
97
|
+
return new_arr;
|
|
98
|
+
}
|
|
67
99
|
for (i=0; i < node.childNodes.length; i++) {
|
|
68
|
-
// ignore comment nodes (text)
|
|
69
100
|
if (!shouldIgnoreNode(node.childNodes[i])) {
|
|
70
101
|
new_arr.push( parsePlistXML(node.childNodes[i]));
|
|
71
102
|
}
|
|
72
103
|
}
|
|
73
104
|
return new_arr;
|
|
74
|
-
|
|
75
105
|
} else if (node.nodeName === 'dict') {
|
|
76
106
|
new_obj = {};
|
|
77
107
|
key = null;
|
|
108
|
+
counter = 0;
|
|
109
|
+
if (isEmptyNode(node)) {
|
|
110
|
+
return new_obj;
|
|
111
|
+
}
|
|
78
112
|
for (i=0; i < node.childNodes.length; i++) {
|
|
79
|
-
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
113
|
+
if (shouldIgnoreNode(node.childNodes[i])) continue;
|
|
114
|
+
if (counter % 2 === 0) {
|
|
115
|
+
invariant(
|
|
116
|
+
node.childNodes[i].nodeName === 'key',
|
|
117
|
+
'Missing key while parsing <dict/>.'
|
|
118
|
+
);
|
|
119
|
+
key = parsePlistXML(node.childNodes[i]);
|
|
120
|
+
} else {
|
|
121
|
+
invariant(
|
|
122
|
+
node.childNodes[i].nodeName !== 'key',
|
|
123
|
+
'Unexpected key "'
|
|
124
|
+
+ parsePlistXML(node.childNodes[i])
|
|
125
|
+
+ '" while parsing <dict/>.'
|
|
126
|
+
);
|
|
127
|
+
new_obj[key] = parsePlistXML(node.childNodes[i]);
|
|
87
128
|
}
|
|
129
|
+
counter += 1;
|
|
130
|
+
}
|
|
131
|
+
if (counter % 2 === 1) {
|
|
132
|
+
throw new Error('Missing value for "' + key + '" while parsing <dict/>');
|
|
88
133
|
}
|
|
89
134
|
return new_obj;
|
|
90
135
|
|
|
91
136
|
} else if (node.nodeName === 'array') {
|
|
92
137
|
new_arr = [];
|
|
138
|
+
if (isEmptyNode(node)) {
|
|
139
|
+
return new_arr;
|
|
140
|
+
}
|
|
93
141
|
for (i=0; i < node.childNodes.length; i++) {
|
|
94
|
-
// ignore comment nodes (text)
|
|
95
142
|
if (!shouldIgnoreNode(node.childNodes[i])) {
|
|
96
143
|
res = parsePlistXML(node.childNodes[i]);
|
|
97
144
|
if (null != res) new_arr.push(res);
|
|
@@ -103,44 +150,60 @@ function parsePlistXML (node) {
|
|
|
103
150
|
// TODO: what should we do with text types? (CDATA sections)
|
|
104
151
|
|
|
105
152
|
} else if (node.nodeName === 'key') {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
res = node.childNodes[0].nodeValue;
|
|
153
|
+
if (isEmptyNode(node)) {
|
|
154
|
+
return '';
|
|
109
155
|
}
|
|
110
|
-
return
|
|
111
|
-
|
|
156
|
+
return node.childNodes[0].nodeValue;
|
|
112
157
|
} else if (node.nodeName === 'string') {
|
|
113
158
|
res = '';
|
|
114
|
-
|
|
115
|
-
res
|
|
159
|
+
if (isEmptyNode(node)) {
|
|
160
|
+
return res;
|
|
161
|
+
}
|
|
162
|
+
for (i=0; i < node.childNodes.length; i++) {
|
|
163
|
+
var type = node.childNodes[i].nodeType;
|
|
164
|
+
if (type === TEXT_NODE || type === CDATA_NODE) {
|
|
165
|
+
res += node.childNodes[i].nodeValue;
|
|
166
|
+
}
|
|
116
167
|
}
|
|
117
168
|
return res;
|
|
118
169
|
|
|
119
170
|
} else if (node.nodeName === 'integer') {
|
|
120
|
-
|
|
171
|
+
invariant(
|
|
172
|
+
!isEmptyNode(node),
|
|
173
|
+
'Cannot parse "" as integer.'
|
|
174
|
+
);
|
|
121
175
|
return parseInt(node.childNodes[0].nodeValue, 10);
|
|
122
176
|
|
|
123
177
|
} else if (node.nodeName === 'real') {
|
|
178
|
+
invariant(
|
|
179
|
+
!isEmptyNode(node),
|
|
180
|
+
'Cannot parse "" as real.'
|
|
181
|
+
);
|
|
124
182
|
res = '';
|
|
125
|
-
for (
|
|
126
|
-
if (node.childNodes[
|
|
127
|
-
res += node.childNodes[
|
|
183
|
+
for (i=0; i < node.childNodes.length; i++) {
|
|
184
|
+
if (node.childNodes[i].nodeType === TEXT_NODE) {
|
|
185
|
+
res += node.childNodes[i].nodeValue;
|
|
128
186
|
}
|
|
129
187
|
}
|
|
130
188
|
return parseFloat(res);
|
|
131
189
|
|
|
132
190
|
} else if (node.nodeName === 'data') {
|
|
133
191
|
res = '';
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
192
|
+
if (isEmptyNode(node)) {
|
|
193
|
+
return Buffer.from(res, 'base64');
|
|
194
|
+
}
|
|
195
|
+
for (i=0; i < node.childNodes.length; i++) {
|
|
196
|
+
if (node.childNodes[i].nodeType === TEXT_NODE) {
|
|
197
|
+
res += node.childNodes[i].nodeValue.replace(/\s+/g, '');
|
|
137
198
|
}
|
|
138
199
|
}
|
|
139
|
-
|
|
140
|
-
// decode base64 data to a Buffer instance
|
|
141
|
-
return new Buffer(res, 'base64');
|
|
200
|
+
return Buffer.from(res, 'base64');
|
|
142
201
|
|
|
143
202
|
} else if (node.nodeName === 'date') {
|
|
203
|
+
invariant(
|
|
204
|
+
!isEmptyNode(node),
|
|
205
|
+
'Cannot parse "" as Date.'
|
|
206
|
+
)
|
|
144
207
|
return new Date(node.childNodes[0].nodeValue);
|
|
145
208
|
|
|
146
209
|
} else if (node.nodeName === 'true') {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plist",
|
|
3
3
|
"description": "Mac OS X Plist parser/builder for Node.js and browsers",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "3.0.1",
|
|
5
5
|
"author": "Nathan Rajlich <nathan@tootallnate.net>",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Hans Huebner <hans.huebner@gmail.com>",
|
|
@@ -25,17 +25,20 @@
|
|
|
25
25
|
],
|
|
26
26
|
"main": "index.js",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"base64-js": "
|
|
29
|
-
"xmlbuilder": "
|
|
28
|
+
"base64-js": "^1.2.3",
|
|
29
|
+
"xmlbuilder": "^9.0.7",
|
|
30
30
|
"xmldom": "0.1.x"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"browserify": "
|
|
34
|
-
"mocha": "
|
|
35
|
-
"multiline": "1.0.2",
|
|
36
|
-
"zuul": "3.
|
|
33
|
+
"browserify": "^16.1.1",
|
|
34
|
+
"mocha": "^5.0.4",
|
|
35
|
+
"multiline": "^1.0.2",
|
|
36
|
+
"zuul": "^3.10.1"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"test": "make test"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=6"
|
|
40
43
|
}
|
|
41
44
|
}
|