Skip to content

fix: resolved inconsistent exports in ESM#2047

Merged
LinusU merged 4 commits intoAutomattic:masterfrom
kyranet:feat/add-esm-support
Jun 16, 2022
Merged

fix: resolved inconsistent exports in ESM#2047
LinusU merged 4 commits intoAutomattic:masterfrom
kyranet:feat/add-esm-support

Conversation

@kyranet
Copy link
Contributor

@kyranet kyranet commented Jun 2, 2022

Adds ESM support, for users who prefer using import and libraries using canvas that provides ESM bindings.

Thanks for contributing!

  • Have you updated CHANGELOG.md?

Co-authored-by: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
@LinusU
Copy link
Collaborator

LinusU commented Jun 15, 2022

As far as I can tell, the library already works perfectly fine to import via ESM, why is this needed?

$ echo '{"type":"module"}' > package.json

$ npm add canvas

$ cat index.js
import { Canvas } from 'canvas'

console.log(Canvas)

$ node index.js
[Function: Canvas] {
  _registerFont: [Function: _registerFont],
  _deregisterAllFonts: [Function: _deregisterAllFonts]
}

@kyranet
Copy link
Contributor Author

kyranet commented Jun 15, 2022

Which version of Node.js? I'm trying to import createCanvas as well as loadImage, but they seem to be nested (according to import('canvas')):

[Module: null prototype] {
  Canvas: [Function: Canvas] {
    _registerFont: [Function: _registerFont],
    _deregisterAllFonts: [Function: _deregisterAllFonts]
  },
  CanvasGradient: [Function: CanvasGradient],
  CanvasRenderingContext2D: [Function: CanvasRenderingContext2D],
  Context2d: [Function: CanvasRenderingContext2D],
  default: {
    Canvas: [Function: Canvas] {
      _registerFont: [Function: _registerFont],
      _deregisterAllFonts: [Function: _deregisterAllFonts]
    },
    Context2d: [Function: CanvasRenderingContext2D],
    CanvasRenderingContext2D: [Function: CanvasRenderingContext2D],
    CanvasGradient: [Function: CanvasGradient],
    CanvasPattern: [Function: CanvasPattern],
    Image: [Function: Image] { MODE_IMAGE: 1, MODE_MIME: 2 },
    ImageData: [Function: ImageData],
    PNGStream: [class PNGStream extends Readable],
    PDFStream: [class PDFStream extends Readable],
    JPEGStream: [class JPEGStream extends Readable],
    DOMMatrix: [class DOMMatrix],
    DOMPoint: [class DOMPoint],
    registerFont: [Function: registerFont],
    deregisterAllFonts: [Function: deregisterAllFonts],
    parseFont: [Function (anonymous)],
    createCanvas: [Function: createCanvas],
    createImageData: [Function: createImageData],
    loadImage: [Function: loadImage],
    backends: {
      ImageBackend: [Function: ImageBackend],
      PdfBackend: [Function: PdfBackend],
      SvgBackend: [Function: SvgBackend]
    },
    version: '2.9.1',
    cairoVersion: '1.17.4',
    jpegVersion: '8',
    gifVersion: '5.2.1',
    freetypeVersion: '2.11.1',
    rsvgVersion: '2.54.0'
  }
}

This is in Node.js v16.15.1. On runtime I get this error:

Uncaught:
SyntaxError: Named export 'loadImage' not found. The requested module 'canvas' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'canvas';

@LinusU
Copy link
Collaborator

LinusU commented Jun 15, 2022

Hmm, this is very interesting. I cannot figure out what the difference is between how we export e.g. Canvas (which works) and loadImage (which doesn't) 🤔

https://github.com/Automattic/node-canvas/blob/master/index.js

update: this article might hold some answers:

https://simonplend.com/node-js-now-supports-named-imports-from-commonjs-modules-but-what-does-that-mean/

update2: changing the exports in index.js to the following fixes the problem:

exports.Canvas = Canvas
exports.Context2d = CanvasRenderingContext2D // Legacy/compat export
exports.CanvasRenderingContext2D = CanvasRenderingContext2D
exports.CanvasGradient = bindings.CanvasGradient
exports.CanvasPattern = CanvasPattern
exports.Image = Image
exports.ImageData = bindings.ImageData
exports.PNGStream = PNGStream
exports.PDFStream = PDFStream
exports.JPEGStream = JPEGStream
exports.DOMMatrix = DOMMatrix
exports.DOMPoint = DOMPoint

exports.registerFont = registerFont
exports.deregisterAllFonts = deregisterAllFonts
exports.parseFont = parseFont

exports.createCanvas = createCanvas
exports.createImageData = createImageData
exports.loadImage = loadImage

exports.backends = bindings.Backends

/** Library version. */
exports.version = packageJson.version
/** Cairo version. */
exports.cairoVersion = bindings.cairoVersion
/** jpeglib version. */
exports.jpegVersion = bindings.jpegVersion
/** gif_lib version. */
exports.gifVersion = bindings.gifVersion ? bindings.gifVersion.replace(/[^.\d]/g, '') : undefined
/** freetype version. */
exports.freetypeVersion = bindings.freetypeVersion
/** rsvg version. */
exports.rsvgVersion = bindings.rsvgVersion

@kyranet
Copy link
Contributor Author

kyranet commented Jun 15, 2022

Yeah, that also works, I'll update this PR to do those changes instead.

Edit: Done in fbdeeda!

@kyranet kyranet changed the title feat: add ESM support fix: resolved inconsistent exports in ESM Jun 15, 2022
Copy link
Collaborator

@LinusU LinusU left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat 👍

@LinusU
Copy link
Collaborator

LinusU commented Jun 16, 2022

CI test failure seems unrelated...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants