);
}
const fmtRp = (n) => 'Rp ' + (n || 0).toLocaleString('id-ID');
/* Format ringkas untuk kartu statistik sempit (mis. Rp 176,7 jt) */
const fmtRpShort = (n) => {
n = n || 0;
if (n >= 1e9) return 'Rp ' + (n / 1e9).toLocaleString('id-ID', { maximumFractionDigits: 1 }) + ' M';
if (n >= 1e6) return 'Rp ' + (n / 1e6).toLocaleString('id-ID', { maximumFractionDigits: 1 }) + ' jt';
if (n >= 1e3) return 'Rp ' + Math.round(n / 1e3) + ' rb';
return 'Rp ' + n.toLocaleString('id-ID');
};
/* ── Kategori artikel: warna & label ── */
const CATS = {
'Tahfidz': { color: '#1F6B47', bg: 'rgba(31,107,71,.10)' },
'Bahasa Arab': { color: '#1B2F6E', bg: 'rgba(27,47,110,.10)' },
'Fiqih': { color: '#E8912A', bg: 'rgba(232,145,42,.12)' },
'Akhlaq': { color: '#8B5A2B', bg: 'rgba(139,90,43,.12)' },
};
// Palet untuk kategori BARU (otomatis dapat warna konsisten per nama)
const CAT_PALETTE = ['#1F6B47', '#1B2F6E', '#E8912A', '#8B5A2B', '#7A4E8C', '#0E7C86', '#B23A48', '#3A6EA5'];
function hexToRgba(hex, a) { const n = parseInt(hex.slice(1), 16); return `rgba(${(n>>16)&255},${(n>>8)&255},${n&255},${a})`; }
const catStyle = (c) => {
if (CATS[c]) return CATS[c];
if (!c) return { color: 'var(--muted)', bg: 'var(--bg2)' };
// warna deterministik dari nama kategori
let h = 0; for (let i = 0; i < c.length; i++) h = (h * 31 + c.charCodeAt(i)) >>> 0;
const color = CAT_PALETTE[h % CAT_PALETTE.length];
const style = { color, bg: hexToRgba(color, 0.11) };
CATS[c] = style; // cache agar konsisten
return style;
};
window.catStyle = catStyle;
/* Ikon garis elegan per kategori (pengganti emoji childish saat cover kosong) */
const _gi = (p) => "";
const GLYPH = {
book: "",
pen: "",
scale: "",
moon: "",
scroll: "",
cap: "",
calendar:"",
hands: "",
mosque: "",
};
const CAT_GLYPH = { 'Tahfidz': 'book', 'Bahasa Arab': 'pen', 'Fiqih': 'scale', 'Akhlaq': 'moon', 'Hadits': 'scroll' };
function glyphURL(name) { return "url(\"data:image/svg+xml," + _gi(GLYPH[name] || GLYPH.book) + "\")"; }
function GlyphMark({ name, size }) {
return ;
}
window.GLYPH = GLYPH; window.glyphURL = glyphURL; window.GlyphMark = GlyphMark; window.CAT_GLYPH = CAT_GLYPH;
/* Ikon default per kategori (PHP asli tak punya kolom icon) */
const CAT_ICON = { 'Tahfidz': '📖', 'Bahasa Arab': '✍️', 'Fiqih': '⚖️', 'Akhlaq': '🌙' };
/* Normalisasi artikel: PHP asli pakai author_name/read_time/published_at,
mock pakai author/readTime/date. Komponen membaca satu bentuk seragam. */
function normArticle(a) {
if (!a) return a;
const author = a.author || a.author_name || 'Tim MQA';
let date = a.date;
if (!date && a.published_at) {
try { date = new Date(a.published_at).toLocaleDateString('id-ID', { day: 'numeric', month: 'short', year: 'numeric' }); }
catch { date = ''; }
}
return {
...a,
author,
authorInitial: a.authorInitial || (author ? author[0] : '?'),
readTime: a.readTime || a.read_time || '5 menit',
date: date || '',
icon: a.icon || CAT_ICON[a.category] || '📖',
slug: a.slug || slugify(a.title || ('artikel-' + (a.id || ''))),
};
}
function slugify(t) { return String(t).toLowerCase().trim().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''); }
window.slugify = slugify;
window.normArticle = normArticle;
/* ── Markdown ringan & AMAN (escape dulu, lalu format subset) ──
Dukungan: ## H2, ### H3, **tebal**, *miring*, - poin, 1. nomor, > kutipan, [teks](url) */
function renderMD(src) {
if (!src) return '';
// Jika sudah HTML (dari editor WYSIWYG), tampilkan apa adanya
if (/<(p|h2|h3|ul|ol|li|blockquote|br|div|strong|em|b|i|a)[\s>]/i.test(src)) return src;
const esc = (t) => t.replace(/&/g, '&').replace(//g, '>');
const inline = (t) => esc(t)
.replace(/\*\*([^*]+)\*\*/g, '$1')
.replace(/(^|[^*])\*([^*]+)\*/g, '$1$2')
.replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g, '$1');
const lines = String(src).replace(/\r/g, '').split('\n');
const isAr = (t) => { const ar = (t.match(/[\u0600-\u06ff]/g) || []).length; return ar > 0 && ar / t.replace(/\s/g, '').length > 0.4; };
const pTag = (t) => isAr(t) ? '
' + inline(t) + '
' : '
' + inline(t) + '
';
let html = '', list = null;
const closeList = () => { if (list) { html += list === 'ul' ? '' : ''; list = null; } };
for (let raw of lines) {
const line = raw.trim();
if (!line) { closeList(); continue; }
let m;
if ((m = line.match(/^###\s+(.*)/))) { closeList(); html += '
' + inline(m[1]) + '
'; }
else if ((m = line.match(/^##\s+(.*)/))) { closeList(); html += '
' + inline(m[1]) + '
'; }
else if ((m = line.match(/^>\s+(.*)/))) { closeList(); const t = m[1]; html += isAr(t) ? '
' + inline(t) + '
' : '
' + inline(t) + '
'; }
else if ((m = line.match(/^[-*]\s+(.*)/))) { if (list !== 'ul') { closeList(); html += '
'; list = 'ul'; } html += '
' + inline(m[1]) + '
'; }
else if ((m = line.match(/^\d+\.\s+(.*)/))) { if (list !== 'ol') { closeList(); html += ''; list = 'ol'; } html += '
' + inline(m[1]) + '
'; }
else { closeList(); html += pTag(line); }
}
closeList();
return html;
}
window.renderMD = renderMD;
function CatBadge({ cat, small }) {
const s = catStyle(cat);
return (
{cat}
);
}
/* ── Cover artikel: foto asli bila ada, atau pola geometris Islami yang elegan ── */
const STAR_TILE = "url(\"data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='44'%20height='44'%20viewBox='0%200%2044%2044'%3E%3Cg%20fill='none'%20stroke='%23ffffff'%20stroke-opacity='0.16'%20stroke-width='1.3'%3E%3Crect%20x='10'%20y='10'%20width='24'%20height='24'/%3E%3Crect%20x='10'%20y='10'%20width='24'%20height='24'%20transform='rotate(45%2022%2022)'/%3E%3C/g%3E%3C/svg%3E\")";
function CoverArt({ a, ratio, iconSize, badge }) {
const s = catStyle(a.category);
return (
{a.cover_url
?
: <>
>}
{badge && {a.category}}
);
}
/* ── Kartu artikel (anchor ke URL SEO; klik = SPA instan) ── */
function ArticleCard({ a: raw, onClick, featured }) {
const a = normArticle(raw);
const s = catStyle(a.category);
const href = '/artikel/' + a.slug;
const handle = (e) => { if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) return; e.preventDefault(); onClick && onClick(); };
if (featured) {
return (