jskelet 0.5.4 → 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 +387 -385
- 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 +53 -25
- package/docs/08-build.md +40 -18
- 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 +55 -27
- package/docs/en/08-build.md +43 -21
- 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 +152 -18
- 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 +31 -3
- 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
package/README.md
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
the product.
|
|
5
5
|
|
|
6
6
|
JSkelet renders **complete HTML** on an Express 5 server from build-time
|
|
7
|
-
**`.jsk` templates** (EJS
|
|
8
|
-
**islands**, compiles CSS into a **single Tailwind v4
|
|
9
|
-
of ISR keeps an in-process **HTML TTL cache** with
|
|
10
|
-
optional Redis sharing and path-based
|
|
11
|
-
plain JavaScript with JSDoc
|
|
7
|
+
**`.jsk` templates** (optional EJS peer for legacy `.ejs`), adds interactivity
|
|
8
|
+
through vanilla JS **islands**, compiles CSS into a **single Tailwind v4
|
|
9
|
+
stylesheet**, and instead of ISR keeps an in-process **HTML TTL cache** with
|
|
10
|
+
stale-while-revalidate — plus optional Redis sharing and path-based
|
|
11
|
+
invalidation. No React — the framework source is plain JavaScript with JSDoc;
|
|
12
|
+
apps can write client islands and entries in TypeScript, and the published
|
|
13
|
+
package ships declaration files.
|
|
12
14
|
|
|
13
15
|
[](https://www.npmjs.com/package/jskelet)
|
|
14
16
|
[](https://nodejs.org)
|
|
@@ -282,9 +284,9 @@ The complete reference — every field, default and failure mode — is
|
|
|
282
284
|
|
|
283
285
|
| Command | What it does |
|
|
284
286
|
| --- | --- |
|
|
285
|
-
| `jskelet dev` | Watch build plus server, live reload, devtools overlay |
|
|
287
|
+
| `jskelet dev` | Watch build plus server, live reload, devtools overlay. `--murder` kills whatever already holds `PORT` and starts. |
|
|
286
288
|
| `jskelet build` | Production build: templates → fonts → sprite → CSS → JS → images → manifest → precompress |
|
|
287
|
-
| `jskelet start` | Production server; builds first if output is missing |
|
|
289
|
+
| `jskelet start` | Production server; builds first if output is missing. `--murder` same as for `dev`. |
|
|
288
290
|
| `jskelet init` | Scaffolds a feature-first `.jsk` skeleton into the current directory |
|
|
289
291
|
| `jskelet generate` | Scaffolds a `feature` / `page` / `island` |
|
|
290
292
|
|
package/bin/jskelet.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* JSkelet CLI.
|
|
4
4
|
*
|
|
5
|
-
* jskelet dev
|
|
6
|
-
* jskelet build
|
|
7
|
-
* jskelet start
|
|
5
|
+
* jskelet dev [--murder] build watch + sunucu, canlı yenileme, dev overlay
|
|
6
|
+
* jskelet build tek seferlik prod build (fontlar, sprite, CSS, JS, görseller)
|
|
7
|
+
* jskelet start [--murder] prod sunucu (build eksikse önce üretir)
|
|
8
8
|
* jskelet init bulunduğun dizine minimal iskelet kurar
|
|
9
9
|
* jskelet generate feature / page / island iskeleti
|
|
10
|
+
* jskelet migrate Next.js App Router → JSkelet codemod
|
|
10
11
|
*
|
|
11
12
|
* Alt komutlar ayrı süreçlerde çalışır. Sebep: `dev` iki uzun ömürlü süreci
|
|
12
13
|
* (build watch + sunucu) yönetiyor ve sunucunun ESM resolve hook'larına
|
|
@@ -102,15 +103,28 @@ switch (command) {
|
|
|
102
103
|
break;
|
|
103
104
|
}
|
|
104
105
|
|
|
106
|
+
case "migrate": {
|
|
107
|
+
const { migrate } = await import("../src/migrate.mjs");
|
|
108
|
+
try {
|
|
109
|
+
await migrate(process.cwd(), rest);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
process.stderr.write(`${error instanceof Error ? error.message : error}\n`);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
|
|
105
117
|
default: {
|
|
106
118
|
const known = command ? `unknown command: ${command}\n\n` : "";
|
|
107
119
|
process.stderr.write(
|
|
108
|
-
`${known}usage: jskelet <dev|build|start|init|generate
|
|
109
|
-
" dev
|
|
110
|
-
" build
|
|
111
|
-
" start
|
|
112
|
-
" init
|
|
113
|
-
" generate
|
|
120
|
+
`${known}usage: jskelet <dev|build|start|init|generate|migrate> [options]\n\n` +
|
|
121
|
+
" dev [--murder] build watch + server (live reload, dev overlay)\n" +
|
|
122
|
+
" build production build\n" +
|
|
123
|
+
" start [--murder] production server\n" +
|
|
124
|
+
" init scaffold a minimal skeleton in the current directory\n" +
|
|
125
|
+
" generate scaffold feature | page | island\n" +
|
|
126
|
+
" migrate Next.js App Router → JSkelet codemod (scan | apply | config)\n\n" +
|
|
127
|
+
" --murder if the listen port is busy, kill the listener and start\n",
|
|
114
128
|
);
|
|
115
129
|
process.exit(command ? 1 : 0);
|
|
116
130
|
}
|
package/docs/01-baslangic.md
CHANGED
|
@@ -249,11 +249,12 @@ resolve hook'larına (`--import`) süreç başlangıcında ihtiyaç duyması.
|
|
|
249
249
|
|
|
250
250
|
| Komut | Ne yapar |
|
|
251
251
|
| --- | --- |
|
|
252
|
-
| `jskelet dev` | Build watch + sunucu, tek terminalde. Canlı yenileme, CSS hot-swap, dev overlay. `NODE_ENV=development`. |
|
|
252
|
+
| `jskelet dev` | Build watch + sunucu, tek terminalde. Canlı yenileme, CSS hot-swap, dev overlay. `NODE_ENV=development`. Port doluysa başlamaz; `--murder` dinleyiciyi öldürüp bağlar. |
|
|
253
253
|
| `jskelet build` | Tek seferlik prod build: fontlar → ikon sprite → CSS → client JS → görseller → manifest → precompress. `NODE_ENV` verilmemişse `production`. |
|
|
254
|
-
| `jskelet start` | Prod sunucu. Build çıktısı yoksa önce üretir. `NODE_ENV` verilmemişse `production`. |
|
|
254
|
+
| `jskelet start` | Prod sunucu. Build çıktısı yoksa önce üretir. `NODE_ENV` verilmemişse `production`. Port davranışı `dev` ile aynı (`--murder`). |
|
|
255
255
|
| `jskelet init` | Bulunduğun dizine feature-first `.jsk` iskeleti kurar; var olan dosyalara dokunmaz. |
|
|
256
256
|
| `jskelet generate` | `feature` / `page` / `island` iskeleti üretir. |
|
|
257
|
+
| `jskelet migrate` | Next.js App Router → JSkelet codemod (`scan` / `apply` / `config`). [11-tasima.md](./11-tasima.md). |
|
|
257
258
|
|
|
258
259
|
Bilinmeyen bir komut ya da argümansız çağrı kullanım metnini basar.
|
|
259
260
|
|
|
@@ -280,7 +281,7 @@ yalnızca bu belirteçleri kullanın:
|
|
|
280
281
|
| `jskelet/tags` | `link`, `image`, `icon`, `preloadImage`, `toKebab` |
|
|
281
282
|
| `jskelet/log` | Konsol çıktısı yardımcıları (`banner`, `event`, `task`, `size`, `ms`, …) |
|
|
282
283
|
| `jskelet/register` | `node --import jskelet/register` ile alias + uzantı hook'ları |
|
|
283
|
-
| `jskelet/layout` | Framework'ün varsayılan `layout.
|
|
284
|
+
| `jskelet/layout` | Framework'ün varsayılan `layout.jsk` dosyasının yolu |
|
|
284
285
|
|
|
285
286
|
## Sırada ne var
|
|
286
287
|
|
package/docs/02-mimari.md
CHANGED
|
@@ -51,7 +51,7 @@ JSkelet bu gözlemi mimarinin merkezine alır:
|
|
|
51
51
|
│ └─ withHtmlCache TTL + stale-while-revalidate
|
|
52
52
|
│ └─ withUpstreamTracking
|
|
53
53
|
│ └─ withRequestCache
|
|
54
|
-
│ └─ controller → renderPage → EJS
|
|
54
|
+
│ └─ controller → renderPage → .jsk (veya legacy EJS)
|
|
55
55
|
├─ 404 → hooks.notFound()
|
|
56
56
|
└─ hata yönetimi redirect/notFound + 500 fallback
|
|
57
57
|
```
|
|
@@ -254,8 +254,9 @@ teşhisi zor sorunlara dönüşüyor.
|
|
|
254
254
|
|
|
255
255
|
## Neden bu bağımlılık listesi
|
|
256
256
|
|
|
257
|
-
Çalışma zamanı bağımlılıkları
|
|
258
|
-
`tailwind-merge`.
|
|
257
|
+
Çalışma zamanı bağımlılıkları üçtür: `express`, `esbuild`,
|
|
258
|
+
`tailwind-merge`. `ejs` yalnızca legacy `.ejs` şablonları için opsiyonel peer'dır.
|
|
259
|
+
Geri kalan her şey (Tailwind, PostCSS, lightningcss, sharp,
|
|
259
260
|
Phosphor ikonları) **opsiyonel peer bağımlılığıdır** ve yoksa ilgili build adımı
|
|
260
261
|
atlanır.
|
|
261
262
|
|
package/docs/03-routing.md
CHANGED
|
@@ -210,7 +210,7 @@ Controller `async (ctx) => sayfa` biçimindedir ve şu alanları döndürebilir:
|
|
|
210
210
|
|
|
211
211
|
| Alan | Tip | Varsayılan | Anlamı |
|
|
212
212
|
| --- | --- | --- | --- |
|
|
213
|
-
| `view` | `string` | — | `views/` altındaki şablon yolu, uzantısız: `"pages/home"` → `views/pages/home.ejs
|
|
213
|
+
| `view` | `string` | — | `views/` altındaki şablon yolu, uzantısız: `"pages/home"` → `views/pages/home.jsk` (yoksa legacy `.ejs`). |
|
|
214
214
|
| `data` | `object` | `{}` | Şablona local olarak geçen veriler. |
|
|
215
215
|
| `metadata` | `object` | `{}` | `<head>` etiketlerine çevrilir; `hooks.metadata()` çıktısının üzerine biner. Şema: [04-render-ve-sablonlar.md](./04-render-ve-sablonlar.md). |
|
|
216
216
|
| `status` | `number` | `200` | HTTP durum kodu. Yalnızca 200 önbelleğe yazılır. |
|
|
@@ -326,12 +326,17 @@ hata yöneticisi devreye girer, hatayı loglar ve framework'ün kendi hata sayfa
|
|
|
326
326
|
`Cache-Control: no-store` ile döner. Durum kodu hatanın `statusCode` (ya da
|
|
327
327
|
`status`) alanından okunur; 400–599 aralığında değilse 500 kullanılır.
|
|
328
328
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
329
|
+
**Development** (`NODE_ENV=development`, yani `jskelet dev`): 5xx yanıtlarında
|
|
330
|
+
gömülü 500 sayfası ve `hooks.error()` atlanır; mesaj, yığın izi ve varsa
|
|
331
|
+
`cause` zinciri içeren bir teşhis sayfası döner. 4xx (404 vb.) development'ta
|
|
332
|
+
da her zamanki gibi durum sayfasıdır.
|
|
333
333
|
|
|
334
|
-
|
|
334
|
+
**Production**: framework'ün sayfası bilinçli olarak yalın — durum kodu, tek
|
|
335
|
+
satır başlık ve tek satır açıklama. Marka adı, gezinme ya da hata ayrıntısı
|
|
336
|
+
taşımaz; sunucunun içi ziyaretçiye açılmaz. Dil `brand.lang`ten gelir (`tr` ve
|
|
337
|
+
`en` hazır, diğerleri `en`e düşer).
|
|
338
|
+
|
|
339
|
+
Kendi sayfanı vermek için `hooks.error()` (yalnızca production / 4xx):
|
|
335
340
|
|
|
336
341
|
```js
|
|
337
342
|
// jskelet.config.mjs
|
|
@@ -51,7 +51,7 @@ controller data → import edilmiş render(data, helpers) → HTML
|
|
|
51
51
|
{/if}
|
|
52
52
|
|
|
53
53
|
{#each items as item, i}
|
|
54
|
-
<li data-i="
|
|
54
|
+
<li :data-i="i">{{ item }}</li>
|
|
55
55
|
{/each}
|
|
56
56
|
|
|
57
57
|
<Link href="/" text="Home" />
|
|
@@ -99,19 +99,30 @@ code --install-extension extensions/vscode-jsk
|
|
|
99
99
|
|
|
100
100
|
Ayrıntılar uzantı README'sinde.
|
|
101
101
|
|
|
102
|
+
### Yerleşik layout etiketleri
|
|
103
|
+
|
|
104
|
+
`.jsk` ifade dilinde `asset()` / `hasAsset()` çağrılamaz. Layout’ta stylesheet,
|
|
105
|
+
script ve JSON-LD döngüleri için yerleşikler:
|
|
106
|
+
|
|
107
|
+
| Etiket | Props | Çıktı |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| `Stylesheets` | `styles` | `app.css` + sayfa sheet’leri (`data-jskelet-css`) |
|
|
110
|
+
| `BodyScripts` | `entries`, `devtools`, `devBasePath` | `main.js`, entry’ler, isteğe bağlı overlay |
|
|
111
|
+
| `JsonLd` | `items` (`structuredData`) | `application/ld+json` script’leri |
|
|
112
|
+
|
|
102
113
|
### EJS ile birlikte yaşam
|
|
103
114
|
|
|
104
115
|
Aynı `view` id için derlenmiş `.jsk` varsa o kullanılır; yoksa `.ejs` dosyası
|
|
105
|
-
|
|
106
|
-
|
|
116
|
+
**yalnızca `ejs` peer’i kuruluysa** render edilir. `jskelet init` yeni iskeleti
|
|
117
|
+
`.jsk` ile kurar.
|
|
107
118
|
|
|
108
|
-
## EJS motoru (legacy)
|
|
119
|
+
## EJS motoru (legacy peer)
|
|
109
120
|
|
|
110
|
-
EJS
|
|
111
|
-
|
|
112
|
-
|
|
121
|
+
EJS opsiyonel peer bağımlılıktır (`npm i ejs`). `.jsk`-only uygulamalar kurmak
|
|
122
|
+
zorunda değildir. Bir `.ejs` view veya layout istendiğinde paket uygulamadan
|
|
123
|
+
yüklenir; yoksa göç yolunu gösteren bir hata fırlatılır.
|
|
113
124
|
|
|
114
|
-
Ayarlar:
|
|
125
|
+
Motor ilk EJS render’da bir kez kurulur. Ayarlar:
|
|
115
126
|
|
|
116
127
|
| Ayar | Değer | Sebebi |
|
|
117
128
|
| --- | --- | --- |
|
|
@@ -120,9 +131,7 @@ Ayarlar:
|
|
|
120
131
|
| `rmWhitespace` | `true` | çıktı boyutu |
|
|
121
132
|
| `async` | `true` | şablon içinde `await` kullanılabilir |
|
|
122
133
|
|
|
123
|
-
Gömülü kullanımlar (test, script) için `resetRenderEngine()` dışa açık
|
|
124
|
-
dosyaları değişince kaydı yeniler. Dev sunucusu süreci yeniden başlattığı için
|
|
125
|
-
normal akışta gerekmez.
|
|
134
|
+
Gömülü kullanımlar (test, script) için `resetRenderEngine()` dışa açık.
|
|
126
135
|
|
|
127
136
|
## Layout
|
|
128
137
|
|
|
@@ -130,50 +139,33 @@ normal akışta gerekmez.
|
|
|
130
139
|
|
|
131
140
|
1. `jskelet.config.mjs` → `layout` verilmişse o kullanılır. Yol, **views
|
|
132
141
|
dizininin üst dizinine** göre çözülür: `views` varsayılansa
|
|
133
|
-
`layout: "views/ozel.
|
|
142
|
+
`layout: "views/ozel.jsk"` → `<root>/views/ozel.jsk`.
|
|
134
143
|
2. Verilmemişse `views/layout.jsk` (derlenmiş) varsa o kullanılır.
|
|
135
|
-
3. Yoksa `views/layout.ejs` varsa o kullanılır.
|
|
144
|
+
3. Yoksa `views/layout.ejs` varsa o kullanılır (EJS peer gerekir).
|
|
136
145
|
4. O da yoksa framework'ün kendi minimal layout'u kullanılır
|
|
137
|
-
(`node_modules/jskelet/src/templates/layout.
|
|
138
|
-
`jskelet/layout`
|
|
146
|
+
(`node_modules/jskelet/src/templates/layout.jsk`, `jskelet/layout`;
|
|
147
|
+
legacy kopya `jskelet/layout/ejs`).
|
|
139
148
|
|
|
140
149
|
Üçüncü seçenek yeni bir projenin tek route ile çalışabilmesi için var. Kendi
|
|
141
|
-
layout'unuza geçmenin en pratik yolu o dosyayı `views/layout.
|
|
150
|
+
layout'unuza geçmenin en pratik yolu o dosyayı `views/layout.jsk` olarak
|
|
142
151
|
kopyalamaktır.
|
|
143
152
|
|
|
144
153
|
### Framework'ün varsayılan layout'u
|
|
145
154
|
|
|
146
|
-
```
|
|
155
|
+
```jsk
|
|
147
156
|
<!DOCTYPE html>
|
|
148
|
-
<html lang="
|
|
157
|
+
<html :lang="lang">
|
|
149
158
|
<head>
|
|
150
159
|
<meta charset="utf-8">
|
|
151
160
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
<% styles.forEach(function (sheet) { %>
|
|
157
|
-
<% if (hasAsset(sheet)) { %>
|
|
158
|
-
<link rel="stylesheet" href="<%= asset(sheet) %>" data-jskelet-css="<%= sheet %>">
|
|
159
|
-
<% } %>
|
|
160
|
-
<% }); %>
|
|
161
|
-
<%- headMeta %>
|
|
162
|
-
<% structuredData.forEach(function (item) { %>
|
|
163
|
-
<script type="application/ld+json"><%- jsonScript(item) %></script>
|
|
164
|
-
<% }); %>
|
|
161
|
+
{{{ extraHead }}}
|
|
162
|
+
<Stylesheets :styles="styles" />
|
|
163
|
+
{{{ headMeta }}}
|
|
164
|
+
<JsonLd :items="structuredData" />
|
|
165
165
|
</head>
|
|
166
|
-
<body class="
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
<script type="module" src="<%= asset('main.js') %>"></script>
|
|
170
|
-
<% } %>
|
|
171
|
-
<% entries.forEach(function (entry) { %>
|
|
172
|
-
<script type="module" src="<%= asset(entry) %>"></script>
|
|
173
|
-
<% }); %>
|
|
174
|
-
<% if (devtools) { %>
|
|
175
|
-
<script type="module" src="<%= devBasePath %>/overlay.js"></script>
|
|
176
|
-
<% } %>
|
|
166
|
+
<body :class="bodyClass">
|
|
167
|
+
{{{ body }}}
|
|
168
|
+
<BodyScripts :entries="entries" :devtools="devtools" :devBasePath="devBasePath" />
|
|
177
169
|
</body>
|
|
178
170
|
</html>
|
|
179
171
|
```
|
|
@@ -187,7 +179,7 @@ Dikkat edilecek noktalar:
|
|
|
187
179
|
sheet'leri de aynı şekilde basılır. Build çalışmadıysa `hasAsset` false olur
|
|
188
180
|
ve etiket hiç basılmaz.
|
|
189
181
|
- **`hasAsset` kontrolleri** build eksikken sayfanın 404 veren dosyaları
|
|
190
|
-
istememesini sağlar.
|
|
182
|
+
istememesini sağlar (`Stylesheets` / `BodyScripts` içinde).
|
|
191
183
|
- **Devtools script'i** yalnızca `NODE_ENV=development` iken basılır; prod
|
|
192
184
|
çıktısında hiç yoktur.
|
|
193
185
|
|
package/docs/05-islands.md
CHANGED
|
@@ -118,25 +118,29 @@ Pratik sonucu: bir modal'ı `hidden` başlatabilirsiniz, island'ı yine bağlan
|
|
|
118
118
|
```
|
|
119
119
|
client/
|
|
120
120
|
├── entries/
|
|
121
|
-
│ ├── main.js her sayfada yüklenen ortak bootstrap
|
|
121
|
+
│ ├── main.js her sayfada yüklenen ortak bootstrap (veya main.ts)
|
|
122
122
|
│ └── chart.js yalnızca isteyen sayfalarda
|
|
123
123
|
└── islands/
|
|
124
|
-
├── counter.js
|
|
124
|
+
├── counter.ts .js veya .ts
|
|
125
125
|
└── chart.js
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
`client/entries/*.js` içindeki **her dosya bir esbuild entry'sidir**.
|
|
129
|
-
layout tarafından her sayfada yüklenir (manifest'te
|
|
130
|
-
yalnızca onları isteyen sayfalarda yüklenir
|
|
128
|
+
`client/entries/*.{js,ts,mts}` içindeki **her dosya bir esbuild entry'sidir**.
|
|
129
|
+
`main.js` (veya `main.ts`) layout tarafından her sayfada yüklenir (manifest'te
|
|
130
|
+
varsa). Ek entry'ler yalnızca onları isteyen sayfalarda yüklenir. Aynı stem için
|
|
131
|
+
iki uzantı (`main.js` + `main.ts`) build hatasıdır.
|
|
131
132
|
|
|
132
133
|
```js
|
|
133
|
-
// controller
|
|
134
|
+
// controller — manifest anahtarı her zaman *.js kalır
|
|
134
135
|
return { view: "pages/markets", entries: ["chart.js"] };
|
|
135
136
|
```
|
|
136
137
|
|
|
137
138
|
Layout `entries` dizisindeki her adı `asset(entry)` ile çözüp bir
|
|
138
|
-
`<script type="module">` basar. Ad manifest anahtarıdır,
|
|
139
|
-
|
|
139
|
+
`<script type="module">` basar. Ad manifest anahtarıdır (`chart.js`), kaynak
|
|
140
|
+
dosya `chart.ts` olsa bile hash'siz anahtar `.js` kalır.
|
|
141
|
+
|
|
142
|
+
Paylaşılan `@/lib` modülleri sunucuda da import ediliyorsa **`.js` kalsın** —
|
|
143
|
+
Node runtime `.ts` çözmez; `.ts` yalnızca esbuild client hattında derlenir.
|
|
140
144
|
|
|
141
145
|
Kod bölme (`splitting: true`) açık: iki entry'nin paylaştığı modüller ortak bir
|
|
142
146
|
chunk'a çıkar ve iki kez indirilmez.
|
package/docs/07-yapilandirma.md
CHANGED
|
@@ -51,7 +51,7 @@ export default {
|
|
|
51
51
|
lang: "tr",
|
|
52
52
|
},
|
|
53
53
|
|
|
54
|
-
layout: "views/layout.
|
|
54
|
+
layout: "views/layout.jsk",
|
|
55
55
|
routes: ["./routes/10-pages.mjs", "./routes/99-catch-all.mjs"],
|
|
56
56
|
trailingSlash: false,
|
|
57
57
|
|
|
@@ -88,7 +88,7 @@ export default {
|
|
|
88
88
|
watch: ["data"],
|
|
89
89
|
|
|
90
90
|
fonts: [{ family: "Inter", weights: [400, 600, 700] }],
|
|
91
|
-
icons: { scan: ["views", "client", "routes", "lib"] },
|
|
91
|
+
icons: { dir: "icons", scan: ["views", "client", "routes", "lib"] },
|
|
92
92
|
images: { widths: [400, 800, 1200], quality: 78, skip: ["indirmeler"] },
|
|
93
93
|
clientEnv: ["PUBLIC_WS_URL"],
|
|
94
94
|
|
|
@@ -208,26 +208,32 @@ session id taşımak için handoff köprüsünü açar.
|
|
|
208
208
|
|
|
209
209
|
| Alan | Tip | Varsayılan | Anlamı |
|
|
210
210
|
| --- | --- | --- | --- |
|
|
211
|
-
| `crossSubdomainHandoff` | `boolean \| object` | `false` |
|
|
211
|
+
| `crossSubdomainHandoff` | `boolean \| object` | `false` | Açıkken `POST /_jskelet/auth/handoff` + `?handoff=` redeem. Object: `allowedCookieNames` (zorunlu), `ttlSeconds?`, `path?`, `maxValueBytes?`, `maxPendingTickets?`, `maxMintsPerIpPerMinute?` |
|
|
212
212
|
|
|
213
213
|
```js
|
|
214
214
|
auth: {
|
|
215
|
-
crossSubdomainHandoff: {
|
|
215
|
+
crossSubdomainHandoff: {
|
|
216
|
+
allowedCookieNames: ["sid"],
|
|
217
|
+
ttlSeconds: 60,
|
|
218
|
+
},
|
|
216
219
|
},
|
|
217
220
|
```
|
|
218
221
|
|
|
219
|
-
|
|
222
|
+
Mint uç noktası CSRF middleware'inden **sonra** mount edilir (origin kontrolü).
|
|
223
|
+
Cookie adı allowlist dışındaysa veya RFC 6265 token değilse 400. Ayrıntı:
|
|
224
|
+
[12-panel-ve-oturum.md](./12-panel-ve-oturum.md).
|
|
220
225
|
|
|
221
226
|
## `layout`
|
|
222
227
|
|
|
223
228
|
**Tip:** `string` — **Varsayılan:** yok (otomatik çözüm)
|
|
224
229
|
|
|
225
|
-
Layout `.
|
|
226
|
-
göre çözülür, yani varsayılan `views` ile
|
|
227
|
-
`<root>/views/ozel.
|
|
230
|
+
Layout dosyasının yolu (`.jsk` veya legacy `.ejs`). Verilen değer **views
|
|
231
|
+
dizininin üst dizinine** göre çözülür, yani varsayılan `views` ile
|
|
232
|
+
`"views/ozel.jsk"` → `<root>/views/ozel.jsk`.
|
|
228
233
|
|
|
229
|
-
Verilmezse sırayla: `views/layout.jsk`, `views/layout.ejs
|
|
230
|
-
|
|
234
|
+
Verilmezse sırayla: `views/layout.jsk`, `views/layout.ejs` (legacy), yoksa
|
|
235
|
+
framework'ün `src/templates/layout.jsk` varsayılanı. Ayrıntı:
|
|
236
|
+
[04-render-ve-sablonlar.md](./04-render-ve-sablonlar.md).
|
|
231
237
|
|
|
232
238
|
## `routes`
|
|
233
239
|
|
|
@@ -328,7 +334,7 @@ var.
|
|
|
328
334
|
| `trustProxy` | `boolean` | `true` | Express'in `trust proxy` ayarı. Ters proxy arkasında doğru protokol ve istemci IP'si için gerekli. |
|
|
329
335
|
| `cookieSecret` | `string \| null` | `null` | İmzalı cookie sırrı. Verilmezse `JSKELET_SECRET` okunur. |
|
|
330
336
|
| `csrf.enabled` | `boolean` | `true` | Origin/`Sec-Fetch-Site` kontrolü. |
|
|
331
|
-
| `csrf.token` | `boolean` | `false` | Çift gönderim token'ı katmanı. |
|
|
337
|
+
| `csrf.token` | `boolean` | `false` | Çift gönderim token'ı katmanı. Cookie oturumlu formlarda **açın**. |
|
|
332
338
|
| `csrf.allowedOrigins` | `string[]` | `[]` | Kendi host'umuzun yanında kabul edilen origin'ler. |
|
|
333
339
|
| `csrf.exclude` | `string[]` | `[]` | Kontrolden muaf yollar; `source` desen sözdizimi. |
|
|
334
340
|
| `csrf.cookieName` | `string` | `"csrf_token"` | Token cookie'sinin adı. |
|
|
@@ -336,14 +342,17 @@ var.
|
|
|
336
342
|
| `csrf.headerName` | `string` | `"x-csrf-token"` | Token'ın kabul edildiği başlık. |
|
|
337
343
|
|
|
338
344
|
`trustProxy` doğrudan internete açık bir sunucuda **kapatılmalı**: açıkken
|
|
339
|
-
istemci kendi `X-Forwarded-For`
|
|
340
|
-
|
|
345
|
+
istemci kendi `X-Forwarded-For` / `X-Forwarded-Proto` / Host başlığını
|
|
346
|
+
uydurabilir; rate limit, admin IP allowlist, Secure cookie ve cache `vary.host`
|
|
347
|
+
yanlış adresi görür. Ters proxy (nginx, Caddy, Cloudflare) arkasındaysa `true`
|
|
348
|
+
doğru varsayılandır.
|
|
341
349
|
|
|
342
350
|
CSRF kontrolü yalnızca çapraz site olduğu **belli** olan istekleri reddeder —
|
|
343
351
|
`Origin` uyuşmuyorsa ya da `Sec-Fetch-Site: cross-site` geldiyse. İkisi de yoksa
|
|
344
352
|
istek geçer, çünkü tarayıcılar çapraz origin bir POST'ta `Origin`'i her zaman
|
|
345
|
-
gönderirken webhook'lar hiç göndermez.
|
|
346
|
-
`csrf.
|
|
353
|
+
gönderirken webhook'lar hiç göndermez. Cookie ile oturum açan panel/form
|
|
354
|
+
uygulamalarında `csrf.token: true` + `csrfField()` ikinci katmandır; webhook
|
|
355
|
+
uçlarını `csrf.exclude` listesine yazın.
|
|
347
356
|
|
|
348
357
|
## `navigation`
|
|
349
358
|
|
|
@@ -487,21 +496,27 @@ fonts: [
|
|
|
487
496
|
|
|
488
497
|
## `icons`
|
|
489
498
|
|
|
490
|
-
**Tip:** `{ scan?: string[] } | false` — **Varsayılan:** `{}`
|
|
499
|
+
**Tip:** `{ scan?: string[], dir?: string } | false` — **Varsayılan:** `{ dir: "icons" }`
|
|
491
500
|
|
|
492
|
-
|
|
501
|
+
SVG ikon sprite üretimi. Kaynak **XOR** seçilir: `icons.dir` dizini varsa
|
|
502
|
+
yalnızca oradaki düz SVG'ler; yoksa `@phosphor-icons/core` (kuruluysa).
|
|
493
503
|
|
|
494
504
|
| Değer | Sonuç |
|
|
495
505
|
| --- | --- |
|
|
496
|
-
| `{}` (varsayılan) |
|
|
506
|
+
| `{}` (varsayılan) | `dir: "icons"`; taranan dizinler `["views", "client", "routes", "lib", "features", "shared"]` |
|
|
507
|
+
| `{ dir: "assets/icons" }` | Yerel SVG kökü değiştirilir |
|
|
497
508
|
| `{ scan: [...] }` | Taranan dizinler değiştirilir |
|
|
498
509
|
| `false` | Sprite adımı tamamen atlanır |
|
|
499
510
|
|
|
500
|
-
|
|
501
|
-
|
|
511
|
+
Yerel dizin (varsa) düz dosya adları kullanır: `house.svg` → `house:regular`,
|
|
512
|
+
`house-bold.svg` → `house:bold`. Boş bir `icons/` dizini Phosphor'a düşmez —
|
|
513
|
+
dizini silmek fallback'i açar. Ayrıntı: [08-build.md](./08-build.md).
|
|
502
514
|
|
|
503
515
|
```js
|
|
504
|
-
icons: {
|
|
516
|
+
icons: {
|
|
517
|
+
dir: "icons",
|
|
518
|
+
scan: ["views", "client", "routes", "lib", "content"],
|
|
519
|
+
}
|
|
505
520
|
```
|
|
506
521
|
|
|
507
522
|
## `images`
|
|
@@ -534,7 +549,9 @@ icons: { scan: ["views", "client", "routes", "lib", "content"] }
|
|
|
534
549
|
|
|
535
550
|
`false` verilirse görsel adımı hiç çalışmaz. Build adımı `sharp` gerektirir ve
|
|
536
551
|
watch turunda hiç çalışmaz. Remote açıksa `sharp` **runtime**'da da gerekir;
|
|
537
|
-
yoksa optimizer kaynak URL'ye 302 yönlendirir.
|
|
552
|
+
yoksa optimizer kaynak URL'ye 302 yönlendirir. Fetch, redirect'leri otomatik
|
|
553
|
+
takip etmez: her hop `allowHosts` ve private adres kontrolünden geçer.
|
|
554
|
+
Ayrıntı: [08-build.md](./08-build.md).
|
|
538
555
|
|
|
539
556
|
```js
|
|
540
557
|
images: {
|
|
@@ -567,6 +584,9 @@ clientEnv: ["PUBLIC_WS_URL", "PUBLIC_CDN_ORIGIN"]
|
|
|
567
584
|
```
|
|
568
585
|
|
|
569
586
|
**Buraya gizli anahtar koymayın** — değerler bundle'da düz metin olarak durur.
|
|
587
|
+
İsimlerinde `SECRET`, `PASSWORD`, `TOKEN`, `API_KEY`, `PRIVATE` vb. geçen
|
|
588
|
+
anahtarlar build sırasında **reddeder** (`PUBLIC` / `PUBLISHABLE` içerenler
|
|
589
|
+
muaf).
|
|
570
590
|
|
|
571
591
|
## `headers()`
|
|
572
592
|
|
|
@@ -575,7 +595,8 @@ clientEnv: ["PUBLIC_WS_URL", "PUBLIC_CDN_ORIGIN"]
|
|
|
575
595
|
|
|
576
596
|
Yol desenine göre yanıt başlıkları. Framework yalnızca statik dosyalara uzun
|
|
577
597
|
ömürlü cache yazar; bunun dışındaki her başlık (CSP, COOP, HSTS,
|
|
578
|
-
X-Frame-Options…) buradan gelir ve varsayılanların üstüne biner.
|
|
598
|
+
X-Frame-Options…) buradan gelir ve varsayılanların üstüne biner. Üretim
|
|
599
|
+
sitelerinde en azından aşağıdaki güvenlik başlıklarını tanımlayın.
|
|
579
600
|
|
|
580
601
|
Eşleşen **tüm** kurallar uygulanır (redirect'lerin aksine ilk eşleşmede
|
|
581
602
|
durulmaz), sırayla; aynı başlığı iki kural yazarsa sonraki kazanır.
|
|
@@ -590,11 +611,18 @@ async headers() {
|
|
|
590
611
|
source: "/:path*",
|
|
591
612
|
headers: [
|
|
592
613
|
{ key: "X-Frame-Options", value: "SAMEORIGIN" },
|
|
614
|
+
{ key: "X-Content-Type-Options", value: "nosniff" },
|
|
593
615
|
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
|
|
616
|
+
{
|
|
617
|
+
key: "Permissions-Policy",
|
|
618
|
+
value: "camera=(), microphone=(), geolocation=()",
|
|
619
|
+
},
|
|
594
620
|
{
|
|
595
621
|
key: "Content-Security-Policy",
|
|
596
|
-
value: "default-src 'self'; img-src 'self' https://cdn.ornek.com data
|
|
622
|
+
value: "default-src 'self'; img-src 'self' https://cdn.ornek.com data:; script-src 'self'",
|
|
597
623
|
},
|
|
624
|
+
// Yalnızca HTTPS terminasyonu sizin kontrolünüzdeyse:
|
|
625
|
+
// { key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains" },
|
|
598
626
|
],
|
|
599
627
|
},
|
|
600
628
|
{
|
|
@@ -1075,7 +1103,7 @@ basılmaz.
|
|
|
1075
1103
|
| Değişken | Kim okur | Varsayılan | Anlamı |
|
|
1076
1104
|
| --- | --- | --- | --- |
|
|
1077
1105
|
| `NODE_ENV` | her yer | `production` (start/build), `development` (dev) | Dev overlay, EJS cache, manifest yeniden okuma, route hata davranışı ve prewarm varsayılanlarını belirler. `jskelet dev` bunu kendisi ayarlar — `cross-env` gerekmez. |
|
|
1078
|
-
| `PORT` | `startServer` | `3000` | Dinlenecek port |
|
|
1106
|
+
| `PORT` | `startServer` | `3000` | Dinlenecek port. Doluysa süreç başlamaz; `jskelet start|dev --murder` dinleyiciyi öldürür |
|
|
1079
1107
|
| `HOST` | `startServer` | `::` | Bağlanılacak arayüz. Varsayılan çift yığın dinler (IPv6 + IPv4); IPv6 yoksa `0.0.0.0`'a düşer |
|
|
1080
1108
|
| `JSKELET_SECRET` | `jskelet/cookies` | — | İmzalı cookie sırrı. `security.cookieSecret` verilmediğinde buradan okunur; ikisi de yoksa imzalı cookie API'si hata verir. [12](./12-panel-ve-oturum.md) |
|
|
1081
1109
|
| `DEV_TOKEN` | `devGate`, `prewarm` | — | Ayarlıysa token taşımayan her isteğe 404 döner. Isıtma token'ı çerez olarak taşır. [09](./09-dev-araclari.md) |
|
package/docs/08-build.md
CHANGED
|
@@ -167,8 +167,9 @@ etmezdi. Değişiklikler 120 ms birleştirilir.
|
|
|
167
167
|
|
|
168
168
|
## Client JS — esbuild
|
|
169
169
|
|
|
170
|
-
`client/entries/*.js` içindeki her
|
|
171
|
-
|
|
170
|
+
`client/entries/*.{js,ts,mts}` içindeki her kaynak dosya bir entry'dir (`.tsx`
|
|
171
|
+
yok). Manifest anahtarı her zaman `*.js` olur (`main.ts` → `main.js`). Aynı stem
|
|
172
|
+
için birden fazla uzantı build hatasıdır. Dizin yoksa ya da boşsa adım atlanır.
|
|
172
173
|
|
|
173
174
|
esbuild ayarları:
|
|
174
175
|
|
|
@@ -178,7 +179,7 @@ esbuild ayarları:
|
|
|
178
179
|
| `format` | `esm` | `type="module"` script'ler |
|
|
179
180
|
| `target` | `chrome111`, `edge111`, `firefox111`, `safari16.4` | ESM + dinamik import + `IntersectionObserver` island modelinin alt sınırı; daha eskisine transpile etmek çıktıyı büyütüp hiçbir ziyaretçi kazandırmıyor |
|
|
180
181
|
| `minify` | `true` | — |
|
|
181
|
-
| `sourcemap` | `
|
|
182
|
+
| `sourcemap` | yalnızca `NODE_ENV=development` | Prod'da `.map` dosyaları `public/assets` altında yayınlanmaz |
|
|
182
183
|
| `entryNames` | `[name].[hash]` | `immutable` cache |
|
|
183
184
|
| `chunkNames` | `chunks/[name].[hash]` | — |
|
|
184
185
|
| `legalComments` | `none` | — |
|
|
@@ -189,16 +190,19 @@ esbuild ayarları:
|
|
|
189
190
|
### `@/` alias'ı
|
|
190
191
|
|
|
191
192
|
esbuild tarafında `@/` proje köküne çözülür ve uzantı tamamlama yapılır
|
|
192
|
-
(`.js`, `.mjs`, `.json`, `/index.js`). Node
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
(`.js`, `.mjs`, `.ts`, `.mts`, `.json`, `/index.js`, `/index.ts`). Node
|
|
194
|
+
`alias-hooks.mjs` sunucuda yalnızca `.js` / `.mjs` / `.json` çözer; paylaşılan
|
|
195
|
+
`@/lib` dosyaları bu yüzden `.js` kalmalıdır. Client-only `.ts` import'ları
|
|
196
|
+
esbuild hattında çalışır.
|
|
195
197
|
|
|
196
198
|
### `clientEnv` gömülmesi
|
|
197
199
|
|
|
198
200
|
Tarayıcıda `process` yoktur; sunucuyla paylaşılan modüller yine de `process.env`
|
|
199
201
|
okur. `config.clientEnv` ile bildirilen anahtarlar ve `NODE_ENV` build zamanında
|
|
200
202
|
tek nesne olarak define edilir, yani listede olmayan bir anahtar okunduğunda
|
|
201
|
-
çökme yerine `undefined` döner.
|
|
203
|
+
çökme yerine `undefined` döner. İsimleri secret benzeri olan anahtarlar
|
|
204
|
+
(`SECRET`, `API_KEY`, …) build'i düşürür; `PUBLIC` / `PUBLISHABLE` içerenler
|
|
205
|
+
muaf. Ayrıntı: [07-yapilandirma.md](./07-yapilandirma.md).
|
|
202
206
|
|
|
203
207
|
### Manifest anahtarları
|
|
204
208
|
|
|
@@ -249,16 +253,32 @@ bu dosyalara otomatik olarak `immutable` cache yazılır.
|
|
|
249
253
|
|
|
250
254
|
## İkon sprite
|
|
251
255
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
+
**Yalnızca kaynakta kullanılan** ikonlar için bir `<symbol>` seti üretir. Tüm
|
|
257
|
+
seti göndermek 1500+ ikon, yani birkaç megabayt; kullanım taraması sprite'ı
|
|
258
|
+
tipik olarak 10-30 sembolde tutuyor. Çıktı hash'li `sprite.svg` olarak
|
|
259
|
+
`public/assets/` altına yazılır ve precompress kapsamına girer.
|
|
260
|
+
|
|
261
|
+
Kaynak **XOR** seçilir — ikisi birleştirilmez:
|
|
262
|
+
|
|
263
|
+
1. `icons.dir` (varsayılan `icons/`) **dizin olarak varsa** yalnızca oradaki
|
|
264
|
+
düz SVG'ler. Boş dizin Phosphor'a düşmez; fallback için dizini silin.
|
|
265
|
+
2. Aksi hâlde `@phosphor-icons/core` (uygulamanın `node_modules`'ünden). Kurulu
|
|
266
|
+
değilse adım sessizce atlanır.
|
|
267
|
+
|
|
268
|
+
Yerel dosya adları:
|
|
269
|
+
|
|
270
|
+
| Dosya | Sprite anahtarı |
|
|
271
|
+
| --- | --- |
|
|
272
|
+
| `icons/house.svg` | `house:regular` |
|
|
273
|
+
| `icons/house-regular.svg` | `house:regular` |
|
|
274
|
+
| `icons/arrow-right-bold.svg` | `arrow-right:bold` |
|
|
256
275
|
|
|
257
276
|
- Sembol id'si: `<kebab-ad>-<weight>`, örn. `arrow-right-bold`.
|
|
258
|
-
-
|
|
259
|
-
|
|
260
|
-
- Taranan dizinler varsayılan olarak `views`, `client`, `routes`, `lib
|
|
261
|
-
`icons.scan` ile değiştirilebilir. Taranan uzantılar:
|
|
277
|
+
- `viewBox` kaynak SVG'den `<symbol>`'e taşınır; yoksa `0 0 256 256`
|
|
278
|
+
(Phosphor ve `icon()` ile uyum için önerilen kutu).
|
|
279
|
+
- Taranan dizinler varsayılan olarak `views`, `client`, `routes`, `lib`,
|
|
280
|
+
`features`, `shared`; `icons.scan` ile değiştirilebilir. Taranan uzantılar:
|
|
281
|
+
`.ejs`, `.jsk`, `.js`, `.mjs`, `.ts`, `.mts`.
|
|
262
282
|
- Ağırlıklar: `thin`, `light`, `regular`, `bold`, `fill`, `duotone`. Tanınmayan
|
|
263
283
|
bir ağırlık `regular` sayılır.
|
|
264
284
|
|
|
@@ -285,7 +305,7 @@ Bu uyarıyı görürseniz ya adı sabit yazın, ya `icons.scan` listesine ilgili
|
|
|
285
305
|
dizini ekleyin, ya da adı bir yapılandırma alanında `icon: "XLogo"` biçiminde
|
|
286
306
|
tutun.
|
|
287
307
|
|
|
288
|
-
|
|
308
|
+
Kaynakta bulunamayan adlar build sonunda özet olarak uyarılır:
|
|
289
309
|
`N icons missing → …`
|
|
290
310
|
|
|
291
311
|
## Görsel optimizasyonu
|
|
@@ -323,7 +343,9 @@ orijinal dosyaya döner. Watch turunda hiç çalışmaz.
|
|
|
323
343
|
`images.remote.allowHosts` verilirse `createApp` `/_jskelet/image` ucunu
|
|
324
344
|
mount eder. CMS / CDN kapakları build'e girmediği için `image()` bu host'lardaki
|
|
325
345
|
URL'leri `?url=&w=` biçiminde yeniden yazar; uç sharp ile webp üretir ve
|
|
326
|
-
`.jskelet/image-cache/` altına yazar.
|
|
346
|
+
`.jskelet/image-cache/` altına yazar. Upstream fetch redirect'leri elle takip
|
|
347
|
+
edilir: her hop allowlist + private IP / DNS kontrolünden geçer (açık redirect
|
|
348
|
+
SSRF kapalı). Ayrıntı: [07-yapilandirma.md](./07-yapilandirma.md).
|
|
327
349
|
|
|
328
350
|
## Precompress
|
|
329
351
|
|
|
@@ -355,7 +377,7 @@ Bu dosyaları `staticPrecompressed` middleware'i servis eder; kopya yoksa istek
|
|
|
355
377
|
| `tailwindcss` | CSS (peer) | Tailwind direktifleri çözülemez |
|
|
356
378
|
| `lightningcss` | CSS minifikasyonu | Tailwind çıktısı kullanılır, birkaç kB daha büyük |
|
|
357
379
|
| `sharp` | Görsel optimizasyonu | Adım atlanır; `image()` orijinali kullanır |
|
|
358
|
-
| `@phosphor-icons/core` | İkon sprite | Adım atlanır; `icon()` boş `<use>` üretir |
|
|
380
|
+
| `@phosphor-icons/core` | İkon sprite (yerel `icons/` yoksa) | Adım atlanır; `icon()` boş `<use>` üretir |
|
|
359
381
|
|
|
360
382
|
CSS kullanmayacaksanız `paths.styles` dosyasını hiç oluşturmayın: adım uyarıyla
|
|
361
383
|
atlanır ve postcss'e ihtiyaç kalmaz.
|