OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
 
master @ 79 LINES
 
[ HISTORY ]  [ UP ]
 

// Hand-rolled RSS and sitemap XML - no integration dependency, and the
// builders stay pure and testable.

export interface FeedItem {
  title: string;
  url: string;       // absolute
  published: string; // ISO date
  description: string;
}

export interface SitemapUrl {
  loc: string;       // absolute
  lastmod?: string;  // ISO date
}

const esc = (s: string) =>
  s
    .replace(/&/g, "&")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");

export interface RssOpts {
  title: string;
  site: string;      // absolute site url
  description: string;
  items: FeedItem[];
}

export function buildRss({ title, site, description, items }: RssOpts): string {
  const channel = items
    .map((it) =>
      [
        "    <item>",
        `      <title>${esc(it.title)}</title>`,
        `      <link>${esc(it.url)}</link>`,
        `      <guid>${esc(it.url)}</guid>`,
        `      <pubDate>${new Date(it.published).toUTCString()}</pubDate>`,
        `      <description>${esc(it.description)}</description>`,
        "    </item>",
      ].join("\n"),
    )
    .join("\n");
  return [
    `<?xml version="1.0" encoding="UTF-8"?>`,
    `<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">`,
    "  <channel>",
    `    <title>${esc(title)}</title>`,
    `    <link>${esc(site)}</link>`,
    `    <atom:link href="${esc(site)}rss.xml" rel="self" type="application/rss+xm
l"/>`,
    `    <description>${esc(description)}</description>`,
    "    <language>en</language>",
    channel,
    "  </channel>",
    "</rss>",
    "",
  ].join("\n");
}

export function buildSitemap(urls: SitemapUrl[]): string {
  const body = urls
    .map((u) =>
      [
        "  <url>",
        `    <loc>${esc(u.loc)}</loc>`,
        ...(u.lastmod ? [`    <lastmod>${esc(u.lastmod)}</lastmod>`] : []),
        "  </url>",
      ].join("\n"),
    )
    .join("\n");
  return [
    `<?xml version="1.0" encoding="UTF-8"?>`,
    `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`,
    body,
    "</urlset>",
    "",
  ].join("\n");
}

// Hand-rolled RSS and sitemap XML - no inte
gration dependency, and the
// builders stay pure and testable.

export interface FeedItem {
  title: string;
  url: string;       // absolute
  published: string; // ISO date
  description: string;
}

export interface SitemapUrl {
  loc: string;       // absolute
  lastmod?: string;  // ISO date
}

const esc = (s: string) =>
  s
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;");

export interface RssOpts {
  title: string;
  site: string;      // absolute site url
  description: string;
  items: FeedItem[];
}

export function buildRss({ title, site, desc
ription, items }: RssOpts): string {
  const channel = items
    .map((it) =>
      [
        "    <item>",
        `      <title>${esc(it.title)}</titl
e>`,
        `      <link>${esc(it.url)}</link>`,
        `      <guid>${esc(it.url)}</guid>`,
        `      <pubDate>${new Date(it.publis
hed).toUTCString()}</pubDate>`,
        `      <description>${esc(it.descrip
tion)}</description>`,
        "    </item>",
      ].join("\n"),
    )
    .join("\n");
  return [
    `<?xml version="1.0" encoding="UTF-8"?>`
,
    `<rss version="2.0" xmlns:atom="http://w
ww.w3.org/2005/Atom">`,
    "  <channel>",
    `    <title>${esc(title)}</title>`,
    `    <link>${esc(site)}</link>`,
    `    <atom:link href="${esc(site)}rss.xm
l" rel="self" type="application/rss+xml"/>`,
    `    <description>${esc(description)}</d
escription>`,
    "    <language>en</language>",
    channel,
    "  </channel>",
    "</rss>",
    "",
  ].join("\n");
}

export function buildSitemap(urls: SitemapUr
l[]): string {
  const body = urls
    .map((u) =>
      [
        "  <url>",
        `    <loc>${esc(u.loc)}</loc>`,
        ...(u.lastmod ? [`    <lastmod>${esc
(u.lastmod)}</lastmod>`] : []),
        "  </url>",
      ].join("\n"),
    )
    .join("\n");
  return [
    `<?xml version="1.0" encoding="UTF-8"?>`
,
    `<urlset xmlns="http://www.sitemaps.org/
schemas/sitemap/0.9">`,
    body,
    "</urlset>",
    "",
  ].join("\n");
}
 
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET