json-toon-parser 1.0.1 → 1.1.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/README.md +19 -11
- package/dist/cli.js +22 -1
- package/dist/cli.js.map +1 -1
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +96 -0
- package/dist/server.js.map +1 -0
- package/package.json +9 -4
- package/public/index.html +706 -0
package/README.md
CHANGED
|
@@ -7,8 +7,20 @@
|
|
|
7
7
|
npm install -g json-toon-parser
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
+
## Quick Start - Web UI
|
|
11
|
+
After installation, start the web server:
|
|
12
|
+
```bash
|
|
13
|
+
json-toon serve
|
|
14
|
+
```
|
|
15
|
+
Then open your browser to `http://localhost:3000` and start converting JSON to TOON with a beautiful interface!
|
|
16
|
+
|
|
10
17
|
## CLI Usage
|
|
11
18
|
```bash
|
|
19
|
+
# Start web UI server (recommended for easy usage)
|
|
20
|
+
json-toon serve
|
|
21
|
+
# Or with custom port:
|
|
22
|
+
json-toon serve --port 8080
|
|
23
|
+
|
|
12
24
|
# Compare JSON with TOON format
|
|
13
25
|
json-toon compare data.json
|
|
14
26
|
|
|
@@ -38,12 +50,14 @@ const toonString = jsonToToon({ hello: "world" });
|
|
|
38
50
|
|
|
39
51
|
## Features
|
|
40
52
|
|
|
53
|
+
- 🌐 **Web UI** - Beautiful web interface for easy conversion
|
|
41
54
|
- ✅ Convert JSON to TOON format
|
|
42
55
|
- 📊 Compare token efficiency between formats
|
|
43
56
|
- 💾 Auto-save TOON files with timestamps
|
|
44
57
|
- 🔧 CLI tool for easy usage
|
|
45
58
|
- 📦 Programmatic API for Node.js
|
|
46
59
|
- 🎯 TypeScript support with full type definitions
|
|
60
|
+
- ⚡ Real-time conversion with live stats
|
|
47
61
|
|
|
48
62
|
## API
|
|
49
63
|
|
|
@@ -80,11 +94,11 @@ Format comparison result for display.
|
|
|
80
94
|
============================================================
|
|
81
95
|
COMPARISON RESULTS
|
|
82
96
|
============================================================
|
|
83
|
-
JSON Tokens:
|
|
84
|
-
TOON Tokens:
|
|
85
|
-
Token Savings:
|
|
86
|
-
Efficiency:
|
|
87
|
-
Output File: output/
|
|
97
|
+
JSON Tokens: 24890
|
|
98
|
+
TOON Tokens: 10204
|
|
99
|
+
Token Savings: 14686
|
|
100
|
+
Efficiency: 59.00% reduction
|
|
101
|
+
Output File: output/data_DateTime.toon
|
|
88
102
|
============================================================
|
|
89
103
|
```
|
|
90
104
|
|
|
@@ -103,9 +117,3 @@ Output File: output/data_2024-01-15T10-30-45.toon
|
|
|
103
117
|
## License
|
|
104
118
|
|
|
105
119
|
MIT © Bhushan Chaudhari
|
|
106
|
-
|
|
107
|
-
## Links
|
|
108
|
-
|
|
109
|
-
- [GitHub Repository](https://github.com/bhushan44/json-toon-parser)
|
|
110
|
-
- [Report Issues](https://github.com/bhushan44/json-toon-parser/issues)
|
|
111
|
-
- [NPM Package](https://www.npmjs.com/package/json-toon-parser)
|
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import { compareFile, convertFile, formatResult, updateJsonFile } from "./index.js";
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
4
9
|
const program = new Command();
|
|
5
10
|
program
|
|
6
11
|
.name("json-toon")
|
|
7
12
|
.description("Compare and convert JSON to TOON format")
|
|
8
|
-
.version("1.0.
|
|
13
|
+
.version("1.0.1");
|
|
9
14
|
program
|
|
10
15
|
.command("compare")
|
|
11
16
|
.description("Compare JSON file with TOON format")
|
|
@@ -58,5 +63,21 @@ program
|
|
|
58
63
|
process.exit(1);
|
|
59
64
|
}
|
|
60
65
|
});
|
|
66
|
+
program
|
|
67
|
+
.command("serve")
|
|
68
|
+
.description("Start web UI server for JSON to TOON conversion")
|
|
69
|
+
.option("-p, --port <port>", "Port number", "3000")
|
|
70
|
+
.action((options) => {
|
|
71
|
+
const serverPath = path.join(__dirname, "server.js");
|
|
72
|
+
const env = { ...process.env, PORT: options.port };
|
|
73
|
+
const serverProcess = spawn("node", [serverPath], {
|
|
74
|
+
env,
|
|
75
|
+
stdio: "inherit",
|
|
76
|
+
});
|
|
77
|
+
serverProcess.on("error", (error) => {
|
|
78
|
+
console.error("Failed to start server:", error.message);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
61
82
|
program.parse();
|
|
62
83
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":""}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import http from "node:http";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
const PORT = process.env.PORT || 3000;
|
|
9
|
+
const server = http.createServer((req, res) => {
|
|
10
|
+
// Set CORS headers
|
|
11
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
12
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
13
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
14
|
+
if (req.method === "OPTIONS") {
|
|
15
|
+
res.writeHead(200);
|
|
16
|
+
res.end();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (req.url === "/" || req.url === "/index.html") {
|
|
20
|
+
// Serve the HTML file
|
|
21
|
+
const htmlPath = path.join(__dirname, "..", "public", "index.html");
|
|
22
|
+
if (!fs.existsSync(htmlPath)) {
|
|
23
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
24
|
+
res.end("HTML file not found");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const html = fs.readFileSync(htmlPath, "utf-8");
|
|
28
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
29
|
+
res.end(html);
|
|
30
|
+
}
|
|
31
|
+
else if (req.url === "/api/convert" && req.method === "POST") {
|
|
32
|
+
// API endpoint for conversion
|
|
33
|
+
let body = "";
|
|
34
|
+
req.on("data", (chunk) => {
|
|
35
|
+
body += chunk.toString();
|
|
36
|
+
});
|
|
37
|
+
req.on("end", async () => {
|
|
38
|
+
try {
|
|
39
|
+
const { encode } = await import("@toon-format/toon");
|
|
40
|
+
const { encode: tokenize } = await import("gpt-3-encoder");
|
|
41
|
+
const jsonData = JSON.parse(body);
|
|
42
|
+
const toonOutput = encode(jsonData);
|
|
43
|
+
const jsonString = JSON.stringify(jsonData, null, 2);
|
|
44
|
+
const jsonTokens = tokenize(jsonString).length;
|
|
45
|
+
const toonTokens = tokenize(toonOutput).length;
|
|
46
|
+
const savings = jsonTokens - toonTokens;
|
|
47
|
+
const savingsPercentage = ((savings / jsonTokens) * 100).toFixed(2);
|
|
48
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
49
|
+
res.end(JSON.stringify({
|
|
50
|
+
success: true,
|
|
51
|
+
toonOutput,
|
|
52
|
+
jsonTokens,
|
|
53
|
+
toonTokens,
|
|
54
|
+
savings,
|
|
55
|
+
savingsPercentage,
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
60
|
+
res.end(JSON.stringify({
|
|
61
|
+
success: false,
|
|
62
|
+
error: error instanceof Error ? error.message : "Invalid JSON",
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
69
|
+
res.end("Not Found");
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
server.listen(PORT, () => {
|
|
73
|
+
console.log(`
|
|
74
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
75
|
+
║ ║
|
|
76
|
+
║ 🚀 JSON-TOON Converter Server ║
|
|
77
|
+
║ ║
|
|
78
|
+
║ Server running at: http://localhost:${PORT} ║
|
|
79
|
+
║ ║
|
|
80
|
+
║ 📝 Open your browser and start converting! ║
|
|
81
|
+
║ ⚡ Real-time JSON to TOON conversion ║
|
|
82
|
+
║ 💾 Token efficiency analysis ║
|
|
83
|
+
║ ║
|
|
84
|
+
║ Press Ctrl+C to stop the server ║
|
|
85
|
+
║ ║
|
|
86
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
87
|
+
`);
|
|
88
|
+
});
|
|
89
|
+
process.on("SIGINT", () => {
|
|
90
|
+
console.log("\n\n👋 Shutting down server...");
|
|
91
|
+
server.close(() => {
|
|
92
|
+
console.log("✅ Server stopped");
|
|
93
|
+
process.exit(0);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-toon-parser",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Compare and convert JSON to TOON format with token efficiency analysis",
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "Compare and convert JSON to TOON format with token efficiency analysis - Now with Web UI!",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"bin": {
|
|
@@ -10,12 +10,15 @@
|
|
|
10
10
|
"type": "module",
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "tsc",
|
|
13
|
-
"start": "npm run build && node dist/
|
|
13
|
+
"start": "npm run build && node dist/server.js",
|
|
14
|
+
"serve": "npm run build && node dist/server.js",
|
|
15
|
+
"dev": "tsc && node dist/server.js",
|
|
14
16
|
"prepublishOnly": "npm run build",
|
|
15
17
|
"test": "echo \"No tests specified\" && exit 0"
|
|
16
18
|
},
|
|
17
19
|
"files": [
|
|
18
20
|
"dist",
|
|
21
|
+
"public",
|
|
19
22
|
"README.md",
|
|
20
23
|
"LICENSE"
|
|
21
24
|
],
|
|
@@ -35,8 +38,10 @@
|
|
|
35
38
|
"license": "MIT",
|
|
36
39
|
"dependencies": {
|
|
37
40
|
"@toon-format/toon": "^1.0.0",
|
|
41
|
+
"1.0.1": "^1.0.0",
|
|
42
|
+
"commander": "^12.0.0",
|
|
38
43
|
"gpt-3-encoder": "^1.1.4",
|
|
39
|
-
"
|
|
44
|
+
"json-toon-parser": "^1.0.1"
|
|
40
45
|
},
|
|
41
46
|
"devDependencies": {
|
|
42
47
|
"@types/node": "^20.0.0",
|
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>JSON to TOON Converter - Live Tool</title>
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
16
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
17
|
+
min-height: 100vh;
|
|
18
|
+
padding: 20px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.container {
|
|
22
|
+
max-width: 1400px;
|
|
23
|
+
margin: 0 auto;
|
|
24
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
25
|
+
border-radius: 24px;
|
|
26
|
+
box-shadow: 0 30px 60px rgba(0,0,0,0.5);
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Header */
|
|
31
|
+
.header {
|
|
32
|
+
padding: 40px;
|
|
33
|
+
border-bottom: 1px solid rgba(255,255,255,0.1);
|
|
34
|
+
background: rgba(255,255,255,0.02);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.header-content {
|
|
38
|
+
display: flex;
|
|
39
|
+
justify-content: space-between;
|
|
40
|
+
align-items: center;
|
|
41
|
+
flex-wrap: wrap;
|
|
42
|
+
gap: 20px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.brand {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: 16px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.logo {
|
|
52
|
+
width: 50px;
|
|
53
|
+
height: 50px;
|
|
54
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
55
|
+
border-radius: 12px;
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
font-size: 24px;
|
|
60
|
+
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.brand-text h1 {
|
|
64
|
+
font-size: 28px;
|
|
65
|
+
font-weight: 800;
|
|
66
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
67
|
+
-webkit-background-clip: text;
|
|
68
|
+
-webkit-text-fill-color: transparent;
|
|
69
|
+
background-clip: text;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.brand-text p {
|
|
73
|
+
font-size: 14px;
|
|
74
|
+
color: #94a3b8;
|
|
75
|
+
margin-top: 4px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.actions {
|
|
79
|
+
display: flex;
|
|
80
|
+
gap: 12px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.btn {
|
|
84
|
+
padding: 12px 24px;
|
|
85
|
+
border-radius: 10px;
|
|
86
|
+
font-size: 14px;
|
|
87
|
+
font-weight: 600;
|
|
88
|
+
cursor: pointer;
|
|
89
|
+
border: none;
|
|
90
|
+
transition: all 0.3s ease;
|
|
91
|
+
display: flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
gap: 8px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.btn-primary {
|
|
97
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
98
|
+
color: white;
|
|
99
|
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.btn-primary:hover {
|
|
103
|
+
transform: translateY(-2px);
|
|
104
|
+
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.btn-secondary {
|
|
108
|
+
background: rgba(255,255,255,0.1);
|
|
109
|
+
color: #e2e8f0;
|
|
110
|
+
border: 1px solid rgba(255,255,255,0.2);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.btn-secondary:hover {
|
|
114
|
+
background: rgba(255,255,255,0.15);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* Main Content */
|
|
118
|
+
.main-content {
|
|
119
|
+
padding: 40px;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* Editor Section */
|
|
123
|
+
.editor-section {
|
|
124
|
+
display: grid;
|
|
125
|
+
grid-template-columns: 1fr 1fr;
|
|
126
|
+
gap: 20px;
|
|
127
|
+
margin-bottom: 30px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.editor-panel {
|
|
131
|
+
background: rgba(255,255,255,0.03);
|
|
132
|
+
border: 1px solid rgba(255,255,255,0.1);
|
|
133
|
+
border-radius: 16px;
|
|
134
|
+
overflow: hidden;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.panel-header {
|
|
138
|
+
padding: 20px;
|
|
139
|
+
background: rgba(255,255,255,0.05);
|
|
140
|
+
border-bottom: 1px solid rgba(255,255,255,0.1);
|
|
141
|
+
display: flex;
|
|
142
|
+
justify-content: space-between;
|
|
143
|
+
align-items: center;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.panel-title {
|
|
147
|
+
display: flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
gap: 10px;
|
|
150
|
+
font-size: 16px;
|
|
151
|
+
font-weight: 700;
|
|
152
|
+
color: #ffffff;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.title-icon {
|
|
156
|
+
font-size: 20px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.panel-actions {
|
|
160
|
+
display: flex;
|
|
161
|
+
gap: 8px;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.icon-btn {
|
|
165
|
+
width: 32px;
|
|
166
|
+
height: 32px;
|
|
167
|
+
border-radius: 8px;
|
|
168
|
+
background: rgba(255,255,255,0.1);
|
|
169
|
+
border: none;
|
|
170
|
+
color: #94a3b8;
|
|
171
|
+
cursor: pointer;
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
justify-content: center;
|
|
175
|
+
transition: all 0.3s ease;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.icon-btn:hover {
|
|
179
|
+
background: rgba(255,255,255,0.15);
|
|
180
|
+
color: #e2e8f0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.panel-content {
|
|
184
|
+
padding: 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
textarea {
|
|
188
|
+
width: 100%;
|
|
189
|
+
height: 400px;
|
|
190
|
+
background: rgba(0,0,0,0.3);
|
|
191
|
+
border: none;
|
|
192
|
+
color: #e2e8f0;
|
|
193
|
+
padding: 20px;
|
|
194
|
+
font-family: 'Monaco', 'Courier New', monospace;
|
|
195
|
+
font-size: 14px;
|
|
196
|
+
line-height: 1.6;
|
|
197
|
+
resize: vertical;
|
|
198
|
+
outline: none;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
textarea::placeholder {
|
|
202
|
+
color: #64748b;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* Stats Section */
|
|
206
|
+
.stats-section {
|
|
207
|
+
background: rgba(255,255,255,0.03);
|
|
208
|
+
border: 1px solid rgba(255,255,255,0.1);
|
|
209
|
+
border-radius: 16px;
|
|
210
|
+
padding: 30px;
|
|
211
|
+
margin-bottom: 20px;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.stats-grid {
|
|
215
|
+
display: grid;
|
|
216
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
217
|
+
gap: 20px;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.stat-card {
|
|
221
|
+
background: rgba(255,255,255,0.05);
|
|
222
|
+
border: 1px solid rgba(255,255,255,0.1);
|
|
223
|
+
border-radius: 12px;
|
|
224
|
+
padding: 24px;
|
|
225
|
+
text-align: center;
|
|
226
|
+
transition: all 0.3s ease;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.stat-card:hover {
|
|
230
|
+
background: rgba(255,255,255,0.08);
|
|
231
|
+
transform: translateY(-2px);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.stat-icon {
|
|
235
|
+
font-size: 32px;
|
|
236
|
+
margin-bottom: 12px;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.stat-value {
|
|
240
|
+
font-size: 36px;
|
|
241
|
+
font-weight: 800;
|
|
242
|
+
color: #ffffff;
|
|
243
|
+
margin-bottom: 8px;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.stat-label {
|
|
247
|
+
font-size: 13px;
|
|
248
|
+
color: #94a3b8;
|
|
249
|
+
text-transform: uppercase;
|
|
250
|
+
letter-spacing: 1px;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.stat-card.highlight {
|
|
254
|
+
background: linear-gradient(135deg, rgba(16, 185, 129, 0.2) 0%, rgba(5, 150, 105, 0.2) 100%);
|
|
255
|
+
border-color: rgba(16, 185, 129, 0.3);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.stat-card.highlight .stat-value {
|
|
259
|
+
color: #10b981;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/* Error/Success Messages */
|
|
263
|
+
.message {
|
|
264
|
+
padding: 16px 20px;
|
|
265
|
+
border-radius: 12px;
|
|
266
|
+
margin-bottom: 20px;
|
|
267
|
+
display: none;
|
|
268
|
+
align-items: center;
|
|
269
|
+
gap: 12px;
|
|
270
|
+
font-size: 14px;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.message.show {
|
|
274
|
+
display: flex;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.message-error {
|
|
278
|
+
background: rgba(239, 68, 68, 0.2);
|
|
279
|
+
border: 1px solid rgba(239, 68, 68, 0.3);
|
|
280
|
+
color: #fca5a5;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.message-success {
|
|
284
|
+
background: rgba(16, 185, 129, 0.2);
|
|
285
|
+
border: 1px solid rgba(16, 185, 129, 0.3);
|
|
286
|
+
color: #6ee7b7;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* Sample Data Section */
|
|
290
|
+
.samples {
|
|
291
|
+
display: flex;
|
|
292
|
+
gap: 12px;
|
|
293
|
+
flex-wrap: wrap;
|
|
294
|
+
margin-bottom: 20px;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.sample-btn {
|
|
298
|
+
padding: 10px 16px;
|
|
299
|
+
border-radius: 8px;
|
|
300
|
+
background: rgba(255,255,255,0.05);
|
|
301
|
+
border: 1px solid rgba(255,255,255,0.1);
|
|
302
|
+
color: #94a3b8;
|
|
303
|
+
font-size: 13px;
|
|
304
|
+
cursor: pointer;
|
|
305
|
+
transition: all 0.3s ease;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.sample-btn:hover {
|
|
309
|
+
background: rgba(255,255,255,0.1);
|
|
310
|
+
border-color: rgba(102, 126, 234, 0.5);
|
|
311
|
+
color: #667eea;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/* Footer */
|
|
315
|
+
.footer {
|
|
316
|
+
padding: 30px 40px;
|
|
317
|
+
border-top: 1px solid rgba(255,255,255,0.1);
|
|
318
|
+
text-align: center;
|
|
319
|
+
color: #64748b;
|
|
320
|
+
font-size: 13px;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.footer-links {
|
|
324
|
+
display: flex;
|
|
325
|
+
justify-content: center;
|
|
326
|
+
gap: 24px;
|
|
327
|
+
margin-top: 16px;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.footer-link {
|
|
331
|
+
color: #94a3b8;
|
|
332
|
+
text-decoration: none;
|
|
333
|
+
transition: color 0.3s ease;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.footer-link:hover {
|
|
337
|
+
color: #667eea;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* Responsive */
|
|
341
|
+
@media (max-width: 968px) {
|
|
342
|
+
.editor-section {
|
|
343
|
+
grid-template-columns: 1fr;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.stats-grid {
|
|
347
|
+
grid-template-columns: repeat(2, 1fr);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
@media (max-width: 640px) {
|
|
352
|
+
.header-content {
|
|
353
|
+
flex-direction: column;
|
|
354
|
+
align-items: flex-start;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.stats-grid {
|
|
358
|
+
grid-template-columns: 1fr;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
</style>
|
|
362
|
+
</head>
|
|
363
|
+
<body>
|
|
364
|
+
<div class="container">
|
|
365
|
+
<!-- Header -->
|
|
366
|
+
<div class="header">
|
|
367
|
+
<div class="header-content">
|
|
368
|
+
<div class="brand">
|
|
369
|
+
<div class="logo">📦</div>
|
|
370
|
+
<div class="brand-text">
|
|
371
|
+
<h1>JSON to TOON Converter</h1>
|
|
372
|
+
<p>Optimize your LLM token usage in real-time</p>
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
<div class="actions">
|
|
376
|
+
<button class="btn btn-primary" onclick="convertJson()">
|
|
377
|
+
<span>⚡</span>
|
|
378
|
+
<span>Convert</span>
|
|
379
|
+
</button>
|
|
380
|
+
<button class="btn btn-secondary" onclick="clearAll()">
|
|
381
|
+
<span>🔄</span>
|
|
382
|
+
<span>Clear</span>
|
|
383
|
+
</button>
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
</div>
|
|
387
|
+
|
|
388
|
+
<!-- Main Content -->
|
|
389
|
+
<div class="main-content">
|
|
390
|
+
<!-- Messages -->
|
|
391
|
+
<div id="errorMessage" class="message message-error">
|
|
392
|
+
<span>⚠️</span>
|
|
393
|
+
<span id="errorText"></span>
|
|
394
|
+
</div>
|
|
395
|
+
|
|
396
|
+
<div id="successMessage" class="message message-success">
|
|
397
|
+
<span>✅</span>
|
|
398
|
+
<span>Conversion successful!</span>
|
|
399
|
+
</div>
|
|
400
|
+
|
|
401
|
+
<!-- Sample Data -->
|
|
402
|
+
<div class="samples">
|
|
403
|
+
<span style="color: #94a3b8; font-size: 13px; font-weight: 600; margin-right: 8px;">Try samples:</span>
|
|
404
|
+
<button class="sample-btn" onclick="loadSample('simple')">Simple Object</button>
|
|
405
|
+
<button class="sample-btn" onclick="loadSample('array')">Array Data</button>
|
|
406
|
+
<button class="sample-btn" onclick="loadSample('nested')">Nested Structure</button>
|
|
407
|
+
<button class="sample-btn" onclick="loadSample('complex')">Complex Data</button>
|
|
408
|
+
</div>
|
|
409
|
+
|
|
410
|
+
<!-- Editor Section -->
|
|
411
|
+
<div class="editor-section">
|
|
412
|
+
<!-- JSON Input -->
|
|
413
|
+
<div class="editor-panel">
|
|
414
|
+
<div class="panel-header">
|
|
415
|
+
<div class="panel-title">
|
|
416
|
+
<span class="title-icon">{ }</span>
|
|
417
|
+
<span>JSON Input</span>
|
|
418
|
+
</div>
|
|
419
|
+
<div class="panel-actions">
|
|
420
|
+
<button class="icon-btn" onclick="copyJson()" title="Copy">📋</button>
|
|
421
|
+
<button class="icon-btn" onclick="formatJson()" title="Format">✨</button>
|
|
422
|
+
</div>
|
|
423
|
+
</div>
|
|
424
|
+
<div class="panel-content">
|
|
425
|
+
<textarea id="jsonInput" placeholder='Paste your JSON here...'></textarea>
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
428
|
+
|
|
429
|
+
<!-- TOON Output -->
|
|
430
|
+
<div class="editor-panel">
|
|
431
|
+
<div class="panel-header">
|
|
432
|
+
<div class="panel-title">
|
|
433
|
+
<span class="title-icon">⚡</span>
|
|
434
|
+
<span>TOON Output</span>
|
|
435
|
+
</div>
|
|
436
|
+
<div class="panel-actions">
|
|
437
|
+
<button class="icon-btn" onclick="copyToon()" title="Copy">📋</button>
|
|
438
|
+
<button class="icon-btn" onclick="downloadToon()" title="Download">💾</button>
|
|
439
|
+
</div>
|
|
440
|
+
</div>
|
|
441
|
+
<div class="panel-content">
|
|
442
|
+
<textarea id="toonOutput" placeholder="TOON output will appear here..." readonly></textarea>
|
|
443
|
+
</div>
|
|
444
|
+
</div>
|
|
445
|
+
</div>
|
|
446
|
+
|
|
447
|
+
<!-- Stats Section -->
|
|
448
|
+
<div class="stats-section">
|
|
449
|
+
<div class="stats-grid">
|
|
450
|
+
<div class="stat-card">
|
|
451
|
+
<div class="stat-icon">📄</div>
|
|
452
|
+
<div class="stat-value" id="jsonTokens">0</div>
|
|
453
|
+
<div class="stat-label">JSON Tokens</div>
|
|
454
|
+
</div>
|
|
455
|
+
|
|
456
|
+
<div class="stat-card">
|
|
457
|
+
<div class="stat-icon">⚡</div>
|
|
458
|
+
<div class="stat-value" id="toonTokens">0</div>
|
|
459
|
+
<div class="stat-label">TOON Tokens</div>
|
|
460
|
+
</div>
|
|
461
|
+
|
|
462
|
+
<div class="stat-card highlight">
|
|
463
|
+
<div class="stat-icon">💰</div>
|
|
464
|
+
<div class="stat-value" id="tokenSavings">0</div>
|
|
465
|
+
<div class="stat-label">Tokens Saved</div>
|
|
466
|
+
</div>
|
|
467
|
+
|
|
468
|
+
<div class="stat-card highlight">
|
|
469
|
+
<div class="stat-icon">📊</div>
|
|
470
|
+
<div class="stat-value" id="savingsPercent">0%</div>
|
|
471
|
+
<div class="stat-label">Efficiency Gain</div>
|
|
472
|
+
</div>
|
|
473
|
+
</div>
|
|
474
|
+
</div>
|
|
475
|
+
</div>
|
|
476
|
+
|
|
477
|
+
<!-- Footer -->
|
|
478
|
+
<div class="footer">
|
|
479
|
+
<p>Made with ❤️ using json-toon-parser</p>
|
|
480
|
+
<div class="footer-links">
|
|
481
|
+
<a href="https://www.npmjs.com/package/json-toon-parser" class="footer-link" target="_blank">📦 NPM Package</a>
|
|
482
|
+
<a href="https://github.com/bhushan44/json-toon-parser" class="footer-link" target="_blank">⭐ GitHub</a>
|
|
483
|
+
<a href="#" class="footer-link">📖 Documentation</a>
|
|
484
|
+
</div>
|
|
485
|
+
</div>
|
|
486
|
+
</div>
|
|
487
|
+
|
|
488
|
+
<!-- Include TOON library from CDN -->
|
|
489
|
+
<script type="module">
|
|
490
|
+
// Import TOON encoder
|
|
491
|
+
import { encode } from 'https://cdn.jsdelivr.net/npm/@toon-format/toon@1.0.0/+esm';
|
|
492
|
+
|
|
493
|
+
// Make encode available globally
|
|
494
|
+
window.toonEncode = encode;
|
|
495
|
+
|
|
496
|
+
// Simple tokenizer (GPT-3 approximation)
|
|
497
|
+
// This is a simplified version - for exact counts, you'd need the actual GPT-3 encoder
|
|
498
|
+
function countTokens(text) {
|
|
499
|
+
// Approximate token count: ~4 characters per token on average
|
|
500
|
+
// This is a rough estimate - actual GPT-3 tokenization is more complex
|
|
501
|
+
const words = text.split(/\s+/).length;
|
|
502
|
+
const chars = text.length;
|
|
503
|
+
const punctuation = (text.match(/[.,;:!?(){}[\]"']/g) || []).length;
|
|
504
|
+
|
|
505
|
+
// Better approximation
|
|
506
|
+
return Math.ceil((chars / 4) + (punctuation * 0.5));
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
window.countTokens = countTokens;
|
|
510
|
+
|
|
511
|
+
// Sample data
|
|
512
|
+
window.samples = {
|
|
513
|
+
simple: {
|
|
514
|
+
name: "John Doe",
|
|
515
|
+
age: 30,
|
|
516
|
+
email: "john@example.com",
|
|
517
|
+
active: true
|
|
518
|
+
},
|
|
519
|
+
array: {
|
|
520
|
+
users: [
|
|
521
|
+
{ id: 1, name: "Alice", role: "admin" },
|
|
522
|
+
{ id: 2, name: "Bob", role: "user" },
|
|
523
|
+
{ id: 3, name: "Charlie", role: "moderator" }
|
|
524
|
+
]
|
|
525
|
+
},
|
|
526
|
+
nested: {
|
|
527
|
+
company: {
|
|
528
|
+
name: "Tech Corp",
|
|
529
|
+
employees: [
|
|
530
|
+
{
|
|
531
|
+
id: 1,
|
|
532
|
+
name: "Alice",
|
|
533
|
+
department: {
|
|
534
|
+
id: 10,
|
|
535
|
+
name: "Engineering",
|
|
536
|
+
location: "Building A"
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
],
|
|
540
|
+
founded: 2020
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
complex: {
|
|
544
|
+
product: {
|
|
545
|
+
id: "prod_123",
|
|
546
|
+
name: "Awesome Product",
|
|
547
|
+
price: 99.99,
|
|
548
|
+
categories: ["electronics", "gadgets"],
|
|
549
|
+
specs: {
|
|
550
|
+
weight: "500g",
|
|
551
|
+
dimensions: { width: 10, height: 5, depth: 2 },
|
|
552
|
+
colors: ["black", "white", "blue"]
|
|
553
|
+
},
|
|
554
|
+
reviews: [
|
|
555
|
+
{ user: "Alice", rating: 5, comment: "Great!" },
|
|
556
|
+
{ user: "Bob", rating: 4, comment: "Good value" }
|
|
557
|
+
],
|
|
558
|
+
inStock: true,
|
|
559
|
+
metadata: {
|
|
560
|
+
created: "2024-01-15",
|
|
561
|
+
updated: "2024-01-20",
|
|
562
|
+
tags: ["featured", "bestseller"]
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
console.log('TOON converter loaded successfully!');
|
|
569
|
+
</script>
|
|
570
|
+
|
|
571
|
+
<script>
|
|
572
|
+
function showError(message) {
|
|
573
|
+
const errorEl = document.getElementById('errorMessage');
|
|
574
|
+
const errorText = document.getElementById('errorText');
|
|
575
|
+
errorText.textContent = message;
|
|
576
|
+
errorEl.classList.add('show');
|
|
577
|
+
|
|
578
|
+
setTimeout(() => {
|
|
579
|
+
errorEl.classList.remove('show');
|
|
580
|
+
}, 5000);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function showSuccess() {
|
|
584
|
+
const successEl = document.getElementById('successMessage');
|
|
585
|
+
successEl.classList.add('show');
|
|
586
|
+
|
|
587
|
+
setTimeout(() => {
|
|
588
|
+
successEl.classList.remove('show');
|
|
589
|
+
}, 3000);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
function convertJson() {
|
|
593
|
+
const jsonInput = document.getElementById('jsonInput').value.trim();
|
|
594
|
+
|
|
595
|
+
if (!jsonInput) {
|
|
596
|
+
showError('Please enter some JSON data');
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
try {
|
|
601
|
+
// Parse JSON
|
|
602
|
+
const jsonData = JSON.parse(jsonInput);
|
|
603
|
+
|
|
604
|
+
// Convert to TOON
|
|
605
|
+
const toonOutput = window.toonEncode(jsonData);
|
|
606
|
+
|
|
607
|
+
// Display TOON output
|
|
608
|
+
document.getElementById('toonOutput').value = toonOutput;
|
|
609
|
+
|
|
610
|
+
// Calculate tokens
|
|
611
|
+
const jsonString = JSON.stringify(jsonData, null, 2);
|
|
612
|
+
const jsonTokens = window.countTokens(jsonString);
|
|
613
|
+
const toonTokens = window.countTokens(toonOutput);
|
|
614
|
+
const savings = jsonTokens - toonTokens;
|
|
615
|
+
const savingsPercent = ((savings / jsonTokens) * 100).toFixed(1);
|
|
616
|
+
|
|
617
|
+
// Update stats
|
|
618
|
+
document.getElementById('jsonTokens').textContent = jsonTokens;
|
|
619
|
+
document.getElementById('toonTokens').textContent = toonTokens;
|
|
620
|
+
document.getElementById('tokenSavings').textContent = savings;
|
|
621
|
+
document.getElementById('savingsPercent').textContent = savingsPercent + '%';
|
|
622
|
+
|
|
623
|
+
showSuccess();
|
|
624
|
+
} catch (error) {
|
|
625
|
+
showError('Invalid JSON: ' + error.message);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function clearAll() {
|
|
630
|
+
document.getElementById('jsonInput').value = '';
|
|
631
|
+
document.getElementById('toonOutput').value = '';
|
|
632
|
+
document.getElementById('jsonTokens').textContent = '0';
|
|
633
|
+
document.getElementById('toonTokens').textContent = '0';
|
|
634
|
+
document.getElementById('tokenSavings').textContent = '0';
|
|
635
|
+
document.getElementById('savingsPercent').textContent = '0%';
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
function formatJson() {
|
|
639
|
+
const jsonInput = document.getElementById('jsonInput').value.trim();
|
|
640
|
+
|
|
641
|
+
if (!jsonInput) return;
|
|
642
|
+
|
|
643
|
+
try {
|
|
644
|
+
const jsonData = JSON.parse(jsonInput);
|
|
645
|
+
document.getElementById('jsonInput').value = JSON.stringify(jsonData, null, 2);
|
|
646
|
+
} catch (error) {
|
|
647
|
+
showError('Cannot format invalid JSON');
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function copyJson() {
|
|
652
|
+
const jsonInput = document.getElementById('jsonInput');
|
|
653
|
+
jsonInput.select();
|
|
654
|
+
document.execCommand('copy');
|
|
655
|
+
showSuccess();
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
function copyToon() {
|
|
659
|
+
const toonOutput = document.getElementById('toonOutput');
|
|
660
|
+
if (!toonOutput.value) {
|
|
661
|
+
showError('No TOON output to copy');
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
toonOutput.select();
|
|
665
|
+
document.execCommand('copy');
|
|
666
|
+
showSuccess();
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
function downloadToon() {
|
|
670
|
+
const toonOutput = document.getElementById('toonOutput').value;
|
|
671
|
+
|
|
672
|
+
if (!toonOutput) {
|
|
673
|
+
showError('No TOON output to download');
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
const blob = new Blob([toonOutput], { type: 'text/plain' });
|
|
678
|
+
const url = URL.createObjectURL(blob);
|
|
679
|
+
const a = document.createElement('a');
|
|
680
|
+
a.href = url;
|
|
681
|
+
a.download = `output_${new Date().toISOString().replace(/[:.]/g, '-')}.toon`;
|
|
682
|
+
document.body.appendChild(a);
|
|
683
|
+
a.click();
|
|
684
|
+
document.body.removeChild(a);
|
|
685
|
+
URL.revokeObjectURL(url);
|
|
686
|
+
|
|
687
|
+
showSuccess();
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function loadSample(type) {
|
|
691
|
+
const sample = window.samples[type];
|
|
692
|
+
if (sample) {
|
|
693
|
+
document.getElementById('jsonInput').value = JSON.stringify(sample, null, 2);
|
|
694
|
+
convertJson();
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// Auto-convert on Enter (Ctrl+Enter)
|
|
699
|
+
document.getElementById('jsonInput').addEventListener('keydown', function(e) {
|
|
700
|
+
if (e.ctrlKey && e.key === 'Enter') {
|
|
701
|
+
convertJson();
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
</script>
|
|
705
|
+
</body>
|
|
706
|
+
</html>
|