// The Questions plot: a note's "## Questions" section printed as seeds in a plot. import { QUESTIONS_ART } from './questions-art.mjs'; import { sprigMarkup } from '../../notes-src/stack/folio.mjs'; const INLINE_VOID = new Set(['br', 'img', 'wbr']); /** * Split a paragraph's inner HTML into seeds, one per question. A cut falls after each "?" (and any closing * quote) that sits outside inline tags and is followed by a space and a word that doesn't start lowercase, so * "(California Forever?) in my…" stays whole. Text after the last question stays with it. * @param {string} inner * @returns {string[]} */ export function questionSeeds(inner) { const seeds = []; const re = /<(\/?)([a-zA-Z][a-zA-Z0-9]*)\b[^>]*?(\/?)>|\?[”"’]*(?=\s+[^\sa-z])/g; let depth = 0, last = 0, m; while ((m = re.exec(inner))) { if (m[2]) { if (!INLINE_VOID.has(m[2].toLowerCase()) && !m[3]) depth += m[1] ? -1 : 1; } else if (depth === 0) { seeds.push(inner.slice(last, m.index + m[0].length)); last = m.index + m[0].length; } } const rest = inner.slice(last).trim(); if (rest && seeds.length && !/\?[”"’]*(<\/[a-z]+>)*$/i.test(rest)) seeds[seeds.length - 1] += ` ${rest}`; else if (rest) seeds.push(rest); return seeds.map((s) => s.trim()).filter(Boolean); } /** * Wrap the "## Questions" section in a plot: each paragraph becomes seeds in one list. Sidenotes and other * blocks (an answer list, say) are left as they are. Note pages also get the plot's art; cards don't. */ export function wrapQuestions(html, { art = true } = {}) { const start = html.indexOf('

/g, (a) => `\u0000${asides.push(a) - 1}\u0000`) .replace(/

([\s\S]*?)<\/p>/g, (_, inner) => `

`) .replace(/<\/ul>\s*

') + ''.length; section = section.slice(0, head) + QUESTIONS_ART + section.slice(head); } return `${html.slice(0, start)}
${section}
${html.slice(end)}`; }