toon-formatter 2.0.1 → 2.2.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/CHANGELOG.md +39 -1
- package/README.md +211 -0
- package/bin/toon-formatter.js +3 -0
- package/package.json +17 -7
- package/src/cli.js +271 -0
- package/src/csv.js +19 -50
- package/src/csv_formatter/index.js +496 -0
- package/src/csv_formatter/validator.js +36 -0
- package/src/index.js +9 -1
- package/src/json.js +117 -67
- package/src/json_formatter/csv.js +145 -0
- package/src/json_formatter/index.js +525 -0
- package/src/json_formatter/validator.js +29 -0
- package/src/json_formatter/xml.js +206 -0
- package/src/json_formatter/yaml.js +81 -0
- package/src/utils.js +262 -64
- package/src/xml.js +24 -79
- package/src/xml_formatter/csv.js +122 -0
- package/src/xml_formatter/index.js +488 -0
- package/src/xml_formatter/validator.js +53 -0
- package/src/yaml_formatter/csv.js +101 -0
- package/src/yaml_formatter/index.js +542 -0
- package/src/yaml_formatter/validator.js +31 -0
- package/src/yaml_formatter/xml.js +116 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSV <-> XML Converter (for XmlConverter)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { extractCsvFromString, extractJsonFromString, extractXmlFromString } from '../utils.js';
|
|
6
|
+
import { csvToJsonSync, jsonToCsvSync } from '../json_formatter/csv.js';
|
|
7
|
+
import { jsonToXmlSync, xmlToJsonSync } from '../json_formatter/xml.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Convert CSV string to XML string (Sync)
|
|
11
|
+
* Supports mixed text CSV.
|
|
12
|
+
* @param {string} csvString
|
|
13
|
+
* @returns {string} XML string
|
|
14
|
+
*/
|
|
15
|
+
export function csvToXmlSync(csvString) {
|
|
16
|
+
if (!csvString || typeof csvString !== 'string') {
|
|
17
|
+
throw new Error('Input must be a non-empty string');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let convertedText = csvString;
|
|
21
|
+
let iterationCount = 0;
|
|
22
|
+
const maxIterations = 100;
|
|
23
|
+
let wasModified = false;
|
|
24
|
+
|
|
25
|
+
// Check pure CSV
|
|
26
|
+
const firstExtract = extractCsvFromString(csvString);
|
|
27
|
+
if (firstExtract === csvString.trim()) {
|
|
28
|
+
const json = csvToJsonSync(csvString);
|
|
29
|
+
return jsonToXmlSync(json);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Mixed Loop
|
|
33
|
+
while (iterationCount < maxIterations) {
|
|
34
|
+
const csvBlock = extractCsvFromString(convertedText);
|
|
35
|
+
if (!csvBlock) break;
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const jsonObject = csvToJsonSync(csvBlock);
|
|
39
|
+
const xmlOutput = jsonToXmlSync(jsonObject);
|
|
40
|
+
convertedText = convertedText.replace(csvBlock, xmlOutput);
|
|
41
|
+
wasModified = true;
|
|
42
|
+
iterationCount++;
|
|
43
|
+
} catch (e) {
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (wasModified) return convertedText;
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const json = csvToJsonSync(csvString);
|
|
52
|
+
return jsonToXmlSync(json);
|
|
53
|
+
} catch (e) {
|
|
54
|
+
return csvString;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Convert CSV string to XML string (Async)
|
|
60
|
+
* @param {string} csvString
|
|
61
|
+
* @returns {Promise<string>} XML string
|
|
62
|
+
*/
|
|
63
|
+
export async function csvToXml(csvString) {
|
|
64
|
+
return csvToXmlSync(csvString);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Convert XML string to CSV string (Sync)
|
|
69
|
+
* Supports mixed text XML.
|
|
70
|
+
* @param {string} xmlString
|
|
71
|
+
* @returns {string} CSV string
|
|
72
|
+
*/
|
|
73
|
+
export function xmlToCsvSync(xmlString) {
|
|
74
|
+
if (!xmlString || typeof xmlString !== 'string') {
|
|
75
|
+
throw new Error('Input must be a non-empty string');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let convertedText = xmlString;
|
|
79
|
+
let iterationCount = 0;
|
|
80
|
+
const maxIterations = 100;
|
|
81
|
+
let wasModified = false;
|
|
82
|
+
|
|
83
|
+
// Check pure XML
|
|
84
|
+
const firstExtract = extractXmlFromString(xmlString);
|
|
85
|
+
if (firstExtract === xmlString.trim()) {
|
|
86
|
+
const json = xmlToJsonSync(xmlString);
|
|
87
|
+
return jsonToCsvSync(json);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
while (iterationCount < maxIterations) {
|
|
91
|
+
const xmlBlock = extractXmlFromString(convertedText);
|
|
92
|
+
if (!xmlBlock) break;
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const jsonObject = xmlToJsonSync(xmlBlock);
|
|
96
|
+
const csvOutput = jsonToCsvSync(jsonObject);
|
|
97
|
+
convertedText = convertedText.replace(xmlBlock, csvOutput);
|
|
98
|
+
wasModified = true;
|
|
99
|
+
iterationCount++;
|
|
100
|
+
} catch (e) {
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (wasModified) return convertedText;
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const json = xmlToJsonSync(xmlString);
|
|
109
|
+
return jsonToCsvSync(json);
|
|
110
|
+
} catch (e) {
|
|
111
|
+
return xmlString;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Convert XML string to CSV string (Async)
|
|
117
|
+
* @param {string} xmlString
|
|
118
|
+
* @returns {Promise<string>} CSV string
|
|
119
|
+
*/
|
|
120
|
+
export async function xmlToCsv(xmlString) {
|
|
121
|
+
return xmlToCsvSync(xmlString);
|
|
122
|
+
}
|
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XmlConverter Class
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { toonToXml, toonToXmlSync, xmlToToon, xmlToToonSync } from '../xml.js';
|
|
6
|
+
import { jsonToXml, jsonToXmlSync, xmlToJson, xmlToJsonSync } from '../json_formatter/xml.js';
|
|
7
|
+
import { yamlToXml, yamlToXmlSync, xmlToYaml, xmlToYamlSync } from '../yaml_formatter/xml.js';
|
|
8
|
+
import { csvToXml, csvToXmlSync, xmlToCsv, xmlToCsvSync } from './csv.js';
|
|
9
|
+
import { validateXmlString, validateXmlStringSync } from './validator.js';
|
|
10
|
+
|
|
11
|
+
export class XmlConverter {
|
|
12
|
+
/**
|
|
13
|
+
* Creates an XmlConverter instance
|
|
14
|
+
* @param {Object} [encryptor=null] - Optional Encryptor instance for encryption support
|
|
15
|
+
*/
|
|
16
|
+
constructor(encryptor = null) {
|
|
17
|
+
this.encryptor = encryptor;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// --- Helper Methods for Encryption ---
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Applies encryption logic based on conversion mode (synchronous)
|
|
24
|
+
* @private
|
|
25
|
+
* @param {Function} fn - The converter function to call
|
|
26
|
+
* @param {*} data - Data to convert
|
|
27
|
+
* @param {string} mode - Conversion mode: 'no_encryption', 'middleware', 'ingestion', 'export'
|
|
28
|
+
* @returns {*} Converted (and possibly encrypted) data
|
|
29
|
+
*/
|
|
30
|
+
_convertWithEncryption(fn, data, mode) {
|
|
31
|
+
if (!this.encryptor || mode === 'no_encryption') {
|
|
32
|
+
return fn(data);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
switch (mode) {
|
|
36
|
+
case 'middleware':
|
|
37
|
+
const decrypted = this.encryptor.decrypt(data);
|
|
38
|
+
const result = fn(decrypted);
|
|
39
|
+
return this.encryptor.encrypt(result);
|
|
40
|
+
case 'ingestion':
|
|
41
|
+
const dec = this.encryptor.decrypt(data);
|
|
42
|
+
return fn(dec);
|
|
43
|
+
case 'export':
|
|
44
|
+
const res = fn(data);
|
|
45
|
+
return this.encryptor.encrypt(res);
|
|
46
|
+
default:
|
|
47
|
+
return fn(data);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async _convertWithEncryptionAsync(fn, data, mode) {
|
|
52
|
+
if (!this.encryptor || mode === 'no_encryption') {
|
|
53
|
+
return await fn(data);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
switch (mode) {
|
|
57
|
+
case 'middleware':
|
|
58
|
+
const decrypted = this.encryptor.decrypt(data);
|
|
59
|
+
const result = await fn(decrypted);
|
|
60
|
+
return this.encryptor.encrypt(result);
|
|
61
|
+
case 'ingestion':
|
|
62
|
+
const dec = this.encryptor.decrypt(data);
|
|
63
|
+
return await fn(dec);
|
|
64
|
+
case 'export':
|
|
65
|
+
const res = await fn(data);
|
|
66
|
+
return this.encryptor.encrypt(res);
|
|
67
|
+
default:
|
|
68
|
+
return await fn(data);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// --- TOON Conversions ---
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Convert TOON string to XML (Sync)
|
|
76
|
+
* @param {string} toonString - TOON formatted string
|
|
77
|
+
* @param {Object} [options={}] - Conversion options
|
|
78
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
79
|
+
* @returns {string} XML formatted string
|
|
80
|
+
*/
|
|
81
|
+
fromToon(toonString, options = {}) {
|
|
82
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
83
|
+
return this._convertWithEncryption(
|
|
84
|
+
(data) => toonToXmlSync(data),
|
|
85
|
+
toonString,
|
|
86
|
+
conversionMode
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Convert TOON string to XML (Async)
|
|
92
|
+
* @param {string} toonString - TOON formatted string
|
|
93
|
+
* @param {Object} [options={}] - Conversion options
|
|
94
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
95
|
+
* @returns {Promise<string>} XML formatted string
|
|
96
|
+
*/
|
|
97
|
+
async fromToonAsync(toonString, options = {}) {
|
|
98
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
99
|
+
return this._convertWithEncryptionAsync(
|
|
100
|
+
async (data) => toonToXml(data),
|
|
101
|
+
toonString,
|
|
102
|
+
conversionMode
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Convert XML to TOON string (Sync)
|
|
108
|
+
* @param {string} xmlString - XML formatted string (supports mixed text)
|
|
109
|
+
* @param {Object} [options={}] - Conversion options
|
|
110
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
111
|
+
* @returns {string} TOON formatted string
|
|
112
|
+
*/
|
|
113
|
+
toToon(xmlString, options = {}) {
|
|
114
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
115
|
+
return this._convertWithEncryption(
|
|
116
|
+
(data) => xmlToToonSync(data),
|
|
117
|
+
xmlString,
|
|
118
|
+
conversionMode
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Convert XML to TOON string (Async)
|
|
124
|
+
* @param {string} xmlString - XML formatted string (supports mixed text)
|
|
125
|
+
* @param {Object} [options={}] - Conversion options
|
|
126
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
127
|
+
* @returns {Promise<string>} TOON formatted string
|
|
128
|
+
*/
|
|
129
|
+
async toToonAsync(xmlString, options = {}) {
|
|
130
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
131
|
+
return this._convertWithEncryptionAsync(
|
|
132
|
+
async (data) => xmlToToon(data),
|
|
133
|
+
xmlString,
|
|
134
|
+
conversionMode
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// --- JSON Conversions ---
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Convert JSON to XML (Sync)
|
|
142
|
+
* @param {Object|string} jsonData - JSON data or string with embedded JSON
|
|
143
|
+
* @param {Object} [options={}] - Conversion options
|
|
144
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
145
|
+
* @returns {string} XML formatted string
|
|
146
|
+
*/
|
|
147
|
+
fromJson(jsonData, options = {}) {
|
|
148
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
149
|
+
return this._convertWithEncryption(
|
|
150
|
+
(data) => jsonToXmlSync(data),
|
|
151
|
+
jsonData,
|
|
152
|
+
conversionMode
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Convert JSON to XML (Async)
|
|
158
|
+
* @param {Object|string} jsonData - JSON data or string with embedded JSON
|
|
159
|
+
* @param {Object} [options={}] - Conversion options
|
|
160
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
161
|
+
* @returns {Promise<string>} XML formatted string
|
|
162
|
+
*/
|
|
163
|
+
async fromJsonAsync(jsonData, options = {}) {
|
|
164
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
165
|
+
return this._convertWithEncryptionAsync(
|
|
166
|
+
async (data) => jsonToXml(data),
|
|
167
|
+
jsonData,
|
|
168
|
+
conversionMode
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Convert XML to JSON (Sync)
|
|
174
|
+
* @param {string} xmlString - XML formatted string (supports mixed text)
|
|
175
|
+
* @param {Object} [options={}] - Conversion options
|
|
176
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
177
|
+
* @returns {Object|string} JSON result
|
|
178
|
+
*/
|
|
179
|
+
toJson(xmlString, options = {}) {
|
|
180
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
181
|
+
return this._convertWithEncryption(
|
|
182
|
+
(data) => xmlToJsonSync(data),
|
|
183
|
+
xmlString,
|
|
184
|
+
conversionMode
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Convert XML to JSON (Async)
|
|
190
|
+
* @param {string} xmlString - XML formatted string (supports mixed text)
|
|
191
|
+
* @param {Object} [options={}] - Conversion options
|
|
192
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
193
|
+
* @returns {Promise<Object|string>} JSON result
|
|
194
|
+
*/
|
|
195
|
+
async toJsonAsync(xmlString, options = {}) {
|
|
196
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
197
|
+
return this._convertWithEncryptionAsync(
|
|
198
|
+
async (data) => xmlToJson(data),
|
|
199
|
+
xmlString,
|
|
200
|
+
conversionMode
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// --- YAML Conversions ---
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Convert YAML to XML (Sync)
|
|
208
|
+
* @param {string} yamlString - YAML formatted string
|
|
209
|
+
* @param {Object} [options={}] - Conversion options
|
|
210
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
211
|
+
* @returns {string} XML formatted string
|
|
212
|
+
*/
|
|
213
|
+
fromYaml(yamlString, options = {}) {
|
|
214
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
215
|
+
return this._convertWithEncryption(
|
|
216
|
+
(data) => yamlToXmlSync(data),
|
|
217
|
+
yamlString,
|
|
218
|
+
conversionMode
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async fromYamlAsync(yamlString, options = {}) {
|
|
223
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
224
|
+
return this._convertWithEncryptionAsync(
|
|
225
|
+
async (data) => yamlToXml(data),
|
|
226
|
+
yamlString,
|
|
227
|
+
conversionMode
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Convert XML to YAML (Sync)
|
|
233
|
+
* @param {string} xmlString - XML formatted string (supports mixed text)
|
|
234
|
+
* @param {Object} [options={}] - Conversion options
|
|
235
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
236
|
+
* @returns {string} YAML formatted string
|
|
237
|
+
*/
|
|
238
|
+
toYaml(xmlString, options = {}) {
|
|
239
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
240
|
+
return this._convertWithEncryption(
|
|
241
|
+
(data) => xmlToYamlSync(data),
|
|
242
|
+
xmlString,
|
|
243
|
+
conversionMode
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async toYamlAsync(xmlString, options = {}) {
|
|
248
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
249
|
+
return this._convertWithEncryptionAsync(
|
|
250
|
+
async (data) => xmlToYaml(data),
|
|
251
|
+
xmlString,
|
|
252
|
+
conversionMode
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// --- CSV Conversions ---
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Convert CSV to XML (Sync)
|
|
260
|
+
* @param {string} csvString - CSV formatted string (supports mixed text)
|
|
261
|
+
* @param {Object} [options={}] - Conversion options
|
|
262
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
263
|
+
* @returns {string} XML formatted string
|
|
264
|
+
*/
|
|
265
|
+
fromCsv(csvString, options = {}) {
|
|
266
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
267
|
+
return this._convertWithEncryption(
|
|
268
|
+
(data) => csvToXmlSync(data),
|
|
269
|
+
csvString,
|
|
270
|
+
conversionMode
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async fromCsvAsync(csvString, options = {}) {
|
|
275
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
276
|
+
return this._convertWithEncryptionAsync(
|
|
277
|
+
async (data) => csvToXml(data),
|
|
278
|
+
csvString,
|
|
279
|
+
conversionMode
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Convert XML to CSV (Sync)
|
|
285
|
+
* @param {string} xmlString - XML formatted string (supports mixed text)
|
|
286
|
+
* @param {Object} [options={}] - Conversion options
|
|
287
|
+
* @param {string} [options.conversionMode='no_encryption'] - Encryption mode
|
|
288
|
+
* @returns {string} CSV formatted string
|
|
289
|
+
*/
|
|
290
|
+
toCsv(xmlString, options = {}) {
|
|
291
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
292
|
+
return this._convertWithEncryption(
|
|
293
|
+
(data) => xmlToCsvSync(data),
|
|
294
|
+
xmlString,
|
|
295
|
+
conversionMode
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async toCsvAsync(xmlString, options = {}) {
|
|
300
|
+
const { conversionMode = 'no_encryption' } = options;
|
|
301
|
+
return this._convertWithEncryptionAsync(
|
|
302
|
+
async (data) => xmlToCsv(data),
|
|
303
|
+
xmlString,
|
|
304
|
+
conversionMode
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// --- Validation ---
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Validate XML string (Sync)
|
|
312
|
+
* @param {string} xmlString - XML string to validate
|
|
313
|
+
* @returns {boolean} True if valid
|
|
314
|
+
*/
|
|
315
|
+
validate(xmlString) {
|
|
316
|
+
return validateXmlStringSync(xmlString);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async validateAsync(xmlString) {
|
|
320
|
+
return validateXmlString(xmlString);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// ========================================
|
|
324
|
+
// Static Methods (Backward Compatibility)
|
|
325
|
+
// ========================================
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Convert TOON string to XML (Sync)
|
|
329
|
+
* @param {string} toonString - TOON formatted string
|
|
330
|
+
* @returns {string} XML formatted string
|
|
331
|
+
*/
|
|
332
|
+
static fromToon(toonString) {
|
|
333
|
+
return toonToXmlSync(toonString);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Convert TOON string to XML (Async)
|
|
338
|
+
* @param {string} toonString - TOON formatted string
|
|
339
|
+
* @returns {Promise<string>} XML formatted string
|
|
340
|
+
*/
|
|
341
|
+
static async fromToonAsync(toonString) {
|
|
342
|
+
return toonToXml(toonString);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Convert XML to TOON string (Sync)
|
|
347
|
+
* @param {string} xmlString - XML formatted string
|
|
348
|
+
* @returns {string} TOON formatted string
|
|
349
|
+
*/
|
|
350
|
+
static toToon(xmlString) {
|
|
351
|
+
return xmlToToonSync(xmlString);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Convert XML to TOON string (Async)
|
|
356
|
+
* @param {string} xmlString - XML formatted string
|
|
357
|
+
* @returns {Promise<string>} TOON formatted string
|
|
358
|
+
*/
|
|
359
|
+
static async toToonAsync(xmlString) {
|
|
360
|
+
return xmlToToon(xmlString);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Convert JSON to XML string (Sync)
|
|
365
|
+
* @param {Object|string} jsonData - JSON data or string with embedded JSON
|
|
366
|
+
* @returns {string} XML formatted string
|
|
367
|
+
*/
|
|
368
|
+
static fromJson(jsonData) {
|
|
369
|
+
return jsonToXmlSync(jsonData);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Convert JSON to XML string (Async)
|
|
374
|
+
* @param {Object|string} jsonData - JSON data or string with embedded JSON
|
|
375
|
+
* @returns {Promise<string>} XML formatted string
|
|
376
|
+
*/
|
|
377
|
+
static async fromJsonAsync(jsonData) {
|
|
378
|
+
return jsonToXml(jsonData);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Convert XML to JSON (Sync)
|
|
383
|
+
* @param {string} xmlString - XML formatted string
|
|
384
|
+
* @returns {Object|string} JSON result
|
|
385
|
+
*/
|
|
386
|
+
static toJson(xmlString) {
|
|
387
|
+
return xmlToJsonSync(xmlString);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Convert XML to JSON (Async)
|
|
392
|
+
* @param {string} xmlString - XML formatted string
|
|
393
|
+
* @returns {Promise<Object|string>} JSON result
|
|
394
|
+
*/
|
|
395
|
+
static async toJsonAsync(xmlString) {
|
|
396
|
+
return xmlToJson(xmlString);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Convert YAML to XML string (Sync)
|
|
401
|
+
* @param {string} yamlString - YAML formatted string
|
|
402
|
+
* @returns {string} XML formatted string
|
|
403
|
+
*/
|
|
404
|
+
static fromYaml(yamlString) {
|
|
405
|
+
return yamlToXmlSync(yamlString);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Convert YAML to XML string (Async)
|
|
410
|
+
* @param {string} yamlString - YAML formatted string
|
|
411
|
+
* @returns {Promise<string>} XML formatted string
|
|
412
|
+
*/
|
|
413
|
+
static async fromYamlAsync(yamlString) {
|
|
414
|
+
return yamlToXml(yamlString);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Convert XML to YAML string (Sync)
|
|
419
|
+
* @param {string} xmlString - XML formatted string
|
|
420
|
+
* @returns {string} YAML formatted string
|
|
421
|
+
*/
|
|
422
|
+
static toYaml(xmlString) {
|
|
423
|
+
return xmlToYamlSync(xmlString);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Convert XML to YAML string (Async)
|
|
428
|
+
* @param {string} xmlString - XML formatted string
|
|
429
|
+
* @returns {Promise<string>} YAML formatted string
|
|
430
|
+
*/
|
|
431
|
+
static async toYamlAsync(xmlString) {
|
|
432
|
+
return xmlToYaml(xmlString);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Convert CSV to XML string (Sync)
|
|
437
|
+
* @param {string} csvString - CSV formatted string
|
|
438
|
+
* @returns {string} XML formatted string
|
|
439
|
+
*/
|
|
440
|
+
static fromCsv(csvString) {
|
|
441
|
+
return csvToXmlSync(csvString);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Convert CSV to XML string (Async)
|
|
446
|
+
* @param {string} csvString - CSV formatted string
|
|
447
|
+
* @returns {Promise<string>} XML formatted string
|
|
448
|
+
*/
|
|
449
|
+
static async fromCsvAsync(csvString) {
|
|
450
|
+
return csvToXml(csvString);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Convert XML to CSV string (Sync)
|
|
455
|
+
* @param {string} xmlString - XML formatted string
|
|
456
|
+
* @returns {string} CSV formatted string
|
|
457
|
+
*/
|
|
458
|
+
static toCsv(xmlString) {
|
|
459
|
+
return xmlToCsvSync(xmlString);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Convert XML to CSV string (Async)
|
|
464
|
+
* @param {string} xmlString - XML formatted string
|
|
465
|
+
* @returns {Promise<string>} CSV formatted string
|
|
466
|
+
*/
|
|
467
|
+
static async toCsvAsync(xmlString) {
|
|
468
|
+
return xmlToCsv(xmlString);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Validate XML string
|
|
473
|
+
* @param {string} xmlString - XML string to validate
|
|
474
|
+
* @returns {boolean} True if valid
|
|
475
|
+
*/
|
|
476
|
+
static validate(xmlString) {
|
|
477
|
+
return validateXmlStringSync(xmlString);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Validate XML string (Async)
|
|
482
|
+
* @param {string} xmlString - XML string to validate
|
|
483
|
+
* @returns {Promise<boolean>} True if valid
|
|
484
|
+
*/
|
|
485
|
+
static async validateAsync(xmlString) {
|
|
486
|
+
return validateXmlString(xmlString);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XML Validator (for XmlConverter)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { encodeXmlReservedChars } from '../utils.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Validate XML string (Sync)
|
|
9
|
+
* @param {string} xmlString
|
|
10
|
+
* @returns {boolean} True if valid, throws error if invalid
|
|
11
|
+
*/
|
|
12
|
+
export function validateXmlStringSync(xmlString) {
|
|
13
|
+
if (typeof xmlString !== 'string') {
|
|
14
|
+
throw new Error("Input must be a string.");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let Parser;
|
|
18
|
+
if (typeof DOMParser !== 'undefined') {
|
|
19
|
+
Parser = DOMParser;
|
|
20
|
+
} else {
|
|
21
|
+
throw new Error('DOMParser is not available for validation.');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const parser = new Parser();
|
|
25
|
+
const xmlDoc = parser.parseFromString(
|
|
26
|
+
encodeXmlReservedChars(xmlString),
|
|
27
|
+
'application/xml'
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const parserError = xmlDoc.querySelector ? xmlDoc.querySelector('parsererror') :
|
|
31
|
+
(xmlDoc.documentElement && xmlDoc.documentElement.nodeName === 'parsererror' ? xmlDoc.documentElement : null);
|
|
32
|
+
|
|
33
|
+
if (parserError) {
|
|
34
|
+
throw new Error(`Invalid XML: ${parserError.textContent}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Validate XML string (Async)
|
|
42
|
+
* @param {string} xmlString
|
|
43
|
+
* @returns {Promise<boolean>} True if valid
|
|
44
|
+
*/
|
|
45
|
+
export async function validateXmlString(xmlString) {
|
|
46
|
+
if (typeof DOMParser === 'undefined') {
|
|
47
|
+
try {
|
|
48
|
+
const { DOMParser: NodeDOMParser } = await import('xmldom');
|
|
49
|
+
global.DOMParser = NodeDOMParser;
|
|
50
|
+
} catch (e) { }
|
|
51
|
+
}
|
|
52
|
+
return validateXmlStringSync(xmlString);
|
|
53
|
+
}
|