@ozsarman/clarityjs 0.6.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.
- package/README.md +178 -0
- package/package.json +168 -0
- package/src/analyze.js +534 -0
- package/src/async-state.js +555 -0
- package/src/bundle-runtime.js +35 -0
- package/src/clarity-bundle.js +332 -0
- package/src/clarity-test.js +622 -0
- package/src/cli.js +453 -0
- package/src/codegen.js +1934 -0
- package/src/dev-server.js +362 -0
- package/src/devtools.js +765 -0
- package/src/edge.js +606 -0
- package/src/error-overlay.js +535 -0
- package/src/file-conventions.js +472 -0
- package/src/font.js +513 -0
- package/src/game-loop.js +106 -0
- package/src/head.js +393 -0
- package/src/hydrate.js +292 -0
- package/src/i18n.js +403 -0
- package/src/image.js +352 -0
- package/src/index.js +193 -0
- package/src/islands.js +284 -0
- package/src/isr.js +306 -0
- package/src/layout.js +342 -0
- package/src/lexer.js +572 -0
- package/src/linter.js +547 -0
- package/src/pages-router.js +229 -0
- package/src/parser.js +1108 -0
- package/src/router.js +732 -0
- package/src/runtime.js +1465 -0
- package/src/scoped-css.js +641 -0
- package/src/server-actions.js +439 -0
- package/src/server-data.js +225 -0
- package/src/sourcemap.js +130 -0
- package/src/ssg.js +310 -0
- package/src/ssr.js +621 -0
- package/src/store.js +276 -0
- package/src/transitions.js +438 -0
- package/src/ts-plugin.js +613 -0
- package/src/typegen.js +240 -0
- package/src/vite-plugin.js +447 -0
- package/types/index.d.ts +366 -0
package/src/image.js
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clarity.js — Image Optimization
|
|
3
|
+
*
|
|
4
|
+
* next/image / @nuxt/image eşdeğeri.
|
|
5
|
+
* Responsive srcset, lazy loading, blur placeholder, CLS önleme, WebP/AVIF.
|
|
6
|
+
*
|
|
7
|
+
* ── Clarity şablonunda kullanım ───────────────────────────────────────────────
|
|
8
|
+
*
|
|
9
|
+
* import { ClarityImage } from '@ozsarman/clarityjs/image'
|
|
10
|
+
*
|
|
11
|
+
* component Hero() {
|
|
12
|
+
* render {
|
|
13
|
+
* { ClarityImage({
|
|
14
|
+
* src: '/images/hero.jpg',
|
|
15
|
+
* alt: 'Hero görseli',
|
|
16
|
+
* width: 1200,
|
|
17
|
+
* height: 600,
|
|
18
|
+
* priority: true, // LCP görüntüsü — hemen yükle
|
|
19
|
+
* sizes: '100vw',
|
|
20
|
+
* }) }
|
|
21
|
+
*
|
|
22
|
+
* { ClarityImage({
|
|
23
|
+
* src: '/images/avatar.jpg',
|
|
24
|
+
* alt: 'Profil fotoğrafı',
|
|
25
|
+
* width: 80,
|
|
26
|
+
* height: 80,
|
|
27
|
+
* quality: 80,
|
|
28
|
+
* placeholder: 'blur',
|
|
29
|
+
* blurDataURL: 'data:image/jpeg;base64,...',
|
|
30
|
+
* }) }
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* ── Vite plugin entegrasyonu (otomatik) ──────────────────────────────────────
|
|
35
|
+
*
|
|
36
|
+
* clarityPlugin({ imageOptimization: true })
|
|
37
|
+
* // Build sırasında: görüntüleri WebP'ye çevirir, birden fazla boyut üretir
|
|
38
|
+
* // Dev: orijinal görüntüyü döndürür
|
|
39
|
+
*
|
|
40
|
+
* ── Loader API (özel CDN) ─────────────────────────────────────────────────────
|
|
41
|
+
*
|
|
42
|
+
* import { setImageLoader } from '@ozsarman/clarityjs/image'
|
|
43
|
+
*
|
|
44
|
+
* setImageLoader(({ src, width, quality }) =>
|
|
45
|
+
* `https://cdn.example.com/${src}?w=${width}&q=${quality}&fmt=webp`
|
|
46
|
+
* );
|
|
47
|
+
*
|
|
48
|
+
* Author: Claude (Anthropic) + Özdemir Sarman
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
// ─── Varsayılan görüntü boyutları (responsive breakpoints) ───────────────────
|
|
52
|
+
|
|
53
|
+
const DEFAULT_SIZES = [16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840];
|
|
54
|
+
const DEVICE_SIZES = [640, 750, 828, 1080, 1200, 1920, 2048, 3840];
|
|
55
|
+
const IMAGE_SIZES = [16, 32, 48, 64, 96, 128, 256, 384];
|
|
56
|
+
|
|
57
|
+
// ─── Loader ───────────────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
let _loader = null;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Özel görüntü URL oluşturucu tanımla (CDN entegrasyonu için).
|
|
63
|
+
*
|
|
64
|
+
* @param {Function} loaderFn – ({ src, width, quality, format }) => string
|
|
65
|
+
*/
|
|
66
|
+
export function setImageLoader(loaderFn) {
|
|
67
|
+
_loader = loaderFn;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function _buildUrl(src, width, quality = 75, format = 'webp') {
|
|
71
|
+
if (_loader) return _loader({ src, width, quality, format });
|
|
72
|
+
|
|
73
|
+
// Varsayılan: Clarity image endpoint (geliştirme sunucusu + production)
|
|
74
|
+
if (src.startsWith('http://') || src.startsWith('https://')) {
|
|
75
|
+
// Harici URL — optimize edilemez, doğrudan döndür
|
|
76
|
+
return src;
|
|
77
|
+
}
|
|
78
|
+
return `/_clarity/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality}&fmt=${format}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ─── ClarityImage runtime component ──────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Optimize edilmiş görüntü elementi oluştur.
|
|
85
|
+
*
|
|
86
|
+
* @param {object} props
|
|
87
|
+
* @param {string} props.src – görüntü yolu (zorunlu)
|
|
88
|
+
* @param {string} props.alt – erişilebilirlik metni (zorunlu)
|
|
89
|
+
* @param {number} props.width – görüntü genişliği px (zorunlu — CLS önleme)
|
|
90
|
+
* @param {number} props.height – görüntü yüksekliği px (zorunlu — CLS önleme)
|
|
91
|
+
* @param {string} [props.sizes] – CSS sizes değeri (örn: '(max-width: 768px) 100vw, 50vw')
|
|
92
|
+
* @param {number} [props.quality=75] – sıkıştırma kalitesi 1-100
|
|
93
|
+
* @param {boolean} [props.priority] – LCP görüntüsü: preload ekle, lazy yükleme kapat
|
|
94
|
+
* @param {string} [props.placeholder] – 'blur' | 'empty' (default: 'empty')
|
|
95
|
+
* @param {string} [props.blurDataURL] – base64 blur placeholder
|
|
96
|
+
* @param {string} [props.className] – CSS sınıfı
|
|
97
|
+
* @param {string} [props.style] – inline stil
|
|
98
|
+
* @param {string} [props.objectFit] – CSS object-fit: 'cover' | 'contain' | ...
|
|
99
|
+
* @param {string} [props.objectPosition] – CSS object-position
|
|
100
|
+
* @param {Function} [props.onLoad] – yükleme tamamlandığında callback
|
|
101
|
+
* @param {Function} [props.onError] – hata durumunda callback
|
|
102
|
+
* @returns {HTMLElement}
|
|
103
|
+
*/
|
|
104
|
+
export function ClarityImage(props = {}) {
|
|
105
|
+
const {
|
|
106
|
+
src,
|
|
107
|
+
alt = '',
|
|
108
|
+
width,
|
|
109
|
+
height,
|
|
110
|
+
sizes = '100vw',
|
|
111
|
+
quality = 75,
|
|
112
|
+
priority = false,
|
|
113
|
+
placeholder = 'empty',
|
|
114
|
+
blurDataURL = null,
|
|
115
|
+
className = '',
|
|
116
|
+
style = '',
|
|
117
|
+
objectFit = null,
|
|
118
|
+
objectPosition = null,
|
|
119
|
+
onLoad = null,
|
|
120
|
+
onError = null,
|
|
121
|
+
} = props;
|
|
122
|
+
|
|
123
|
+
if (!src) throw new Error('[clarity/image] ClarityImage: src zorunludur');
|
|
124
|
+
|
|
125
|
+
// Wrapper div — CLS önlemek için aspect ratio tutar
|
|
126
|
+
const wrapper = typeof document !== 'undefined'
|
|
127
|
+
? _createClientImage(props)
|
|
128
|
+
: null;
|
|
129
|
+
|
|
130
|
+
return wrapper || _createSSRImage(props);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function _createSSRImage({ src, alt, width, height, sizes, quality, priority, placeholder, blurDataURL, className, style, objectFit, objectPosition }) {
|
|
134
|
+
// SSR: <img> tag HTML string olarak üretilir — ssr.js tarafından kullanılır
|
|
135
|
+
// Bu fonksiyon doğrudan HTMLElement döndürür — server ortamında string tabanlı render
|
|
136
|
+
|
|
137
|
+
// srcset üret
|
|
138
|
+
const relevantSizes = _getRelevantSizes(width);
|
|
139
|
+
const srcset = relevantSizes
|
|
140
|
+
.map(w => `${_buildUrl(src, w, quality)} ${w}w`)
|
|
141
|
+
.join(', ');
|
|
142
|
+
|
|
143
|
+
// Placeholder stili
|
|
144
|
+
let imgStyle = '';
|
|
145
|
+
if (objectFit) imgStyle += `object-fit:${objectFit};`;
|
|
146
|
+
if (objectPosition) imgStyle += `object-position:${objectPosition};`;
|
|
147
|
+
if (style) imgStyle += style;
|
|
148
|
+
|
|
149
|
+
// Blur placeholder
|
|
150
|
+
if (placeholder === 'blur' && blurDataURL) {
|
|
151
|
+
imgStyle += `background-image:url(${blurDataURL});background-size:cover;`;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const loading = priority ? 'eager' : 'lazy';
|
|
155
|
+
const decoding = priority ? 'sync' : 'async';
|
|
156
|
+
const fetchpriority = priority ? ' fetchpriority="high"' : '';
|
|
157
|
+
|
|
158
|
+
// SSR için basit string döndür (ssr.js h() fonksiyonuyla entegre olur)
|
|
159
|
+
return {
|
|
160
|
+
__clarityImageSSR: true,
|
|
161
|
+
html: `<img
|
|
162
|
+
src="${_buildUrl(src, width ?? 1200, quality)}"
|
|
163
|
+
srcset="${srcset}"
|
|
164
|
+
sizes="${sizes}"
|
|
165
|
+
alt="${_escAttr(alt)}"
|
|
166
|
+
width="${width || ''}"
|
|
167
|
+
height="${height || ''}"
|
|
168
|
+
loading="${loading}"
|
|
169
|
+
decoding="${decoding}"${fetchpriority}
|
|
170
|
+
${className ? `class="${_escAttr(className)}"` : ''}
|
|
171
|
+
${imgStyle ? `style="${_escAttr(imgStyle)}"` : ''}
|
|
172
|
+
/>`,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function _createClientImage({ src, alt, width, height, sizes, quality, priority, placeholder, blurDataURL, className, style, objectFit, objectPosition, onLoad, onError }) {
|
|
177
|
+
const img = document.createElement('img');
|
|
178
|
+
|
|
179
|
+
// Zorunlu attr
|
|
180
|
+
img.alt = alt;
|
|
181
|
+
if (width) img.width = width;
|
|
182
|
+
if (height) img.height = height;
|
|
183
|
+
|
|
184
|
+
// Stil
|
|
185
|
+
const styles = [];
|
|
186
|
+
if (objectFit) styles.push(`object-fit:${objectFit}`);
|
|
187
|
+
if (objectPosition) styles.push(`object-position:${objectPosition}`);
|
|
188
|
+
if (style) styles.push(style);
|
|
189
|
+
if (styles.length) img.style.cssText = styles.join(';');
|
|
190
|
+
|
|
191
|
+
if (className) img.className = className;
|
|
192
|
+
|
|
193
|
+
// Blur placeholder
|
|
194
|
+
if (placeholder === 'blur' && blurDataURL) {
|
|
195
|
+
img.style.backgroundImage = `url(${blurDataURL})`;
|
|
196
|
+
img.style.backgroundSize = 'cover';
|
|
197
|
+
img.addEventListener('load', () => {
|
|
198
|
+
img.style.backgroundImage = '';
|
|
199
|
+
}, { once: true });
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// srcset
|
|
203
|
+
const relevantSizes = _getRelevantSizes(width);
|
|
204
|
+
img.srcset = relevantSizes.map(w => `${_buildUrl(src, w, quality)} ${w}w`).join(', ');
|
|
205
|
+
img.sizes = sizes;
|
|
206
|
+
img.src = _buildUrl(src, width ?? 1200, quality);
|
|
207
|
+
img.loading = priority ? 'eager' : 'lazy';
|
|
208
|
+
img.decoding = priority ? 'sync' : 'async';
|
|
209
|
+
|
|
210
|
+
if (priority) {
|
|
211
|
+
img.setAttribute('fetchpriority', 'high');
|
|
212
|
+
// Preload link ekle
|
|
213
|
+
_injectPreload(src, sizes, relevantSizes, quality);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (onLoad) img.addEventListener('load', onLoad);
|
|
217
|
+
if (onError) img.addEventListener('error', onError);
|
|
218
|
+
|
|
219
|
+
return img;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ─── Vite / Dev Server: görüntü endpoint'i ───────────────────────────────────
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Express/Vite için görüntü optimizasyon endpoint'i.
|
|
226
|
+
* Dev server'da `/_clarity/image` isteğini karşılar.
|
|
227
|
+
*
|
|
228
|
+
* @param {object} [opts]
|
|
229
|
+
* @param {boolean} [opts.sharp=false] – sharp kütüphanesi varsa kullan (prod)
|
|
230
|
+
* @returns {Function} Express middleware
|
|
231
|
+
*/
|
|
232
|
+
export function createImageMiddleware(opts = {}) {
|
|
233
|
+
const { sharp: useSharp = false } = opts;
|
|
234
|
+
|
|
235
|
+
return async function imageMiddleware(req, res, next) {
|
|
236
|
+
if (!req.path.startsWith('/_clarity/image')) return next();
|
|
237
|
+
|
|
238
|
+
const { url, w, q = '75', fmt = 'webp' } = req.query;
|
|
239
|
+
if (!url) return res.status(400).json({ error: 'url parametresi gerekli' });
|
|
240
|
+
|
|
241
|
+
const width = parseInt(w, 10) || null;
|
|
242
|
+
const quality = Math.min(100, Math.max(1, parseInt(q, 10)));
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
// Dev modda: orijinal görüntüyü döndür (optimizasyon yok)
|
|
246
|
+
if (!useSharp) {
|
|
247
|
+
const { createReadStream, existsSync } = await import('node:fs');
|
|
248
|
+
const { resolve } = await import('node:path');
|
|
249
|
+
const filePath = resolve('.' + decodeURIComponent(url));
|
|
250
|
+
if (!existsSync(filePath)) return res.status(404).end();
|
|
251
|
+
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
|
|
252
|
+
return createReadStream(filePath).pipe(res);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Production: sharp ile WebP dönüşümü
|
|
256
|
+
const sharp = await import('sharp');
|
|
257
|
+
const { resolve } = await import('node:path');
|
|
258
|
+
const filePath = resolve('.' + decodeURIComponent(url));
|
|
259
|
+
|
|
260
|
+
let pipeline = sharp.default(filePath);
|
|
261
|
+
if (width) pipeline = pipeline.resize(width);
|
|
262
|
+
|
|
263
|
+
const buffer = await pipeline[fmt === 'avif' ? 'avif' : 'webp']({ quality }).toBuffer();
|
|
264
|
+
res.setHeader('Content-Type', `image/${fmt}`);
|
|
265
|
+
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
|
|
266
|
+
res.send(buffer);
|
|
267
|
+
|
|
268
|
+
} catch (err) {
|
|
269
|
+
console.error('[clarity/image] middleware hata:', err.message);
|
|
270
|
+
next(err);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// ─── Build-time görüntü optimizasyonu (Vite plugin hook) ─────────────────────
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Vite plugin için görüntü optimizasyon hook'u.
|
|
279
|
+
* vite-plugin.js içinde `generateBundle` hook'undan çağrılır.
|
|
280
|
+
*
|
|
281
|
+
* @param {string} publicDir – public/ dizini
|
|
282
|
+
* @param {string} outDir – dist/ dizini
|
|
283
|
+
* @param {object} [opts]
|
|
284
|
+
*/
|
|
285
|
+
export async function optimizeImages(publicDir, outDir, opts = {}) {
|
|
286
|
+
const { quality = 80, formats = ['webp'], sizes = DEVICE_SIZES } = opts;
|
|
287
|
+
|
|
288
|
+
let sharp;
|
|
289
|
+
try {
|
|
290
|
+
sharp = (await import('sharp')).default;
|
|
291
|
+
} catch {
|
|
292
|
+
console.warn('[clarity/image] sharp bulunamadı — görüntü optimizasyonu atlandı. npm install sharp');
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const { readdir, mkdir: mkdirFn, stat: statFn } = await import('node:fs/promises');
|
|
297
|
+
const { join: joinFn, extname: extnFn } = await import('node:path');
|
|
298
|
+
const IMAGE_EXTS = new Set(['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff']);
|
|
299
|
+
|
|
300
|
+
async function processDir(dir, outBase) {
|
|
301
|
+
const entries = await readdir(dir).catch(() => []);
|
|
302
|
+
for (const entry of entries) {
|
|
303
|
+
const srcFull = joinFn(dir, entry);
|
|
304
|
+
const info = await statFn(srcFull).catch(() => null);
|
|
305
|
+
if (!info) continue;
|
|
306
|
+
|
|
307
|
+
if (info.isDirectory()) {
|
|
308
|
+
await processDir(srcFull, joinFn(outBase, entry));
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const ext = extnFn(entry).toLowerCase();
|
|
313
|
+
if (!IMAGE_EXTS.has(ext)) continue;
|
|
314
|
+
|
|
315
|
+
await mkdirFn(joinFn(outBase, '_clarity_images'), { recursive: true });
|
|
316
|
+
|
|
317
|
+
for (const fmt of formats) {
|
|
318
|
+
for (const w of sizes) {
|
|
319
|
+
const outName = `${entry.replace(ext, '')}_${w}.${fmt}`;
|
|
320
|
+
const outFull = joinFn(outBase, '_clarity_images', outName);
|
|
321
|
+
try {
|
|
322
|
+
await sharp(srcFull).resize(w)[fmt]({ quality }).toFile(outFull);
|
|
323
|
+
} catch { /* skip */ }
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
await processDir(publicDir, outDir);
|
|
330
|
+
console.log('[clarity/image] ✅ Görüntü optimizasyonu tamamlandı');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
334
|
+
|
|
335
|
+
function _getRelevantSizes(width) {
|
|
336
|
+
const max = width ? width * 2 : 3840;
|
|
337
|
+
return DEFAULT_SIZES.filter(s => s <= max);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function _injectPreload(src, sizes, widths, quality) {
|
|
341
|
+
if (typeof document === 'undefined') return;
|
|
342
|
+
const link = document.createElement('link');
|
|
343
|
+
link.rel = 'preload';
|
|
344
|
+
link.as = 'image';
|
|
345
|
+
link.imageSrcset = widths.map(w => `${_buildUrl(src, w, quality)} ${w}w`).join(', ');
|
|
346
|
+
link.imageSizes = sizes;
|
|
347
|
+
document.head.appendChild(link);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function _escAttr(str) {
|
|
351
|
+
return String(str ?? '').replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<');
|
|
352
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clarity.js — Public API
|
|
3
|
+
*
|
|
4
|
+
* The full compiler pipeline:
|
|
5
|
+
* source (.clarity) → tokens → AST → JavaScript
|
|
6
|
+
*
|
|
7
|
+
* Author: Claude (Anthropic)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Lexer, tokenize } from './lexer.js';
|
|
11
|
+
import { Parser, parse } from './parser.js';
|
|
12
|
+
import { CodeGenerator, generate } from './codegen.js';
|
|
13
|
+
import { TypeGenerator, generateTypes } from './typegen.js';
|
|
14
|
+
|
|
15
|
+
export { Lexer, tokenize, T } from './lexer.js';
|
|
16
|
+
export { Parser, parse } from './parser.js';
|
|
17
|
+
export { CodeGenerator, generate } from './codegen.js';
|
|
18
|
+
export { TypeGenerator, generateTypes } from './typegen.js';
|
|
19
|
+
|
|
20
|
+
// Router — re-exported for convenience (also importable from '@ozsarman/clarityjs/router')
|
|
21
|
+
export {
|
|
22
|
+
navigate, navigateReplace, back, forward,
|
|
23
|
+
currentPath, currentQuery, routeParams,
|
|
24
|
+
matchRoute, Route, Link, Switch, Outlet,
|
|
25
|
+
beforeEnter, removeGuard,
|
|
26
|
+
createRouter, setServerPath, createSSRMiddleware, renderWithPath,
|
|
27
|
+
prefetchRoute, registerRouteChunk, injectModulepreloads,
|
|
28
|
+
useViewTransition,
|
|
29
|
+
} from './router.js';
|
|
30
|
+
|
|
31
|
+
// File-based pages router — consumes the Vite `scanPages` virtual module
|
|
32
|
+
export {
|
|
33
|
+
filePathToRoutePattern, routeScore, sortRoutes, selectRoute,
|
|
34
|
+
buildRouteTable, createPagesRouter,
|
|
35
|
+
} from './pages-router.js';
|
|
36
|
+
|
|
37
|
+
// Reactivity extras
|
|
38
|
+
export { reactive, createContext, useContext, _pushContext, _popContext,
|
|
39
|
+
_withComponent, beforeMount, onMount, onCleanup, onUpdate,
|
|
40
|
+
createRef, useRef } from './runtime.js';
|
|
41
|
+
|
|
42
|
+
// AI Agent SDK — audit log + permission enforcement
|
|
43
|
+
export { getAIAuditLog, clearAIAuditLog, onAIAction,
|
|
44
|
+
_aiAuditRecord, _setAIActionContext, _protectedSignal,
|
|
45
|
+
ClarityAIForbiddenError, _aiThrowForbidden } from './runtime.js';
|
|
46
|
+
|
|
47
|
+
// Error boundary
|
|
48
|
+
export { ErrorBoundary } from './runtime.js';
|
|
49
|
+
|
|
50
|
+
// Portal — render children outside the component tree
|
|
51
|
+
export { createPortal } from './runtime.js';
|
|
52
|
+
|
|
53
|
+
// Suspense — show fallback while lazy children load
|
|
54
|
+
export { Suspense } from './runtime.js';
|
|
55
|
+
|
|
56
|
+
// SSR — server-side rendering utilities
|
|
57
|
+
export { renderToString, renderToStringAsync, renderToDocument, renderToStream, escapeHTML, escapeAttr, SSRElement } from './ssr.js';
|
|
58
|
+
|
|
59
|
+
// Hydration — client-side adoption of server-rendered HTML
|
|
60
|
+
export { hydrateRoot, isHydrated, getSSRData } from './hydrate.js';
|
|
61
|
+
|
|
62
|
+
// Component-level SSR data fetching — server fetch + serialize + hydrate
|
|
63
|
+
export { useServerData, renderWithServerData, renderToDocumentWithData } from './server-data.js';
|
|
64
|
+
|
|
65
|
+
// Game / animation loop — requestAnimationFrame with fixed/variable timestep
|
|
66
|
+
export { createGameLoop, useRaf } from './game-loop.js';
|
|
67
|
+
|
|
68
|
+
// Async state — TanStack Query / SWR style reactive data fetching
|
|
69
|
+
export {
|
|
70
|
+
createQuery, useFetch, createMutation,
|
|
71
|
+
invalidateQuery, prefetchQuery, clearQueryCache, getCacheEntry,
|
|
72
|
+
} from './async-state.js';
|
|
73
|
+
|
|
74
|
+
// Transitions — Vue-compatible enter/leave animations + FLIP list animations
|
|
75
|
+
export { Transition, TransitionGroup, useTransition, injectTransitionStyles } from './transitions.js';
|
|
76
|
+
|
|
77
|
+
// Scoped CSS — <style scoped> processor for .clarity files
|
|
78
|
+
export { extractStyles, scopeCSS, injectScopeAttr, collectStyles, hashId, cssModules } from './scoped-css.js';
|
|
79
|
+
|
|
80
|
+
// Global Store — Pinia/Zustand style cross-component reactive state
|
|
81
|
+
export { createStore, getStoreRegistry, resetAllStores, disposeAllStores } from './store.js';
|
|
82
|
+
|
|
83
|
+
// Head / Meta management — reactive <title>, <meta>, <og:*>, <link rel="canonical">
|
|
84
|
+
export { createHead, getHead, useHead, renderHead, _setHeadLifecycleHook } from './head.js';
|
|
85
|
+
|
|
86
|
+
// Image Optimization — next/image eşdeğeri: responsive srcset, lazy, blur placeholder, WebP/AVIF
|
|
87
|
+
export { ClarityImage, setImageLoader, createImageMiddleware, optimizeImages } from './image.js';
|
|
88
|
+
|
|
89
|
+
// Font Optimization — next/font eşdeğeri: Google Fonts self-hosting, lokal font, sıfır layout shift
|
|
90
|
+
export { GoogleFont, LocalFont, SystemFonts, renderFontHead, resetFontRegistry, getRegisteredFonts, downloadGoogleFonts, optimizeFonts, applyFontDisplay } from './font.js';
|
|
91
|
+
|
|
92
|
+
// SSG — Static Site Generation: getStaticProps/getStaticPaths, build-time HTML
|
|
93
|
+
export { generateStaticSite, fetchStaticProps, fetchStaticPaths, createSSGContext } from './ssg.js';
|
|
94
|
+
|
|
95
|
+
// ISR — Incremental Static Regeneration: stale-while-revalidate, on-demand revalidation
|
|
96
|
+
export { revalidatePath, revalidateTag, createISRMiddleware, startISRScheduler } from './isr.js';
|
|
97
|
+
|
|
98
|
+
// Islands Architecture — selective hydration, zero JS server components
|
|
99
|
+
export { createIsland, hydrateIslands, defineServerComponent, isServerComponent, renderPageWithIslands } from './islands.js';
|
|
100
|
+
|
|
101
|
+
// Layout System — nested layouts, definePageMeta, dosya tabanlı _layout.js konvansiyonu
|
|
102
|
+
export { defineLayout, getLayout, resetLayoutRegistry, definePageMeta, buildLayoutChain, wrapWithLayouts, renderWithLayouts, scanAndRegisterLayouts, initLayoutRouter, BlankLayout, HTMLShellLayout } from './layout.js';
|
|
103
|
+
|
|
104
|
+
// Formatter & Linter — clarity format / clarity lint
|
|
105
|
+
export { formatCode, formatFile, lintCode, lintFile, processDirectory, formatLintReport, loadConfig, DEFAULT_FORMAT_OPTIONS, DEFAULT_LINT_RULES } from './linter.js';
|
|
106
|
+
|
|
107
|
+
// File-based routing conventions — loading.js, error.js, not-found.js
|
|
108
|
+
export {
|
|
109
|
+
registerConventions, resolveConventions, resetConventionRegistry,
|
|
110
|
+
wrapWithConventions, scanConventions,
|
|
111
|
+
resolveNotFound,
|
|
112
|
+
DefaultNotFound, DefaultLoading,
|
|
113
|
+
createFileRouter, clarityConventionsPlugin,
|
|
114
|
+
LOADING_FILE, ERROR_FILE, NOT_FOUND_FILE, LAYOUT_FILE, SPECIAL_FILES,
|
|
115
|
+
} from './file-conventions.js';
|
|
116
|
+
|
|
117
|
+
// TypeScript Language Service Plugin + Volar integration
|
|
118
|
+
export { init, createClarityTypeChecker, createClarityVolarPlugin, TSCONFIG_PRESET, AMBIENT_DECLARATIONS } from './ts-plugin.js';
|
|
119
|
+
|
|
120
|
+
// Edge Runtime — Cloudflare Workers, Deno Deploy, Vercel Edge, Bun support
|
|
121
|
+
export {
|
|
122
|
+
detectEdgeRuntime, isEdgeRuntime,
|
|
123
|
+
normalizeRequest,
|
|
124
|
+
htmlResponse, jsonResponse, redirectResponse, streamResponse,
|
|
125
|
+
renderEdge,
|
|
126
|
+
createEdgeHandler, adaptFetchHandler,
|
|
127
|
+
createEdgeCache,
|
|
128
|
+
getGeo, getEnv,
|
|
129
|
+
randomId, hmacSign,
|
|
130
|
+
} from './edge.js';
|
|
131
|
+
|
|
132
|
+
// Server Actions — type-safe client→server RPC, "use server" directive support
|
|
133
|
+
export {
|
|
134
|
+
defineServerAction, listServerActions,
|
|
135
|
+
createActionRouter,
|
|
136
|
+
createServerClient,
|
|
137
|
+
useServerAction,
|
|
138
|
+
registerServerModule,
|
|
139
|
+
composeActionMiddleware, logActionMiddleware, createAuthMiddleware,
|
|
140
|
+
} from './server-actions.js';
|
|
141
|
+
|
|
142
|
+
// Devtools — in-page overlay (Shadow DOM, no external deps)
|
|
143
|
+
export { initDevtools,
|
|
144
|
+
_devRecordSignalUpdate, _devRenderStart, _devRenderEnd, _devClearPerfData } from './devtools.js';
|
|
145
|
+
|
|
146
|
+
// Error Overlay — dev mode compiler + runtime error UI (Shadow DOM)
|
|
147
|
+
export { initErrorOverlay, _overlayShowError, _overlayDismiss } from './error-overlay.js';
|
|
148
|
+
|
|
149
|
+
// i18n — Internationalization with RTL support
|
|
150
|
+
export { createI18n, useI18n, t, getLocale, getIsRTL,
|
|
151
|
+
isRTLLocale, RTL_LOCALES, applyDir, BiDiWrapper } from './i18n.js';
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Full compilation pipeline: .clarity source → JavaScript string
|
|
155
|
+
*
|
|
156
|
+
* @param {string} source - Clarity source code
|
|
157
|
+
* @param {object} options - Compilation options
|
|
158
|
+
* @returns {{ code: string, ast: object, tokens: array }}
|
|
159
|
+
*/
|
|
160
|
+
export function compile(source, options = {}) {
|
|
161
|
+
const filename = options.filename ?? '<anonymous>';
|
|
162
|
+
|
|
163
|
+
// Step 1: Lex
|
|
164
|
+
const lexer = new Lexer(source, filename);
|
|
165
|
+
const tokens = lexer.tokenize();
|
|
166
|
+
|
|
167
|
+
// Step 2: Parse
|
|
168
|
+
const parser = new Parser(tokens, source);
|
|
169
|
+
const ast = parser.parse();
|
|
170
|
+
|
|
171
|
+
// Step 3: Generate
|
|
172
|
+
const codegen = new CodeGenerator({
|
|
173
|
+
...options,
|
|
174
|
+
sourceFile: filename,
|
|
175
|
+
outputFile: filename.replace(/\.clarity$/, '.js'),
|
|
176
|
+
sourceContent: source,
|
|
177
|
+
});
|
|
178
|
+
const { code, map } = codegen.generate(ast);
|
|
179
|
+
|
|
180
|
+
// Optionally generate TypeScript declarations
|
|
181
|
+
const dts = options.types
|
|
182
|
+
? new TypeGenerator({ runtimePath: options.runtimePath }).generate(ast, { filename })
|
|
183
|
+
: null;
|
|
184
|
+
|
|
185
|
+
return { code, map, dts, ast, tokens };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Quick compile — just returns the JavaScript string
|
|
190
|
+
*/
|
|
191
|
+
export function compileToJS(source, options = {}) {
|
|
192
|
+
return compile(source, options).code;
|
|
193
|
+
}
|