/** * Builder class to generate xml and robots.txt * Returns only string values */ export class SitemapBuilder { /** * Create XML Template * @param content * @returns */ withXMLTemplate(content) { return `\n\n${content}`; } /** * Generates sitemap-index.xml * @param allSitemaps * @returns */ buildSitemapIndexXml(allSitemaps) { return [ '', '', ...(allSitemaps?.map((x) => `${x}`) ?? []), '', ].join('\n'); } /** * Normalize sitemap field keys to stay consistent with order * @link https://www.w3schools.com/xml/el_sequence.asp * @link https://github.com/iamvishnusankar/next-sitemap/issues/345 * @param x * @returns */ normalizeSitemapField(x) { const { loc, lastmod, changefreq, priority, ...restProps } = x; // Return keys in following order return { loc, lastmod, changefreq, priority, ...restProps, }; } /** * Generates sitemap.xml * @param fields * @returns */ buildSitemapXml(fields) { const content = fields .map((x) => { // Normalize sitemap field keys to stay consistent with order const field = this.normalizeSitemapField(x); // Field array to keep track of properties const fieldArr = []; // Iterate all object keys and key value pair to field-set for (const key of Object.keys(field)) { // Skip reserved keys if (['trailingSlash'].includes(key)) { continue; } if (field[key]) { if (key !== 'alternateRefs') { fieldArr.push(`<${key}>${field[key]}`); } else { const altRefField = this.buildAlternateRefsXml(field.alternateRefs); fieldArr.push(altRefField); } } } // Append previous value and return return `${fieldArr.join('')}\n`; }) .join(''); return this.withXMLTemplate(content); } /** * Generate alternate refs.xml * @param alternateRefs * @returns */ buildAlternateRefsXml(alternateRefs = []) { return alternateRefs .map((alternateRef) => { return ``; }) .join(''); } }