Giter VIP home page Giter VIP logo

Comments (21)

thetw avatar thetw commented on July 29, 2024 6

Sorry for the late answer.
This issue can be closed, it was an issue with accidentally calling the require context function on the Helvetica font after force importing the raw file.
Thanks for your help! 😄

from pdfkit-webpack-example.

thetw avatar thetw commented on July 29, 2024 1

@GO-gyan You don't need to use the registerFiles.js file, if you only want to inline the basic Helvetica font. To achieve this, just do this:

import fs from 'fs'
import Helvetica from '!!raw-loader!pdfkit/js/data/Helvetica.afm'

fs.writeFileSync('data/Helvetica.afm', Helvetica)

This will add the raw content of the .afm font to the Virtual file system of PDFKit.
I've used Create React App with the custom webpack config provided by this repo.

Please mention, that you have to register a custom font in order to make another fonts working with PDFKit. I did this with fetching an external font file in order to keep bundle size small and then passing the response ArrayBuffer to the doc.registerFont('FontName', <ArrayBuffer>); function of PDFKit.

from pdfkit-webpack-example.

jakubsuplicki avatar jakubsuplicki commented on July 29, 2024 1

Just a heads up for people who struggle to implement pdfkit in Nuxt.js / Vue.js:

  1. Install all required dependencies the same as in the example.
  2. In your nuxt.config.js write the following:
    extend(config, ctx) {
      const alias = config.resolve.alias = config.resolve.alias || {}
      alias['fs'] = 'pdfkit/js/virtual-fs.js'
      config.module.rules.push(
        { enforce: 'post', test: /fontkit[/\\]index.js$/, loader: "transform-loader?brfs" },
        { enforce: 'post', test: /unicode-properties[/\\]index.js$/, loader: "transform-loader?brfs" },
        { enforce: 'post', test: /linebreak[/\\]src[/\\]linebreaker.js/, loader: "transform-loader?brfs" },
        { test: /src[/\\]assets/, loader: 'arraybuffer-loader'},
        { test: /\.afm$/, loader: 'raw-loader'}
      )
    }
  1. In your Vue template (note that I am importing only one font so there is no need to use the register-files.js as mentioned above by @thetw ):
<script>
  import fs from 'fs'
  import Helvetica from '!!raw-loader!pdfkit/js/data/Helvetica.afm'
  if(process.browser){
      fs.writeFileSync('data/Helvetica.afm', Helvetica)
      var PDFDocument = require('pdfkit').default;
      var blobStream = require('blob-stream');
      var ace = require('brace');
      require('brace/mode/javascript');
      require('brace/theme/monokai');
  }
</script>

By doing it this way, you will avoid having problems with server-side rendering.

Thanks everyone, hope it helps.

from pdfkit-webpack-example.

seyfer avatar seyfer commented on July 29, 2024 1

If somebody comes here with this issue on AWS Lambda and your error looks like
/var/task/data/Helvetica.afm not found
this SO answer helped me
https://stackoverflow.com/questions/72775287/cdk-lambda-nodejsfunction-pdfmake-enoent-error
basically, you need to not bundle pdfkit, but include it fully in node_modules when deploying to AWS Lambda

from pdfkit-webpack-example.

zvizesna avatar zvizesna commented on July 29, 2024 1

I managed to solve this properly for create-react-app without ejecting or triggering the ESLint error import/no-webpack-loader-syntax.

I used CRACO and the following craco.config.js:

const webpack = require("webpack");

