New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More โ†’
Socket
Sign inDemoInstall
Socket

sitemap-manager

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sitemap-manager - npm Package Compare versions

Comparing version 2.1.0 to 2.2.0

dist/main.d.ts

18

CHANGELOG.md

@@ -0,1 +1,19 @@

# [2.2.0](https://github.com/CBW2007/sitemap-manager/compare/v2.1.0...v2.2.0) (2022-01-22)
### Bug Fixes
* **main:** fix a bug that makes "isFinished" not work ([7be745f](https://github.com/CBW2007/sitemap-manager/commit/7be745fb6002a22b8047863bffb2a60ba3e3e9bf))
* **test:** remove rmDirSync, use rmSync instead ([0af6a53](https://github.com/CBW2007/sitemap-manager/commit/0af6a532909e98bb0d015ad8137080f64723337b))
### Features
* add checks of the repeated and invalid url ([343ef17](https://github.com/CBW2007/sitemap-manager/commit/343ef17c485d75eb682fb4a72496d28327a90bc6))
* add hooks ([cfab1e9](https://github.com/CBW2007/sitemap-manager/commit/cfab1e99f9f782c9ac84f74fdcdd96f523335a85))
* allow to add single url obj ([789c48e](https://github.com/CBW2007/sitemap-manager/commit/789c48e7a0b83293f95be23a0ce148c07edfab80))
* export types as well ([5fc8d18](https://github.com/CBW2007/sitemap-manager/commit/5fc8d1884e1fb15027d0dc38c8d3aa5eccfc5718))
# [2.1.0](https://github.com/CBW2007/sitemap-manager/compare/v2.0.1...v2.1.0) (2021-08-04)

@@ -2,0 +20,0 @@

23

dist/index.d.ts

@@ -1,20 +0,3 @@

interface Option {
outDir?: string;
siteURL: string;
pathPrefix?: string;
}
interface Url {
loc: string;
lastmod?: string | Date;
changefreq?: 'never' | 'yearly' | 'monthly' | 'weekly' | 'daily' | 'hourly' | 'always' | 1 | 2 | 3 | 4 | 5 | 6 | 7;
priority?: number;
}
declare class SitemapManager {
#private;
options: Option;
isFinished: Boolean;
constructor(options: Option);
addUrl(name: string, url: Array<Url>): void;
finish(): Promise<void>;
}
export { SitemapManager };
import { SitemapManager } from './main';
import * as types from './types';
export { SitemapManager, types };
"use strict";
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _SitemapManager_urlDatas;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SitemapManager = void 0;
const fs_1 = __importDefault(require("fs"));
const xml_1 = __importDefault(require("xml"));
const url_1 = require("url");
const path_1 = __importDefault(require("path"));
const xmlStylesheet = Buffer.from('PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjx4c2w6c3R5bGVzaGVldCB4bWxuczp4c2w9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvWFNML1RyYW5zZm9ybSIgeG1sbnM6c2l0ZW1hcD0iaHR0cDovL3d3dy5zaXRlbWFwcy5vcmcvc2NoZW1hcy9zaXRlbWFwLzAuOSIgeG1sbnM6Zm49Imh0dHA6Ly93d3cudzMub3JnLzIwMDUvMDIveHBhdGgtZnVuY3Rpb25zIiB2ZXJzaW9uPSIxLjAiPjx4c2w6dGVtcGxhdGUgbWF0Y2g9Ii8iPjxodG1sPjxoZWFkPjx0aXRsZT5TaXRlbWFwPC90aXRsZT48bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEsIG1heGltdW0tc2NhbGU9MSwgc2hyaW5rLXRvLWZpdD1ubyIvPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJCSAJCS5hLW5vLXVsOjpiZWZvcmUgew0KCQkgCQkJZGlzcGxheTogbm9uZTsNCgkJIAkJfQ0KCQkJPC9zdHlsZT48IS0tIE1EVUkgQ1NTIC0tPjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9tZHVpQDEuMC4xL2Rpc3QvY3NzL21kdWkubWluLmNzcyIgaW50ZWdyaXR5PSJzaGEzODQtY0xSck1xMzlIT1pkdkUwajZ5Qm9qTzQrMVBySGZCN2E5bDVxTGNtUm0vZmlXWFlZK0NuZEpQbXl1NUZWLzlUdyIgY3Jvc3NvcmlnaW49ImFub255bW91cyIvPjwvaGVhZD48Ym9keT48ZGl2IGNsYXNzPSJtZHVpLWNvbnRhaW5lciBtZHVpLXR5cG8iPjxoMSBzdHlsZT0idGV4dC1hbGlnbjpjZW50ZXIiPlNpdGVtYXA8L2gxPjxkaXYgY2xhc3M9Im1kdWktZGl2aWRlciIvPjx4c2w6aWYgdGVzdD0iY291bnQoc2l0ZW1hcDpzaXRlbWFwaW5kZXgvc2l0ZW1hcDpzaXRlbWFwKSAmbHQ7IDEiPjxhIGhyZWY9InNpdGVtYXAueG1sIiBjbGFzcz0ibWR1aS1idG4gYS1uby11bCI+PGkgY2xhc3M9Im1kdWktaWNvbiBtYXRlcmlhbC1pY29ucyI+7oybPC9pPmJhY2sgdG8gaW5kZXg8L2E+PC94c2w6aWY+PHhzbDppZiB0ZXN0PSJjb3VudChzaXRlbWFwOnNpdGVtYXBpbmRleC9zaXRlbWFwOnNpdGVtYXApICZsdDsgMSI+PHRhYmxlIGNsYXNzPSJtZHVpLXRhYmxlIj48dGhlYWQ+PHRyPjx0aCBzdHlsZT0id2lkdGg6NzAlIj5VUkw8L3RoPjx0aCBzdHlsZT0id2lkdGg6MjAlIj5MYXN0IG1vZGlmaWNhdGlvbiB0aW1lPC90aD48dGggc3R5bGU9IndpZHRoOjUlIj5DaGFuZ2UgZnJlcXVlbmNlPC90aD48dGggc3R5bGU9IndpZHRoOjUlIj5Qcmlvcml0eTwvdGg+PC90cj48L3RoZWFkPjx0Ym9keT48eHNsOmZvci1lYWNoIHNlbGVjdD0ic2l0ZW1hcDp1cmxzZXQvc2l0ZW1hcDp1cmwiPjx0cj48dGQ+PHhzbDp2YXJpYWJsZSBuYW1lPSJsb2NVcmwiPjx4c2w6dmFsdWUtb2Ygc2VsZWN0PSJzaXRlbWFwOmxvYyIvPjwveHNsOnZhcmlhYmxlPjxhIGhyZWY9InskbG9jVXJsfSI+PHhzbDp2YWx1ZS1vZiBzZWxlY3Q9InNpdGVtYXA6bG9jIi8+PC9hPjwvdGQ+PHRkPjx4c2w6dmFsdWUtb2Ygc2VsZWN0PSJzaXRlbWFwOmxhc3Rtb2QiLz48L3RkPjx0ZD48eHNsOnZhbHVlLW9mIHNlbGVjdD0ic2l0ZW1hcDpjaGFuZ2VmcmVxIi8+PC90ZD48dGQ+PHhzbDp2YWx1ZS1vZiBzZWxlY3Q9InNpdGVtYXA6cHJpb3JpdHkiLz48L3RkPjwvdHI+PC94c2w6Zm9yLWVhY2g+PC90Ym9keT48L3RhYmxlPjwveHNsOmlmPjx4c2w6aWYgdGVzdD0iY291bnQoc2l0ZW1hcDpzaXRlbWFwaW5kZXgvc2l0ZW1hcDpzaXRlbWFwKSAmZ3Q7IDAiPjx0YWJsZSBjbGFzcz0ibWR1aS10YWJsZSI+PHRoZWFkPjx0cj48dGggc3R5bGU9IndpZHRoOjgwJSI+VVJMPC90aD48dGggc3R5bGU9IndpZHRoOjIwJSI+TGFzdCBtb2RpZmljYXRpb24gdGltZTwvdGg+PC90cj48L3RoZWFkPjx0Ym9keT48eHNsOmZvci1lYWNoIHNlbGVjdD0ic2l0ZW1hcDpzaXRlbWFwaW5kZXgvc2l0ZW1hcDpzaXRlbWFwIj48dHI+PHRkPjx4c2w6dmFyaWFibGUgbmFtZT0ibG9jVXJsIj48eHNsOnZhbHVlLW9mIHNlbGVjdD0ic2l0ZW1hcDpsb2MiLz48L3hzbDp2YXJpYWJsZT48YSBocmVmPSJ7JGxvY1VybH0iPjx4c2w6dmFsdWUtb2Ygc2VsZWN0PSJzaXRlbWFwOmxvYyIvPjwvYT48L3RkPjx0ZD48eHNsOnZhbHVlLW9mIHNlbGVjdD0ic2l0ZW1hcDpsYXN0bW9kIi8+PC90ZD48L3RyPjwveHNsOmZvci1lYWNoPjwvdGJvZHk+PC90YWJsZT48L3hzbDppZj48L2Rpdj48IS0tIE1EVUkgSmF2YVNjcmlwdCAtLT48c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9tZHVpQDEuMC4xL2Rpc3QvanMvbWR1aS5taW4uanMiIGludGVncml0eT0ic2hhMzg0LWdDTVpjc2hZS09HUlg5cjZ3YkRydkYrVGNDQ3N3U0hGdWNVelVQd2thK0dyK3VIZ2psWXZrQUJyOTVUQ096M0EiIGNyb3Nzb3JpZ2luPSJhbm9ueW1vdXMiLz48L2JvZHk+PC9odG1sPjwveHNsOnRlbXBsYXRlPjwveHNsOnN0eWxlc2hlZXQ+DQo=', 'base64').toString();
const xmlDeclaration = '<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="sitemap.xsl"?>';
const freqMap = ['', 'never', 'yearly', 'monthly', 'weekly', 'daily', 'hourly', 'always'];
function dateConverter(date) {
return new Date(date).toISOString();
}
class SitemapManager {
constructor(options) {
_SitemapManager_urlDatas.set(this, new Map());
this.isFinished = false;
this.options = options;
}
addUrl(name, url) {
if (this.isFinished) {
throw new Error('[SitemapManager] Error: Lifecycle finished');
}
__classPrivateFieldGet(this, _SitemapManager_urlDatas, "f").set(name, [...(__classPrivateFieldGet(this, _SitemapManager_urlDatas, "f").get(name) || []), ...url]);
}
finish() {
return new Promise((resolve, reject) => {
var _a, _b;
if (this.isFinished) {
reject(new Error('[SitemapManager] Error: Lifecycle finished'));
}
// Create index sitemap
let xmlContents = [];
__classPrivateFieldGet(this, _SitemapManager_urlDatas, "f").forEach((v, k) => {
xmlContents.push({
sitemap: [
{ loc: new url_1.URL(path_1.default.join(this.options.pathPrefix || '', `sitemap-${k}.xml`), this.options.siteURL).toString() },
{ lastmod: dateConverter(new Date()) }
]
});
});
try {
fs_1.default.writeFileSync(path_1.default.resolve(((_a = this.options) === null || _a === void 0 ? void 0 : _a.outDir) || './public', 'sitemap.xml'), xmlDeclaration + xml_1.default({ sitemapindex: [{ _attr: { xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9' } }, ...xmlContents] }));
}
catch (e) {
reject(new Error(`[SitemapManager] Failed to write file sitemap.xml: ${e.message}`));
}
// Create each sitemap
__classPrivateFieldGet(this, _SitemapManager_urlDatas, "f").forEach((value, key) => {
var _a;
xmlContents = [];
value.forEach((node) => {
const ele = [{ loc: node.loc }];
if (node.lastmod)
ele.push({ lastmod: dateConverter(node.lastmod) });
if (node.changefreq &&
((typeof (node.changefreq) === 'number' && node.changefreq >= 1 && node.changefreq <= 7) ||
(typeof (node.changefreq) === 'string' && freqMap.includes(node.changefreq)))) {
ele.push({ changefreq: typeof (node.changefreq) === 'string' ? node.changefreq : freqMap[node.changefreq] });
}
else if (node.changefreq) {
reject(new Error(`[SitemapManager] Invalid changefreq value: Expects a number ranges from 1 to 7(1 for the least, 7 for the most) or a string. See more: https://www.sitemaps.org/protocol.html#xmlTagDefinitions. Received ${node.changefreq}`));
}
if (node.priority && node.priority >= 0 && node.priority <= 1) {
ele.push({ priority: node.priority });
}
else if (node.priority) {
reject(new Error(`[SitemapManager] Invalid priority value: Expects a number ranges from 0.0 to 1.0. Received ${node.priority}`));
}
xmlContents.push({
url: ele
});
});
try {
fs_1.default.writeFileSync(path_1.default.resolve(((_a = this.options) === null || _a === void 0 ? void 0 : _a.outDir) || './public', `sitemap-${key}.xml`), xmlDeclaration + xml_1.default({ urlset: [{ _attr: { xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9' } }, ...xmlContents] }));
}
catch (e) {
reject(new Error(`[SitemapManager] Failed to write file sitemap-${key}.xml: ${e.message}`));
}
});
// Create sitemap stylesheet
try {
fs_1.default.writeFileSync(path_1.default.resolve(((_b = this.options) === null || _b === void 0 ? void 0 : _b.outDir) || './public', 'sitemap.xsl'), xmlStylesheet);
}
catch (e) {
reject(new Error(`[SitemapManager]: Failed to write file sitemap.xsl: ${e.message}`));
}
resolve();
});
}
}
exports.SitemapManager = SitemapManager;
_SitemapManager_urlDatas = new WeakMap();
exports.types = exports.SitemapManager = void 0;
const main_1 = require("./main");
Object.defineProperty(exports, "SitemapManager", { enumerable: true, get: function () { return main_1.SitemapManager; } });
const types = __importStar(require("./types"));
exports.types = types;
{
"name": "sitemap-manager",
"version": "2.1.0",
"version": "2.2.0",
"description": "An easy way to create sitemaps!",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"build": "rm -rf dist && tsc",
"prepare": "npm run build",

@@ -27,8 +27,5 @@ "pretest": "npm run build",

"homepage": "https://github.com/CBW2007/sitemap-manager#readme",
"dependencies": {
"xml": "^1.0.1"
},
"devDependencies": {
"@tsconfig/node12": "^1.0.9",
"@types/xml": "^1.0.5",
"@types/node": "^16.9.1",
"@typescript-eslint/eslint-plugin": "^4.28.5",

@@ -35,0 +32,0 @@ "@typescript-eslint/parser": "^4.28.5",

@@ -19,3 +19,3 @@ # sitemap-manager

// For yarn users
yarn add sitemap manager
yarn add sitemap-manager
```

@@ -22,0 +22,0 @@

const { SitemapManager } = require('../dist/index')
const fs = require('fs')
if (fs.existsSync('./public')) { fs.rmdirSync('./public', { recursive: true }) }
if (fs.existsSync('./public')) { fs.rmSync('./public', { recursive: true }) }
fs.mkdirSync('./public')

@@ -9,3 +9,10 @@

siteURL: 'https://example.com/',
pathPrefix: 'aaa'
pathPrefix: 'aaa',
hooks: {
// warningHandler: (msg) => { console.log('#' + msg) },
/* fileHandler: (file, data) => {
console.log(`===${file}===`)
console.log(data)
} */
}
})

@@ -21,5 +28,6 @@

{ loc: 'https://example.com/aaa/b/a', changefreq: 4 },
{ loc: 'https://example.com/aaa/b/c', changefreq: 7 },
{ loc: 'https://example.com/aaa/b/c', changefreq: 'daily' }
// { loc: 'https://example.com/aaa/b/c', changefreq: 'what' } // wrong case
{ loc: 'https://example.com/aaa/b/b', changefreq: 7 }/*,
{ loc: 'https://example.com/aaa/b/c', changefreq: 'daily' },
{ loc: 'https://example.com/aaa/b/d', changefreq: 114514 }, // wrong case,
{ loc: 'https://example.com/aaa/b/e', changefreq: 'what' } // wrong case */
])

@@ -29,21 +37,21 @@

{ loc: 'https://example.com/aaa/c/a', priority: 0.3 },
{ loc: 'https://example.com/aaa/c/c', priority: 0.5 }
// { loc: 'https://example.com/aaa/c/c', priority: 2 }, // wrong case
// { loc: 'https://example.com/aaa/c/c', priority: -1 } // wrong case
{ loc: 'https://example.com/aaa/c/b', priority: 0.5 }/*,
{ loc: 'https://example.com/aaa/c/c', priority: 2 }, // wrong case
{ loc: 'https://example.com/aaa/c/d', priority: -1 } // wrong case */
])
MySitemap.addUrl('mix', [{
MySitemap.addUrl('mix', {
loc: 'https://example.com/aaa/d/a'
}])
MySitemap.addUrl('mix', [{
})
MySitemap.addUrl('mix', {
loc: 'https://example.com/aaa/d/b',
changefreq: 3,
lastmod: new Date()
}])
MySitemap.addUrl('mix', [{
})
MySitemap.addUrl('mix', {
loc: 'https://example.com/aaa/d/c',
priority: 0.1,
lastmod: new Date('1949-10-01T08:00:00')
}])
MySitemap.addUrl('mix', [{
})
MySitemap.addUrl('mix', {
loc: 'https://example.com/aaa/d/d',

@@ -53,4 +61,10 @@ changefreq: 'always',

priority: 0.9
}])
})
/* MySitemap.addUrl('mix', { // repeat case
loc: 'https://example.com/aaa/d/d',
changefreq: 'always',
lastmod: '2007-03-13T08:00:00',
priority: 0.9
}) */
MySitemap.finish()

@@ -1,105 +0,4 @@

import fs from 'fs'
import xml from 'xml'
import { URL } from 'url'
import path from 'path'
import { SitemapManager } from './main'
import * as types from './types'
const xmlStylesheet = Buffer.from('PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjx4c2w6c3R5bGVzaGVldCB4bWxuczp4c2w9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvWFNML1RyYW5zZm9ybSIgeG1sbnM6c2l0ZW1hcD0iaHR0cDovL3d3dy5zaXRlbWFwcy5vcmcvc2NoZW1hcy9zaXRlbWFwLzAuOSIgeG1sbnM6Zm49Imh0dHA6Ly93d3cudzMub3JnLzIwMDUvMDIveHBhdGgtZnVuY3Rpb25zIiB2ZXJzaW9uPSIxLjAiPjx4c2w6dGVtcGxhdGUgbWF0Y2g9Ii8iPjxodG1sPjxoZWFkPjx0aXRsZT5TaXRlbWFwPC90aXRsZT48bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEsIG1heGltdW0tc2NhbGU9MSwgc2hyaW5rLXRvLWZpdD1ubyIvPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJCSAJCS5hLW5vLXVsOjpiZWZvcmUgew0KCQkgCQkJZGlzcGxheTogbm9uZTsNCgkJIAkJfQ0KCQkJPC9zdHlsZT48IS0tIE1EVUkgQ1NTIC0tPjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9tZHVpQDEuMC4xL2Rpc3QvY3NzL21kdWkubWluLmNzcyIgaW50ZWdyaXR5PSJzaGEzODQtY0xSck1xMzlIT1pkdkUwajZ5Qm9qTzQrMVBySGZCN2E5bDVxTGNtUm0vZmlXWFlZK0NuZEpQbXl1NUZWLzlUdyIgY3Jvc3NvcmlnaW49ImFub255bW91cyIvPjwvaGVhZD48Ym9keT48ZGl2IGNsYXNzPSJtZHVpLWNvbnRhaW5lciBtZHVpLXR5cG8iPjxoMSBzdHlsZT0idGV4dC1hbGlnbjpjZW50ZXIiPlNpdGVtYXA8L2gxPjxkaXYgY2xhc3M9Im1kdWktZGl2aWRlciIvPjx4c2w6aWYgdGVzdD0iY291bnQoc2l0ZW1hcDpzaXRlbWFwaW5kZXgvc2l0ZW1hcDpzaXRlbWFwKSAmbHQ7IDEiPjxhIGhyZWY9InNpdGVtYXAueG1sIiBjbGFzcz0ibWR1aS1idG4gYS1uby11bCI+PGkgY2xhc3M9Im1kdWktaWNvbiBtYXRlcmlhbC1pY29ucyI+7oybPC9pPmJhY2sgdG8gaW5kZXg8L2E+PC94c2w6aWY+PHhzbDppZiB0ZXN0PSJjb3VudChzaXRlbWFwOnNpdGVtYXBpbmRleC9zaXRlbWFwOnNpdGVtYXApICZsdDsgMSI+PHRhYmxlIGNsYXNzPSJtZHVpLXRhYmxlIj48dGhlYWQ+PHRyPjx0aCBzdHlsZT0id2lkdGg6NzAlIj5VUkw8L3RoPjx0aCBzdHlsZT0id2lkdGg6MjAlIj5MYXN0IG1vZGlmaWNhdGlvbiB0aW1lPC90aD48dGggc3R5bGU9IndpZHRoOjUlIj5DaGFuZ2UgZnJlcXVlbmNlPC90aD48dGggc3R5bGU9IndpZHRoOjUlIj5Qcmlvcml0eTwvdGg+PC90cj48L3RoZWFkPjx0Ym9keT48eHNsOmZvci1lYWNoIHNlbGVjdD0ic2l0ZW1hcDp1cmxzZXQvc2l0ZW1hcDp1cmwiPjx0cj48dGQ+PHhzbDp2YXJpYWJsZSBuYW1lPSJsb2NVcmwiPjx4c2w6dmFsdWUtb2Ygc2VsZWN0PSJzaXRlbWFwOmxvYyIvPjwveHNsOnZhcmlhYmxlPjxhIGhyZWY9InskbG9jVXJsfSI+PHhzbDp2YWx1ZS1vZiBzZWxlY3Q9InNpdGVtYXA6bG9jIi8+PC9hPjwvdGQ+PHRkPjx4c2w6dmFsdWUtb2Ygc2VsZWN0PSJzaXRlbWFwOmxhc3Rtb2QiLz48L3RkPjx0ZD48eHNsOnZhbHVlLW9mIHNlbGVjdD0ic2l0ZW1hcDpjaGFuZ2VmcmVxIi8+PC90ZD48dGQ+PHhzbDp2YWx1ZS1vZiBzZWxlY3Q9InNpdGVtYXA6cHJpb3JpdHkiLz48L3RkPjwvdHI+PC94c2w6Zm9yLWVhY2g+PC90Ym9keT48L3RhYmxlPjwveHNsOmlmPjx4c2w6aWYgdGVzdD0iY291bnQoc2l0ZW1hcDpzaXRlbWFwaW5kZXgvc2l0ZW1hcDpzaXRlbWFwKSAmZ3Q7IDAiPjx0YWJsZSBjbGFzcz0ibWR1aS10YWJsZSI+PHRoZWFkPjx0cj48dGggc3R5bGU9IndpZHRoOjgwJSI+VVJMPC90aD48dGggc3R5bGU9IndpZHRoOjIwJSI+TGFzdCBtb2RpZmljYXRpb24gdGltZTwvdGg+PC90cj48L3RoZWFkPjx0Ym9keT48eHNsOmZvci1lYWNoIHNlbGVjdD0ic2l0ZW1hcDpzaXRlbWFwaW5kZXgvc2l0ZW1hcDpzaXRlbWFwIj48dHI+PHRkPjx4c2w6dmFyaWFibGUgbmFtZT0ibG9jVXJsIj48eHNsOnZhbHVlLW9mIHNlbGVjdD0ic2l0ZW1hcDpsb2MiLz48L3hzbDp2YXJpYWJsZT48YSBocmVmPSJ7JGxvY1VybH0iPjx4c2w6dmFsdWUtb2Ygc2VsZWN0PSJzaXRlbWFwOmxvYyIvPjwvYT48L3RkPjx0ZD48eHNsOnZhbHVlLW9mIHNlbGVjdD0ic2l0ZW1hcDpsYXN0bW9kIi8+PC90ZD48L3RyPjwveHNsOmZvci1lYWNoPjwvdGJvZHk+PC90YWJsZT48L3hzbDppZj48L2Rpdj48IS0tIE1EVUkgSmF2YVNjcmlwdCAtLT48c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9tZHVpQDEuMC4xL2Rpc3QvanMvbWR1aS5taW4uanMiIGludGVncml0eT0ic2hhMzg0LWdDTVpjc2hZS09HUlg5cjZ3YkRydkYrVGNDQ3N3U0hGdWNVelVQd2thK0dyK3VIZ2psWXZrQUJyOTVUQ096M0EiIGNyb3Nzb3JpZ2luPSJhbm9ueW1vdXMiLz48L2JvZHk+PC9odG1sPjwveHNsOnRlbXBsYXRlPjwveHNsOnN0eWxlc2hlZXQ+DQo=', 'base64').toString()
const xmlDeclaration = '<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="sitemap.xsl"?>'
// src: src/sitemap.xsl
interface Option {
outDir?: string,
siteURL: string,
pathPrefix?: string
}
interface Url {
loc: string,
lastmod?: string | Date,
changefreq?: 'never' | 'yearly' | 'monthly' | 'weekly' | 'daily' | 'hourly' | 'always' | 1 | 2 | 3 | 4 | 5 | 6 | 7,
priority?: number
}
const freqMap = ['', 'never', 'yearly', 'monthly', 'weekly', 'daily', 'hourly', 'always']
function dateConverter (date: Date | string): string {
return new Date(date).toISOString()
}
class SitemapManager {
options: Option
#urlDatas: Map<string, Array<Url>> = new Map()
isFinished: Boolean = false
constructor (options: Option) {
this.options = options
}
addUrl (name: string, url: Array<Url>): void {
if (this.isFinished) { throw new Error('[SitemapManager] Error: Lifecycle finished') }
this.#urlDatas.set(name, [...(this.#urlDatas.get(name) || []), ...url])
}
finish (): Promise<void> {
return new Promise((resolve, reject) => {
if (this.isFinished) { reject(new Error('[SitemapManager] Error: Lifecycle finished')) }
// Create index sitemap
let xmlContents:Array<any> = []
this.#urlDatas.forEach((v, k) => {
xmlContents.push({
sitemap: [
{ loc: new URL(path.join(this.options.pathPrefix || '', `sitemap-${k}.xml`), this.options.siteURL).toString() },
{ lastmod: dateConverter(new Date()) }
]
})
})
try {
fs.writeFileSync(path.resolve(this.options?.outDir || './public', 'sitemap.xml'),
xmlDeclaration + xml({ sitemapindex: [{ _attr: { xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9' } }, ...xmlContents] }))
} catch (e) {
reject(new Error(`[SitemapManager] Failed to write file sitemap.xml: ${e.message}`))
}
// Create each sitemap
this.#urlDatas.forEach((value, key) => {
xmlContents = []
value.forEach((node) => {
const ele:Array<any> = [{ loc: node.loc }]
if (node.lastmod) ele.push({ lastmod: dateConverter(node.lastmod) })
if (node.changefreq &&
((typeof (node.changefreq) === 'number' && node.changefreq >= 1 && node.changefreq <= 7) ||
(typeof (node.changefreq) === 'string' && freqMap.includes(node.changefreq)))) {
ele.push({ changefreq: typeof (node.changefreq) === 'string' ? node.changefreq : freqMap[node.changefreq] })
} else if (node.changefreq) {
reject(new Error(`[SitemapManager] Invalid changefreq value: Expects a number ranges from 1 to 7(1 for the least, 7 for the most) or a string. See more: https://www.sitemaps.org/protocol.html#xmlTagDefinitions. Received ${node.changefreq}`))
}
if (node.priority && node.priority >= 0 && node.priority <= 1) {
ele.push({ priority: node.priority })
} else if (node.priority) {
reject(new Error(`[SitemapManager] Invalid priority value: Expects a number ranges from 0.0 to 1.0. Received ${node.priority}`))
}
xmlContents.push({
url: ele
})
})
try {
fs.writeFileSync(path.resolve(this.options?.outDir || './public', `sitemap-${key}.xml`),
xmlDeclaration + xml({ urlset: [{ _attr: { xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9' } }, ...xmlContents] }))
} catch (e) {
reject(new Error(`[SitemapManager] Failed to write file sitemap-${key}.xml: ${e.message}`))
}
})
// Create sitemap stylesheet
try {
fs.writeFileSync(path.resolve(this.options?.outDir || './public', 'sitemap.xsl'), xmlStylesheet)
} catch (e) {
reject(new Error(`[SitemapManager]: Failed to write file sitemap.xsl: ${e.message}`))
}
resolve()
})
}
}
export { SitemapManager }
export { SitemapManager, types }
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc