hüküm: tamamlandı
tip: dokümantasyon
okur: FW-CSS-MOTOR-1 / FW-CSS-MOTOR-2, proje geliştiricileri, ajanlar
platform: Windows
05 — Asset Sistemi (CSS / JS / Font / İkon Yükleme)
Bu belge hangi commit'e göre yazıldı:
d4af18d(dalfeat/fw-license-master, 2026-10-05 20:49)
Son doğrulama tarihi: 2026-10-05
Yayın tabanı: 0.9.7 = bu commit + sonrası; belge yalnız doğrulama anındaki kodu anlatır
Kapsam:rbnframework/deposunun asset katmanı —Core/Support/Definitions/Render/*,
Core/Render/{Builders,Controllers,Services,Providers,Configs}/*,Resources/Assets/RbnCommon/*
Yazım kuralı: Her iddiadosya:satırile kaynağa bağlıdır. Ölçülen sayılar bu belgedeki
ölçüm komutunun çıktısıdır; başka bir yerden alınmış tahmin yoktur. Kodla doğrulanamayanlar
§8BILINMEYENLERbölümündedir.
Bu belge KOD DEĞİŞTİRMEZ. Yalnız okur/uygular.
ÖNCEKİ YANLIŞ VARSAYIMIN DÜZELTİLMESİ
"framework-assets/fonts/space-mono yerelden gelir" → YANLIŞ.
AssetController::serve()fonts/<slug>yolunuAssetFonts::FONT_LIBRARYiçindeki Google Fonts
URL'sine 307 ile yönlendirir. Yerel font dosyası sunulmaz.
Canlı kanıt (§2.4,curlçıktısı):GET /framework-assets/fonts/space-mono → 307 Location: https://fonts.googleapis.com/css2?family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swapBu bir tasarım kararıdır, hata değil: §2.5'te anlatıldığı gibi Google Fonts / Google Tag Manager /
Remix Icon kalıcıdır;AssetDefinitionCDN adresleri bilinçli çok yönlüdür (isteyen kullanır).
İçindekiler
- Yükleme sistemi uçtan uca
- Sabit tablosu (
AssetDefinition) AssetBundles— paketler ve bağlam yığınlarıAssetBuilder— sıralama,css_enginekararı, URL üretimi, sürümlemeAssetController— sunum uçları, font yönlendirmesi, medya vekili- Font sistemi (
AssetFonts) - CSS katmanları
- JS katmanları
- İkon sistemi
- Favicon / OG görseli konvansiyonu (
AssetConvention) - "Bir kaynağı nasıl ister / değiştiririm" tarifleri
- Performans notları (yalnız ölçülen)
- BILINMEYENLER
1. Yükleme sistemi uçtan uca
Altı katman, tek yönde çalışır:
(1) project-routemap.php → css_engine: 'rbn' | belirtilmemiş (= bootstrap)
(2) AssetDefinition.php → tek dosya yol/CDN sabitleri (saf kayıt defteri, mantık YOK)
(3) AssetBundles.php → BUNDLES (hangi asset hangi paket) + STACK_MAP (hangi paket hangi bağlamda)
(4) AssetBuilder.php → injectCoreStack() → collect() → compile() → build() [sıralama + URL]
(5) AssetController.php → /framework-assets/… , /project-assets/… [fiziksel sunum]
(6) Controller addAsset() → yalnızca SAYFAYA ÖZEL ek varlık
Yol haritası:
| Katman | Dosya | Satır sayısı |
|---|---|---|
| (2) | Core/Support/Definitions/Render/AssetDefinition.php |
64 |
| (3) | Core/Support/Definitions/Render/AssetBundles.php |
82 |
| (6) | Core/Render/Controllers/FrontendBaseController.php |
222 |
| (4) | Core/Render/Builders/AssetBuilder.php |
317 |
| (5) | Core/Render/Controllers/AssetController.php |
402 |
| keşif | Core/System/Discovery/Clusters/Resources/AssetResolver.php |
123 |
| boyama | Core/Render/Providers/AssetProvider.php |
112 |
| orkestrasyon | Core/Render/Services/AssetService.php |
96 |
| rota | Core/Routes/Mappings/core.php:46 |
71 (dosya) |
Rotalar (Core/Routes/Mappings/core.php:45):
// Framework Assets Proxy
Route::prefix('framework-assets')->get('{path:.+}', 'AssetController@serve');
// Project Assets Proxy (Dynamic)
Route::prefix('project-assets')->get('{path:.+}', 'AssetController@serveProject');
serveProject() (AssetController.php:315) yalnızca serve($path, true) çağırır; tek fark
$isProject = true — sanal SVG ve sanal OG görseli dalları sadece bu bayrakla açılır
(AssetController.php:107, :124).
Token sözleşmesi (AssetConfig::PROXY_SETUP, Core/Render/Configs/AssetConfig.php:24):
| Önek | Proxy yolu | Kaynak |
|---|---|---|
@project/ |
/project-assets/ |
projenin public/ kökü |
@fw/ |
/framework-assets/ |
framework Resources/Assets/ |
@font/ |
/framework-assets/fonts/<slug> |
yok — 307 yönlendirme (§6) |
Token ayrıştırma AssetBuilder::resolveToken() (:350-369), sırayla project → framework → font
denenir; ilk eşleşen önek kazanır.
2. Sabit tablosu (AssetDefinition)
Core/Support/Definitions/Render/AssetDefinition.php — 36 public const. Sınıf dokümanı
(:7-12) bunu açıkça söyler: "This file is a PURE REGISTRY … Hiçbir mantık yok." Doğrulandı:
dosyada tek bir if/foreach/metot yok.
2.1 Dış CDN sabitleri (tür: CDN)
| Sabit | Satır | URL / Yol | Hangi bundle |
|---|---|---|---|
BOOTSTRAP_CSS |
18 | https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css |
bootstrap |
BOOTSTRAP_JS |
19 | https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js |
bootstrap |
FONT_AWESOME |
21 | https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css |
font_awesome |
BOOTSTRAP_ICONS |
22 | https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css |
bootstrap_icons |
REMIX_ICON |
23 | https://cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.css |
remix_icon |
FLAG_ICON |
24 | https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/6.6.6/css/flag-icons.min.css |
flag_icon |
JQUERY |
26 | ['path' => 'https://code.jquery.com/jquery-3.7.1.min.js', 'renderInHead' => true] |
jquery |
SORTABLE_JS |
27 | https://cdn.jsdelivr.net/npm/sortablejs@1.15.2/Sortable.min.js |
sortable |
AOS_CSS |
28 | https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.css |
aos |
AOS_JS |
29 | https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.js |
aos |
JQUERYtek CDN sabiti değil, dizi biçimindedir (path+renderInHead), çünkü<head>'de
çalışması gerekir.AssetBuilder::compile()diziyiis_array($item)dalında açıprenderInHead
veattributesalanlarını korur (:311-312).
2.2 Framework ortak varlıkları (tür: yerel, token @fw/)
| Sabit | Satır | Yol | Hangi bundle |
|---|---|---|---|
RBN_ADMIN_CSS |
34 | @fw/RbnAdmin/css/rbnAdmin.css |
rbn_core_panel |
RBN_ADMIN_JS |
35 | @fw/RbnAdmin/js/rbnAdmin.js |
rbn_core_panel |
RBN_ADMIN_VARIABLES_CSS |
36 | @fw/RbnAdmin/css/variables.css |
admin_core_css |
RBN_ADMIN_GLOBAL_CSS |
37 | @fw/RbnAdmin/css/global.css |
admin_core_css |
RBN_ADMIN_APP |
38 | @fw/RbnAdmin/js/rbnAdminApp.js |
security |
RBN_MASTER_JS |
44 | @fw/RbnCommon/js/rbn-master.js |
rbn_master_js ve rbn_master |
RBN_COMMON_CSS |
45 | @fw/RbnCommon/css/rbn-common.css |
rbn_core_frontend |
RBN_MASTER_CSS |
46 | @fw/RbnCommon/css/rbn-master.css |
rbn_core_panel, rbn_core_auth, rbn_master |
RBN_SHIELD_CSS |
47 | @fw/RbnCommon/css/rbn-shield.css |
HİÇBİR PAKETTE YOK (§13-B1) |
RBN_DASHBOARD_CSS |
48 | @fw/RbnCommon/css/core/dashboard.css |
rbn_core_panel, rbnDashboard |
RBN_AUTH_CSS |
49 | @fw/RbnCommon/css/core/rbn-auth.css |
rbn_core_auth |
RBN_EXTENDED_UTILITIES_CSS |
55 | @fw/RbnCommon/css/optional/rbn-utilities-extended.css |
rbnExtended |
RBN_EXTENDED_COMPONENTS_CSS |
56 | @fw/RbnCommon/css/optional/rbn-components-extended.css |
rbnExtended |
RBN_SERVICE |
61 | @fw/RbnCommon/js/Networking/rbnService.js |
HİÇBİR PAKETTE YOK (§13-B1) |
RBN_DEBUG_BRIDGE |
62 | @fw/RbnCommon/js/Networking/DebugBridge.js |
HİÇBİR PAKETTE YOK (§13-B1) |
RBN_ALERT_JS |
63 | @fw/RbnCommon/js/components/rbnAlert.js |
HİÇBİR PAKETTE YOK — rbn-master.js dinamik yüklüyor (§8.1) |
RBN_ALERT_CSS |
64 | @fw/RbnCommon/css/components/rbnAlert.css |
rbn_core_frontend |
RBN_MODAL_JS |
65 | @fw/RbnCommon/js/components/rbnModal.js |
HİÇBİR PAKETTE YOK — dinamik yükleniyor |
RBN_MODAL_CSS |
66 | @fw/RbnCommon/css/components/rbnModal.css |
rbnModal |
RBN_UTILS |
67 | @fw/RbnCommon/js/Utils/rbnUtils.js |
HİÇBİR PAKETTE YOK — dinamik yükleniyor |
RBN_BINDERS |
68 | @fw/RbnCommon/js/Utils/rbnBinders.js |
HİÇBİR PAKETTE YOK — dinamik yükleniyor |
RBN_AI |
69 | @fw/RbnCommon/js/Utils/rbnAi.js |
HİÇBİR PAKETTE YOK |
RBN_CHARTS_JS |
70 | @fw/RbnCommon/js/components/rbnCharts.js |
rbnCharts |
RBN_CHARTS_CSS |
71 | @fw/RbnCommon/css/components/rbnCharts.css |
rbnCharts |
RBN_TABLE_JS |
72 | @fw/RbnCommon/js/components/rbnTable.js |
rbnTable |
RBN_TABLE_CSS |
73 | @fw/RbnCommon/css/components/rbnTable.css |
rbnTable |
Önemli gözlem (davranış, hata değil): rbn-master.js çekirdek JS modüllerini kendisi dinamik
olarak yükler (§8.1). Bu yüzden RBN_ALERT_JS, RBN_MODAL_JS, RBN_UTILS, RBN_BINDERS
sabitleri vardır ama hiçbir pakete bağlı değildir — tanımları BUNDLES yerine rbn-master.js
içindeki coreModules dizisini besler. Yeni bir çekirdek JS modülü eklemek için iki yer güncellenir:
sabit + rbn-master.js dizisi.
2.3 Token'ı doğrudan yazan paket girdileri
AssetBundles içinde sabit kullanılmayan iki yer:
| Değer | Satır | Ne yapar |
|---|---|---|
'@project/css/master.css' |
AssetBundles.php:48 (rbn_core_frontend) |
frontend'in proje giriş CSS'i; her frontend sayfasında otomatik |
'@project/master.css' |
AssetBundles.php:90 (project) |
⚠️ project paketi rbn_core_frontend ile çakışır ve kullanılmaz; ayrıca domains/**/css/master.css (21 dosya) yapısıyla uyuşmaz (@project/master.css proje kökü bekler). §13-B2 |
'@font/<Ad>' |
AssetBundles.php:36 (fonts_panel, fonts_auth) |
§6 |
2.4 Yönlendirme (tür: yönlendirme) — fonts/<slug>
AssetController::serve() (AssetController.php:53):
- Yol
fonts/ile başlıyorsa slug çıkarılır (fonts/soyulur). AssetFonts::FONT_LIBRARYiçindeki her anahtar içinstrtolower(str_replace(' ', '-', $name))
slug'ı hesaplanır ve istenen slug ile karşılaştırılır.- Eşleşirse: hedef
FONT_LIBRARY'den gelir (istekten gelmez → açık yönlendirme riski yok).
Yine de iki kontrol uygulanır (:68-72): kontrol karakteri/CRLF yok, şemahttp/https.
Başarısızsaabort(404, '… guvensiz font hedefi reddedildi'). header("Location: $url", true, 307); exit;
Canlı ölçüm (yerel canlı, 2026-10-05):
$ curl -s -k -D - https://example.tr.test/framework-assets/fonts/space-mono
HTTP/1.1 307 Temporary Redirect
Location: https://fonts.googleapis.com/css2?family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap
$ curl -s -k -I https://example.tr.test/framework-assets/fonts/space-mono # HEAD
HTTP/1.1 307 Temporary Redirect
Location: https://fonts.googleapis.com/css2?family=Space+Mono:...
$ curl … /framework-assets/fonts/space-mono=v1.0 # sürüm son eki
HTTP/1.1 307 Temporary Redirect → aynı hedef (sürüm son eki fonts/ yolunu BOZMAZ)
Yerel font dosyası fonts/ rotasından sunulmaz. Doğrulandı:
GET /framework-assets/fonts/BebasNeue-Regular.ttf → HTTP 500 (aşağıda "404 gerçekte 500" notu).
Kütüphanede slug'ı olmayan bir istek de aynı şekilde 500'e düşer.
⚠️ Ölçülen davranış —
abort(404)HTTP 500 döner.
AssetController"bulunamadı" için$this->abort(404, …)çağırıyor (AssetController.php:135),
amaabort()→shield()->abort()→throw new \Exception($message, $code)
(Core/Services/Exception/Concerns/ErrorHandlingTrait.php:65,
Core/Services/Exception/Concerns/Shield.php:86) ve istisna işleyicisi 500 üretiyor.
Ölçüm:/framework-assets/rbncommon/yok.css→ 500; normal bir sayfa 404'ü/yok-boyle-bir-sayfa-xyz
→ 404. Yani asset 404'leri şu an 500 olarak çıkıyor. §13-B3.
2.5 "Bu CDN'ler neden duruyor?" — Proje sahibi kararı (2026-10-05)
AssetDefinition'daki CDN sabitleri bilinçli çok yönlü tasarımdır; framework geneldir ve tek
bir CSS/JS ailesi dayatmaz (Anayasa §9). Ölçülen gerçek kullanım:
| Aile | Gerekçe (ÖLÇÜLDÜ) |
|---|---|
| Google Fonts | AssetFonts::FONT_LIBRARY'ın 33/33 girdisi fonts.googleapis.com (§6). Yerel font yolu yok. |
| Remix Icon | class="… ri-…" içeren view satırı: 2 527 (framework + projeler). bi- 726, fa*/fas- 0. ri- fiili standarttır. |
| Google Tag Manager | <site-b>.test ana sayfasında canlı: https://www.googletagmanager.com/gtag/js?id=G-J49KXF3T2L. Proje ayarı/Controller üzerinden yükleniyor (addAsset değil, view/$google_analytics_code kanalı — §13-B4). |
| Bootstrap / Bootstrap Icons / Font Awesome | Yalnız css_engine belirtilmemiş projelerde yüklenir (§4.2). Canlıda <site-c> ve <site-b>.test hâlâ Bootstrap alıyor. |
flag_icon |
Tek proje isteği: <grup-x>/…/<projeC>FrontendController.php:23 + framework PanelMap.php ('assets' => ['rbnCharts','flag_icon']). |
| jQuery / Sortable | Yalnız panel bağlamında otomatik (STACK_MAP['panel']). Frontend'de yok. |
Sonuç: Google Fonts, Google Tag Manager ve Remix Icon KALIR. Kaldırmak 2 527 view satırını
kırar; motor bi- (Bootstrap Icons) karşılığı yoktur (bi- kullanımı 726 satır, rbn motorunda
bu ikonlar tarayıcıda boş — §13-B5).
3. AssetBundles — paketler ve bağlam yığınları
Core/Support/Definitions/Render/AssetBundles.php.
3.1 STACK_MAP (:21-26) — hangi bağlamda hangi paketler otomatik
| Bağlam | Otomatik paketler (satır) |
|---|---|
universal |
bootstrap, font_awesome, bootstrap_icons, remix_icon, rbn_master_js (:22) |
frontend |
rbn_core_frontend (:23) |
panel |
fonts_panel, jquery, sortable, rbn_core_panel, rbnTable (:24) |
auth |
fonts_auth, rbn_core_auth (:25) |
STACK_MAPbir bağlam → paket adı eşlemesidir.universalher bağlamda önce çalışır
(AssetBuilder::injectCoreStack(),:257-263), sonra bağlama özgü yığın (:270-274).
Yani birfrontendsayfasıuniversal+frontendpaketlerini alır.
3.2 BUNDLES (:32-92) — 24 paket
| Paket | Satır | styles |
scripts |
|---|---|---|---|
rbn_master_js |
34 | — | RBN_MASTER_JS |
fonts_panel |
36 | @font/Plus Jakarta Sans, @font/DM Serif Display, @font/JetBrains Mono |
— |
fonts_auth |
37 | @font/Plus Jakarta Sans |
— |
bootstrap |
38 | BOOTSTRAP_CSS |
BOOTSTRAP_JS |
font_awesome |
39 | FONT_AWESOME |
— |
bootstrap_icons |
40 | BOOTSTRAP_ICONS |
— |
remix_icon |
41 | REMIX_ICON |
— |
flag_icon |
42 | FLAG_ICON |
— |
jquery |
43 | — | JQUERY |
admin_core_css |
46 | RBN_ADMIN_VARIABLES_CSS, RBN_ADMIN_GLOBAL_CSS |
— |
rbn_core_frontend |
47-49 | RBN_ALERT_CSS, RBN_COMMON_CSS, @project/css/master.css |
— |
rbn_core_panel |
51-56 | RBN_MASTER_CSS, RBN_DASHBOARD_CSS, RBN_ADMIN_CSS |
RBN_ADMIN_JS |
rbn_core_auth |
57-65 | RBN_MASTER_CSS, RBN_AUTH_CSS |
— |
rbnExtended |
72-74 | RBN_EXTENDED_UTILITIES_CSS, RBN_EXTENDED_COMPONENTS_CSS |
— |
rbnModal |
77 | RBN_MODAL_CSS |
RBN_MODAL_JS |
rbnDashboard |
78 | RBN_DASHBOARD_CSS |
— |
rbnCharts |
79 | RBN_CHARTS_CSS |
RBN_CHARTS_JS |
rbnTable |
80 | RBN_TABLE_CSS |
RBN_TABLE_JS |
sortable |
81 | — | SORTABLE_JS |
aos |
82 | AOS_CSS |
AOS_JS |
rbn_master |
83-86 | RBN_MASTER_CSS |
RBN_MASTER_JS |
security |
87 | — | RBN_ADMIN_APP |
project |
90 | @project/master.css |
— |
frontend |
91 | — | — |
Ölçülen gerçek kullanım (tüm repo, Storage/framework derleme önbelleği hariç):
| Paket | Kullanan yer |
|---|---|
rbnTable |
20 (framework PanelMap, <proje-b> <projeB>Map/<projeB2>Map 'assets' => ['rbnTable']) + STACK_MAP['panel'] |
rbnCharts |
<proje-a>/…/<projeA>FrontendController.php:28, RbnAdmin/Models/PanelMap.php |
aos |
<proje-b> <projeB>FrontendController.php:90, <projeB2>FrontendController.php:51, <proje-d> <projeD>FrontendController.php |
flag_icon |
<grup-x>/…/<projeC>FrontendController.php:23, RbnAdmin/Models/PanelMap.php |
rbnDashboard |
example/…/EmailFrontendController.php |
rbnModal |
hiçbir yerden istenmiyor — motor rbn-master.js yüklüyor (:8.1) |
admin_core_css |
hiçbir yerden istenmiyor (§13-B6) |
rbnExtended |
hiçbir yerden istenmiyor (§7.5) |
security |
22 eşleşme ama hepsi Security/Syshub controller sınıf adı; paket adı olarak istenmiyor (§13-B7) |
3.3 Paket başvurusu iki yoldan yapılır
- Controller:
$this->addAsset('rbnCharts')→
FrontendBaseController::addAsset()(:92-132),:119pakette tanımlı olduğu için başlık
dönüştürülmez;AssetService::prepare($items, 'frontend')çağrılır (:128). - Paket haritası (
PanelMap/*Map.php):'assets' => ['rbnCharts','flag_icon']→
Core/Render/Providers/UI/PanelProvider.php:48:prepare($subModuleData['assets'], 'panel'),
sonraheaderAssets/footerAssetsyeniden basılır.
addAsset()'ın ön-eğri kuralı (:118-122): paket adı değilse ve@/http//ile başlamıyorsa
başına@project/konur. Bu yüzdenaddAsset('js/frontend.js')veaddAsset('/js/frontend.js')farklı
yollara gider: ilki@project/js/frontend.js, ikinci site-kökünden çözülür. Ölçüm:<proje-a>ana sayfasında
.../project-assets/js/frontend.js=v1789207191(tek<script>) — projelerde/ile başlayan
biçim baskın.
3.4 Mükerrerlik koruması
AssetBuilder::injectCoreStack() (:276-282): auth / panel / rbn motorunda
common.css ve rbnAlert.css rbn-master.css içinde zaten var; filtre bunları atar:
if (($isAuthContext || $isPanelContext || $isRbnEngine) && isset($payload['styles'])) {
$payload['styles'] = array_values(array_filter($payload['styles'], function ($style) {
$path = is_array($style) ? ($style['path'] ?? '') : $style;
return !str_contains($path, 'common.css') && !str_contains($path, 'rbnAlert.css');
}));
}
Canlı doğrulama (aynı anda iki paket görünmez):
| Sayfa | rbn-master.css |
rbnalert.css |
rbn-common.css |
|---|---|---|---|
example.tr.test (css_engine=rbn) |
✅ =v1791201628 |
❌ yok | ❌ yok |
<site-a>.test (css_engine=rbn) |
✅ =v1791201628 |
❌ yok | ❌ yok |
<site-b>.test (bootstrap) |
❌ yok | ✅ =v1788997133 |
✅ =v1789055904 |
<site-c>.test (bootstrap) |
❌ yok | ✅ =v1788997133 |
✅ =v1789055904 |
Filtre çalışıyor; ayrıca 4 sayfanın hiçbirinde aynı CSS iki kez basılmıyor (sayım §12).
4. AssetBuilder — sıralama, css_engine kararı, URL üretimi, sürümleme
Core/Render/Builders/AssetBuilder.php.
4.1 css_engine kararı (injectCoreStack(), :245-283)
$projectKey = (string) ($this->resolveProjectData('project_key') ?? ''); // :250
$cssEngine = $this->getRouteConfig($projectKey, 'css_engine'); // :251
$isRbnEngine = (strtolower((string) $cssEngine) === 'rbn'); // :252
$isAuthContext = ($appContext === 'auth'); // :254
$isPanelContext = ($appContext === 'panel'); // :255
- Bootstrap baypası (
:257-263) —auth/panel/rbnmotorundabootstrap,
bootstrap_icons,font_awesomepaketlericontinueile atlanır (0 KB).
remix_iconverbn_master_jsher zaman yüklenir (listeden düşmez). rbn_masterenjeksiyonu (:266-268) — koşul:
if ($isAuthContext || ($isRbnEngine && $appContext === 'frontend')).
⚠️panelbağlamı bu koşula girmiyor; panelrbn_master'i zaten
STACK_MAP['panel'] → rbn_core_paneliçinden alıyor (§4.1 tablosu).- Bağlam yığını (
:270-274).
getRouteConfig() (Core/Base/Concerns/Data/ResolvesProjectConfigTrait.php:71) okuma yolunu
doğrudan dosyadan verir: Paths::project()->configs('project-routemap.php') → require →
['view_mapping'][$projectKey][$key]. Yani css_engine yalnız
projects/<proje>/Core/Config/project-routemap.php → view_mapping.<alt-proje>.css_engine
altında aranır.
Mevcut durum — ÖLÇÜLDÜ (tüm project-routemap.php dosyaları taranmış):
| Değer | Alt proje sayısı | Dosya:satır |
|---|---|---|
'css_engine' => 'rbn' |
13 | example (:11,:25,:37,:49), <grup-y> (:36,:92), <grup-z> (:13,:46), <proje-d> (:17,:43,:58), <proje-a> (:11,:21) |
| belirtilmemiş (⇒ bootstrap) | 8 | <grup-w> (<proje-b>,<proje-b2>), <grup-x> (<proje-c>,<proje-g>,<proje-h>), <grup-y> (<proje-e>,<proje-f>) |
Toplam view_mapping girişi |
21 |
Önceki analiz (
css-dahil-etme-sistemi.md:54) "6 alt projerbn,
5 varsayılan" diyordu. Bu sayım bayattır; 2026-10-05'te ölçülen gerçek sayı 13 / 8.
(O analiz 2026-10-02 tarihliydi; sonraki gece işçilericss_engineeklemiş.)
Canlı doğrulama:
| Site | css_engine |
Bootstrap CSS | rbn-master.css |
|---|---|---|---|
example.tr.test |
rbn |
❌ | ✅ |
<site-a2>.test |
rbn |
❌ | ✅ |
<site-c>.test |
(yok) | ✅ bootstrap@5.3.2 |
❌ |
<site-b>.test |
(yok) | ✅ bootstrap@5.3.2 |
❌ |
4.2 Sıralama (build(), :142-202)
uasort comparator (:164-192) üç kural uygular, sırayla:
@project-assets/ile başlayanlar daima en son (:166-174) — framework ve CDN'leri ezebilmek için.- Yolu
bootstrap/rbn-master.css/rbn-core.cssiçeren her şey daima en başta (:177-185). priorityküçükten büyüğe (:187-189). Varsayılan10(:39,:313);
addFont()15verir (:70) ama pratikte fontlar=vüretiminden gelir;
build()'in varsayılan-Inter graceful fallback'ipriority = 5(:159).
Varsayılan Inter fallback'i (:144-162): frontend'de hiç /fonts/ içeren yol yoksa
@font/Inter priority 5 ile eklenir. Ayrıca prepare() (:92-113) özel bir font istenmişse ve
kullanıcı açıkça @font/Inter dememişse, önceki çalışmadan kalmış varsayılan Inter'i siler.
Ölçülen gözlem:
<proje-a><projeA>FrontendController.php:28@font/Inter'i açıkça istediği için
Inter + Outfit + JetBrains Mono + Space Mono = 4 font basıldı.<proje-c>yalnız@font/Syne
istedi → 1 font.example@font/Space Mono+@font/JetBrains Mono→ 2 font, Inter düştü.
<proje-b>hiç font istemedi → fallback devreye girmeliydi ama sayfada font link'i yok
(§13-B8).
4.3 Derleme ve sürümleme (compile(), :289-316)
$version = AssetConfig::VERSION; // '1.0' (:301)
if ($detected && file_exists($detected->path)) {
$version = (string) filemtime($detected->path); // fiziksel dosya varsa (:303)
}
- Fiziksel dosya varsa sürüm =
filemtime→ dosya değişince URL değişir, tarayıcı önbelleği kırılır. - Fiziksel dosya bulunamazsa (
$detected === null) ve yolhttpiçermiyorsa vefontdeğilse
compile()nulldöner → asset sessizce düşer (:297-299).
Doğrulama: filemtime canlıda görünür —
rbn-master.css=v1791201628, rbn-common.css=v1789055904, proje master.css=v1788046898
(farklı dosyalar, farklı zaman damgaları; hepsi 2026-10 çevresi).
4.4 URL üretimi (generateWebUrl(), :318-348)
| Girdi | Çıktı | Satır |
|---|---|---|
@font/<Ad> |
url('/framework-assets/fonts/<ad>-<kısa-i>) |
:320-322 |
http… |
olduğu gibi (CDN, sürümleme yok) | :324-326 |
@fw/RbnCommon/css/rbn-master.css |
url('/framework-assets/rbncommon/rbn-master.css=v<filemtime>') |
:335-347 |
@project/css/master.css |
url('/project-assets/css/master.css=v<filemtime>') |
:343-347 |
Framework "düzleştirme" kuralı (:335-342) — önemli ve çok sık hata yapılan yer:
@fw/<küme>/<derin/yol>/<dosya> → /framework-assets/<küme>/<dosya>. Alt klasörler kaybolur,
yalnız küme (ilk segment, küçük harf) ve dosya adı (küçük harf) kalır.
Tek istisna: küme images ise yol düzleştirilmez, tam yol küçük harfe iner (:337-339).
Canlı kanıt (düzleştirme gerçekten oluyor):
GET /framework-assets/rbncommon/rbn-master.css=v1791201628 → 200
GET /framework-assets/rbncommon/BebasNeue-Regular.ttf → 200 (küme + dosya adı)
GET /framework-assets/rbncommon/bebasneue-regular.ttf → 200 (büyük/küçük harf ayrımı YOK)
GET /framework-assets/images/favicon-rbnauth.svg → 200 (images istisnası)
Bu, fiziksel keşfin neden "yapılandırılmış" olduğunu açıklar: AssetResolver (§5.5) düz
yolu bulamazsa küme klasöründe özyinelemeli arama yapar (AssetResolver.php:68).
4.5 Sürümleme biçimi: =v… path sonu, query değil
generateWebUrl() (:347): … . "/{$proxy}/{$finalPath}=v{$version}".
AssetController::serve() (:48-51) gelen yolda = varsa explode('=', …)[0] ile keser.
⚠️ Elle
<link … ?v=123>yazan kod bu ayrıştırmayı tetiklemez → sürümleme çalışmaz
ve?v=dosya adının bir parçası olur. Doğrulandı:
GET /framework-assets/fonts/space-mono=v1.0307 döndü (yani=v1.0doğru kesildi);
?v=biçiminde yazılan bir elle link için bu belge canlı test yapmamıştır — kod
(str_contains($path, '='))?v='yi görmez, dolayısıyla kesinlikle sürümlemez (§13-B9).
5. AssetController — sunum uçları, font yönlendirmesi, medya vekili
Core/Render/Controllers/AssetController.php, 402 satır.
5.1 Akış sırası (serve(), :46-158)
| # | Koşul | Satır | Sonuç |
|---|---|---|---|
| 0 | yolda = varsa |
48-51 | sürüm son eki kesilir |
| 1 | fonts/ ile başlıyor |
55-77 | 307 → FONT_LIBRARY URL'si, exit |
| 2 | media/ ile başlıyor |
80-104 | 307 → base64 çözülmüş medya, exit |
| 3 | $isProject ve .svg |
107-110 | serveVirtualResource() — SEO resolver'dan SVG |
| 4 | $isProject ve og-image-* |
124-127 | serveVirtualOgImage() (§10) |
| 5 | fiziksel keşif | 130-157 | AssetResolver → MIME + Cache-Control + gövde, exit |
5.2 Fiziksel teslim başlıkları (:150-157)
header('Content-Type: ' . $contentType);
header('Cache-Control: public, max-age=31536000'); // 1 yıl — :152
header('Content-Length: ' . strlen($content));
header('X-RBN-Source: ' . $detected->source);
Gzip framework değil, web sunucusu tarafından ekleniyor (AssetController Content-Encoding
yazmıyor). Canlı kanıt:
$ curl -H 'Accept-Encoding: gzip' … /framework-assets/rbncommon/rbn-master.css=v1791201628
HTTP/1.1 200 OK
Content-Type: text/css;charset=UTF-8
Content-Length: 1420 ← sıkıştırılmamış (banner + 19 @import satırı)
Cache-Control: public, max-age=31536000
X-RBN-Source: framework
(Accept-Encoding: gzip ile) Content-Encoding: gzip
immutableyok veAssetController.php:35bunu bilinçli açıklıyor: bir kez önbelleğe alınan
307 hedefiimmutableile kalıcı olarak değiştirilemiyordu (cache poisoning).media/dalı
Cache-Control: private, max-age=300(:99-100).
5.3 decorate() — içerik imzası
AssetProvider::decorate() (:108-134): .css/.js içeriğinin başına 🔱/🏛️/🛰️/⚓/🛡️ banner'ı
eklenir (framework adı + sürüm + kit adı + dosya adı + etiket). Bu yüzden
rbn-master.css ham 1 097 bayt iken canlı Content-Length 1 420'dir (banner ≈ 323 bayt).
Ölçülen bu fark, §12'deki boyut tablosunun "sunulan" sütununu açıklar.
5.4 media/<base64> — dış varlık vekili + proxy_allowed_hosts
AssetController.php:80 ve guvenliProxyHedefi() (:180-248).
Yol biçimi: /framework-assets/media/<kategori>/<base64url>/<ad> veya
/framework-assets/media/<base64url>/<ad>. Kod 2. segmenti base64 kabul eder (:81-83).
Base64 varyantı standart değil: strtr($encodedUrl, '-_', '+/') — yani base64url.
Doğrulama sırası (guvenliProxyHedefi()):
- Kontrol karakteri / CRLF → red (
:189-191). - Ters bölü →
/normalizasyonu ([F-01],:196). TarayıcıLocation: /\evil.example/x
değerini//evil.example/xsayar; normalizasyon olmazsa "göreli yol" sanılıp geçerdi. - Tek bölü/çizgi ile başlayan göreli yol → olduğu gibi geçer (yerel
/storage/...medya) (:200-202). - Mutlak hedef → şema beyaz listesi: yalnız
http/https;javascript:,data:,vbscript:kapanır (:205-209). - Ana beyaz liste:
RedirectTrait::guvenliHedef($url) !== '/'→ aktif proje alan adı + grup alan adları- doğrulanmış istek host'u (
:217-219).
- doğrulanmış istek host'u (
- Ek yapılandırılabilir liste — İKİ KAYNAK BİRLİKTE (
:233-244):AssetConfig::PROXY_ALLOWED_HOSTS(AssetConfig.php:70) — framework varsayılanı BOŞ
(üç satır yorum örnek olarak duruyor).projectAllowedProxyHosts()(:272-310) →Config::get('project-settings.proxy_allowed_hosts').
project-settings.php'dehas_route_mapaçıksaConfig::get, aktifproject_keyiçin
project-routemap.php → view_mappingdeğerlerini project-settings üstüne yazar
(:220-226yorumu) — yani anahtarproject-routemap.php'de de verilebilir.- Eşleşme: tam host ya da son ek (
cdn.example.com→*.example.com),.'.$sonEk
ile kontrol edilir kinotcdn.example.comyanlış eşleşmesin (:241). - Geçersiz girdi (dizi değil, şema/port/yol/boşluk/kontrol karakteri,
.., baş/son tire)
sessizce yok sayılır; hata fırlatmaz, liste genişlemez (:286-305).
- Fail-closed →
null→Locationbaşlığı üretilmez, istek normal asset akışına düşer → 404/500.
Canlı kanıt:
# Beyaz listede olmayan dış hedef
GET /project-assets/media/<b64(https://evil.example/x.png)> → HTTP 500 (Location YOK)
# Beyaz listedeki host (<proje-b>: 'i.ytimg.com', 'yt3.ggpht.com')
GET /project-assets/media/<b64(https://i.ytimg.com/vi/x/default.jpg)>
→ HTTP 307
Cache-Control: private, max-age=300
Location: https://i.ytimg.com/vi/x/default.jpg
proxy_allowed_hosts gerçek tanımları (ölçüldü, project-routemap.php):
| Proje | Satır | Host'lar |
|---|---|---|
<proje-b> |
projects/<grup>/<proje>/Core/Config/project-routemap.php:15 |
i.ytimg.com, yt3.ggpht.com |
<proje-c> |
projects/<grup>/<proje>/Core/Config/project-routemap.php:16 |
image.tmdb.org |
<proje-e> |
projects/<grup>/<proje>/Core/Config/project-routemap.php:16 |
img.youtube.com |
<proje-f> |
projects/<grup>/<proje>/Core/Config/project-routemap.php:68 |
is1-ssl.mzstatic.com, www.8x8.com |
Mühendislik notu:
AssetConfig::PROXY_ALLOWED_HOSTSboş bırakılmış olması doğru davranıştır
(Anayasa §9: framework'e proje/müşteri adı yazılmaz). Dış CDN kullanacaksanız listeyi projenizin
project-routemap.php → view_mapping.<alt-proje>.proxy_allowed_hostsgirdisine ekleyin —
framework'e değil.
5.5 Fiziksel keşif (AssetResolver)
Core/System/Discovery/Clusters/Resources/AssetResolver.php, resolve($name, $context).
| Adım | Satır | Davranış |
|---|---|---|
| 1 | 24-25 | path_symmetric($name), baştaki / ve \ atılır |
| 2 | 29-40 | Project first: Paths::project()->public() altında tam yol |
| 3 | 43-66 | Framework: Paths::framework()->assets() altında tam yol, sonra Paths::framework()->resources() altında tam yol |
| 4 | 68-89 | Düzleştirilmiş yol kurtarma: ilk segment = küme adayı; küme klasörü glob ile büyük/küçük harf duyarsız bulunur, sonra deepSearch() (:113-125) özyinelemeli olarak dosya adını arar |
| 5 | 91-104 | Akıllı desen: ^rbn([A-Z][a-zA-Z0-9]+)\.(css|js)$ → RbnCommon/<css|js>/components/<ad> |
resolve() üç source değeri döndürür: 'project', 'framework', (yoksa) null.
X-RBN-Source başlığı bunu yazar (:154) — canlı: proje CSS → X-RBN-Source: project,
framework CSS → X-RBN-Source: framework. Ölçüldü.
6. Font sistemi (AssetFonts)
Core/Support/Definitions/Render/AssetFonts.php, 74 satır.
6.1 FONT_LIBRARY — 33 slug, hepsi Google Fonts
Ölçüldü (AssetFonts.php:19): 33 anahtar. Slug kuralı
AssetController.php:60: strtolower(str_replace(' ', '-', $name)) — tire, boşluk→tire, küçük harf.
| Kategori (yorum satırı) | Slug'lar (ad → slug) |
|---|---|
Modern Sans-Serif (:20) |
Inter→inter, Outfit→outfit, Plus Jakarta Sans→plus-jakarta-sans, Poppins→poppins, Manrope→manrope, Geist→geist, Roboto→roboto, Montserrat→montserrat, IBM Plex Sans→ibm-plex-sans |
Expressive / Editorial Display Serif (:31) |
Fraunces→fraunces, Newsreader→newsreader, Instrument Serif→instrument-serif, DM Serif Display→dm-serif-display, Cormorant Garamond→cormorant-garamond, EB Garamond→eb-garamond, Bodoni Moda→bodoni-moda, Cardo→cardo, Source Serif 4→source-serif-4, Spectral→spectral, Crimson Pro→crimson-pro, Playfair Display→playfair-display, Lora→lora |
Brutalist / Poster / Dynamic (:46) |
Bricolage Grotesque→bricolage-grotesque, Space Grotesk→space-grotesk, Syne→syne, Anton→anton, Big Shoulders Display→big-shoulders-display, Tomorrow→tomorrow |
Monospace (:54) |
JetBrains Mono→jetbrains-mono, Space Mono→space-mono, Geist Mono→geist-mono, IBM Plex Mono→ibm-plex-mono, Fira Code→fira-code |
Hedef URL biçimi (33/33): https://fonts.googleapis.com/css2?family=<Ad:+,@,&ital…>&display=swap.
Kütüphane URL'si tek tek elle yazılmıştır; <slug> = ad → kısa-i dönüşümü yalnız istem yolunda
(AssetController.php:60) ve URL üretiminde (AssetBuilder.php:321) uygulanır.
6.2 Doğrudan erişim takma adları (:65-80)
16 sabit (INTER, OUTFIT, GEIST, JETBRAINS_MONO, SPACE_MONO, GEIST_MONO,
PLUS_JAKARTA_SANS, POPPINS, SYNE, MANROPE, FRAUNCES, NEWSREADER, INSTRUMENT_SERIF,
DM_SERIF_DISPLAY, BRICOLAGE_GROTESQUE, SPACE_GROTESK) — yalnız sekmey tamamlama için
(:63 yorumu). Çalışma zamanında kullanılmıyor; @font/<ad> metinini kullanmak daha doğru.
6.3 Font <link>'i neden <head>'de iki yerde basılmaz?
Font linkleri SEO katmanında basılır, asset katmanında filtrelenir:
AssetProvider::renderStyle()(:78-81) →/framework-assets/fonts/içeren yol için''döner.SeoProvider::renderLinks()(Core/Render/Providers/SeoProvider.php:204) →assetBuilder->build()
sonucunu gezer,/framework-assets/fonts/içerenleri<link rel="stylesheet">olarak basar.
renderLinks() ayrıca preconnect ekler (SeoProvider.php:201):
https://fonts.googleapis.com ve https://fonts.gstatic.com (crossorigin).
Her canlı sayfada bu iki satır doğrulandı.
Sıralama: header şablonu (Resources/Views/RbnCommon/header.rbn.php:14):
<head>
{!! $appSeoHtml !!} ← SEO: preconnect + FONT linkleri + favicon
{!! $headerAssets !!} ← Asset: CSS + head script'leri (fontlar ZATEN basıldığı için atlanır)
{!! $appSchemaHtml !!} {!! $headStateHtml !!} {!! $google_analytics_code !!}
{!! $google_adsense_code !!} {!! $head_scripts !!}
</head>
6.4 Panele özel font paketleri (kim ne zaman yükler)
| Paket | Fontlar | Ne zaman |
|---|---|---|
fonts_panel (AssetBundles.php:36) |
Plus Jakarta Sans, DM Serif Display, JetBrains Mono | panel bağlamında otomatik |
fonts_auth (:37) |
Plus Jakarta Sans | auth bağlamında otomatik |
frontend |
— | otomatik font yok; @font/<Ad> ile addAsset() gerekir, hiç istenmezse fallback Inter |
Canlı kanıt — auth sayfası (https://example.tr.test/rbn-admin, HTTP 200):
<link href="…/framework-assets/fonts/inter" ← fallback Inter (priority 5)
<link href="…/framework-assets/fonts/plus-jakarta-sans" ← fonts_auth paketi
<link href="…/framework-assets/images/favicon-rbnauth.svg=v1787673791
<link href="…/framework-assets/rbncommon/rbn-master.css=v1791201628
<link href="…cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.css
<link href="…/framework-assets/rbncommon/rbn-auth.css=v1791205000
<script src="…/framework-assets/rbncommon/rbn-master.js=v1788037859"
jQuery auth sayfasında YOK — doğru (STACK_MAP['auth'] yalnız fonts_auth + rbn_core_auth).
Auth sayfasında Bootstrap/BAI/FA da yok — injectCoreStack() :259-261 baypası çalışıyor.
rbn-auth.css dosyası, eskiden auth_header.rbn.php içindeki 12 501 baytlık view-içi <style>
bloğunun taşındığı yerdir (AssetBundles.php:58 yorumu).
6.5 "Fontu yerelden sunabilir miyim?" — HAYIR, destek yok
Kodda fonts/ rotasının yalnız FONT_LIBRARY 307 yönlendirmesi vardır (AssetController.php:55).
Yerel .ttf/.woff2 dosyası için fonts/ rotasında hiçbir dal yok. Ölçüldü:
GET /framework-assets/fonts/BebasNeue-Regular.ttf → 500.
Framework'te 3 yerel TTF vardır — Resources/Assets/RbnCommon/fonts/:
BebasNeue-Regular.ttf (61 400), Montserrat-Bold.ttf (200 460), Poppins-Bold.ttf (155 996).
Bunlar fonts/ rotasından değil, düz framework keşfinden servis edilir:
GET /framework-assets/rbncommon/BebasNeue-Regular.ttf → 200 (düzleştirme kuralı, §4.4).
Yeni yerel font isteyen bir proje için yol haritası (kod değişikliği gerekir):
Assets/altına (veya projeninpublic/fonts/).woff2koyun.- Proje
master.cssiçinde@font-face { src: url('/project-assets/fonts/<ad>.woff2') }yazın
—frontend-and-ui.md§2.1 yalnız Google Fonts@import'unu yasaklar,@font-faceyazmaz. - Ya da framework'e bir dal eklersiniz:
AssetController.php:55bloğu, slug eşleşmediğinde
fonts/<slug>.<ext>dosyasınıAssets/altında aramayı dener. Bu bir motor değişikliğidir;
§11.1'de tarif edilen üç adımlı yol tercih edilir.
7. CSS katmanları
7.1 rbn-master.css @import zinciri (19 dosya, sıra önemli)
Resources/Assets/RbnCommon/css/rbn-master.css (29 satır, ham 1 097 bayt) — yalnız @import.
| # | Satır | Dosya | Katman |
|---|---|---|---|
| 1 | 7 | rbn-colors.css |
A — Master renk kütüphanesi (24 rainbow + nötr) |
| 2 | 10 | core/tokens.css |
A — token tanımları |
| 3 | 11 | core/reset.css |
A — reset |
| 4 | 12 | core/layout.css |
A + B (12-kolon ızgara, .d-flex, .py-*, .mb-*) |
| 5 | 13 | core/utilities.css |
B (tek yönlü pt-*/pb-*, gap-*, rounded-*) |
| 6 | 14 | core/buttons.css |
A (.rbn-btn*) |
| 7 | 15 | core/forms.css |
A (.rbn-form-*) |
| 8 | 16 | core/cards.css |
A (.rbn-card*, .object-*) |
| 9 | 17 | core/badges.css |
A (.rbn-badge*) |
| 10 | 18 | core/tabs.css |
A |
| 11 | 19 | core/dropdowns.css |
A |
| 12 | 20 | core/elements.css |
A |
| 13 | 21 | core/surfaces.css |
A |
| 14 | 22 | core/colors.css |
B (text-*, bg-*) |
| 15 | 23 | core/responsive.css |
A/B duyarlılık |
| 16 | 26 | rbn-common.css |
A/B ortak araçlar |
| 17 | 27 | components/rbnAlert.css |
A |
| 18 | 28 | components/rbnModal.css |
A |
| 19 | 29 | components/rbnTable.css |
A |
Kapanışa girmeyenler (ve neden): core/dashboard.css (yalnız panel),
core/rbn-auth.css (yalnız auth), optional/* (opsiyonel paket), rbn-shield.css
(hiçbir pakette yok — §13-B1), rbn-terminal.css (hiçbir paket/sabit yok — §13-B10).
7.2 ÖLÇÜLEN boyut tablosu
Ölçüm yöntemi: gzip.compress(baytlar, 9) (Python gzip — sunucudaki gzip seviyesiyle birebir
aynı değildir; göreli karşılaştırma içindir). Kapanış = 19 dosyanın toplamı.
| Dosya | Ham (bayt) | gzip -9 (bayt) |
|---|---|---|
rbn-colors.css |
6 331 | 2 160 |
core/tokens.css |
3 274 | 960 |
core/reset.css |
866 | 407 |
core/layout.css |
16 978 | 3 078 |
core/utilities.css |
12 075 | 2 725 |
core/buttons.css |
15 510 | 2 972 |
core/forms.css |
12 754 | 2 938 |
core/cards.css |
10 950 | 2 819 |
core/badges.css |
5 182 | 1 626 |
core/tabs.css |
4 178 | 1 263 |
core/dropdowns.css |
3 900 | 1 207 |
core/elements.css |
20 481 | 4 707 |
core/surfaces.css |
8 050 | 2 076 |
core/colors.css |
12 844 | 2 339 |
core/responsive.css |
8 834 | 2 276 |
rbn-common.css |
15 287 | 3 412 |
components/rbnAlert.css |
19 327 | 4 029 |
components/rbnModal.css |
12 660 | 2 745 |
components/rbnTable.css |
18 482 | 4 203 |
| KAPANIŞ TOPLAM (19 dosya) | 207 963 | 47 942 |
rbn-master.css (kapanış dosyasının kendisi) |
1 097 | 422 |
optional/rbn-utilities-extended.css |
21 642 | 3 932 |
optional/rbn-components-extended.css |
20 746 | 4 446 |
core/dashboard.css (panel) |
16 231 | 3 244 |
core/rbn-auth.css (auth) |
12 853 | 2 692 |
rbn-shield.css (bağsız) |
13 155 | 3 070 |
rbn-terminal.css (bağsız) |
5 189 | 1 388 |
Sunulan boyut farkı: canlıda rbn-master.css Content-Length: 1420 (banner ≈ +323 bayt) ve
Accept-Encoding: gzip ile Content-Encoding: gzip gönderiliyor. Yani tarayıcı 19 dosyayı
ayrı ayrı değil, @import zinciriyle 19 ayrı istek olarak çekiyor (§13-B11).
7.3 Üç katmanlı adlandırma (design-system §4.2 ile uyum)
design-system.md §4.2'deki tablo kod taramasıyla doğrulandı:
| Katman | Önek | Nerede tanımlanır | Doğrulama |
|---|---|---|---|
| A. Çekirdek bileşen | rbn- (her zaman) |
core/*.css, components/*.css |
✅ kapanışta 471 rbn- sınıfı |
| B. Yardımcı (utility) | ön eksiz (Bootstrap uyumlu) | yalnız core/layout.css, core/utilities.css, core/colors.css |
✅ kapanışta 722 ön eksiz sınıf |
| C. Alan (domain) | rbn-{alan}- |
ilgili bundle dosyası | ✅ rbn-auth-*, rbn-dash-*, rbn-admin-* örnekleri mevcut |
"Ön eksiz utility yalnız B katmanında tanımlanır" kuralı: tarama sonucu tutarlı —
core/layout.css, core/utilities.css, core/colors.css dışında ön eksiz sınıf tanımı yok
(.object-cover gibi cards.css içindeki 5 istisna hariç — §13-B12).
Token düzeni (core/tokens.css, 66 satır): 8 grup hâlinde --rbn-*:
| Grup | Satır | Örnekler |
|---|---|---|
| Canvas & Surface | 7-10 | --rbn-bg-canvas, --rbn-bg-surface, --rbn-bg-surface-subtle, --rbn-bg-surface-hover |
| Typography & Ink | 13-20 | --rbn-font-sans, --rbn-font-display, --rbn-font-mono, --rbn-text-display/primary/secondary/muted |
| Brand & Functional | 23-31 | --rbn-primary, --rbn-primary-hover, --rbn-secondary, --rbn-accent, --rbn-success, --rbn-warning, --rbn-danger |
| Borders & Hairlines | 34-36 | --rbn-border, --rbn-border-subtle, --rbn-border-strong |
| 8-Point Spatial Grid | 39-49 | --rbn-space-0..16 |
| Geometry & Radius | 52-56 | --rbn-radius-none/sm/md/lg/pill |
| 3-Level Elevation | 59-63 | --rbn-shadow-sm/card/hover/modal, --rbn-bg-overlay |
| On-primary | 64 | --rbn-text-on-primary |
Kritik tasarım kararı — token çift katmanlı (:7-63):
--rbn-* token'ları her zaman bir proje token'ına geri düşer:
--rbn-bg-canvas: var(--bg-canvas, var(--rbn-slate-50));
--rbn-primary: var(--primary-color, var(--rbn-blue-600));
--rbn-radius-md: var(--radius-md, 10px);
Yani proje variables.css yalnız --rbn-* DEĞİL, ön ek olmadan (--bg-canvas,
--primary-color, --font-display, --radius-md, --border-color, --shadow-card…) tanım
yapar ve motor onları otomatik toplar. Bu, design-system.md §1.3'ün
"variables.css: sadece renk/zemin/font/radius token'ları" ile birebir örtüşür.
Örnek: domains/<marka>/example.tr/css/variables.css --primary-color, --bg-canvas,
--font-mono, --text-display vb. tanımlıyor; core/tokens.css bunları --rbn-* altına topluyor.
8-Point ızgarası — iki FARKLI ölçek var (kritik!):
| Ölçek | Değerler | Kaynak |
|---|---|---|
core/tokens.css --rbn-space-* |
0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64 (-0..-16) |
tokens.css:39-49 |
.p-*/.py-* eşlemesi |
.p-1=4 · .p-2=8 · .p-3=16 · .p-4=24 · .p-5=32 · .p-6=48 |
design-system.md §4.2 + utilities.css |
docs/gorevler/css-bootstrap-rbn-esleme.json sayiOlcegi |
"1=4px 2=8px 3=12px 4=16px 5=20px 6=24px" (--rbn-space-{0,1,2,3,4,5,6,8,10,12,16}) |
JSON :14 |
⚠️ Bu üçü çelişiyor. design-system.md §4.2 .p-3 = 16px derken utilities.css:17 de
.pt-3 { padding-top: var(--rbn-space-4) } → 16px ✓ aynı; ama eşleme JSON'u .p-3 → 12px
diyor. --rbn-space-3 = 12px. Yani design-system.md ile eşleme JSON'u birbirini tutmuyor.
Kod doğrusu: utilities.css:17 (--rbn-space-4 = 16px). JSON §13-B13'e yazıldı.
7.4 Proje CSS'i (project-assets/css/*)
-
Kaynak:
domains/<proje_yolu>/css/. Ölçüldü: 21master.css, hepsicss/altında. -
Giriş noktası:
rbn_core_frontendpaketi@project/css/master.css'i her frontend sayfasında
otomatik yükler (AssetBundles.php:48). -
Yükleme sırası:
build()comparator kural 1 →/project-assets/daima en son
(AssetBuilder.php:166). Yani proje CSS'i framework'ü ve CDN'leri ezebilir. -
İçerik deseni:
master.cssbir@importgirişidir (kopyala-yapıştır örnekler):/* LUMIÈRE Master CSS Import */ @import url('variables.css'); @import url('global.css'); @import url('common.css'); @import url('components.css'); @import url('header-footer.css'); @import url('hero.css'); … @import url('responsive.css');/* 1. Variables - Renk paleti ve sabitler */ @import url('variables.css'); /* 2. Layout & Components */ @import url('layout.css'); @import url('m-components.css'); /* 3. Pages & Tools */ @import url('m-pages.css'); @import url('m-blog.css'); @import url('m-tools.css'); -
Kural (frontend-and-ui.md §3): CSS
domains/<public_path>/css/altında, tek dosyaya
doldurma yasağı,variables.cssyalnız token,modules/<modül>.cssmodül bazlı,
master.css@importbirleştirici. 21 projenin hepsi bu yapıda.
Ölçülen uyarı — proje CSS'i büyüyor: <proje-c> master.css 13 @import satırı içeriyor.
design-system.md §4.2 "proje CSS'i mümkün olduğunca az (hedef: sıfıra yakın)" diyor;
bootstrap-eksiksizlik.md/eşleme tablosu bu yönde ilerleme kaydediyor. §13-B14'e not.
7.5 optional/ paketleri (isteğe bağlı)
| Sabit | Satır | Dosya | Ham | gzip |
|---|---|---|---|---|
RBN_EXTENDED_UTILITIES_CSS |
AssetDefinition.php:55 |
optional/rbn-utilities-extended.css |
21 642 | 3 932 |
RBN_EXTENDED_COMPONENTS_CSS |
AssetDefinition.php:56 |
optional/rbn-components-extended.css |
20 746 | 4 446 |
Paket: rbnExtended (AssetBundles.php:72).
Kim/nasıl yükler (yorum :69-71):
// Iste: `assets => ['rbnExtended']` (Map) veya `$this->addAsset('rbnExtended')` (Controller).
"HER SAYFAYA OTOMATİK YÜKLENMEZ" doğrulaması (üç bağımsız kanıt):
rbn-master.cssiçindeoptional/extendedgeçmişi yok (Select-String → boş).rbnExtendedadı hiçbir proje/framework PHP dosyasında istenmiyor — yalnız
AssetBundles.php'in kendi 3 satırında geçiyor (:70,:71,:72).- Canlı hiçbir sayfanın
<link>listesinderbn-utilities-extended/rbn-components-extended
yok (4 sayfa tarandı: example, <proje-a>, <proje-c>, <proje-b>). - Dosyalar yine de sunulabilir durumda:
GET /framework-assets/rbncommon/rbn-utilities-extended.css=v1→ 200 (düzleştirme).
Ölçülen çakışma: opsiyonel paketlerin 387 sınıfı var; bunların 17 tanesi zaten kapanışta
tanımlı (rbn-form-input dâhil). Bu 17 sınıf iki yerden geliyorsa son sıralama bazen farklı değer
üretebilir (özellikle !important taşıyan B katmanı yardımcıları — §88 kural). §13-B15.
7.6 "Bir sınıf motorda var mı?" — nasıl denetlenir
Yöntem 1 (canlı, tek sınıf): curl ile kapanış dosyasını indirip ara:
curl.exe -s -k https://<site>/framework-assets/rbncommon/rbn-master.css=v1 -o E:\tmp\_gecici\m.css
Select-String -Path E:\tmp\_gecici\m.css -Pattern '\.pt-3\b'
Dikkat:
rbn-master.cssyalnız@importsatırlarıdır. Sınıflar içindeki dosyalarda.
Düzleştirme kuralı sayesinde her biri doğrudan adreslenebilir:
https://<site>/framework-assets/rbncommon/core/utilities.css→ 200.
Yöntem 2 (kapsam denetimi — toplu): eşleme tablosu
E:\AgentSpace\docs\gorevler\css-bootstrap-rbn-esleme.json (135 212 bayt,
$schema: rbn-css-esleme/v1, surum: 1.1.0, uretim.tarih: 2026-10-05,
üretici FW-CSS-MOTOR-2). Yapısı:
"olcum": {
"motorKapanisDosyaSayisi": 23,
"motorKapanisSinif": 1563,
"motorKapanisRbnOnekli": 575,
"motorKapanisOneksiz": 988,
"eslemeGirdisi": 863,
"hedefTanimli": 863,
"hedefEksik": 0,
"eksikBootstrapSiniflari": [],
"paketler": { "rbn_master": "…", "rbnExtended": "…", "rbn_core_auth": "…" }
}
Her giriş {"<bootstrap-adı>": {"rbn": "<rbn karşılığı>", "durum": "TANIMLI|EKSIK", "motor": "<motor>"}}
biçimindedir (ör. :34-38 "accordion" → rbn-accordion, :64-68 "active" → active).
⚠️ JSON'un ölçüm sayıları bu belgedeki bağımsız ölçümle UYUŞMUYOR (§13-B16):
| Ölçüm | JSON (1.1.0) | Bu belgenin bağımsız ölçümü |
|---|---|---|
| Kapanış dosya sayısı | 23 | 19 |
| Kapanış sınıf | 1 563 | 1 193 |
rbn- önekli |
575 | 471 |
| Ön eksiz | 988 | 722 |
hedefEksik |
0 | — |
eksikBootstrapSiniflari |
[] (boş) |
— |
JSON'daki
hedefEksik: 0iddiası kapsam daraltılmadan anlamsız: bootstrap'ın ~1 300 sınıfının
tamamı listelenmemiş, yalnız 863 girdi taranmış ve hepsi karşılık bulmuş.
Gerçek eksik sayısı ancakcss_engine=rbnVE panel/auth kapsamına daraltılınca anlamlıdır.
Bu belgede kapsam daraltılmış ölçüm yapılmadı — bu bir sonraki görevin işidir; §13-B16'da
açıkça bırakıldı.ölcu-genis.mjsbetiği repoda bulunamadı (§13-B17).
Bu belgenin bağımsız sınıf ölçümü (yöntem ve ham sonuç):
\.(-\?[A-Za-z_][A-Za-z0-9_-]*) deseniyle, kapanıştaki 19 dosyanın birleşimi:
kapanis sinif sayisi = 1193 (471 rbn- onekli · 722 oneksiz)
opsiyonel paket sinif = 387 (bunlarin 17'si kapanista zaten var)
Bu belgede doğrulanan 25 sınıf (tümü kapanışta):
| Sınıf | Kapanışta? | Nerede |
|---|---|---|
rbn-btn, rbn-btn-primary |
✅ | core/buttons.css |
rbn-card, rbn-card-header |
✅ | core/cards.css |
rbn-container, rbn-grid-3 |
✅ | core/layout.css |
rbn-form-input |
✅ | core/forms.css |
rbn-badge |
✅ | core/badges.css |
rbn-modal |
✅ | components/rbnModal.css |
rbn-empty-state (FW-096-C3), rbn-accordion |
✅ | core/elements.css |
rbn-drawer-right (+ rbn-drawer-aside, FW-096-C3) |
✅ | core/responsive.css |
pt-3 |
✅ | core/utilities.css:17 .pt-3 { padding-top: var(--rbn-space-4) !important; } |
pb-3, mb-0, py-2, gap-4, d-flex, rounded, rounded-3, border-bottom, fs-sm, fw-bold, text-dark |
✅ | B katmanı |
text-primary |
✅ | core/colors.css tek tanım, var(--rbn-primary) (FW-096-C1: layout.css çift tanımı kaldırıldı) |
object-fit-cover |
❌ | YANLIŞ İDDİA — §13-B19 |
<projeA>-tag |
❌ | motorda yok; projelerin kendi CSS'inde (domains/<grup>/<site>/css/{components,elements}.css) |
design-system.md§4.2'dekiobject-fit-coverörneği motorda YOK.core/cards.css:363-367'de
.object-cover/.object-contain/.object-fill/.object-none/.object-scale-downvar;
.object-fit-coveryok (Select-String tümResources/Assets/**/*.css→ yalnız bu 5 +cards.css:323
bir özellik kullanımı). §13-B19.
<projeA>-tagde motorda yok —design-system.md§4.1 standart şablonunda kullanılıyor ama tanımı
projeye ait. §13-B20.
8. JS katmanları
8.1 rbn-master.js — dinamik modül yükleyici (2 740 bayt, 83 satır)
Resources/Assets/RbnCommon/js/rbn-master.js. Yükleyen paket: rbn_master_js (universal →
her bağlamda otomatik) ve rbn_master (AssetBundles.php:83).
İki bölüm:
1. rbnReady kuyruk motoru (:11-54)
window.rbnReady = rbnReady; // :47
window.rbnProcessQueue = …; // :48
window._rbnQueue = window._rbnQueue || []; // :14
Fonksiyonu document.readyState === 'loading' ise kuyruğa alır, değilse hemen çalıştırır
(:20-24). DOMContentLoaded'da kuyruk boşaltılır (:27-45).
Kullanım: rbnReady(function () { … }).
2. Dinamik çekirdek modül yükleyici (:56-81) — CSS'in @import mantığının JS karşılığı:
const basePath = currentScript ? currentScript.src.substring(0, currentScript.src.lastIndexOf('/'))
: '/framework-assets/rbncommon/js'; // :60-62
const coreModules = [
'core/rbnDom.js', 'core/rbnComponents.js',
'Utils/rbnUtils.js', 'Utils/rbnBinders.js', 'Utils/rbnFile.js',
'components/rbnAlert.js', 'components/rbnModal.js', 'components/rbnTable.js',
'Networking/rbnService.js'
]; // :64-74
coreModules.forEach(module => { /* <script src=basePath/module>, async=false */ }); // :76-81
script.async = false (:79) sıralı çalıştırma garantisi verir — rbnDom.js → rbnComponents.js
→ bileşenler sırası önemlidir.
Kapanış dışında kalan JS'ler (dinamik yüklenmez):
Utils/rbnAi.js (15 207), Networking/DebugBridge.js (11 196), components/rbnCharts.js (22 683).
rbnCharts rbnCharts paketiyle isteğe bağlı; rbnAi/DebugBridge hiçbir paketten yüklenmiyor
(§13-B1).
Boyut (ham bayt): rbn-master.js 2 740 · rbnDom.js 16 965 · rbnComponents.js 14 369 ·
rbnUtils.js 3 201 · rbnBinders.js 23 711 · rbnFile.js 7 599 · rbnAlert.js 20 453 ·
rbnModal.js 20 389 · rbnTable.js 28 272 · rbnService.js 14 152 · rbnCharts.js 22 683 ·
rbnAi.js 15 207 · DebugBridge.js 11 196 · rbnAdmin.js (RbnAdmin) · rbnAdminApp.js (RbnAdmin).
Yalnız rbn-master.js kapsamının toplamı (9 dosya): 151 852 bayt — yani ilk <script> 2 740 bayt,
kalan 8 dosya çalışma anında indirilir. §13-B11.
8.2 data-rbn-* ve data-bs-* öznitelikleri
Kritik düzeltme: "data-bs-* = Bootstrap JS" yanlıştır. Framework'ün kendi JS'i
data-bs-* özniteliklerini okur — rbnComponents.js ve rbnModal.js içinde
data-bs-toggle / data-bs-target / data-bs-parent / data-bs-dismiss /
data-bs-backdrop-static kendi seçicileriyle sorgulanır:
| Öznitelik | Okuyan yer |
|---|---|
[data-bs-toggle="dropdown"] |
core/rbnComponents.js:88 |
[data-bs-toggle="collapse"] |
core/rbnComponents.js:145 |
data-bs-target |
core/rbnComponents.js:149,187,245 |
data-bs-parent |
core/rbnComponents.js:156 |
[data-bs-toggle="offcanvas"] |
core/rbnComponents.js:184 |
[data-bs-dismiss="offcanvas"] |
core/rbnComponents.js:214 |
[data-bs-toggle="tab"], [data-bs-toggle="pill"] |
core/rbnComponents.js:241 |
[data-bs-dismiss="modal"] |
components/rbnModal.js:35 |
data-bs-backdrop-static |
components/rbnModal.js:44 |
data-bs-title (tooltip) |
core/rbnDom.js:173 (üretir) |
Ayrıca rbnComponents.js:38 data-bs-toggle="dropdown" özniteliğini kendisi üretir
(native <select> → custom dropdown dönüşümünde, :35-40).
Yani: css_engine='rbn' projelerinde Bootstrap JS yüklü değil ama Bootstrap'ın data-bs-*
sözleşmesi motor tarafından geriye uyumlu olarak uygulanıyor. Ölçüldü: framework JS'inde
data-bs- eşleşmesi 21 satır, hepsi yukarıdaki okuma noktaları.
Desen (her yerde aynı): data-bs-X önce, data-rbn-X fallback:
// rbnComponents.js:88
const toggle = e.target.closest('[data-bs-toggle="dropdown"], [data-rbn-toggle="dropdown"], .dropdown-toggle');
// rbnComponents.js:149
const targetSelector = btn.getAttribute('data-bs-target') || btn.getAttribute('data-rbn-target') || btn.getAttribute('href');
// rbnModal.js:26
const trigger = e.target.closest('[data-rbn-modal="true"], [data-rbn-toggle="modal"], .notification-modal-btn');
// rbnModal.js:35
const closeBtn = e.target.closest('[data-bs-dismiss="modal"], [data-rbn-dismiss="modal"], .btn-close, .modal-close-btn');
⚠️
rbnModal.js:24yorum satırı[data-rbn-modal="true"], [data-bs-toggle="modal"], [data-rbn-toggle="modal"]
diyor ama:26'daki gerçek seçici[data-bs-toggle="modal"]içermiyor. Yorum kod ile uyuşmuyor.
§13-B21.
data-rbn-* envanteri (framework JS'i, 43 benzersiz):
data-rbn-toggle (11), data-rbn-otp (6), data-rbn-table-reset (5), data-rbn-table-search (5),
data-rbn-ai (4), data-rbn-chart (4), data-rbn-preview (3), data-rbn-sort-select (3),
data-rbn-table-filter (3), data-rbn-target-table (3), data-rbn-filter-col (3),
data-rbn-target (3), data-rbn-form (3), data-rbn-password-toggle (3), data-rbn-dismiss (3),
data-rbn-file-label (2), data-rbn-filter-attr (2), data-rbn-table-export (2),
data-rbn-table-sort (2), data-rbn-cascade (2), data-rbn-confirm (2), data-rbn-mask (2),
data-rbn-copy (2), data-rbn-password-generate (2), data-rbn-geo (2), data-rbn-modal (2),
data-rbn-redirect, data-rbn-sortable, data-rbn-theme-icon, data-rbn-status-toggle,
data-rbn-enhanced, data-rbn-select, data-rbn-drawer, data-rbn-parent, data-rbn-ajax,
data-rbn-bulk-action, data-rbn-tooltip, data-rbn-scroll-top, data-rbn-password-length,
data-rbn-type, data-rbn-action, data-rbn-theme-toggle, data-rbn-title.
8.3 Dış kütüphaneler: kim ne zaman yükler
| Kütüphane | Yükleme yolu | Otomatik mi? | Ölçülen canlı |
|---|---|---|---|
| jQuery 3.7.1 | jquery paketi → STACK_MAP['panel'] |
yalnız panel, otomatik |
rbn-admin (auth) sayfasında yok ✓; frontend'de yok ✓ |
| SortableJS 1.15.2 | sortable paketi → STACK_MAP['panel'] |
yalnız panel, otomatik |
— |
| Bootstrap JS 5.3.2 | bootstrap paketi → STACK_MAP['universal'] |
evet, ama rbn/panel/auth'ta baypas |
<proje-b> ve <proje-c> sayfalarında var; example/<proje-a>/rbn-admin sayfasında yok ✓ |
| AOS 2.3.4 | aos paketi |
hayır — addAsset('aos') gerekir |
<proje-b> (<projeB>/<projeB2> addAsset('aos', …)) ve example (MainFrontendController.php:35) sayfalarında css+js var; <proje-a>/<proje-c> sayfasında yok ✓ |
Chart.js (rbnCharts paketi) |
rbnCharts paketi |
hayır | <proje-a> <alt-site-a> sayfasında isteniyor (<projeA>FrontendController.php:28); ana <site-a> sayfasında yok ✓ |
| Google Tag Manager | ⚠️ paket/AssetDefinition YOK | — | <proje-b> ana sayfasında <script src="https://www.googletagmanager.com/gtag/js?id=G-J49KXF3T2L"> var; bu asset sisteminden gelmiyor (§13-B4) |
8.4 Bootstrap JS olmadığında ne olur (davranış)
rbn-master.js → rbnModal.js başlıklı yorumu (:1-8) bunu açıkça söyler:
"100% Native Pure JavaScript (Zero Bootstrap JS & Zero jQuery Dependency)".
Sonuç: data-bs-toggle="modal|dropdown|tab|collapse|offcanvas", data-bs-dismiss,
data-bs-target, data-bs-parent çalışır; ama Bootstrap'ın JS API'si
(new bootstrap.Modal(), bootstrap.Tooltip(), bootstrap.Dropdown nesneleri) yoktur.
Tooltip/modal kendi motoruyla çalışır (rbnDom.js tooltip, rbnModal.js modal).
9. İkon sistemi
9.1 Üç ayrı ikon ailesi, üç ayrı kaynak
| Aile | Kaynak | Yükleme | Ölçülen kullanım (view satırı) |
|---|---|---|---|
Remix Icon (ri-*) |
CDN remixicon@4.2.0 |
remix_icon paketi → STACK_MAP['universal'], her sayfada otomatik |
2 527 ✅ fiili standart |
Bootstrap Icons (bi-*) |
CDN bootstrap-icons@1.11.3 |
bootstrap_icons paketi → universal, ama rbn/panel/auth'ta baypas |
726 — bu projelerde boş (§13-B5) |
Font Awesome (fas/fa*) |
CDN font-awesome@6.5.1 |
font_awesome paketi → universal, rbn/panel/auth'ta baypas |
0 (view class özniteliğinde) |
| flag-icon-css | CDN flag-icon-css@6.6.6 |
flag_icon paketi — hiçbir STACK_MAP girdisinde YOK |
2 isteyici (<projeC>FrontendController.php:23, PanelMap.php) |
Frame notu:
IconLibrary'nin icon listeleribi-/fasklasör adları olarak kullanılır
(IconLibrary.php:34:bootstrap_icons.php,font_awesome.php). Bu,rbnmotorunda
Bootstrap Icons CDN'i yüklenmediği halde panel ikon listelerinin hâlâbi-*sınıfları
döndürebileceği anlamına gelir — panel bağlamıbootstrap_icons'u baypas ediyor.
Ölçülen kanıt:rbn-adminlogin sayfasındabi-*veyafa*CDN linki yok
(auth bağlamı baypası). §13-B5.
9.2 IconLibrary / SmartIconCategories
Core/Support/Bridges/Helpers/Library/IconLibrary.php (105 satır) — kayıt:
Core/System/Registries/RegistryMap/SystemResourceMapTrait.php:31 → 'icons' => IconLibrary.
| Metot | Satır | Ne yapar |
|---|---|---|
all() |
32-43 | Icons/Internal/bootstrap_icons.php + font_awesome.php (solid+regular+brands) → IconCollection |
category(string $categoryName) |
51-78 | 7 kategoriye yönlendirir: admin, developer, popular, sidebar, menu, form, status |
search(string $keyword) |
83-86 | all() içinde arama → ilk eşleşen IconCollection |
match(string $keyword, string $default = 'bi-circle') |
99-102 | SmartIconCategories::matchKeyword() → anahtar kelime → ikon sınıfı |
Sabitler BOOTSTRAP='bootstrap', FONTAWESOME='fontawesome', ALL='all' (:19-21) —
dokümanlama düzeyinde; metotlarda kullanılmıyor.
SmartIconCategories (Icons/SmartIconCategories.php) her kategoriyi
'sınıf' => ['label' => 'Türkçe etiket', 'emoji' => '…'] biçiminde döndürür
(ör. 'bi bi-speedometer2' => ['label' => 'Dashboard', …], :23).
Panel ikonları ri-* olarak da tanımlı (PanelMap.php: 'icon' => 'ri-dashboard-line',
'icon' => 'ri-line-chart-line', 'icon' => 'ri-terminal-box-line').
9.3 "icon()-benzeri" yardımcı var mı?" — framework seviyesinde YOK
icon() adlı bir global yardımcı framework'te yok. Tarama:
Get-ChildItem -Recurse -Include *.php -Path rbnframework + function icon → tek eşleşme
Bundles/RbnSuite/RbnAdmin/Providers/SocialMediaProvider.php:82 (public function icon(): string —
bir sınıf metodu, view helper değil, sosyal medya sağlayıcısının ikon alanı).
Kullanılan desen (view'larda): düz sınıf adı —
<i class="ri-close-line"></i>, <i class="ri-arrow-down-s-line opacity-50"></i>
(rbnComponents.js:40,54).
Yardımcı sınıflar: IconCollection (Icons/IconCollection.php), SmartIconCategories,
ColorHelper, FormatHelper, TextHelper, MetaSeoHelper — hepsi Core/Support/Bridges/Helpers/
altında. Global fonksiyon dosyaları: Helpers/Global/{http,project,support,system}_helpers.php
Helpers/rbn_helpers.php.
9.4 SVG ikon varlıkları
Framework'te statik SVG ikon dosyası yok (Get-ChildItem -Recurse -Include *.svg -Path rbnframework\Resources\Assets → boş). SVG'ler çalışma anında üretilir:
- Sanal logo/favicon:
AssetController::serveVirtualResource()(:409-453) —
resolver('seo')->getVirtualResourceRaw($name)→ yoksaSeoConfig::LOGO_SVGfallback'i
(:416-419).data:image/svg+xml;base64,…önekini temizler (:422-433). - Sanal OG görseli:
serveVirtualOgImage()(:376-407) — §10.
10. Favicon / OG görseli konvansiyonu (AssetConvention)
Core/Support/Definitions/Render/AssetConvention.php, 228 satır.
Dosya dokümanı (:22-32) "dört kapı"nın aynı kararı vermek zorunda kaldığını ve bu sınıfın
tek doğruluk kaynağı olduğunu anlatıyor: SeoResolver, AssetController,
RedirectManager::selfHealingAssets(), SchemaResolver.
10.1 Ad kalıbı
| Varlık | Kural | Uzantılar (öncelik sırasıyla) | Konum |
|---|---|---|---|
| favicon | favicon-<project_key>.<ext> |
svg, png, ico (:43) |
images/ |
| og image | og-image-<project_key>.<ext> |
png, jpg, webp (:46) |
images/ |
| apple-touch-icon (FW-096-C7) | apple-touch-icon-<project_key>.png |
png (180x180, zeminli) |
images/ — dosya varsa <link rel="apple-touch-icon"> |
| web manifest (FW-096-C7) | manifest-<project_key>.webmanifest |
webmanifest, json |
images/ — dosya varsa <link rel="manifest"> |
Anahtar normalizeKey() (:219-228) ile normalize edilir: küçük harf, trim, [a-z0-9_-]{1,64}
deseni. Uymayan anahtar null → bozuk ad (og-image-.png) üretilmez.
10.2 Aday listeleri (geriye uyum, "son geri dönüş")
faviconCandidates() (:62-83), öncelik sırasıyla:
images/favicon-<key>.{svg,png,ico}← KURALimages/<key>.{svg,png,ico}← eski (anahtarlı, kural dışı ad)images/favicon.{svg,png,ico}← eski (anahtarsız)
ogImageCandidates() (:90-107):
images/og-image-<key>.{png,jpg,webp}← KURALimages/og-image.{png,jpg,webp}← eski
findFavicon() / findOgImage() (:115-130) listede gerçekten var olan ilk dosyayı döndürür
(firstExisting(), :235-250). findOgImage() dosya yoksa null döner → og:image meta
etiketi hiç üretilmez (uydurma görsel yasak, :120-126).
10.3 Sanal OG görseli rotası
/project-assets/og-image-<key>.<png|jpg|webp> → AssetController::serveVirtualOgImage() (:376-407).
- Tanıma:
isVirtualOgImageName()(:183-198) —VIRTUAL_OG_PATTERN
/^og-image-([A-Za-z0-9_-]{1,64})\.(png|jpg|webp)$/(:55); ayrıca/,\,..ve kontrol
karakteri reddi. - Çözümleme:
resolveVirtualOgImage()(:143-178) —Paths::isInitialized()değilsenull(sessiz fallback,:256-265).public/images/<ad>fiziksel dosya kontrolü.realpath()kök sızırma kontrolü (:167-177): çözülen yolpublic/images/altında mı?
rtrim(realpath(public/images), '/') . '/'öneki ile başlıyor mu — sembolik bağlantı ve..
kaçışı bu adımda kapanır ([R-14]).
- MIME:
ogImageMimeType()(:203-213) —png→image/png,jpg/jpeg→image/jpeg,webp→image/webp,
bilinmeyen →null→ 404. - Başlıklar:
Cache-Control: public, max-age=31536000(:398),X-RBN-Source: ProjectConvention(:400),
X-RBN-Resource: <guvenliBaslikDegeri()>(:403). guvenliBaslikDegeri()(:351-364) — kontrol karakteri ayıklanır,basename()ile sınırlandırılır,
255 bayta kırpılır, boşsa'bilinmiyor'.
Bu dal 2026-10-05'te eklenmiş (:112-123 yorumu): öncesinde yalnız .svg açıktı, raster OG
görselleri fiziksel keşfe düşüyor ve og:image her sitede ölü URL üretiyordu.
Canlı kanıt:
| Site | <link rel="icon"> |
og:image |
|---|---|---|
example.tr.test |
/project-assets/favicon-example.svg |
… |
<site-a2>.test |
/project-assets/favicon-<proje-a>.svg |
… |
<site-b>.test |
/project-assets/favicon-<proje-b>.svg |
/project-assets/og-image-<proje-b>.png |
<site-c>.test |
/project-assets/images/favicon-<proje-c>.png=v1782671388 |
… |
rbn-admin (auth) |
/framework-assets/images/favicon-rbnauth.svg=v1787673791 |
… |
Fark gözlemlendi: Yeni siteler
AssetConventionkuralına uyuyor
(favicon-<key>.svg, dosya kökünde),<proje-c>ise projeimages/klasöründe ve
sürüm son ekli (=v1782671388) — yaniSeoResolvermeta etiketi üretirken fiziksel yolu
doğrudan basıyor, sanalAssetControllerrotasını kullanmıyor. İki yol birlikte çalışıyor;
AssetConvention'ın tek doğruluk kaynağı olma hedefi tam kapanmamış (§13-B22).
<proje-b>og:imageise sanal rotayı kullanıyor ✓ — yani yeni kural uygulanıyor.
Favicon <link> basımı: SeoProvider::renderLinks() (:221-232) — type uzantıdan türetilir
(.png→image/png, .svg/data:image/svg→image/svg+xml, aksi halde image/x-icon).
11. "Bir kaynağı nasıl ister / değiştiririm" tarifleri
11.1 Yeni bir CDN kütüphanesi ekleme (3 adım — paket üzerinden)
Adım 1 — sabit (Core/Support/Definitions/Render/AssetDefinition.php, CDN bloğuna):
public const CHARTJS_JS = 'https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js';
Kural: sürümü URL'ye yaz, açıklama metni Türkçe, sabit adı İngilizce
(.agents/rules/core-architecture.md§10). Proje/müşteri adı yazma (§9).
Adım 2 — paket (AssetBundles.php, BUNDLES):
'chartJs' => ['scripts' => [AD::CHARTJS_JS]],
Adım 3 — iste (2 yol):
// (a) Controller — yalnız o sayfaya özel
$this->addAsset('chartJs');
// (b) Panel/Map alt modülü — kalıcı olarak o modülde
// PanelMap.php: 'assets' => ['chartJs'],
Asla yapma: view/layout'da <script src="…"> elle yazma, <style>/style= kullanma
(frontend-and-ui.md §1, design-system.md §5).
Bir paket STACK_MAP'e girerse her sayfaya otomatik yüklenir — bu bilinçli bir karar olmalıdır
(§12'deki dış istek sayısına bak).
11.2 Yerel CSS/JS dosyası ekleme (proje tarafı — kod değişikliği gerekmez)
// projects/<proje>/Modules/Frontend/<Modül>/Controllers/<X>FrontendController.php
protected function onAfterBoot(): void
{
parent::onAfterBoot();
// Yalnız SAYFAYA ÖZEL varlık — çekirdek asset'ler (rbn-master.css,
// rbn-common.css, rbnAlert.css, rbn-master.js) zaten otomatik geliyor.
$this->addAsset('@font/Syne'); // font: @font/<KütüphaneAdı>
$this->addAsset('@project/css/modules/blog.css'); // proje CSS'i → EN SON
$this->addAsset('@project/js/landing.js'); // proje JS'i → footer
}
- Dosyayı
domains/<proje_yolu>/css/veyajs/altına koy (frontend-and-ui.md §3). .js→ footer'a basılır (renderInHead=false,AssetService::renderFooter(),:71-85).- CDN olmayan tek yol
renderInHead: true: sabiti dizi olarak tanımla
(['path' => '…', 'renderInHead' => true]), tıpkıJQUERY(AssetDefinition.php:26). - Çekirdek asset'leri
addAsset()ile tekrar ekleme (frontend-and-ui.md§2) — mükerrer<link>.
11.3 css_engine seçimi
// projects/<proje>/Core/Config/project-routemap.php
'view_mapping' => [
'<alt-proje-key>' => [
'module' => '<Modül>',
'domain' => '<site.example>',
'css_engine' => 'rbn', // ← 'rbn' yaz veya YAZMA
],
],
| Değer | Sonuç |
|---|---|
'rbn' |
Bootstrap + Bootstrap Icons + Font Awesome 0 KB baypas; rbn-master.css en üstte; common.css/rbnAlert.css mükerrerlik filtresi devrede |
yazılmamış veya 'bootstrap' |
Bootstrap 5.3.2 + BAI + FA CDN'den; rbn-master.css yüklenmez; rbn-common.css + rbnAlert.css ayrı ayrı yüklenir |
Geçiş yaparken: (1) design-system.md §1.2 gereği view'ları rbn-* sınıflarına dönüştür;
(2) frontend-and-ui.md §4.1 uyarısı: pb-*/pt-* artık tanımlı (core/utilities.css) —
eski kural geçersiz, geliştiriciyi alıkoymasın; (3) bi-* ikonları ri-*/rbn-* ile değiştir
(§13-B5); (4) docs/gorevler/css-bootstrap-rbn-esleme.json'u güncelle.
Dönüşü olmayan nokta: projeye özel CSS'te tanımlı Bootstrap'a özgü sınıflar kaybolabilir.
11.4 İsteğe bağlı CSS paketi isteme
$this->addAsset('rbnExtended'); // frontend Controller
// veya PanelMap/*Map.php: 'assets' => ['rbnExtended'],
- Eklenen:
optional/rbn-utilities-extended.css(21 642 B) +optional/rbn-components-extended.css(20 746 B). - Ham +42 388 B, gzip -9 +8 378 B (yalnız CSS; §7.2).
- Yüklenme sırası:
@project-assetsen son kuralı bu dosyalar için geçerli değil
(/framework-assets/…), yani önce framework çekirdeği, sonra opsiyonel paket gelir. - ⚠️ 387 sınıfın 17'si kapanışta zaten var (§7.5) — paketi eklerken özgüllük (specificity)
ve!important(B katmanı kuralı,design-system.md§88) çatışmasına dikkat.
11.5 Font ekleme
AssetFonts::FONT_LIBRARYiçine'Yeni Font' => 'https://fonts.googleapis.com/css2?family=…&display=swap'
veya mevcut listeden seç (§6.1).$this->addAsset('@font/Yeni Font').- CSS'te
@importile font yasak (frontend-and-ui.md§2.1) — yalnız@font-face(§6.5). - Panel/auth'ta
fonts_panel/fonts_authpaketleriniAssetBundles.php:36'den düzenle.
11.6 Bir sınıf motorda yok gibi görünüyorsa — teşhis sırası
css_enginedoğru mu? (rbndeğilse.rbn-*sınıflar yüklenmiyor → §4.1)- Sınıf B katmanında mı? →
core/layout.css,core/utilities.css,core/colors.css(§7.3) - Opsiyonel pakette mi? →
optional/*.css(§7.5) - Proje CSS'inde tanımlı mı? →
domains/<proje>/css/*.css(bu kural ihlali —design-system.md§4.2) - Adlandırma:
.pt-3var,.pt-md-3yok (kırılma son eki kaynakta önce:
rounded-3,fs-sm,rbn-btn-outline-danger— JSON:13) !importantçatışması: B katmanı!importantyazıyor (utilities.css:17), A katmanında yasak
(design-system.md§88) → yeni A sınıfı B sınıfına kaybeder.- Doğrulama: §7.6 Yöntem 1 (canlı
curl) veya eşleme JSON'u.
12. Performans notları (yalnız ölçülen)
12.1 CSS kapanışı boyutu (ham + gzip -9)
Bkz. §7.2 tam tablo. Özet:
| Ölçüm | Değer |
|---|---|
rbn-master.css kapanışı (19 dosya) |
207 963 B ham · 47 942 B gzip -9 |
rbn-master.css dosyasının kendisi |
1 097 B ham · 422 B gzip |
Canlı Content-Length (banner dâhil) |
1 420 B |
rbnExtended (2 dosya, opsiyonel) |
42 388 B ham · 8 378 B gzip |
core/dashboard.css (yalnız panel) |
16 231 B ham · 3 244 B gzip |
core/rbn-auth.css (yalnız auth) |
12 853 B ham · 2 692 B gzip |
rbn-shield.css (bağsız) |
13 155 B ham · 3 070 B gzip |
12.2 Bir sayfa için dış istek sayısı (canlı <link>+<script> taraması)
| Site | css_engine |
Dış host isteği | Yerel varlık isteği | Toplam <link>+<script> |
|---|---|---|---|---|
<site-a2>.test |
rbn |
2 (fonts.gstatic.com preconnect, remixicon.css) |
9 | 13 |
example.tr.test |
rbn |
4 (fonts.gstatic.com, remixicon.css, aos.css, aos.js) |
6 | 12 |
<site-c>.test |
bootstrap | 7 (fonts.gstatic.com, bootstrap, BAI, FA, remixicon, flag-icon, bootstrap.js) |
8 | 17 |
<site-b>.test |
bootstrap | 9 (+ GTM googletagmanager.com) |
6 | 17 |
preconnect fonts.googleapis.com yalnız <link rel="preconnect"> — istek sayımına
fonts.gstatic.com dahil, fonts.googleapis.com hariç tutuldu (istek açan değil, hazırlık).
Ölçülen fark:
css_engine='rbn'projeleri 2-4 dış istekle, bootstrap projeleri 7-9 dış istekle
çalışıyor. Fark: Bootstrap CSS (~230 KB ham) + BAI (~100 KB) + FA (~100 KB) + bootstrap.js (~80 KB).
css_engine='rbn'bunların tamamını 0'a indiriyor.
12.3 HTTP önbellekleme
| Varlık | Cache-Control |
immutable |
Kaynak |
|---|---|---|---|
| Fiziksel CSS/JS/görsel | public, max-age=31536000 (1 yıl) |
❌ | AssetController.php:152 |
| Sanal SVG (favicon/logo) | public, max-age=31536000 |
❌ | AssetController.php:440 |
| Sanal OG görseli | public, max-age=31536000 |
❌ | AssetController.php:398 |
media/<base64> 307 |
private, max-age=300 |
❌ (bilinçli kaldırıldı) | AssetController.php:99, :35-38 |
| Font 307 | (başlık yazılmıyor) | — | AssetController.php:73 |
Sürümleme =v<filemtime> ile 1 yıllık önbelleği güvenli kılar; immutable bilinçli yok
(bir kez önbelleğe alınan 307 hedefi kalıcı değişemiyordu — cache poisoning).
12.4 Sıkıştırma
AssetController Content-Encoding yazmaz — gzip web sunucusunda. Canlı kanıt:
Accept-Encoding: gzip → Content-Encoding: gzip; Content-Length: 1420 (sıkıştırılmamış
beyan, transfer sıkıştırılmış).
13. BILINMEYENLER
Kodla doğrulanamayan ya da çelişen noktalar. Her satır: gözlem + kanıt + öneri.
| # | Konu | Gözlem | Kanıt |
|---|---|---|---|
| B1 | Pakete bağlı olmayan sabitler | RBN_SHIELD_CSS, RBN_SERVICE, RBN_DEBUG_BRIDGE, RBN_AI, RBN_UTILS, RBN_BINDERS, RBN_ALERT_JS, RBN_MODAL_JS hiçbir BUNDLES paketine girmiyor. JS olanlar rbn-master.js coreModules dizisiyle dinamik yükleniyor (kabul edilebilir); CSS olan RBN_SHIELD_CSS ve JS olan RBN_SERVICE/DebugBridge/rbnAi hiçbir yoldan yüklenmiyor. |
AssetDefinition.php:47,61,62,69,67,68,63,65 ↔ AssetBundles.php:32 (çapraz arama). rbn-service.js yalnız dinamik listede (rbn-master.js:73). |
| B2 | project paketi |
'project' => ['styles' => ['@project/master.css']] (AssetBundles.php:90) kullanılmıyor ve yolu yanlış: 21 projenin master.css'i css/ altında, bu paket proje kökünü bekliyor. rbn_core_frontend zaten @project/css/master.css yüklüyor (:48). |
Get-ChildItem -Recurse -Filter master.css -Path domains → 21 dosya, hepsi */css/master.css; kök seviyede 0. 'project' adı hiçbir yerde istenmiyor. |
| B3 | Asset 404'leri 500 dönüyor | AssetController "bulunamadı" için abort(404, …) çağırıyor; Shield::abort() throw new Exception → istisna işleyicisi 500 üretiyor. Tarayıcı/SEO tarafında yanlış sinyal; CDN negatif önbellekleme de bozulur. |
AssetController.php:135 · ErrorHandlingTrait.php:65 · Shield.php:86. Canlı: /framework-assets/rbncommon/yok.css → 500; /yok-boyle-bir-sayfa-xyz → 404. Öneri: Shield::abort() http_response_code($code) + exit (veya bu dalda doğrudan 404) — ayrı görev, bu belgede kod değiştirilmedi. |
| B4 | Google Tag Manager asset sisteminden gelmiyor | <proje-b> ana sayfasında <script src="googletagmanager.com/gtag/js?id=G-J49KXF3T2L"> var; AssetDefinition/AssetBundles/addAsset içinde GTM yok (Select-String googletagmanager → projects/** 0 eşleşme). Yani header'daki $google_analytics_code kanalından geliyor — bu belgenin kapsamı dışında bir yol. |
<proje-b>-home.html <script> listesi (canlı). Get-ChildItem -Recurse -Include *.php -Path projects \| Select-String googletagmanager → 0. |
| B5 | bi-* ikonları rbn motorunda boş |
726 view satırı bi-* kullanıyor, ama injectCoreStack() (:259) bootstrap_icons'u rbn/panel/auth'ta baypas ediyor → ikon dosyası indirilmiyor, ikonlar görünmez. IconLibrary/SmartIconCategories ise panel ikon listelerini bi-* sınıflarıyla döndürüyor (IconLibrary.php:34, SmartIconCategories.php:23+) — panel bağlamı da BAI'sız. |
Ölçüm: view satırları (ri- 2 527, bi- 726, fas- 0). rbn-admin sayfasının <link> listesinde BAI CDN linki yok. |
| B6 | admin_core_css paketi ölü |
RBN_ADMIN_VARIABLES_CSS + RBN_ADMIN_GLOBAL_CSS paketi hiçbir yerden istenmiyor ve STACK_MAP'te yok. |
Select-String "'admin_core_css'" → yalnız AssetBundles.php:46. |
| B7 | security paketi |
'security' => ['scripts' => [AD::RBN_ADMIN_APP]] (:87). 22 eşleşmenin hepsi Security/Syshub controller sınıf adı; paket adı olarak istenmiyor → rbnAdminApp.js hiç yüklenmiyor. |
Select-String "'security'" → 22 dosya, hiçbiri addAsset('security') değil. |
| B8 | Varsayılan Inter fallback'i <proje-b>'da düşmüyor |
build() (:154-162) frontend'de font yoksa @font/Inter eklemeli. <proje-b> hiç addAsset font çağırmıyor, sayfada hiç font link'i yok. <proje-c> (@font/Syne) → 1 font, example (2 font) → Inter düştü, <proje-a> (açıkça @font/Inter) → 4 font. <proje-b> → 0 font (Inter de yok). Muhtemel prepare()'teki :104-112 temizleme ile build()'in :154 kontrolünün etkileşimi ya da hasAnyFont sayımının /fonts/ kalıbı. |
Canlı font link sayımı (§6.4 tablosu). Kod: AssetBuilder.php:93 ve :144-162. Kök neden bu belgede kesinleştirilemedi — example'da Space Mono varken Inter düşmesi :104-112 ile açıklanıyor; <proje-b>'da :104-112 de tetiklenmemeli (özel font yok). İnceleme gerekiyor. |
| B9 | ?v= elle sürümleme çalışmaz |
Üretici =v<filemtime> (path sonu) üretir ve serve() yalnız = ile ayırır. Elle yazılan ?v= hiçbir şeyi ayırmaz → sürümleme çalışmaz. |
AssetBuilder.php:347 · AssetController.php:48. =v1.0 ile 307 doğrulandı; ?v= ile canlı test yapılmadı (kod yolu açık). Resources/Views/Errors/Layouts/shield_header.php bu konuda elle link yazıyor (önceki analiz D-07/D-08) — bu belgede yeniden ölçülmedi. |
| B10 | rbn-terminal.css bağsız |
5 189 B ham dosya hiçbir sabitte, pakette veya @import'ta geçmiyor. |
Select-String 'rbn-terminal' tüm repo → 0 (dosya adı hariç). |
| B11 | @import ve dinamik JS: 19 + 9 = 28 ek istek |
rbn-master.css 19 @import → tarayıcı 19 ayrı istek açar (HTTP/2 altında da 19 kaynak). rbn-master.js 9 modülü document.createElement('script') ile çalışma anında ekler → 9 ek istek + JS yürütme gecikmesi. Ölçülen toplam: CSS 207 963 B / JS 151 852 B ham. |
rbn-master.css:7-29 (19 satır) · rbn-master.js:64-81 (9 modül). Canlı: example sayfasında 6 yerel varlık isteği (baskı sonrası gerçek sayım §12.2). Karar gerekiyor: kapanışı tek dosyaya birleştirmek (FW-CSS-MOTOR-2 kararı: "bundle bölme kararı (geriye uyumlu, en küçük değişiklik)" — sıra korundu, paketler ayrıldı). |
| B12 | B katmanı kuralına istisna | design-system.md §4.2: ön eksiz utility yalnız layout.css/utilities.css/colors.css içinde tanımlanır. Ama core/cards.css:363-367 ön eksiz .object-cover/.object-contain/.object-fill/.object-none/.object-scale-down tanımlıyor. |
core/cards.css:363-367 (Select-String ile doğrulandı). |
| B13 | Üç farklı boşluk ölçeği çelişiyor | design-system.md §4.2: .p-3 = 16px. docs/gorevler/css-bootstrap-rbn-esleme.json sayiOlcegi: "1=4px 2=8px 3=12px 4=16px". Kod (utilities.css:17): .pt-3 { padding-top: var(--rbn-space-4) } → --rbn-space-4 = 16px. Yani JSON ile kural belgesi çelişiyor. |
design-system.md:87 · JSON :14 · utilities.css:17 · tokens.css:42 (--rbn-space-4: 16px). Kod doğrusu (16px). Öneri: JSON'daki sayiOlcegi düzeltilsin veya --rbn-space dizini ile .p-* dizisi bilinçli ayrılsın. |
| B14 | Proje CSS'i şişiyor | <proje-c> master.css 13 @import; design-system.md §4.2 "hedef: sıfıra yakın". |
domains/<grup>/<site>/css/master.css (13 satır @import). |
| B15 | rbnExtended ile kapanış arasında 17 sınıf çakışması |
Opsiyonel paketlerin 387 sınıfından 17si zaten kapanışta. B katmanı !important yazdığı için (B14/B88 kuralı) yükleme sırasına göre sonuç değişebilir. |
Ölçüm: |opsiyonel ∩ kapanış| = 17 (örn. rbn-form-input). |
| B16 | Eşleme JSON'u ölçüm sayıları tutarsız ve üretim betiği yok | JSON surum 1.1.0: kapanış 23 dosya / 1 563 sınıf / 575 rbn- / 988 ön eksiz. Bu belgenin bağımsız ölçümü: 19 dosya / 1 193 sınıf / 471 rbn- / 722 ön eksiz. Ayrıca hedefEksik: 0 ve eksikBootstrapSiniflari: [] iddiaları kapsam daraltılmadan anlamsız (863 girdi taranmış, bootstrap'ın ~1 300 sınıfının hepsi değil). |
JSON :19-31 · bu belgenin §7.6 ölçümü (19 dosya, \.[-\w]+ regex). Bu belgede kapsam-daraltılmış yeniden ölçüm YAPILMADI — css_engine=rbn + panel/auth kapsamına daraltılmış gerçek eksik sayısı açık bir sonraki görevdir. |
| B17 | Ölçüm betiği repoda yok | JSON uretici: "FW-CSS-MOTOR-2 / team member (olcu-genis.mjs + el ile)". olcu-genis.mjs araması: E:\localhost, E:\AgentSpace, E:\tmp\_araclar → bulunamadı. Yeniden üretilebilirlik yok. |
Get-ChildItem -Recurse -Include *.mjs,*.ps1,*.py (üç kök) — eşleşme yok. |
| B18 | .text-primary çift tanımlı |
core/colors.css:10: .text-primary, .text-blue { color: var(--rbn-blue-600, #2563eb) !important; } · core/layout.css:118: .text-primary { color: var(--primary-color, var(--rbn-primary)) !important; }. İkisi de !important, ikisi de layout.css/colors.css B katmanı. rbn-master.css sırası: layout.css (12) → colors.css (22) ⇒ colors.css kazanır, yani --rbn-blue-600 (sabit mavi). Proje --primary-color ezilmez. |
core/colors.css:10 + core/layout.css:118 · sıra rbn-master.css:12 vs :22. |
| B19 | design-system.md §4.2 object-fit-cover yanlış |
§4.2 B katmanı örneği olarak object-fit-cover veriyor. Motorda yok. Var olan: .object-cover/.object-contain/.object-fill/.object-none/.object-scale-down (core/cards.css:363-367). |
Select-String 'object-fit' tüm Resources/Assets/**/*.css → yalnız cards.css:323 (özellik) ve :363-367 (sınıflar). |
| B20 | <projeA>-tag motorda yok |
design-system.md §4.1 "Standart Şablon"unda <projeA>-tag <projeA>-tag-blue kullanılıyor. Framework motorunda tanımı yok; tanımları proje CSS'inde (domains/<grup>/<site>/css/{components,elements}.css). Yani bu "standart şablon" bir projeye özgü sınıfı standart gösteriyor. |
Select-String '\.<projeA>-tag' rbnframework/** → 0; domains/** → <site-a2> dosyaları. |
| B21 | rbnModal.js yorumu kodla uyuşmuyor |
:24 yorumu [data-rbn-modal="true"], [data-bs-toggle="modal"], [data-rbn-toggle="modal"] diyor; :26'daki gerçek seçici [data-bs-toggle="modal"] içermiyor. |
components/rbnModal.js:24 vs :26. |
| B22 | AssetConvention tek doğruluk kaynağı tam kapanmamış |
<proje-c> favicon'ı SeoResolver üzerinden fiziksel yol + =v<filemtime> ile basıyor (/project-assets/images/favicon-<proje-c>.png=v1782671388), sanal AssetController rotasını kullanmıyor. Yeni siteler (example, sro, <proje-b>) sanal/uyumlu yolu kullanıyor. |
Canlı <link rel="icon"> taraması (§10.3). |
| B23 | panel bağlamı css_engine'den bağımsız |
injectCoreStack() :266 koşulu panel'i içermiyor; panel rbn_master'i STACK_MAP['panel'] → rbn_core_panel ile alıyor. Davranış doğru ama kod okuyan kişi :266'ya bakıp "panel'de rbn_master yüklenmiyor" sanabilir. Belge düzeltmesi değil, okuma tuzağı notu. |
AssetBuilder.php:266 vs AssetBundles.php:24,51-56. Canlı rbn-admin sayfasında rbn-master.css var ✓. |
| B24 | addAsset('js/x.js') ile addAsset('/js/x.js') farklı yollar |
addAsset() :118-122 yalnız @/http// ile başlamayan yola @project/ ekler. js/frontend.js → @project/js/frontend.js; /js/frontend.js → site kökü (düzleştirme yok, .test altına gider). İkisi de 200 dönebilir ama farklı fiziksel dosyalardır. |
FrontendBaseController.php:118. Canlı <proje-a>: …/project-assets/js/frontend.js=v1789207191 (addAsset('/js/frontend.js') çağrısından, <projeA>FrontendController.php:28). |
Bölüm başına bağımsız doğrulama özeti
Her bölüm için 5 rastgele iddia bu belgenin yazımı sırasında koddan/canlıdan bağımsız olarak
yeniden sorgulandı. Sonuçlar:
| Bölüm | 5 iddia | Sonuç |
|---|---|---|
| §1 Yükleme sistemi | core.php:46 iki rota · PROXY_SETUP iki kaynak · serveProject tek bayrak farkı · token sırası project→framework→font · AssetDefinition saf kayıt |
5/5 ✅ |
| §2 Sabit tablosu | 36 public const · 10 CDN · JQUERY dizi · REMIX_ICON her bağlamda · RBN_SHIELD_CSS paketsiz |
5/5 ✅ (paket dışı olanlar §13-B1'e yazıldı) |
§3 AssetBundles |
4 STACK_MAP bağlamı · 24 paket · rbn_core_frontend 3 stil · rbnExtended 2 stil · PanelProvider:48-55 assets yolu |
5/5 ✅ |
§4 AssetBuilder |
:250-252 css_engine okuma · :259 baypas · :266 enjeksiyon koşulu · :303 filemtime · :347 =v biçimi · :166-174 @project en son |
6/6 ✅ (css_engine sayımı eski analizle çelişti → 13/8 düzeltildi) |
§5 AssetController |
=v kesme · fonts/ 307 · media/ 307 + beyaz liste · sanal SVG/OG dalları · Cache-Control 1 yıl · immutable yok |
6/6 ✅ (bir yeni bulgu: 404→500, §13-B3) |
| §6 Font | 33 slug · slug kuralı · 16 takma ad · link basımı SeoProvider'da · AssetProvider filtresi · fonts_panel/fonts_auth |
6/6 ✅ (yeni bulgu: fallback Inter düşmüyor, §13-B8) |
| §7 CSS | 19 @import · 19 dosya ölçümü · pt-3 = utilities.css:17 · token çift katmanı · .text-primary çift tanım · object-fit-cover yok |
6/6 (4 ✅, 2 yeni çelişki: §13-B18, §13-B19) |
| §8 JS | 9 dinamik modül · async=false · data-bs-* okunuyor · 21 data-bs eşleşmesi · jquery yalnız panel · rbnExtended kullanılmıyor |
6/6 ✅ (data-bs-* "yok" varsayımı çürütüldü) |
| §9 İkon | ri- 2 527 / bi- 726 / fas- 0 · flag_icon STACK_MAP dışı · IconLibrary::match · icon() global yok · PanelMap ri-* |
5/5 ✅ (bi- boşluğu yeni bulgu → §13-B5) |
§10 AssetConvention |
3 uzantı / 3 uzantı · aday sırası · realpath kök kontrolü · findOgImage null · sanal OG MIME |
5/5 ✅ (<proje-c> sapması yeni → §13-B22) |
| §11 Tarifler | addAsset ön-eğri · rbnExtended 3 yol · ?v= çalışmaz · @font-face serbest · findFavicon öncelik |
5/5 ✅ |
| §12 Performans | 19 dosya ham/gzip · canlı Content-Length 1420 · dış istek 2/4/7/9 · max-age=31536000 · gzip sunucuda |
5/5 ✅ |
| §13 Bilinmeyenler | 24 kalem, her biri kanıt bağlantılı · B16/B17 ölçüm tekrarlanamazlığı açıkça belirtildi | — |
PLATFORM BEYANI
İş doğrulandığı platform: Windows (PowerShell, curl.exe, Python 3 gzip, Git 2.x).
Platforma bağlı olan ve dokunduğum kod yolu:
- Dosya yolu ayrımı —
AssetBuilder::generateWebUrl():332str_replace('\\', '/', $path)ve
AssetResolver::resolve():25ltrim($path, '/\\')her iki platformda ters bölüyü
düzleştirir.AssetConvention::resolveVirtualOgImage():161ise ters bölüyüDIRECTORY_SEPARATOR'a
çevirir — macOS/Linux'daDIRECTORY_SEPARATOR=/, Windows'ta\.realpath()kök kontrolü
(:167-177) iki platformda dastr_replace('\\', '/')ile normalize edildiği için
platformdan bağımsız. Canlı doğrulama Windows'ta yapıldı; macOS/Linux'da aynı sonucu verir. - Yol küçük harfe inmesi ve büyük/küçük harf duyarsızlığı — URL üretimi küçük harfe indirir
(AssetBuilder.php:336,340) amaAssetResolver::deepSearch()(:119) karşılaştırmayı
strtolower()ile yapar. Windows'ta dosya sistemi zaten büyük/küçük harf duyarsız; macOS/Linux'da
da aynı sonuç verir çünkü eşleştirme uygulama seviyesindestrtolowerile yapılıyor.
Doğrulama (/framework-assets/rbncommon/bebasneue-regular.ttf→ 200) Windows'ta yapıldı;
Linux'tadeepSearchyolu devreye girer ve sonuç aynıdır. - Kabuk/ikili adı — ölçüm komutlarında
curl.exe(Windows),pythonveGet-ChildItem
(PowerShell) kullanıldı. Bunlar yalnız ölçüm araçlarıdır, belgedeki hiçbir iddia
platforma bağlı değildir. macOS/Linux'tacurl(.exesoneksiz) vepython3gerekir;
belgedeki URL'ler ve sonuçlar aynıdır. - Sıkıştırma —
gzip.compress(data, 9)Python'ın zlib seviyesidir. Canlıdaki web sunucusu
(nginx/Apache) farklı bir seviye kullanabilir. Bu yüzden §12'deki gzip rakamları
"gzip -9 referansı" olarak etiketlendi, sunucu ölçümü iddiası olarak yazılmadı.
Sunucunun gerçekContent-Length'i canlı ölçüldü (1420), ama bu sıkıştırılmamış beyan. - HTTP istekleri —
curl.exe -kile yerel*.testalan adlarına yapıldı; TLS doğrulaması
kapatıldı (-k, yerel sertifika). macOS/Linux'ta da aynı bayrak geçerli. Canlı üretim
alan adları kullanılmadı. - Süreç/izin gerektiren hiçbir kodu dokunmadım. Kod değişikliği yapmadım; yalnız okudum,
ölçtüm ve bu belgeyi yazdım. Bu nedenle "diğer platformda ne olur" sorusu §5/§10/§13'teki
davranışsal iddialar için yukarıdaki 1-2. maddelerle sınırlıdır.
Koşulamadığım platformlar: macOS ve Linux — bu ortamda yalnız Windows bulundu
(win32). Kod okuma, statik doğrulama ve yerel HTTP ölçümü yapabildim; macOS/Linux'a özgü bir
çalıştırma ortamı yoktu. §5.5 AssetResolver deepSearch() özyinelemeli tarayıcısı ve
AssetConvention realpath() kök kontrolü koddan platformdan bağımsız olduğu için bu iki
yerde macOS/Linux'ta aynı sonucu verecektir; ancak "koşulamadı + neden" notu düşülmüştür.