diff --git a/packages/easy-sitemap/.eslintrc.js b/packages/easy-sitemap/.eslintrc.js new file mode 100644 index 0000000..7a0472e --- /dev/null +++ b/packages/easy-sitemap/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + "parserOptions": { + "project": __dirname + "/tsconfig.json" + } +} \ No newline at end of file diff --git a/packages/easy-sitemap/.npmignore b/packages/easy-sitemap/.npmignore new file mode 100644 index 0000000..b873d06 --- /dev/null +++ b/packages/easy-sitemap/.npmignore @@ -0,0 +1,13 @@ +node_modules +src +test +.babelrc +.eslintrc.js +.gitignore +.npmignore +tsconfig.* +webpack.config.js +yarn-error.log +coverage +__tests__ +jest.config.js diff --git a/packages/easy-sitemap/CHANGELOG.md b/packages/easy-sitemap/CHANGELOG.md new file mode 100644 index 0000000..be60ed3 --- /dev/null +++ b/packages/easy-sitemap/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased]() + +## [1.0.0] - 2021-01-20 + +### Added +- The sitemap is ready ! + + +[1.0.4]: https://github.com/dzeiocom/libs/releases/tag/%40dzeio%2Fobject-util%401.0.4 +[1.0.2]: https://github.com/dzeiocom/libs/releases/tag/%40dzeio%2Fobject-util%401.0.2 +[1.0.1]: https://github.com/dzeiocom/libs/releases/tag/%40dzeio%2Fobject-util%401.0.1 +[1.0.0]: https://github.com/dzeiocom/libs/releases/tag/%40easy-sitemap%401.0.0 diff --git a/packages/easy-sitemap/README.md b/packages/easy-sitemap/README.md new file mode 100644 index 0000000..3476f5f --- /dev/null +++ b/packages/easy-sitemap/README.md @@ -0,0 +1,48 @@ +# URL Manager + +A very easy to use sitemap generator + +## Usage + +- Import easy-sitemap + +```typescript +import Sitemap from 'easy-sitemap' +// or +const Sitemap = require('easy-sitemap').default +``` + +- Initialize it + +```typescript +// Create a new instance +const sitemap = new Sitemap('https://www.example.com') // initialize using your website base + +// if you want to let the library manage the response object the line is this +const sitemap = new Sitemap('https://www.example.com', { + response: res +}) + +``` + +- add you're paths + +```typescript +sitemap.addEntry('/path') + +// you can also add optionnal elements +sitemap.addEntry('/path', { + // each one are optionnal and they don't all need to be added + changefreq: 'always', // webpage change freq + lastmod: new Date('2021-01-20'), // webpage lastmod Date + priority: 1 // crawler priority +}) +``` + +- finally build it ! + +```typescript +// it will return a string containing the whole sitemap +// if you are letting the library manage the response Object it will return an empty string but the page will render ! +const result = sitemap.build() +``` diff --git a/packages/easy-sitemap/__tests__/__snapshots__/index.test.ts.snap b/packages/easy-sitemap/__tests__/__snapshots__/index.test.ts.snap new file mode 100644 index 0000000..dbb1d4d --- /dev/null +++ b/packages/easy-sitemap/__tests__/__snapshots__/index.test.ts.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Basic Sitemap Tests should not add changefreq if value is incorrect 1`] = `"https://www.example.com/path"`; + +exports[`Basic Sitemap Tests should not add priority when it is incorrect 1`] = `"https://www.example.com/path"`; + +exports[`Basic Sitemap Tests should return a basic sitemap 1`] = `"https://www.example.com/pathhttps://www.example.com/"`; + +exports[`Basic Sitemap Tests should return a sitemap 1`] = `"https://www.example.com/pathalways2021-01-20T00:00:00.000Z1https://www.example.com/"`; + +exports[`Basic Sitemap Tests should return an empty sitemap 1`] = `""`; diff --git a/packages/easy-sitemap/__tests__/index.test.ts b/packages/easy-sitemap/__tests__/index.test.ts new file mode 100644 index 0000000..cc62d56 --- /dev/null +++ b/packages/easy-sitemap/__tests__/index.test.ts @@ -0,0 +1,43 @@ +/// + +import Sitemap from '../src/Sitemap' + +describe('Basic Sitemap Tests', () => { + it('should return an empty sitemap', () => { + const sitemap = new Sitemap('https://www.example.com') + expect(sitemap.build()).toMatchSnapshot() + }) + it('should return a basic sitemap', () => { + const sitemap = new Sitemap('https://www.example.com') + sitemap.addEntry('/path') + sitemap.addEntry('/') + expect(sitemap.build()).toMatchSnapshot() + }) + it('should return a sitemap', () => { + const sitemap = new Sitemap('https://www.example.com') + sitemap.addEntry('/path', { + changefreq: 'always', + lastmod: new Date('2021-01-20'), + priority: 1 + }) + sitemap.addEntry('/') + expect(sitemap.build()).toMatchSnapshot() + }) + it('should not add priority when it is incorrect', () => { + const sitemap = new Sitemap('https://www.example.com') + sitemap.addEntry('/path', { + // @ts-expect-error + priority: 255 + }) + expect(sitemap.build()).toMatchSnapshot() + }) + it('should not add changefreq if value is incorrect', () => { + const sitemap = new Sitemap('https://www.example.com') + sitemap.addEntry('/path', { + // @ts-expect-error + changefreq: 'pouet' + }) + expect(sitemap.build()).toMatchSnapshot() + }) + +}) diff --git a/packages/easy-sitemap/jest.config.js b/packages/easy-sitemap/jest.config.js new file mode 100644 index 0000000..b5ab11f --- /dev/null +++ b/packages/easy-sitemap/jest.config.js @@ -0,0 +1 @@ +module.exports = require('../../jest.base.json') diff --git a/packages/easy-sitemap/package.json b/packages/easy-sitemap/package.json new file mode 100644 index 0000000..1e3bf78 --- /dev/null +++ b/packages/easy-sitemap/package.json @@ -0,0 +1,30 @@ +{ + "name": "easy-sitemap", + "version": "1.0.0", + "description": "A very easy sitemap maker library", + "repository": { + "type": "git", + "url": "https://github.com/dzeiocom/libs.git", + "directory": "packages/easy-sitemap" + }, + "author": "Aviortheking", + "license": "MIT", + "main": "./dist/Sitemap.js", + "types": "./dist/Sitemap.d.ts", + "devDependencies": { + "@types/chai": "^4.2.12", + "@types/jest": "^26.0.10", + "jest": "^26.4.2", + "ts-node": "^9.0.0", + "typescript": "^4.0.2" + }, + "scripts": { + "prepublishOnly": "yarn build", + "build": "tsc", + "test": "jest --coverage" + }, + "keywords": [ + "sitemap", + "sitemap.xml" + ] +} diff --git a/packages/easy-sitemap/src/Sitemap.ts b/packages/easy-sitemap/src/Sitemap.ts new file mode 100644 index 0000000..5cfc9fc --- /dev/null +++ b/packages/easy-sitemap/src/Sitemap.ts @@ -0,0 +1,70 @@ +import { ServerResponse } from 'http' + +export default class Sitemap { + + private static allowedChangefreq = ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'] + + private datas = '' + + public constructor( + private domain: string, private options?: { + response?: ServerResponse + } + ) { + if (this.options?.response) { + this.options.response.setHeader('Content-Type', 'text/xml') + this.options.response.write(this.datas) + } + } + + public addEntry(path: string, options?: { + changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never' + lastmod?: Date + priority?: 1 | 0.9 | 0.8 | 0.7 | 0.6 | 0.5 | 0.4 | 0.3 | 0.2 | 0.1 | 0 + }) { + let entryString = '' + + const url = `${this.domain}${path}` + .replace(/&/g, '&') + .replace(/'/g, ''') + .replace(/"/g, '"') + .replace(/>/g, '>') + .replace(/${url}` + if (options) { + if (options.changefreq) { + if (!Sitemap.allowedChangefreq.includes(options.changefreq)) { + console.warn(`changefreq is not one of the allowed words (${options.changefreq})\nChangeFreq won't be added`) + } else { + entryString += `${options.changefreq}` + } + } + if (options.lastmod) { + entryString += `${options.lastmod.toISOString()}` + } + if (options.priority) { + if (options.priority <= 1 && options.priority >= 0 && options.priority.toString().length <= 3) { + entryString += `${options.priority}` + } else { + console.warn(`Priority is not between 0 and 1 and only containing one decimal (${options.priority})\nPriority won't be added`) + } + } + } + entryString += '' + if (this.options?.response) { + this.options.response.write(entryString) + } else { + this.datas += entryString + } + } + + public build(): string { + if (this.options?.response) { + this.options.response.write('') + this.options.response.end() + return '' + } + return this.datas + '' + } +} diff --git a/packages/easy-sitemap/tsconfig.json b/packages/easy-sitemap/tsconfig.json new file mode 100644 index 0000000..c32b060 --- /dev/null +++ b/packages/easy-sitemap/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist" + }, + "files": [ + "src/Sitemap.ts" + ] +}