lib/plugins/generator/asset.ts

Summary

Maintainability
A
35 mins
Test Coverage
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { exists, createReadStream } from 'hexo-fs';
import Promise from 'bluebird';
import { extname } from 'path';
import { magenta } from 'picocolors';
import type Hexo from '../../hexo';
import type { AssetGenerator, AssetSchema } from '../../types';
import type Document from 'warehouse/dist/document';

interface Data {
  modified: boolean;
  data?: () => any;
}

const process = (name: string, ctx: Hexo) => {
  return Promise.filter(ctx.model(name).toArray(), (asset: Document<AssetSchema>) => exists(asset.source).tap(exist => {
    if (!exist) return asset.remove();
  })).map((asset: Document<AssetSchema>) => {
    const { source } = asset;
    let { path } = asset;
    const data: Data = {
      modified: asset.modified
    };

    if (asset.renderable && ctx.render.isRenderable(path)) {
      // Replace extension name if the asset is renderable
      const filename = path.substring(0, path.length - extname(path).length);

      path = `${filename}.${ctx.render.getOutput(path)}`;

      data.data = () => ctx.render.render({
        path: source,
        toString: true
      }).catch((err: Error) => {
        ctx.log.error({err}, 'Asset render failed: %s', magenta(path));
      });
    } else {
      data.data = () => createReadStream(source);
    }

    return { path, data };
  });
};

function assetGenerator(this: Hexo): Promise<AssetGenerator[]> {
  return Promise.all([
    process('Asset', this),
    process('PostAsset', this)
  ]).then(data => [].concat(...data));
}

export = assetGenerator;