toon-formatter 1.1.1 → 2.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/CHANGELOG.md +95 -0
- package/README.md +538 -6
- package/package.json +11 -4
- package/src/encryptor.js +244 -0
- package/src/index.js +350 -10
- package/src/json.js +9 -7
- package/.github/FUNDING.yml +0 -15
- package/ENHANCEMENTS.md +0 -124
- package/test/basic.test.js +0 -139
- package/test/converters.test.js +0 -135
package/src/json.js
CHANGED
|
@@ -120,10 +120,11 @@ export async function jsonToToon(data) {
|
|
|
120
120
|
/**
|
|
121
121
|
* Converts TOON to JSON format (Synchronous)
|
|
122
122
|
* @param {string} toonString - TOON formatted string
|
|
123
|
-
* @
|
|
123
|
+
* @param {boolean} [returnJson=false] - If true, returns JSON string; if false, returns object
|
|
124
|
+
* @returns {Object|string} JSON object or JSON string
|
|
124
125
|
* @throws {Error} If TOON string is invalid
|
|
125
126
|
*/
|
|
126
|
-
export function toonToJsonSync(toonString) {
|
|
127
|
+
export function toonToJsonSync(toonString, returnJson = false) {
|
|
127
128
|
// Validate TOON string before conversion
|
|
128
129
|
const validationStatus = validateToonStringSync(toonString);
|
|
129
130
|
if (!validationStatus.isValid) {
|
|
@@ -136,7 +137,7 @@ export function toonToJsonSync(toonString) {
|
|
|
136
137
|
|
|
137
138
|
// Pre-process: Check for Root Array or Root Primitive
|
|
138
139
|
const firstLine = lines.find(l => l.trim() !== '');
|
|
139
|
-
if (!firstLine) return {}; // Empty document
|
|
140
|
+
if (!firstLine) return returnJson ? '{}' : {}; // Empty document
|
|
140
141
|
|
|
141
142
|
// Root Array detection: [N]... at start of line
|
|
142
143
|
if (firstLine.trim().startsWith('[')) {
|
|
@@ -324,14 +325,15 @@ export function toonToJsonSync(toonString) {
|
|
|
324
325
|
}
|
|
325
326
|
}
|
|
326
327
|
|
|
327
|
-
return root;
|
|
328
|
+
return returnJson ? JSON.stringify(root) : root;
|
|
328
329
|
}
|
|
329
330
|
|
|
330
331
|
/**
|
|
331
332
|
* Converts TOON to JSON format (Async)
|
|
332
333
|
* @param {string} toonString - TOON formatted string
|
|
333
|
-
* @
|
|
334
|
+
* @param {boolean} [returnJson=false] - If true, returns JSON string; if false, returns object
|
|
335
|
+
* @returns {Promise<Object|string>} Parsed JSON data (object or string)
|
|
334
336
|
*/
|
|
335
|
-
export async function toonToJson(toonString) {
|
|
336
|
-
return toonToJsonSync(toonString);
|
|
337
|
+
export async function toonToJson(toonString, returnJson = false) {
|
|
338
|
+
return toonToJsonSync(toonString, returnJson);
|
|
337
339
|
}
|
package/.github/FUNDING.yml
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# These are supported funding model platforms
|
|
2
|
-
|
|
3
|
-
github: [ankitpal181] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
|
4
|
-
# patreon: # Replace with a single Patreon username
|
|
5
|
-
# open_collective: # Replace with a single Open Collective username
|
|
6
|
-
# ko_fi: # Replace with a single Ko-fi username
|
|
7
|
-
# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
8
|
-
# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
9
|
-
# liberapay: # Replace with a single Liberapay username
|
|
10
|
-
# issuehunt: # Replace with a single IssueHunt username
|
|
11
|
-
# lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
|
12
|
-
# polar: # Replace with a single Polar username
|
|
13
|
-
# buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
|
14
|
-
# thanks_dev: # Replace with a single thanks.dev username
|
|
15
|
-
# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
package/ENHANCEMENTS.md
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
# TOON Converter Library - Enhancement Summary
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
Updated the `toon-converter-lib` package with improved validators, mixed text extraction capabilities, validation checks on reverse conversions, and loop-based conversion for embedded formats.
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## ✨ New Features Added
|
|
9
|
-
|
|
10
|
-
### 1. **Enhanced Validator** (`src/validator.js`)
|
|
11
|
-
- **Empty Block Detection**: Validates that arrays with size > 0 have actual items
|
|
12
|
-
- **Tabular Array Support**: Properly handles tabular arrays with `{field1,field2}` syntax
|
|
13
|
-
- **List Item Context Checking**: Ensures `-` items only appear in array contexts
|
|
14
|
-
- **Better Error Messages**: Line numbers and specific error descriptions
|
|
15
|
-
|
|
16
|
-
**Example Error**:
|
|
17
|
-
```
|
|
18
|
-
L5: Array declared with size 3 but has no items (expected indented block).
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
### 2. **Format Extraction Functions** (`src/utils.js`)
|
|
24
|
-
Added utilities to extract specific formats from mixed text:
|
|
25
|
-
|
|
26
|
-
- `extractJsonFromString(text)` - Finds and extracts JSON objects/arrays
|
|
27
|
-
- `extractYamlFromString(text)` - Extracts YAML blocks
|
|
28
|
-
- `extractXmlFromString(text)` - Extracts XML elements with balance checking
|
|
29
|
-
- `extractCsvFromString(text)` - Identifies CSV data
|
|
30
|
-
|
|
31
|
-
**Use Case**: Allows conversion of mixed content (e.g., JSON embedded in markdown).
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
### 3. **Integrated Mixed Text Conversion**
|
|
36
|
-
The conversion functions now automatically detect and handle mixed text input using an extraction loop. This logic covers both embedded data and full data strings.
|
|
37
|
-
|
|
38
|
-
**Synchronous API (Main Logic)**:
|
|
39
|
-
- `jsonToToonSync(input)`
|
|
40
|
-
- `xmlToToonSync(input)`
|
|
41
|
-
- `csvToToonSync(input)`
|
|
42
|
-
- `yamlToToonSync(input)`
|
|
43
|
-
|
|
44
|
-
**Asynchronous API (Wrappers)**:
|
|
45
|
-
- `jsonToToon(input)`
|
|
46
|
-
- `xmlToToon(input)`
|
|
47
|
-
- `csvToToon(input)`
|
|
48
|
-
- `yamlToToon(input)`
|
|
49
|
-
|
|
50
|
-
**Behavior**:
|
|
51
|
-
1. Checks if input is a string.
|
|
52
|
-
2. Uses extraction logic (`extract*FromString`) in a loop to find and convert all data blocks.
|
|
53
|
-
3. If no blocks are found (and input is not valid data), it returns the original text (or throws if strict parsing fails inside the loop).
|
|
54
|
-
|
|
55
|
-
**Note**: `*TextToToon` functions have been removed in favor of this integrated approach.
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
### 4. **Validation on Reverse Conversions**
|
|
62
|
-
All `toonTo*` functions now validate TOON input before conversion:
|
|
63
|
-
|
|
64
|
-
- `toonToJson()` - Validates before parsing
|
|
65
|
-
- `toonToYaml()` - Validates before conversion
|
|
66
|
-
- `toonToXml()` - Validates before conversion
|
|
67
|
-
- `toonToCsv()` - Validates before conversion
|
|
68
|
-
|
|
69
|
-
**Benefits**:
|
|
70
|
-
- Early error detection
|
|
71
|
-
- Clear error messages
|
|
72
|
-
- Prevents invalid conversions
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
### 6. **API Consistency (Sync & Async)**
|
|
77
|
-
All converters now support both Synchronous and Asynchronous operations for consistency.
|
|
78
|
-
|
|
79
|
-
| Format | Sync Method | Async Method |
|
|
80
|
-
|--------|-------------|--------------|
|
|
81
|
-
| **JSON** | `jsonToToon` | `jsonToToonAsync` |
|
|
82
|
-
| **YAML** | `yamlToToon` | `yamlToToonAsync` |
|
|
83
|
-
| **XML** | `xmlToToonSync`* | `xmlToToon` |
|
|
84
|
-
| **CSV** | `csvToToonSync` | `csvToToon` |
|
|
85
|
-
|
|
86
|
-
*\*Note: `xmlToToonSync` in Node.js requires a global `DOMParser` polyfill (e.g., via `jsdom`).*
|
|
87
|
-
|
|
88
|
-
### 7. **Unified Class API** (`ToonConverter`)
|
|
89
|
-
The `ToonConverter` class now exposes all variations:
|
|
90
|
-
|
|
91
|
-
```javascript
|
|
92
|
-
// Async
|
|
93
|
-
await ToonConverter.fromJsonAsync(data);
|
|
94
|
-
await ToonConverter.fromXmlAsync(xml);
|
|
95
|
-
await ToonConverter.fromCsvAsync(csv);
|
|
96
|
-
|
|
97
|
-
// Sync
|
|
98
|
-
ToonConverter.fromJson(data);
|
|
99
|
-
ToonConverter.fromXmlSync(xml);
|
|
100
|
-
ToonConverter.fromCsvSync(csv);
|
|
101
|
-
|
|
102
|
-
// Mixed Text
|
|
103
|
-
ToonConverter.fromJsonText(text);
|
|
104
|
-
await ToonConverter.fromXmlText(text);
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## 🚀 Benefits
|
|
110
|
-
|
|
111
|
-
- **Robustness**: Validation prevents invalid conversions
|
|
112
|
-
- **Flexibility**: Handle mixed content seamlessly
|
|
113
|
-
- **Consistency**: Unified API for all formats
|
|
114
|
-
- **Developer Experience**: Clear errors, easy debugging
|
|
115
|
-
- **Reliability**: Comprehensive validation at every step
|
|
116
|
-
- **Reusability**: Extraction functions available for custom use
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
**Note**: History feature was intentionally NOT added to the package as requested.
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
Made with ❤️ for the TOON Formatter project
|
package/test/basic.test.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Basic tests for TOON Converter
|
|
3
|
-
* Run with: node --test test/basic.test.js
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { test } from 'node:test';
|
|
7
|
-
import assert from 'node:assert';
|
|
8
|
-
import { jsonToToonSync, toonToJsonSync } from '../src/json.js';
|
|
9
|
-
import { validateToonStringSync } from '../src/validator.js';
|
|
10
|
-
|
|
11
|
-
test('JSON to TOON - Simple Object', () => {
|
|
12
|
-
const input = { name: "Alice", age: 30, active: true };
|
|
13
|
-
const result = jsonToToonSync(input);
|
|
14
|
-
|
|
15
|
-
assert.ok(result.includes('name: "Alice"'));
|
|
16
|
-
assert.ok(result.includes('age: 30'));
|
|
17
|
-
assert.ok(result.includes('active: true'));
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test('JSON to TOON - Array of Primitives', () => {
|
|
21
|
-
const input = { numbers: [1, 2, 3, 4, 5] };
|
|
22
|
-
const result = jsonToToonSync(input);
|
|
23
|
-
|
|
24
|
-
assert.ok(result.includes('numbers[5]: 1, 2, 3, 4, 5'));
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
test('JSON to TOON - Tabular Array', () => {
|
|
28
|
-
const input = {
|
|
29
|
-
users: [
|
|
30
|
-
{ id: 1, name: "Alice", active: true },
|
|
31
|
-
{ id: 2, name: "Bob", active: false }
|
|
32
|
-
]
|
|
33
|
-
};
|
|
34
|
-
const result = jsonToToonSync(input);
|
|
35
|
-
|
|
36
|
-
assert.ok(result.includes('users[2]{id,name,active}:'));
|
|
37
|
-
assert.ok(result.includes('1,"Alice",true'));
|
|
38
|
-
assert.ok(result.includes('2,"Bob",false'));
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('TOON to JSON - Simple Object', () => {
|
|
42
|
-
const input = `name: "Alice"\nage: 30\nactive: true`;
|
|
43
|
-
const result = toonToJsonSync(input);
|
|
44
|
-
|
|
45
|
-
assert.strictEqual(result.name, "Alice");
|
|
46
|
-
assert.strictEqual(result.age, 30);
|
|
47
|
-
assert.strictEqual(result.active, true);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test('TOON to JSON - Array of Primitives', () => {
|
|
51
|
-
const input = `numbers[5]: 1, 2, 3, 4, 5`;
|
|
52
|
-
const result = toonToJsonSync(input);
|
|
53
|
-
|
|
54
|
-
assert.ok(Array.isArray(result.numbers));
|
|
55
|
-
assert.strictEqual(result.numbers.length, 5);
|
|
56
|
-
assert.deepStrictEqual(result.numbers, [1, 2, 3, 4, 5]);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test('TOON to JSON - Tabular Array', () => {
|
|
60
|
-
const input = `users[2]{id,name,active}:\n 1,"Alice",true\n 2,"Bob",false`;
|
|
61
|
-
const result = toonToJsonSync(input);
|
|
62
|
-
|
|
63
|
-
assert.ok(Array.isArray(result.users));
|
|
64
|
-
assert.strictEqual(result.users.length, 2);
|
|
65
|
-
assert.strictEqual(result.users[0].id, 1);
|
|
66
|
-
assert.strictEqual(result.users[0].name, "Alice");
|
|
67
|
-
assert.strictEqual(result.users[0].active, true);
|
|
68
|
-
assert.strictEqual(result.users[1].id, 2);
|
|
69
|
-
assert.strictEqual(result.users[1].name, "Bob");
|
|
70
|
-
assert.strictEqual(result.users[1].active, false);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test('Round-trip Conversion - Object', () => {
|
|
74
|
-
const original = {
|
|
75
|
-
company: "TechCorp",
|
|
76
|
-
employees: [
|
|
77
|
-
{ name: "Alice", role: "Engineer" },
|
|
78
|
-
{ name: "Bob", role: "Designer" }
|
|
79
|
-
]
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const toon = jsonToToonSync(original);
|
|
83
|
-
const result = toonToJsonSync(toon);
|
|
84
|
-
|
|
85
|
-
assert.deepStrictEqual(result, original);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test('Validator - Valid TOON', () => {
|
|
89
|
-
const input = `name: "Alice"\nage: 30`;
|
|
90
|
-
const result = validateToonStringSync(input);
|
|
91
|
-
|
|
92
|
-
assert.strictEqual(result.isValid, true);
|
|
93
|
-
assert.strictEqual(result.error, null);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test('Validator - Invalid TOON (Array Size Mismatch)', () => {
|
|
97
|
-
const input = `items[3]: 1, 2`; // Declared 3, but only 2 items
|
|
98
|
-
const result = validateToonStringSync(input);
|
|
99
|
-
|
|
100
|
-
assert.strictEqual(result.isValid, false);
|
|
101
|
-
assert.ok(result.error.includes('Array size mismatch'));
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test('Validator - Valid Tabular Array', () => {
|
|
105
|
-
const input = `users[2]{id,name}:\n 1,"Alice"\n 2,"Bob"`;
|
|
106
|
-
const result = validateToonStringSync(input);
|
|
107
|
-
|
|
108
|
-
assert.strictEqual(result.isValid, true);
|
|
109
|
-
assert.strictEqual(result.error, null);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
test('Edge Case - Empty Object', () => {
|
|
113
|
-
const input = {};
|
|
114
|
-
const result = jsonToToonSync(input);
|
|
115
|
-
|
|
116
|
-
assert.strictEqual(result.trim(), '');
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test('Edge Case - Null Value', () => {
|
|
120
|
-
const input = { value: null };
|
|
121
|
-
const result = jsonToToonSync(input);
|
|
122
|
-
|
|
123
|
-
assert.ok(result.includes('value: null'));
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test('Edge Case - Nested Objects', () => {
|
|
127
|
-
const input = {
|
|
128
|
-
level1: {
|
|
129
|
-
level2: {
|
|
130
|
-
level3: "deep"
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
const toon = jsonToToonSync(input);
|
|
136
|
-
const result = toonToJsonSync(toon);
|
|
137
|
-
|
|
138
|
-
assert.deepStrictEqual(result, input);
|
|
139
|
-
});
|
package/test/converters.test.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for YAML, XML, and CSV Converters
|
|
3
|
-
* Run with: node --test test/converters.test.js
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { test } from 'node:test';
|
|
7
|
-
import assert from 'node:assert';
|
|
8
|
-
import { yamlToToonSync, toonToYamlSync } from '../src/yaml.js';
|
|
9
|
-
import { xmlToToon, toonToXmlSync } from '../src/xml.js';
|
|
10
|
-
import { csvToToon, csvToToonSync, toonToCsvSync } from '../src/csv.js';
|
|
11
|
-
|
|
12
|
-
// --- YAML Tests ---
|
|
13
|
-
|
|
14
|
-
test('YAML to TOON - Simple Object', () => {
|
|
15
|
-
const yaml = `
|
|
16
|
-
name: Alice
|
|
17
|
-
age: 30
|
|
18
|
-
`;
|
|
19
|
-
const toon = yamlToToonSync(yaml);
|
|
20
|
-
assert.ok(toon.includes('name: "Alice"'));
|
|
21
|
-
assert.ok(toon.includes('age: 30'));
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test('TOON to YAML - Simple Object', () => {
|
|
25
|
-
const toon = `name: "Alice"\nage: 30`;
|
|
26
|
-
const yaml = toonToYamlSync(toon);
|
|
27
|
-
assert.ok(yaml.includes('name: Alice'));
|
|
28
|
-
assert.ok(yaml.includes('age: 30'));
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('YAML to TOON - Nested Structure', () => {
|
|
32
|
-
const yaml = `
|
|
33
|
-
user:
|
|
34
|
-
name: Alice
|
|
35
|
-
roles:
|
|
36
|
-
- admin
|
|
37
|
-
- editor
|
|
38
|
-
`;
|
|
39
|
-
const toon = yamlToToonSync(yaml);
|
|
40
|
-
assert.ok(toon.includes('user:'));
|
|
41
|
-
assert.ok(toon.includes('name: "Alice"'));
|
|
42
|
-
assert.ok(toon.includes('roles[2]:'));
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// --- XML Tests ---
|
|
46
|
-
|
|
47
|
-
test('XML to TOON - Simple Element', async () => {
|
|
48
|
-
const xml = `<user><name>Alice</name><age>30</age></user>`;
|
|
49
|
-
const toon = await xmlToToon(xml);
|
|
50
|
-
|
|
51
|
-
// Note: XML conversion wraps based on root element
|
|
52
|
-
assert.ok(toon.includes('user:'));
|
|
53
|
-
assert.ok(toon.includes('name: "Alice"'));
|
|
54
|
-
assert.ok(toon.includes('age: "30"')); // XML text content is usually string
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test('TOON to XML - Simple Element', () => {
|
|
58
|
-
const toon = `user:\n name: "Alice"\n age: 30`;
|
|
59
|
-
const xml = toonToXmlSync(toon);
|
|
60
|
-
|
|
61
|
-
assert.ok(xml.includes('<user>'));
|
|
62
|
-
assert.ok(xml.includes('<name>Alice</name>'));
|
|
63
|
-
assert.ok(xml.includes('<age>30</age>'));
|
|
64
|
-
assert.ok(xml.includes('</user>'));
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test('XML to TOON - Attributes', async () => {
|
|
68
|
-
const xml = `<item id="123" type="widget">Content</item>`;
|
|
69
|
-
const toon = await xmlToToon(xml);
|
|
70
|
-
|
|
71
|
-
assert.ok(toon.includes('item:'));
|
|
72
|
-
assert.ok(toon.includes('@attributes:'));
|
|
73
|
-
assert.ok(toon.includes('id: "123"'));
|
|
74
|
-
assert.ok(toon.includes('type: "widget"'));
|
|
75
|
-
assert.ok(toon.includes('#text: "Content"'));
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// --- CSV Tests ---
|
|
79
|
-
|
|
80
|
-
test('CSV to TOON - Basic (Async)', async () => {
|
|
81
|
-
const csv = `name,age,active
|
|
82
|
-
Alice,30,true
|
|
83
|
-
Bob,25,false`;
|
|
84
|
-
|
|
85
|
-
const toon = await csvToToon(csv);
|
|
86
|
-
|
|
87
|
-
// Should detect as tabular array or array of objects
|
|
88
|
-
// Since root is array, it might be [2]{name,age,active}: ...
|
|
89
|
-
|
|
90
|
-
assert.ok(toon.includes('[2]{name,age,active}:'));
|
|
91
|
-
assert.ok(toon.includes('Alice'));
|
|
92
|
-
assert.ok(toon.includes('30'));
|
|
93
|
-
assert.ok(toon.includes('true'));
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test('CSV to TOON - Basic (Sync)', () => {
|
|
97
|
-
const csv = `id,product
|
|
98
|
-
1,Apple
|
|
99
|
-
2,Banana`;
|
|
100
|
-
|
|
101
|
-
const toon = csvToToonSync(csv);
|
|
102
|
-
|
|
103
|
-
assert.ok(toon.includes('[2]{id,product}:'));
|
|
104
|
-
assert.ok(toon.includes('1,"Apple"'));
|
|
105
|
-
assert.ok(toon.includes('2,"Banana"'));
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
test('TOON to CSV - Basic', () => {
|
|
109
|
-
const toon = `
|
|
110
|
-
[2]{name,role}:
|
|
111
|
-
"Alice","Admin"
|
|
112
|
-
"Bob","User"
|
|
113
|
-
`;
|
|
114
|
-
const csv = toonToCsvSync(toon);
|
|
115
|
-
|
|
116
|
-
assert.ok(csv.includes('name,role'));
|
|
117
|
-
assert.ok(csv.includes('Alice,Admin'));
|
|
118
|
-
assert.ok(csv.includes('Bob,User'));
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test('CSV Round Trip', async () => {
|
|
122
|
-
const originalCsv = `name,score
|
|
123
|
-
Alice,100
|
|
124
|
-
Bob,95`;
|
|
125
|
-
|
|
126
|
-
const toon = await csvToToon(originalCsv);
|
|
127
|
-
const finalCsv = toonToCsvSync(toon);
|
|
128
|
-
|
|
129
|
-
// Note: PapaParse might add/remove quotes or change spacing, so exact match isn't always guaranteed
|
|
130
|
-
// But content should be same
|
|
131
|
-
assert.ok(finalCsv.includes('name'));
|
|
132
|
-
assert.ok(finalCsv.includes('score'));
|
|
133
|
-
assert.ok(finalCsv.includes('Alice'));
|
|
134
|
-
assert.ok(finalCsv.includes('100'));
|
|
135
|
-
});
|