YouTube yerleştirmelerinden interaktif akordeonlara, tema dosyalarına dokunmadan basit bir shortcode sistemiyle yeniden kullanılabilir içerik blokları oluşturun.
Shortcode'lar Neden Hala Onemli
Blok editorler bugunlerde tum dikkati uzerine cekiyor, ancak shortcode'lar yazi govdeleri icinde dinamik içerik gommenin en hizli yolu olmaya devam ediyor. İçerik duzenleyicisi yazi editorunde [gallery ids="12,15,18" columns="3"] yazdiginda, sistem bunu görüntulenme zamaninda tam olarak oluşturulmus bir görsel gridle degistirir. JavaScript widget'i yok, iframe yok, ucuncu taraf gomme yok — sadece aninda yuklenen sunucu tarafinda oluşturulmus HTML.
JekCMS'e shortcode destegini 1.2 surumunde ekledik, uc musterinin ayni seyi istemesinden sonra: blog yazilari icinde HTML'e dokunmadan foto galerileri, YouTube videolari ve bilgi kutulari gommenin bir yolu. Uygulama çekirdek parser için iki gun ve yerlesik shortcode'lar için bir gun surdu. Nasil insa ettigimizi burada tam olarak anlatacagim.
Parser Mimarisi
Bir shortcode parser'inin dort durumu ele almasi gerekir:
- Kendi kendine kapanan:
[youtube id="dQw4w9WgXcQ"] - İçerikli:
[callout type="warning"]Buna dikkat edin.[/callout] - Ic ice:
[accordion][section title="SSS 1"]Cevap burada[/section][/accordion] - Parametresiz:
[divider]
Dort durumu da ele alan regex sasirtici derecede kompakt:
class ShortcodeParser {
private array $registered = [];
public function register(string $tag, callable $handler): void {
$this->registered[$tag] = $handler;
}
public function parse(string $content): string {
if (strpos($content, '[') === false) {
return $content; // Hizli yol: shortcode olasi degil
}
$tags = implode('|', array_map('preg_quote', array_keys($this->registered)));
if (empty($tags)) return $content;
// İçerikli shortcode'lari esle: [tag attrs]içerik[/tag]
$pattern = '/[(' . $tags . ')([^]]*)](.*?)[/1]/s';
$content = preg_replace_callback($pattern, function($m) {
return $this->execute($m[1], $this->parseAttributes($m[2]), $m[3]);
}, $content);
// Kendi kendine kapanan shortcode'lari esle: [tag attrs]
$pattern = '/[(' . $tags . ')([^]]*?)/?]/s';
$content = preg_replace_callback($pattern, function($m) {
return $this->execute($m[1], $this->parseAttributes($m[2]), '');
}, $content);
return $content;
}
}
9. satirdaki hizli yol vurgulanmaya deger. Herhangi bir regex calistirmadan once, icerigin bir [ karakteri icerup iceramedigini kontrol ediyoruz. Shortcode'suz yazilar için (ki cogu yazidir), bu regex motorunu tamamen atlar. 2.000 yazili bir blogda, bu optimizasyon shortcode parser'inin her yazi görüntulemesinde çalışmasi nedeniyle toplam sayfa yuku başına yaklasik 15ms kazandirdi.
Galeri Shortcode'unu Oluşturma
Galeri shortcode'u en cok istenen özelliktir. Virgule ayrilmis medya kimlikleri listesi alir ve bunlari lightbox destekli responsive bir grid olarak oluşturur.
Kullanim: [gallery ids="12,15,18,22" columns="3" size="medium"]
$parser->register('gallery', function(array $attrs, string $content) {
$ids = array_filter(array_map('intval', explode(',', $attrs['ids'] ?? '')));
$columns = max(1, min(6, (int)($attrs['columns'] ?? 3)));
$size = in_array($attrs['size'] ?? 'medium', ['thumbnail', 'medium', 'large'])
? $attrs['size'] : 'medium';
if (empty($ids)) return '<!-- gallery: gecerli id yok -->';
global $db;
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$images = $db->fetchAll(
"SELECT * FROM media WHERE id IN ({$placeholders})",
$ids
);
$html = '<div class="shortcode-gallery" style="--gallery-cols: ' . $columns . '">';
foreach ($images as $img) {
$thumb = get_thumbnail_path($img['path'], $size);
$alt = htmlspecialchars($img['alt_text'] ?? $img['filename'], ENT_QUOTES, 'UTF-8');
$html .= '<figure class="gallery-item">';
$html .= '<img src="' . $thumb . '" alt="' . $alt . '" ';
$html .= 'width="400" height="300" loading="lazy">';
$html .= '</figure>';
}
$html .= '</div>';
return $html;
});
CSS, sutun sayisi için özel bir özellik kullanan CSS Grid kullanir. Her sutun sayisi için ayri CSS siniflari oluşturmak yerine bir CSS kuralinin 1'den 6'ya kadar herhangi bir sutun sayisini yonetmesini sağlar.
YouTube Shortcode'unu Oluşturma
YouTube gomulueri dikkatsizce yapilirsa performans katilleridir. Her iframe yaklasik 600KB JavaScript yukler. Shortcode'umuz fasad kalibini kullanir — oynatma dugmeli bir küçük resim gosterir ve yalnizca kullanıcı tikladiginda iframe'i yukler.
Kullanim: [youtube id="dQw4w9WgXcQ" title="Video basligi"]
Iki güvenlik detayi: izleme cerezlerinden kacinmak için youtube.com yerine youtube-nocookie.com kullaniyoruz. Ve işleyicinin 2. satirinda video kimliginden alfanumerik olmayan tum karakterleri cikartiyoruz — bu, hazirlanmis shortcode parametreleri araciligiyla XSS'i onler.
Callout Shortcode'unu Oluşturma
Callout kutulari bir yazidaki onemli bilgileri vurgular. Dort tipi destekler: info, warning, success ve error.
Kullanim: [callout type="warning"]Bu adimda dikkatli olun. Veri kaybi mumkundur.[/callout]
role="alert" ozelligi ekran okuyucularin callout icerigini duyurmasini sağlar ve onu erişilebilir kilar.
Accordion Shortcode'unu Oluşturma
Accordion'lar ic ice shortcode'larla bir ebeveyn-cocuk yapısı kullanir. Bu en karmasik kaliptir cunku parser'in dis [accordion] etiketini ve ic [section] etiketlerini dogru sirada ele almasi gerekir.
Ozel JavaScript yerine yerel HTML <details> ve <summary> elemanlarini kullaniyoruz. Bu bize yerlesik klavye erişilebilirligi verir ve JavaScript olmadan çalışır. Gereken tek JavaScript, bir bolumu acmanin digerlerini kapattigi istege bagli "tekli acik" modudur.
Ic Ice Shortcode'lari Ele Alma
Parser shortcode'lari icten disa dogru isler. [accordion][section]...[/section][/accordion] ile karsilastiginda, once [section] etiketlerini isler (içerik tasiyan regex tarafindan once eslestirildikleri icin) ve sonra zaten oluşturulmus section HTML'siyle [accordion] isler.
Bu cogu durum için dogal olarak çalışır, ancak ic shortcode adi regex kalibinda dis olandan once gozukurse bozulur. Cozum, içerik tasiyan kalibi (kapanma etiketleriyle) kendi kendine kapanan kaliptan once işlemektir.
Güvenlik: Shortcode Ciktisinda XSS Onleme
Shortcode'lar kullanıcı tarafindan saglanan parametreleri kabul ettikleri için potansiyel bir XSS vektorudur. Parametreleri kacis yapmadan doğrudan HTML'ye oluşturursaniz, bir saldirgan hazirlanmis shortcode özellikleri araciligiyla script etiketleri enjekte edebilir.
Savunmamizin uc katmani vardir:
- Beyaz liste doğrulamasi:
typegibi numaralandirilmis parametreler için yalnizca bilinen degerleri kabul edin. Callout işleyicisi['info', 'warning', 'success', 'error']listesini kontrol eder ve baska herhangi bir sey içininfovarsayilanini kullanir. - Tip dönüştürme:
columnsgibi sayisal parametreler için hemen tamsayiya dönüştürun:(int)($attrs['columns'] ?? 3). Bu, herhangi bir dize tabanli enjeksiyonu ortadan kaldirir. - Cikis kacisi:
titlegibi serbest metin parametreleri için her zamanhtmlspecialchars($value, ENT_QUOTES, 'UTF-8')kullanin.ENT_QUOTESbayragi hem tek hem de cift tirneklerin kacislnmasini sağlar.
İçerik govdesi (acilis ve kapanis etiketleri arasindaki metin) kendi temizligine ihtiyac duyar. Güvenli elemanlarin beyaz listesi disindaki tum HTML etiketlerini cikaririz: <p>, <br>, <strong>, <em>, <a>, <code>, <ul>, <ol>, <li>.
Kayit ve Kullanim
Tum shortcode'lar tema baslatma sirasinda yuklenen tek bir dosyada kayit edilir. Şablonda shortcode'lar yazi oluşturma sirasinda islenir:
<article class="post-content">
<?= process_shortcodes($post['content']) ?>
</article>
Siteniz için özel bir shortcode oluşturmak yaklasik 15 dakika surer: işleyici fonksiyonunu yazin, parser'a kaydedin ve CSS'i ekleyin. Parser tum regex eslestirmeyi, özellik ayristirmayi ve ic ice yapılandırmayi halleder — işleyiciniz sadece temiz diziler alir ve HTML dondurur.