patorjk / figlet.js

A FIG Driver written in JavaScript which aims to fully implement the FIGfont spec.
MIT License
2.51k stars 164 forks source link

Webpack & TypeScript support #52

Open Nightbr opened 4 years ago

Nightbr commented 4 years ago

Hello there, first of all, thanks for this awesome package which enhances all our CLI tool :+1:

Problem Statement

We would like to develop a more robust CLI tool using Webpack & TypeScript. Everything is setup and works properly but I'm running into some errors with figlet integration.

Context

Here is my setup for the project, I will create a boilerplate if needed on Github. But right now, I can share the webpack.config.js:

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.ts',
  target: 'node',
  stats: {
    warnings: false // /!\ nunjucks as broken import, so webpack log warnings, disabling them for now...
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js']
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
    libraryTarget: 'commonjs'
  }
};

and the tsconfig.json

{
  "compilerOptions": {
    "target": "es2017",
    "module": "commonjs",
    "outDir": "./dist",
    "strict": true,
    "baseUrl": "./src/",
    "typeRoots": ["node_modules/@types"],
    "types": ["node"],
    "esModuleInterop": true,
    "inlineSourceMap": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "resolveJsonModule": true,
    "preserveSymlinks": true
  }
}

But when I want to use figlet there is some errors.

First, with a simple implementation:

import figlet from 'figlet';

console.log(chalk.greenBright(figlet.textSync('plop')));

This will throw an error because webpack doesn't achieve to resolve the fonts folder.

(node:12876) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open '/fonts/Standard.flf'
    at Object.openSync (fs.js:440:3)
    at Object.readFileSync (fs.js:342:35)
    at Function.figlet.loadFontSync (webpack:///./node_modules/figlet/lib/node-figlet.js?:48:23)
    at Object.me.textSync (webpack:///./node_modules/figlet/lib/figlet.js?:732:43)
    at main (webpack:///./src/index.ts?:27:52)
    at Object.eval (webpack:///./src/index.ts?:66:1)
    at eval (webpack:///./src/index.ts?:68:30)

I saw issues about this: #46 & #50 but the node: { __dirname: false } just don't work (or you have to copy the fonts folder at root of your project) & figlet.parseFont has no typing - see https://github.com/DefinitelyTyped/DefinitelyTyped/issues/38318

import figlet from "figlet";
import banner3 from "figlet/importable-fonts/Banner3";

figlet.parseFont("Banner3", banner3);

Add to this, the solution with parseFont is the best I think but you have to declare all importable-fonts in the typing too or you will get this error: If the 'figlet' package actually exposes this module, consider sending a pull request to amend 'https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/figlet.ts(7016)

import figlet from "figlet";
import banner3 from "figlet/importable-fonts/Banner3";

figlet.parseFont("Banner3", banner3);

Possible Solution

I think we just need to update the typing of figlet on https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/figlet/index.d.ts

I'm not an expert on module typing with TypeScript that's why I create an issue & not a pull request in order to discuss the best way to create the typing.

Thanks for help :+1:

patorjk commented 4 years ago

Hi @Nightbr, as you mentioned, https://github.com/DefinitelyTyped/DefinitelyTyped/issues/38318 has been opened over on DefinitelyTyped for this. However, I don't think it'll be worked unless someone submits a PR.

I'm not really familar with TypeScript, but this is what I think the new file should look like:

https://github.com/patorjk/DefinitelyTyped/blob/figlet_fix/types/figlet/index.d.ts

However, I'm not on a computer where I can run the DefinitelyTyped code. If you want to put in PR for this fix definitely do so. Otherwise if I get some time tonight I'll try and put in a PR with the above branch (all I did for that was put in the line I think is missing).

reezpatel commented 3 years ago

Hi @patorjk , How about adding an index.d.ts in the package, would you like a PR?

Yingrjimsch commented 3 years ago

Hi there. I got a similar error. I'm building a npm package, which should contain figlet. If I test it I get following error: http://localhost:4200/fonts/Standard.flf 404 (Not Found) somehow the npm package does not find the correct font.

index.js file

var figlet = require('figlet');
  figlet('Hello World!!', function(err, data) {
    if (err) {
        console.log('Something went wrong...');
        console.dir(err);
        return;
    }
    console.log(data)
});

Does someone has an idea what I'm doing wrong?

Edit: If I import both figlet and a font like following it works. Is there a method I don't have to import the font seperately? Is it possible to expose all fonts per default?

import figlet from 'figlet';
import standard from 'figlet/importable-fonts/Standard.js'

figlet.parseFont('Standard', standard);

figlet.text('test', {
    font: 'Standard',
}, function(err, data) {
    console.log(data);
});
patorjk commented 3 years ago

I would accept a PR.

guicara commented 3 years ago

Hello,

Until the TypeScript definition on DefinitelyTyped is updated, you can use something like that in your project (inspired from https://github.com/DefinitelyTyped/DefinitelyTyped/issues/38318 and https://github.com/aplr/DefinitelyTyped/commit/099f9bea0641922116078c2421e234e72e3a2cb6):

// src/types/figlet.d.ts

// Extended type definitions for figlet 1.2
// Project: https://github.com/patorjk/figlet.js
// Definitions by: Junyoung Clare Jang <https://github.com/Ailrun>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped

import * as figlet from 'figlet';

declare global {
    export namespace figlet {
        /*
         * Parses data from a FIGlet font file and places it into the figFonts object.
         */
        function parseFont(fontName: string, data: string): FontOptions;

        declare module 'figlet/importable-fonts/*' {
            const value: string;
            export default value;
        }
    }
}

// Important to have this line (even if empty...)
declare module 'figlet' {}

Of course, you'll need to update your TypeScript project configuration to load custom types. For example:

// tsconfig.json

{
  "compilerOptions": {
    (...)
    "typeRoots": [
      "src/types",
      "node_modules/@types"
    ]
  },
}
elgs commented 2 years ago

It's 2021, why do we still want to support webpack. Why not just support native ES code and everybody can use it without webpack?

Nightbr commented 2 years ago

@elgs sure thing, make a PR to refactor this lib into a native ES module and it could be bundle with any ES bundler 👌

extending commented 2 years ago

resolve the problem , thanks

wujibear commented 4 months ago

Does this have es support now then?