UNPKG

meblog

Version:

A simple blog engine for personal blogging

164 lines (163 loc) 6.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const fs_1 = tslib_1.__importDefault(require("fs")); const path_1 = tslib_1.__importDefault(require("path")); const glob_1 = tslib_1.__importDefault(require("glob")); const gulplog_1 = tslib_1.__importDefault(require("gulplog")); const ansi_colors_1 = tslib_1.__importDefault(require("ansi-colors")); const DataSource_1 = tslib_1.__importDefault(require("./DataSource")); const Post_1 = require("../post/Post"); const MarkdownPostParser_1 = tslib_1.__importDefault(require("../post/MarkdownPostParser")); const FileUtils_1 = tslib_1.__importDefault(require("../util/FileUtils")); class FilesSource extends DataSource_1.default { postsDirectoryPath; dataDirectoryPath; separator; postParser; postLayouts; posts = []; tags = []; constructor(config, postsDirectoryPath, separator = '---') { super(config); postsDirectoryPath = postsDirectoryPath.trim(); if (postsDirectoryPath.endsWith('/')) { postsDirectoryPath.slice(0, -1); } this.postsDirectoryPath = postsDirectoryPath; if (!fs_1.default.existsSync(this.postsDirectoryPath)) { return; } this.dataDirectoryPath = path_1.default.resolve(this.postsDirectoryPath, '../cache'); this.separator = separator; this.postParser = new MarkdownPostParser_1.default(); this.postLayouts = this.getLayouts(); } get postsJsonPath() { return path_1.default.join(this.dataDirectoryPath, 'posts.json'); } get tagsJsonPath() { return path_1.default.join(this.dataDirectoryPath, 'tags.json'); } getLayouts() { return glob_1.default .sync(path_1.default.join(this.config.rootDir, './templates/posts/*.pug')) .map((file) => FileUtils_1.default.basenameWithoutExt(file)); } filterInvalidPostLayout(post) { if (!this.postLayouts.includes(post.layout)) { gulplog_1.default.info(`Post ${ansi_colors_1.default.green(post.title)}\ has ${ansi_colors_1.default.red(`invalid layout "${post.layout}" will be ignored`)}`); return false; } return true; } getSourcePostPaths() { return glob_1.default.sync(`${this.postsDirectoryPath}/**/*.md`); } hasAnyChanges() { if (!fs_1.default.existsSync(this.postsJsonPath)) { gulplog_1.default.debug('Cache data is not found'); return true; } const postsJsonLastModifiedAt = fs_1.default.statSync(this.postsJsonPath).mtimeMs; const files = this.getSourcePostPaths(); for (const filePath of files) { const lastModifiedAt = fs_1.default.statSync(filePath).mtimeMs; if (lastModifiedAt > postsJsonLastModifiedAt) { gulplog_1.default.info('New post change at file:', filePath); return true; } } return false; } parse() { const files = this.getSourcePostPaths(); const posts = this.parsePostsFromPaths(files); const tags = posts.flatMap((p) => p.tags).filter((t) => t); posts.sort((p1, p2) => p2.publishedAt.getTime() - p1.publishedAt.getTime()); return { posts: posts, tags: Array.from(new Set(tags)), }; } parsePosts(force = false) { let shouldParse = false; if (force || this.hasAnyChanges()) { shouldParse = true; } if (!shouldParse) { return; } const result = this.parse(); this.cacheData(result); } cacheData({ posts, tags }) { const jsonPrettySpace = this.config.devMode ? 2 : 0; if (!fs_1.default.existsSync(this.dataDirectoryPath)) { fs_1.default.mkdirSync(this.dataDirectoryPath); } fs_1.default.writeFileSync(this.postsJsonPath, JSON.stringify(posts, null, jsonPrettySpace)); fs_1.default.writeFileSync(this.tagsJsonPath, JSON.stringify(tags, null, jsonPrettySpace)); } filterUnpublishedPosts(filePath) { return !FileUtils_1.default.basename(filePath).startsWith('__'); } parsePostsFromPaths(filePaths) { return filePaths .filter((file) => this.filterUnpublishedPosts(file)) .filter((file) => fs_1.default.existsSync(file)) .map((file) => this.postParser.parse(file, this.separator)) .filter((p) => p.title && p.publishedAt && p.slug) .filter((p) => this.filterInvalidPostLayout(p)) .map((p) => { p.url = this.postRootUrl(p); p.relativeUrl = this.postUrl(p); return p; }); } loadData(force = false) { if (!fs_1.default.existsSync(this.postsDirectoryPath)) { return; } this.parsePosts(force); delete require.cache[this.postsJsonPath]; delete require.cache[this.tagsJsonPath]; const jsonPosts = require(this.postsJsonPath); this.posts = jsonPosts.map((p) => new Post_1.Post(p)); this.setupPostMap(this.posts); this.tags = require(this.tagsJsonPath); } setupPostMap(posts) { posts.reduce((_, post) => { _[post.slug] = post; return _; }, posts); } filterPost(post, locale) { const { language } = post; locale = locale || this.config.defaultLocale; return language ? language === locale : locale === this.config.defaultLocale; } getPosts(locale) { const posts = this.posts.filter(p => this.filterPost(p, locale)); this.setupPostMap(posts); return posts; } getAllPosts() { return this.posts; } getPostsByTag(tag, locale) { const posts = this.posts .filter((p) => p.tags.includes(tag)) .filter(p => this.filterPost(p, locale)); this.setupPostMap(posts); return posts; } getTags() { return this.tags; } } exports.default = FilesSource;