UNPKG

3.35 kBJavaScriptView Raw
1import { INDENT_ROOT, NEWLINE_STRING } from "./options.mjs";
2import { xmlDecode, xmlElementChildElements } from "./util.mjs";
3import { ValueDict } from "./value/dict.mjs";
4const xmlDeclaration = '<?xml version="1.0" encoding="UTF-8"?>';
5const xmlDoctype = '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">';
6
7/**
8 * Plist object.
9 */
10export class Plist {
11 /**
12 * Default XML declaration.
13 */
14 static XML_DECLARATION = xmlDeclaration;
15
16 /**
17 * Default XML doctype.
18 */
19 static XML_DOCTYPE = xmlDoctype;
20
21 /**
22 * XML declaration.
23 */
24 xmlDeclaration = xmlDeclaration;
25
26 /**
27 * XML doctype.
28 */
29 xmlDoctype = xmlDoctype;
30
31 /**
32 * Value element.
33 */
34 value = null;
35
36 /**
37 * Plist constructor.
38 *
39 * @param value The value.
40 */
41 constructor(value = null) {
42 this.value = value;
43 }
44
45 /**
46 * Get value or throw if null.
47 *
48 * @returns The value.
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 * Cast to specific type or null.
62 *
63 * @param Type Type constructor.
64 * @returns The object or null.
65 */
66 valueCastTo(Type) {
67 const {
68 value
69 } = this;
70 return value ? value.castTo(Type) : null;
71 }
72
73 /**
74 * Cast to specific type or throw.
75 *
76 * @param Type Type constructor.
77 * @returns The object.
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 * Decode document from string.
89 *
90 * @param xml XML string.
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 * Decode document from element.
103 *
104 * @param element XML element.
105 * @param declaration XML declaration.
106 * @param doctype XML doctype.
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 * Decode child element from XML element.
127 *
128 * @param element XML element.
129 * @returns Value element.
130 */
131 childFromXmlElement(element) {
132 const a = new ValueDict();
133 return a.childFromXmlElement(element);
134 }
135
136 /**
137 * Encode documents to string.
138 *
139 * @param options Options object.
140 * @returns XML string.
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//# sourceMappingURL=plist.mjs.map
\No newline at end of file