diff --git a/library/packet/packet-render.js b/library/packet/packet-render.js
index 5515195bd..35b553f67 100644
--- a/library/packet/packet-render.js
+++ b/library/packet/packet-render.js
@@ -1440,6 +1440,11 @@ export function createPacketRenderer({ strings, lang = 'en', fontData = null, de
for (const w of widths) { if (x > 0 && x + 20 + w > width) { rows++; x = 0; } x += (x > 0 ? 20 : 0) + w; }
return rows;
};
+ // A point's text may carry two marks: **...** sets a run in bold, and a line break starts a new line inside the
+ // point (point 12: the reading, then its open-ended praise line under it). Measured the same way: each line on
+ // its own (an empty one still takes a line), the bold runs at PT_BOLD.
+ const ptTextLines = (str, fs, width) => String(str || '').split('\n').reduce((n, ln) =>
+ n + Math.max(1, ptLines(ln.split('**').map((part, i) => [part, fs, i % 2 ? PT_BOLD : 1]).filter(([part]) => part.trim()), width)), 0);
// A line's "normal" height, measured: 1.18-1.19 x its size in the serif faces, 1.31-1.32 where it is Chinese.
const ptNormal = (str) => (CJK.test(String(str || '')) ? 1.33 : 1.19);
function pointsHeight(sz) {
@@ -1459,7 +1464,7 @@ export function createPacketRenderer({ strings, lang = 'en', fontData = null, de
for (const p of POINTS) {
const refs = (p.refs || []).map(refText).join(' · ');
h += ptLines([[`${p.n}. ${tr(p.rhythm)}`, sz.head, PT_BOLD], ...(p.sub ? [[`— ${p.sub}`, sz.sub, 1]] : [])], BW) * sz.head * ptNormal(tr(p.rhythm));
- h += 2 + ptLines([[p.text, sz.text, 1]], BW) * sz.text * 1.3;
+ h += 2 + ptTextLines(p.text, sz.text, BW) * sz.text * 1.3;
h += 2 + ptLines([[refs, sz.refs, PT_SEMI]], BW) * sz.refs * ptNormal(refs);
if (p.print_passage) {
const IW = BW - 15; // the passage and heart blocks' 12px inset and 3px rule
@@ -1525,6 +1530,8 @@ export function createPacketRenderer({ strings, lang = 'en', fontData = null, de
`${esc(x)} ${(sref[i] || []).map(refSpan).join(' · ')}`)).join('')}
`;
}
+ // A point's text on the page: escaped first, then **...** -> bold and a line break ->
(see ptTextLines).
+ const ptText = (str) => String(str || '').split('\n').map((ln) => esc(ln).replace(/\*\*(.+?)\*\*/g, '$1')).join('
');
// `tier` forces a size tier (0..PT_TIERS); probes and gates only. data-pt-tier states the tier chosen and
// data-pt-est its estimated height, so check:packet-render can hold the estimate to the real page.
function pointsPage(tier) {
@@ -1536,7 +1543,7 @@ export function createPacketRenderer({ strings, lang = 'en', fontData = null, de
return `