Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: improvement hexo.extend #5208

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
{
"extends": "hexo",
"root": true
}
{
"root": true,
"extends": "hexo/ts.js",
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2020
},
"rules": {
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-var-requires": 0,
"node/no-missing-require": 0
}
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ package-lock.json
coverage/
.tmp*
.vscode
dist/
15 changes: 11 additions & 4 deletions lib/box/file.js → lib/box/file.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
'use strict';

const { readFile, readFileSync, stat, statSync } = require('hexo-fs');
import { readFile, readFileSync, stat, statSync } from 'hexo-fs';

class File {
public source: any;
public path: any;
public params: any;
public type: any;
static TYPE_CREATE: 'create';
static TYPE_UPDATE: 'update';
static TYPE_SKIP: 'skip';
static TYPE_DELETE: 'delete';

constructor({ source, path, params, type }) {
this.source = source;
this.path = path;
Expand Down Expand Up @@ -32,4 +39,4 @@ File.TYPE_UPDATE = 'update';
File.TYPE_SKIP = 'skip';
File.TYPE_DELETE = 'delete';

module.exports = File;
export = File;
62 changes: 41 additions & 21 deletions lib/box/index.js → lib/box/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
'use strict';

const { join, sep } = require('path');
const Promise = require('bluebird');
const File = require('./file');
const { Pattern, createSha1Hash } = require('hexo-util');
const { createReadStream, readdir, stat, watch } = require('hexo-fs');
const { magenta } = require('picocolors');
const { EventEmitter } = require('events');
const { isMatch, makeRe } = require('micromatch');
import { join, sep } from 'path';
import BlueBirdPromise from 'bluebird';
import File from './file';
import { Pattern, createSha1Hash } from 'hexo-util';
import { createReadStream, readdir, stat, watch } from 'hexo-fs';
import { magenta } from 'picocolors';
import { EventEmitter } from 'events';
import { isMatch, makeRe } from 'micromatch';

const defaultPattern = new Pattern(() => ({}));

interface Processor {
pattern: Pattern;
process: (file: File) => void;
}

class Box extends EventEmitter {
constructor(ctx, base, options) {
public options: any;
public context: any;
public base: any;
public processors: Processor[];
public _processingFiles: any;
public watcher: any;
public Cache: any;
// TODO: replace runtime class _File
public File: any;
public ignore: any;
public source: any;
public emit: any;
public ctx: any;

constructor(ctx, base, options?: object) {
super();

this.options = Object.assign({
Expand Down Expand Up @@ -40,10 +57,13 @@ class Box extends EventEmitter {
this.ignore = targets;
this.options.ignored = targets.map(s => toRegExp(ctx, s)).filter(x => x);
}

_createFileClass() {
const ctx = this.context;

class _File extends File {
public box: Box;

render(options) {
return ctx.render.render({
path: this.source
Expand Down Expand Up @@ -100,7 +120,7 @@ class Box extends EventEmitter {
}));
}

process(callback) {
process(callback?) {
const { base, Cache, context: ctx } = this;

return stat(base).then(stats => {
Expand All @@ -121,7 +141,7 @@ class Box extends EventEmitter {

_processFile(type, path) {
if (this._processingFiles[path]) {
return Promise.resolve();
return BlueBirdPromise.resolve();
}

this._processingFiles[path] = true;
Expand All @@ -133,7 +153,7 @@ class Box extends EventEmitter {
path
});

return Promise.reduce(this.processors, (count, processor) => {
return BlueBirdPromise.reduce(this.processors, (count, processor) => {
const params = processor.pattern.match(path);
if (!params) return count;

Expand All @@ -144,7 +164,7 @@ class Box extends EventEmitter {
type
});

return Reflect.apply(Promise.method(processor.process), ctx, [file])
return Reflect.apply(BlueBirdPromise.method(processor.process), ctx, [file])
.thenReturn(count + 1);
}, 0).then(count => {
if (count) {
Expand All @@ -162,9 +182,9 @@ class Box extends EventEmitter {
}).thenReturn(path);
}

watch(callback) {
watch(callback?) {
if (this.isWatching()) {
return Promise.reject(new Error('Watcher has already started.')).asCallback(callback);
return BlueBirdPromise.reject(new Error('Watcher has already started.')).asCallback(callback);
}

const { base } = this;
Expand Down Expand Up @@ -218,7 +238,7 @@ function getHash(path) {
const src = createReadStream(path);
const hasher = createSha1Hash();

const finishedPromise = new Promise((resolve, reject) => {
const finishedPromise = new BlueBirdPromise((resolve, reject) => {
src.once('error', reject);
src.once('end', resolve);
});
Expand Down Expand Up @@ -247,9 +267,9 @@ function isIgnoreMatch(path, ignore) {
}

function readDirWalker(ctx, base, results, ignore, prefix) {
if (isIgnoreMatch(base, ignore)) return Promise.resolve();
if (isIgnoreMatch(base, ignore)) return BlueBirdPromise.resolve();

return Promise.map(readdir(base).catch(err => {
return BlueBirdPromise.map(readdir(base).catch(err => {
ctx.log.error({ err }, 'Failed to read directory: %s', base);
if (err && err.code === 'ENOENT') return [];
throw err;
Expand All @@ -272,4 +292,4 @@ function readDirWalker(ctx, base, results, ignore, prefix) {
});
}

module.exports = Box;
export = Box;
64 changes: 46 additions & 18 deletions lib/extend/console.js → lib/extend/console.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
'use strict';
import Promise from 'bluebird';
import abbrev from 'abbrev';

const Promise = require('bluebird');
const abbrev = require('abbrev');
type Option = Partial<{
usage: string;
desc: string;
init: boolean;
arguments: {
name: string;
desc: string;
}[];
options: {
name: string;
desc: string;
}[];
}>

/**
* Console plugin option
* @typedef {Object} Option
* @property {String} usage - The usage of a console command
* @property {{name: String, desc: String}[]} arguments - The description of each argument of a console command
* @property {{name: String, desc: String}[]} options - The description of each option of a console command
*/
interface Args {
_: string[];
[key: string]: string | boolean | string[];
}
type AnyFn = (args: Args) => any;
interface StoreFunction extends AnyFn {
desc?: string;
options?: Option;
}

interface Store {
[key: string]: StoreFunction
}
interface Alias {
[key: string]: string
}

class Console {
public store: Store;
public alias: Alias;

constructor() {
this.store = {};
this.alias = {};
Expand All @@ -20,9 +44,9 @@ class Console {
/**
* Get a console plugin function by name
* @param {String} name - The name of the console plugin
* @returns {Function} - The console plugin function
* @returns {StoreFunction} - The console plugin function
*/
get(name) {
get(name: string): StoreFunction {
name = name.toLowerCase();
return this.store[this.alias[name]];
}
Expand All @@ -36,9 +60,13 @@ class Console {
* @param {String} name - The name of console plugin to be registered
* @param {String} desc - More detailed information about a console command
* @param {Option} options - The description of each option of a console command
* @param {Function} fn - The console plugin to be registered
* @param {AnyFn} fn - The console plugin to be registered
*/
register(name, desc, options, fn) {
register(name: string, fn: AnyFn): void
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) {
if (!name) throw new TypeError('name is required');

if (!fn) {
Expand Down Expand Up @@ -73,13 +101,13 @@ class Console {
fn = Promise.method(fn);
}

const c = fn;
const c = fn as StoreFunction;
this.store[name.toLowerCase()] = c;
c.options = options;
c.desc = desc;
c.options = options as Option;
c.desc = desc as string;

this.alias = abbrev(Object.keys(this.store));
}
}

module.exports = Console;
export = Console;
20 changes: 15 additions & 5 deletions lib/extend/deployer.js → lib/extend/deployer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
'use strict';
import Promise from 'bluebird';

const Promise = require('bluebird');
interface StoreFunction {
(deployArg: {
type: string;
[key: string]: any
}) : any;
}
interface Store {
[key: string]: StoreFunction
}

class Deployer {
public store: Store;

constructor() {
this.store = {};
}
Expand All @@ -11,11 +21,11 @@ class Deployer {
return this.store;
}

get(name) {
get(name: string) {
return this.store[name];
}

register(name, fn) {
register(name: string, fn: StoreFunction) {
if (!name) throw new TypeError('name is required');
if (typeof fn !== 'function') throw new TypeError('fn must be a function');

Expand All @@ -29,4 +39,4 @@ class Deployer {
}
}

module.exports = Deployer;
export = Deployer;
Loading