UNPKG

@taprootio/rollup-plugin-taproot

Version:
137 lines (115 loc) 4.12 kB
import { cloneable } from "./helpers.ts/cloneable" import { PageData } from "./models/TaprootPageRenderer" import { Author, Publisher } from "./models/TaprootPluginOptions" interface SocialImage { Url: string Width: number Height: number MediaType: string } interface HeadData extends Omit<PageData, "Author"> { Author?: Author CharSet?: string Locale?: string NoRobots?: boolean PageType?: string Publisher: Publisher SocialImage: SocialImage } // NOTE: Flash of unstyled content can happen when resources, // such as fonts and other styles, are loaded after // initial render. This waits for things to load before // showing the page. Template body needs an initial // class of "loading" for it to work. const FUCFix = [ `<style> body { transition: opacity ease-in 500ms; } body.loading { opacity: 0; } body.loading.loaded { opacity: 100; } </style>`, `<script type="text/javascript"> window.onload = () => { document.body.classList.add("loaded") } </script>`, ] const BuildHead = (data: HeadData): string => { if (!data.Canonical) { throw "No canonical specified" } // Clone it so any changes made here do not bubble up. data = cloneable.deepCopy(data) console.log(JSON.stringify(data)) data.Canonical = data.Canonical?.replace("index.html", "") data.CharSet = data.CharSet ?? "UTF-8" data.Locale = data.Locale ?? "en_US" data.PageType = data.PageType?.toLowerCase() ?? "article" if (!data.Title) { throw `No title for ${data.Canonical}` } if (!data.Description) { throw `No description for ${data.Canonical}` } const validPageTypes = ["article", "website"] if (validPageTypes.indexOf(data.PageType) < 0) { throw `Invalid page type for ${data.Canonical}` } if (data.PageType == "article" && !data.Author) { throw `Article must have an author for ${data.Canonical}` } const tags = [ `<meta charset="${data.CharSet}" />`, `<meta name="viewport" content="width=device-width, initial-scale=1" />`, ] if (!data.NoRobots) { tags.push( `<meta name="robots" content="index, follow, max-image-preview:large" />` ) } tags.push(...FUCFix) tags.push( `<title>${data.Title} → ${data.Publisher.Name}</title>`, `<meta name="description" content="${data.Description}" />`, `<link rel="canonical" href="${data.Canonical}" />`, `<meta property="og:locale" content="${data.Locale}" />`, `<meta property="og:type" content="${data.PageType}" />`, `<meta property="og:title" content="${data.Title}" />`, `<meta property="og:description" content="${data.Description}" />`, `<meta property="og:url" content="${data.Canonical}" />`, `<meta property="og:site_name" content="${data.Publisher.Name}" />`, `<meta property="article:publisher" content="${data.Publisher.FacebookPage}" />`, `<meta property="og:image" content="${data.SocialImage.Url}" />`, `<meta property="og:image:width" content="${data.SocialImage.Width}" />`, `<meta property="og:image:height" content="${data.SocialImage.Height}" />`, `<meta property="og:image:type" content="${data.SocialImage.MediaType}" />`, // e.g. "image/png" `<meta name="twitter:card" content="summary_large_image" />`, `<meta name="twitter:site" content="${data.Publisher.TwitterHandle}" />` ) if (data.DatePublished) { tags.push( `<meta property="article:published_time" content="${data.DatePublished}" />` ) } if (data.DateModified) { tags.push( `<meta property="article:modified_time" content="${data.DateModified}" />` ) } if (data.Author) { tags.push( `<meta property="article:author" content="${data.Author.FacebookPage}" />`, `<meta name="author" content="${data.Author.Name}" />`, `<meta name="twitter:creator" content="${data.Author.TwitterHandle}" />`, `<meta name="twitter:label1" content="Written by" />`, `<meta name="twitter:data1" content="${data.Author.Name}" />` ) } return tags.join("\n") } export { BuildHead, type HeadData, type SocialImage }