create-aziz-app 3.0.8 → 3.0.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-aziz-app",
3
- "version": "3.0.8",
3
+ "version": "3.0.10",
4
4
  "description": "Create Aziz.js apps — lightweight Next.js clone with file-based routing, React hooks, and API routes",
5
5
  "keywords": [
6
6
  "aziz.js",
@@ -118,15 +118,19 @@ function matchRoute(pattern, pathname) {
118
118
 
119
119
  // Find the best matching route for a pathname
120
120
  function resolveRoute(pathname) {
121
+ // Normalize: treat '' and '/' the same
122
+ const normalized = pathname === '' ? '/' : pathname;
123
+
121
124
  // Exact match first
122
- if (routes[pathname]) {
123
- return { route: routes[pathname], params: {} };
125
+ const exact = routes[normalized];
126
+ if (exact !== undefined) {
127
+ return { route: exact, params: {} };
124
128
  }
125
129
 
126
- // Pattern match
130
+ // Pattern match (dynamic segments like /blog/[slug])
127
131
  for (const pattern in routes) {
128
132
  if (pattern.includes('[')) {
129
- const params = matchRoute(pattern, pathname);
133
+ const params = matchRoute(pattern, normalized);
130
134
  if (params !== null) {
131
135
  return { route: routes[pattern], params };
132
136
  }
@@ -213,6 +217,7 @@ export const router = {
213
217
  // Find matching route
214
218
  const match = resolveRoute(pathname);
215
219
  console.log(`🔍 resolveRoute('${pathname}'):`, match);
220
+ console.log('📦 All registered routes:', Object.keys(routes));
216
221
 
217
222
  if (!match) {
218
223
  root.innerHTML = '';
@@ -266,7 +271,15 @@ export const router = {
266
271
  };
267
272
  }
268
273
 
269
- // Render
274
+ // Render — preserve focus so inputs don't lose cursor on state update
275
+ const activeEl = document.activeElement;
276
+ const activeId = activeEl?.id || null;
277
+ const activeName = activeEl?.getAttribute?.('name') || null;
278
+ const activePlaceholder = activeEl?.getAttribute?.('placeholder') || null;
279
+ const activeTag = activeEl?.tagName || null;
280
+ const activeCursorStart = activeEl?.selectionStart ?? null;
281
+ const activeCursorEnd = activeEl?.selectionEnd ?? null;
282
+
270
283
  root.innerHTML = '';
271
284
  const tree = content();
272
285
  if (Array.isArray(tree)) {
@@ -276,6 +289,24 @@ export const router = {
276
289
  } else if (tree instanceof Node) {
277
290
  root.appendChild(tree);
278
291
  }
292
+
293
+ // Restore focus to the previously active input
294
+ let restored = null;
295
+ if (activeId) {
296
+ restored = root.querySelector(`#${CSS.escape(activeId)}`);
297
+ }
298
+ if (!restored && activeName) {
299
+ restored = root.querySelector(`[name="${activeName}"]`);
300
+ }
301
+ if (!restored && activePlaceholder && activeTag) {
302
+ restored = root.querySelector(`${activeTag.toLowerCase()}[placeholder="${activePlaceholder}"]`);
303
+ }
304
+ if (restored && typeof restored.focus === 'function') {
305
+ restored.focus();
306
+ if (activeCursorStart !== null && restored.setSelectionRange) {
307
+ try { restored.setSelectionRange(activeCursorStart, activeCursorEnd); } catch {}
308
+ }
309
+ }
279
310
  }
280
311
  };
281
312
 
@@ -86,25 +86,34 @@ function buildRouteManifest() {
86
86
  // Transforms: import X from '@/lib/db' → import X from '/lib/db.js'
87
87
 
88
88
  function rewriteImports(code, filePath) {
89
- // Rewrite @/ alias to absolute path
90
- code = code.replace(
91
- /from\s+['"]@\/([^'"]+)['"]/g,
92
- (_, p) => `from '/${p}'`
93
- );
94
-
95
- // Rewrite bare specifiers (not starting with /, ./, ../)
96
- code = code.replace(
97
- /from\s+['"]([^'"./][^'"]*)['"]/g,
98
- (match, specifier) => `from '/_modules/${specifier}'`
99
- );
89
+ // Process line by line — only rewrite actual import/export statements
90
+ // This avoids corrupting string literals that contain import-like syntax
91
+ return code.split('\n').map(line => {
92
+ const trimmed = line.trimStart();
93
+
94
+ // Only process lines that are import or export statements
95
+ if (!trimmed.startsWith('import ') && !trimmed.startsWith('export ')) {
96
+ return line;
97
+ }
100
98
 
101
- // Same for dynamic imports
102
- code = code.replace(
103
- /import\s*\(\s*['"]([^'"./][^'"]*)['"]\s*\)/g,
99
+ // Rewrite @/ alias → absolute path
100
+ line = line.replace(
101
+ /from\s+['"]@\/([^'"]+)['"]/g,
102
+ (_, p) => `from '/${p}'`
103
+ );
104
+
105
+ // Rewrite bare specifiers (not starting with /, ./, ../)
106
+ line = line.replace(
107
+ /from\s+['"]([^'"./][^'"]*)['"]/g,
108
+ (_, specifier) => `from '/_modules/${specifier}'`
109
+ );
110
+
111
+ return line;
112
+ }).join('\n').replace(
113
+ // Dynamic imports can appear anywhere — but only rewrite bare specifiers
114
+ /\bimport\s*\(\s*['"]([^'"./][^'"]*)['"]\s*\)/g,
104
115
  (_, specifier) => `import('/_modules/${specifier}')`
105
116
  );
106
-
107
- return code;
108
117
  }
109
118
 
110
119
  // ─── Module Resolver ─────────────────────────────────────────