UNPKG

@forge42/seo-tools

Version:

Framework agnostic set of helpers designed to help you create, maintain and develop your SEO

1 lines 5.79 kB
{"version":3,"sources":["../src/canonical.ts"],"sourcesContent":["export interface CanonicalLinkOptions<U> {\n\t/**\n\t * Transformer function that generates the alternative url for the link tag by looping through the alternatives\n\t * @param params Object containing the url, alternative and domain\n\t * @returns The url to be passed to the href attribute of the link tag\n\t * ```ts\n\t * urlTransformer: ({ url, alternative, domain }) => {\n\t * return `${domain}/${alternative}${url}`;\n\t * }\n\t * ```\n\t */\n\turlTransformer: (params: { url: string; alternative: U; domain: string; canonicalUrl: string }) => string | null\n\t/**\n\t * Transformer function that generates the attributes for the alternative link tag\n\t * @param params Object containing the url, alternative and domain\n\t * @returns Record of attributes to be added to the link tag\n\t *\n\t * ```ts\n\t * altAttributesTransformer: ({ url, alternative, domain }) => {\n\t * return {\n\t * hreflang: alternative,\n\t * href: `${domain}/${alternative}${url}`,\n\t * };\n\t * }\n\t * ```\n\t */\n\taltAttributesTransformer?: (params: { url: string; alternative: U; domain: string }) => Omit<\n\t\tCanonicalLink,\n\t\t\"tagName\" | \"rel\" | \"href\"\n\t>\n\t/**\n\t * Array of alternative languages/urls or whatever you want to generate the alternative links for\n\t * @example [\"en\", \"bs\"]\n\t */\n\talternatives: U[]\n\t/**\n\t * The domain of the website\n\t * @example \"https://example.com\"\n\t */\n\tdomain: string\n\t/**\n\t * The url of the current page\n\t * @example \"/some-page\"\n\t */\n\turl: string\n\t/**\n\t * The canonical url of the current page\n\t * @example \"https://example.com/some-page\"\n\t */\n\tcanonicalUrl?: string\n\t/**\n\t * Object containing the attributes to be added to the canonical link tag\n\t * @example {rel: \"canonical\", href: \"https://example.com/some-page\"}\n\t *\n\t * */\n\tcanonicalAttributes?: Record<string, string>\n}\n\nexport interface CanonicalLink {\n\ttagName: \"link\"\n\trel: string\n\thref: string\n\t[key: string]: string\n}\n\nconst convertObjectToString = (obj: Record<string, string>) => {\n\treturn Object.entries(obj)\n\t\t.map(([key, value]) => `${key}=\"${value}\"`)\n\t\t.join(\" \")\n}\n\nfunction isHrefDefined(obj: Record<string, string | null>): obj is CanonicalLink {\n\treturn obj.href !== null\n}\n/**\n * Method used to generate the canonical and alternative links for a page\n * @param options CanonicalLinkOptions - Object containing the options for generating the canonical links\n * @param asJson Whether to return the canonical links as an array of objects or a string\n * @returns Returns an array of objects or a string containing the canonical and alternative links\n */\nexport const generateCanonicalLinks = <U, T extends boolean>(\n\toptions: CanonicalLinkOptions<U>,\n\tasJson: T = true as T\n): T extends true ? CanonicalLink[] : string => {\n\tconst { urlTransformer, alternatives, domain, canonicalAttributes, url, altAttributesTransformer } = options\n\tconst generatedCanonicalAttributes = canonicalAttributes ? convertObjectToString(canonicalAttributes) : \"\"\n\tconst canonicalUrl = options.canonicalUrl ?? `${domain + url}`\n\tif (asJson) {\n\t\treturn [\n\t\t\t{\n\t\t\t\ttagName: \"link\",\n\t\t\t\trel: \"canonical\",\n\t\t\t\thref: canonicalUrl,\n\t\t\t\t...(canonicalAttributes ? canonicalAttributes : {}),\n\t\t\t},\n\t\t\t...alternatives\n\t\t\t\t.map((alternative) => ({\n\t\t\t\t\ttagName: \"link\" as const,\n\t\t\t\t\trel: \"alternate\",\n\t\t\t\t\thref: urlTransformer({ url, alternative, domain, canonicalUrl }),\n\t\t\t\t\t...(altAttributesTransformer ? altAttributesTransformer({ url, alternative, domain }) : {}),\n\t\t\t\t}))\n\t\t\t\t.filter(isHrefDefined),\n\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: we use satisfies to type-safe it and as any cast to allow for conditional return type\n\t\t] satisfies CanonicalLink[] as any\n\t}\n\treturn [\n\t\t`<link rel=\"canonical\" href=\"${domain + url}\" ${generatedCanonicalAttributes}>`,\n\t\t...alternatives.map(\n\t\t\t(alternative) =>\n\t\t\t\t`<link rel=\"alternate\" href=\"${urlTransformer({ url, alternative, domain, canonicalUrl })}\" ${\n\t\t\t\t\taltAttributesTransformer ? convertObjectToString(altAttributesTransformer({ url, alternative, domain })) : \"\"\n\t\t\t\t} >`\n\t\t),\n\t\t// biome-ignore lint/suspicious/noExplicitAny: we use satisfies to type-safe it and as any cast to allow for conditional return type\n\t].join(\"\\n\") satisfies string as any\n}\n"],"mappings":"AAiEA,IAAMA,EAAyBC,GACvB,OAAO,QAAQA,CAAG,EACvB,IAAI,CAAC,CAACC,EAAKC,CAAK,IAAM,GAAGD,CAAG,KAAKC,CAAK,GAAG,EACzC,KAAK,GAAG,EAGX,SAASC,EAAcH,EAA0D,CAChF,OAAOA,EAAI,OAAS,IACrB,CAOO,IAAMI,EAAyB,CACrCC,EACAC,EAAY,KACmC,CAC/C,GAAM,CAAE,eAAAC,EAAgB,aAAAC,EAAc,OAAAC,EAAQ,oBAAAC,EAAqB,IAAAC,EAAK,yBAAAC,CAAyB,EAAIP,EAC/FQ,EAA+BH,EAAsBX,EAAsBW,CAAmB,EAAI,GAClGI,EAAeT,EAAQ,cAAgB,GAAGI,EAASE,CAAG,GAC5D,OAAIL,EACI,CACN,CACC,QAAS,OACT,IAAK,YACL,KAAMQ,EACN,GAAIJ,GAA4C,CAAC,CAClD,EACA,GAAGF,EACD,IAAKO,IAAiB,CACtB,QAAS,OACT,IAAK,YACL,KAAMR,EAAe,CAAE,IAAAI,EAAK,YAAAI,EAAa,OAAAN,EAAQ,aAAAK,CAAa,CAAC,EAC/D,GAAIF,EAA2BA,EAAyB,CAAE,IAAAD,EAAK,YAAAI,EAAa,OAAAN,CAAO,CAAC,EAAI,CAAC,CAC1F,EAAE,EACD,OAAON,CAAa,CAGvB,EAEM,CACN,iCAAiCM,EAASE,CAAG,KAAKE,CAA4B,IAC9E,GAAGL,EAAa,IACdO,GACA,+BAA+BR,EAAe,CAAE,IAAAI,EAAK,YAAAI,EAAa,OAAAN,EAAQ,aAAAK,CAAa,CAAC,CAAC,KACxFF,EAA2Bb,EAAsBa,EAAyB,CAAE,IAAAD,EAAK,YAAAI,EAAa,OAAAN,CAAO,CAAC,CAAC,EAAI,EAC5G,IACF,CAED,EAAE,KAAK;AAAA,CAAI,CACZ","names":["convertObjectToString","obj","key","value","isHrefDefined","generateCanonicalLinks","options","asJson","urlTransformer","alternatives","domain","canonicalAttributes","url","altAttributesTransformer","generatedCanonicalAttributes","canonicalUrl","alternative"]}