jskelet 0.5.5 → 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/AGENTS.md +18 -13
- package/CHANGELOG.md +95 -0
- package/README.md +9 -7
- package/bin/jskelet.mjs +24 -10
- package/docs/01-baslangic.md +4 -3
- package/docs/02-mimari.md +4 -3
- package/docs/03-routing.md +11 -6
- package/docs/04-render-ve-sablonlar.md +35 -43
- package/docs/05-islands.md +12 -8
- package/docs/07-yapilandirma.md +40 -18
- package/docs/08-build.md +15 -9
- package/docs/09-dev-araclari.md +5 -1
- package/docs/10-dagitim.md +6 -1
- package/docs/11-tasima.md +51 -17
- package/docs/12-panel-ve-oturum.md +10 -4
- package/docs/README.md +7 -5
- package/docs/en/01-getting-started.md +4 -3
- package/docs/en/02-architecture.md +5 -5
- package/docs/en/03-routing.md +12 -7
- package/docs/en/04-rendering.md +47 -59
- package/docs/en/05-islands.md +13 -8
- package/docs/en/07-configuration.md +40 -20
- package/docs/en/08-build.md +16 -10
- package/docs/en/09-dev-tools.md +6 -1
- package/docs/en/10-deployment.md +6 -1
- package/docs/en/11-migration.md +51 -16
- package/docs/en/12-dashboards-and-sessions.md +9 -4
- package/docs/en/README.md +7 -5
- package/package.json +49 -14
- package/src/build/tasks/client.mjs +91 -10
- package/src/build/tasks/icons.mjs +11 -1
- package/src/client/index.js +2 -2
- package/src/compile/codegen.js +4 -0
- package/src/compile/compile-all.js +12 -21
- package/src/compile/expr.js +5 -0
- package/src/compile/parse.js +64 -8
- package/src/compile/resolve.js +3 -0
- package/src/config/defaults.js +12 -2
- package/src/config/index.js +1 -1
- package/src/dev-server.mjs +26 -3
- package/src/http/cookies-entry.js +1 -0
- package/src/http/cookies.js +18 -0
- package/src/logo.png +0 -0
- package/src/migrate/apply.mjs +262 -0
- package/src/migrate/babel.mjs +79 -0
- package/src/migrate/classify.mjs +155 -0
- package/src/migrate/config.mjs +126 -0
- package/src/migrate/fs-walk.mjs +191 -0
- package/src/migrate/parse.mjs +26 -0
- package/src/migrate/scan.mjs +177 -0
- package/src/migrate/transform/expr-source.mjs +168 -0
- package/src/migrate/transform/island.mjs +67 -0
- package/src/migrate/transform/jsx-to-component.mjs +302 -0
- package/src/migrate/transform/jsx-to-jsk.mjs +330 -0
- package/src/migrate/transform/page-split.mjs +435 -0
- package/src/migrate/write.mjs +81 -0
- package/src/migrate.mjs +171 -0
- package/src/server/auth/handoff.js +94 -11
- package/src/server/create-app.js +28 -10
- package/src/server/ejs-adapter.js +59 -0
- package/src/server/image-optimizer.js +94 -26
- package/src/server/port-guard.js +255 -0
- package/src/server/render.js +27 -9
- package/src/server/status-page.js +105 -4
- package/src/start.mjs +18 -3
- package/src/templates/layout.ejs +8 -28
- package/src/templates/layout.jsk +30 -0
- package/src/templates/layout.render.js +41 -0
- package/src/views/helpers/tags.js +86 -3
- package/types/build/resolve-peer.d.mts +13 -0
- package/types/client/dom.d.ts +55 -0
- package/types/client/form.d.ts +19 -0
- package/types/client/index.d.ts +20 -0
- package/types/client/registry.d.ts +53 -0
- package/types/client/safe-image.d.ts +19 -0
- package/types/client/shared-cookie.d.ts +82 -0
- package/types/client/store.d.ts +18 -0
- package/types/client/swap.d.ts +46 -0
- package/types/compile/codegen.d.ts +32 -0
- package/types/compile/compile-all.d.ts +42 -0
- package/types/compile/errors.d.ts +30 -0
- package/types/compile/expr.d.ts +67 -0
- package/types/compile/index.d.ts +10 -0
- package/types/compile/parse.d.ts +82 -0
- package/types/compile/resolve.d.ts +46 -0
- package/types/compile/scan-exports.d.ts +9 -0
- package/types/config/defaults.d.ts +449 -0
- package/types/config/index.d.ts +299 -0
- package/types/config/pattern.d.ts +38 -0
- package/types/http/control-flow.d.ts +45 -0
- package/types/http/cookies-entry.d.ts +5 -0
- package/types/http/cookies.d.ts +113 -0
- package/types/http/request-cache.d.ts +13 -0
- package/types/http/request-context.d.ts +67 -0
- package/types/http/shared-cookie.d.ts +73 -0
- package/types/index.d.ts +30 -0
- package/types/log.d.mts +153 -0
- package/types/server/admin/actions.d.ts +16 -0
- package/types/server/admin/auth.d.ts +52 -0
- package/types/server/admin/event-log.d.ts +38 -0
- package/types/server/admin/gate.d.ts +43 -0
- package/types/server/admin/inventory.d.ts +40 -0
- package/types/server/admin/mount.d.ts +6 -0
- package/types/server/admin/router.d.ts +6 -0
- package/types/server/admin/snapshot.d.ts +6 -0
- package/types/server/assets.d.ts +47 -0
- package/types/server/auth/handoff.d.ts +12 -0
- package/types/server/cache-deps.d.ts +16 -0
- package/types/server/cache-vary.d.ts +30 -0
- package/types/server/cloudflare.d.ts +163 -0
- package/types/server/create-app.d.ts +25 -0
- package/types/server/data-cache.d.ts +116 -0
- package/types/server/dev/devtools.d.ts +44 -0
- package/types/server/dev/report.d.ts +229 -0
- package/types/server/dev/socket.d.ts +17 -0
- package/types/server/dev/version-check.d.mts +15 -0
- package/types/server/ejs-adapter.d.ts +11 -0
- package/types/server/head-hints.d.ts +40 -0
- package/types/server/html-cache.d.ts +173 -0
- package/types/server/image-optimizer.d.ts +68 -0
- package/types/server/logs/access-middleware.d.ts +7 -0
- package/types/server/logs/file-sink.d.ts +17 -0
- package/types/server/logs/pipeline.d.ts +37 -0
- package/types/server/logs/s3-put.d.ts +85 -0
- package/types/server/logs/s3-sink.d.ts +26 -0
- package/types/server/metadata.d.ts +38 -0
- package/types/server/middleware/compression.d.ts +17 -0
- package/types/server/middleware/csrf.d.ts +4 -0
- package/types/server/middleware/dev-gate.d.ts +2 -0
- package/types/server/middleware/headers.d.ts +2 -0
- package/types/server/middleware/redirects.d.ts +2 -0
- package/types/server/middleware/static-precompressed.d.ts +5 -0
- package/types/server/middleware/trailing-slash.d.ts +11 -0
- package/types/server/middleware/upstream-proxy.d.ts +21 -0
- package/types/server/og-image.d.ts +149 -0
- package/types/server/port-guard.d.ts +50 -0
- package/types/server/prewarm.d.ts +128 -0
- package/types/server/redis.d.ts +163 -0
- package/types/server/render.d.ts +101 -0
- package/types/server/router.d.ts +5 -0
- package/types/server/status-page.d.ts +24 -0
- package/types/server/upstream-limiter.d.ts +123 -0
- package/types/server/upstream-tracking.d.ts +42 -0
- package/types/shared/cookie-domain.d.ts +29 -0
- package/types/templates/layout.render.d.ts +7 -0
- package/types/version.d.mts +10 -0
- package/types/views/components/loader.d.ts +5 -0
- package/types/views/helpers/html.d.ts +39 -0
- package/types/views/helpers/tags.d.ts +127 -0
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `next/link`, `next/image` ve `@phosphor-icons/react` karşılıkları.
|
|
3
|
-
* Hepsi HTML string döndürür;
|
|
3
|
+
* Hepsi HTML string döndürür; şablonlarda PascalCase etiket veya
|
|
4
|
+
* (legacy EJS) `<%- %>` ile basılır.
|
|
4
5
|
*/
|
|
5
|
-
import { attrs, esc, cn } from "./html.js";
|
|
6
|
-
import {
|
|
6
|
+
import { attrs, esc, cn, jsonScript } from "./html.js";
|
|
7
|
+
import {
|
|
8
|
+
asset,
|
|
9
|
+
hasAsset,
|
|
10
|
+
getSpriteIds,
|
|
11
|
+
optimizedImage,
|
|
12
|
+
} from "../../server/assets.js";
|
|
7
13
|
import {
|
|
8
14
|
parseAllowedRemoteUrl,
|
|
9
15
|
remoteImageUrl,
|
|
@@ -290,3 +296,80 @@ export function toKebab(name) {
|
|
|
290
296
|
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2")
|
|
291
297
|
.toLowerCase();
|
|
292
298
|
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Layout `<head>` stylesheet'leri. `hasAsset` false olanları basmaz —
|
|
302
|
+
* build yokken 404 link'i istememek için. `.jsk` ifade dilinde `asset()` /
|
|
303
|
+
* `hasAsset()` çağrılamadığı için layout bu etiketi kullanır.
|
|
304
|
+
*
|
|
305
|
+
* @param {{ styles?: string[] }} [props]
|
|
306
|
+
* @returns {string}
|
|
307
|
+
*/
|
|
308
|
+
export function stylesheets(props = {}) {
|
|
309
|
+
const styles = Array.isArray(props.styles) ? props.styles : [];
|
|
310
|
+
/** @type {string[]} */
|
|
311
|
+
const parts = [];
|
|
312
|
+
|
|
313
|
+
if (hasAsset("app.css")) {
|
|
314
|
+
parts.push(
|
|
315
|
+
`<link rel="stylesheet" href="${esc(asset("app.css"))}" data-jskelet-css="app.css">`,
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
for (const sheet of styles) {
|
|
320
|
+
if (!sheet || !hasAsset(sheet)) continue;
|
|
321
|
+
parts.push(
|
|
322
|
+
`<link rel="stylesheet" href="${esc(asset(sheet))}" data-jskelet-css="${esc(sheet)}">`,
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return parts.join("\n ");
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Layout gövde sonu script'leri: `main.js`, controller `entries`, isteğe
|
|
331
|
+
* bağlı dev overlay.
|
|
332
|
+
*
|
|
333
|
+
* @param {{ entries?: string[], devtools?: boolean, devBasePath?: string }} [props]
|
|
334
|
+
* @returns {string}
|
|
335
|
+
*/
|
|
336
|
+
export function bodyScripts(props = {}) {
|
|
337
|
+
const entries = Array.isArray(props.entries) ? props.entries : [];
|
|
338
|
+
const devBasePath = props.devBasePath ?? "/__jskelet/dev";
|
|
339
|
+
/** @type {string[]} */
|
|
340
|
+
const parts = [];
|
|
341
|
+
|
|
342
|
+
if (hasAsset("main.js")) {
|
|
343
|
+
parts.push(`<script type="module" src="${esc(asset("main.js"))}"></script>`);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
for (const entry of entries) {
|
|
347
|
+
if (!entry) continue;
|
|
348
|
+
parts.push(`<script type="module" src="${esc(asset(entry))}"></script>`);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (props.devtools) {
|
|
352
|
+
parts.push(
|
|
353
|
+
`<script type="module" src="${esc(devBasePath)}/overlay.js"></script>`,
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return parts.join("\n ");
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* JSON-LD script etiketleri. `structuredData` dizisindeki her öğe için bir
|
|
362
|
+
* `<script type="application/ld+json">`.
|
|
363
|
+
*
|
|
364
|
+
* @param {{ items?: unknown[] }} [props]
|
|
365
|
+
* @returns {string}
|
|
366
|
+
*/
|
|
367
|
+
export function jsonLd(props = {}) {
|
|
368
|
+
const items = Array.isArray(props.items) ? props.items : [];
|
|
369
|
+
return items
|
|
370
|
+
.map(
|
|
371
|
+
(item) =>
|
|
372
|
+
`<script type="application/ld+json">${jsonScript(item)}</script>`,
|
|
373
|
+
)
|
|
374
|
+
.join("\n ");
|
|
375
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} root Uygulama kökü.
|
|
3
|
+
* @param {string} specifier
|
|
4
|
+
* @returns {Promise<any>}
|
|
5
|
+
* @throws Paket bulunamazsa; zorunlu bağımlılıklar için.
|
|
6
|
+
*/
|
|
7
|
+
export declare function importFromApp(root: string, specifier: string): Promise<any>;
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} root
|
|
10
|
+
* @param {string} specifier
|
|
11
|
+
* @returns {Promise<any | null>} Paket yoksa `null`; adım atlanabilsin diye.
|
|
12
|
+
*/
|
|
13
|
+
export declare function tryImportFromApp(root: string, specifier: string): Promise<any | null>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Island'ların paylaştığı küçük DOM yardımcıları. */
|
|
2
|
+
/**
|
|
3
|
+
* @param {ParentNode} root
|
|
4
|
+
* @param {string} selector
|
|
5
|
+
* @returns {HTMLElement | null}
|
|
6
|
+
*/
|
|
7
|
+
export declare function qs(root: ParentNode, selector: string): HTMLElement | null;
|
|
8
|
+
/**
|
|
9
|
+
* @param {ParentNode} root
|
|
10
|
+
* @param {string} selector
|
|
11
|
+
* @returns {HTMLElement[]}
|
|
12
|
+
*/
|
|
13
|
+
export declare function qsa(root: ParentNode, selector: string): HTMLElement[];
|
|
14
|
+
/**
|
|
15
|
+
* Otomatik temizlenebilir listener.
|
|
16
|
+
* @param {EventTarget} target
|
|
17
|
+
* @param {string} type
|
|
18
|
+
* @param {EventListenerOrEventListenerObject} handler
|
|
19
|
+
* @param {AddEventListenerOptions | boolean} [options]
|
|
20
|
+
* @returns {() => void}
|
|
21
|
+
*/
|
|
22
|
+
export declare function on(target: EventTarget, type: string, handler: EventListenerOrEventListenerObject, options?: AddEventListenerOptions | boolean): () => void;
|
|
23
|
+
/**
|
|
24
|
+
* `data-*` üzerinden delege edilmiş click.
|
|
25
|
+
* @param {HTMLElement} root
|
|
26
|
+
* @param {string} selector
|
|
27
|
+
* @param {(event: MouseEvent, target: HTMLElement) => void} handler
|
|
28
|
+
* @returns {() => void}
|
|
29
|
+
*/
|
|
30
|
+
export declare function onClick(root: HTMLElement, selector: string, handler: (event: MouseEvent, target: HTMLElement) => void): () => void;
|
|
31
|
+
/**
|
|
32
|
+
* @param {number} ms
|
|
33
|
+
* @param {(...args: any[]) => void} fn
|
|
34
|
+
* @returns {(...args: any[]) => void}
|
|
35
|
+
*/
|
|
36
|
+
export declare function debounce(ms: number, fn: (...args: any[]) => void): (...args: any[]) => void;
|
|
37
|
+
/**
|
|
38
|
+
* requestAnimationFrame ile birleştirilmiş çağrı.
|
|
39
|
+
* @param {() => void} fn
|
|
40
|
+
* @returns {() => void}
|
|
41
|
+
*/
|
|
42
|
+
export declare function raf(fn: () => void): () => void;
|
|
43
|
+
/**
|
|
44
|
+
* @param {HTMLElement} element
|
|
45
|
+
* @param {string} name
|
|
46
|
+
* @param {boolean} active
|
|
47
|
+
*/
|
|
48
|
+
export declare function toggleClass(element: HTMLElement, name: string, active: boolean): void;
|
|
49
|
+
/**
|
|
50
|
+
* Overlay portal hedefi: layout'ta `<div id="jskelet-overlays">` varsa
|
|
51
|
+
* modal/drawer içeriği oraya taşınır, yoksa `body`ye. Portal, `overflow`
|
|
52
|
+
* ya da `transform` taşıyan bir ata elementin `position: fixed` overlay'i
|
|
53
|
+
* kırpmasını engeller.
|
|
54
|
+
*/
|
|
55
|
+
export declare function getOverlayRoot(): HTMLElement;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tek bir formu bağlar.
|
|
3
|
+
*
|
|
4
|
+
* `data-target` verilirse başarılı yanıtın gövdesi o bölgeye takılır; yoksa
|
|
5
|
+
* yanıt formun kendisini değiştirir (doğrulama hatalarının geldiği yol).
|
|
6
|
+
*
|
|
7
|
+
* @param {HTMLFormElement} form
|
|
8
|
+
* @returns {() => void} Dinleyiciyi söken fonksiyon.
|
|
9
|
+
*/
|
|
10
|
+
export declare function enhanceForm(form: HTMLFormElement): () => void;
|
|
11
|
+
/**
|
|
12
|
+
* `data-enhance` taşıyan formları tek bir delege dinleyiciyle bağlar.
|
|
13
|
+
* `submit` olayı köpürdüğü için sonradan DOM'a giren (fragment ile gelen)
|
|
14
|
+
* formlar da kapsanır ve her takastan sonra yeniden bağlama gerekmez.
|
|
15
|
+
*
|
|
16
|
+
* @param {ParentNode} [root]
|
|
17
|
+
* @returns {() => void}
|
|
18
|
+
*/
|
|
19
|
+
export declare function startForms(root?: ParentNode): () => void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSkelet island runtime'ının tarayıcı tarafı API'si.
|
|
3
|
+
*
|
|
4
|
+
* `client/entries/main.js` (veya `main.ts`) içinde:
|
|
5
|
+
*
|
|
6
|
+
* import { registerAll, start } from "jskelet/client";
|
|
7
|
+
*
|
|
8
|
+
* registerAll({
|
|
9
|
+
* counter: () => import("../islands/counter.ts"),
|
|
10
|
+
* });
|
|
11
|
+
*
|
|
12
|
+
* start();
|
|
13
|
+
*/
|
|
14
|
+
export { register, registerAll, hydrate, unmount, observeDocument, start, } from "./registry.js";
|
|
15
|
+
export { swap, startSwapLinks } from "./swap.js";
|
|
16
|
+
export { enhanceForm, startForms } from "./form.js";
|
|
17
|
+
export { createStore } from "./store.js";
|
|
18
|
+
export { debounce, on, onClick, qs, qsa, raf, toggleClass, getOverlayRoot, } from "./dom.js";
|
|
19
|
+
export { startSafeImages } from "./safe-image.js";
|
|
20
|
+
export { clearSharedCookie, consumeWindowNameHandoff, createHandoffUrl, handoffViaWindowName, readCookie, resolveSharedCookieDomain, SHARED_COOKIE_WARN_BYTES, writeSharedCookie, } from "./shared-cookie.js";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Island registry.
|
|
3
|
+
*
|
|
4
|
+
* Sunucu HTML'i tamdır; JS yalnızca davranış ekler. Bir element
|
|
5
|
+
* `data-island="ad"` taşıdığında ilgili modül dinamik import edilir ve
|
|
6
|
+
* `mount(element, props)` çağrılır.
|
|
7
|
+
*
|
|
8
|
+
* Hidrasyon **varsayılan olarak görünürlüğe bağlıdır**: her island bir
|
|
9
|
+
* IntersectionObserver'a verilir, ekranda olanlar zaten ilk gözlemde tetiklenir,
|
|
10
|
+
* ekran dışındakiler kaydırılana kadar hiç indirilmez. Ana sayfadaki grafik
|
|
11
|
+
* kütüphanesi gibi ağır modüller böylece ilk yükten tamamen çıkar.
|
|
12
|
+
*
|
|
13
|
+
* `data-island-eager` görünürlükten bağımsız, hemen bağlanmayı zorlar
|
|
14
|
+
* (header, çerez bandı gibi global davranışlar için).
|
|
15
|
+
*
|
|
16
|
+
* `data-island-idle` görünür olsa bile sayfa sakinleşene (load + boş zaman)
|
|
17
|
+
* kadar bekletir. İlk ekranda görünen ama kritik olmayan ağır modüller
|
|
18
|
+
* (ör. grafik kütüphanesi çeken mini grafik) LCP ile yarışmasın diye.
|
|
19
|
+
*
|
|
20
|
+
* `data-island-props` JSON ise parse edilip props olarak geçer.
|
|
21
|
+
*/
|
|
22
|
+
export type MountFn = (element: HTMLElement, props: object) => void | (() => void);
|
|
23
|
+
/**
|
|
24
|
+
* @param {string} name
|
|
25
|
+
* @param {() => Promise<{ mount: MountFn }>} loader
|
|
26
|
+
*/
|
|
27
|
+
export declare function register(name: string, loader: () => Promise<{
|
|
28
|
+
mount: MountFn;
|
|
29
|
+
}>): void;
|
|
30
|
+
/** @param {Record<string, () => Promise<{ mount: MountFn }>>} entries */
|
|
31
|
+
export declare function registerAll(entries: Record<string, () => Promise<{
|
|
32
|
+
mount: MountFn;
|
|
33
|
+
}>>): void;
|
|
34
|
+
/**
|
|
35
|
+
* Bir alt ağaçtaki island'ları söker.
|
|
36
|
+
*
|
|
37
|
+
* Fragment takasında çağrılması zorunlu: `innerHTML` ile değiştirilen bir
|
|
38
|
+
* bölgenin island'ları DOM'dan çıkar ama `document`/`window` üzerine
|
|
39
|
+
* kurdukları dinleyiciler ve `setInterval`'ları yaşamaya devam eder. Birkaç
|
|
40
|
+
* takastan sonra aynı olay birden fazla kez işlenmeye başlar.
|
|
41
|
+
*
|
|
42
|
+
* Sökülen element yeniden bağlanabilir hâle gelir: `mounted` kaydı da
|
|
43
|
+
* temizlenir, böylece aynı düğüm tekrar DOM'a girerse `hydrate()` onu
|
|
44
|
+
* yeniden görür.
|
|
45
|
+
*
|
|
46
|
+
* @param {ParentNode} [root] Kökün kendisi de island olabilir.
|
|
47
|
+
*/
|
|
48
|
+
export declare function unmount(root?: ParentNode): void;
|
|
49
|
+
/** @param {ParentNode} [root] */
|
|
50
|
+
export declare function hydrate(root?: ParentNode): void;
|
|
51
|
+
/** Sonradan DOM'a eklenen island'ları da yakalar (infinite scroll, portal). */
|
|
52
|
+
export declare function observeDocument(): MutationObserver;
|
|
53
|
+
export declare function start(): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Yüklenemeyen görseller için tek bir belge dinleyicisi.
|
|
3
|
+
*
|
|
4
|
+
* Bu iş bilinçli olarak **island değil**. Görsel ağırlıklı bir sayfada 80+
|
|
5
|
+
* `<img>` olabiliyor ve her birine ayrı island bağlamak (gözlemci + dinamik
|
|
6
|
+
* import + mount) sırf hata ihtimali için ciddi bir hidrasyon yükü. `error`
|
|
7
|
+
* olayı kabarmaz ama yakalama fazında görülebilir, bu yüzden tek dinleyici
|
|
8
|
+
* hepsini karşılar ve sonradan DOM'a eklenen görseller de kendiliğinden
|
|
9
|
+
* kapsanır.
|
|
10
|
+
*
|
|
11
|
+
* Kullanım: görsele `data-safe-image` ekleyin. Kendi hata görünümünüzü
|
|
12
|
+
* vermek için görseli `data-safe-image-host` taşıyan bir sarmalayıcıya alın
|
|
13
|
+
* ve içine `<template data-safe-image-fallback>` koyun — framework hiçbir
|
|
14
|
+
* stil dayatmaz, yalnızca değiştirme işini yapar.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* @returns {void}
|
|
18
|
+
*/
|
|
19
|
+
export declare function startSafeImages(): void;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export { SHARED_COOKIE_WARN_BYTES, resolveSharedCookieDomain, stripHostPort, } from "../shared/cookie-domain.js";
|
|
2
|
+
/**
|
|
3
|
+
* @param {string} name
|
|
4
|
+
* @returns {string | null}
|
|
5
|
+
*/
|
|
6
|
+
export declare function readCookie(name: string): string | null;
|
|
7
|
+
export type ClientSharedCookieResult = {
|
|
8
|
+
ok: boolean;
|
|
9
|
+
domain: string | null;
|
|
10
|
+
handoff: boolean;
|
|
11
|
+
reason?: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {object} ClientSharedCookieResult
|
|
15
|
+
* @property {boolean} ok
|
|
16
|
+
* @property {string | null} domain
|
|
17
|
+
* @property {boolean} handoff
|
|
18
|
+
* @property {string} [reason]
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} name
|
|
22
|
+
* @param {string} value
|
|
23
|
+
* @param {{ roots?: string[], maxAge?: number, path?: string, sameSite?: string,
|
|
24
|
+
* secure?: boolean }} [options]
|
|
25
|
+
* @returns {ClientSharedCookieResult}
|
|
26
|
+
*/
|
|
27
|
+
export declare function writeSharedCookie(name: string, value: string, options?: {
|
|
28
|
+
roots?: string[];
|
|
29
|
+
maxAge?: number;
|
|
30
|
+
path?: string;
|
|
31
|
+
sameSite?: string;
|
|
32
|
+
secure?: boolean;
|
|
33
|
+
}): ClientSharedCookieResult;
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} name
|
|
36
|
+
* @param {{ roots?: string[], path?: string, secure?: boolean, sameSite?: string }} [options]
|
|
37
|
+
* @returns {ClientSharedCookieResult}
|
|
38
|
+
*/
|
|
39
|
+
export declare function clearSharedCookie(name: string, options?: {
|
|
40
|
+
roots?: string[];
|
|
41
|
+
path?: string;
|
|
42
|
+
secure?: boolean;
|
|
43
|
+
sameSite?: string;
|
|
44
|
+
}): ClientSharedCookieResult;
|
|
45
|
+
/**
|
|
46
|
+
* Handoff bileti ister; dönen URL'ye gidilir (`?handoff=` taşır).
|
|
47
|
+
*
|
|
48
|
+
* @param {{ name: string, value: string, next: string }} body
|
|
49
|
+
* @param {{ path?: string }} [options]
|
|
50
|
+
* @returns {Promise<string | null>}
|
|
51
|
+
*/
|
|
52
|
+
export declare function createHandoffUrl(body: {
|
|
53
|
+
name: string;
|
|
54
|
+
value: string;
|
|
55
|
+
next: string;
|
|
56
|
+
}, options?: {
|
|
57
|
+
path?: string;
|
|
58
|
+
}): Promise<string | null>;
|
|
59
|
+
/**
|
|
60
|
+
* first-party `window.name` köprüsü — cookie Domain reddedilince yedek.
|
|
61
|
+
* Kaynak sayfada hedefe gitmeden önce çağırın; hedefte
|
|
62
|
+
* `consumeWindowNameHandoff` okur.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} targetUrl
|
|
65
|
+
* @param {{ name: string, value: string, maxAge?: number }} cookie
|
|
66
|
+
* @returns {void}
|
|
67
|
+
*/
|
|
68
|
+
export declare function handoffViaWindowName(targetUrl: string, cookie: {
|
|
69
|
+
name: string;
|
|
70
|
+
value: string;
|
|
71
|
+
maxAge?: number;
|
|
72
|
+
}): void;
|
|
73
|
+
/**
|
|
74
|
+
* Hedef host'ta `window.name` içindeki handoff'u host-only cookie olarak yazar.
|
|
75
|
+
*
|
|
76
|
+
* @param {{ write?: typeof writeSharedCookie }} [options]
|
|
77
|
+
* Varsayılan: Domain denemeden host-only `document.cookie`.
|
|
78
|
+
* @returns {boolean} Bir şey yazıldı mı.
|
|
79
|
+
*/
|
|
80
|
+
export declare function consumeWindowNameHandoff(options?: {
|
|
81
|
+
write?: typeof writeSharedCookie;
|
|
82
|
+
}): boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Context yerine kullanılan minimal pub/sub store.
|
|
3
|
+
* `useSyncExternalStore` köprüsünün yerini alır: doğrudan `subscribe`.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @param {T} initial
|
|
7
|
+
* @returns {{
|
|
8
|
+
* get: () => T,
|
|
9
|
+
* set: (next: T | ((prev: T) => T)) => void,
|
|
10
|
+
* subscribe: (listener: (value: T) => void) => () => void,
|
|
11
|
+
* }}
|
|
12
|
+
* @template T
|
|
13
|
+
*/
|
|
14
|
+
export declare function createStore<T>(initial: T): {
|
|
15
|
+
get: () => T;
|
|
16
|
+
set: (next: T | ((prev: T) => T)) => void;
|
|
17
|
+
subscribe: (listener: (value: T) => void) => () => void;
|
|
18
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type SwapOptions = {
|
|
2
|
+
/**
|
|
3
|
+
* Varsayılan `GET`.
|
|
4
|
+
*/
|
|
5
|
+
method?: string;
|
|
6
|
+
body?: BodyInit | null;
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
/**
|
|
10
|
+
* `true` → adres çubuğu `url` ile güncellenir.
|
|
11
|
+
*/
|
|
12
|
+
history?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Varsayılan `replace`.
|
|
15
|
+
*/
|
|
16
|
+
mode?: "replace" | "append";
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {object} SwapOptions
|
|
20
|
+
* @property {string} [method] Varsayılan `GET`.
|
|
21
|
+
* @property {BodyInit | null} [body]
|
|
22
|
+
* @property {Record<string, string>} [headers]
|
|
23
|
+
* @property {AbortSignal} [signal]
|
|
24
|
+
* @property {boolean} [history] `true` → adres çubuğu `url` ile güncellenir.
|
|
25
|
+
* @property {"replace" | "append"} [mode] Varsayılan `replace`.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* @param {Element | string} target Takas edilecek bölge.
|
|
29
|
+
* @param {string} url Parçayı döndüren uç.
|
|
30
|
+
* @param {SwapOptions} [options]
|
|
31
|
+
* @returns {Promise<boolean>} Başarılıysa `true`; hata durumunda mevcut
|
|
32
|
+
* içerik korunur ve `false` döner.
|
|
33
|
+
*/
|
|
34
|
+
export declare function swap(target: Element | string, url: string, options?: SwapOptions): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* `data-swap` taşıyan bağlantı ve butonları otomatik bağlar.
|
|
37
|
+
*
|
|
38
|
+
* <a href="/_fragment/rows?page=2" data-swap="#rows" data-swap-history>…</a>
|
|
39
|
+
*
|
|
40
|
+
* Tek bir delege dinleyici: sonradan DOM'a giren bağlantılar da çalışır ve
|
|
41
|
+
* her takastan sonra yeniden bağlama gerekmez.
|
|
42
|
+
*
|
|
43
|
+
* @param {ParentNode} [root]
|
|
44
|
+
* @returns {() => void} Dinleyiciyi söken fonksiyon.
|
|
45
|
+
*/
|
|
46
|
+
export declare function startSwapLinks(root?: ParentNode): () => void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type AstNode = import('./parse.js').AstNode;
|
|
2
|
+
export type AttrNode = import('./parse.js').AttrNode;
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import('./parse.js').AstNode} AstNode
|
|
5
|
+
* @typedef {import('./parse.js').AttrNode} AttrNode
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* @param {AstNode[]} ast
|
|
9
|
+
* @param {{ viewId: string, file?: string, knownComponents?: Set<string> }} options
|
|
10
|
+
* @returns {{ code: string, includes: string[], components: string[] }}
|
|
11
|
+
*/
|
|
12
|
+
export declare function codegen(ast: AstNode[], options: {
|
|
13
|
+
viewId: string;
|
|
14
|
+
file?: string;
|
|
15
|
+
knownComponents?: Set<string>;
|
|
16
|
+
}): {
|
|
17
|
+
code: string;
|
|
18
|
+
includes: string[];
|
|
19
|
+
components: string[];
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Include yolunu view id'ye çevir (uzantısız, `/` ayırıcılı).
|
|
23
|
+
* @param {string} includePath
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
export declare function normalizeIncludeId(includePath: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* `market-hero` / `MarketHero` → `MarketHero`
|
|
29
|
+
* @param {string} name
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
export declare function toPascalCase(name: string): string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {{ root: string, dirs: Record<string, string> }} config
|
|
3
|
+
* @param {{ quiet?: boolean }} [options]
|
|
4
|
+
* @returns {Promise<{ count: number, manifest: Record<string, string>, outDir: string }>}
|
|
5
|
+
*/
|
|
6
|
+
export declare function compileAll(config: {
|
|
7
|
+
root: string;
|
|
8
|
+
dirs: Record<string, string>;
|
|
9
|
+
}, _options?: {}): Promise<{
|
|
10
|
+
count: number;
|
|
11
|
+
manifest: Record<string, string>;
|
|
12
|
+
outDir: string;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* Manifest yoksa veya herhangi bir `.jsk` daha yeniyse yeniden derler.
|
|
16
|
+
* Dev sunucu restart'ında build watch kaçırmış olsa bile şablonlar güncel kalır.
|
|
17
|
+
*
|
|
18
|
+
* @param {{ root: string, dirs: Record<string, string> }} config
|
|
19
|
+
* @returns {Promise<{ count: number, rebuilt: boolean }>}
|
|
20
|
+
*/
|
|
21
|
+
export declare function ensureTemplatesCompiled(config: {
|
|
22
|
+
root: string;
|
|
23
|
+
dirs: Record<string, string>;
|
|
24
|
+
}): Promise<{
|
|
25
|
+
count: number;
|
|
26
|
+
rebuilt: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Tek kaynak dizgisini derler (birim testleri).
|
|
30
|
+
* @param {string} source
|
|
31
|
+
* @param {{ viewId?: string, file?: string, knownComponents?: Set<string> }} [options]
|
|
32
|
+
* @returns {{ code: string, includes: string[], components: string[] }}
|
|
33
|
+
*/
|
|
34
|
+
export declare function compileSource(source: string, options?: {
|
|
35
|
+
viewId?: string;
|
|
36
|
+
file?: string;
|
|
37
|
+
knownComponents?: Set<string>;
|
|
38
|
+
}): {
|
|
39
|
+
code: string;
|
|
40
|
+
includes: string[];
|
|
41
|
+
components: string[];
|
|
42
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Şablon derleme hataları. Satır/sütun korunur ki DX overlay ve CLI
|
|
3
|
+
* çıktısı kaynağa işaret edebilsin.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @param {string} source
|
|
7
|
+
* @param {number} index
|
|
8
|
+
* @returns {{ line: number, column: number }}
|
|
9
|
+
*/
|
|
10
|
+
export declare function indexToLocation(source: string, index: number): {
|
|
11
|
+
line: number;
|
|
12
|
+
column: number;
|
|
13
|
+
};
|
|
14
|
+
export declare class CompileError extends Error {
|
|
15
|
+
file: string | undefined;
|
|
16
|
+
line: number | undefined;
|
|
17
|
+
column: number | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* @param {string} message
|
|
20
|
+
* @param {{ file?: string, source?: string, index?: number,
|
|
21
|
+
* line?: number, column?: number }} [opts]
|
|
22
|
+
*/
|
|
23
|
+
constructor(message: string, opts?: {
|
|
24
|
+
file?: string;
|
|
25
|
+
source?: string;
|
|
26
|
+
index?: number;
|
|
27
|
+
line?: number;
|
|
28
|
+
column?: number;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export type LiteralNode = {
|
|
2
|
+
type: 'Literal';
|
|
3
|
+
value: string | number | boolean | null;
|
|
4
|
+
raw: string;
|
|
5
|
+
};
|
|
6
|
+
export type IdentNode = {
|
|
7
|
+
type: 'Ident';
|
|
8
|
+
name: string;
|
|
9
|
+
};
|
|
10
|
+
export type MemberNode = {
|
|
11
|
+
type: 'Member';
|
|
12
|
+
object: ExprNode;
|
|
13
|
+
property: string;
|
|
14
|
+
optional: boolean;
|
|
15
|
+
};
|
|
16
|
+
export type IndexNode = {
|
|
17
|
+
type: 'Index';
|
|
18
|
+
object: ExprNode;
|
|
19
|
+
index: ExprNode;
|
|
20
|
+
optional: boolean;
|
|
21
|
+
};
|
|
22
|
+
export type UnaryNode = {
|
|
23
|
+
type: 'Unary';
|
|
24
|
+
op: '!' | '-';
|
|
25
|
+
argument: ExprNode;
|
|
26
|
+
};
|
|
27
|
+
export type BinaryNode = {
|
|
28
|
+
type: 'Binary';
|
|
29
|
+
op: string;
|
|
30
|
+
left: ExprNode;
|
|
31
|
+
right: ExprNode;
|
|
32
|
+
};
|
|
33
|
+
export type CondNode = {
|
|
34
|
+
type: 'Cond';
|
|
35
|
+
test: ExprNode;
|
|
36
|
+
consequent: ExprNode;
|
|
37
|
+
alternate: ExprNode;
|
|
38
|
+
};
|
|
39
|
+
export type ExprNode = LiteralNode | IdentNode | MemberNode | IndexNode | UnaryNode | BinaryNode | CondNode;
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} source
|
|
42
|
+
* @param {number} start
|
|
43
|
+
* @param {number} end
|
|
44
|
+
* @param {{ file?: string, templateSource?: string, templateIndex?: number }} [meta]
|
|
45
|
+
* @returns {ExprNode}
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseExpr(source: string, start?: number, end?: number, meta?: {
|
|
48
|
+
file?: string;
|
|
49
|
+
templateSource?: string;
|
|
50
|
+
templateIndex?: number;
|
|
51
|
+
}): ExprNode;
|
|
52
|
+
/**
|
|
53
|
+
* İfadeyi JS kaynak metnine çevirir. `locals` içindeki isimler çıplak kalır;
|
|
54
|
+
* diğerleri `data.` öneki alır.
|
|
55
|
+
*
|
|
56
|
+
* @param {ExprNode} node
|
|
57
|
+
* @param {Set<string>} [locals]
|
|
58
|
+
* @returns {string}
|
|
59
|
+
*/
|
|
60
|
+
export declare function codegenExpr(node: ExprNode, locals?: Set<string>): string;
|
|
61
|
+
/**
|
|
62
|
+
* İfadede geçen kök tanımlayıcılar (data alanları / local adayları).
|
|
63
|
+
* @param {ExprNode} node
|
|
64
|
+
* @param {Set<string>} [out]
|
|
65
|
+
* @returns {Set<string>}
|
|
66
|
+
*/
|
|
67
|
+
export declare function collectIdents(node: ExprNode, out?: Set<string>): Set<string>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build-time `.jsk` derleyici yüzeyi.
|
|
3
|
+
*/
|
|
4
|
+
export { CompileError, indexToLocation } from "./errors.js";
|
|
5
|
+
export { parseExpr, codegenExpr } from "./expr.js";
|
|
6
|
+
export { parseTemplate, isComponentTag } from "./parse.js";
|
|
7
|
+
export { codegen, toPascalCase, normalizeIncludeId } from "./codegen.js";
|
|
8
|
+
export { getViewRoots, getComponentDirs, discoverJskFiles, componentNameFromViewId, collectKnownComponents, toComponentTag, } from "./resolve.js";
|
|
9
|
+
export { scanNamedExports } from "./scan-exports.js";
|
|
10
|
+
export { compileAll, compileSource, ensureTemplatesCompiled } from "./compile-all.js";
|