themebooth 0.2.0 → 0.3.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.
@@ -7,47 +7,45 @@ function generateColorPalette(manifest, resolved) {
7
7
  for (const [name, color] of Object.entries(manifest.variables || {})) {
8
8
  const resolvedColor = resolved[name] || color;
9
9
  html += `
10
- <div class="color-box">
11
- <div class="swatch" style="background-color: ${resolvedColor};"></div>
12
- <div class="name">${name}</div>
13
- <div class="value">${resolvedColor}</div>
14
- </div>`;
10
+ <div class="color-box">
11
+ <div class="swatch" style="background-color: ${resolvedColor};"></div>
12
+ <div class="name">${name}</div>
13
+ <div class="value">${resolvedColor}</div>
14
+ </div>`;
15
15
  }
16
16
  return html;
17
17
  }
18
18
  function generateCSSFromTheme(manifest) {
19
- let css = "";
20
- // Set root colors
21
- if (manifest.colors?.["editor.background"]) {
22
- css += `body { background-color: ${manifest.colors["editor.background"]}; }\n`;
23
- }
24
- if (manifest.colors?.["editor.foreground"]) {
25
- css += `body { color: ${manifest.colors["editor.foreground"]}; }\n`;
26
- }
27
- // Token styles
28
- css += `.keyword { color: ${manifest.tokens?.keyword?.foreground || "#569cd6"}; `;
29
- if (typeof manifest.tokens?.keyword?.fontStyle === "string" && manifest.tokens.keyword.fontStyle.includes("bold"))
30
- css += "font-weight: bold; ";
31
- css += "}\n";
32
- css += `.string { color: ${manifest.tokens?.string?.foreground || "#ce9178"}; }\n`;
33
- css += `.comment { color: ${manifest.tokens?.comment?.foreground || "#6a9955"}; `;
34
- if (typeof manifest.tokens?.comment?.fontStyle === "string" && manifest.tokens.comment.fontStyle.includes("italic"))
35
- css += "font-style: italic; ";
36
- css += "}\n";
37
- css += `.number { color: ${manifest.tokens?.number?.foreground || "#b5cea8"}; }\n`;
38
- css += `.builtin { color: ${manifest.tokens?.["constant.builtin"]?.foreground || "#4ec9b0"}; }\n`;
19
+ const keywordColor = manifest.tokens?.keyword?.foreground || "#569cd6";
20
+ const stringColor = manifest.tokens?.string?.foreground || "#ce9178";
21
+ const commentColor = manifest.tokens?.comment?.foreground || "#6a9955";
22
+ const numberColor = manifest.tokens?.number?.foreground || "#b5cea8";
23
+ const builtinColor = manifest.tokens?.["constant.builtin"]?.foreground || "#4ec9b0";
24
+ const typeColor = manifest.tokens?.["entity.name.type"]?.foreground || "#4ec9b0";
25
+ const methodColor = manifest.tokens?.["entity.name.function"]?.foreground || "#dcdcaa";
26
+ const operatorColor = manifest.tokens?.operator?.foreground || "#d4d4d4";
27
+ let css = ".keyword { color: " + keywordColor + "; font-weight: bold; }\n";
28
+ css += ".string { color: " + stringColor + "; }\n";
29
+ css += ".comment { color: " + commentColor + "; font-style: italic; }\n";
30
+ css += ".number { color: " + numberColor + "; }\n";
31
+ css += ".builtin { color: " + builtinColor + "; }\n";
32
+ css += ".type { color: " + typeColor + "; }\n";
33
+ css += ".method { color: " + methodColor + "; }\n";
34
+ css += ".operator { color: " + operatorColor + "; }\n";
39
35
  return css;
40
36
  }
41
37
  function renderPreview(manifest, themeName) {
42
- // Resolve variables for color display
43
38
  const variableResolution = (0, variables_1.resolveVariables)(manifest);
44
39
  const resolved = variableResolution.success ? variableResolution.variables : {};
45
- // Get interpolated manifest for rendering
46
40
  const interpolated = variableResolution.success ?
47
41
  (0, variables_1.interpolateManifest)(manifest, resolved)
48
42
  : manifest;
49
43
  const colorPalette = generateColorPalette(manifest, resolved);
50
44
  const themeCSS = generateCSSFromTheme(interpolated);
45
+ const bgColor = interpolated.colors?.["editor.background"] || "#1e1e1e";
46
+ const fgColor = interpolated.colors?.["editor.foreground"] || "#d4d4d4";
47
+ const accentColor = interpolated.colors?.["editor.lineNumberActiveForeground"] || "#61dafb";
48
+ const dimColor = interpolated.colors?.["editorWhitespace.foreground"] || "#888";
51
49
  return `<!DOCTYPE html>
52
50
  <html lang="en">
53
51
  <head>
@@ -63,93 +61,155 @@ function renderPreview(manifest, themeName) {
63
61
 
64
62
  body {
65
63
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
66
- background-color: ${interpolated.colors?.["editor.background"] || "#1e1e1e"};
67
- color: ${interpolated.colors?.["editor.foreground"] || "#d4d4d4"};
64
+ background-color: ${bgColor};
65
+ color: ${fgColor};
68
66
  padding: 20px;
69
67
  line-height: 1.6;
70
68
  }
71
69
 
72
- .container {
73
- max-width: 1200px;
70
+ .wrapper {
71
+ display: flex;
72
+ gap: 20px;
73
+ max-width: 1600px;
74
74
  margin: 0 auto;
75
+ min-height: 100vh;
75
76
  }
76
77
 
77
- h1 {
78
- margin-bottom: 10px;
79
- color: ${interpolated.colors?.["editor.lineNumberActiveForeground"] || "#61dafb"};
78
+ .palette-panel {
79
+ width: 180px;
80
+ flex-shrink: 0;
81
+ display: flex;
82
+ flex-direction: column;
83
+ gap: 10px;
80
84
  }
81
85
 
82
- .subtitle {
83
- color: ${interpolated.colors?.["editorWhitespace.foreground"] || "#888"};
84
- margin-bottom: 30px;
86
+ .palette-panel h2 {
87
+ font-size: 14px;
88
+ color: ${accentColor};
89
+ margin-bottom: 15px;
90
+ padding-bottom: 8px;
91
+ border-bottom: 1px solid #444;
85
92
  }
86
93
 
87
- .section {
88
- margin-bottom: 40px;
94
+ .palette {
95
+ display: flex;
96
+ flex-wrap: wrap;
97
+ gap: 8px;
98
+ padding-right: 5px;
89
99
  }
90
100
 
91
- .section h2 {
92
- font-size: 18px;
93
- color: ${interpolated.colors?.["editor.lineNumberActiveForeground"] || "#61dafb"};
94
- margin-bottom: 15px;
95
- border-bottom: 1px solid #444;
96
- padding-bottom: 10px;
101
+ .color-box {
102
+ display: flex;
103
+ flex-direction: column;
104
+ align-items: center;
105
+ gap: 4px;
106
+ flex: 0 1 calc(50% - 4px);
107
+ min-width: 70px;
97
108
  }
98
109
 
99
- .code-sample {
100
- background-color: ${interpolated.colors?.["editor.background"] || "#252526"};
110
+ .color-box .swatch {
111
+ width: 48px;
112
+ height: 48px;
113
+ border-radius: 3px;
101
114
  border: 1px solid #3e3e42;
102
- border-radius: 4px;
103
- padding: 15px;
104
- overflow-x: auto;
105
- margin-bottom: 15px;
115
+ cursor: pointer;
116
+ transition: all 0.2s ease;
106
117
  }
107
118
 
108
- .code-sample code {
119
+ .color-box .swatch:hover {
120
+ border-color: ${accentColor};
121
+ box-shadow: 0 0 8px rgba(97, 218, 251, 0.3);
122
+ }
123
+
124
+ .color-box .name {
125
+ font-size: 9px;
126
+ color: #888;
127
+ text-align: center;
128
+ word-break: break-word;
129
+ max-width: 50px;
130
+ }
131
+
132
+ .color-box .value {
133
+ font-size: 8px;
134
+ color: ${accentColor};
135
+ font-family: monospace;
136
+ display: none;
137
+ }
138
+
139
+ .color-box:hover .value {
109
140
  display: block;
110
141
  }
111
142
 
112
- ${themeCSS}
143
+ .main-content {
144
+ flex: 1;
145
+ }
113
146
 
114
- .palette {
115
- display: grid;
116
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
117
- gap: 15px;
147
+ h1 {
148
+ margin-bottom: 10px;
149
+ color: ${accentColor};
150
+ }
151
+
152
+ .subtitle {
153
+ color: ${dimColor};
118
154
  margin-bottom: 20px;
119
155
  }
120
156
 
121
- .color-box {
157
+ .controls {
158
+ margin-bottom: 20px;
122
159
  display: flex;
123
- flex-direction: column;
160
+ gap: 10px;
124
161
  align-items: center;
125
- padding: 15px;
162
+ }
163
+
164
+ .controls label {
165
+ color: ${dimColor};
166
+ font-size: 14px;
167
+ }
168
+
169
+ .controls select {
170
+ background-color: #252526;
126
171
  border: 1px solid #3e3e42;
127
172
  border-radius: 4px;
128
- background-color: ${interpolated.colors?.["editor.background"] || "#252526"};
173
+ color: ${fgColor};
174
+ padding: 8px 12px;
175
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
176
+ font-size: 13px;
177
+ cursor: pointer;
129
178
  }
130
179
 
131
- .color-box .swatch {
132
- width: 100%;
133
- height: 80px;
134
- border-radius: 4px;
135
- margin-bottom: 10px;
180
+ .controls select:hover {
181
+ border-color: ${accentColor};
182
+ }
183
+
184
+ .code-sample {
185
+ background-color: #252526;
136
186
  border: 1px solid #3e3e42;
187
+ border-radius: 4px;
188
+ padding: 15px;
189
+ overflow-x: auto;
190
+ display: none;
191
+ max-height: 600px;
137
192
  }
138
193
 
139
- .color-box .name {
194
+ .code-sample.active {
195
+ display: block;
196
+ }
197
+
198
+ .code-sample pre {
199
+ margin: 0;
200
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
140
201
  font-size: 12px;
141
- color: ${interpolated.colors?.["editorWhitespace.foreground"] || "#888"};
142
- text-align: center;
143
- word-break: break-word;
202
+ line-height: 1.5;
203
+ white-space: pre;
204
+ overflow-x: auto;
144
205
  }
145
206
 
146
- .color-box .value {
147
- font-size: 11px;
148
- color: ${interpolated.colors?.["editor.lineNumberActiveForeground"] || "#61dafb"};
149
- font-family: monospace;
150
- margin-top: 5px;
207
+ .code-sample code {
208
+ font-size: 12px;
151
209
  }
152
210
 
211
+ ${themeCSS}
212
+
153
213
  .status {
154
214
  padding: 10px 15px;
155
215
  border-radius: 4px;
@@ -177,62 +237,453 @@ function renderPreview(manifest, themeName) {
177
237
  font-size: 12px;
178
238
  color: #888;
179
239
  }
240
+
241
+ ::-webkit-scrollbar {
242
+ width: 8px;
243
+ height: 8px;
244
+ }
245
+
246
+ ::-webkit-scrollbar-track {
247
+ background: ${bgColor};
248
+ }
249
+
250
+ ::-webkit-scrollbar-thumb {
251
+ background: #404040;
252
+ border-radius: 4px;
253
+ }
254
+
255
+ ::-webkit-scrollbar-thumb:hover {
256
+ background: #505050;
257
+ }
180
258
  </style>
181
259
  </head>
182
260
  <body>
183
- <div class="container">
184
- <h1>${themeName}</h1>
185
- <p class="subtitle">Live Preview • Edit manifest.json to see changes</p>
186
-
187
- <div id="status" class="status success" style="display:none;"></div>
188
-
189
- <div class="section">
190
- <h2>Color Palette</h2>
261
+ <div class="wrapper">
262
+ <div class="palette-panel">
263
+ <h2>Palette</h2>
191
264
  <div class="palette" id="palette">${colorPalette}</div>
192
265
  </div>
193
266
 
194
- <div class="section">
195
- <h2>JavaScript</h2>
196
- <div class="code-sample">
197
- <code>
198
- <span class="keyword">const</span> greeting = <span class="string">"Hello, World!"</span>;
199
- <span class="keyword">function</span> greet(name) {
200
- <span class="comment">// Print greeting</span>
201
- console.log(\`\${greeting} My name is \${name}\`);
202
- <span class="keyword">return</span> <span class="number">42</span>;
267
+ <div class="main-content">
268
+ <h1>${themeName}</h1>
269
+ <p class="subtitle">Live Preview • Edit manifest.json to see changes</p>
270
+
271
+ <div id="status" class="status success" style="display:none;"></div>
272
+
273
+ <div class="controls">
274
+ <label for="language-select">Language:</label>
275
+ <select id="language-select" onchange="switchLanguage(this.value)">
276
+ <option value="javascript">JavaScript</option>
277
+ <option value="python">Python</option>
278
+ <option value="java">Java</option>
279
+ <option value="php">PHP</option>
280
+ <option value="json">JSON</option>
281
+ </select>
282
+ </div>
283
+
284
+ <div class="code-sample active" id="javascript">
285
+ <pre><code>
286
+ <span class="comment">// Advanced JavaScript with multiple language primitives</span>
287
+ <span class="comment">// Demonstrates classes, interfaces, functions, async/await, destructuring, etc.</span>
288
+
289
+ <span class="keyword">interface</span> User {
290
+ id: <span class="type">number</span>;
291
+ name: <span class="type">string</span>;
292
+ email: <span class="type">string</span>;
293
+ role: <span class="type">'admin'</span> | <span class="type">'user'</span>;
203
294
  }
204
- </code>
295
+
296
+ <span class="keyword">class</span> <span class="type">UserManager</span> {
297
+ <span class="keyword">private</span> users: User[] = [];
298
+ <span class="keyword">private</span> <span class="keyword">readonly</span> maxUsers = <span class="number">100</span>;
299
+
300
+ <span class="keyword">constructor</span>(<span class="keyword">private</span> apiUrl: <span class="type">string</span>) {}
301
+
302
+ <span class="keyword">async</span> <span class="method">fetchUsers</span>(): <span class="type">Promise</span>&lt;User[]&gt; {
303
+ <span class="keyword">try</span> {
304
+ <span class="keyword">const</span> response = <span class="keyword">await</span> fetch(this.apiUrl);
305
+ <span class="keyword">const</span> data = <span class="keyword">await</span> response.json();
306
+ <span class="keyword">this</span>.users = data;
307
+ <span class="keyword">return</span> this.users;
308
+ } <span class="keyword">catch</span> (error) {
309
+ console.error(<span class="string">'Failed to fetch users:'</span>, error);
310
+ <span class="keyword">return</span> [];
311
+ }
312
+ }
313
+
314
+ <span class="method">addUser</span>(user: User): <span class="type">boolean</span> {
315
+ <span class="keyword">if</span> (<span class="keyword">this</span>.users.length &gt;= <span class="keyword">this</span>.maxUsers) {
316
+ <span class="keyword">throw</span> <span class="keyword">new</span> Error(<span class="string">'User limit exceeded'</span>);
317
+ }
318
+ <span class="keyword">this</span>.users.push(user);
319
+ <span class="keyword">return</span> <span class="keyword">true</span>;
320
+ }
321
+
322
+ <span class="method">removeUser</span>(id: <span class="type">number</span>): <span class="type">boolean</span> {
323
+ <span class="keyword">const</span> index = <span class="keyword">this</span>.users.findIndex(u =&gt; u.id === id);
324
+ <span class="keyword">if</span> (index &gt; <span class="operator">-</span><span class="number">1</span>) {
325
+ <span class="keyword">this</span>.users.splice(index, <span class="number">1</span>);
326
+ <span class="keyword">return</span> <span class="keyword">true</span>;
327
+ }
328
+ <span class="keyword">return</span> <span class="keyword">false</span>;
329
+ }
330
+
331
+ <span class="method">filterByRole</span>(role: <span class="type">string</span>): User[] {
332
+ <span class="keyword">return</span> <span class="keyword">this</span>.users.filter(user =&gt; user.role === role);
333
+ }
334
+
335
+ <span class="method">mapToEmails</span>(): <span class="type">string</span>[] {
336
+ <span class="keyword">return</span> <span class="keyword">this</span>.users.map(({ email }) =&gt; email);
337
+ }
338
+
339
+ <span class="method">getAdmins</span>(): User[] {
340
+ <span class="keyword">const</span> { users } = <span class="keyword">this</span>;
341
+ <span class="keyword">return</span> users.filter(u =&gt; u.role === <span class="string">'admin'</span>);
342
+ }
343
+ }
344
+
345
+ <span class="comment">// Anonymous function with arrow syntax</span>
346
+ <span class="keyword">const</span> calculateSum = (arr: <span class="type">number</span>[]): <span class="type">number</span> =&gt; {
347
+ <span class="keyword">return</span> arr.reduce((sum, val) =&gt; sum + val, <span class="number">0</span>);
348
+ };
349
+
350
+ <span class="comment">// Higher-order function</span>
351
+ <span class="keyword">const</span> memoize = &lt;T, U&gt;(fn: (arg: T) =&gt; U) =&gt; {
352
+ <span class="keyword">const</span> cache = <span class="keyword">new</span> Map&lt;T, U&gt;();
353
+ <span class="keyword">return</span> (arg: T): U =&gt; {
354
+ <span class="keyword">if</span> (cache.has(arg)) {
355
+ <span class="keyword">return</span> cache.get(arg)!;
356
+ }
357
+ <span class="keyword">const</span> result = fn(arg);
358
+ cache.set(arg, result);
359
+ <span class="keyword">return</span> result;
360
+ };
361
+ };
362
+
363
+ <span class="comment">// Object destructuring with rest operator</span>
364
+ <span class="keyword">const</span> { name, email, ...rest } = <span class="keyword">this</span>.users[<span class="number">0</span>];
365
+
366
+ <span class="comment">// Array destructuring</span>
367
+ <span class="keyword">const</span> [first, second, ...others] = <span class="keyword">this</span>.users;
368
+
369
+ <span class="comment">// Async iterator pattern</span>
370
+ <span class="keyword">async</span> <span class="keyword">function</span>* <span class="method">asyncGenerator</span>() {
371
+ <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="number">5</span>; i++) {
372
+ <span class="keyword">await</span> <span class="keyword">new</span> Promise(r =&gt; setTimeout(r, <span class="number">1000</span>));
373
+ <span class="keyword">yield</span> i;
374
+ }
375
+ }
376
+
377
+ <span class="comment">// Usage example</span>
378
+ <span class="keyword">const</span> manager = <span class="keyword">new</span> UserManager(<span class="string">'https://api.example.com/users'</span>);
379
+ manager.fetchUsers();
380
+ <span class="keyword">const</span> admins = manager.getAdmins();
381
+ <span class="keyword">const</span> emails = manager.mapToEmails();
382
+ </code></pre>
205
383
  </div>
206
- </div>
207
384
 
208
- <div class="section">
209
- <h2>Python</h2>
210
- <div class="code-sample">
211
- <code>
212
- <span class="keyword">def</span> greet(name):
213
- <span class="comment"># Print greeting</span>
214
- greeting = <span class="string">"Hello, World!"</span>
215
- print(f<span class="string">"{greeting} My name is {name}"</span>)
216
- <span class="keyword">return</span> <span class="number">42</span>
217
-
218
- greet(<span class="string">"Python"</span>)
219
- </code>
385
+ <div class="code-sample" id="python">
386
+ <pre><code>
387
+ <span class="comment"># Advanced Python with classes, decorators, async, comprehensions</span>
388
+ <span class="comment"># Demonstrates various Python language features and patterns</span>
389
+
390
+ <span class="keyword">from</span> typing <span class="keyword">import</span> List, Dict, Optional, TypeVar, Generic
391
+ <span class="keyword">from</span> abc <span class="keyword">import</span> ABC, abstractmethod
392
+ <span class="keyword">import</span> asyncio
393
+ <span class="keyword">from</span> functools <span class="keyword">import</span> wraps
394
+
395
+ T = TypeVar(<span class="string">'T'</span>)
396
+
397
+ <span class="comment"># Abstract base class</span>
398
+ <span class="keyword">class</span> <span class="type">Repository</span>(ABC):
399
+ <span class="keyword">@abstractmethod</span>
400
+ <span class="keyword">async</span> <span class="keyword">def</span> <span class="method">fetch</span>(self):
401
+ <span class="keyword">pass</span>
402
+
403
+ <span class="keyword">class</span> <span class="type">User</span>:
404
+ <span class="keyword">def</span> <span class="method">__init__</span>(self, id: int, name: str, email: str):
405
+ self.id = id
406
+ self.name = name
407
+ self.email = email
408
+
409
+ <span class="keyword">def</span> <span class="method">__repr__</span>(self):
410
+ <span class="keyword">return</span> <span class="string">f"User(id={self.id}, name={self.name})"</span>
411
+
412
+ <span class="keyword">class</span> <span class="type">UserManager</span>(Repository):
413
+ <span class="keyword">def</span> <span class="method">__init__</span>(self, api_url: str):
414
+ self.api_url = api_url
415
+ self.users: List[User] = []
416
+
417
+ <span class="keyword">async</span> <span class="keyword">def</span> <span class="method">fetch</span>(self) -&gt; List[User]:
418
+ <span class="keyword">try</span>:
419
+ <span class="comment"># Simulated async API call</span>
420
+ <span class="keyword">await</span> asyncio.sleep(<span class="number">1</span>)
421
+ <span class="keyword">return</span> self.users
422
+ <span class="keyword">except</span> Exception <span class="keyword">as</span> e:
423
+ print(<span class="string">f"Error fetching users: {e}"</span>)
424
+ <span class="keyword">return</span> []
425
+
426
+ <span class="keyword">def</span> <span class="method">add_user</span>(self, user: User) -&gt; bool:
427
+ self.users.append(user)
428
+ <span class="keyword">return</span> <span class="keyword">True</span>
429
+
430
+ <span class="keyword">def</span> <span class="method">get_by_role</span>(self, role: str) -&gt; List[User]:
431
+ <span class="keyword">return</span> [u <span class="keyword">for</span> u <span class="keyword">in</span> self.users <span class="keyword">if</span> hasattr(u, <span class="string">'role'</span>) <span class="keyword">and</span> u.role == role]
432
+
433
+ <span class="keyword">def</span> <span class="method">get_emails</span>(self) -&gt; List[str]:
434
+ <span class="keyword">return</span> [u.email <span class="keyword">for</span> u <span class="keyword">in</span> self.users]
435
+
436
+ <span class="keyword">def</span> <span class="method">filter_by_name</span>(self, pattern: str) -&gt; List[User]:
437
+ <span class="keyword">return</span> [u <span class="keyword">for</span> u <span class="keyword">in</span> self.users <span class="keyword">if</span> pattern <span class="keyword">in</span> u.name]
438
+
439
+ <span class="comment"># Decorator function</span>
440
+ <span class="keyword">def</span> <span class="method">timer</span>(func):
441
+ <span class="keyword">@wraps</span>(func)
442
+ <span class="keyword">def</span> <span class="method">wrapper</span>(*args, **kwargs):
443
+ import time
444
+ start = time.time()
445
+ result = func(*args, **kwargs)
446
+ elapsed = time.time() - start
447
+ print(<span class="string">f"{func.__name__} took {elapsed:.2f}s"</span>)
448
+ <span class="keyword">return</span> result
449
+ <span class="keyword">return</span> wrapper
450
+
451
+ <span class="comment"># Generator function</span>
452
+ <span class="keyword">def</span> <span class="method">count_up_to</span>(n: int):
453
+ i = <span class="number">0</span>
454
+ <span class="keyword">while</span> i &lt; n:
455
+ <span class="keyword">yield</span> i
456
+ i += <span class="number">1</span>
457
+
458
+ <span class="keyword">async</span> <span class="keyword">def</span> <span class="method">main</span>():
459
+ manager = <span class="type">UserManager</span>(<span class="string">'https://api.example.com'</span>)
460
+ users = <span class="keyword">await</span> manager.fetch()
461
+ <span class="keyword">return</span> users
462
+
463
+ <span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:
464
+ asyncio.run(main())
465
+ </code></pre>
220
466
  </div>
221
- </div>
222
467
 
223
- <div class="section">
224
- <h2>JSON</h2>
225
- <div class="code-sample">
226
- <code>
468
+ <div class="code-sample" id="java">
469
+ <pre><code>
470
+ <span class="comment">// Advanced Java with interfaces, generics, lambdas, annotations</span>
471
+ <span class="comment">// Demonstrates comprehensive language features and patterns</span>
472
+
473
+ <span class="keyword">package</span> com.example.user;
474
+
475
+ <span class="keyword">import</span> java.util.*;
476
+ <span class="keyword">import</span> java.util.stream.*;
477
+ <span class="keyword">import</span> java.util.concurrent.*;
478
+
479
+ <span class="keyword">public</span> <span class="keyword">interface</span> <span class="type">Repository</span>&lt;T&gt; {
480
+ Optional&lt;T&gt; findById(<span class="type">int</span> id);
481
+ List&lt;T&gt; findAll();
482
+ <span class="keyword">void</span> save(T entity);
483
+ <span class="keyword">void</span> delete(T entity);
484
+ }
485
+
486
+ <span class="keyword">public</span> <span class="keyword">class</span> <span class="type">User</span> {
487
+ <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">int</span> id;
488
+ <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">String</span> name;
489
+ <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">String</span> email;
490
+ <span class="keyword">private</span> <span class="type">UserRole</span> role;
491
+
492
+ <span class="keyword">public</span> <span class="type">User</span>(<span class="type">int</span> id, <span class="type">String</span> name, <span class="type">String</span> email) {
493
+ <span class="keyword">this</span>.id = id;
494
+ <span class="keyword">this</span>.name = name;
495
+ <span class="keyword">this</span>.email = email;
496
+ }
497
+
498
+ <span class="keyword">public</span> <span class="type">int</span> <span class="method">getId</span>() { <span class="keyword">return</span> id; }
499
+ <span class="keyword">public</span> <span class="type">String</span> <span class="method">getName</span>() { <span class="keyword">return</span> name; }
500
+ <span class="keyword">public</span> <span class="type">String</span> <span class="method">getEmail</span>() { <span class="keyword">return</span> email; }
501
+
502
+ @Override
503
+ <span class="keyword">public</span> <span class="type">String</span> <span class="method">toString</span>() {
504
+ <span class="keyword">return</span> <span class="string">String.format("User(id=%d, name=%s)"</span>, id, name);
505
+ }
506
+ }
507
+
508
+ <span class="keyword">public</span> <span class="keyword">enum</span> <span class="type">UserRole</span> {
509
+ ADMIN, USER, GUEST
510
+ }
511
+
512
+ <span class="keyword">public</span> <span class="keyword">class</span> <span class="type">UserManager</span> <span class="keyword">implements</span> <span class="type">Repository</span>&lt;<span class="type">User</span>&gt; {
513
+ <span class="keyword">private</span> <span class="keyword">final</span> List&lt;<span class="type">User</span>&gt; users;
514
+ <span class="keyword">private</span> <span class="keyword">final</span> <span class="type">String</span> apiUrl;
515
+ <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> MAX_USERS = <span class="number">100</span>;
516
+
517
+ <span class="keyword">public</span> <span class="type">UserManager</span>(<span class="type">String</span> apiUrl) {
518
+ <span class="keyword">this</span>.apiUrl = apiUrl;
519
+ <span class="keyword">this</span>.users = <span class="keyword">new</span> CopyOnWriteArrayList&lt;&gt;();
520
+ }
521
+
522
+ @Override
523
+ <span class="keyword">public</span> Optional&lt;<span class="type">User</span>&gt; <span class="method">findById</span>(<span class="type">int</span> id) {
524
+ <span class="keyword">return</span> users.stream()
525
+ .filter(u -&gt; u.getId() == id)
526
+ .findFirst();
527
+ }
528
+
529
+ @Override
530
+ <span class="keyword">public</span> List&lt;<span class="type">User</span>&gt; <span class="method">findAll</span>() {
531
+ <span class="keyword">return</span> <span class="keyword">new</span> ArrayList&lt;&gt;(users);
532
+ }
533
+
534
+ @Override
535
+ <span class="keyword">public</span> <span class="keyword">void</span> <span class="method">save</span>(<span class="type">User</span> user) {
536
+ <span class="keyword">if</span> (users.size() &gt;= MAX_USERS) {
537
+ <span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException(<span class="string">"User limit exceeded"</span>);
538
+ }
539
+ users.add(user);
540
+ }
541
+
542
+ @Override
543
+ <span class="keyword">public</span> <span class="keyword">void</span> <span class="method">delete</span>(<span class="type">User</span> user) {
544
+ users.remove(user);
545
+ }
546
+
547
+ <span class="keyword">public</span> List&lt;<span class="type">String</span>&gt; <span class="method">getEmails</span>() {
548
+ <span class="keyword">return</span> users.stream()
549
+ .map(<span class="type">User</span>::getEmail)
550
+ .collect(Collectors.toList());
551
+ }
552
+
553
+ <span class="keyword">public</span> <span class="type">Map</span>&lt;<span class="type">Integer</span>, <span class="type">User</span>&gt; <span class="method">toMap</span>() {
554
+ <span class="keyword">return</span> users.stream()
555
+ .collect(Collectors.toMap(<span class="type">User</span>::getId, u -&gt; u));
556
+ }
557
+
558
+ <span class="keyword">public</span> &lt;T&gt; List&lt;T&gt; <span class="method">map</span>(<span class="type">Function</span>&lt;<span class="type">User</span>, T&gt; mapper) {
559
+ <span class="keyword">return</span> users.stream()
560
+ .map(mapper)
561
+ .collect(Collectors.toList());
562
+ }
563
+
564
+ <span class="keyword">public</span> <span class="type">CompletableFuture</span>&lt;List&lt;<span class="type">User</span>&gt;&gt; <span class="method">fetchUsersAsync</span>() {
565
+ <span class="keyword">return</span> <span class="type">CompletableFuture</span>.supplyAsync(() -&gt; {
566
+ <span class="keyword">try</span> {
567
+ <span class="type">Thread</span>.sleep(<span class="number">1000</span>);
568
+ <span class="keyword">return</span> users;
569
+ } <span class="keyword">catch</span> (<span class="type">InterruptedException</span> e) {
570
+ <span class="type">Thread</span>.currentThread().interrupt();
571
+ <span class="keyword">return</span> <span class="keyword">new</span> ArrayList&lt;&gt;();
572
+ }
573
+ });
574
+ }
575
+ }
576
+ </code></pre>
577
+ </div>
578
+
579
+ <div class="code-sample" id="php">
580
+ <pre><code>
581
+ <span class="keyword">&lt;?php</span>
582
+
583
+ <span class="keyword">namespace</span> App\\User;
584
+
585
+ <span class="keyword">use</span> Exception;
586
+
587
+ <span class="comment">// Interface definition</span>
588
+ <span class="keyword">interface</span> <span class="type">RepositoryInterface</span> {
589
+ <span class="keyword">public</span> <span class="keyword">function</span> findById(<span class="type">int</span> \$id);
590
+ <span class="keyword">public</span> <span class="keyword">function</span> findAll(): <span class="type">array</span>;
591
+ <span class="keyword">public</span> <span class="keyword">function</span> save(\$entity): <span class="type">bool</span>;
592
+ }
593
+
594
+ <span class="keyword">class</span> <span class="type">User</span> {
595
+ <span class="keyword">private</span> <span class="type">int</span> \$id;
596
+ <span class="keyword">private</span> <span class="type">string</span> \$name;
597
+ <span class="keyword">private</span> <span class="type">string</span> \$email;
598
+
599
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">__construct</span>(<span class="type">int</span> \$id, <span class="type">string</span> \$name, <span class="type">string</span> \$email) {
600
+ \$this-&gt;id = \$id;
601
+ \$this-&gt;name = \$name;
602
+ \$this-&gt;email = \$email;
603
+ }
604
+
605
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">getId</span>(): <span class="type">int</span> {
606
+ <span class="keyword">return</span> \$this-&gt;id;
607
+ }
608
+
609
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">getName</span>(): <span class="type">string</span> {
610
+ <span class="keyword">return</span> \$this-&gt;name;
611
+ }
612
+
613
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">getEmail</span>(): <span class="type">string</span> {
614
+ <span class="keyword">return</span> \$this-&gt;email;
615
+ }
616
+
617
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">__toString</span>(): <span class="type">string</span> {
618
+ <span class="keyword">return</span> <span class="string">"User(id={\$this-&gt;id}, name={\$this-&gt;name})"</span>;
619
+ }
620
+ }
621
+
622
+ <span class="keyword">class</span> <span class="type">UserManager</span> <span class="keyword">implements</span> <span class="type">RepositoryInterface</span> {
623
+ <span class="keyword">private</span> <span class="type">array</span> \$users = [];
624
+ <span class="keyword">private</span> <span class="type">string</span> \$apiUrl;
625
+ <span class="keyword">private</span> <span class="keyword">const</span> MAX_USERS = <span class="number">100</span>;
626
+
627
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">__construct</span>(<span class="type">string</span> \$apiUrl) {
628
+ \$this-&gt;apiUrl = \$apiUrl;
629
+ }
630
+
631
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">findById</span>(<span class="type">int</span> \$id) {
632
+ <span class="keyword">foreach</span> (\$this-&gt;users <span class="keyword">as</span> \$user) {
633
+ <span class="keyword">if</span> (\$user-&gt;getId() === \$id) {
634
+ <span class="keyword">return</span> \$user;
635
+ }
636
+ }
637
+ <span class="keyword">return</span> <span class="keyword">null</span>;
638
+ }
639
+
640
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">findAll</span>(): <span class="type">array</span> {
641
+ <span class="keyword">return</span> \$this-&gt;users;
642
+ }
643
+
644
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">save</span>(\$user): <span class="type">bool</span> {
645
+ <span class="keyword">if</span> (<span class="builtin">count</span>(\$this-&gt;users) &gt;= <span class="keyword">self</span>::MAX_USERS) {
646
+ <span class="keyword">throw</span> <span class="keyword">new</span> Exception(<span class="string">'User limit exceeded'</span>);
647
+ }
648
+ \$this-&gt;users[] = \$user;
649
+ <span class="keyword">return</span> <span class="keyword">true</span>;
650
+ }
651
+
652
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">getEmails</span>(): <span class="type">array</span> {
653
+ <span class="keyword">return</span> <span class="builtin">array_map</span>(<span class="keyword">fn</span>(\$u) =&gt; \$u-&gt;getEmail(), \$this-&gt;users);
654
+ }
655
+
656
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">filter</span>(<span class="type">callable</span> \$predicate): <span class="type">array</span> {
657
+ <span class="keyword">return</span> <span class="builtin">array_filter</span>(\$this-&gt;users, \$predicate);
658
+ }
659
+
660
+ <span class="keyword">public</span> <span class="keyword">function</span> <span class="method">map</span>(<span class="type">callable</span> \$fn): <span class="type">array</span> {
661
+ <span class="keyword">return</span> <span class="builtin">array_map</span>(\$fn, \$this-&gt;users);
662
+ }
663
+ }
664
+
665
+ <span class="keyword">?&gt;</span>
666
+ </code></pre>
667
+ </div>
668
+
669
+ <div class="code-sample" id="json">
670
+ <pre><code>
227
671
  {
228
- <span class="string">"name"</span>: <span class="string">"My Theme"</span>,
229
- <span class="string">"version"</span>: <span class="string">"1.0.0"</span>,
672
+ <span class="string">"theme"</span>: {
673
+ <span class="string">"name"</span>: <span class="string">"${themeName}"</span>,
674
+ <span class="string">"version"</span>: <span class="string">"2.0.0"</span>,
675
+ <span class="string">"description"</span>: <span class="string">"Color theme"</span>,
676
+ <span class="string">"author"</span>: <span class="string">"Theme Creator"</span>
677
+ },
230
678
  <span class="string">"colors"</span>: {
231
- <span class="string">"background"</span>: <span class="string">"${interpolated.colors?.["editor.background"] || "#1e1e1e"}"</span>,
232
- <span class="string">"foreground"</span>: <span class="string">"${interpolated.colors?.["editor.foreground"] || "#d4d4d4"}"</span>
679
+ <span class="string">"primary"</span>: {
680
+ <span class="string">"background"</span>: <span class="string">"${interpolated.colors?.["editor.background"] || "#1e1e1e"}"</span>,
681
+ <span class="string">"foreground"</span>: <span class="string">"${interpolated.colors?.["editor.foreground"] || "#d4d4d4"}"</span>,
682
+ <span class="string">"accent"</span>: <span class="string">"${accentColor}"</span>
683
+ }
233
684
  }
234
685
  }
235
- </code>
686
+ </code></pre>
236
687
  </div>
237
688
  </div>
238
689
  </div>
@@ -240,7 +691,17 @@ greet(<span class="string">"Python"</span>)
240
691
  <div class="reload-hint">🔄 Watching for changes...</div>
241
692
 
242
693
  <script>
243
- // Hot-reload on file change
694
+ function switchLanguage(language) {
695
+ document.querySelectorAll('.code-sample').forEach(sample => {
696
+ sample.classList.remove('active');
697
+ });
698
+
699
+ const selected = document.getElementById(language);
700
+ if (selected) {
701
+ selected.classList.add('active');
702
+ }
703
+ }
704
+
244
705
  const ws = new WebSocket(\`ws://\${window.location.host}/ws\`);
245
706
  ws.addEventListener('message', (event) => {
246
707
  if (event.data === 'reload') {