Skip to content

Commit

Permalink
feat(postbuild): create schema on postbuild #1
Browse files Browse the repository at this point in the history
  • Loading branch information
bartholomej committed Jun 29, 2021
1 parent 1b18c3a commit f8c793e
Show file tree
Hide file tree
Showing 17 changed files with 269 additions and 209 deletions.
2 changes: 1 addition & 1 deletion demo.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { createSitemap } from './src/index';

createSitemap('https://example.com', { debug: true, resetTime: true });
createSitemap('https://example.com/', { debug: true, resetTime: true });
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
"release:major": "git checkout master && npm version major -m \"chore(update): major release %s 💥 \""
},
"dependencies": {
"minimist": "^1.2.5",
"xml": "^1.0.1"
"minimist": "^1.2.5"
},
"devDependencies": {
"@babel/preset-typescript": "^7.13.0",
Expand All @@ -41,6 +40,7 @@
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"fast-glob": "^3.2.5",
"glob": "^7.1.7",
"husky": "^6.0.0",
"jest": "^27.0.4",
Expand All @@ -50,7 +50,8 @@
"rimraf": "^3.0.2",
"ts-jest": "^27.0.3",
"ts-node": "^10.0.0",
"typescript": "^4.3.2"
"typescript": "^4.3.2",
"xmlbuilder2": "^2.4.1"
},
"repository": {
"url": "git+https://github.com/bartholomej/svelte-sitemap.git",
Expand Down
1 change: 1 addition & 0 deletions src/build/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Nothing here...
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
27 changes: 27 additions & 0 deletions src/build/sitemap.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/</loc>
<lastmod>2021-06-20</lastmod>
</url>
<url>
<loc>https://example.com/page2/</loc>
<lastmod>2021-06-20</lastmod>
</url>
<url>
<loc>https://example.com/page1/</loc>
<lastmod>2021-06-20</lastmod>
</url>
<url>
<loc>https://example.com/page2/subpage2/</loc>
<lastmod>2021-06-20</lastmod>
</url>
<url>
<loc>https://example.com/page1/subpage1/</loc>
<lastmod>2021-06-20</lastmod>
</url>
<url>
<loc>https://example.com/page2/subpage2/subsubpage2/</loc>
<lastmod>2021-06-20</lastmod>
</url>
</urlset>
182 changes: 33 additions & 149 deletions src/helpers/global.helper.ts
Original file line number Diff line number Diff line change
@@ -1,161 +1,45 @@
import fs, { writeFile } from 'fs';
import { Options } from 'interfaces/global.interface';
import path from 'path';
import xml from 'xml';
import fg from 'fast-glob';
import fs from 'fs';
import { create } from 'xmlbuilder2';
import { Options, PagesJson } from '../interfaces/global.interface';

interface Page {
title: string;
slug: string;
lastModified: string;
created: string;
}

interface File {
file: string;
created: number;
modified: number;
}
const PATH_BUILD = './src/build/';

const ROUTES = 'src/routes';

/**
* Main wrapper
* @param {string} domain Your domain
*/
export const buildSitemap = (domain: string, options: Options): void => {
const files = getFiles(options);
assembleXML(files, domain, options);
const getUrl = (url: string, domain: string) => {
const slash = domain.split('/').pop() ? '/' : '';
const trimmed = url.slice(12).replace('index.html', '');
return `${domain}${slash}${trimmed}`;
};

const walkSync = (dir: string, filelist: any[] = []) => {
fs.readdirSync(dir).forEach((file) => {
const filePath = path.join(dir, file);
const created = fs.statSync(filePath).ctime;
const modified = fs.statSync(filePath).mtime;
export async function buildSitemap(domain: string, options?: Options): Promise<PagesJson[]> {
const pages = await fg([`${PATH_BUILD}**/*.html`]);

filelist = fs.statSync(path.join(dir, file)).isDirectory()
? walkSync(path.join(dir, file), filelist)
: filelist.concat({ file: filePath, created, modified });
const results: PagesJson[] = pages.map((page) => {
return {
page: getUrl(page, domain),
changeFreq: options?.changeFreq ?? '',
lastMod: options?.resetTime ? new Date().toISOString().split('T')[0] : ''
};
});
return filelist;
};

/**
* Gathering files from subolders
* @param {string} options some options
*/
export const getFiles = (options: Options): Page[] => {
const pages: Page[] = [];

const paths = walkSync(ROUTES);

if (!paths?.length) {
console.error(
'No routes found in you project... Make sure you have this folder created:',
ROUTES
);
return [];
}

paths.forEach((route: File) => {
const fileRaw = route.file.split('/');
return results;
}

const file = fileRaw.splice(2, 10).join('/');
// Excluding svelte files
const slug = file.replace('/index.svelte', '').replace('.svelte', '');
if (slug !== 'index' && slug.includes('__') === false) {
pages.push({
lastModified: (options.resetTime ? new Date() : new Date(route.modified))
.toISOString()
.slice(0, 10),
title: slug,
created: (options.resetTime ? new Date() : new Date(route.created))
.toISOString()
.slice(0, 10),
slug
});
}
export const writeSitemap = (items: PagesJson[]): void => {
const sitemap = create({ version: '1.0' }).ele('urlset', {
xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9'
});

if (options?.debug) {
console.log('pages', pages);
for (const item of items) {
const page = sitemap.ele('url');
page.ele('loc').txt(item.page);
if (item.changeFreq) {
page.ele('changefreq').txt(item.changeFreq);
}
if (item.lastMod) {
page.ele('lastmod').txt(item.lastMod);
}
}
return pages;
};

/**
* Assemble xml and create file
* @param {string[]} pages List of pages
* @param {string} domain Your domain
* @param {string} options Some useful options
*/
export const assembleXML = (pages: Page[], domain: string, options: Options) => {
const indexItem = {
// build index item
url: [
{
loc: domain
},
{
lastmod: new Date(
Math.max.apply(
null,
pages.map((page) => {
return new Date(page.lastModified ?? page.created) as unknown as number;
})
)
)
.toISOString()
.split('T')[0]
},
{ changefreq: 'daily' },
{ priority: '1.0' }
]
};
const xml = sitemap.end({ prettyPrint: true });

const sitemapItems = pages.reduce(
(
items: { url: [{ loc: string }, { lastmod: string }] }[],
item: {
title: string;
slug: string;
lastModified?: string;
created: string;
}
) => {
// build page items
items.push({
url: [
{
loc: `${domain}/${item.slug}`
},
{
lastmod: new Date(item.lastModified ?? item.created).toISOString().split('T')[0]
}
]
});
return items;
},
[]
);

const sitemapObject = {
urlset: [
{
_attr: {
xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9'
}
},
indexItem,
...sitemapItems
]
};

const sitemap = `<?xml version="1.0" encoding="UTF-8"?>${xml(sitemapObject)}`;

writeFile('./static/sitemap.xml', sitemap, (err) => {
if (!err) {
console.log('\x1b[32m', `File './static/sitemap.xml' has been created.`, '\x1b[0m');
}
});
fs.writeFileSync(`${PATH_BUILD}/sitemap.xml`, xml);
};
18 changes: 14 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { Options } from 'interfaces/global.interface';
import { buildSitemap } from './helpers/global.helper';
import { buildSitemap, writeSitemap } from './helpers/global.helper';
import { Options } from './interfaces/global.interface';
import { DOMAIN } from './vars';

export const createSitemap = (domain: string = DOMAIN, options: Options) => {
buildSitemap(domain, options);
export const createSitemap = async (domain: string = DOMAIN, options?: Options) => {
if (options?.debug) {
console.log('OPTIONS', options);
}

const json = await buildSitemap(domain, options);

if (options?.debug) {
console.log('RESULT', json);
}

writeSitemap(json);
};
9 changes: 9 additions & 0 deletions src/interfaces/global.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,14 @@ export interface Arguments {

export interface Options {
debug?: boolean;
changeFreq?: ChangeFreq;
resetTime?: boolean;
}

export interface PagesJson {
page: string;
changeFreq?: ChangeFreq;
lastMod?: string;
}

type ChangeFreq = 'weekly' | 'daily' | string;
1 change: 0 additions & 1 deletion src/routes/__layout.svelte

This file was deleted.

1 change: 0 additions & 1 deletion src/routes/homepage.svelte

This file was deleted.

4 changes: 4 additions & 0 deletions src/vars.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
import { Options } from './interfaces/global.interface';

export const DOMAIN = 'https://example.com';

export const OPTIONS: Options = { resetTime: false, debug: false, changeFreq: 'weekly' };
Loading

0 comments on commit f8c793e

Please sign in to comment.