index/indexedReplacer.ts

Summary

Maintainability
A
1 hr
Test Coverage
import { DomReplacement } from "../time/DomReplacement"
import { HtmlRR0SsgContext } from "../RR0SsgContext"

export class IndexedReplacer implements DomReplacement<HtmlRR0SsgContext> {

  async replacement(context: HtmlRR0SsgContext, element: HTMLElement): Promise<HTMLElement> {
    const items = element.querySelectorAll("li")
    let value = 1
    for (let i = 0; i < items.length; i++) {
      const item = items[i]
      value = this.replaceItem(context, item, value)
    }
    return element
  }

  protected replaceItem(context: HtmlRR0SsgContext, item: HTMLLIElement, i: number): number {
    const anchor = item.querySelector(".index-anchor")
    let nextIndex: number
    if (!anchor) {
      const value = item.getAttribute("value")
      const valueIndex = parseInt(value, 10)
      nextIndex = Number.isInteger(valueIndex) ? valueIndex + 1 : i + 1
      const idOrValue = item.getAttribute("id") || value
      let dateTime: string
      if (!idOrValue) {
        dateTime = (item.querySelector("time") as HTMLTimeElement)?.dateTime
      }
      const id = idOrValue || dateTime || String(i)
      const anchorEl = context.file.document.createElement("span")
      anchorEl.id = id
      item.removeAttribute("id")
      if (!dateTime) {
        item.setAttribute("value", id)
      }
      anchorEl.classList.add("index-anchor", "anchor")
      item.prepend(anchorEl)
      item.setAttribute("onclick", `window.location.hash='${id}';event.stopPropagation()`)
    } else {
      nextIndex = i
    }
    return nextIndex
  }
}