module.exports = {
    webpack: {
        configure: (webpackConfig, { env, paths }) => {

            // Modifying webpack.module.rules with CRACO is only possible using the `configure` function,
            // not using the `configure` object literal.
            // See supported config for webpack: https://craco.js.org/docs/configuration/webpack/

            webpackConfig.module.rules = [
                ...webpackConfig.module.rules,
                // bundle and load afm files verbatim
                { test: /\.afm$/, type: 'asset/source' },
                // bundle and load binary files inside static-assets folder as base64
                {
                    test: /src[/\\]static-assets/,
                    type: 'asset/inline',
                    generator: {
                        dataUrl: content => {
                            return content.toString('base64');
                        },
                    },
                },
                // load binary files inside lazy-assets folder as an URL
                {
                    test: /src[/\\]lazy-assets/,
                    type: 'asset/resource'
                },
                // convert to base64 and include inline file system binary files used by fontkit and linebreak
                {
                    enforce: 'post',
                    test: /fontkit[/\\]index.js$/,
                    loader: 'transform-loader',
                    options: {
                        brfs: {}
                    },
                },
                {
                    enforce: 'post',
                    test: /linebreak[/\\]src[/\\]linebreaker.js/,
                    loader: 'transform-loader',
                    options: {
                        brfs: {}
                    },
                },
            ];

            webpackConfig.resolve.alias = {
                ...webpackConfig.resolve.alias,

                // maps fs to a virtual one allowing to register file content dynamically
                fs: 'pdfkit/js/virtual-fs.js',
                // iconv-lite is used to load cid less fonts (not spec compliant)
                'iconv-lite': false,
            };

            webpackConfig.resolve.fallback = {
                ...webpackConfig.resolve.fallback,
                
                // crypto module is not necessary at browser
                crypto: false,
                // fallbacks for native node libraries
                process: require.resolve("process/browser"),
                zlib: require.resolve("browserify-zlib"),
                stream: require.resolve("stream-browserify"),
                util: require.resolve("util"),
                buffer: require.resolve("buffer"),
                assert: require.resolve("assert"),
            };

            webpackConfig.plugins = [
                ...webpackConfig.plugins,

                new webpack.ProvidePlugin({
                    Buffer: ["buffer", "Buffer"],
                    process: "process/browser",
                }),
            ];

            return webpackConfig;
        }
    }
}

Then I followed the webpack example, copied the src/registerStaticFiles.js to my project, created a src/static-assets folder, and added import './registerStaticFiles' where I create the PDFDocument . Now it works without having to explicitly import and register Helvetica.

from pdfkit-webpack-example.

blikblum avatar blikblum commented on July 29, 2024

What version of pdfkit are you using?

Try:

import Helvetica from 'pdfkit/js/data/Helvetica.afm'
import fs from 'fs'

//some debug:
console.log(Helvetica)
console.log(typeof  Helvetica)


fs.writeFileSync('data/Helvetica.afm', Helvetica)

from pdfkit-webpack-example.

thetw avatar thetw commented on July 29, 2024

I'm using the same version as in your example: pdfkit v.0.9.1

I've tried your snippet with the following results:

console.log(Helvetica)
// Output: /static/media/Helvetica.d6455828.afm
console.log(typeof  Helvetica)
// Output: string

The error changed to:


Uncaught (in promise) TypeError: Cannot read property 'split' of undefined
    at new AFMFont (pdfkit.es5.js:2453)
    at new StandardFont (pdfkit.es5.js:2700)
    at Function.open (pdfkit.es5.js:3096)
    at PDFDocument.font (pdfkit.es5.js:3170)
    at PDFDocument.initFonts (pdfkit.es5.js:3132)
    at new PDFDocument (pdfkit.es5.js:4890)
    at new PDFBuilder (PDFBuilder.js:42)
    at PDFCreator.createID (index.jsx:40)
    at PDFCreator.componentDidMount (index.jsx:72)

In comparison to the last one, now the error is happening while trying to create the AFMFont invoked by StandardFont.

This line from the source causes the error:

this.bbox = this.attributes['FontBBox'].split(/\s+/).map(function (e) {
      return +e;
    });

The font is still not inlined...
Instead webpack only creates the reference to the now bundled asset (as we see in the log above):

/***/ "./node_modules/pdfkit/js/data/Helvetica.afm":
/*!***************************************************!*\
  !*** ./node_modules/pdfkit/js/data/Helvetica.afm ***!
  \***************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

module.exports = __webpack_require__.p + "static/media/Helvetica.d6455828.afm";

/***/ }),

from pdfkit-webpack-example.

blikblum avatar blikblum commented on July 29, 2024

Some other loader is taking precedence over raw-loader. From raw-loader docs try:

import Helvetica from '!!raw-loader!pdfkit/js/data/Helvetica.afm'

from pdfkit-webpack-example.

blikblum avatar blikblum commented on July 29, 2024

Some other loader is taking precedence over raw-loader.

Probably https://webpack.js.org/loaders/file-loader

