diff --git a/.gitignore b/.gitignore index a611977..d150b9f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ tmp/ .idea/ coverage dist -package-lock.json \ No newline at end of file +package-lock.json +.vscode +.idea \ No newline at end of file diff --git a/lib/front_matter.ts b/lib/front_matter.ts index 9da7101..c3d7ead 100644 --- a/lib/front_matter.ts +++ b/lib/front_matter.ts @@ -32,7 +32,48 @@ function split(str: string) { return { content: str }; } -function parse(str: string, options?: yaml.LoadOptions) { +/** + * Hexo Front Matter Parse Result + * * required while used in hexo plugins or themes + * * to identify page metadata properties + */ +export type HexoFMResult = Partial<{ + + /** + * title of page + */ + title: string; + + /** + * description of page + */ + description: string; + + /** + * thumbnail of page + */ + thumbnail: string; + + /** + * page created date + */ + date: any; + + /** + * page modified date + */ + updated: any; + + /** + * page permalink + */ + permalink: string; +}>; +export type ParseResult = Record & { + _content: string; +} & HexoFMResult; + +function parse(str: string, options: yaml.LoadOptions = {}) { if (typeof str !== 'string') throw new TypeError('str is required!'); const splitData = split(str); @@ -40,12 +81,12 @@ function parse(str: string, options?: yaml.LoadOptions) { if (!raw) return { _content: str }; - let data; + let data: ParseResult; if (splitData.separator.startsWith(';')) { data = parseJSON(raw); } else { - data = parseYAML(raw, options); + data = parseYAML(raw, options) as any; } if (!data) return { _content: str }; @@ -55,7 +96,9 @@ function parse(str: string, options?: yaml.LoadOptions) { const item = data[key]; if (item instanceof Date) { - data[key] = new Date(item.getTime() + (item.getTimezoneOffset() * 60 * 1000)); + data[key] = new Date( + item.getTime() + (item.getTimezoneOffset() * 60 * 1000) + ); } }); @@ -63,18 +106,18 @@ function parse(str: string, options?: yaml.LoadOptions) { return data; } -function parseYAML(str, options: yaml.LoadOptions) { +function parseYAML(str: string, options: yaml.LoadOptions) { const result = yaml.load(escapeYAML(str), options); if (typeof result !== 'object') return; return result; } -function parseJSON(str) { +function parseJSON(str: string) { try { return JSON.parse(`{${str}}`); } catch (err) { - return; // eslint-disable-line + return; // eslint-disable-line } } @@ -93,12 +136,12 @@ function escapeYAML(str: string) { } interface Options { - mode?: 'json' | '', - prefixSeparator?: boolean, - separator?: string + mode?: 'json' | ''; + prefixSeparator?: boolean; + separator?: string; } -function stringify(obj, options: Options = {}) { +function stringify(obj: Record, options: Options = {}): string { if (!obj) throw new TypeError('obj is required!'); const { _content: content = '' } = obj; @@ -123,12 +166,14 @@ function stringify(obj, options: Options = {}) { return result; } -function stringifyYAML(obj, options) { +type YamlMergedOpts = Options & yaml.DumpOptions; + +function stringifyYAML(obj: Record, options: YamlMergedOpts) { const keys = Object.keys(obj); const data = {}; - const nullKeys = []; - const dateKeys = []; - let key, value, i, len; + const nullKeys: string[] = []; + const dateKeys: string[] = []; + let key: string, value: any, i: number, len: number; for (i = 0, len = keys.length; i < len; i++) { key = keys[i]; @@ -162,24 +207,25 @@ function stringifyYAML(obj, options) { } function stringifyJSON(obj) { - return JSON.stringify(obj, null, ' ') + return ( + JSON.stringify(obj, null, ' ') // Remove indention - .replace(/\n {2}/g, () => '\n') + .replace(/\n {2}/g, () => '\n') // Remove prefixing and trailing braces - .replace(/^{\n|}$/g, ''); + .replace(/^{\n|}$/g, '') + ); } -function doubleDigit(num) { +function doubleDigit(num: number) { return num.toString().padStart(2, '0'); } -function formatDate(date) { - return `${date.getFullYear()}-${doubleDigit(date.getMonth() + 1)}-${doubleDigit(date.getDate())} ${doubleDigit(date.getHours())}:${doubleDigit(date.getMinutes())}:${doubleDigit(date.getSeconds())}`; +function formatDate(date: Date) { + return `${date.getFullYear()}-${doubleDigit( + date.getMonth() + 1 + )}-${doubleDigit(date.getDate())} ${doubleDigit( + date.getHours() + )}:${doubleDigit(date.getMinutes())}:${doubleDigit(date.getSeconds())}`; } -export { - parse, - split, - escapeYAML as escape, - stringify -}; +export { parse, split, escapeYAML as escape, stringify }; diff --git a/package.json b/package.json index d55bffd..656ed9f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "name": "hexo-front-matter", "version": "4.1.0", "description": "Front-matter parser.", - "main": "dist/front_matter", + "main": "dist/front_matter.js", + "types": "./dist/front_matter.d.ts", "scripts": { "prepublish ": "npm run clean && npm run build", "build": "tsc -b", @@ -13,9 +14,8 @@ "test-cov": "c8 --reporter=lcovonly npm run test" }, "files": [ - "dist/**" + "dist" ], - "types": "./dist/front_matter.d.ts", "repository": "hexojs/hexo-front-matter", "keywords": [ "front-matter", @@ -31,8 +31,9 @@ "js-yaml": "^4.1.0" }, "devDependencies": { + "@types/chai": "^4.3.5", "@types/js-yaml": "^4.0.5", - "@types/node": "^18.11.7", + "@types/node": "^18.16.3", "@typescript-eslint/eslint-plugin": "^5.41.0", "@typescript-eslint/parser": "^5.41.0", "c8": "^7.12.0", diff --git a/tsconfig.json b/tsconfig.json index c2b1773..91d1c90 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,19 +1,14 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "sourceMap": true, - "outDir": "dist", - "declaration": true, - "esModuleInterop": true, - "types": [ - "node" - ] - }, - "include": [ - "lib/front_matter.ts" - ], - "exclude": [ - "node_modules" - ] -} \ No newline at end of file + "compilerOptions": { + "module": "CommonJS", + "target": "ES6", + "sourceMap": true, + "outDir": "dist", + "declaration": true, + "esModuleInterop": true, + "skipDefaultLibCheck": true, + "skipLibCheck": true + }, + "include": ["lib/front_matter.ts"], + "exclude": ["node_modules", "dist"] +}