Skip to content

Content Renderer

The renderer system in @welshman/content provides flexible ways to convert parsed content into text or HTML output. It includes customizable rendering options and specialized handlers for each content type.

Renderer Class

typescript
class Renderer {
  constructor(readonly options: RenderOptions)

  // Core methods
  toString(): string
  addText(value: string): void
  addNewlines(count: number): void
  addLink(href: string, display: string): void
  addEntityLink(entity: string): void
}

Render Options

typescript
type RenderOptions = {
  // String to use for newlines
  newline: string

  // Base URL for Nostr entities
  entityBase: string

  // Custom link rendering
  renderLink: (href: string, display: string) => string

  // Custom entity rendering
  renderEntity: (entity: string) => string
}

Built-in Renderers

Text Renderer

typescript
const textRenderOptions = {
  newline: "\n",
  entityBase: "",
  renderLink: (href, display) => href,
  renderEntity: (entity) => entity.slice(0, 16) + "…"
}

const textRenderer = makeTextRenderer({
  // Override default options if needed
})

HTML Renderer

typescript
const htmlRenderOptions = {
  newline: "\n",
  entityBase: "https://njump.me/",
  renderLink: (href, display) => {
    const element = document.createElement("a")
    element.href = sanitizeUrl(href)
    element.target = "_blank"
    element.innerText = display
    return element.outerHTML
  },
  renderEntity: (entity) => entity.slice(0, 16) + "…"
}

const htmlRenderer = makeHtmlRenderer({
  // Override default options if needed
})

Content Type Renderers

typescript
// Basic content
renderText(p: ParsedText, r: Renderer): void
renderNewline(p: ParsedNewline, r: Renderer): void
renderCode(p: ParsedCode, r: Renderer): void
renderTopic(p: ParsedTopic, r: Renderer): void

// Links
renderLink(p: ParsedLink, r: Renderer): void

// Nostr entities
renderEvent(p: ParsedEvent, r: Renderer): void
renderProfile(p: ParsedProfile, r: Renderer): void
renderAddress(p: ParsedAddress, r: Renderer): void

// Special formats
renderCashu(p: ParsedCashu, r: Renderer): void
renderInvoice(p: ParsedInvoice, r: Renderer): void
renderEllipsis(p: ParsedEllipsis, r: Renderer): void

Usage Examples

Basic Text Rendering

typescript
const parsed = parse({
  content: "Hello #nostr, check nostr:npub1...",
  tags: []
})

// Render as plain text
const text = renderAsText(parsed).toString()

// Render as HTML
const html = renderAsHtml(parsed).toString()

Custom Rendering Options

typescript
// Custom text renderer
const customText = renderAsText(parsed, {
  entityBase: "nostr:",
  renderEntity: (entity) => entity.slice(0, 8)
}).toString()

// Custom HTML renderer
const customHtml = renderAsHtml(parsed, {
  entityBase: "https://example.com/",
  renderLink: (href, display) => `<a class="custom-link" href="${href}">${display}</a>`,
  renderEntity: (entity) => `<span class="entity">${entity}</span>`
}).toString()

Rendering Individual Elements

typescript
const renderer = makeHtmlRenderer()

// Render single element
renderOne({
  type: ParsedType.Link,
  value: {
    url: new URL("https://example.com"),
    meta: {},
    isMedia: false
  },
  raw: "https://example.com"
}, renderer)

// Render multiple elements
renderMany([
  {
    type: ParsedType.Text,
    value: "Hello ",
    raw: "Hello "
  },
  {
    type: ParsedType.Topic,
    value: "nostr",
    raw: "#nostr"
  }
], renderer)

Complete Example

typescript
// Parse and process content
const parsed = parse({
  content: `
    Check out this profile: nostr:npub1...

    Code example:
    \`console.log("hello")\`

    #nostr #bitcoin

    https://example.com/image.jpg
  `,
  tags: []
})

// Create custom renderer
const renderer = makeHtmlRenderer({
  entityBase: "https://example.com/",
  renderLink: (href, display) => {
    if (href.endsWith('.jpg')) {
      return `<img src="${href}" alt="${display}">`
    }
    return `<a href="${href}">${display}</a>`
  },
  renderEntity: (entity) => {
    return `<span class="entity">${entity.slice(0, 8)}</span>`
  }
})

// Render content
const html = render(parsed, renderer).toString()

The renderer system provides a flexible way to output parsed content in various formats while maintaining control over the rendering process. Its modular design allows for easy customization and extension for specific application needs.