@ynor/ynor 1.0.2 → 1.0.3

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 CHANGED
@@ -14,3 +14,98 @@ A lightweight, next-generation JavaScript extension framework inspired by Svelte
14
14
  - **🌐 Cross-browser**: Works in all modern browsers
15
15
 
16
16
  ## Project Structure
17
+
18
+
19
+ `📁 ynor/
20
+ ├── 📁 .svelte-kit/
21
+ │ ├── 📁 generated/
22
+ │ │ ├── 📁 client/
23
+ │ │ │ ├── 📁 nodes/
24
+ │ │ │ │ ├── 📄 0.js [.js] (1 lines)
25
+ │ │ │ │ ├── 📄 1.js [.js] (1 lines)
26
+ │ │ │ │ └── 📄 2.js [.js] (1 lines)
27
+ │ │ │ ├── 📄 app.js [.js] (39 lines)
28
+ │ │ │ └── 📄 matchers.js [.js] (1 lines)
29
+ │ │ ├── 📁 server/
30
+ │ │ │ └── 📄 internal.js [.js] (56 lines)
31
+ │ │ ├── 📁 shared/
32
+ │ │ │ └── 📄 error-template.js [.js] (1 lines)
33
+ │ │ ├── 📄 root.js [.js] (3 lines)
34
+ │ │ └── 📄 root.svelte [.svelte] (68 lines)
35
+ │ ├── 📁 types/
36
+ │ │ ├── 📁 src/
37
+ │ │ │ └── 📁 routes/
38
+ │ │ │ └── 📄 $types.d.ts [.ts] (23 lines)
39
+ │ │ └── 📄 route_meta_data.json [.json] (3 lines)
40
+ │ ├── 📄 ambient.d.ts [.ts] (361 lines)
41
+ │ ├── 📄 env.d.ts [.ts] (1 lines)
42
+ │ ├── 📄 non-ambient.d.ts [.ts] (43 lines)
43
+ │ └── 📄 tsconfig.json [.json] (56 lines)
44
+ ├── 📁 .vscode/
45
+ │ └── 📄 extensions.json [.json] (4 lines)
46
+ ├── 📁 scripts/
47
+ │ ├── 📄 gen_readme.js [.js] (473 lines)
48
+ │ ├── 📄 gen_tree.cjs [.cjs]
49
+ │ ├── 📄 git_init.js [.js] (508 lines)
50
+ │ └── 📄 git_update.js [.js] (565 lines)
51
+ ├── 📁 src/
52
+ │ ├── 📁 lib/
53
+ │ │ ├── 📁 assets/
54
+ │ │ │ ├── 📄 favicon.ico [.ico]
55
+ │ │ │ └── 📄 logo.png [.png]
56
+ │ │ ├── 📁 components/
57
+ │ │ │ ├── 📄 Counter.ynor [.ynor]
58
+ │ │ │ ├── 📄 MyComponent.ynor [.ynor]
59
+ │ │ │ └── 📄 TodoList.ynor [.ynor]
60
+ │ │ └── 📁 core/
61
+ │ │ ├── 📄 compiler.d.ts [.ts] (294 lines)
62
+ │ │ ├── 📄 compiler.js [.js] (842 lines)
63
+ │ │ ├── 📄 index.js [.js] (43 lines)
64
+ │ │ ├── 📄 plugin.js [.js] (109 lines)
65
+ │ │ └── 📄 runtime.js [.js] (102 lines)
66
+ │ ├── 📁 routes/
67
+ │ │ ├── 📄 +layout.svelte [.svelte] (22 lines)
68
+ │ │ └── 📄 +page.svelte [.svelte] (54 lines)
69
+ │ ├── 📁 styles/
70
+ │ │ └── 📄 global.css [.css] (57 lines)
71
+ │ ├── 📄 app.d.ts [.ts] (14 lines)
72
+ │ ├── 📄 App.ynor [.ynor]
73
+ │ └── 📄 main.js [.js] (28 lines)
74
+ ├── 📁 static/
75
+ │ ├── 📄 favicon.ico [.ico]
76
+ │ ├── 📄 logo.png [.png]
77
+ │ └── 📄 robots.txt [.txt] (4 lines)
78
+ ├── 📄 .gitignore [(no extension)]
79
+ ├── 📄 .npmrc [(no extension)]
80
+ ├── 📄 index.html [.html] (30 lines)
81
+ ├── 📄 jsconfig.json [.json] (20 lines)
82
+ ├── 📄 package.json [.json] (53 lines)
83
+ ├── 📄 README.md [.md] (17 lines)
84
+ ├── 📄 svelte.config.js [.js] (15 lines)
85
+ ├── 📄 vite.config.js [.js] (27 lines)
86
+ └── 📄 ynor.config.js [.js] (23 lines)
87
+
88
+ 📊 SUMMARY
89
+ ===========
90
+ Total Directories: 19
91
+ Total Files: 48
92
+ Total Lines of Code: 3962
93
+
94
+ 📈 FILE EXTENSIONS
95
+ ==================
96
+ .js: 19 files
97
+ .ts: 6 files
98
+ .json: 5 files
99
+ .ynor: 4 files
100
+ .svelte: 3 files
101
+ no extension: 2 files
102
+ .ico: 2 files
103
+ .png: 2 files
104
+ .html: 1 file
105
+ .md: 1 file
106
+ .cjs: 1 file
107
+ .css: 1 file
108
+ .txt: 1 file
109
+
110
+ Generated: 29/06/2026, 11:57:18 am
111
+ `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynor/ynor",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "⚡ Lightweight next-gen JS extension framework like Svelte",
5
5
  "type": "module",
