Düzenleyici sözleşmesi
Temanın tasarımı serbest; Mağaza Düzenleyici ve MultiZeka ile nasıl konuştuğu değil. Bloğa nitelik, metne duzenle, hareketli parçada mk:select.
Temanı istediğin gibi tasarlayabilirsin. Satıcı ise her temada aynı düzenleyiciyi kullanır. Önizlemede bir bannera tıklayınca o banner seçilir, başlığa çift tıklayınca yazı yerinde değişir, slayt seçilince durur. MultiZeka da aynı alanları okuyup yazar. Bunun için temanın uyması gereken birkaç kural var.
Kurallar yüklemede denetlenir. Hata varsa tema yüklenmez; uyarı yüklemeyi durdurmaz. Yüklemeden önce kendin denetle:
npx @multikolay/tema dogrulaMCP sunucusundaki tema_dogrula aracı da aynı denetimi yapar.
1. Bloğa nitelik
Her bloğun kök ögesine {{ b.nitelik }} yaz. Düzenleyici tıklanan noktadaki en içteki işaretli ögeyi seçer:
bannera tıklayan satıcı bölümü değil, o bannerı düzenler. Esc bir üst ögeye (bölüme) çıkar.
{%- for b in section.blocks -%}
<a class="banner" href="{{ b.settings.url | default: '#' }}" {{ b.nitelik }}>…</a>
{%- endfor -%}Döngü dışında tek bir blok çiziyorsan (ör. yalnız ilk slayt) onu da işaretle:
{%- assign ilk = section.blocks | first -%}
<div class="giris" {{ ilk.nitelik }}>…</div>Bölümün kendi kök ögesini platform verir; bölüme nitelik yazma.
2. Metne duzenle
Sayfada görünen her text ve textarea ayarının ögesine | duzenle süzgecini yaz. Satıcı önizlemede yazıya
çift tıklar, yazar, Enter'a basar; değer o ayara kaydedilir.
<h2 {{ section | duzenle: 'baslik' }}>{{ section.settings.baslik }}</h2>
{%- for b in section.blocks -%}
<p {{ b | duzenle: 'metin' }}>{{ b.settings.metin }}</p>
{%- endfor -%}- Süzgeç bölüm için
section, blok için döngüdeki blok değişkenini (b) ve ayarın kimliğini alır. - Önizlemede
data-editniteliği basar, canlı sitede boş döner. Canlı HTML değişmez, CSS'in etkilenmez. - Ögenin içinde yalnız o metin olsun. Yanında ikon ya da başka yazı varsa metni kendi
<span>'ine al:<a href="…"><span {{ b | duzenle: 'dugme' }}>{{ b.settings.dugme }}</span> →</a>. Temanın CSS'i o ögedekispan'leri hedefliyorsa (.etiket > span { … }) yenispande etkilenir; o zaman işareti dış ögeye koy ya da seçiciyi daralt. Boş süs ögeleri (ikon, nokta) yerinde düzenlemede yok sayılır. - Nitelik içindeki değerler (
alt="{{ … }}"),default:ile gelen yedek değer vemeta_doldurile ürün bilgisinden dolan kalıp yerinde düzenlenmez; bunlar içinduzenlegerekmez.
3. Olaylar
Önizlemede düzenleyici sayfaya şu olayları gönderir. Slayt, akordeon, sekme gibi hareketli parçalar dinlemeli.
| Olay | detail | Ne zaman |
|---|---|---|
mk:select | { id }: seçilen bölüm ya da blok kimliği; null seçim kalktı | Satıcı önizlemede ya da Katmanlar'da bir öge seçince |
mk:bolum:yuklendi | { id }: yeniden çizilen bölüm | Satıcı bir ayarı değiştirince bölüm yeniden çizilir; ardından geçerli seçim yeniden mk:select olarak gelir |
Olaylar window'a gönderilir. Kimlik, bloğun data-mk-blok niteliğindeki değerdir. Önizlemede kökte
data-mk-tasarim="1" bulunur. Canlı sitede ne olay ne de bu nitelik vardır.
Kendiliğinden geçen bir parçan varsa (şemada otomatik ya da autoplay onay kutusu) tema.js mk:select'i
dinlemek zorunda. Seçilen slayta geçmeli ve seçim sürdükçe durmalı; yoksa satıcı düzenlediği slaytı göremez.
<section class="slayt" data-slayt data-otomatik="{{ section.settings.otomatik }}">
{%- for b in section.blocks -%}
<div class="slayt-kare{% if forloop.first %} is-aktif{% endif %}" {{ b.nitelik }}>
<h2 {{ b | duzenle: 'baslik' }}>{{ b.settings.baslik }}</h2>
</div>
{%- endfor -%}
</section>
{% schema %}
{
"name": "Slayt",
"settings": [{ "type": "checkbox", "id": "otomatik", "label": "Kendiliğinden geçsin", "default": true }],
"blocks": [{ "type": "kare", "name": "Slayt", "settings": [{ "type": "text", "id": "baslik", "label": "Başlık" }] }],
"presets": [{ "name": "Slayt", "blocks": [{ "type": "kare" }, { "type": "kare" }] }]
}
{% endschema %}function slayt(kok) {
const kareler = [...kok.querySelectorAll(".slayt-kare")]
let i = 0
let zaman = null
let sabit = false // düzenleyicide seçiliyken durur
const git = (n) => {
i = (n + kareler.length) % kareler.length
kareler.forEach((k, j) => k.classList.toggle("is-aktif", j === i))
sur()
}
const sur = () => {
clearTimeout(zaman)
if (kok.dataset.otomatik === "true" && !sabit) zaman = setTimeout(() => git(i + 1), 6000)
}
const secim = (e) => {
// Bölüm yeniden çizildiyse eski kopya dinlemeyi bırakır.
if (!kok.isConnected) return window.removeEventListener("mk:select", secim)
const id = e.detail?.id
const el = id ? document.querySelector(`[data-mk-blok="${CSS.escape(id)}"]`) : null
const n = el ? kareler.findIndex((k) => k.contains(el)) : -1
sabit = n >= 0
if (n >= 0 && n !== i) git(n)
else sur()
}
window.addEventListener("mk:select", secim)
git(0)
}
const kurulu = new WeakSet()
const kur = () => document.querySelectorAll("[data-slayt]").forEach((k) => kurulu.has(k) || (kurulu.add(k), slayt(k)))
kur()
window.addEventListener("mk:bolum:yuklendi", kur)4. Görsel
Görsel ayarını image_url ile bas: mağazanın görselleri istenen genişlikte, hızlı yüklenir.
<img src="{{ b.settings.gorsel | image_url: width: 1200 }}" alt="{{ b.settings.gorsel_alt }}">Denetlenen kurallar
| Kural | Düzey |
|---|---|
Bloğu olan bölümde blok işareti yok ({{ b.nitelik }}) | hata |
| Döngü dışında çizilen tek blok işaretsiz | hata |
Görünen text/textarea ayarında | duzenle yok | hata |
Kendiliğinden geçen bölüm var, tema.js mk:select dinlemiyor | hata |
Görsel image_url olmadan basılıyor | uyarı |
Denetim bölümün {% render %} ile çağırdığı parçalara da bakar: blok kartını bir parçada çizebilirsin. Alt
temada yalnız kendi dosyaların denetlenir.