| 1 |
(function () { |
| 2 |
'use strict'; |
| 3 |
|
| 4 |
function mk(tag, cls, styles) { |
| 5 |
var d = document.createElement(tag); |
| 6 |
if (cls) d.className = cls; |
| 7 |
if (styles) Object.keys(styles).forEach(function (k) { d.style[k] = styles[k]; }); |
| 8 |
return d; |
| 9 |
} |
| 10 |
function mkText(tag, cls, text, styles) { |
| 11 |
var d = mk(tag, cls, styles); |
| 12 |
d.textContent = text; |
| 13 |
return d; |
| 14 |
} |
| 15 |
|
| 16 |
function getNoteStyle(type, o) { |
| 17 |
if (type === 'quote') return { bg: o.quoteBg, color: o.quoteColor, accent: o.quoteAccent }; |
| 18 |
if (type === 'insight') return { bg: o.insightBg, color: o.insightColor, accent: o.insightAccent }; |
| 19 |
if (type === 'question') return { bg: o.questionBg, color: o.questionColor, accent: o.questionAccent }; |
| 20 |
return { bg: o.summaryBg, color: o.summaryColor, accent: o.summaryAccent }; |
| 21 |
} |
| 22 |
|
| 23 |
function noteIcon(type) { |
| 24 |
if (type === 'quote') return '\u201C'; /* " */ |
| 25 |
if (type === 'insight') return '💡'; |
| 26 |
if (type === 'question') return '?'; |
| 27 |
return '📝'; |
| 28 |
} |
| 29 |
|
| 30 |
function buildStars(rating, starColor) { |
| 31 |
var span = mk('span', 'bkbg-rn-stars', { color: starColor, letterSpacing: '2px', fontSize: '18px' }); |
| 32 |
var s = ''; |
| 33 |
for (var i = 1; i <= 5; i++) { s += i <= rating ? '� |
| 34 |
' : '☆'; } |
| 35 |
span.textContent = s; |
| 36 |
return span; |
| 37 |
} |
| 38 |
|
| 39 |
var _typoKeys = { |
| 40 |
family:'font-family', weight:'font-weight', style:'font-style', |
| 41 |
decoration:'text-decoration', transform:'text-transform', |
| 42 |
sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m', |
| 43 |
lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m', |
| 44 |
letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m', |
| 45 |
wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m' |
| 46 |
}; |
| 47 |
function typoCssVarsForEl(el, obj, prefix) { |
| 48 |
if (!obj || typeof obj !== 'object') return; |
| 49 |
Object.keys(_typoKeys).forEach(function (k) { |
| 50 |
var v = obj[k]; |
| 51 |
if (v === undefined || v === '' || v === null) return; |
| 52 |
if (k === 'sizeDesktop' || k === 'sizeTablet' || k === 'sizeMobile') v = v + (obj.sizeUnit || 'px'); |
| 53 |
else if (k === 'lineHeightDesktop' || k === 'lineHeightTablet' || k === 'lineHeightMobile') v = v + (obj.lineHeightUnit || ''); |
| 54 |
else if (k === 'letterSpacingDesktop' || k === 'letterSpacingTablet' || k === 'letterSpacingMobile') v = v + (obj.letterSpacingUnit || 'px'); |
| 55 |
else if (k === 'wordSpacingDesktop' || k === 'wordSpacingTablet' || k === 'wordSpacingMobile') v = v + (obj.wordSpacingUnit || 'px'); |
| 56 |
el.style.setProperty(prefix + _typoKeys[k], String(v)); |
| 57 |
}); |
| 58 |
} |
| 59 |
|
| 60 |
function init() { |
| 61 |
document.querySelectorAll('.bkbg-reading-notes-app').forEach(function (appEl) { |
| 62 |
if (appEl.dataset.rendered) return; |
| 63 |
appEl.dataset.rendered = '1'; |
| 64 |
|
| 65 |
var opts; try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; } |
| 66 |
|
| 67 |
var o = { |
| 68 |
bookTitle: opts.bookTitle || '', |
| 69 |
author: opts.author || '', |
| 70 |
genre: opts.genre || '', |
| 71 |
coverEmoji: opts.coverEmoji || '📖', |
| 72 |
rating: opts.rating !== undefined ? opts.rating : 5, |
| 73 |
dateRead: opts.dateRead || '', |
| 74 |
showHeader: opts.showHeader !== false, |
| 75 |
showAuthor: opts.showAuthor !== false, |
| 76 |
showGenre: opts.showGenre !== false, |
| 77 |
showRating: opts.showRating !== false, |
| 78 |
showDateRead: opts.showDateRead !== false, |
| 79 |
notes: opts.notes || [], |
| 80 |
layout: opts.layout || 'list', |
| 81 |
borderRadius: opts.borderRadius !== undefined ? opts.borderRadius : 12, |
| 82 |
gap: opts.gap !== undefined ? opts.gap : 12, |
| 83 |
|
| 84 |
bgColor: opts.bgColor || '', |
| 85 |
headerBg: opts.headerBg || '#1e293b', |
| 86 |
headerColor: opts.headerColor || '#ffffff', |
| 87 |
starColor: opts.starColor || '#f59e0b', |
| 88 |
quoteBg: opts.quoteBg || '#fdf2f8', |
| 89 |
quoteColor: opts.quoteColor || '#86198f', |
| 90 |
quoteAccent: opts.quoteAccent || '#d946ef', |
| 91 |
insightBg: opts.insightBg || '#eff6ff', |
| 92 |
insightColor: opts.insightColor || '#1d4ed8', |
| 93 |
insightAccent: opts.insightAccent || '#3b82f6', |
| 94 |
questionBg: opts.questionBg || '#fffbeb', |
| 95 |
questionColor: opts.questionColor || '#92400e', |
| 96 |
questionAccent:opts.questionAccent || '#f59e0b', |
| 97 |
summaryBg: opts.summaryBg || '#f0fdf4', |
| 98 |
summaryColor: opts.summaryColor || '#14532d', |
| 99 |
summaryAccent: opts.summaryAccent || '#22c55e' |
| 100 |
}; |
| 101 |
|
| 102 |
/* ── Outer block ─────────────────────────────────── */ |
| 103 |
var block = mk('div', 'bkbg-rn-block'); |
| 104 |
typoCssVarsForEl(block, opts.titleTypo || {}, '--bkrn-tt-'); |
| 105 |
typoCssVarsForEl(block, opts.noteTypo || {}, '--bkrn-nt-'); |
| 106 |
if (o.bgColor) block.style.background = o.bgColor; |
| 107 |
|
| 108 |
/* ── Header ──────────────────────────────────────── */ |
| 109 |
if (o.showHeader) { |
| 110 |
var header = mk('div', 'bkbg-rn-header', { |
| 111 |
background: o.headerBg, |
| 112 |
color: o.headerColor, |
| 113 |
padding: '24px 28px', |
| 114 |
borderRadius: o.borderRadius + 'px', |
| 115 |
marginBottom: o.gap + 'px' |
| 116 |
}); |
| 117 |
|
| 118 |
var emojiEl = mkText('div', 'bkbg-rn-cover-emoji', '', { fontSize: '48px', lineHeight: '1', flexShrink: '0' }); |
| 119 |
var _IP = window.bkbgIconPicker; |
| 120 |
if (_IP && o.coverEmojiType && o.coverEmojiType !== 'custom-char') { |
| 121 |
var _icn = _IP.buildFrontendIcon(o.coverEmojiType, o.coverEmoji, o.coverEmojiDashicon, o.coverEmojiImageUrl, o.coverEmojiDashiconColor); |
| 122 |
if (_icn) emojiEl.appendChild(_icn); |
| 123 |
else emojiEl.textContent = o.coverEmoji; |
| 124 |
} else { |
| 125 |
emojiEl.textContent = o.coverEmoji; |
| 126 |
} |
| 127 |
header.appendChild(emojiEl); |
| 128 |
|
| 129 |
var info = mk('div', 'bkbg-rn-book-info', { flex: '1' }); |
| 130 |
|
| 131 |
var titleEl = mkText('h3', 'bkbg-rn-book-title', o.bookTitle, { |
| 132 |
margin: '0 0 4px', color: o.headerColor |
| 133 |
}); |
| 134 |
info.appendChild(titleEl); |
| 135 |
|
| 136 |
if (o.showAuthor && o.author) { |
| 137 |
info.appendChild(mkText('div', 'bkbg-rn-author', 'by ' + o.author, { |
| 138 |
fontSize: '14px', color: o.headerColor, opacity: '.84', marginBottom: '8px' |
| 139 |
})); |
| 140 |
} |
| 141 |
|
| 142 |
var meta = mk('div', 'bkbg-rn-meta'); |
| 143 |
if (o.showGenre && o.genre) { |
| 144 |
meta.appendChild(mkText('span', 'bkbg-rn-genre-badge', o.genre, { |
| 145 |
background: 'rgba(255,255,255,.15)', color: o.headerColor |
| 146 |
})); |
| 147 |
} |
| 148 |
if (o.showRating) { |
| 149 |
meta.appendChild(buildStars(o.rating, o.starColor)); |
| 150 |
} |
| 151 |
if (o.showDateRead && o.dateRead) { |
| 152 |
meta.appendChild(mkText('span', 'bkbg-rn-date', o.dateRead, { |
| 153 |
fontSize: '12px', color: o.headerColor, opacity: '.7' |
| 154 |
})); |
| 155 |
} |
| 156 |
info.appendChild(meta); |
| 157 |
header.appendChild(info); |
| 158 |
block.appendChild(header); |
| 159 |
} |
| 160 |
|
| 161 |
/* ── Notes ───────────────────────────────────────── */ |
| 162 |
var notesWrap = mk('div', 'bkbg-rn-notes' + (o.layout === 'grid' ? ' is-grid' : ''), { |
| 163 |
gap: o.gap + 'px' |
| 164 |
}); |
| 165 |
|
| 166 |
o.notes.forEach(function (note) { |
| 167 |
var ns = getNoteStyle(note.type || 'insight', o); |
| 168 |
var isQuote = note.type === 'quote'; |
| 169 |
|
| 170 |
var noteEl = mk('div', 'bkbg-rn-note bkbg-rn-note--' + (note.type || 'insight'), { |
| 171 |
background: ns.bg, |
| 172 |
borderLeft: '4px solid ' + ns.accent, |
| 173 |
borderRadius: (o.borderRadius - 2) + 'px', |
| 174 |
padding: '14px 18px' |
| 175 |
}); |
| 176 |
|
| 177 |
var iconEl = mkText('span', 'bkbg-rn-note-icon' + (isQuote ? ' is-quote' : ''), noteIcon(note.type || 'insight'), { |
| 178 |
color: ns.accent, |
| 179 |
fontSize: isQuote ? '32px' : '18px', |
| 180 |
lineHeight: '1', |
| 181 |
flexShrink: '0', |
| 182 |
fontFamily: isQuote ? 'Georgia, serif' : 'inherit', |
| 183 |
marginTop: isQuote ? '-6px' : '0' |
| 184 |
}); |
| 185 |
|
| 186 |
var body = mk('div', 'bkbg-rn-note-body', { flex: '1' }); |
| 187 |
|
| 188 |
body.appendChild(mkText('span', 'bkbg-rn-note-type-label', note.type || 'insight', { color: ns.accent })); |
| 189 |
|
| 190 |
var text = mk('p', 'bkbg-rn-note-text', { |
| 191 |
margin: '0', |
| 192 |
color: ns.color |
| 193 |
}); |
| 194 |
text.textContent = note.text || ''; |
| 195 |
body.appendChild(text); |
| 196 |
|
| 197 |
if (note.source) { |
| 198 |
body.appendChild(mkText('span', 'bkbg-rn-note-source', '— ' + note.source, { |
| 199 |
color: ns.accent, fontSize: '12px', fontStyle: 'italic' |
| 200 |
})); |
| 201 |
} |
| 202 |
|
| 203 |
noteEl.appendChild(iconEl); |
| 204 |
noteEl.appendChild(body); |
| 205 |
notesWrap.appendChild(noteEl); |
| 206 |
}); |
| 207 |
|
| 208 |
block.appendChild(notesWrap); |
| 209 |
|
| 210 |
/* ── Insert ──────────────────────────────────────── */ |
| 211 |
appEl.parentNode.insertBefore(block, appEl); |
| 212 |
appEl.style.display = 'none'; |
| 213 |
}); |
| 214 |
} |
| 215 |
|
| 216 |
if (document.readyState !== 'loading') { init(); } |
| 217 |
else { document.addEventListener('DOMContentLoaded', init); } |
| 218 |
})(); |
| 219 |
|