6
6
  "main": "./src/lib/core/index.js",
@@ -26,7 +26,7 @@
26
26
  "ynor": "./bin/ynor.js"
27
27
  },
28
28
  "files": [
29
- "src/lib/core/",
29
+ "src/",
30
30
  "bin/",
31
31
  "README.md",
32
32
  "LICENSE",
package/src/App.ynor ADDED
@@ -0,0 +1,67 @@
1
+ <!-- src/App.ynor -->
2
+ <script>
3
+ // Define variables on 'this'
4
+ this.count = 0;
5
+
6
+ // Define function - make sure it's properly bound
7
+ this.increment = function() {
8
+ this.count = this.count + 1;
9
+ console.log('Count:', this.count);
10
+ this._update();
11
+ };
12
+
13
+ console.log('🔧 App.ynor script loaded');
14
+ console.log('🔧 this.increment:', this.increment);
15
+ </script>
16
+
17
+ <style>
18
+ .app {
19
+ padding: 40px;
20
+ text-align: center;
21
+ font-family: system-ui, sans-serif;
22
+ background: white;
23
+ border-radius: 20px;
24
+ max-width: 600px;
25
+ margin: 20px auto;
26
+ box-shadow: 0 8px 30px rgba(0,0,0,0.08);
27
+ }
28
+ .app h1 {
29
+ color: #4f46e5;
30
+ font-size: 2.5rem;
31
+ margin-bottom: 10px;
32
+ }
33
+ .app p {
34
+ font-size: 1.2rem;
35
+ color: #1e293b;
36
+ }
37
+ .count {
38
+ font-size: 3rem;
39
+ font-weight: 700;
40
+ color: #4f46e5;
41
+ margin: 20px 0;
42
+ }
43
+ .app button {
44
+ padding: 10px 24px;
45
+ border: none;
46
+ border-radius: 40px;
47
+ background: #4f46e5;
48
+ color: white;
49
+ font-weight: 600;
50
+ cursor: pointer;
51
+ font-size: 16px;
52
+ transition: all 0.2s;
53
+ }
54
+ .app button:hover {
55
+ background: #4338ca;
56
+ transform: scale(1.02);
57
+ }
58
+ </style>
59
+
60
+ <template>
61
+ <div class="app">
62
+ <h1>⚡ .ynor</h1>
63
+ <p>Framework is working!</p>
64
+ <div class="count">{count}</div>
65
+ <button on:click={increment}>Increment</button>
66
+ </div>
67
+ </template>
package/src/app.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ // See https://svelte.dev/docs/kit/types#app.d.ts
2
+ // for information about these interfaces
3
+ declare global {
4
+ namespace App {
5
+ // interface Error {}
6
+ // interface Locals {}
7
+ // interface PageData {}
8
+ // interface PageState {}
9
+ // interface Platform {}
10
+ }
11
+ }
12
+
13
+ export {};
Binary file
Binary file
@@ -0,0 +1,117 @@
1
+ <!-- src/components/Counter.ynor -->
2
+ <script>
3
+ let count = 0;
4
+ let step = 1;
5
+
6
+ // Reactive statement
7
+ $: console.log(`Count is now: ${count}`);
8
+
9
+ function increment() {
10
+ count += step;
11
+ }
12
+
13
+ function decrement() {
14
+ count -= step;
15
+ }
16
+
17
+ function reset() {
18
+ count = 0;
19
+ }
20
+
21
+ export function setCount(value) {
22
+ count = value;
23
+ }
24
+ </script>
25
+
26
+ <style>
27
+ .counter-container {
28
+ background: white;
29
+ border-radius: 20px;
30
+ padding: 30px;
31
+ box-shadow: 0 8px 30px rgba(0,0,0,0.08);
32
+ text-align: center;
33
+ }
34
+
35
+ .counter-number {
36
+ font-size: 4rem;
37
+ font-weight: 700;
38
+ margin: 20px 0;
39
+ color: #4f46e5;
40
+ }
41
+
42
+ .counter-controls {
43
+ display: flex;
44
+ gap: 12px;
45
+ justify-content: center;
46
+ flex-wrap: wrap;
47
+ }
48
+
49
+ .counter-controls button {
50
+ padding: 10px 24px;
51
+ border: none;
52
+ border-radius: 40px;
53
+ font-weight: 600;
54
+ cursor: pointer;
55
+ transition: all 0.2s;
56
+ }
57
+
58
+ .btn-primary {
59
+ background: #4f46e5;
60
+ color: white;
61
+ box-shadow: 0 4px 12px rgba(79,70,229,0.25);
62
+ }
63
+
64
+ .btn-secondary {
65
+ background: #e2e8f0;
66
+ color: #1e293b;
67
+ }
68
+
69
+ .btn-primary:hover, .btn-secondary:hover {
70
+ transform: scale(1.05);
71
+ }
72
+
73
+ .step-control {
74
+ margin-top: 20px;
75
+ display: flex;
76
+ align-items: center;
77
+ gap: 16px;
78
+ justify-content: center;
79
+ }
80
+
81
+ .step-control input[type="range"] {
82
+ width: 200px;
83
+ }
84
+
85
+ .badge {
86
+ background: #eef2ff;
87
+ color: #4f46e5;
88
+ padding: 4px 16px;
89
+ border-radius: 40px;
90
+ font-size: 0.9rem;
91
+ font-weight: 500;
92
+ }
93
+ </style>
94
+
95
+ <template>
96
+ <div class="counter-container">
97
+ <h2>Counter</h2>
98
+ <div class="counter-number">{count}</div>
99
+
100
+ <div class="counter-controls">
101
+ <button class="btn-secondary" on:click={decrement}>-</button>
102
+ <button class="btn-primary" on:click={increment}>+</button>
103
+ <button class="btn-secondary" on:click={reset}>Reset</button>
104
+ </div>
105
+
106
+ <div class="step-control">
107
+ <span>Step:</span>
108
+ <input
109
+ type="range"
110
+ min="1"
111
+ max="10"
112
+ bind:value={step}
113
+ />
114
+ <span class="badge">+{step}</span>
115
+ </div>
116
+ </div>
117
+ </template>
@@ -0,0 +1,24 @@
1
+ <!-- src/components/MyComponent.ynor -->
2
+ <script>
3
+ let count = 0;
4
+ $: console.log(`Count: ${count}`);
5
+
6
+ function increment() {
7
+ count++;
8
+ }
9
+ </script>
10
+
11
+ <style>
12
+ .my-component {
13
+ padding: 20px;
14
+ background: white;
15
+ border-radius: 10px;
16
+ }
17
+ </style>
18
+
19
+ <template>
20
+ <div class="my-component">
21
+ <h2>Count: {count}</h2>
22
+ <button on:click={increment}>+</button>
23
+ </div>
24
+ </template>
@@ -0,0 +1,241 @@
1
+ <!-- src/components/TodoList.ynor -->
2
+ <script>
3
+ import { store } from '../lib/runtime.js';
4
+
5
+ let newTodo = '';
6
+ let filter = 'all';
7
+ let todos = [];
8
+
9
+ // Get store
10
+ const todosStore = store('todos', []);
11
+
12
+ // Subscribe to store
13
+ todosStore.subscribe(value => {
14
+ todos = value;
15
+ });
16
+
17
+ function addTodo() {
18
+ if (!newTodo.trim()) return;
19
+ const newTodos = [...todos, {
20
+ id: Date.now(),
21
+ text: newTodo.trim(),
22
+ done: false
23
+ }];
24
+ todosStore.set(newTodos);
25
+ newTodo = '';
26
+ }
27
+
28
+ function toggleTodo(id) {
29
+ const newTodos = todos.map(t =>
30
+ t.id === id ? { ...t, done: !t.done } : t
31
+ );
32
+ todosStore.set(newTodos);
33
+ }
34
+
35
+ function deleteTodo(id) {
36
+ const newTodos = todos.filter(t => t.id !== id);
37
+ todosStore.set(newTodos);
38
+ }
39
+
40
+ function getFilteredTodos() {
41
+ if (filter === 'active') return todos.filter(t => !t.done);
42
+ if (filter === 'done') return todos.filter(t => t.done);
43
+ return todos;
44
+ }
45
+
46
+ function getStats() {
47
+ const total = todos.length;
48
+ const done = todos.filter(t => t.done).length;
49
+ return { total, done };
50
+ }
51
+ </script>
52
+
53
+ <style>
54
+ .todo-container {
55
+ background: white;
56
+ border-radius: 20px;
57
+ padding: 30px;
58
+ box-shadow: 0 8px 30px rgba(0,0,0,0.08);
59
+ }
60
+
61
+ .todo-header {
62
+ display: flex;
63
+ justify-content: space-between;
64
+ align-items: center;
65
+ margin-bottom: 20px;
66
+ }
67
+
68
+ .todo-stats {
69
+ color: #64748b;
70
+ font-size: 0.9rem;
71
+ }
72
+
73
+ .todo-input {
74
+ display: flex;
75
+ gap: 12px;
76
+ margin-bottom: 20px;
77
+ }
78
+
79
+ .todo-input input {
80
+ flex: 1;
81
+ padding: 10px 18px;
82
+ border: 2px solid #e2e8f0;
83
+ border-radius: 40px;
84
+ font-size: 1rem;
85
+ outline: none;
86
+ transition: all 0.2s;
87
+ }
88
+
89
+ .todo-input input:focus {
90
+ border-color: #4f46e5;
91
+ box-shadow: 0 0 0 4px rgba(79,70,229,0.15);
92
+ }
93
+
94
+ .todo-input button {
95
+ padding: 10px 24px;
96
+ border: none;
97
+ border-radius: 40px;
98
+ background: #4f46e5;
99
+ color: white;
100
+ font-weight: 600;
101
+ cursor: pointer;
102
+ transition: all 0.2s;
103
+ }
104
+
105
+ .todo-input button:hover {
106
+ background: #4338ca;
107
+ transform: scale(1.02);
108
+ }
109
+
110
+ .todo-filters {
111
+ display: flex;
112
+ gap: 8px;
113
+ margin-bottom: 20px;
114
+ }
115
+
116
+ .todo-filters button {
117
+ padding: 6px 16px;
118
+ border: none;
119
+ border-radius: 40px;
120
+ background: #e2e8f0;
121
+ color: #1e293b;
122
+ cursor: pointer;
123
+ transition: all 0.2s;
124
+ font-size: 0.9rem;
125
+ }
126
+
127
+ .todo-filters button.active {
128
+ background: #4f46e5;
129
+ color: white;
130
+ }
131
+
132
+ .todo-item {
133
+ display: flex;
134
+ align-items: center;
135
+ justify-content: space-between;
136
+ padding: 10px 0;
137
+ border-bottom: 1px solid #f1f5f9;
138
+ }
139
+
140
+ .todo-item:last-child {
141
+ border-bottom: none;
142
+ }
143
+
144
+ .todo-item-left {
145
+ display: flex;
146
+ align-items: center;
147
+ gap: 12px;
148
+ }
149
+
150
+ .todo-item input[type="checkbox"] {
151
+ width: 20px;
152
+ height: 20px;
153
+ cursor: pointer;
154
+ }
155
+
156
+ .todo-item .todo-text {
157
+ font-size: 1rem;
158
+ }
159
+
160
+ .todo-item .todo-text.done {
161
+ text-decoration: line-through;
162
+ color: #94a3b8;
163
+ }
164
+
165
+ .todo-item .delete-btn {
166
+ padding: 4px 12px;
167
+ border: none;
168
+ border-radius: 40px;
169
+ background: #fee2e2;
170
+ color: #dc2626;
171
+ cursor: pointer;
172
+ transition: all 0.2s;
173
+ font-size: 0.8rem;
174
+ }
175
+
176
+ .todo-item .delete-btn:hover {
177
+ background: #fecaca;
178
+ }
179
+
180
+ .todo-empty {
181
+ text-align: center;
182
+ color: #94a3b8;
183
+ padding: 20px 0;
184
+ }
185
+ </style>
186
+
187
+ <template>
188
+ <div class="todo-container">
189
+ <div class="todo-header">
190
+ <h2>Todo List</h2>
191
+ <span class="todo-stats">{getStats().done} / {getStats().total} done</span>
192
+ </div>
193
+
194
+ <div class="todo-input">
195
+ <input
196
+ type="text"
197
+ placeholder="Add a new task..."
198
+ bind:value={newTodo}
199
+ on:keydown={(e) => e.key === 'Enter' && addTodo()}
200
+ />
201
+ <button on:click={addTodo}>Add</button>
202
+ </div>
203
+
204
+ <div class="todo-filters">
205
+ {#each ['all', 'active', 'done'] as f}
206
+ <button
207
+ class:active={filter === f}
208
+ on:click={() => filter = f}
209
+ >
210
+ {f.toUpperCase()}
211
+ </button>
212
+ {/each}
213
+ </div>
214
+
215
+ <div class="todo-list">
216
+ {#each getFilteredTodos() as todo}
217
+ <div class="todo-item">
218
+ <div class="todo-item-left">
219
+ <input
220
+ type="checkbox"
221
+ checked={todo.done}
222
+ on:change={() => toggleTodo(todo.id)}
223
+ />
224
+ <span class:done={todo.done} class="todo-text">
225
+ {todo.text}
226
+ </span>
227
+ </div>
228
+ <button class="delete-btn" on:click={() => deleteTodo(todo.id)}>
229
+ ✕
230
+ </button>
231
+ </div>
232
+ {/each}
233
+
234
+ {#if getFilteredTodos().length === 0}
235
+ <div class="todo-empty">
236
+ No tasks in this filter
237
+ </div>
238
+ {/if}
239
+ </div>
240
+ </div>
241
+ </template>
@@ -3,7 +3,7 @@ import { VERSION, YnorCompiler, AST } from './compiler.js';
3
3
  import { YnorRuntime, YnorComponent, runtime, store, mount } from './runtime.js';
4
4
  import { ynorPlugin } from './plugin.js';
5
5
 
6
- // Error handling utilities
6
+ // Error handling utilities - FIXED PATH
7
7
  import {
8
8
  YnorError,
9
9
  YnorCompilerError,
@@ -14,10 +14,7 @@ import {
14
14
  warn,
15
15
  info,
16
16
  success
17
- } from './utils/errors.js';
18
-
19
- // CLI utilities
20
- import { createProject, buildProject, devProject } from './cli.js';
17
+ } from '../utils/errors.js'; // Changed from './src/utils/errors.js' to '../utils/errors.js'
21
18
 
22
19
  // Export everything
23
20
  export {
@@ -38,10 +35,7 @@ export {
38
35
  handleError,
39
36
  warn,
40
37
  info,
41
- success,
42
- createProject,
43
- buildProject,
44
- devProject
38
+ success
45
39
  };
46
40
 
47
41
  // Default export
package/src/main.js ADDED
@@ -0,0 +1,44 @@
1
+ // src/main.js
2
+ import { runtime, mount, store } from './lib/core/runtime.js';
3
+ import App from './App.ynor';
4
+
5
+ console.log('🚀 Starting .ynor application...');
6
+
7
+ // Initialize stores (not using export inside try)
8
+ const todos = store('todos', [
9
+ { id: 1, text: 'Learn .ynor', done: true },
10
+ { id: 2, text: 'Build something great', done: false },
11
+ { id: 3, text: 'Share with community', done: false }
12
+ ]);
13
+
14
+ console.log('đŸ“Ļ Store initialized:', todos.get());
15
+
16
+ // Mount app with error handling
17
+ try {
18
+ const app = mount(App, document.getElementById('app'), {
19
+ todos: todos
20
+ });
21
+
22
+ console.log('⚡ .ynor framework initialized');
23
+ console.log('📁 Components loaded:', Array.from(runtime.components.keys()));
24
+
25
+ // Export for HMR
26
+ if (import.meta.hot) {
27
+ import.meta.hot.accept('./App.ynor', ({ default: NewApp }) => {
28
+ app.$destroy();
29
+ mount(NewApp, document.getElementById('app'), { todos });
30
+ });
31
+ }
32
+ } catch (error) {
33
+ console.error('❌ Error starting .ynor application:', error);
34
+ document.getElementById('app').innerHTML = `
35
+ <div style="color: red; padding: 20px; font-family: system-ui;">
36
+ <h2>Error loading .ynor app</h2>
37
+ <pre style="background: #f1f1f1; padding: 10px; border-radius: 5px; overflow: auto;">${error.message}</pre>
38
+ <p>Check console for details</p>
39
+ </div>
40
+ `;
41
+ }
42
+
43
+ // Export todos for use in other modules if needed
44
+ export { todos };
@@ -0,0 +1,22 @@
1
+ <!-- src/routes/+layout.svelte -->
2
+ <script>
3
+ import '../styles/global.css';
4
+ </script>
5
+
6
+ <slot />
7
+
8
+ <style>
9
+ /* Global layout styles */
10
+ :global(*) {
11
+ box-sizing: border-box;
12
+ margin: 0;
13
+ padding: 0;
14
+ }
15
+
16
+ :global(body) {
17
+ font-family: system-ui, -apple-system, sans-serif;
18
+ background: #f5f7fb;
19
+ color: #1e293b;
20
+ line-height: 1.6;
21
+ }
22
+ </style>
@@ -0,0 +1,54 @@
1
+ <!-- src/routes/+page.svelte -->
2
+ <script>
3
+ import { onMount } from 'svelte';
4
+ import { mount } from '$lib/core/runtime.js';
5
+ import Counter from '$lib/components/Counter.ynor';
6
+ import TodoList from '$lib/components/TodoList.ynor';
7
+
8
+ let counterInstance;
9
+ let todoInstance;
10
+
11
+ onMount(() => {
12
+ // Mount .ynor components in SvelteKit
13
+ const counterContainer = document.getElementById('counter-container');
14
+ const todoContainer = document.getElementById('todo-container');
15
+
16
+ if (counterContainer) {
17
+ counterInstance = mount(Counter, counterContainer);
18
+ }
19
+
20
+ if (todoContainer) {
21
+ todoInstance = mount(TodoList, todoContainer);
22
+ }
23
+
24
+ return () => {
25
+ if (counterInstance) counterInstance.$destroy();
26
+ if (todoInstance) todoInstance.$destroy();
27
+ };
28
+ });
29
+ </script>
30
+
31
+ <div class="container">
32
+ <h1>Welcome to .ynor + SvelteKit</h1>
33
+
34
+ <div id="counter-container"></div>
35
+ <div id="todo-container"></div>
36
+ </div>
37
+
38
+ <style>
39
+ .container {
40
+ max-width: 1200px;
41
+ margin: 0 auto;
42
+ padding: 20px;
43
+ }
44
+
45
+ h1 {
46
+ color: #4f46e5;
47
+ margin-bottom: 30px;
48
+ }
49
+
50
+ #counter-container,
51
+ #todo-container {
52
+ margin: 20px 0;
53
+ }
54
+ </style>
@@ -0,0 +1,57 @@
1
+ /* src/styles/global.css */
2
+ * {
3
+ box-sizing: border-box;
4
+ margin: 0;
5
+ padding: 0;
6
+ }
7
+
8
+ body {
9
+ font-family: system-ui, -apple-system, sans-serif;
10
+ background: #f5f7fb;
11
+ color: #1e293b;
12
+ line-height: 1.6;
13
+ }
14
+
15
+ #app {
16
+ min-height: 100vh;
17
+ padding: 20px;
18
+ }
19
+
20
+ /* Utility classes */
21
+ .container {
22
+ max-width: 1200px;
23
+ margin: 0 auto;
24
+ padding: 0 20px;
25
+ }
26
+
27
+ .text-center {
28
+ text-align: center;
29
+ }
30
+
31
+ .mt-4 {
32
+ margin-top: 2rem;
33
+ }
34
+
35
+ .mb-4 {
36
+ margin-bottom: 2rem;
37
+ }
38
+
39
+ /* Scrollbar styling */
40
+ ::-webkit-scrollbar {
41
+ width: 8px;
42
+ height: 8px;
43
+ }
44
+
45
+ ::-webkit-scrollbar-track {
46
+ background: #f1f1f1;
47
+ border-radius: 10px;
48
+ }
49
+
50
+ ::-webkit-scrollbar-thumb {
51
+ background: #cbd5e1;
52
+ border-radius: 10px;
53
+ }
54
+
55
+ ::-webkit-scrollbar-thumb:hover {
56
+ background: #94a3b8;
57
+ }
@@ -0,0 +1,115 @@
1
+ // src/utils/errors.js
2
+ import chalk from 'chalk';
3
+
4
+ export class YnorError extends Error {
5
+ constructor(message, code, details = {}) {
6
+ super(message);
7
+ this.name = 'YnorError';
8
+ this.code = code;
9
+ this.details = details;
10
+ Error.captureStackTrace(this, this.constructor);
11
+ }
12
+
13
+ toString() {
14
+ return `${chalk.red('❌')} ${chalk.bold(this.code)}: ${this.message}`;
15
+ }
16
+ }
17
+
18
+ export class YnorCompilerError extends YnorError {
19
+ constructor(message, details = {}) {
20
+ super(message, 'COMPILER_ERROR', details);
21
+ this.name = 'YnorCompilerError';
22
+ }
23
+ }
24
+
25
+ export class YnorRuntimeError extends YnorError {
26
+ constructor(message, details = {}) {
27
+ super(message, 'RUNTIME_ERROR', details);
28
+ this.name = 'YnorRuntimeError';
29
+ }
30
+ }
31
+
32
+ export class YnorTemplateError extends YnorError {
33
+ constructor(message, details = {}) {
34
+ super(message, 'TEMPLATE_ERROR', details);
35
+ this.name = 'YnorTemplateError';
36
+ }
37
+ }
38
+
39
+ export class YnorComponentError extends YnorError {
40
+ constructor(message, details = {}) {
41
+ super(message, 'COMPONENT_ERROR', details);
42
+ this.name = 'YnorComponentError';
43
+ }
44
+ }
45
+
46
+ export function handleError(error, context = {}) {
47
+ console.error('');
48
+ if (error instanceof YnorError) {
49
+ console.error(chalk.red(' âš ī¸ ') + chalk.bold(error.code));
50
+ console.error(chalk.dim(' ──────────────────────────────'));
51
+ console.error(' ' + error.message);
52
+
53
+ if (error.details && Object.keys(error.details).length > 0) {
54
+ console.error(chalk.dim('\n 📋 Details:'));
55
+ Object.entries(error.details).forEach(([key, value]) => {
56
+ console.error(` ${chalk.dim(key)}: ${value}`);
57
+ });
58
+ }
59
+
60
+ if (context.file) {
61
+ console.error(chalk.dim(`\n 📁 File: ${context.file}`));
62
+ }
63
+ if (context.line) {
64
+ console.error(chalk.dim(` 📍 Line: ${context.line}`));
65
+ }
66
+ } else {
67
+ console.error(chalk.red(' ❌ ') + chalk.bold('Unexpected Error'));
68
+ console.error(chalk.dim(' ──────────────────────────────'));
69
+ console.error(' ' + error.message);
70
+ if (error.stack) {
71
+ console.error(chalk.dim('\n 📚 Stack Trace:'));
72
+ console.error(error.stack.split('\n').slice(1, 5).join('\n'));
73
+ }
74
+ }
75
+ console.error('');
76
+ }
77
+
78
+ export function warn(message, details = {}) {
79
+ console.warn(chalk.yellow(' âš ī¸ ') + chalk.bold('Warning'));
80
+ console.warn(chalk.dim(' ──────────────────────────────'));
81
+ console.warn(' ' + message);
82
+ if (Object.keys(details).length > 0) {
83
+ console.warn(chalk.dim('\n 📋 Details:'));
84
+ Object.entries(details).forEach(([key, value]) => {
85
+ console.warn(` ${chalk.dim(key)}: ${value}`);
86
+ });
87
+ }
88
+ console.warn('');
89
+ }
90
+
91
+ export function info(message, details = {}) {
92
+ console.log(chalk.blue(' â„šī¸ ') + chalk.bold('Info'));
93
+ console.log(chalk.dim(' ──────────────────────────────'));
94
+ console.log(' ' + message);
95
+ if (Object.keys(details).length > 0) {
96
+ console.log(chalk.dim('\n 📋 Details:'));
97
+ Object.entries(details).forEach(([key, value]) => {
98
+ console.log(` ${chalk.dim(key)}: ${value}`);
99
+ });
100
+ }
101
+ console.log('');
102
+ }
103
+
104
+ export function success(message, details = {}) {
105
+ console.log(chalk.green(' ✅ ') + chalk.bold('Success'));
106
+ console.log(chalk.dim(' ──────────────────────────────'));
107
+ console.log(' ' + message);
108
+ if (Object.keys(details).length > 0) {
109
+ console.log(chalk.dim('\n 📋 Details:'));
110
+ Object.entries(details).forEach(([key, value]) => {
111
+ console.log(` ${chalk.dim(key)}: ${value}`);
112
+ });
113
+ }
114
+ console.log('');
115
+ }