OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-note / lib / views / search-ui.js

50 lines · javascript ref:
/**
 * Search Results — Full-page search results view
 *
 * SSR view showing search results across notebooks.
 */

import { renderPage } from '../page-layout.js'

function esc (s) {
  return (s || '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')
}

/**
 * Render the search results page
 *
 * @param {string} query - Search query
 * @param {Array} results - Search result objects
 * @param {Object} opts - { pathPrefix }
 * @returns {string} Full HTML page
 */
export function renderSearchPage (query, results, opts = {}) {
  const pathPrefix = opts.pathPrefix || ''

  let content = ''
  content += '<h1>Search</h1>'
  content += `<form method="get" action="${pathPrefix}/search" style="margin-bottom:24px">`
  content += `<input type="search" name="q" value="${esc(query)}" placeholder="Search notes..." autofocus style="max-width:500px">`
  content += '</form>'

  if (!query) {
    content += '<p class="meta">Enter a search term above.</p>'
  } else if (results.length === 0) {
    content += `<p class="meta">No results for "${esc(query)}"</p>`
  } else {
    content += `<p class="meta">${results.length} result${results.length !== 1 ? 's' : ''} for "${esc(query)}"</p>`
    for (const r of results) {
      const href = `${pathPrefix}/notebooks/${encodeURIComponent(r.notebook)}/notes/${encodeURIComponent(r.slug || r.id)}`
      content += `<a class="card" href="${href}">`
      content += `<h3>${esc(r.title || 'Untitled')}</h3>`
      content += `<div class="desc">${esc(r.notebook)}</div>`
      if (r.snippet) {
        content += `<div class="desc">${esc(r.snippet.substring(0, 200))}</div>`
      }
      content += '</a>'
    }
  }

  return renderPage('Search', content, { pathPrefix, activePage: '' })
}