diff --git a/lib/box/file.ts b/lib/box/file.ts index 6171e430d6..99bb509ddd 100644 --- a/lib/box/file.ts +++ b/lib/box/file.ts @@ -1,10 +1,12 @@ -import { readFile, readFileSync, stat, statSync } from 'hexo-fs'; +import type Promise from 'bluebird'; +import { readFile, readFileSync, stat, statSync, type ReadFileOptions } from 'hexo-fs'; +import type fs from 'fs'; class File { - public source: any; - public path: any; + public source: string; + public path: string; public params: any; - public type: any; + public type: string; static TYPE_CREATE: 'create'; static TYPE_UPDATE: 'update'; static TYPE_SKIP: 'skip'; @@ -17,19 +19,19 @@ class File { this.type = type; } - read(options) { + read(options?: ReadFileOptions): Promise { return readFile(this.source, options); } - readSync(options) { + readSync(options?: ReadFileOptions): string | Buffer { return readFileSync(this.source, options); } - stat(options) { + stat(): Promise { return stat(this.source); } - statSync(options) { + statSync(): fs.Stats { return statSync(this.source); } } diff --git a/lib/box/index.ts b/lib/box/index.ts index a61e08e54e..3222b55880 100644 --- a/lib/box/index.ts +++ b/lib/box/index.ts @@ -6,6 +6,7 @@ import { createReadStream, readdir, stat, watch } from 'hexo-fs'; import { magenta } from 'picocolors'; import { EventEmitter } from 'events'; import { isMatch, makeRe } from 'micromatch'; +import type Hexo from '../hexo'; const defaultPattern = new Pattern(() => ({})); @@ -16,20 +17,18 @@ interface Processor { class Box extends EventEmitter { public options: any; - public context: any; - public base: any; + public context: Hexo; + public base: string; public processors: Processor[]; public _processingFiles: any; public watcher: any; public Cache: any; // TODO: replace runtime class _File public File: any; - public ignore: any; + public ignore: any[]; public source: any; - public emit: any; - public ctx: any; - constructor(ctx, base, options?: object) { + constructor(ctx: Hexo, base: string, options?: object) { super(); this.options = Object.assign({ @@ -64,13 +63,13 @@ class Box extends EventEmitter { class _File extends File { public box: Box; - render(options) { + render(options?: object) { return ctx.render.render({ path: this.source }, options); } - renderSync(options) { + renderSync(options?: object) { return ctx.render.renderSync({ path: this.source }, options); @@ -82,7 +81,9 @@ class Box extends EventEmitter { return _File; } - addProcessor(pattern, fn) { + addProcessor(pattern: (...args: any[]) => any): void; + addProcessor(pattern: string | RegExp | Pattern | ((...args: any[]) => any), fn: (...args: any[]) => any): void; + addProcessor(pattern: string | RegExp | Pattern | ((...args: any[]) => any), fn?: (...args: any[]) => any): void { if (!fn && typeof pattern === 'function') { fn = pattern; pattern = defaultPattern; @@ -97,7 +98,7 @@ class Box extends EventEmitter { }); } - _readDir(base, prefix = '') { + _readDir(base: string, prefix = ''): BlueBirdPromise { const { context: ctx } = this; const results = []; return readDirWalker(ctx, base, results, this.ignore, prefix) @@ -106,7 +107,7 @@ class Box extends EventEmitter { .map(file => this._processFile(file.type, file.path).return(file.path)); } - _checkFileStatus(path) { + _checkFileStatus(path: string) { const { Cache, context: ctx } = this; const src = join(this.base, path); @@ -120,7 +121,7 @@ class Box extends EventEmitter { })); } - process(callback?) { + process(callback?: NodeJSLikeCallback): BlueBirdPromise { const { base, Cache, context: ctx } = this; return stat(base).then(stats => { @@ -132,14 +133,14 @@ class Box extends EventEmitter { // Handle deleted files return this._readDir(base) - .then(files => cacheFiles.filter(path => !files.includes(path))) - .map(path => this._processFile(File.TYPE_DELETE, path)); + .then((files: string[]) => cacheFiles.filter((path: string) => !files.includes(path))) + .map((path: string) => this._processFile(File.TYPE_DELETE, path) as PromiseLike); }).catch(err => { if (err && err.code !== 'ENOENT') throw err; }).asCallback(callback); } - _processFile(type, path) { + _processFile(type: string, path: string): BlueBirdPromise | BlueBirdPromise { if (this._processingFiles[path]) { return BlueBirdPromise.resolve(); } @@ -182,7 +183,7 @@ class Box extends EventEmitter { }).thenReturn(path); } - watch(callback?) { + watch(callback?: NodeJSLikeCallback): BlueBirdPromise { if (this.isWatching()) { return BlueBirdPromise.reject(new Error('Watcher has already started.')).asCallback(callback); } @@ -217,24 +218,24 @@ class Box extends EventEmitter { }).asCallback(callback); } - unwatch() { + unwatch(): void { if (!this.isWatching()) return; this.watcher.close(); this.watcher = null; } - isWatching() { + isWatching(): boolean { return Boolean(this.watcher); } } -function escapeBackslash(path) { +function escapeBackslash(path: string): string { // Replace backslashes on Windows return path.replace(/\\/g, '/'); } -function getHash(path) { +function getHash(path: string): BlueBirdPromise { const src = createReadStream(path); const hasher = createSha1Hash(); @@ -248,7 +249,7 @@ function getHash(path) { return finishedPromise.then(() => hasher.digest('hex')); } -function toRegExp(ctx, arg) { +function toRegExp(ctx: Hexo, arg: string): RegExp | null { if (!arg) return null; if (typeof arg !== 'string') { ctx.log.warn('A value of "ignore:" section in "_config.yml" is not invalid (not a string)'); @@ -262,11 +263,11 @@ function toRegExp(ctx, arg) { return result; } -function isIgnoreMatch(path, ignore) { +function isIgnoreMatch(path: string, ignore: string | any[]): boolean { return path && ignore && ignore.length && isMatch(path, ignore); } -function readDirWalker(ctx, base, results, ignore, prefix) { +function readDirWalker(ctx: Hexo, base: string, results: any[], ignore: any, prefix: string): BlueBirdPromise { if (isIgnoreMatch(base, ignore)) return BlueBirdPromise.resolve(); return BlueBirdPromise.map(readdir(base).catch(err => { @@ -292,4 +293,10 @@ function readDirWalker(ctx, base, results, ignore, prefix) { }); } -export = Box; +export interface _File extends File { + box: Box; + render(options?: any): any; + renderSync(options?: any): any; +} + +export default Box; diff --git a/lib/extend/console.ts b/lib/extend/console.ts index c4af6322d7..a5b7868af9 100644 --- a/lib/extend/console.ts +++ b/lib/extend/console.ts @@ -51,7 +51,7 @@ class Console { return this.store[this.alias[name]]; } - list() { + list(): Store { return this.store; } @@ -66,7 +66,7 @@ class Console { register(name: string, desc: string, fn: AnyFn): void register(name: string, options: Option, fn: AnyFn): void register(name: string, desc: string, options: Option, fn: AnyFn): void - register(name: string, desc: string | Option | AnyFn, options?: Option | AnyFn, fn?: AnyFn) { + register(name: string, desc: string | Option | AnyFn, options?: Option | AnyFn, fn?: AnyFn): void { if (!name) throw new TypeError('name is required'); if (!fn) { diff --git a/lib/extend/deployer.ts b/lib/extend/deployer.ts index d42d3d854c..ae88664cdc 100644 --- a/lib/extend/deployer.ts +++ b/lib/extend/deployer.ts @@ -17,15 +17,15 @@ class Deployer { this.store = {}; } - list() { + list(): Store { return this.store; } - get(name: string) { + get(name: string): StoreFunction { return this.store[name]; } - register(name: string, fn: StoreFunction) { + register(name: string, fn: StoreFunction): void { if (!name) throw new TypeError('name is required'); if (typeof fn !== 'function') throw new TypeError('fn must be a function'); diff --git a/lib/extend/filter.ts b/lib/extend/filter.ts index 78113d01c2..2af06fae87 100644 --- a/lib/extend/filter.ts +++ b/lib/extend/filter.ts @@ -38,7 +38,7 @@ class Filter { register(fn: StoreFunction, priority: number): void register(type: string, fn: StoreFunction): void register(type: string, fn: StoreFunction, priority: number): void - register(type: string | StoreFunction, fn?: StoreFunction | number, priority?: number) { + register(type: string | StoreFunction, fn?: StoreFunction | number, priority?: number): void { if (!priority) { if (typeof type === 'function') { priority = fn as number; @@ -61,7 +61,7 @@ class Filter { store.sort((a, b) => a.priority - b.priority); } - unregister(type: string, fn: StoreFunction) { + unregister(type: string, fn: StoreFunction): void { if (!type) throw new TypeError('type is required'); if (typeof fn !== 'function') throw new TypeError('fn must be a function'); @@ -75,7 +75,7 @@ class Filter { if (index !== -1) list.splice(index, 1); } - exec(type: string, data: any[], options: FilterOptions = {}) { + exec(type: string, data: any[], options: FilterOptions = {}): Promise { const filters = this.list(type); if (filters.length === 0) return Promise.resolve(data); diff --git a/lib/extend/generator.ts b/lib/extend/generator.ts index 6360d1eb2c..2854f8f869 100644 --- a/lib/extend/generator.ts +++ b/lib/extend/generator.ts @@ -31,17 +31,17 @@ class Generator { this.store = {}; } - list() { + list(): Store { return this.store; } - get(name: string) { + get(name: string): StoreFunction { return this.store[name]; } register(fn: GeneratorFunction): void register(name: string, fn: GeneratorFunction): void - register(name: string | GeneratorFunction, fn?: GeneratorFunction) { + register(name: string | GeneratorFunction, fn?: GeneratorFunction): void { if (!fn) { if (typeof name === 'function') { // fn fn = name; diff --git a/lib/extend/helper.ts b/lib/extend/helper.ts index 7903557c97..f167282371 100644 --- a/lib/extend/helper.ts +++ b/lib/extend/helper.ts @@ -35,7 +35,7 @@ class Helper { * @param {String} name - The name of the helper plugin * @param {StoreFunction} fn - The helper plugin function */ - register(name: string, fn: StoreFunction) { + register(name: string, fn: StoreFunction): void { if (!name) throw new TypeError('name is required'); if (typeof fn !== 'function') throw new TypeError('fn must be a function'); diff --git a/lib/extend/injector.ts b/lib/extend/injector.ts index fd1d09acdd..edb4a45094 100644 --- a/lib/extend/injector.ts +++ b/lib/extend/injector.ts @@ -24,15 +24,15 @@ class Injector { this.cache = new Cache(); } - list() { + list(): Store { return this.store; } - get(entry: Entry, to = 'default') { + get(entry: Entry, to = 'default'): any[] { return Array.from(this.store[entry][to] || []); } - getText(entry: Entry, to = 'default') { + getText(entry: Entry, to = 'default'): string { const arr = this.get(entry, to); if (!arr || !arr.length) return ''; return arr.join(''); @@ -42,7 +42,7 @@ class Injector { return this.cache.apply(`${entry}-size`, Object.keys(this.store[entry]).length); } - register(entry: Entry, value: string | (() => string), to = 'default') { + register(entry: Entry, value: string | (() => string), to = 'default'): void { if (!entry) throw new TypeError('entry is required'); if (typeof value === 'function') value = value(); @@ -52,7 +52,7 @@ class Injector { entryMap[to] = valueSet; } - _getPageType(pageLocals) { + _getPageType(pageLocals): string { let currentType = 'default'; if (pageLocals.__index) currentType = 'home'; if (pageLocals.__post) currentType = 'post'; @@ -65,7 +65,7 @@ class Injector { return currentType; } - _injector(input, pattern, flag, isBegin = true, currentType) { + _injector(input: string, pattern: string | RegExp, flag: Entry, isBegin = true, currentType: string): string { if (input.includes(`hexo injector ${flag}`)) return input; const code = this.cache.apply(`${flag}-${currentType}-code`, () => { @@ -81,7 +81,7 @@ class Injector { return input.replace(pattern, str => { return isBegin ? str + code : code + str; }); } - exec(data, locals = { page: {} }) { + exec(data: string, locals = { page: {} }): string { const { page } = locals; const currentType = this._getPageType(page); diff --git a/lib/extend/migrator.ts b/lib/extend/migrator.ts index 2a149f191a..5ab0f7063e 100644 --- a/lib/extend/migrator.ts +++ b/lib/extend/migrator.ts @@ -14,15 +14,15 @@ class Migrator { this.store = {}; } - list() { + list(): Store { return this.store; } - get(name: string) { + get(name: string): StoreFunction { return this.store[name]; } - register(name: string, fn: StoreFunction) { + register(name: string, fn: StoreFunction): void { if (!name) throw new TypeError('name is required'); if (typeof fn !== 'function') throw new TypeError('fn must be a function'); diff --git a/lib/extend/processor.ts b/lib/extend/processor.ts index 0af6998494..ce73da1031 100644 --- a/lib/extend/processor.ts +++ b/lib/extend/processor.ts @@ -19,13 +19,13 @@ class Processor { this.store = []; } - list() { + list(): Store { return this.store; } register(fn: StoreFunction): void; register(pattern: patternType, fn: StoreFunction): void; - register(pattern: patternType | StoreFunction, fn?: StoreFunction) { + register(pattern: patternType | StoreFunction, fn?: StoreFunction): void { if (!fn) { if (typeof pattern === 'function') { fn = pattern; diff --git a/lib/extend/renderer.ts b/lib/extend/renderer.ts index c70e054f18..15f90c6de6 100644 --- a/lib/extend/renderer.ts +++ b/lib/extend/renderer.ts @@ -8,36 +8,36 @@ const getExtname = (str: string) => { return ext.startsWith('.') ? ext.slice(1) : ext; }; -interface StoreSyncFunction { +export interface StoreFunctionData { + path?: any; + text?: string; + engine?: string; + toString?: any; + onRenderEnd?: any; +} + +export interface StoreSyncFunction { + [x: string]: any; ( - data: { - path?: string; - text: string; - }, + data: StoreFunctionData, options: object, - // callback: (err: Error, value: string) => any + // callback: NodeJSLikeCallback ): any; output?: string; - compile?: (local: object) => string; + compile?: (local: object) => any; } -interface StoreFunction { +export interface StoreFunction { ( - data: { - path?: string; - text: string; - }, + data: StoreFunctionData, options: object, ): Promise; ( - data: { - path?: string; - text: string; - }, + data: StoreFunctionData, options: object, - callback: (err: Error, value: string) => any + callback: NodeJSLikeCallback ): void; output?: string; - compile?: (local: object) => string; + compile?: (local: object) => any; disableNunjucks?: boolean; } @@ -57,25 +57,25 @@ class Renderer { this.storeSync = {}; } - list(sync: boolean) { + list(sync: boolean): Store | SyncStore { return sync ? this.storeSync : this.store; } - get(name: string, sync?: boolean) { + get(name: string, sync?: boolean): StoreSyncFunction | StoreFunction { const store = this[sync ? 'storeSync' : 'store']; return store[getExtname(name)] || store[name]; } - isRenderable(path: string) { + isRenderable(path: string): boolean { return Boolean(this.get(path)); } - isRenderableSync(path: string) { + isRenderableSync(path: string): boolean { return Boolean(this.get(path, true)); } - getOutput(path: string) { + getOutput(path: string): string { const renderer = this.get(path); return renderer ? renderer.output : ''; } @@ -109,4 +109,4 @@ class Renderer { } } -export = Renderer; +export default Renderer; diff --git a/lib/extend/syntax_highlight.ts b/lib/extend/syntax_highlight.ts index 419a950f24..c5cf28a95f 100644 --- a/lib/extend/syntax_highlight.ts +++ b/lib/extend/syntax_highlight.ts @@ -3,7 +3,7 @@ import type Hexo from '../hexo'; export interface HighlightOptions { lang: string | undefined, caption: string | undefined, - lines_length: number, + lines_length?: number | undefined, // plugins/filter/before_post_render/backtick_code_block firstLineNumber?: string | number @@ -39,13 +39,13 @@ class SyntaxHighlight { this.store = {}; } - register(name: string, fn: StoreFunction) { + register(name: string, fn: StoreFunction): void { if (typeof fn !== 'function') throw new TypeError('fn must be a function'); this.store[name] = fn; } - query(name: string) { + query(name: string): StoreFunction { return name && this.store[name]; } diff --git a/lib/extend/tag.ts b/lib/extend/tag.ts index f2fcc3d325..d44b5dd993 100644 --- a/lib/extend/tag.ts +++ b/lib/extend/tag.ts @@ -4,7 +4,7 @@ import { Environment } from 'nunjucks'; import Promise from 'bluebird'; const rSwigRawFullBlock = /{% *raw *%}/; const rCodeTag = /]*>[\s\S]+?<\/code>/g; -const escapeSwigTag = str => str.replace(/{/g, '{').replace(/}/g, '}'); +const escapeSwigTag = (str: string) => str.replace(/{/g, '{').replace(/}/g, '}'); interface TagFunction { (args: any[], content: string): string; @@ -66,7 +66,7 @@ class NunjucksTag { } } -const trimBody = body => { +const trimBody = (body: () => any) => { return stripIndent(body()).replace(/^\n?|\n?$/g, ''); }; @@ -126,7 +126,7 @@ class NunjucksAsyncBlock extends NunjucksBlock { } } -const getContextLineNums = (min, max, center, amplitude) => { +const getContextLineNums = (min: number, max: number, center: number, amplitude: number) => { const result = []; let lbound = Math.max(min, center - amplitude); const hbound = Math.min(max, center + amplitude); @@ -136,7 +136,7 @@ const getContextLineNums = (min, max, center, amplitude) => { const LINES_OF_CONTEXT = 5; -const getContext = (lines, errLine, location, type) => { +const getContext = (lines: string[], errLine: number, location: string, type: string) => { const message = [ location + ' ' + red(type), cyan(' ===== Context Dump ====='), @@ -173,7 +173,7 @@ class NunjucksError extends Error { * @param {string} str string input for Nunjucks * @return {Error} New error object with embedded context */ -const formatNunjucksError = (err, input, source = '') => { +const formatNunjucksError = (err: Error, input: string, source = ''): Error => { err.message = err.message.replace('(unknown path)', source ? magenta(source) : ''); const match = err.message.match(/Line (\d+), Column \d+/); @@ -199,8 +199,8 @@ type RegisterOptions = { } class Tag { - public env: any; - public source: any; + public env: Environment; + public source: string; constructor() { this.env = new Environment(null, { @@ -211,7 +211,7 @@ class Tag { register(name: string, fn: TagFunction): void register(name: string, fn: TagFunction, ends: boolean): void register(name: string, fn: TagFunction, options: RegisterOptions): void - register(name: string, fn: TagFunction, options?: RegisterOptions | boolean) { + register(name: string, fn: TagFunction, options?: RegisterOptions | boolean):void { if (!name) throw new TypeError('name is required'); if (typeof fn !== 'function') throw new TypeError('fn must be a function'); @@ -243,7 +243,7 @@ class Tag { this.env.addExtension(name, tag); } - unregister(name) { + unregister(name: string): void { if (!name) throw new TypeError('name is required'); const { env } = this; @@ -251,7 +251,7 @@ class Tag { if (env.hasExtension(name)) env.removeExtension(name); } - render(str, options: { source?: string } = {}, callback) { + render(str: string, options: { source?: string } = {}, callback?: NodeJSLikeCallback): Promise { if (!callback && typeof options === 'function') { callback = options; options = {}; diff --git a/lib/hexo/index.ts b/lib/hexo/index.ts index 2d347c7bde..c248b7b675 100644 --- a/lib/hexo/index.ts +++ b/lib/hexo/index.ts @@ -36,16 +36,17 @@ import defaultConfig from './default_config'; import loadDatabase from './load_database'; import multiConfigPath from './multi_config_path'; import { deepMerge, full_url_for } from 'hexo-util'; +import type Box from '../box'; let resolveSync; // = require('resolve'); const libDir = dirname(__dirname); const dbVersion = 1; -const stopWatcher = box => { if (box.isWatching()) box.unwatch(); }; +const stopWatcher = (box: Box) => { if (box.isWatching()) box.unwatch(); }; const routeCache = new WeakMap(); -const castArray = obj => { return Array.isArray(obj) ? obj : [obj]; }; +const castArray = (obj: any) => { return Array.isArray(obj) ? obj : [obj]; }; const mergeCtxThemeConfig = ctx => { // Merge hexo.config.theme_config into hexo.theme.config before post rendering & generating @@ -335,7 +336,7 @@ class Hexo extends EventEmitter { }); } - call(name, args, callback) { + call(name: string, args: any, callback?: NodeJSLikeCallback) { if (!callback && typeof args === 'function') { callback = args; args = {}; @@ -348,11 +349,11 @@ class Hexo extends EventEmitter { return Promise.reject(new Error(`Console \`${name}\` has not been registered yet!`)); } - model(name, schema) { + model(name: string, schema?: any) { return this.database.model(name, schema); } - resolvePlugin(name, basedir) { + resolvePlugin(name: string, basedir: string) { try { // Try to resolve the plugin with the Node.js's built-in require.resolve. return require.resolve(name, { paths: [basedir] }); @@ -370,18 +371,18 @@ class Hexo extends EventEmitter { } } - loadPlugin(path: string, callback: (...args: any[]) => any) { + loadPlugin(path: string, callback?: NodeJSLikeCallback) { return readFile(path).then(script => { // Based on: https://github.com/joyent/node/blob/v0.10.33/src/node.js#L516 const module = new Module(path); module.filename = path; module.paths = Module._nodeModulePaths(path); - function req(path) { + function req(path: string) { return module.require(path); } - req.resolve = request => Module._resolveFilename(request, module); + req.resolve = (request: string) => Module._resolveFilename(request, module); req.main = require.main; req.extensions = Module._extensions; @@ -400,7 +401,7 @@ class Hexo extends EventEmitter { return args.draft || args.drafts || this.config.render_drafts; } - load(callback) { + load(callback?: NodeJSLikeCallback) { return loadDatabase(this).then(() => { this.log.info('Start processing'); @@ -414,7 +415,7 @@ class Hexo extends EventEmitter { }).asCallback(callback); } - watch(callback) { + watch(callback?: NodeJSLikeCallback) { let useCache = false; const { cache } = Object.assign({ cache: false @@ -478,7 +479,7 @@ class Hexo extends EventEmitter { site: object; cache?: boolean; - constructor(path, locals) { + constructor(path: string, locals) { this.page = { ...locals }; if (this.page.path == null) this.page.path = path; this.path = path; @@ -512,7 +513,7 @@ class Hexo extends EventEmitter { }, []); } - _routerRefresh(runningGenerators, useCache) { + _routerRefresh(runningGenerators: Promise, useCache: boolean) { const { route } = this; const routeList = route.list(); const Locals = this._generateLocals(); @@ -580,11 +581,11 @@ class Hexo extends EventEmitter { }); } - execFilter(type, data, options) { + execFilter(type: string, data: any, options) { return this.extend.filter.exec(type, data, options); } - execFilterSync(type, data, options) { + execFilterSync(type: string, data: any, options) { return this.extend.filter.execSync(type, data, options); } } diff --git a/lib/hexo/load_config.ts b/lib/hexo/load_config.ts index 231e285f02..489f4e03ff 100644 --- a/lib/hexo/load_config.ts +++ b/lib/hexo/load_config.ts @@ -6,8 +6,9 @@ import { exists, readdir } from 'hexo-fs'; import { magenta } from 'picocolors'; import { deepMerge } from 'hexo-util'; import validateConfig from './validate_config'; +import type Hexo from './index'; -export = async ctx => { +export = async (ctx: Hexo) => { if (!ctx.env.init) return; const baseDir = ctx.base_dir; @@ -65,7 +66,7 @@ export = async ctx => { }; -async function findConfigPath(path) { +async function findConfigPath(path: string) { const { dir, name } = parse(path); const files = await readdir(dir); diff --git a/lib/hexo/load_database.ts b/lib/hexo/load_database.ts index c64719c929..f0ac5decb0 100644 --- a/lib/hexo/load_database.ts +++ b/lib/hexo/load_database.ts @@ -1,7 +1,8 @@ import { exists, unlink } from 'hexo-fs'; import Promise from 'bluebird'; +import type Hexo from './index'; -export = ctx => { +export = (ctx: Hexo) => { if (ctx._dbLoaded) return Promise.resolve(); const db = ctx.database; diff --git a/lib/hexo/load_plugins.ts b/lib/hexo/load_plugins.ts index c1dcb29067..289474f00f 100644 --- a/lib/hexo/load_plugins.ts +++ b/lib/hexo/load_plugins.ts @@ -2,14 +2,15 @@ import { join } from 'path'; import { exists, readFile, listDir } from 'hexo-fs'; import Promise from 'bluebird'; import { magenta } from 'picocolors'; +import type Hexo from './index'; -export = ctx => { +export = (ctx: Hexo) => { if (!ctx.env.init || ctx.env.safe) return; return loadModules(ctx).then(() => loadScripts(ctx)); }; -function loadModuleList(ctx, basedir) { +function loadModuleList(ctx: Hexo, basedir: string) { const packagePath = join(basedir, 'package.json'); // Make sure package.json exists @@ -42,14 +43,14 @@ function loadModuleList(ctx, basedir) { }); } -function loadModules(ctx) { +function loadModules(ctx: Hexo) { return Promise.map([ctx.base_dir, ctx.theme_dir], basedir => loadModuleList(ctx, basedir)) .then(([hexoModuleList, themeModuleList]) => { return Object.entries(Object.assign(themeModuleList, hexoModuleList)); }) .map(([name, path]) => { // Load plugins - return ctx.loadPlugin(path).then(() => { + return ctx.loadPlugin(path as string).then(() => { ctx.log.debug('Plugin loaded: %s', magenta(name)); }).catch(err => { ctx.log.error({err}, 'Plugin load failed: %s', magenta(name)); @@ -57,7 +58,7 @@ function loadModules(ctx) { }); } -function loadScripts(ctx) { +function loadScripts(ctx: Hexo) { const baseDirLength = ctx.base_dir.length; return Promise.filter([ @@ -76,6 +77,6 @@ function loadScripts(ctx) { })); } -function displayPath(path, baseDirLength) { +function displayPath(path: string, baseDirLength: number) { return magenta(path.substring(baseDirLength)); } diff --git a/lib/hexo/load_theme_config.ts b/lib/hexo/load_theme_config.ts index 57a28adb41..54c700960a 100644 --- a/lib/hexo/load_theme_config.ts +++ b/lib/hexo/load_theme_config.ts @@ -3,8 +3,9 @@ import tildify from 'tildify'; import { exists, readdir } from 'hexo-fs'; import { magenta } from 'picocolors'; import { deepMerge } from 'hexo-util'; +import type Hexo from './index'; -export = ctx => { +export = (ctx: Hexo) => { if (!ctx.env.init) return; if (!ctx.config.theme) return; @@ -30,7 +31,7 @@ export = ctx => { }); }; -function findConfigPath(path) { +function findConfigPath(path: string) { const { dir, name } = parse(path); return readdir(dir).then(files => { diff --git a/lib/hexo/locals.ts b/lib/hexo/locals.ts index 468dabe26f..7153cb0a48 100644 --- a/lib/hexo/locals.ts +++ b/lib/hexo/locals.ts @@ -9,7 +9,7 @@ class Locals { this.getters = {}; } - get(name) { + get(name: string) { if (typeof name !== 'string') throw new TypeError('name must be a string!'); return this.cache.apply(name, () => { @@ -20,7 +20,7 @@ class Locals { }); } - set(name, value) { + set(name: string, value: any) { if (typeof name !== 'string') throw new TypeError('name must be a string!'); if (value == null) throw new TypeError('value is required!'); @@ -32,7 +32,7 @@ class Locals { return this; } - remove(name) { + remove(name: string) { if (typeof name !== 'string') throw new TypeError('name must be a string!'); this.getters[name] = null; diff --git a/lib/hexo/multi_config_path.ts b/lib/hexo/multi_config_path.ts index 8d140d3569..978c04fca0 100644 --- a/lib/hexo/multi_config_path.ts +++ b/lib/hexo/multi_config_path.ts @@ -2,8 +2,9 @@ import { isAbsolute, resolve, join, extname } from 'path'; import { existsSync, readFileSync, writeFileSync } from 'hexo-fs'; import yml from 'js-yaml'; import { deepMerge } from 'hexo-util'; +import type Hexo from './index'; -export = ctx => function multiConfigPath(base, configPaths, outputDir) { +export = (ctx: Hexo) => function multiConfigPath(base: string, configPaths: string, outputDir: string) { const { log } = ctx; const defaultPath = join(base, '_config.yml'); @@ -12,7 +13,7 @@ export = ctx => function multiConfigPath(base, configPaths, outputDir) { return join(base, '_config.yml'); } - let paths; + let paths: string[]; // determine if comma or space separated if (configPaths.includes(',')) { paths = configPaths.replace(' ', '').split(','); diff --git a/lib/hexo/post.ts b/lib/hexo/post.ts index 748d73fd94..f9269484e2 100644 --- a/lib/hexo/post.ts +++ b/lib/hexo/post.ts @@ -7,6 +7,7 @@ import { load } from 'js-yaml'; import { slugize, escapeRegExp } from 'hexo-util'; import { copyDir, exists, listDir, mkdirs, readFile, rmdir, unlink, writeFile } from 'hexo-fs'; import { parse as yfmParse, split as yfmSplit, stringify as yfmStringify } from 'hexo-front-matter'; +import type Hexo from './index'; const preservedKeys = ['title', 'slug', 'path', 'layout', 'date', 'content']; const rHexoPostRenderEscape = /([\s\S]+?)<\/hexoPostRenderCodeBlock>/g; @@ -20,7 +21,7 @@ const STATE_SWIG_COMMENT = Symbol('swig_comment'); const STATE_SWIG_TAG = Symbol('swig_tag'); const STATE_SWIG_FULL_TAG = Symbol('swig_full_tag'); -const isNonWhiteSpaceChar = char => char !== '\r' +const isNonWhiteSpaceChar = (char: string) => char !== '\r' && char !== '\n' && char !== '\t' && char !== '\f' @@ -28,18 +29,18 @@ const isNonWhiteSpaceChar = char => char !== '\r' && char !== ' '; class PostRenderEscape { - public stored: any; - public length: any; + public stored: any[]; + public length: number; constructor() { this.stored = []; } - static escapeContent(cache, flag, str) { + static escapeContent(cache: any[], flag: string, str: string) { return ``; } - static restoreContent(cache) { + static restoreContent(cache: any[]) { return (_, index) => { assert(cache[index]); const value = cache[index]; @@ -48,16 +49,16 @@ class PostRenderEscape { }; } - restoreAllSwigTags(str) { + restoreAllSwigTags(str: string) { const restored = str.replace(rSwigPlaceHolder, PostRenderEscape.restoreContent(this.stored)); return restored; } - restoreCodeBlocks(str) { + restoreCodeBlocks(str: string) { return str.replace(rCodeBlockPlaceHolder, PostRenderEscape.restoreContent(this.stored)); } - escapeCodeBlocks(str) { + escapeCodeBlocks(str: string) { return str.replace(rHexoPostRenderEscape, (_, content) => PostRenderEscape.escapeContent(this.stored, 'code', content)); } @@ -65,7 +66,7 @@ class PostRenderEscape { * @param {string} str * @returns string */ - escapeAllSwigTags(str) { + escapeAllSwigTags(str: string) { let state = STATE_PLAINTEXT; let buffer = ''; let output = ''; @@ -185,7 +186,7 @@ class PostRenderEscape { } } -const prepareFrontMatter = (data, jsonMode) => { +const prepareFrontMatter = (data: any, jsonMode: boolean) => { for (const [key, item] of Object.entries(data)) { if (moment.isMoment(item)) { data[key] = item.utc().format('YYYY-MM-DD HH:mm:ss'); @@ -202,11 +203,11 @@ const prepareFrontMatter = (data, jsonMode) => { }; -const removeExtname = str => { +const removeExtname = (str: string) => { return str.substring(0, str.length - extname(str).length); }; -const createAssetFolder = (path, assetFolder) => { +const createAssetFolder = (path: string, assetFolder: boolean) => { if (!assetFolder) return Promise.resolve(); const target = removeExtname(path); @@ -231,17 +232,24 @@ interface Data { source?: string; } +interface PostData { + title?: string; + layout?: string; + slug?: string; + path?: string; + [prop: string]: any; +} + class Post { - public context: any; - public config: any; - public tag: any; - public separator: any; + public context: Hexo; - constructor(context) { + constructor(context: Hexo) { this.context = context; } - create(data, replace, callback?) { + create(data: PostData, callback?: NodeJSLikeCallback); + create(data: PostData, replace: boolean, callback?: NodeJSLikeCallback); + create(data: PostData, replace: boolean | (NodeJSLikeCallback), callback?: NodeJSLikeCallback) { if (!callback && typeof replace === 'function') { callback = replace; replace = false; @@ -276,7 +284,7 @@ class Post { }).asCallback(callback); } - _getScaffold(layout) { + _getScaffold(layout: string) { const ctx = this.context; return ctx.scaffold.get(layout).then(result => { @@ -285,7 +293,7 @@ class Post { }); } - _renderScaffold(data) { + _renderScaffold(data: PostData) { const { tag } = this.context.extend; let splitted; @@ -327,7 +335,7 @@ class Post { }); } - publish(data, replace, callback) { + publish(data: PostData, replace: boolean, callback?: NodeJSLikeCallback) { if (!callback && typeof replace === 'function') { callback = replace; replace = false; @@ -354,7 +362,7 @@ class Post { // Read the content src = join(draftDir, item); return readFile(src); - }).then(content => { + }).then((content: string) => { // Create post Object.assign(data, yfmParse(content)); data.content = data._content; @@ -380,7 +388,7 @@ class Post { }).thenReturn(result).asCallback(callback); } - render(source, data: Data = {}, callback) { + render(source: string, data: Data = {}, callback?: NodeJSLikeCallback) { const ctx = this.context; const { config } = ctx; const { tag } = ctx.extend; diff --git a/lib/hexo/register_models.ts b/lib/hexo/register_models.ts index 864e4e3631..88a73e6081 100644 --- a/lib/hexo/register_models.ts +++ b/lib/hexo/register_models.ts @@ -1,6 +1,7 @@ import * as models from '../models'; +import type Hexo from './index'; -export = ctx => { +export = (ctx: Hexo) => { const db = ctx.database; const keys = Object.keys(models); diff --git a/lib/hexo/render.ts b/lib/hexo/render.ts index a25d152314..4d1ebda922 100644 --- a/lib/hexo/render.ts +++ b/lib/hexo/render.ts @@ -1,8 +1,11 @@ import { extname } from 'path'; import Promise from 'bluebird'; import { readFile, readFileSync } from 'hexo-fs'; +import type Hexo from './index'; +import type { Renderer } from '../extend'; +import type { StoreFunctionData } from '../extend/renderer'; -const getExtname = str => { +const getExtname = (str: string) => { if (typeof str !== 'string') return ''; const ext = extname(str); @@ -24,35 +27,35 @@ const toString = (result, options) => { }; class Render { - public context: any; - public renderer: any; + public context: Hexo; + public renderer: Renderer; - constructor(ctx) { + constructor(ctx: Hexo) { this.context = ctx; this.renderer = ctx.extend.renderer; } - isRenderable(path) { + isRenderable(path: string) { return this.renderer.isRenderable(path); } - isRenderableSync(path) { + isRenderableSync(path: string) { return this.renderer.isRenderableSync(path); } - getOutput(path) { + getOutput(path: string) { return this.renderer.getOutput(path); } - getRenderer(ext, sync?) { + getRenderer(ext: string, sync?: boolean) { return this.renderer.get(ext, sync); } - getRendererSync(ext) { + getRendererSync(ext: string) { return this.getRenderer(ext, true); } - render(data, options, callback) { + render(data: StoreFunctionData, options?: { highlight?: boolean; }, callback?: undefined) { if (!callback && typeof options === 'function') { callback = options; options = {}; @@ -96,14 +99,14 @@ class Render { }).asCallback(callback); } - renderSync(data, options = {}) { + renderSync(data: StoreFunctionData, options = {}) { if (!data) throw new TypeError('No input file or string!'); const ctx = this.context; if (data.text == null) { if (!data.path) throw new TypeError('No input file or string!'); - data.text = readFileSync(data.path); + data.text = readFileSync(data.path) as string; } if (data.text == null) throw new TypeError('No input file or string!'); diff --git a/lib/hexo/router.ts b/lib/hexo/router.ts index f00824d381..33edb61478 100644 --- a/lib/hexo/router.ts +++ b/lib/hexo/router.ts @@ -18,8 +18,6 @@ class RouteStream extends Readable { public _data: any; public _ended: boolean; public modified: any; - public push: any; - public emit: any; constructor(data: Data) { super({ objectMode: true }); @@ -133,14 +131,14 @@ class Router extends EventEmitter { return new RouteStream(data); } - isModified(path) { + isModified(path: string) { if (typeof path !== 'string') throw new TypeError('path must be a string!'); const data = this.routes[this.format(path)]; return data ? data.modified : false; } - set(path, data) { + set(path: string, data: any) { if (typeof path !== 'string') throw new TypeError('path must be a string!'); if (data == null) throw new TypeError('data is required!'); @@ -175,7 +173,7 @@ class Router extends EventEmitter { return this; } - remove(path) { + remove(path: string) { if (typeof path !== 'string') throw new TypeError('path must be a string!'); path = this.format(path); diff --git a/lib/hexo/scaffold.ts b/lib/hexo/scaffold.ts index 18a1a5ff41..37b6e65e86 100644 --- a/lib/hexo/scaffold.ts +++ b/lib/hexo/scaffold.ts @@ -1,12 +1,12 @@ import { extname, join } from 'path'; import { exists, listDir, readFile, unlink, writeFile } from 'hexo-fs'; - +import type Hexo from './index'; class Scaffold { - public context: any; - public scaffoldDir: any; + public context: Hexo; + public scaffoldDir: string; public defaults: any; - constructor(context) { + constructor(context: Hexo) { this.context = context; this.scaffoldDir = context.scaffold_dir; this.defaults = { @@ -36,11 +36,11 @@ class Scaffold { })); } - _getScaffold(name) { + _getScaffold(name: string) { return this._listDir().then(list => list.find(item => item.name === name)); } - get(name, callback) { + get(name: string, callback?: NodeJSLikeCallback) { return this._getScaffold(name).then(item => { if (item) { return readFile(item.path); @@ -50,7 +50,7 @@ class Scaffold { }).asCallback(callback); } - set(name, content, callback) { + set(name: string, content: any, callback: NodeJSLikeCallback) { const { scaffoldDir } = this; return this._getScaffold(name).then(item => { @@ -61,7 +61,7 @@ class Scaffold { }).asCallback(callback); } - remove(name, callback) { + remove(name: string, callback: NodeJSLikeCallback) { return this._getScaffold(name).then(item => { if (!item) return; diff --git a/lib/hexo/source.ts b/lib/hexo/source.ts index ab4d26bc45..736a41037f 100644 --- a/lib/hexo/source.ts +++ b/lib/hexo/source.ts @@ -1,7 +1,8 @@ import Box from '../box'; +import type Hexo from './index'; class Source extends Box { - constructor(ctx) { + constructor(ctx: Hexo) { super(ctx, ctx.source_dir); this.processors = ctx.extend.processor.list(); diff --git a/lib/hexo/update_package.ts b/lib/hexo/update_package.ts index 03319913e6..4b8f3593bd 100644 --- a/lib/hexo/update_package.ts +++ b/lib/hexo/update_package.ts @@ -1,7 +1,8 @@ import { join } from 'path'; import { writeFile, exists, readFile } from 'hexo-fs'; +import type Hexo from './index'; -export = ctx => { +export = (ctx: Hexo) => { const pkgPath = join(ctx.base_dir, 'package.json'); return readPkg(pkgPath).then(pkg => { @@ -18,7 +19,7 @@ export = ctx => { }); }; -function readPkg(path) { +function readPkg(path: string) { return exists(path).then(exist => { if (!exist) return; diff --git a/lib/hexo/validate_config.ts b/lib/hexo/validate_config.ts index 8dfcb389e9..66af8ceeba 100644 --- a/lib/hexo/validate_config.ts +++ b/lib/hexo/validate_config.ts @@ -1,4 +1,6 @@ -export = ctx => { +import type Hexo from './index'; + +export = (ctx: Hexo) => { const { config, log } = ctx; log.info('Validating config'); diff --git a/lib/models/asset.ts b/lib/models/asset.ts index 006391d3b5..5a761192da 100644 --- a/lib/models/asset.ts +++ b/lib/models/asset.ts @@ -1,7 +1,8 @@ import warehouse from 'warehouse'; import { join } from 'path'; +import type Hexo from '../hexo'; -export = ctx => { +export = (ctx: Hexo) => { const Asset = new warehouse.Schema({ _id: {type: String, required: true}, path: {type: String, required: true}, diff --git a/lib/models/cache.ts b/lib/models/cache.ts index d4b43f4722..60db5ce1c4 100644 --- a/lib/models/cache.ts +++ b/lib/models/cache.ts @@ -1,7 +1,8 @@ import warehouse from 'warehouse'; import Promise from 'bluebird'; +import type Hexo from '../hexo'; -export = ctx => { +export = (ctx: Hexo) => { const Cache = new warehouse.Schema({ _id: {type: String, required: true}, hash: {type: String, default: ''}, diff --git a/lib/models/category.ts b/lib/models/category.ts index 740bc67015..2fdbfb58df 100644 --- a/lib/models/category.ts +++ b/lib/models/category.ts @@ -1,7 +1,8 @@ import warehouse from 'warehouse'; import { slugize, full_url_for } from 'hexo-util'; +import type Hexo from '../hexo'; -export = ctx => { +export = (ctx: Hexo) => { const Category = new warehouse.Schema({ name: {type: String, required: true}, parent: { type: warehouse.Schema.Types.CUID, ref: 'Category'} diff --git a/lib/models/data.ts b/lib/models/data.ts index 0cdefe318a..89832d3cf0 100644 --- a/lib/models/data.ts +++ b/lib/models/data.ts @@ -1,6 +1,7 @@ import warehouse from 'warehouse'; +import type Hexo from '../hexo'; -export = ctx => { +export = (ctx: Hexo) => { const Data = new warehouse.Schema({ _id: {type: String, required: true}, data: Object diff --git a/lib/models/page.ts b/lib/models/page.ts index bbaa606422..f1a96922d7 100644 --- a/lib/models/page.ts +++ b/lib/models/page.ts @@ -3,8 +3,9 @@ import { join } from 'path'; import Moment from './types/moment'; import moment from 'moment'; import { full_url_for } from 'hexo-util'; +import type Hexo from '../hexo'; -export = ctx => { +export = (ctx: Hexo) => { const Page = new warehouse.Schema({ title: {type: String, default: ''}, date: { diff --git a/lib/models/post.ts b/lib/models/post.ts index 10b274d7ad..208e8ea477 100644 --- a/lib/models/post.ts +++ b/lib/models/post.ts @@ -4,6 +4,7 @@ import { extname, join, sep } from 'path'; import Promise from 'bluebird'; import Moment from './types/moment'; import { full_url_for, Cache } from 'hexo-util'; +import type Hexo from '../hexo'; function pickID(data) { return data._id; @@ -15,7 +16,7 @@ function removeEmptyTag(tags) { const tagsGetterCache = new Cache(); -export = ctx => { +export = (ctx: Hexo) => { const Post = new warehouse.Schema({ id: String, title: {type: String, default: ''}, diff --git a/lib/models/post_asset.ts b/lib/models/post_asset.ts index 72ec5f90f1..fe73a02a47 100644 --- a/lib/models/post_asset.ts +++ b/lib/models/post_asset.ts @@ -1,7 +1,8 @@ import warehouse from 'warehouse'; import { join } from 'path'; +import type Hexo from '../hexo'; -export = ctx => { +export = (ctx: Hexo) => { const PostAsset = new warehouse.Schema({ _id: {type: String, required: true}, slug: {type: String, required: true}, diff --git a/lib/models/post_category.ts b/lib/models/post_category.ts index f3c813f8be..8b8feb0c0a 100644 --- a/lib/models/post_category.ts +++ b/lib/models/post_category.ts @@ -1,6 +1,7 @@ import warehouse from 'warehouse'; +import type Hexo from '../hexo'; -export = ctx => { +export = (ctx: Hexo) => { const PostCategory = new warehouse.Schema({ post_id: {type: warehouse.Schema.Types.CUID, ref: 'Post'}, category_id: {type: warehouse.Schema.Types.CUID, ref: 'Category'} diff --git a/lib/models/post_tag.ts b/lib/models/post_tag.ts index e727ca5e3e..b55533c49a 100644 --- a/lib/models/post_tag.ts +++ b/lib/models/post_tag.ts @@ -1,6 +1,7 @@ import warehouse from 'warehouse'; +import type Hexo from '../hexo'; -export = ctx => { +export = (ctx: Hexo) => { const PostTag = new warehouse.Schema({ post_id: {type: warehouse.Schema.Types.CUID, ref: 'Post'}, tag_id: {type: warehouse.Schema.Types.CUID, ref: 'Tag'} diff --git a/lib/models/tag.ts b/lib/models/tag.ts index 9c5b10a55e..84a118aa25 100644 --- a/lib/models/tag.ts +++ b/lib/models/tag.ts @@ -1,8 +1,9 @@ import warehouse from 'warehouse'; import { slugize, full_url_for } from 'hexo-util'; const { hasOwnProperty: hasOwn } = Object.prototype; +import type Hexo from '../hexo'; -export = ctx => { +export = (ctx: Hexo) => { const Tag = new warehouse.Schema({ name: {type: String, required: true} }); diff --git a/lib/plugins/console/clean.ts b/lib/plugins/console/clean.ts index fb799039d8..eea456a757 100644 --- a/lib/plugins/console/clean.ts +++ b/lib/plugins/console/clean.ts @@ -1,7 +1,8 @@ import Promise from 'bluebird'; import { exists, unlink, rmdir } from 'hexo-fs'; +import type Hexo from '../../hexo'; -function cleanConsole(args) { +function cleanConsole(this: Hexo): Promise<[void, void, any]> { return Promise.all([ deleteDatabase(this), deletePublicDir(this), @@ -9,7 +10,7 @@ function cleanConsole(args) { ]); } -function deleteDatabase(ctx) { +function deleteDatabase(ctx: Hexo): Promise { const dbPath = ctx.database.options.path; return exists(dbPath).then(exist => { @@ -21,7 +22,7 @@ function deleteDatabase(ctx) { }); } -function deletePublicDir(ctx) { +function deletePublicDir(ctx: Hexo): Promise { const publicDir = ctx.public_dir; return exists(publicDir).then(exist => { diff --git a/lib/plugins/console/config.ts b/lib/plugins/console/config.ts index 841c241c23..777bc4e1d0 100644 --- a/lib/plugins/console/config.ts +++ b/lib/plugins/console/config.ts @@ -2,8 +2,9 @@ import yaml from 'js-yaml'; import { exists, writeFile } from 'hexo-fs'; import { extname } from 'path'; import Promise from 'bluebird'; +import type Hexo from '../../hexo'; -function configConsole(args) { +function configConsole(this: Hexo, args): Promise { const key = args._[0]; let value = args._[1]; @@ -35,7 +36,7 @@ function configConsole(args) { }); } -function getProperty(obj, key) { +function getProperty(obj: object, key: string): any { const split = key.split('.'); let result = obj[split[0]]; @@ -46,7 +47,7 @@ function getProperty(obj, key) { return result; } -function setProperty(obj, key, value) { +function setProperty(obj: object, key: string, value: any): void { const split = key.split('.'); let cursor = obj; const lastKey = split.pop(); @@ -60,7 +61,7 @@ function setProperty(obj, key, value) { cursor[lastKey] = value; } -function castValue(value) { +function castValue(value: string): any { switch (value) { case 'true': return true; diff --git a/lib/plugins/console/deploy.ts b/lib/plugins/console/deploy.ts index 6da32c2e76..1da54819d4 100644 --- a/lib/plugins/console/deploy.ts +++ b/lib/plugins/console/deploy.ts @@ -1,7 +1,8 @@ import { exists } from 'hexo-fs'; import { underline, magenta } from 'picocolors'; +import type Hexo from '../../hexo'; -function deployConsole(args) { +function deployConsole(this: Hexo, args) { let config = this.config.deploy; const deployers = this.extend.deployer.list(); diff --git a/lib/plugins/console/generate.ts b/lib/plugins/console/generate.ts index ccae2b3d94..2b17697b49 100644 --- a/lib/plugins/console/generate.ts +++ b/lib/plugins/console/generate.ts @@ -6,21 +6,22 @@ import { cyan, magenta } from 'picocolors'; import tildify from 'tildify'; import { PassThrough } from 'stream'; import { createSha1Hash } from 'hexo-util'; +import type Hexo from '../../hexo'; class Generater { - public context: any; + public context: Hexo; public force: any; public bail: any; public concurrency: any; public watch: any; public deploy: any; - public generatingFiles: any; - public start: any; + public generatingFiles: Set; + public start: [number, number]; public args: any; public route: any; public log: any; - constructor(ctx, args) { + constructor(ctx: Hexo, args) { this.context = ctx; this.force = args.f || args.force; this.bail = args.b || args.bail; @@ -31,7 +32,7 @@ class Generater { this.start = process.hrtime(); this.args = args; } - generateFile(path) { + generateFile(path: string) { const publicDir = this.context.public_dir; const { generatingFiles } = this; const { route } = this.context; @@ -58,7 +59,7 @@ class Generater { generatingFiles.delete(path); }); } - writeFile(path, force?) { + writeFile(path: string, force?: boolean): Promise { const { route, log } = this.context; const publicDir = this.context.public_dir; const Cache = this.context.model('Cache'); @@ -99,7 +100,7 @@ class Generater { }); }); } - deleteFile(path) { + deleteFile(path: string): Promise { const { log } = this.context; const publicDir = this.context.public_dir; const dest = join(publicDir, path); @@ -126,7 +127,7 @@ class Generater { return dataStream.pipe(new PassThrough()); } - firstGenerate() { + firstGenerate(): Promise { const { concurrency } = this; const { route, log } = this.context; const publicDir = this.context.public_dir; @@ -171,7 +172,7 @@ class Generater { log.info('%d files generated in %s', count, cyan(interval)); }); } - execWatch() { + execWatch(): Promise { const { route, log } = this.context; return this.context.watch().then(() => this.firstGenerate()).then(() => { log.info('Hexo is watching for file changes. Press Ctrl+C to exit.'); diff --git a/lib/plugins/console/list/category.ts b/lib/plugins/console/list/category.ts index 0044ec3a0e..a1c6527c80 100644 --- a/lib/plugins/console/list/category.ts +++ b/lib/plugins/console/list/category.ts @@ -1,8 +1,9 @@ import { underline } from 'picocolors'; import table from 'text-table'; import { stringLength } from './common'; +import type Hexo from '../../../hexo'; -function listCategory() { +function listCategory(this: Hexo): void { const categories = this.model('Category'); const data = categories.sort({name: 1}).map(cate => [cate.name, String(cate.length)]); diff --git a/lib/plugins/console/list/common.ts b/lib/plugins/console/list/common.ts index 5adcb8022c..cc18685f5c 100644 --- a/lib/plugins/console/list/common.ts +++ b/lib/plugins/console/list/common.ts @@ -1,6 +1,6 @@ import strip from 'strip-ansi'; -export function stringLength(str) { +export function stringLength(str: string): number { str = strip(str); const len = str.length; diff --git a/lib/plugins/console/list/index.ts b/lib/plugins/console/list/index.ts index 7c3f084138..cd091ca272 100644 --- a/lib/plugins/console/list/index.ts +++ b/lib/plugins/console/list/index.ts @@ -4,6 +4,7 @@ import post from './post'; import route from './route'; import tag from './tag'; import category from './category'; +import type Hexo from '../../../hexo'; const store = { page, post, route, tag, category @@ -11,7 +12,7 @@ const store = { const alias = abbrev(Object.keys(store)); -function listConsole(args) { +function listConsole(this: Hexo, args) { const type = args._.shift(); // Display help message if user didn't input any arguments diff --git a/lib/plugins/console/list/page.ts b/lib/plugins/console/list/page.ts index d132231450..8b9de1bc09 100644 --- a/lib/plugins/console/list/page.ts +++ b/lib/plugins/console/list/page.ts @@ -1,8 +1,9 @@ import { magenta, underline, gray } from 'picocolors'; import table from 'text-table'; import { stringLength } from './common'; +import type Hexo from '../../../hexo'; -function listPage() { +function listPage(this: Hexo): void { const Page = this.model('Page'); const data = Page.sort({date: 1}).map(page => { diff --git a/lib/plugins/console/list/post.ts b/lib/plugins/console/list/post.ts index e4dca1a578..280b339df8 100644 --- a/lib/plugins/console/list/post.ts +++ b/lib/plugins/console/list/post.ts @@ -1,12 +1,13 @@ import { gray, magenta, underline } from 'picocolors'; import table from 'text-table'; import { stringLength } from './common'; +import type Hexo from '../../../hexo'; function mapName(item) { return item.name; } -function listPost() { +function listPost(this: Hexo): void { const Post = this.model('Post'); const data = Post.sort({published: -1, date: 1}).map(post => { diff --git a/lib/plugins/console/list/route.ts b/lib/plugins/console/list/route.ts index a29e4e4c54..2c15e217cc 100644 --- a/lib/plugins/console/list/route.ts +++ b/lib/plugins/console/list/route.ts @@ -1,6 +1,7 @@ import archy from 'archy'; +import type Hexo from '../../../hexo'; -function listRoute() { +function listRoute(this: Hexo): void { const routes = this.route.list().sort(); const tree = buildTree(routes); const nodes = buildNodes(tree); diff --git a/lib/plugins/console/list/tag.ts b/lib/plugins/console/list/tag.ts index 09c0a148df..4ce37595d1 100644 --- a/lib/plugins/console/list/tag.ts +++ b/lib/plugins/console/list/tag.ts @@ -1,8 +1,9 @@ import { magenta, underline } from 'picocolors'; import table from 'text-table'; import { stringLength } from './common'; +import type Hexo from '../../../hexo'; -function listTag() { +function listTag(this: Hexo): void { const Tag = this.model('Tag'); const data = Tag.sort({name: 1}).map(tag => [tag.name, String(tag.length), magenta(tag.path)]); diff --git a/lib/plugins/console/migrate.ts b/lib/plugins/console/migrate.ts index df341f6ed4..afe5dfb537 100644 --- a/lib/plugins/console/migrate.ts +++ b/lib/plugins/console/migrate.ts @@ -1,6 +1,7 @@ import { underline, magenta } from 'picocolors'; +import type Hexo from '../../hexo'; -function migrateConsole(args) { +function migrateConsole(this: Hexo, args) { // Display help message if user didn't input any arguments if (!args._.length) { return this.call('help', {_: ['migrate']}); diff --git a/lib/plugins/console/new.ts b/lib/plugins/console/new.ts index becbe1c625..64e3d83bd1 100644 --- a/lib/plugins/console/new.ts +++ b/lib/plugins/console/new.ts @@ -1,6 +1,7 @@ import tildify from 'tildify'; import { magenta } from 'picocolors'; import { basename } from 'path'; +import Hexo from '../../hexo'; const reservedKeys = { _: true, @@ -19,7 +20,7 @@ const reservedKeys = { silent: true }; -function newConsole(args) { +function newConsole(this: Hexo, args) { const path = args.p || args.path; let title; if (args._.length) { diff --git a/lib/plugins/console/publish.ts b/lib/plugins/console/publish.ts index f73d87ec55..6f97f9d175 100644 --- a/lib/plugins/console/publish.ts +++ b/lib/plugins/console/publish.ts @@ -1,7 +1,8 @@ import tildify from 'tildify'; import { magenta } from 'picocolors'; +import type Hexo from '../../hexo'; -function publishConsole(args) { +function publishConsole(this: Hexo, args) { // Display help message if user didn't input any arguments if (!args._.length) { return this.call('help', {_: ['publish']}); diff --git a/lib/plugins/console/render.ts b/lib/plugins/console/render.ts index 01cb57c581..c40230f728 100644 --- a/lib/plugins/console/render.ts +++ b/lib/plugins/console/render.ts @@ -3,8 +3,9 @@ import tildify from 'tildify'; import prettyHrtime from 'pretty-hrtime'; import { writeFile } from 'hexo-fs'; import { cyan, magenta } from 'picocolors'; +import type Hexo from '../../hexo'; -function renderConsole(args) { +function renderConsole(this: Hexo, args) { // Display help message if user didn't input any arguments if (!args._.length) { return this.call('help', {_: 'render'}); diff --git a/lib/plugins/filter/after_post_render/excerpt.ts b/lib/plugins/filter/after_post_render/excerpt.ts index ef1746a352..5694ce5dec 100644 --- a/lib/plugins/filter/after_post_render/excerpt.ts +++ b/lib/plugins/filter/after_post_render/excerpt.ts @@ -1,6 +1,6 @@ const rExcerpt = //i; -function excerptFilter(data) { +function excerptFilter(data): void { const { content } = data; if (typeof data.excerpt !== 'undefined') { diff --git a/lib/plugins/filter/after_post_render/external_link.ts b/lib/plugins/filter/after_post_render/external_link.ts index 0b116de8b4..dab35b3a9d 100644 --- a/lib/plugins/filter/after_post_render/external_link.ts +++ b/lib/plugins/filter/after_post_render/external_link.ts @@ -1,11 +1,12 @@ import { isExternalLink } from 'hexo-util'; +import type Hexo from '../../../hexo'; let EXTERNAL_LINK_POST_ENABLED = true; const rATag = /]+?\s+?)href=["']((?:https?:|\/\/)[^<>"']+)["'][^<>]*>/gi; const rTargetAttr = /target=/i; const rRelAttr = /rel=/i; const rRelStrAttr = /rel=["']([^<>"']*)["']/i; -function externalLinkFilter(data) { +function externalLinkFilter(this: Hexo, data): void { if (!EXTERNAL_LINK_POST_ENABLED) return; const { external_link, url } = this.config; @@ -16,7 +17,7 @@ function externalLinkFilter(data) { } data.content = data.content.replace(rATag, (str, href) => { - if (!isExternalLink(href, url, external_link.exclude) || rTargetAttr.test(str)) return str; + if (!isExternalLink(href, url, external_link.exclude as any) || rTargetAttr.test(str)) return str; if (rRelAttr.test(str)) { str = str.replace(rRelStrAttr, (relStr, rel) => { diff --git a/lib/plugins/filter/after_post_render/index.ts b/lib/plugins/filter/after_post_render/index.ts index 87bb8b433c..014eb0b6d0 100644 --- a/lib/plugins/filter/after_post_render/index.ts +++ b/lib/plugins/filter/after_post_render/index.ts @@ -1,4 +1,6 @@ -export = ctx => { +import type Hexo from '../../../hexo'; + +export = (ctx: Hexo) => { const { filter } = ctx.extend; filter.register('after_post_render', require('./external_link')); diff --git a/lib/plugins/filter/after_render/external_link.ts b/lib/plugins/filter/after_render/external_link.ts index a5d7218133..7a0168d842 100644 --- a/lib/plugins/filter/after_render/external_link.ts +++ b/lib/plugins/filter/after_render/external_link.ts @@ -1,4 +1,5 @@ import { isExternalLink } from 'hexo-util'; +import Hexo from '../../../hexo'; let EXTERNAL_LINK_SITE_ENABLED = true; const rATag = /]+?\s+?)href=["']((?:https?:|\/\/)[^<>"']+)["'][^<>]*>/gi; @@ -6,7 +7,7 @@ const rTargetAttr = /target=/i; const rRelAttr = /rel=/i; const rRelStrAttr = /rel=["']([^<>"']*)["']/i; -function externalLinkFilter(data) { +function externalLinkFilter(this: Hexo, data: string): string { if (!EXTERNAL_LINK_SITE_ENABLED) return; const { external_link, url } = this.config; @@ -17,7 +18,7 @@ function externalLinkFilter(data) { } return data.replace(rATag, (str, href) => { - if (!isExternalLink(href, url, external_link.exclude) || rTargetAttr.test(str)) return str; + if (!isExternalLink(href, url, external_link.exclude as any) || rTargetAttr.test(str)) return str; if (rRelAttr.test(str)) { str = str.replace(rRelStrAttr, (relStr, rel) => { diff --git a/lib/plugins/filter/after_render/index.ts b/lib/plugins/filter/after_render/index.ts index 509e95a0f8..a1eb862d5a 100644 --- a/lib/plugins/filter/after_render/index.ts +++ b/lib/plugins/filter/after_render/index.ts @@ -1,4 +1,6 @@ -export = ctx => { +import type Hexo from '../../../hexo'; + +export = (ctx: Hexo) => { const { filter } = ctx.extend; filter.register('after_render:html', require('./external_link')); diff --git a/lib/plugins/filter/after_render/meta_generator.ts b/lib/plugins/filter/after_render/meta_generator.ts index 4c04daee3a..7848f435ee 100644 --- a/lib/plugins/filter/after_render/meta_generator.ts +++ b/lib/plugins/filter/after_render/meta_generator.ts @@ -1,7 +1,9 @@ +import type Hexo from '../../../hexo'; + let NEED_INJECT = true; let META_GENERATOR_TAG; -function hexoMetaGeneratorInject(data) { +function hexoMetaGeneratorInject(this: Hexo, data: string): string { if (!NEED_INJECT) return; if (!this.config.meta_generator diff --git a/lib/plugins/filter/before_exit/index.ts b/lib/plugins/filter/before_exit/index.ts index ba3312749e..1443eed5cb 100644 --- a/lib/plugins/filter/before_exit/index.ts +++ b/lib/plugins/filter/before_exit/index.ts @@ -1,4 +1,6 @@ -export = ctx => { +import type Hexo from '../../../hexo'; + +export = (ctx: Hexo) => { const { filter } = ctx.extend; filter.register('before_exit', require('./save_database')); diff --git a/lib/plugins/filter/before_exit/save_database.ts b/lib/plugins/filter/before_exit/save_database.ts index 9aadce2ee8..9a853eb93e 100644 --- a/lib/plugins/filter/before_exit/save_database.ts +++ b/lib/plugins/filter/before_exit/save_database.ts @@ -1,4 +1,6 @@ -function saveDatabaseFilter() { +import type Hexo from '../../../hexo'; + +function saveDatabaseFilter(this: Hexo) { if (!this.env.init || !this._dbLoaded) return; return this.database.save().then(() => { diff --git a/lib/plugins/filter/before_generate/index.ts b/lib/plugins/filter/before_generate/index.ts index 288bb1651a..9c9565b9f4 100644 --- a/lib/plugins/filter/before_generate/index.ts +++ b/lib/plugins/filter/before_generate/index.ts @@ -1,4 +1,6 @@ -export = ctx => { +import type Hexo from '../../../hexo'; + +export = (ctx: Hexo) => { const { filter } = ctx.extend; filter.register('before_generate', require('./render_post')); diff --git a/lib/plugins/filter/before_generate/render_post.ts b/lib/plugins/filter/before_generate/render_post.ts index 539b5dadda..0a6cbe78d8 100644 --- a/lib/plugins/filter/before_generate/render_post.ts +++ b/lib/plugins/filter/before_generate/render_post.ts @@ -1,6 +1,7 @@ import Promise from 'bluebird'; +import type Hexo from '../../../hexo'; -function renderPostFilter() { +function renderPostFilter(this: Hexo): Promise<[any[], any[]]> { const renderPosts = model => { const posts = model.toArray().filter(post => post.content == null); diff --git a/lib/plugins/filter/before_post_render/backtick_code_block.ts b/lib/plugins/filter/before_post_render/backtick_code_block.ts index b9df3e60f2..7952169edd 100644 --- a/lib/plugins/filter/before_post_render/backtick_code_block.ts +++ b/lib/plugins/filter/before_post_render/backtick_code_block.ts @@ -1,3 +1,5 @@ +import type Hexo from '../../../hexo'; + const rBacktick = /^((?:[^\S\r\n]*>){0,3}[^\S\r\n]*)(`{3,}|~{3,})[^\S\r\n]*((?:.*?[^`\s])?)[^\S\r\n]*\n((?:[\s\S]*?\n)?)(?:(?:[^\S\r\n]*>){0,3}[^\S\r\n]*)\2[^\S\r\n]?(\n+|$)/gm; const rAllOptions = /([^\s]+)\s+(.+?)\s+(https?:\/\/\S+|\/\S+)\s*(.+)?/; const rLangCaption = /([^\s]+)\s*(.+)?/; @@ -11,8 +13,8 @@ interface Options { firstLineNumber?: string | number } -export = ctx => { - return function backtickCodeBlock(data) { +export = (ctx: Hexo) => { + return function backtickCodeBlock(data): void { const dataContent = data.content; if ((!dataContent.includes('```') && !dataContent.includes('~~~')) || !ctx.extend.highlight.query(ctx.config.syntax_highlighter)) return; diff --git a/lib/plugins/filter/before_post_render/index.ts b/lib/plugins/filter/before_post_render/index.ts index 07bde83da3..501b483df7 100644 --- a/lib/plugins/filter/before_post_render/index.ts +++ b/lib/plugins/filter/before_post_render/index.ts @@ -1,4 +1,6 @@ -export = ctx => { +import type Hexo from '../../../hexo'; + +export = (ctx: Hexo) => { const { filter } = ctx.extend; filter.register('before_post_render', require('./backtick_code_block')(ctx)); diff --git a/lib/plugins/filter/before_post_render/titlecase.ts b/lib/plugins/filter/before_post_render/titlecase.ts index 24e596ace8..bd149d3823 100644 --- a/lib/plugins/filter/before_post_render/titlecase.ts +++ b/lib/plugins/filter/before_post_render/titlecase.ts @@ -1,6 +1,6 @@ let titlecase; -function titlecaseFilter(data) { +function titlecaseFilter(data): void { if (!(typeof data.titlecase !== 'undefined' ? data.titlecase : this.config.titlecase) || !data.title) return; if (!titlecase) titlecase = require('titlecase'); diff --git a/lib/plugins/filter/new_post_path.ts b/lib/plugins/filter/new_post_path.ts index c06b946230..1eaa58c9f2 100644 --- a/lib/plugins/filter/new_post_path.ts +++ b/lib/plugins/filter/new_post_path.ts @@ -3,6 +3,7 @@ import moment from 'moment'; import Promise from 'bluebird'; import { createSha1Hash, Permalink } from 'hexo-util'; import { ensurePath } from 'hexo-fs'; +import type Hexo from '../../hexo'; let permalink; const reservedKeys = { @@ -22,7 +23,7 @@ interface Data { date?: Date; } -function newPostPathFilter(data: Data = {}, replace) { +function newPostPathFilter(this: Hexo, data: Data = {}, replace): Promise { const sourceDir = this.source_dir; const draftDir = join(sourceDir, '_drafts'); const postDir = join(sourceDir, '_posts'); diff --git a/lib/plugins/filter/post_permalink.ts b/lib/plugins/filter/post_permalink.ts index c715e67b5d..f066421330 100644 --- a/lib/plugins/filter/post_permalink.ts +++ b/lib/plugins/filter/post_permalink.ts @@ -1,8 +1,9 @@ import { createSha1Hash, Permalink, slugize } from 'hexo-util'; import { basename } from 'path'; +import type Hexo from '../../hexo'; let permalink; -function postPermalinkFilter(data) { +function postPermalinkFilter(this: Hexo, data) { const { config } = this; const { id, _id, slug, title, date, __permalink } = data; diff --git a/lib/plugins/filter/template_locals/i18n.ts b/lib/plugins/filter/template_locals/i18n.ts index 73367d8df0..a709fe8934 100644 --- a/lib/plugins/filter/template_locals/i18n.ts +++ b/lib/plugins/filter/template_locals/i18n.ts @@ -1,6 +1,7 @@ import { Pattern } from 'hexo-util'; +import type Hexo from '../../../hexo'; -function i18nLocalsFilter(locals) { +function i18nLocalsFilter(this: Hexo, locals): void { const { i18n } = this.theme; const { config } = this; const i18nDir = config.i18n_dir; diff --git a/lib/plugins/filter/template_locals/index.ts b/lib/plugins/filter/template_locals/index.ts index 663cb8ab3f..27dbf0caa4 100644 --- a/lib/plugins/filter/template_locals/index.ts +++ b/lib/plugins/filter/template_locals/index.ts @@ -1,4 +1,6 @@ -export = ctx => { +import type Hexo from '../../../hexo'; + +export = (ctx: Hexo) => { const { filter } = ctx.extend; filter.register('template_locals', require('./i18n')); diff --git a/lib/plugins/generator/asset.ts b/lib/plugins/generator/asset.ts index 722807c52e..074f497620 100644 --- a/lib/plugins/generator/asset.ts +++ b/lib/plugins/generator/asset.ts @@ -4,13 +4,14 @@ import Promise from 'bluebird'; import { extname } from 'path'; import { magenta } from 'picocolors'; import type warehouse from 'warehouse'; +import type Hexo from '../../hexo'; interface Data { modified: boolean; data?: () => any; } -const process = (name, ctx) => { +const process = (name: string, ctx: Hexo) => { // @ts-expect-error return Promise.filter(ctx.model(name).toArray(), (asset: warehouse['Schema']) => exists(asset.source).tap(exist => { // @ts-expect-error @@ -46,7 +47,7 @@ const process = (name, ctx) => { }); }; -function assetGenerator() { +function assetGenerator(this: Hexo): Promise { return Promise.all([ process('Asset', this), process('PostAsset', this) diff --git a/lib/plugins/helper/css.ts b/lib/plugins/helper/css.ts index 74ca0ba357..9dac2e3588 100644 --- a/lib/plugins/helper/css.ts +++ b/lib/plugins/helper/css.ts @@ -2,7 +2,7 @@ import { htmlTag, url_for } from 'hexo-util'; import moize from 'moize'; let relative_link = true; -function cssHelper(...args) { +function cssHelper(...args: any[]) { let result = '\n'; relative_link = this.config.relative_link; diff --git a/lib/plugins/helper/date.ts b/lib/plugins/helper/date.ts index b347770dc8..8d45b27147 100644 --- a/lib/plugins/helper/date.ts +++ b/lib/plugins/helper/date.ts @@ -1,13 +1,14 @@ import moment from 'moment-timezone'; const { isMoment } = moment; import moize from 'moize'; +import type Hexo from '../../hexo'; -const isDate = value => +const isDate = (value: moment.MomentInput | moment.Moment): boolean => typeof value === 'object' && value instanceof Date && !isNaN(value.getTime()); -function getMoment(date, lang, timezone) { +function getMoment(date: moment.MomentInput | moment.Moment, lang: string, timezone: string): moment.Moment { if (date == null) date = moment(); - if (!isMoment(date)) date = moment(isDate(date) ? date : new Date(date)); + if (!isMoment(date)) date = moment(isDate(date) ? date : new Date(date)); lang = _toMomentLocale(lang); if (lang) date = date.locale(lang); @@ -16,7 +17,7 @@ function getMoment(date, lang, timezone) { return date; } -function toISOString(date) { +function toISOString(date: string | number | Date | moment.Moment) { if (date == null) { return new Date().toISOString(); } @@ -25,22 +26,22 @@ function toISOString(date) { return date.toISOString(); } - return new Date(date).toISOString(); + return new Date(date as (string | number)).toISOString(); } -function dateHelper(date, format) { +function dateHelper(date: moment.Moment | moment.MomentInput, format: string) { const { config } = this; const moment = getMoment(date, getLanguage(this), config.timezone); return moment.format(format || config.date_format); } -function timeHelper(date, format) { +function timeHelper(date: moment.Moment | moment.MomentInput, format: string) { const { config } = this; const moment = getMoment(date, getLanguage(this), config.timezone); return moment.format(format || config.time_format); } -function fullDateHelper(date, format) { +function fullDateHelper(date: moment.Moment | moment.MomentInput, format: string) { if (format) { const moment = getMoment(date, getLanguage(this), this.config.timezone); return moment.format(format); @@ -49,13 +50,13 @@ function fullDateHelper(date, format) { return `${this.date(date)} ${this.time(date)}`; } -function relativeDateHelper(date) { +function relativeDateHelper(date: moment.Moment | moment.MomentInput) { const { config } = this; const moment = getMoment(date, getLanguage(this), config.timezone); return moment.fromNow(); } -function timeTagHelper(date, format) { +function timeTagHelper(date: string | number | Date | moment.Moment, format: string) { const { config } = this; return ``; } @@ -72,7 +73,7 @@ function getLanguage(ctx) { * * Moment defined locales: https://github.com/moment/moment/tree/master/locale */ -function _toMomentLocale(lang) { +function _toMomentLocale(lang: string) { if (lang === undefined) { return undefined; } diff --git a/lib/plugins/helper/debug.ts b/lib/plugins/helper/debug.ts index ba4a96983f..a097223bb9 100644 --- a/lib/plugins/helper/debug.ts +++ b/lib/plugins/helper/debug.ts @@ -1,12 +1,12 @@ import { inspect } from 'util'; // this format object as string, resolves circular reference -function inspectObject(object, options) { +function inspectObject(object: any, options: boolean) { return inspect(object, options); } // wrapper to log to console -function log(...args) { +function log(...args: any[]) { return Reflect.apply(console.log, null, args); } diff --git a/lib/plugins/helper/favicon_tag.ts b/lib/plugins/helper/favicon_tag.ts index 579c04379a..3c00b5dbd5 100644 --- a/lib/plugins/helper/favicon_tag.ts +++ b/lib/plugins/helper/favicon_tag.ts @@ -1,6 +1,6 @@ import { url_for } from 'hexo-util'; -function faviconTagHelper(path) { +function faviconTagHelper(path: string) { return ``; } diff --git a/lib/plugins/helper/feed_tag.ts b/lib/plugins/helper/feed_tag.ts index 8fccfc7738..bb8bca13ab 100644 --- a/lib/plugins/helper/feed_tag.ts +++ b/lib/plugins/helper/feed_tag.ts @@ -11,7 +11,7 @@ interface Options { type?: string; } -function makeFeedTag(path, options: Options = {}, configFeed?, configTitle?) { +function makeFeedTag(path: string, options: Options = {}, configFeed?: any, configTitle?: string) { const title = options.title || configTitle; if (path) { @@ -46,7 +46,7 @@ function makeFeedTag(path, options: Options = {}, configFeed?, configTitle?) { return ''; } -function feedTagHelper(path, options = {}) { +function feedTagHelper(path: string, options = {}) { const { config } = this; return moize.deep(makeFeedTag.bind(this))(path, options, config.feed, config.title); } diff --git a/lib/plugins/helper/format.ts b/lib/plugins/helper/format.ts index c9372b507e..745e9901ff 100644 --- a/lib/plugins/helper/format.ts +++ b/lib/plugins/helper/format.ts @@ -3,7 +3,7 @@ import titlecase from 'titlecase'; export {stripHTML as strip_html}; export {stripHTML}; -export function trim(str) { +export function trim(str: string) { return str.trim(); } diff --git a/lib/plugins/helper/fragment_cache.ts b/lib/plugins/helper/fragment_cache.ts index 1c38229e0c..91926b919f 100644 --- a/lib/plugins/helper/fragment_cache.ts +++ b/lib/plugins/helper/fragment_cache.ts @@ -1,7 +1,7 @@ - import { Cache } from 'hexo-util'; +import type Hexo from '../../hexo'; -export = ctx => { +export = (ctx: Hexo) => { const cache = new Cache(); // reset cache for watch mode diff --git a/lib/plugins/helper/full_url_for.ts b/lib/plugins/helper/full_url_for.ts index 4e77338082..9484f0e537 100644 --- a/lib/plugins/helper/full_url_for.ts +++ b/lib/plugins/helper/full_url_for.ts @@ -1,6 +1,6 @@ import { full_url_for } from 'hexo-util'; -export = function(path) { +export = function(path: string) { return full_url_for.call(this, path); } diff --git a/lib/plugins/helper/js.ts b/lib/plugins/helper/js.ts index 24ca0fca3d..8ca44e5c52 100644 --- a/lib/plugins/helper/js.ts +++ b/lib/plugins/helper/js.ts @@ -2,7 +2,7 @@ import { htmlTag, url_for } from 'hexo-util'; import moize from 'moize'; let relative_link = true; -function jsHelper(...args) { +function jsHelper(...args: any[]) { let result = '\n'; relative_link = this.config.relative_link; diff --git a/lib/plugins/helper/list_categories.ts b/lib/plugins/helper/list_categories.ts index ff248d6bf3..b2c1fd4e58 100644 --- a/lib/plugins/helper/list_categories.ts +++ b/lib/plugins/helper/list_categories.ts @@ -33,7 +33,7 @@ function listCategoriesHelper(categories, options) { const hierarchicalList = (level: number, parent?: any) => { let result = ''; - prepareQuery(parent).forEach((cat, i) => { + prepareQuery(parent).forEach(cat => { let child; if (!depth || level + 1 < depth) { child = hierarchicalList(level + 1, cat._id); diff --git a/lib/plugins/helper/mail_to.ts b/lib/plugins/helper/mail_to.ts index 90f9ef88c9..be102ef516 100644 --- a/lib/plugins/helper/mail_to.ts +++ b/lib/plugins/helper/mail_to.ts @@ -14,7 +14,7 @@ interface Attrs { [key: string]: string | boolean | null | undefined; } -function mailToHelper(path, text, options: Options = {}) { +function mailToHelper(path: string, text: string, options: Options = {}) { if (Array.isArray(path)) path = path.join(','); if (!text) text = path; diff --git a/lib/plugins/helper/markdown.ts b/lib/plugins/helper/markdown.ts index 956425f072..9465bbb671 100644 --- a/lib/plugins/helper/markdown.ts +++ b/lib/plugins/helper/markdown.ts @@ -1,4 +1,4 @@ -function markdownHelper(text, options) { +function markdownHelper(text: string, options) { return this.render(text, 'markdown', options); } diff --git a/lib/plugins/helper/open_graph.ts b/lib/plugins/helper/open_graph.ts index 9209eeda63..27d142f8bc 100644 --- a/lib/plugins/helper/open_graph.ts +++ b/lib/plugins/helper/open_graph.ts @@ -34,7 +34,7 @@ const localeToTerritory = moize.shallow(str => { } }); -const meta = (name, content, escape?: boolean) => { +const meta = (name: string, content: string | URL, escape?: boolean) => { if (escape !== false && typeof content === 'string') { content = escapeHTML(content); } @@ -43,7 +43,7 @@ const meta = (name, content, escape?: boolean) => { return `\n`; }; -const og = (name, content?: string, escape?: boolean) => { +const og = (name: string, content?: string, escape?: boolean) => { if (escape !== false && typeof content === 'string') { content = escapeHTML(content); } diff --git a/lib/plugins/helper/paginator.ts b/lib/plugins/helper/paginator.ts index 8d37c80739..429aff8b4d 100644 --- a/lib/plugins/helper/paginator.ts +++ b/lib/plugins/helper/paginator.ts @@ -1,12 +1,35 @@ import { htmlTag, url_for } from 'hexo-util'; +import type Hexo from '../../hexo'; -const createLink = (options, ctx) => { +interface Options { + base?: string; + current?: number; + format?: string; + total?: number; + end_size?: number; + mid_size?: number; + space?: string; + next_text?: string; + prev_text?: string; + prev_next?: boolean; + escape?: boolean; + page_class?: string; + current_class?: string; + space_class?: string; + prev_class?: string; + next_class?: string; + force_prev_next?: boolean; + show_all?: boolean; + transform?: (i: number) => any; +} + +const createLink = (options: Options, ctx: Hexo) => { const { base, format } = options; - return i => url_for.call(ctx, i === 1 ? base : base + format.replace('%d', i)); + return (i: number) => url_for.call(ctx, i === 1 ? base : base + format.replace('%d', String(i))); }; -const createPageTag = (options, ctx) => { +const createPageTag = (options: Options, ctx: Hexo) => { const link = createLink(options, ctx); const { current, @@ -16,7 +39,7 @@ const createPageTag = (options, ctx) => { current_class: currentClass } = options; - return i => { + return (i: number) => { if (i === current) { return htmlTag('span', { class: pageClass + ' ' + currentClass }, transform ? transform(i) : i, escape); } @@ -24,7 +47,7 @@ const createPageTag = (options, ctx) => { }; }; -const showAll = (tags, options, ctx) => { +const showAll = (tags: string[], options: Options, ctx: Hexo) => { const { total } = options; const pageLink = createPageTag(options, ctx); @@ -34,7 +57,7 @@ const showAll = (tags, options, ctx) => { } }; -const paginationPartShow = (tags, options, ctx) => { +const paginationPartShow = (tags, options, ctx: Hexo) => { const { current, total, @@ -86,27 +109,6 @@ const paginationPartShow = (tags, options, ctx) => { } }; -interface Options { - base?: string; - current?: number; - format?: string; - total?: number; - end_size?: number; - mid_size?: number; - space?: string; - next_text?: string; - prev_text?: string; - prev_next?: boolean; - escape?: boolean; - page_class?: string; - current_class?: string; - space_class?: string; - prev_class?: string; - next_class?: string; - force_prev_next?: boolean; - show_all?: boolean; -} - function paginatorHelper(options: Options = {}) { options = Object.assign({ base: this.page.base || '', diff --git a/lib/plugins/helper/partial.ts b/lib/plugins/helper/partial.ts index d548a58ba9..fac560117d 100644 --- a/lib/plugins/helper/partial.ts +++ b/lib/plugins/helper/partial.ts @@ -1,11 +1,12 @@ import { dirname, join } from 'path'; +import type Hexo from '../../hexo'; interface Options { cache?: boolean | string; only?: boolean; } -export = ctx => function partial(name, locals, options: Options = {}) { +export = (ctx: Hexo) => function partial(name: string, locals: any, options: Options = {}) { if (typeof name !== 'string') throw new TypeError('name must be a string!'); const { cache } = options; diff --git a/lib/plugins/helper/relative_url.ts b/lib/plugins/helper/relative_url.ts index 631a9946fd..62ebaa16e2 100644 --- a/lib/plugins/helper/relative_url.ts +++ b/lib/plugins/helper/relative_url.ts @@ -1,5 +1,5 @@ import { relative_url } from 'hexo-util'; -export = function(from, to) { +export = function(from: string, to: string) { return relative_url(from, to); } diff --git a/lib/plugins/helper/render.ts b/lib/plugins/helper/render.ts index 9f8473efb3..4d2d7414b3 100644 --- a/lib/plugins/helper/render.ts +++ b/lib/plugins/helper/render.ts @@ -1,4 +1,6 @@ -export = ctx => function render(text, engine, options) { +import type Hexo from '../../hexo'; + +export = (ctx: Hexo) => function render(text: string, engine: string, options:object = {}) { return ctx.render.renderSync({ text, engine diff --git a/lib/plugins/helper/toc.ts b/lib/plugins/helper/toc.ts index 4abec4d30b..02a4b1ad7d 100644 --- a/lib/plugins/helper/toc.ts +++ b/lib/plugins/helper/toc.ts @@ -13,7 +13,7 @@ interface Options { list_number?: boolean; } -function tocHelper(str, options: Options = {}) { +function tocHelper(str: string, options: Options = {}) { options = Object.assign({ min_depth: 1, max_depth: 6, diff --git a/lib/plugins/helper/url_for.ts b/lib/plugins/helper/url_for.ts index 49e7a5f124..e7c58dd05d 100644 --- a/lib/plugins/helper/url_for.ts +++ b/lib/plugins/helper/url_for.ts @@ -1,5 +1,9 @@ import { url_for } from 'hexo-util'; -export = function(path, options) { +interface Options { + relative?: boolean +} + +export = function(path: string, options: Options = {}) { return url_for.call(this, path, options); } diff --git a/lib/plugins/processor/asset.ts b/lib/plugins/processor/asset.ts index 9693bbaeb5..c56ff62052 100644 --- a/lib/plugins/processor/asset.ts +++ b/lib/plugins/processor/asset.ts @@ -4,8 +4,11 @@ import { parse as yfm } from 'hexo-front-matter'; import { extname, relative } from 'path'; import { Pattern } from 'hexo-util'; import { magenta } from 'picocolors'; +import type { _File } from '../../box'; +import type Hexo from '../../hexo'; +import type { Stats } from 'fs'; -export = ctx => { +export = (ctx: Hexo) => { return { pattern: new Pattern(path => { if (isExcludedFile(path, ctx.config)) return; @@ -15,7 +18,7 @@ export = ctx => { }; }), - process: function assetProcessor(file) { + process: function assetProcessor(file: _File) { if (file.params.renderable) { return processPage(ctx, file); } @@ -25,7 +28,7 @@ export = ctx => { }; }; -function processPage(ctx, file) { +function processPage(ctx: Hexo, file: _File) { const Page = ctx.model('Page'); const { path } = file; const doc = Page.findOne({source: path}); @@ -48,7 +51,7 @@ function processPage(ctx, file) { return Promise.all([ file.stat(), file.read() - ]).spread((stats, content) => { + ]).spread((stats: Stats, content: string) => { const data = yfm(content); const output = ctx.render.getOutput(path); @@ -105,7 +108,7 @@ function processPage(ctx, file) { }); } -function processAsset(ctx, file) { +function processAsset(ctx: Hexo, file: _File) { const id = relative(ctx.base_dir, file.source).replace(/\\/g, '/'); const Asset = ctx.model('Asset'); const doc = Asset.findById(id); diff --git a/lib/plugins/processor/common.ts b/lib/plugins/processor/common.ts index c981536598..fa5202b633 100644 --- a/lib/plugins/processor/common.ts +++ b/lib/plugins/processor/common.ts @@ -4,21 +4,21 @@ import micromatch from 'micromatch'; const DURATION_MINUTE = 1000 * 60; -function isMatch(path, patterns) { +function isMatch(path: string, patterns: string| string[]) { if (!patterns) return false; return micromatch.isMatch(path, patterns); } -function isTmpFile(path) { +function isTmpFile(path: string) { return path.endsWith('%') || path.endsWith('~'); } -function isHiddenFile(path) { +function isHiddenFile(path: string) { return /(^|\/)[_.]/.test(path); } -function isExcludedFile(path, config) { +function isExcludedFile(path: string, config) { if (isTmpFile(path)) return true; if (isMatch(path, config.exclude)) return true; if (isHiddenFile(path) && !isMatch(path, config.include)) return true; @@ -34,7 +34,7 @@ export {isTmpFile}; export {isHiddenFile}; export {isExcludedFile}; -export function toDate(date) { +export function toDate(date: string | number | Date) { if (!date || moment.isMoment(date)) return date; if (!(date instanceof Date)) { @@ -46,7 +46,7 @@ export function toDate(date) { return date; } -export function timezone(date, timezone) { +export function timezone(date: Date, timezone: string) { if (moment.isMoment(date)) date = date.toDate(); const offset = date.getTimezoneOffset(); diff --git a/lib/plugins/processor/data.ts b/lib/plugins/processor/data.ts index 7757e7c99c..6db47b3097 100644 --- a/lib/plugins/processor/data.ts +++ b/lib/plugins/processor/data.ts @@ -1,10 +1,12 @@ import { Pattern } from 'hexo-util'; import { extname } from 'path'; +import type Hexo from '../../hexo'; +import type { _File } from '../../box'; -export = ctx => ({ +export = (ctx: Hexo) => ({ pattern: new Pattern('_data/*path'), - process: function dataProcessor(file) { + process: function dataProcessor(file: _File) { const Data = ctx.model('Data'); const { path } = file.params; const id = path.substring(0, path.length - extname(path).length); diff --git a/lib/plugins/processor/post.ts b/lib/plugins/processor/post.ts index 9c61a561b8..c9ec3a1a86 100644 --- a/lib/plugins/processor/post.ts +++ b/lib/plugins/processor/post.ts @@ -5,6 +5,9 @@ import { extname, join } from 'path'; import { stat, listDir } from 'hexo-fs'; import { slugize, Pattern, Permalink } from 'hexo-util'; import { magenta } from 'picocolors'; +import type { _File } from '../../box'; +import type Hexo from '../../hexo'; +import type { Stats } from 'fs'; const postDir = '_posts/'; const draftDir = '_drafts/'; @@ -20,7 +23,7 @@ const preservedKeys = { hash: true }; -export = ctx => { +export = (ctx: Hexo) => { return { pattern: new Pattern(path => { if (isTmpFile(path)) return; @@ -62,7 +65,7 @@ export = ctx => { }; }; -function processPost(ctx, file) { +function processPost(ctx: Hexo, file: _File) { const Post = ctx.model('Post'); const { path } = file.params; const doc = Post.findOne({source: file.path}); @@ -86,7 +89,7 @@ function processPost(ctx, file) { return Promise.all([ file.stat(), file.read() - ]).spread((stats, content) => { + ]).spread((stats: Stats, content: string) => { const data = yfm(content); const info = parseFilename(config.new_post_name, path); const keys = Object.keys(info); @@ -179,7 +182,7 @@ function processPost(ctx, file) { ])); } -function parseFilename(config, path) { +function parseFilename(config: string, path: string) { config = config.substring(0, config.length - extname(config).length); path = path.substring(0, path.length - extname(path).length); @@ -212,7 +215,7 @@ function parseFilename(config, path) { }; } -function scanAssetDir(ctx, post) { +function scanAssetDir(ctx: Hexo, post) { if (!ctx.config.post_asset_folder) return; const assetDir = post.asset_dir; @@ -246,7 +249,7 @@ function scanAssetDir(ctx, post) { }); } -function shouldSkipAsset(ctx, post, asset) { +function shouldSkipAsset(ctx: Hexo, post, asset) { if (!ctx._showDrafts()) { if (post.published === false && asset) { // delete existing draft assets if draft posts are hidden @@ -261,7 +264,7 @@ function shouldSkipAsset(ctx, post, asset) { return asset !== undefined; // skip already existing assets } -function processAsset(ctx, file) { +function processAsset(ctx: Hexo, file: _File) { const PostAsset = ctx.model('PostAsset'); const Post = ctx.model('Post'); const id = file.source.substring(ctx.base_dir.length).replace(/\\/g, '/'); diff --git a/lib/plugins/renderer/json.ts b/lib/plugins/renderer/json.ts index 7c87cf6ecb..c5d02377f9 100644 --- a/lib/plugins/renderer/json.ts +++ b/lib/plugins/renderer/json.ts @@ -1,4 +1,6 @@ -function jsonRenderer(data) { +import type { StoreFunctionData } from '../../extend/renderer'; + +function jsonRenderer(data: StoreFunctionData) { return JSON.parse(data.text); } diff --git a/lib/plugins/renderer/nunjucks.ts b/lib/plugins/renderer/nunjucks.ts index 1ba4ba0205..ccb0281346 100644 --- a/lib/plugins/renderer/nunjucks.ts +++ b/lib/plugins/renderer/nunjucks.ts @@ -1,6 +1,7 @@ -import nunjucks from 'nunjucks'; +import nunjucks, { Environment } from 'nunjucks'; import { readFileSync } from 'hexo-fs'; import { dirname } from 'path'; +import type { StoreFunctionData } from '../../extend/renderer'; function toArray(value) { if (Array.isArray(value)) { @@ -36,13 +37,13 @@ const nunjucksCfg = { lstripBlocks: false }; -const nunjucksAddFilter = env => { +const nunjucksAddFilter = (env: Environment) => { env.addFilter('toarray', toArray); env.addFilter('safedump', safeJsonStringify); }; -function njkCompile(data) { - let env; +function njkCompile(data: StoreFunctionData) { + let env: Environment; if (data.path) { env = nunjucks.configure(dirname(data.path), nunjucksCfg); } else { @@ -52,14 +53,14 @@ function njkCompile(data) { const text = 'text' in data ? data.text : readFileSync(data.path); - return nunjucks.compile(text, env, data.path); + return nunjucks.compile(text as string, env, data.path); } -function njkRenderer(data, locals) { +function njkRenderer(data: StoreFunctionData, locals: object) { return njkCompile(data).render(locals); } -njkRenderer.compile = data => { +njkRenderer.compile = (data: StoreFunctionData) => { // Need a closure to keep the compiled template. return locals => njkCompile(data).render(locals); }; diff --git a/lib/plugins/renderer/plain.ts b/lib/plugins/renderer/plain.ts index e1aa47f2df..99c35a1c1c 100644 --- a/lib/plugins/renderer/plain.ts +++ b/lib/plugins/renderer/plain.ts @@ -1,4 +1,6 @@ -function plainRenderer(data) { +import type { StoreFunctionData } from '../../extend/renderer'; + +function plainRenderer(data: StoreFunctionData) { return data.text; } diff --git a/lib/plugins/renderer/yaml.ts b/lib/plugins/renderer/yaml.ts index a8f0af4a34..fd460d14a0 100644 --- a/lib/plugins/renderer/yaml.ts +++ b/lib/plugins/renderer/yaml.ts @@ -1,6 +1,7 @@ import yaml from 'js-yaml'; import { escape } from 'hexo-front-matter'; import logger from 'hexo-log'; +import type { StoreFunctionData } from '../../extend/renderer'; let schema = {}; // FIXME: workaround for https://github.com/hexojs/hexo/issues/4917 @@ -14,7 +15,7 @@ try { } } -function yamlHelper(data) { +function yamlHelper(data: StoreFunctionData) { return yaml.load(escape(data.text), { schema }); } diff --git a/lib/plugins/tag/asset_img.ts b/lib/plugins/tag/asset_img.ts index e608b499ff..8a9941b74a 100644 --- a/lib/plugins/tag/asset_img.ts +++ b/lib/plugins/tag/asset_img.ts @@ -1,5 +1,6 @@ import img from './img'; import { encodeURL } from 'hexo-util'; +import type Hexo from '../../hexo'; /** * Asset image tag @@ -7,10 +8,10 @@ import { encodeURL } from 'hexo-util'; * Syntax: * {% asset_img [class names] slug [width] [height] [title text [alt text]]%} */ -export = ctx => { +export = (ctx: Hexo) => { const PostAsset = ctx.model('PostAsset'); - return function assetImgTag(args) { + return function assetImgTag(args: string[]) { const len = args.length; // Find image URL diff --git a/lib/plugins/tag/asset_link.ts b/lib/plugins/tag/asset_link.ts index eb07087625..f132730db2 100644 --- a/lib/plugins/tag/asset_link.ts +++ b/lib/plugins/tag/asset_link.ts @@ -1,4 +1,5 @@ import { encodeURL, escapeHTML } from 'hexo-util'; +import type Hexo from '../../hexo'; /** * Asset link tag @@ -6,10 +7,10 @@ import { encodeURL, escapeHTML } from 'hexo-util'; * Syntax: * {% asset_link slug [title] [escape] %} */ -export = ctx => { +export = (ctx: Hexo) => { const PostAsset = ctx.model('PostAsset'); - return function assetLinkTag(args) { + return function assetLinkTag(args: string[]) { const slug = args.shift(); if (!slug) return; diff --git a/lib/plugins/tag/asset_path.ts b/lib/plugins/tag/asset_path.ts index 7242e3ce73..60e4c31746 100644 --- a/lib/plugins/tag/asset_path.ts +++ b/lib/plugins/tag/asset_path.ts @@ -1,4 +1,5 @@ import { encodeURL } from 'hexo-util'; +import type Hexo from '../../hexo'; /** * Asset path tag @@ -6,10 +7,10 @@ import { encodeURL } from 'hexo-util'; * Syntax: * {% asset_path slug %} */ -export = ctx => { +export = (ctx: Hexo) => { const PostAsset = ctx.model('PostAsset'); - return function assetPathTag(args) { + return function assetPathTag(args: string[]) { const slug = args.shift(); if (!slug) return; diff --git a/lib/plugins/tag/blockquote.ts b/lib/plugins/tag/blockquote.ts index 1f99e67c1a..d523e6b994 100644 --- a/lib/plugins/tag/blockquote.ts +++ b/lib/plugins/tag/blockquote.ts @@ -1,6 +1,7 @@ // Based on: https://raw.github.com/imathis/octopress/master/plugins/blockquote.rb import titlecase from 'titlecase'; +import type Hexo from '../../hexo'; const rFullCiteWithTitle = /(\S.*)\s+(https?:\/\/\S+)\s+(.+)/i; const rFullCite = /(\S.*)\s+(https?:\/\/\S+)/i; @@ -10,7 +11,7 @@ const rAuthorTitle = /([^,]+),\s*([^,]+)/; * @param {string[]} args * @param {Hexo} ctx */ -const parseFooter = (args, ctx) => { +const parseFooter = (args: string[], ctx: Hexo) => { const str = args.join(' '); if (!str) return ''; @@ -55,7 +56,7 @@ const parseFooter = (args, ctx) => { * {% endblockquote %} */ -export = ctx => function blockquoteTag(args, content) { +export = (ctx: Hexo) => function blockquoteTag(args: string[], content: string) { const footer = parseFooter(args, ctx); let result = '
'; diff --git a/lib/plugins/tag/code.ts b/lib/plugins/tag/code.ts index 266bda70e2..e56e2122c4 100644 --- a/lib/plugins/tag/code.ts +++ b/lib/plugins/tag/code.ts @@ -1,23 +1,13 @@ // Based on: https://raw.github.com/imathis/octopress/master/plugins/code_block.rb import { escapeHTML } from 'hexo-util'; +import type Hexo from '../../hexo'; +import type { HighlightOptions } from '../../extend/syntax_highlight'; const rCaptionUrlTitle = /(\S[\S\s]*)\s+(https?:\/\/\S+)\s+(.+)/i; const rCaptionUrl = /(\S[\S\s]*)\s+(https?:\/\/\S+)/i; const rCaption = /\S[\S\s]*/; -interface Options { - lang: string; - language_attr: boolean; - firstLine: number; - caption: string; - line_number: boolean; - line_threshold: number; - mark: number[]; - wrap: boolean; - lines_length?: number; -} - /** * Code block tag * Syntax: @@ -37,11 +27,11 @@ interface Options { * @returns {String} Code snippet with code highlighting */ -function parseArgs(args): Options { +function parseArgs(args: string[]): HighlightOptions { const _else = []; const len = args.length; - let lang, language_attr, - line_number, line_threshold, wrap; + let lang: string, language_attr: boolean, + line_number: boolean, line_threshold: number, wrap: boolean; let firstLine = 1; const mark = []; for (let i = 0; i < len; i++) { @@ -63,10 +53,10 @@ function parseArgs(args): Options { line_number = value === 'true'; break; case 'line_threshold': - if (!isNaN(value)) line_threshold = +value; + if (!isNaN(Number(value))) line_threshold = +value; break; case 'first_line': - if (!isNaN(value)) firstLine = +value; + if (!isNaN(Number(value))) firstLine = +value; break; case 'wrap': wrap = value === 'true'; @@ -88,7 +78,7 @@ function parseArgs(args): Options { mark.push(a); } } - if (!isNaN(cur)) mark.push(+cur); + if (!isNaN(Number(cur))) mark.push(+cur); } break; } @@ -126,14 +116,14 @@ function parseArgs(args): Options { }; } -export = ctx => function codeTag(args, content) { +export = (ctx: Hexo) => function codeTag(args: string[], content: string) { // If neither highlight.js nor prism.js is enabled, return escaped code directly if (!ctx.extend.highlight.query(ctx.config.syntax_highlighter)) { return `
${escapeHTML(content)}
`; } - let index; + let index: number; let enableHighlight = true; if ((index = args.findIndex(item => item.startsWith('highlight:'))) !== -1) { diff --git a/lib/plugins/tag/full_url_for.ts b/lib/plugins/tag/full_url_for.ts index 6dd2ff76b8..887b2f07c7 100644 --- a/lib/plugins/tag/full_url_for.ts +++ b/lib/plugins/tag/full_url_for.ts @@ -1,4 +1,5 @@ import { full_url_for, htmlTag } from 'hexo-util'; +import type Hexo from '../../hexo'; /** * Full url for tag @@ -6,7 +7,7 @@ import { full_url_for, htmlTag } from 'hexo-util'; * Syntax: * {% full_url_for text path %} */ -export = ctx => { +export = (ctx: Hexo) => { return function fullUrlForTag([text, path]) { const url = full_url_for.call(ctx, path); const attrs = { diff --git a/lib/plugins/tag/iframe.ts b/lib/plugins/tag/iframe.ts index f1e6b2663d..9597a809a7 100644 --- a/lib/plugins/tag/iframe.ts +++ b/lib/plugins/tag/iframe.ts @@ -7,7 +7,7 @@ import { htmlTag } from 'hexo-util'; * {% iframe url [width] [height] %} */ -function iframeTag(args) { +function iframeTag(args: string[]) { const src = args[0]; const width = args[1] && args[1] !== 'default' ? args[1] : '100%'; const height = args[2] && args[2] !== 'default' ? args[2] : '300'; diff --git a/lib/plugins/tag/img.ts b/lib/plugins/tag/img.ts index 22e4970020..2e8b1c8d29 100644 --- a/lib/plugins/tag/img.ts +++ b/lib/plugins/tag/img.ts @@ -1,4 +1,5 @@ import { htmlTag, url_for } from 'hexo-util'; +import type Hexo from '../../hexo'; const rUrl = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[.!/\\w]*))?)/; const rMetaDoubleQuote = /"?([^"]+)?"?/; @@ -10,9 +11,9 @@ const rMetaSingleQuote = /'?([^']+)?'?/; * Syntax: * {% img [class names] /path/to/image [width] [height] [title text [alt text]] %} */ -export = ctx => { +export = (ctx: Hexo) => { - return function imgTag(args) { + return function imgTag(args: string[]) { const classes = []; let src, width, height, title, alt; diff --git a/lib/plugins/tag/include_code.ts b/lib/plugins/tag/include_code.ts index 8457c75294..78edbe1bdb 100644 --- a/lib/plugins/tag/include_code.ts +++ b/lib/plugins/tag/include_code.ts @@ -1,5 +1,6 @@ import { exists, readFile } from 'hexo-fs'; import { basename, extname, join, posix } from 'path'; +import type Hexo from '../../hexo'; const rCaptionTitleFile = /(.*)?(?:\s+|^)(\/*\S+)/; const rLang = /\s*lang:(\w+)/i; @@ -13,7 +14,7 @@ const rTo = /\s*to:(\d+)/i; * {% include_code [title] [lang:language] path/to/file %} */ -export = ctx => function includeCodeTag(args) { +export = (ctx: Hexo) => function includeCodeTag(args: string[]) { let codeDir = ctx.config.code_dir; let arg = args.join(' '); diff --git a/lib/plugins/tag/index.ts b/lib/plugins/tag/index.ts index b2306d36e4..8f3d303db2 100644 --- a/lib/plugins/tag/index.ts +++ b/lib/plugins/tag/index.ts @@ -52,7 +52,7 @@ export default (ctx: Hexo) => { // Use WeakMap to track different ctx (in case there is any) const moized = new WeakMap(); -export function postFindOneFactory(ctx) { +export function postFindOneFactory(ctx: Hexo) { if (moized.has(ctx)) { return moized.get(ctx); } @@ -66,7 +66,7 @@ export function postFindOneFactory(ctx) { return moizedPostFindOne; } -function createPostFindOne(ctx) { +function createPostFindOne(ctx: Hexo) { const Post = ctx.model('Post'); return Post.findOne.bind(Post); } diff --git a/lib/plugins/tag/link.ts b/lib/plugins/tag/link.ts index 0df202b574..b0afbacfcd 100644 --- a/lib/plugins/tag/link.ts +++ b/lib/plugins/tag/link.ts @@ -9,7 +9,7 @@ const rUrl = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:ww * {% link text url [external] [title] %} */ -function linkTag(args, content) { +function linkTag(args: string[]) { let url = ''; const text = []; let external = false; diff --git a/lib/plugins/tag/post_link.ts b/lib/plugins/tag/post_link.ts index 782714a1d2..577b1319ef 100644 --- a/lib/plugins/tag/post_link.ts +++ b/lib/plugins/tag/post_link.ts @@ -1,5 +1,6 @@ import { encodeURL, escapeHTML } from 'hexo-util'; import { postFindOneFactory } from './'; +import type Hexo from '../../hexo'; /** * Post link tag @@ -7,8 +8,8 @@ import { postFindOneFactory } from './'; * Syntax: * {% post_link slug | title [title] [escape] %} */ -export = ctx => { - return function postLinkTag(args) { +export = (ctx: Hexo) => { + return function postLinkTag(args: string[]) { const slug = args.shift(); if (!slug) { throw new Error(`Post not found: "${slug}" doesn't exist for {% post_link %}`); diff --git a/lib/plugins/tag/post_path.ts b/lib/plugins/tag/post_path.ts index e9aec212f2..fdc33eccab 100644 --- a/lib/plugins/tag/post_path.ts +++ b/lib/plugins/tag/post_path.ts @@ -1,5 +1,6 @@ import { encodeURL } from 'hexo-util'; import { postFindOneFactory } from './'; +import type Hexo from '../../hexo'; /** * Post path tag @@ -7,8 +8,8 @@ import { postFindOneFactory } from './'; * Syntax: * {% post_path slug | title %} */ -export = ctx => { - return function postPathTag(args) { +export = (ctx: Hexo) => { + return function postPathTag(args: any[]) { const slug = args.shift(); if (!slug) return; diff --git a/lib/plugins/tag/pullquote.ts b/lib/plugins/tag/pullquote.ts index 1235a26d9e..89bf01697a 100644 --- a/lib/plugins/tag/pullquote.ts +++ b/lib/plugins/tag/pullquote.ts @@ -1,3 +1,5 @@ +import type Hexo from '../../hexo'; + /** * Pullquote tag * @@ -6,7 +8,7 @@ * Quote string * {% endpullquote %} */ -export = ctx => function pullquoteTag(args, content) { +export = (ctx: Hexo) => function pullquoteTag(args: string[], content: string) { args.unshift('pullquote'); const result = ctx.render.renderSync({text: content, engine: 'markdown'}); diff --git a/lib/plugins/tag/url_for.ts b/lib/plugins/tag/url_for.ts index 6fb3750886..a417fa6219 100644 --- a/lib/plugins/tag/url_for.ts +++ b/lib/plugins/tag/url_for.ts @@ -1,4 +1,5 @@ import { url_for, htmlTag } from 'hexo-util'; +import type Hexo from '../../hexo'; /** * Url for tag @@ -6,7 +7,7 @@ import { url_for, htmlTag } from 'hexo-util'; * Syntax: * {% url_for text path [relative] %} */ -export = ctx => { +export = (ctx: Hexo) => { return function urlForTag([text, path, relative]) { const url = url_for.call(ctx, path, relative ? { relative: relative !== 'false' } : undefined); const attrs = { diff --git a/lib/theme/index.ts b/lib/theme/index.ts index d37cd281b5..aff5a74711 100644 --- a/lib/theme/index.ts +++ b/lib/theme/index.ts @@ -6,14 +6,16 @@ import { config } from './processors/config'; import { i18n } from './processors/i18n'; import { source } from './processors/source'; import { view } from './processors/view'; +import type Hexo from '../hexo'; class Theme extends Box { public config: any; public views: any; - public i18n: any; + public i18n: I18n; public View: any; + public processors: any[]; - constructor(ctx, options?) { + constructor(ctx: Hexo, options?) { super(ctx, ctx.theme_dir, options); this.config = {}; @@ -46,7 +48,7 @@ class Theme extends Box { _View.prototype._helper = ctx.extend.helper; } - getView(path) { + getView(path: string) { // Replace backslashes on Windows path = path.replace(/\\/g, '/'); @@ -63,7 +65,7 @@ class Theme extends Box { return views[Object.keys(views)[0]]; } - setView(path, data) { + setView(path: string, data) { const ext = extname(path); const name = path.substring(0, path.length - ext.length); this.views[name] = this.views[name] || {}; @@ -72,7 +74,7 @@ class Theme extends Box { views[ext] = new this.View(path, data); } - removeView(path) { + removeView(path: string) { const ext = extname(path); const name = path.substring(0, path.length - ext.length); const views = this.views[name]; diff --git a/lib/theme/processors/config.ts b/lib/theme/processors/config.ts index 64f65e2c28..c37f3ed13a 100644 --- a/lib/theme/processors/config.ts +++ b/lib/theme/processors/config.ts @@ -1,13 +1,15 @@ import { Pattern } from 'hexo-util'; +import type { _File } from '../../box'; +import Theme from '..'; -function process(file) { +function process(file: _File) { if (file.type === 'delete') { - file.box.config = {}; + (file.box as Theme).config = {}; return; } return file.render().then(result => { - file.box.config = result; + (file.box as Theme).config = result; this.log.debug('Theme config loaded.'); }).catch(err => { this.log.error('Theme config load failed.'); diff --git a/lib/theme/processors/i18n.ts b/lib/theme/processors/i18n.ts index ce955eb8a4..af2db9be95 100644 --- a/lib/theme/processors/i18n.ts +++ b/lib/theme/processors/i18n.ts @@ -1,11 +1,13 @@ import { Pattern } from 'hexo-util'; import { extname } from 'path'; +import type { _File } from '../../box'; +import type Theme from '..'; -function process(file) { +function process(file: _File) { const { path } = file.params; const ext = extname(path); const name = path.substring(0, path.length - ext.length); - const { i18n } = file.box; + const { i18n } = (file.box as Theme); if (file.type === 'delete') { i18n.remove(name); diff --git a/lib/theme/processors/source.ts b/lib/theme/processors/source.ts index 40915fae47..ac8c21a1fe 100644 --- a/lib/theme/processors/source.ts +++ b/lib/theme/processors/source.ts @@ -1,7 +1,8 @@ import { Pattern } from 'hexo-util'; import * as common from '../../plugins/processor/common'; +import type { _File } from '../../box'; -function process(file) { +function process(file: _File) { const Asset = this.model('Asset'); const id = file.source.substring(this.base_dir.length).replace(/\\/g, '/'); const { path } = file.params; diff --git a/lib/theme/processors/view.ts b/lib/theme/processors/view.ts index c4011564e2..c127d02e7c 100644 --- a/lib/theme/processors/view.ts +++ b/lib/theme/processors/view.ts @@ -1,15 +1,17 @@ import { Pattern } from 'hexo-util'; +import type { _File } from '../../box'; +import type Theme from '..'; -function process(file) { +function process(file: _File) { const { path } = file.params; if (file.type === 'delete') { - file.box.removeView(path); + (file.box as Theme).removeView(path); return; } return file.read().then(result => { - file.box.setView(path, result); + (file.box as Theme).setView(path, result); }); } diff --git a/lib/theme/view.ts b/lib/theme/view.ts index f2b2234d4f..af4c75be62 100644 --- a/lib/theme/view.ts +++ b/lib/theme/view.ts @@ -1,8 +1,10 @@ import { dirname, extname, join } from 'path'; import { parse as yfm } from 'hexo-front-matter'; import Promise from 'bluebird'; +import type Theme from '.'; +import type Render from '../hexo/render'; -const assignIn = (target, ...sources) => { +const assignIn = (target: any, ...sources: any[]) => { const length = sources.length; if (length < 1 || target == null) return target; @@ -21,18 +23,16 @@ class Options { } class View { - public path: any; + public path: string; public source: any; - public _theme: any; + public _theme: Theme; public data: any; public _compiled: any; public _compiledSync: any; public _helper: any; - public _render: any; - public layout: any; - public _content: any; + public _render: Render; - constructor(path, data) { + constructor(path: string, data) { this.path = path; this.source = join(this._theme.base, 'layout', path); this.data = typeof data === 'string' ? yfm(data) : data; @@ -106,7 +106,7 @@ class View { return locals; } - _resolveLayout(name) { + _resolveLayout(name: string) { // Relative path const layoutPath = join(dirname(this.path), name); let layoutView = this._theme.getView(layoutPath); @@ -128,7 +128,7 @@ class View { text: this.data._content }; - function buildFilterArguments(result) { + function buildFilterArguments(result: any): [string, any, any] { const output = render.getOutput(ext) || ext; return [ `after_render:${output}`, diff --git a/lib/types.ts b/lib/types.ts new file mode 100644 index 0000000000..ea6313c253 --- /dev/null +++ b/lib/types.ts @@ -0,0 +1 @@ +type NodeJSLikeCallback = (err: E, result?: R) => void diff --git a/package.json b/package.json index a9681ab722..f9cfc7ad34 100644 --- a/package.json +++ b/package.json @@ -66,12 +66,13 @@ "warehouse": "^5.0.0" }, "devDependencies": { - "0x": "^5.1.2", "@types/bluebird": "^3.5.37", "@types/node": "^18.11.8", "@types/nunjucks": "^3.2.2", + "@types/text-table": "^0.2.4", "@typescript-eslint/eslint-plugin": "^5.41.0", "@typescript-eslint/parser": "^5.41.0", + "0x": "^5.1.2", "c8": "^8.0.0", "chai": "^4.3.6", "cheerio": "0.22.0", diff --git a/test/scripts/box/box.js b/test/scripts/box/box.js index 71548cceeb..4aaebd8698 100644 --- a/test/scripts/box/box.js +++ b/test/scripts/box/box.js @@ -9,7 +9,7 @@ const { spy, match, assert: sinonAssert } = require('sinon'); describe('Box', () => { const Hexo = require('../../../dist/hexo'); const baseDir = join(__dirname, 'box_tmp'); - const Box = require('../../../dist/box'); + const Box = require('../../../dist/box').default; const newBox = (path, config) => { const hexo = new Hexo(baseDir, { silent: true }); diff --git a/test/scripts/box/file.js b/test/scripts/box/file.js index e019d913cc..f2fe533b4c 100644 --- a/test/scripts/box/file.js +++ b/test/scripts/box/file.js @@ -7,7 +7,7 @@ const { load } = require('js-yaml'); describe('File', () => { const Hexo = require('../../../dist/hexo'); const hexo = new Hexo(__dirname); - const Box = require('../../../dist/box'); + const Box = require('../../../dist/box').default; const box = new Box(hexo, join(hexo.base_dir, 'file_test')); const { File } = box; diff --git a/test/scripts/extend/renderer.js b/test/scripts/extend/renderer.js index 44327d0cb7..8cb8131251 100644 --- a/test/scripts/extend/renderer.js +++ b/test/scripts/extend/renderer.js @@ -1,7 +1,7 @@ 'use strict'; describe('Renderer', () => { - const Renderer = require('../../../dist/extend/renderer'); + const Renderer = require('../../../dist/extend/renderer').default; it('register()', () => { const r = new Renderer();