plist 3.1.0 → 4.0.0
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/README.md +33 -28
- package/index.js +2 -13
- package/lib/build.js +32 -28
- package/lib/parse.js +80 -94
- package/package.json +10 -12
- package/.github/workflows/ci.yml +0 -24
- package/.jshintrc +0 -4
- package/History.md +0 -196
- package/Makefile +0 -75
- package/dist/plist-build.js +0 -5348
- package/dist/plist-parse.js +0 -7456
- package/dist/plist.js +0 -9888
- package/examples/browser/index.html +0 -14
package/README.md
CHANGED
|
@@ -20,33 +20,44 @@ and vice-versa.
|
|
|
20
20
|
Install using `npm`:
|
|
21
21
|
|
|
22
22
|
``` bash
|
|
23
|
-
$ npm install
|
|
23
|
+
$ npm install plist
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Then `
|
|
26
|
+
Then import the `parse()` and `build()` functions:
|
|
27
27
|
|
|
28
28
|
``` js
|
|
29
|
-
|
|
29
|
+
import { parse, build } from 'plist';
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
var val = plist.parse('<plist><string>Hello World!</string></plist>');
|
|
31
|
+
const val = parse('<plist><string>Hello World!</string></plist>');
|
|
33
32
|
console.log(val); // "Hello World!"
|
|
34
33
|
```
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
### Browser
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
Use an [import map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap)
|
|
39
|
+
to resolve the bare module specifiers used by plist and its dependencies,
|
|
40
|
+
then import directly from the source:
|
|
40
41
|
|
|
41
42
|
``` html
|
|
42
|
-
<script
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
<script type="importmap">
|
|
44
|
+
{
|
|
45
|
+
"imports": {
|
|
46
|
+
"@xmldom/xmldom": "https://esm.sh/@xmldom/xmldom",
|
|
47
|
+
"xmlbuilder": "https://esm.sh/xmlbuilder"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
</script>
|
|
51
|
+
<script type="module">
|
|
52
|
+
import { parse, build } from './node_modules/plist/index.js';
|
|
53
|
+
|
|
54
|
+
const val = parse('<plist><string>Hello World!</string></plist>');
|
|
46
55
|
console.log(val); // "Hello World!"
|
|
47
56
|
</script>
|
|
48
57
|
```
|
|
49
58
|
|
|
59
|
+
See the [browser example](./examples/browser/) for a drag-and-drop demo.
|
|
60
|
+
|
|
50
61
|
|
|
51
62
|
## API
|
|
52
63
|
|
|
@@ -54,20 +65,20 @@ Include the `dist/plist.js` in a `<script>` tag in your HTML file:
|
|
|
54
65
|
|
|
55
66
|
Parsing a plist from filename:
|
|
56
67
|
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
``` js
|
|
69
|
+
import { readFileSync } from 'node:fs';
|
|
70
|
+
import { parse } from 'plist';
|
|
60
71
|
|
|
61
|
-
|
|
72
|
+
const obj = parse(readFileSync('myPlist.plist', 'utf8'));
|
|
62
73
|
console.log(JSON.stringify(obj));
|
|
63
74
|
```
|
|
64
75
|
|
|
65
76
|
Parsing a plist from string payload:
|
|
66
77
|
|
|
67
|
-
```
|
|
68
|
-
|
|
78
|
+
``` js
|
|
79
|
+
import { parse } from 'plist';
|
|
69
80
|
|
|
70
|
-
|
|
81
|
+
const xml =
|
|
71
82
|
'<?xml version="1.0" encoding="UTF-8"?>' +
|
|
72
83
|
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' +
|
|
73
84
|
'<plist version="1.0">' +
|
|
@@ -84,7 +95,7 @@ var xml =
|
|
|
84
95
|
'</dict>' +
|
|
85
96
|
'</plist>';
|
|
86
97
|
|
|
87
|
-
console.log(
|
|
98
|
+
console.log(parse(xml));
|
|
88
99
|
|
|
89
100
|
// [
|
|
90
101
|
// "metadata",
|
|
@@ -102,10 +113,10 @@ console.log(plist.parse(xml));
|
|
|
102
113
|
Given an existing JavaScript Object, you can turn it into an XML document
|
|
103
114
|
that complies with the plist DTD:
|
|
104
115
|
|
|
105
|
-
```
|
|
106
|
-
|
|
116
|
+
``` js
|
|
117
|
+
import { build } from 'plist';
|
|
107
118
|
|
|
108
|
-
|
|
119
|
+
const obj = [
|
|
109
120
|
"metadata",
|
|
110
121
|
{
|
|
111
122
|
"bundle-identifier": "com.company.app",
|
|
@@ -115,7 +126,7 @@ var json = [
|
|
|
115
126
|
}
|
|
116
127
|
];
|
|
117
128
|
|
|
118
|
-
console.log(
|
|
129
|
+
console.log(build(obj));
|
|
119
130
|
|
|
120
131
|
// <?xml version="1.0" encoding="UTF-8"?>
|
|
121
132
|
// <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -134,12 +145,6 @@ console.log(plist.build(json));
|
|
|
134
145
|
// </plist>
|
|
135
146
|
```
|
|
136
147
|
|
|
137
|
-
## Cross Platform Testing Credits
|
|
138
|
-
|
|
139
|
-
Much thanks to Sauce Labs for providing free resources that enable cross-browser testing on this project!
|
|
140
|
-
|
|
141
|
-
[](https://saucelabs.com)
|
|
142
|
-
|
|
143
148
|
|
|
144
149
|
## License
|
|
145
150
|
|
package/index.js
CHANGED
|
@@ -1,13 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
var parserFunctions = require('./lib/parse');
|
|
6
|
-
Object.keys(parserFunctions).forEach(function (k) { exports[k] = parserFunctions[k]; });
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Builder functions.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
var builderFunctions = require('./lib/build');
|
|
13
|
-
Object.keys(builderFunctions).forEach(function (k) { exports[k] = builderFunctions[k]; });
|
|
1
|
+
export { parse } from './lib/parse.js';
|
|
2
|
+
export { build } from './lib/build.js';
|
package/lib/build.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
* Module dependencies.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
var base64 = require('base64-js');
|
|
6
|
-
var xmlbuilder = require('xmlbuilder');
|
|
1
|
+
import xmlbuilder from 'xmlbuilder';
|
|
7
2
|
|
|
8
3
|
/**
|
|
9
|
-
*
|
|
4
|
+
* Encode a Uint8Array into a base64 string.
|
|
5
|
+
*
|
|
6
|
+
* @param {Uint8Array} bytes
|
|
7
|
+
* @returns {String} base64 encoded string
|
|
8
|
+
* @api private
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
function uint8ArrayToBase64(bytes) {
|
|
12
|
+
let binary = '';
|
|
13
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
14
|
+
binary += String.fromCharCode(bytes[i]);
|
|
15
|
+
}
|
|
16
|
+
return btoa(binary);
|
|
17
|
+
}
|
|
13
18
|
|
|
14
19
|
/**
|
|
15
20
|
* Accepts a `Date` instance and returns an ISO date string.
|
|
@@ -40,9 +45,9 @@ function ISODateString(d){
|
|
|
40
45
|
* @api private
|
|
41
46
|
*/
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
const toString = Object.prototype.toString;
|
|
44
49
|
function type (obj) {
|
|
45
|
-
|
|
50
|
+
const m = toString.call(obj).match(/\[object (.*)\]/);
|
|
46
51
|
return m ? m[1] : m;
|
|
47
52
|
}
|
|
48
53
|
|
|
@@ -55,18 +60,18 @@ function type (obj) {
|
|
|
55
60
|
* @api public
|
|
56
61
|
*/
|
|
57
62
|
|
|
58
|
-
function build (obj, opts) {
|
|
59
|
-
|
|
63
|
+
export function build (obj, opts) {
|
|
64
|
+
const XMLHDR = {
|
|
60
65
|
version: '1.0',
|
|
61
66
|
encoding: 'UTF-8'
|
|
62
67
|
};
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
const XMLDTD = {
|
|
65
70
|
pubid: '-//Apple//DTD PLIST 1.0//EN',
|
|
66
71
|
sysid: 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'
|
|
67
72
|
};
|
|
68
73
|
|
|
69
|
-
|
|
74
|
+
const doc = xmlbuilder.create('plist');
|
|
70
75
|
|
|
71
76
|
doc.dec(XMLHDR.version, XMLHDR.encoding, XMLHDR.standalone);
|
|
72
77
|
doc.dtd(XMLDTD.pubid, XMLDTD.sysid);
|
|
@@ -88,23 +93,29 @@ function build (obj, opts) {
|
|
|
88
93
|
*/
|
|
89
94
|
|
|
90
95
|
function walk_obj(next, next_child) {
|
|
91
|
-
|
|
92
|
-
var name = type(next);
|
|
96
|
+
const name = type(next);
|
|
93
97
|
|
|
94
98
|
if ('Undefined' == name) {
|
|
95
99
|
return;
|
|
96
100
|
} else if (Array.isArray(next)) {
|
|
97
101
|
next_child = next_child.ele('array');
|
|
98
|
-
for (i = 0; i < next.length; i++) {
|
|
102
|
+
for (let i = 0; i < next.length; i++) {
|
|
99
103
|
walk_obj(next[i], next_child);
|
|
100
104
|
}
|
|
101
105
|
|
|
102
|
-
} else if (
|
|
103
|
-
next_child.ele('data').raw(next
|
|
106
|
+
} else if (next instanceof ArrayBuffer) {
|
|
107
|
+
next_child.ele('data').raw(uint8ArrayToBase64(new Uint8Array(next)));
|
|
108
|
+
|
|
109
|
+
} else if (ArrayBuffer.isView(next)) {
|
|
110
|
+
// Handles Uint8Array, Buffer, and all typed arrays
|
|
111
|
+
const bytes = next instanceof Uint8Array
|
|
112
|
+
? next
|
|
113
|
+
: new Uint8Array(next.buffer, next.byteOffset, next.byteLength);
|
|
114
|
+
next_child.ele('data').raw(uint8ArrayToBase64(bytes));
|
|
104
115
|
|
|
105
116
|
} else if ('Object' == name) {
|
|
106
117
|
next_child = next_child.ele('dict');
|
|
107
|
-
for (prop in next) {
|
|
118
|
+
for (const prop in next) {
|
|
108
119
|
if (next.hasOwnProperty(prop)) {
|
|
109
120
|
next_child.ele('key').txt(prop);
|
|
110
121
|
walk_obj(next[prop], next_child);
|
|
@@ -114,7 +125,7 @@ function walk_obj(next, next_child) {
|
|
|
114
125
|
} else if ('Number' == name) {
|
|
115
126
|
// detect if this is an integer or real
|
|
116
127
|
// TODO: add an ability to force one way or another via a "cast"
|
|
117
|
-
tag_type = (next % 1 === 0) ? 'integer' : 'real';
|
|
128
|
+
const tag_type = (next % 1 === 0) ? 'integer' : 'real';
|
|
118
129
|
next_child.ele(tag_type).txt(next.toString());
|
|
119
130
|
|
|
120
131
|
} else if ('BigInt' == name) {
|
|
@@ -129,13 +140,6 @@ function walk_obj(next, next_child) {
|
|
|
129
140
|
} else if ('String' == name) {
|
|
130
141
|
next_child.ele('string').txt(next);
|
|
131
142
|
|
|
132
|
-
} else if ('ArrayBuffer' == name) {
|
|
133
|
-
next_child.ele('data').raw(base64.fromByteArray(next));
|
|
134
|
-
|
|
135
|
-
} else if (next && next.buffer && 'ArrayBuffer' == type(next.buffer)) {
|
|
136
|
-
// a typed array
|
|
137
|
-
next_child.ele('data').raw(base64.fromByteArray(new Uint8Array(next.buffer), next_child));
|
|
138
|
-
|
|
139
143
|
} else if ('Null' === name) {
|
|
140
144
|
next_child.ele('null').txt('');
|
|
141
145
|
|
package/lib/parse.js
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
* Module dependencies.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const { DOMParser } = require('@xmldom/xmldom');
|
|
1
|
+
import { DOMParser } from '@xmldom/xmldom';
|
|
6
2
|
|
|
7
3
|
/**
|
|
8
|
-
*
|
|
4
|
+
* Decode a base64 string into a Uint8Array.
|
|
5
|
+
*
|
|
6
|
+
* @param {String} base64 - base64 encoded string
|
|
7
|
+
* @returns {Uint8Array}
|
|
8
|
+
* @api private
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
function base64ToUint8Array(base64) {
|
|
12
|
+
const binary = atob(base64);
|
|
13
|
+
const bytes = new Uint8Array(binary.length);
|
|
14
|
+
for (let i = 0; i < binary.length; i++) {
|
|
15
|
+
bytes[i] = binary.charCodeAt(i);
|
|
16
|
+
}
|
|
17
|
+
return bytes;
|
|
18
|
+
}
|
|
16
19
|
|
|
20
|
+
const TEXT_NODE = 3;
|
|
21
|
+
const CDATA_NODE = 4;
|
|
22
|
+
const COMMENT_NODE = 8;
|
|
17
23
|
|
|
18
24
|
/**
|
|
19
25
|
* We ignore raw text (usually whitespace), <!-- xml comments -->,
|
|
@@ -24,10 +30,12 @@ var COMMENT_NODE = 8;
|
|
|
24
30
|
* @api private
|
|
25
31
|
*/
|
|
26
32
|
|
|
27
|
-
function shouldIgnoreNode
|
|
28
|
-
return
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
function shouldIgnoreNode(node) {
|
|
34
|
+
return (
|
|
35
|
+
node.nodeType === TEXT_NODE ||
|
|
36
|
+
node.nodeType === COMMENT_NODE ||
|
|
37
|
+
node.nodeType === CDATA_NODE
|
|
38
|
+
);
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
/**
|
|
@@ -40,8 +48,8 @@ function shouldIgnoreNode (node) {
|
|
|
40
48
|
* @returns {Boolean}
|
|
41
49
|
* @api private
|
|
42
50
|
*/
|
|
43
|
-
function isEmptyNode(node){
|
|
44
|
-
if(!node.childNodes || node.childNodes.length === 0) {
|
|
51
|
+
function isEmptyNode(node) {
|
|
52
|
+
if (!node.childNodes || node.childNodes.length === 0) {
|
|
45
53
|
return true;
|
|
46
54
|
} else {
|
|
47
55
|
return false;
|
|
@@ -62,13 +70,13 @@ function invariant(test, message) {
|
|
|
62
70
|
* @api public
|
|
63
71
|
*/
|
|
64
72
|
|
|
65
|
-
function parse
|
|
66
|
-
|
|
73
|
+
export function parse(xml) {
|
|
74
|
+
const doc = new DOMParser().parseFromString(xml, "text/xml");
|
|
67
75
|
invariant(
|
|
68
|
-
doc.documentElement.nodeName ===
|
|
69
|
-
|
|
76
|
+
doc.documentElement.nodeName === "plist",
|
|
77
|
+
"malformed document. First element should be <plist>",
|
|
70
78
|
);
|
|
71
|
-
|
|
79
|
+
let plist = parsePlistXML(doc.documentElement);
|
|
72
80
|
|
|
73
81
|
// the root <plist> node gets interpreted as an Array,
|
|
74
82
|
// so pull out the inner data first
|
|
@@ -85,143 +93,121 @@ function parse (xml) {
|
|
|
85
93
|
* @api private
|
|
86
94
|
*/
|
|
87
95
|
|
|
88
|
-
function parsePlistXML
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (!node)
|
|
92
|
-
return null;
|
|
96
|
+
function parsePlistXML(node) {
|
|
97
|
+
if (!node) return null;
|
|
93
98
|
|
|
94
|
-
if (node.nodeName ===
|
|
95
|
-
new_arr = [];
|
|
99
|
+
if (node.nodeName === "plist") {
|
|
100
|
+
const new_arr = [];
|
|
96
101
|
if (isEmptyNode(node)) {
|
|
97
102
|
return new_arr;
|
|
98
103
|
}
|
|
99
|
-
for (i=0; i < node.childNodes.length; i++) {
|
|
104
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
100
105
|
if (!shouldIgnoreNode(node.childNodes[i])) {
|
|
101
|
-
new_arr.push(
|
|
106
|
+
new_arr.push(parsePlistXML(node.childNodes[i]));
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
return new_arr;
|
|
105
|
-
} else if (node.nodeName ===
|
|
106
|
-
new_obj = {};
|
|
107
|
-
key = null;
|
|
108
|
-
counter = 0;
|
|
110
|
+
} else if (node.nodeName === "dict") {
|
|
111
|
+
const new_obj = {};
|
|
112
|
+
let key = null;
|
|
113
|
+
let counter = 0;
|
|
109
114
|
if (isEmptyNode(node)) {
|
|
110
115
|
return new_obj;
|
|
111
116
|
}
|
|
112
|
-
for (i=0; i < node.childNodes.length; i++) {
|
|
117
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
113
118
|
if (shouldIgnoreNode(node.childNodes[i])) continue;
|
|
114
119
|
if (counter % 2 === 0) {
|
|
115
120
|
invariant(
|
|
116
|
-
node.childNodes[i].nodeName ===
|
|
117
|
-
|
|
121
|
+
node.childNodes[i].nodeName === "key",
|
|
122
|
+
"Missing key while parsing <dict/>.",
|
|
118
123
|
);
|
|
119
124
|
key = parsePlistXML(node.childNodes[i]);
|
|
120
125
|
} else {
|
|
121
126
|
invariant(
|
|
122
|
-
node.childNodes[i].nodeName !==
|
|
123
|
-
'Unexpected key "'
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
node.childNodes[i].nodeName !== "key",
|
|
128
|
+
'Unexpected key "' +
|
|
129
|
+
parsePlistXML(node.childNodes[i]) +
|
|
130
|
+
'" while parsing <dict/>.',
|
|
126
131
|
);
|
|
127
132
|
new_obj[key] = parsePlistXML(node.childNodes[i]);
|
|
128
133
|
}
|
|
129
134
|
counter += 1;
|
|
130
135
|
}
|
|
131
136
|
if (counter % 2 === 1) {
|
|
132
|
-
new_obj[key] =
|
|
137
|
+
new_obj[key] = "";
|
|
133
138
|
}
|
|
134
|
-
|
|
135
|
-
return new_obj;
|
|
136
139
|
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
return new_obj;
|
|
141
|
+
} else if (node.nodeName === "array") {
|
|
142
|
+
const new_arr = [];
|
|
139
143
|
if (isEmptyNode(node)) {
|
|
140
144
|
return new_arr;
|
|
141
145
|
}
|
|
142
|
-
for (i=0; i < node.childNodes.length; i++) {
|
|
146
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
143
147
|
if (!shouldIgnoreNode(node.childNodes[i])) {
|
|
144
|
-
res = parsePlistXML(node.childNodes[i]);
|
|
148
|
+
const res = parsePlistXML(node.childNodes[i]);
|
|
145
149
|
if (null != res) new_arr.push(res);
|
|
146
150
|
}
|
|
147
151
|
}
|
|
148
152
|
return new_arr;
|
|
149
|
-
|
|
150
|
-
} else if (node.nodeName === '#text') {
|
|
153
|
+
} else if (node.nodeName === "#text") {
|
|
151
154
|
// TODO: what should we do with text types? (CDATA sections)
|
|
152
|
-
|
|
153
|
-
} else if (node.nodeName === 'key') {
|
|
155
|
+
} else if (node.nodeName === "key") {
|
|
154
156
|
if (isEmptyNode(node)) {
|
|
155
|
-
return
|
|
157
|
+
return "";
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
invariant(
|
|
159
|
-
node.childNodes[0].nodeValue !==
|
|
160
|
-
|
|
161
|
+
node.childNodes[0].nodeValue !== "__proto__",
|
|
162
|
+
"__proto__ keys can lead to prototype pollution. More details on CVE-2022-22912",
|
|
161
163
|
);
|
|
162
164
|
|
|
163
165
|
return node.childNodes[0].nodeValue;
|
|
164
|
-
} else if (node.nodeName ===
|
|
165
|
-
res =
|
|
166
|
+
} else if (node.nodeName === "string") {
|
|
167
|
+
let res = "";
|
|
166
168
|
if (isEmptyNode(node)) {
|
|
167
169
|
return res;
|
|
168
170
|
}
|
|
169
|
-
for (i=0; i < node.childNodes.length; i++) {
|
|
170
|
-
|
|
171
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
172
|
+
const type = node.childNodes[i].nodeType;
|
|
171
173
|
if (type === TEXT_NODE || type === CDATA_NODE) {
|
|
172
174
|
res += node.childNodes[i].nodeValue;
|
|
173
175
|
}
|
|
174
176
|
}
|
|
175
177
|
return res;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
invariant(
|
|
179
|
-
!isEmptyNode(node),
|
|
180
|
-
'Cannot parse "" as integer.'
|
|
181
|
-
);
|
|
178
|
+
} else if (node.nodeName === "integer") {
|
|
179
|
+
invariant(!isEmptyNode(node), 'Cannot parse "" as integer.');
|
|
182
180
|
return parseInt(node.childNodes[0].nodeValue, 10);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
'Cannot parse "" as real.'
|
|
188
|
-
);
|
|
189
|
-
res = '';
|
|
190
|
-
for (i=0; i < node.childNodes.length; i++) {
|
|
181
|
+
} else if (node.nodeName === "real") {
|
|
182
|
+
invariant(!isEmptyNode(node), 'Cannot parse "" as real.');
|
|
183
|
+
let res = "";
|
|
184
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
191
185
|
if (node.childNodes[i].nodeType === TEXT_NODE) {
|
|
192
186
|
res += node.childNodes[i].nodeValue;
|
|
193
187
|
}
|
|
194
188
|
}
|
|
195
189
|
return parseFloat(res);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
res = '';
|
|
190
|
+
} else if (node.nodeName === "data") {
|
|
191
|
+
let res = "";
|
|
199
192
|
if (isEmptyNode(node)) {
|
|
200
|
-
return
|
|
193
|
+
return base64ToUint8Array(res);
|
|
201
194
|
}
|
|
202
|
-
for (i=0; i < node.childNodes.length; i++) {
|
|
195
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
203
196
|
if (node.childNodes[i].nodeType === TEXT_NODE) {
|
|
204
|
-
res += node.childNodes[i].nodeValue.replace(/\s+/g,
|
|
197
|
+
res += node.childNodes[i].nodeValue.replace(/\s+/g, "");
|
|
205
198
|
}
|
|
206
199
|
}
|
|
207
|
-
return
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
invariant(
|
|
211
|
-
!isEmptyNode(node),
|
|
212
|
-
'Cannot parse "" as Date.'
|
|
213
|
-
)
|
|
200
|
+
return base64ToUint8Array(res);
|
|
201
|
+
} else if (node.nodeName === "date") {
|
|
202
|
+
invariant(!isEmptyNode(node), 'Cannot parse "" as Date.');
|
|
214
203
|
return new Date(node.childNodes[0].nodeValue);
|
|
215
|
-
|
|
216
|
-
} else if (node.nodeName === 'null') {
|
|
204
|
+
} else if (node.nodeName === "null") {
|
|
217
205
|
return null;
|
|
218
|
-
|
|
219
|
-
} else if (node.nodeName === 'true') {
|
|
206
|
+
} else if (node.nodeName === "true") {
|
|
220
207
|
return true;
|
|
221
|
-
|
|
222
|
-
} else if (node.nodeName === 'false') {
|
|
208
|
+
} else if (node.nodeName === "false") {
|
|
223
209
|
return false;
|
|
224
210
|
} else {
|
|
225
|
-
throw new Error(
|
|
211
|
+
throw new Error("Invalid PLIST tag " + node.nodeName);
|
|
226
212
|
}
|
|
227
213
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plist",
|
|
3
3
|
"description": "Apple's property list parser/builder for Node.js and browsers",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.0",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"author": "Nathan Rajlich <nathan@tootallnate.net>",
|
|
6
7
|
"contributors": [
|
|
7
8
|
"Hans Huebner <hans.huebner@gmail.com>",
|
|
@@ -23,22 +24,19 @@
|
|
|
23
24
|
"parser",
|
|
24
25
|
"xml"
|
|
25
26
|
],
|
|
26
|
-
"
|
|
27
|
+
"exports": "./index.js",
|
|
28
|
+
"files": [
|
|
29
|
+
"index.js",
|
|
30
|
+
"lib"
|
|
31
|
+
],
|
|
27
32
|
"dependencies": {
|
|
28
|
-
"@xmldom/xmldom": "^0.
|
|
29
|
-
"base64-js": "^1.5.1",
|
|
33
|
+
"@xmldom/xmldom": "^0.9.10",
|
|
30
34
|
"xmlbuilder": "^15.1.1"
|
|
31
35
|
},
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"browserify": "^17.0.0",
|
|
34
|
-
"mocha": "^9.2.2",
|
|
35
|
-
"multiline": "^2.0.0",
|
|
36
|
-
"zuul": "3.12.0"
|
|
37
|
-
},
|
|
38
36
|
"scripts": {
|
|
39
|
-
"test": "
|
|
37
|
+
"test": "node --test test/*.js"
|
|
40
38
|
},
|
|
41
39
|
"engines": {
|
|
42
|
-
"node": ">=
|
|
40
|
+
"node": ">=18"
|
|
43
41
|
}
|
|
44
42
|
}
|
package/.github/workflows/ci.yml
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
name: ci
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
pull_request:
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
build:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
|
|
11
|
-
strategy:
|
|
12
|
-
matrix:
|
|
13
|
-
node-version: [ '14', '16', '18' ]
|
|
14
|
-
|
|
15
|
-
steps:
|
|
16
|
-
- uses: actions/checkout@v2
|
|
17
|
-
|
|
18
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
19
|
-
uses: actions/setup-node@v1
|
|
20
|
-
with:
|
|
21
|
-
node-version: ${{ matrix.node-version }}
|
|
22
|
-
|
|
23
|
-
- run: npm install
|
|
24
|
-
- run: npm test
|
package/.jshintrc
DELETED