Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save mehmetsagir/2238895c3cba40ff44d9516f47c63d0c to your computer and use it in GitHub Desktop.

Select an option

Save mehmetsagir/2238895c3cba40ff44d9516f47c63d0c to your computer and use it in GitHub Desktop.
// --- ConfigManager ---
export class ConfigManager {
constructor(config) {
this.config = this.validateConfig(config);
}
validateConfig(config) {
// Basit doğrulama (geliştirilebilir)
return config;
}
get() {
if (!this.config) throw new Error("Config yüklenmedi!");
// Hedef klasörler config'te yoksa default değerleri kullan
const defaultTargetUrlFolders = [
{ name: "urunresimleri", checkThumb: true, forceBigKey: true, customValues: { quality: 85 }, imageType: "product" },
{ name: "ilgiliurunresim", checkThumb: true, forceBigKey: false, customValues: { quality: 85 }, imageType: "product" },
{ name: "aksesuarurunresim", checkThumb: true, forceBigKey: false, customValues: { quality: 85 }, imageType: "product" },
{ name: "sayfatasarim", checkThumb: false, forceBigKey: false, customValues: { quality: 99 }, imageType: "design" },
{ name: "editoruploads", checkThumb: false, forceBigKey: false, customValues: { quality: 99 }, imageType: "design" },
{ name: "images", checkThumb: false, forceBigKey: false, customValues: { quality: 99 }, imageType: "design" },
{ name: "dosyalar", checkThumb: false, forceBigKey: false, customValues: { quality: 99 }, imageType: "design" },
{ name: "kampanyabanner", checkThumb: false, forceBigKey: false, customValues: { quality: 99 }, imageType: "design" },
{ name: "marka", checkThumb: false, forceBigKey: false, customValues: { quality: 99 }, imageType: "brand" },
{ name: "blog", checkThumb: false, forceBigKey: false, customValues: { quality: 99 }, imageType: "blog" },
];
return {
...this.config,
targetUrlFolders: this.config.targetUrlFolders || defaultTargetUrlFolders
};
}
}
// --- ObserverManager ---
export class ObserverManager {
constructor(targetConfig, callback) {
this.observer = null;
this.callback = callback;
this.init(targetConfig);
}
init(targetConfig) {
const target = document.querySelector(targetConfig.rootSelector);
if (target) {
this.observer = new MutationObserver(this.callback);
this.observer.observe(target, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: targetConfig.watchAttributes
});
}
}
disconnect() {
if (this.observer) this.observer.disconnect();
}
}
// --- ImageResizePlugin ---
function createOptimizedUrl({ cdnTarget, width, height, quality, path, targetUrlFolders }) {
// Klasöre göre spesifik kalite varsa onu kullan, yoksa parametreyle gelen quality'yi kullan
let usedQuality = quality;
let matchedFolder = null;
for (let folder of targetUrlFolders) {
if (path.indexOf(folder.name) > -1) {
matchedFolder = folder;
if (folder.customValues && typeof folder.customValues.quality !== 'undefined') {
usedQuality = folder.customValues.quality;
}
break;
}
}
let paramStr = `width=${width}`;
if (height && height !== '-') paramStr += `,height=${height}`;
paramStr += `,quality=${usedQuality}`;
let optimizedUrl = `${cdnTarget}/${paramStr}${path}`;
// /thumb/ -> /buyuk/ düzeltmesi ve forceBigKey uygula
if (matchedFolder) {
if (matchedFolder.checkThumb) {
optimizedUrl = optimizedUrl.replace('/thumb/', '/buyuk/');
}
if (matchedFolder.forceBigKey) {
if (optimizedUrl.indexOf(`/${matchedFolder.name}/`) > -1 && optimizedUrl.indexOf(`/${matchedFolder.name}/buyuk/`) === -1) {
optimizedUrl = optimizedUrl.replace(`/${matchedFolder.name}/`, `/${matchedFolder.name}/buyuk/`);
}
}
}
return optimizedUrl;
}
export class ImageResizePlugin {
constructor(config) {
this.configManager = new ConfigManager(config);
this.observerManager = null;
}
init() {
const config = this.configManager.get();
this.observerManager = new ObserverManager(
config.target,
this.handleMutations.bind(this)
);
this.optimizeAllImages(); // Sayfa yüklenince tüm görselleri optimize et
}
// Tüm hedef container içindeki görselleri optimize et
optimizeAllImages() {
const config = this.configManager.get();
const container = document.querySelector(config.target.rootSelector);
if (!container) return;
container.querySelectorAll("img").forEach(img => {
this.optimizeImage(img);
});
}
handleMutations(mutations) {
mutations.forEach((mutation) => {
if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE && node.tagName === "IMG") {
this.optimizeImage(node);
}
// Eğer birden fazla img içeren bir element eklendiyse:
if (node.nodeType === Node.ELEMENT_NODE) {
node.querySelectorAll?.("img").forEach(img => this.optimizeImage(img));
}
});
}
if (mutation.type === "attributes") {
// İstersen burada da optimizeImage çağrısı yapılabilir
// this.optimizeImage(mutation.target);
}
});
}
// Optimize fonksiyonu: CDN parametreli url oluştur (parent alanına göre width/height)
optimizeImage(img) {
const config = this.configManager.get();
const cdnSource = config.cdn.sourceUrl;
const cdnTarget = config.cdn.targetUrl;
// Genişlik ve yükseklik: Önce parent (ebeveyn) elemandan, yoksa img'den alınır
let width, height;
if (img.parentElement) {
const parentRect = img.parentElement.getBoundingClientRect();
width = Math.round(parentRect.width);
height = Math.round(parentRect.height);
}
if (!width) width = img.width || img.naturalWidth || 1920;
if (!height) height = img.height || img.naturalHeight || undefined;
// Optimize edilecek tüm attribute'lar için döngü
const allowedSrcAttributes = ["src", "data-original", "data-src", "data-second", "data-zoom", "data-bigimg"];
// Kaynak olarak öncelikle data-src, yoksa data-original, yoksa src kullan
let originalSrc = img.getAttribute("data-src") || img.getAttribute("data-original") || img.getAttribute("src");
if (!originalSrc || !originalSrc.startsWith(cdnSource)) return;
// Eğer img'de src varsa ve optimize edilmemişse, src'yi geçici olarak boşalt
if (img.hasAttribute("src") && img.getAttribute("src") === originalSrc) {
img.setAttribute("src", "");
}
for (const attr of allowedSrcAttributes) {
// Her attribute için mevcutsa onu, yoksa originalSrc'yi kullan
let src = img.getAttribute(attr);
if (!src) src = originalSrc;
if (!src.startsWith(cdnSource)) continue;
const url = new URL(src);
// Zaten optimize edilmişse atla
if (url.pathname.startsWith('/cdn-cgi/image/')) {
continue;
}
// /uploads/ dizininden itibaren path'i al
const pathIndex = url.pathname.indexOf('/uploads/');
const path = pathIndex !== -1 ? url.pathname.substring(pathIndex - 5) : url.pathname;
// data-original için optimize edilmemiş (orijinal) src atanır
if (attr === 'data-original') {
img.setAttribute(attr, originalSrc);
console.log(`Görsel (data-original) orijinal olarak eklendi:`, originalSrc);
continue;
}
// Her attribute için config'den özel değerleri al, yoksa genel değerleri kullan
const attrConfig = config.image[attr] || {};
let attrWidth = attrConfig.width !== undefined ? attrConfig.width : width;
let attrHeight = attrConfig.height !== undefined ? attrConfig.height : height;
let attrQuality = attrConfig.quality !== undefined ? attrConfig.quality : (config.image.quality || 95);
// data-zoom ve data-bigimg için width ve height her zaman '-' olmalı
if (attr === 'data-zoom' || attr === 'data-bigimg') {
attrWidth = '-';
attrHeight = '-';
}
// data-zoom için özel durum: width negatif ise orijinal URL kullanılır
if (attr === 'data-zoom' && attrWidth < 0) {
img.setAttribute(attr, src);
console.log(`Görsel optimize edildi (${attr}): orijinal URL kullanıldı`, src);
continue;
}
// Klasöre göre kalite ve path düzeltmesi ile optimize edilmiş URL oluştur (config'ten targetUrlFolders alınır)
const optimizedUrl = createOptimizedUrl({
cdnTarget,
width: attrWidth,
height: attrHeight,
quality: attrQuality,
path,
targetUrlFolders: config.targetUrlFolders
});
// Her zaman ilgili attribute'u güncelle (veya ekle)
img.setAttribute(attr, optimizedUrl);
// src attribute'u için optimize edilen URL'yi de yaz
if (attr === 'src') {
img.setAttribute('src', optimizedUrl);
}
console.log(`Görsel optimize edildi (${attr}):`, optimizedUrl);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment