| 1 |
(function () { |
| 2 |
'use strict'; |
| 3 |
|
| 4 |
var _typoKeys = { |
| 5 |
family:'font-family', weight:'font-weight', style:'font-style', |
| 6 |
transform:'text-transform', decoration:'text-decoration', |
| 7 |
sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m', |
| 8 |
lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m', |
| 9 |
letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m', |
| 10 |
wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m' |
| 11 |
}; |
| 12 |
var _typoUnits = { size:'sizeUnit', lineHeight:'lineHeightUnit', letterSpacing:'letterSpacingUnit', wordSpacing:'wordSpacingUnit' }; |
| 13 |
var _typoUnitDefaults = { size:'px', lineHeight:'', letterSpacing:'px', wordSpacing:'px' }; |
| 14 |
function typoCssVarsForEl(el, obj, prefix) { |
| 15 |
if (!obj || typeof obj !== 'object') return; |
| 16 |
Object.keys(_typoKeys).forEach(function (k) { |
| 17 |
var v = obj[k]; if (v === undefined || v === '') return; |
| 18 |
var prop = _typoKeys[k]; |
| 19 |
var base = k.replace(/Desktop|Tablet|Mobile/, ''); |
| 20 |
var uKey = _typoUnits[base]; |
| 21 |
if (uKey && typeof v === 'number') v = v + (obj[uKey] || _typoUnitDefaults[base] || ''); |
| 22 |
el.style.setProperty(prefix + prop, v); |
| 23 |
}); |
| 24 |
} |
| 25 |
|
| 26 |
function mk(tag, cls, styles) { |
| 27 |
var d = document.createElement(tag); |
| 28 |
if (cls) d.className = cls; |
| 29 |
if (styles) Object.keys(styles).forEach(function (k) { d.style[k] = styles[k]; }); |
| 30 |
return d; |
| 31 |
} |
| 32 |
function tx(tag, cls, text, styles) { |
| 33 |
var d = mk(tag, cls, styles); |
| 34 |
d.textContent = text; |
| 35 |
return d; |
| 36 |
} |
| 37 |
function ap(p) { |
| 38 |
Array.prototype.slice.call(arguments, 1).forEach(function (c) { if (c) p.appendChild(c); }); |
| 39 |
return p; |
| 40 |
} |
| 41 |
|
| 42 |
// ── image placeholder ───────────────────────────────────────────── |
| 43 |
function imgPlaceholder(a) { |
| 44 |
return mk('div', 'bkbg-ogp-img-placeholder', { |
| 45 |
height: (a.imageHeight || 180) + 'px', |
| 46 |
background: a.imageBg || '#6366f1', |
| 47 |
fontSize: Math.floor((a.imageHeight || 180) * 0.35) + 'px' |
| 48 |
}); |
| 49 |
} |
| 50 |
function imgPlaceholderFull(a) { |
| 51 |
var d = imgPlaceholder(a); |
| 52 |
d.textContent = a.imageEmoji || '🖼️'; |
| 53 |
return d; |
| 54 |
} |
| 55 |
function imgThumb(a) { |
| 56 |
var d = mk('div', 'bkbg-ogp-card-slack-thumb', { background: a.imageBg || '#6366f1' }); |
| 57 |
d.textContent = a.imageEmoji || '🖼️'; |
| 58 |
return d; |
| 59 |
} |
| 60 |
|
| 61 |
// ── platform badge ──────────────────────────────────────────────── |
| 62 |
function platformBadge(platform) { |
| 63 |
var configs = { |
| 64 |
twitter: { bg: '#15202b', color: '#1d9bf0', text: '𝕏 X / Twitter' }, |
| 65 |
facebook: { bg: '#1877f2', color: '#ffffff', text: 'f Facebook' }, |
| 66 |
linkedin: { bg: '#0a66c2', color: '#ffffff', text: 'in LinkedIn' }, |
| 67 |
slack: { bg: '#4a154b', color: '#36c5f0', text: '# Slack' }, |
| 68 |
}; |
| 69 |
var cfg = configs[platform]; |
| 70 |
if (!cfg) return null; |
| 71 |
return tx('span', 'bkbg-ogp-platform-label', cfg.text, { background: cfg.bg, color: cfg.color }); |
| 72 |
} |
| 73 |
|
| 74 |
// ── card: twitter ───────────────────────────────────────────────── |
| 75 |
function buildTwitterCard(a) { |
| 76 |
var fs = (a.bodyTypo && a.bodyTypo.sizeDesktop) || a.fontSize || 14; |
| 77 |
var wrap = mk('div', 'bkbg-ogp-card-twitter', { |
| 78 |
background: a.twitterBg || '#15202b', |
| 79 |
border: '1px solid ' + (a.twitterBorder || '#38444d') |
| 80 |
}); |
| 81 |
var body = mk('div', '', { padding: '12px 16px 14px' }); |
| 82 |
ap(body, |
| 83 |
tx('div', 'bkbg-ogp-meta', a.pageUrl, { color: a.twitterMeta || '#6b7280', fontSize: (fs - 2) + 'px', marginBottom: '4px' }), |
| 84 |
tx('div', 'bkbg-ogp-title-twitter', a.pageTitle, { color: a.twitterTitle || '#ffffff', fontSize: (fs + 1) + 'px' }) |
| 85 |
); |
| 86 |
if (a.showDescription !== false && a.pageDescription) { |
| 87 |
ap(body, tx('div', 'bkbg-ogp-desc', a.pageDescription, { |
| 88 |
color: a.twitterDesc || '#8b98a5', fontSize: (fs - 1) + 'px', WebkitLineClamp: '2' |
| 89 |
})); |
| 90 |
} |
| 91 |
ap(wrap, imgPlaceholderFull(a), body); |
| 92 |
return wrap; |
| 93 |
} |
| 94 |
|
| 95 |
// ── card: facebook ──────────────────────────────────────────────── |
| 96 |
function buildFacebookCard(a) { |
| 97 |
var fs = (a.bodyTypo && a.bodyTypo.sizeDesktop) || a.fontSize || 14; |
| 98 |
var border = '1px solid ' + (a.facebookBorder || '#dddfe2'); |
| 99 |
var wrap = mk('div', 'bkbg-ogp-card-facebook', { |
| 100 |
background: a.facebookBg || '#ffffff', |
| 101 |
border: border |
| 102 |
}); |
| 103 |
var body = mk('div', '', { padding: '10px 12px 12px', borderTop: border }); |
| 104 |
ap(body, |
| 105 |
tx('div', 'bkbg-ogp-meta', a.pageUrl, { color: a.facebookMeta || '#8a8d91', fontSize: '10px', marginBottom: '5px' }), |
| 106 |
tx('div', '', a.pageTitle, { color: a.facebookTitle || '#1c1e21', fontWeight: '700', fontSize: fs + 'px', lineHeight: '1.3', marginBottom: '4px' }) |
| 107 |
); |
| 108 |
if (a.showDescription !== false && a.pageDescription) { |
| 109 |
ap(body, tx('div', 'bkbg-ogp-desc', a.pageDescription, { |
| 110 |
color: a.facebookDesc || '#606770', fontSize: (fs - 1) + 'px', WebkitLineClamp: '2' |
| 111 |
})); |
| 112 |
} |
| 113 |
if (a.showSiteName !== false && a.siteName) { |
| 114 |
ap(body, tx('div', '', a.siteName, { color: a.facebookMeta || '#8a8d91', fontSize: '10px', textTransform: 'uppercase', letterSpacing: '0.05em', marginTop: '6px' })); |
| 115 |
} |
| 116 |
ap(wrap, imgPlaceholderFull(a), body); |
| 117 |
return wrap; |
| 118 |
} |
| 119 |
|
| 120 |
// ── card: linkedin ──────────────────────────────────────────────── |
| 121 |
function buildLinkedInCard(a) { |
| 122 |
var fs = (a.bodyTypo && a.bodyTypo.sizeDesktop) || a.fontSize || 14; |
| 123 |
var wrap = mk('div', 'bkbg-ogp-card-linkedin', { |
| 124 |
background: a.linkedinBg || '#ffffff', |
| 125 |
border: '1px solid ' + (a.linkedinBorder || '#e0dfde') |
| 126 |
}); |
| 127 |
var body = mk('div', '', { padding: '12px 16px 14px' }); |
| 128 |
ap(body, tx('div', '', a.pageTitle, { color: a.linkedinTitle || '#000000', fontWeight: '700', fontSize: (fs + 1) + 'px', lineHeight: '1.3', marginBottom: '4px' })); |
| 129 |
if (a.showSiteName !== false && a.siteName) { |
| 130 |
ap(body, tx('div', '', a.siteName + ' › ' + a.pageUrl, { |
| 131 |
color: a.linkedinMeta || '#0a66c2', fontWeight: '600', fontSize: '12px', marginBottom: '4px' |
| 132 |
})); |
| 133 |
} |
| 134 |
if (a.showDescription !== false && a.pageDescription) { |
| 135 |
ap(body, tx('div', 'bkbg-ogp-desc', a.pageDescription, { |
| 136 |
color: a.linkedinDesc || '#434649', fontSize: (fs - 1) + 'px', WebkitLineClamp: '3' |
| 137 |
})); |
| 138 |
} |
| 139 |
ap(wrap, imgPlaceholderFull(a), body); |
| 140 |
return wrap; |
| 141 |
} |
| 142 |
|
| 143 |
// ── card: slack ─────────────────────────────────────────────────── |
| 144 |
function buildSlackCard(a) { |
| 145 |
var fs = (a.bodyTypo && a.bodyTypo.sizeDesktop) || a.fontSize || 14; |
| 146 |
var wrap = mk('div', 'bkbg-ogp-card-slack', { |
| 147 |
background: a.slackBg || '#ffffff', |
| 148 |
border: '1px solid ' + (a.slackBorder || '#e8e8e8') |
| 149 |
}); |
| 150 |
var strip = mk('div', 'bkbg-ogp-card-slack-strip', { background: a.slackAccent || '#36c5f0' }); |
| 151 |
var body = mk('div', 'bkbg-ogp-card-slack-body'); |
| 152 |
var text = mk('div', 'bkbg-ogp-card-slack-text'); |
| 153 |
|
| 154 |
if (a.showSiteName !== false && a.siteName) { |
| 155 |
ap(text, tx('div', '', a.siteName, { color: a.slackTitle || '#1d1c1d', fontWeight: '700', fontSize: '12px', marginBottom: '4px' })); |
| 156 |
} |
| 157 |
ap(text, tx('div', '', a.pageTitle, { |
| 158 |
color: a.slackTitle || '#1d1c1d', fontWeight: '700', fontSize: (fs - 1) + 'px', |
| 159 |
lineHeight: '1.3', marginBottom: '4px', textDecoration: 'underline', cursor: 'pointer' |
| 160 |
})); |
| 161 |
if (a.showDescription !== false && a.pageDescription) { |
| 162 |
ap(text, tx('div', 'bkbg-ogp-desc', a.pageDescription, { |
| 163 |
color: a.slackDesc || '#616061', fontSize: '12px', WebkitLineClamp: '3' |
| 164 |
})); |
| 165 |
} |
| 166 |
ap(text, tx('div', '', a.pageUrl, { color: a.slackMeta || '#868686', fontSize: '11px', marginTop: '6px' })); |
| 167 |
|
| 168 |
ap(body, text, imgThumb(a)); |
| 169 |
ap(wrap, strip, body); |
| 170 |
return wrap; |
| 171 |
} |
| 172 |
|
| 173 |
// ── dispatch rendering ──────────────────────────────────────────── |
| 174 |
function buildCard(platform, a) { |
| 175 |
if (platform === 'twitter') return buildTwitterCard(a); |
| 176 |
if (platform === 'facebook') return buildFacebookCard(a); |
| 177 |
if (platform === 'linkedin') return buildLinkedInCard(a); |
| 178 |
if (platform === 'slack') return buildSlackCard(a); |
| 179 |
return null; |
| 180 |
} |
| 181 |
|
| 182 |
// ── main builder ────────────────────────────────────────────────── |
| 183 |
function buildBlock(appEl) { |
| 184 |
if (appEl.dataset.rendered) return; |
| 185 |
appEl.dataset.rendered = '1'; |
| 186 |
var a; |
| 187 |
try { a = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { a = {}; } |
| 188 |
|
| 189 |
typoCssVarsForEl(appEl, a.bodyTypo, '--bkbg-ogp-bd-'); |
| 190 |
|
| 191 |
var borderRadius = (a.borderRadius || 16) + 'px'; |
| 192 |
var bgColor = a.bgColor || '#f1f5f9'; |
| 193 |
|
| 194 |
var outer = mk('div', 'bkbg-ogp-wrap', { borderRadius: borderRadius, overflow: 'hidden' }); |
| 195 |
var inner = mk('div', 'bkbg-ogp-inner', { background: bgColor, padding: '24px', borderRadius: borderRadius }); |
| 196 |
|
| 197 |
var platforms = ['twitter', 'facebook', 'linkedin', 'slack']; |
| 198 |
var isAll = !a.platform || a.platform === 'all'; |
| 199 |
|
| 200 |
if (isAll) { |
| 201 |
var isGrid = a.layout === 'grid'; |
| 202 |
var container = mk('div', isGrid ? 'bkbg-ogp-grid' : 'bkbg-ogp-stack'); |
| 203 |
platforms.forEach(function (p) { |
| 204 |
var slot = mk('div', ''); |
| 205 |
ap(slot, platformBadge(p)); |
| 206 |
var card = buildCard(p, a); |
| 207 |
if (card) ap(slot, card); |
| 208 |
container.appendChild(slot); |
| 209 |
}); |
| 210 |
ap(inner, container); |
| 211 |
} else { |
| 212 |
var badge = platformBadge(a.platform); |
| 213 |
if (badge) ap(inner, badge); |
| 214 |
var single = buildCard(a.platform, a); |
| 215 |
if (single) ap(inner, single); |
| 216 |
} |
| 217 |
|
| 218 |
ap(outer, inner); |
| 219 |
appEl.innerHTML = ''; |
| 220 |
appEl.appendChild(outer); |
| 221 |
} |
| 222 |
|
| 223 |
function init() { |
| 224 |
document.querySelectorAll('.bkbg-open-graph-preview-app').forEach(buildBlock); |
| 225 |
} |
| 226 |
|
| 227 |
if (document.readyState !== 'loading') { init(); } else { document.addEventListener('DOMContentLoaded', init); } |
| 228 |
})(); |
| 229 |
|