from pdfkit-webpack-example.

thetw avatar thetw commented on July 29, 2024

Thanks for your quick response. I think we are now on good way!
Webpack inlined the raw contents of the Helvetica file, but there's still the same error from above...
Uncaught (in promise) TypeError: Cannot read property 'split' of undefined

I did some research in the code:

class AFMFont {
  static open(filename) {
    return new AFMFont(fs.readFileSync(filename, 'utf8')); // this normally should return the raw content
  }

  constructor(contents) {
    this.contents = contents;
    this.attributes = {};
    this.glyphWidths = {};
    this.boundingBoxes = {};
    this.kernPairs = {};

    this.parse(); // here the raw content should be parsed and set to the properties above
    this.charWidths = new Array(256);
    for (let char = 0; char <= 255; char++) {
      this.charWidths[char] = this.glyphWidths[characters[char]];
    }

    this.bbox = this.attributes['FontBBox'].split(/\s+/).map(e => +e); // this fails because FontBBox is undefined, attributes must be empty
    // ...
  }

So why does webpack not forward the raw source to the static opener?
Maybe there is an issue with the fs implementation? Maybe with context?
The console statements from the beginning are still producing the same output – is this intended?

I'm really stuck, any ideas?

from pdfkit-webpack-example.

blikblum avatar blikblum commented on July 29, 2024

So why does webpack not forward the raw source to the static opener?

The config added by CRA is somehow interfering

Maybe there is an issue with the fs implementation?

No

Maybe with context?

No. Because would work with direct import

The console statements from the beginning are still producing the same output – is this intended?

No. It should display the afm file content:

StartFontMetrics 4.1
Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.  All Rights Reserved.
Comment Creation Date: Thu May  1 12:38:23 1997
Comment UniqueID 43054
...

Try:

import fs from 'fs'
import Helvetica from '!!raw-loader!pdfkit/js/data/Helvetica.afm'

fs.writeFileSync('data/Helvetica.afm', Helvetica)

An then run webpack with --display-modules option should get something like:
[./node_modules/raw-loader/index.js!./node_modules/pdfkit/js/data/Helvetica.afm] ./node_modules/raw-loader!./node_modules/pdfkit/js/data/Helvetica.afm 81.5 KiB {main} [built]

from pdfkit-webpack-example.

GO-gyan avatar GO-gyan commented on July 29, 2024

This issue can be closed, it was an issue with accidentally calling the require context function on the Helvetica font after force importing the raw file.

Hi @thetw I am facing the same problem. Could you please explain above sentence.

from pdfkit-webpack-example.

GO-gyan avatar GO-gyan commented on July 29, 2024

@GO-gyan You don't need to use the registerFiles.js file, if you only want to inline the basic Helvetica font. To achieve this, just do this:

import fs from 'fs'
import Helvetica from '!!raw-loader!pdfkit/js/data/Helvetica.afm'

fs.writeFileSync('data/Helvetica.afm', Helvetica)

This will add the raw content of the .afm font to the Virtual file system of PDFKit.
I've used Create React App with the custom webpack config provided by this repo.

Please mention, that you have to register a custom font in order to make another fonts working with PDFKit. I did this with fetching an external font file in order to keep bundle size small and then passing the response ArrayBuffer to the doc.registerFont('FontName', <ArrayBuffer>); function of PDFKit.

Thanks for your quick reply. It is working fine now.

from pdfkit-webpack-example.

wworrall avatar wworrall commented on July 29, 2024

@GO-gyan You don't need to use the registerFiles.js file, if you only want to inline the basic Helvetica font. To achieve this, just do this:

import fs from 'fs'
import Helvetica from '!!raw-loader!pdfkit/js/data/Helvetica.afm'

fs.writeFileSync('data/Helvetica.afm', Helvetica)

This will add the raw content of the .afm font to the Virtual file system of PDFKit.
I've used Create React App with the custom webpack config provided by this repo.

Please mention, that you have to register a custom font in order to make another fonts working with PDFKit. I did this with fetching an external font file in order to keep bundle size small and then passing the response ArrayBuffer to the doc.registerFont('FontName', <ArrayBuffer>); function of PDFKit.

Hi, I am also facing this issue and have little experience with Webpack. My setup uses CRA and customize-cra in order to add the module loader rules. Fundamentally it seems the rule: { test: /\.afm$/, loader: 'raw-loader' } is ignored as suggested by @blikblum. Are there any further ideas on how to get this to work without @GO-gyan 's work around?

Apologies for my lack of understanding and thank you for the content so far - the work around has helped greatly.

from pdfkit-webpack-example.

jarommadsen avatar jarommadsen commented on July 29, 2024

@wworrall Make certain that the raw-loader and all other loaders are placed above the file-loader if you are using that. Also, if you are not replacing register-files.js with the single Helvetica register, make sure to update the registerAFMFonts function ctx(key) to ctx(key).default

from pdfkit-webpack-example.

suryasarafe avatar suryasarafe commented on July 29, 2024

import fs from 'fs'
import Helvetica from '!!raw-loader!pdfkit/js/data/Helvetica.afm'

fs.writeFileSync('data/Helvetica.afm', Helvetica)

i have problem to find file to put above code, and never use the registerFiles.js, can you be more specify about how to solve it.?

i just import pdfmake.min.js and vfs_fonts.js.

const font = {
  Helvetica: {
    normal: 'Helvetica',
    bold: 'Helvetica-Bold',
    italics: 'Helvetica-Oblique',
    bolditalics: 'Helvetica-BoldOblique'
  },
}
pdfMake.createPdf({
  content: [
    'First paragrap',
    'Second one'
  ],
  defaultStyle: {
    font: 'Helvetica'
  }
}, null, font).open()

Thank you.

from pdfkit-webpack-example.

blikblum avatar blikblum commented on July 29, 2024

You must use webpack. See the code in this repo

from pdfkit-webpack-example.

blikblum avatar blikblum commented on July 29, 2024

BTW: this repository is for pdfkit, not pdfmake

from pdfkit-webpack-example.

ivanvladimirov avatar ivanvladimirov commented on July 29, 2024

I went through this problem and now I am trying to add my custom font. What I tried is adding the font with fs, just like the Helvetica one, but from a local folder. It obviously didn't work - the error I got was:
Error: File 'static/media/Roboto-Regular.11eabca2.ttf' not found in virtual file system

I know I have to use arrayBuffer somehow, but I have no idea what I should do. Please help!

EDIT:
I imported Roboto in the following way:
import Roboto from "../../assets/fonts/Roboto-Regular.ttf"
Then I tried adding my font like so:
const buffer = new Buffer(Roboto) doc.registerFont('Roboto', buffer)
and now the error is:
Error: Unknown font format, also tried with .otf and .afm - same response

@thetw, @blikblum, you think you can help me with that? :(

from pdfkit-webpack-example.

7iomka avatar 7iomka commented on July 29, 2024

@zvizesna

in next.js I have an issue

 ⚯ ../../node_modules/process/browser.js
@steklo24/store:dev-clean: TypeError: Property left of AssignmentExpression expected node to be of a type ["LVal"] but instead got "BooleanLiteral"
@steklo24/store:dev-clean: Import trace for requested module:
@steklo24/store:dev-clean: ../../node_modules/process/browser.js

from pdfkit-webpack-example.

seport avatar seport commented on July 29, 2024

Commenting here in case it helps anyone else. I was having the same problem and for me it boiled down to this line in my webpack.config.js:

module.exports = {
...
resolve: {
    extensions: ['', ...],
...
}

this was the result of me copying and pasting webpack configs from moldy blogs, documentation, or stack overflow threads that warned:

Setting this option will override the default, meaning that webpack will no longer try to resolve modules using the default extensions. If you want modules that were required with their extension (e.g. require('./somefile.ext')) to be properly resolved, you must include an empty string in your array. Similarly, if you want modules that were required without extensions (e.g. require('underscore')) to be resolved to files with “.js” extensions, you must include ".js" in your array.

However, in modern webpack this is no longer necessary, and even used to throw an error warning you not to do that anymore (webpack/webpack#3043) (webpack migration notes)

in modern webpack versions, it seems the empty string in resolve.extensions can cause errors like these and afaik you can just remove it and it should all work 👍

(resolve.extensions documentation)

from pdfkit-webpack-example.

Related Issues (5)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.