1 | import { INDENT_ROOT, NEWLINE_STRING } from "./options.mjs";
|
2 | import { xmlDecode, xmlElementChildElements } from "./util.mjs";
|
3 | import { ValueDict } from "./value/dict.mjs";
|
4 | const xmlDeclaration = '<?xml version="1.0" encoding="UTF-8"?>';
|
5 | const xmlDoctype = '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">';
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | export class Plist {
|
11 | |
12 |
|
13 |
|
14 | static XML_DECLARATION = xmlDeclaration;
|
15 |
|
16 | |
17 |
|
18 |
|
19 | static XML_DOCTYPE = xmlDoctype;
|
20 |
|
21 | |
22 |
|
23 |
|
24 | xmlDeclaration = xmlDeclaration;
|
25 |
|
26 | |
27 |
|
28 |
|
29 | xmlDoctype = xmlDoctype;
|
30 |
|
31 | |
32 |
|
33 |
|
34 | value = null;
|
35 |
|
36 | |
37 |
|
38 |
|
39 |
|
40 |
|
41 | constructor(value = null) {
|
42 | this.value = value;
|
43 | }
|
44 |
|
45 | |
46 |
|
47 |
|
48 |
|
49 |
|
50 | getValue() {
|
51 | const {
|
52 | value
|
53 | } = this;
|
54 | if (!value) {
|
55 | throw new Error('Value is null');
|
56 | }
|
57 | return value;
|
58 | }
|
59 |
|
60 | |
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 | valueCastTo(Type) {
|
67 | const {
|
68 | value
|
69 | } = this;
|
70 | return value ? value.castTo(Type) : null;
|
71 | }
|
72 |
|
73 | |
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 | valueCastAs(Type) {
|
80 | const casted = this.valueCastTo(Type);
|
81 | if (!casted) {
|
82 | throw new Error(`Cannot cast value to type '${Type.TYPE}'`);
|
83 | }
|
84 | return casted;
|
85 | }
|
86 |
|
87 | |
88 |
|
89 |
|
90 |
|
91 |
|
92 | fromXml(xml) {
|
93 | const {
|
94 | declaration,
|
95 | doctype,
|
96 | documentElement
|
97 | } = xmlDecode(xml);
|
98 | this.fromXmlElement(documentElement, declaration, doctype);
|
99 | }
|
100 |
|
101 | |
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 | fromXmlElement(element, declaration = null, doctype = null) {
|
109 | const {
|
110 | tagName
|
111 | } = element;
|
112 | if (tagName !== 'plist') {
|
113 | throw new Error(`Unexpected root plist tag name: ${tagName}`);
|
114 | }
|
115 | const childElements = xmlElementChildElements(element);
|
116 | const childElementsL = childElements.length;
|
117 | if (childElementsL > 1) {
|
118 | throw new Error(`Multiple root plist child tag: ${childElementsL}`);
|
119 | }
|
120 | this.value = childElementsL ? this.childFromXmlElement(childElements[0]) : null;
|
121 | this.xmlDeclaration = declaration || '';
|
122 | this.xmlDoctype = doctype || '';
|
123 | }
|
124 |
|
125 | |
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 | childFromXmlElement(element) {
|
132 | const a = new ValueDict();
|
133 | return a.childFromXmlElement(element);
|
134 | }
|
135 |
|
136 | |
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 | toXml(options = null) {
|
143 | const ir = options?.indentRoot ?? INDENT_ROOT;
|
144 | const n = options?.newlineString ?? NEWLINE_STRING;
|
145 | const v = this.value;
|
146 | return [...[this.xmlDeclaration, this.xmlDoctype].filter(s => s), '<plist version="1.0">', ...(v ? [v.toXml(options, ir ? 1 : 0)] : []), '</plist>', ''].join(n);
|
147 | }
|
148 | }
|
149 |
|
\ | No newline at end of file |