// Build-time markup for the Neighbors page: its Markdown list of sites, drawn as lots on a plat map. import { ITEM, text, trimStop, hash, findList, address } from './list.mjs'; export { address }; const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; /** A plausible survey call for a lot's front line, from its owner's name: "N 04°12′ E · 82.5′". */ export function bearing(name) { const h = hash(name); const deg = String(h % 90).padStart(2, '0'); const min = String((h >>> 7) % 60).padStart(2, '0'); const dist = (70 + ((h >>> 13) % 350) / 10).toFixed(1); return `${h & 1 ? 'N' : 'S'} ${deg}°${min}′ ${h & 2 ? 'E' : 'W'} · ${dist}′`; } /** "Maggie Appleton" → "MA". */ export const initials = (name) => text(name).split(/\s+/).map((w) => w[0]).join('').toUpperCase().slice(0, 3); /** * Parse one rendered list item, `Name: line. Start here: piece. Elsewhere: piece, in Pub.` * @returns {{ href: string, name: string, line: string, start: string, elsewhere: string } | null} */ export function parseNeighbor(li) { const m = li.trim().match(ITEM); if (!m) return null; const [, href, name, rest] = m; const [before, after = ''] = rest.split(/Start here:/); const [start, elsewhere = ''] = after.split(/Elsewhere:/); const line = before.trim() === 'TK.' ? 'TK' : before.trim(); return { href, name, line, start: trimStop(start), elsewhere: trimStop(elsewhere) }; } /** One neighbor's lot on the plat: initials, a sprig, their name and address, and what to read first. */ function lot(n) { return [ `
  • `, ``, ``, `

    ${n.name}

    `, `

    ${address(n.href)}

    `, n.line ? `

    ${n.line}

    ` : '', n.start ? `

    Start here ${n.start}

    ` : '', n.elsewhere ? `

    Elsewhere ${n.elsewhere}

    ` : '', '
  • ', ].join('\n'); } /** * Turn the first list in a rendered page body into the plat: a map key, one lot per neighbor, * a hatched lot for this garden and a title block. Leaves the body alone if the list doesn't parse. * @param {string} html * @param {string} [tended] YYYY-MM-DD, the survey date on the title block */ export function platMap(html, tended) { const list = findList(html ?? ''); if (!list) return html; const items = list.items.map(parseNeighbor); if (!items.length || items.some((n) => !n)) return html; const [y, mo] = String(tended ?? '').split('-').map(Number); const surveyed = y && mo ? `Surveyed ${MONTHS[mo - 1]} ${y} · Sheet 1 of 1` : 'Sheet 1 of 1'; const plat = [ '

    ', 'Hatched lot: ohlin.co/notes, you are here', `${items.length} lots`, 'North', '1 lot = 1 good read', '

    ', '', `

    Plat of the NeighborhoodKevin⚡Ohlin · Notes${surveyed}

    `, ].join('\n'); return html.slice(0, list.start) + plat + html.slice(list.end); }