executablebooks / markdown-it-dollarmath

A markdown-it plugin for $-delimited math
https://executablebooks.github.io/markdown-it-dollarmath/
MIT License
4 stars 5 forks source link

"Syntax error: Cannot use import statement outside a module" w/ node.js 18.12.1 and ESM-mode parent #10

Open zackw opened 1 year ago

zackw commented 1 year ago

Describe the bug

I'm trying to use markdown-it-dollarmath with node.js 18.12.1. The importing package is in ESM mode ("type":"module" in package.json). Import crashes with the following stack trace:

$ cat test.js
import dollarmath from "markdown-it-dollarmath";
$ node test.js
(node:6713) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/.../[parent]/node_modules/markdown-it-dollarmath/dist/esm/index.js:1
import { escapeHtml } from "markdown-it/lib/common/utils";
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:360:18)
    at wrapSafe (node:internal/modules/cjs/loader:1088:15)
    at Module._compile (node:internal/modules/cjs/loader:1123:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:169:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:530:24)

Node.js v18.12.1

It appears to me that markdown-it-dollarmath is trying to ship both CommonJS and ESM modules, but (this version of) node doesn't propagate "this is an ESM module" status from the exports declaration in package.json, only from the file extension. Thus, my ESM import correctly tries to load node_modules/markdown-it-dollarmath/dist/esm/index.js but then it tries to parse it as a CommonJS module and the import statement is rejected.

If I rename dist/esm/index.js to dist/esm/index.mjs and change the references in package.json to match

--- markdown-it-dollarmath/package.json 2022-12-11 12:26:23.567852719 -0500
+++ markdown-it-dollarmath/package.json 2022-12-11 12:52:47.531574035 -0500
@@ -13,7 +13,7 @@
     "math"
   ],
   "main": "dist/cjs/index.js",
-  "module": "dist/esm/index.js",
+  "module": "dist/esm/index.mjs",
   "unpkg": "dist/index.umd.min.js",
   "types": "dist/types/index.d.ts",
   "files": [
@@ -23,7 +23,7 @@
   "exports": {
     ".": {
       "require": "./dist/cjs/index.js",
-      "import": "./dist/esm/index.js"
+      "import": "./dist/esm/index.mjs"
     }
   },
   "scripts": {

then I hit a different error:

$ node test
node:internal/process/esm_loader:97
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/.../[parent]/node_modules/markdown-it/lib/common/utils'
   imported from /.../[parent]/node_modules/markdown-it-dollarmath/dist/esm/index.mjs
Did you mean to import markdown-it/lib/common/utils.js?
    at new NodeError (node:internal/errors:393:5)
    at finalizeResolution (node:internal/modules/esm/resolve:323:11)
    at moduleResolve (node:internal/modules/esm/resolve:916:10)
    at defaultResolve (node:internal/modules/esm/resolve:1124:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:841:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v18.12.1

I don't know how to fix this, and I also don't know how to persuade tsc to emit files with .mjs and/or .cjs suffixes in the first place.

Reproduce the bug

The following shell script will reproduce the crash, assuming a node.js that behaves the way mine does:

cat > test.js <<\EOF
import dollarmath from "markdown-it-dollarmath";
EOF
cat > package.json <<\EOF
{
    "name": "dollarmath-import-bug",
    "type": "module",
    "dependencies": {
        "markdown-it-dollarmath": "=0.4.2"
    }
}
EOF
npm install
node test

List your environment

$ node --version
v18.12.1
$ npm --version
9.1.3
$ jq '.packages | del(."") | map_values(.version)' < package-lock.json | sed 's:"node_modules/:":'
{
  "argparse": "2.0.1",
  "entities": "2.1.0",
  "linkify-it": "3.0.3",
  "markdown-it": "12.3.2",
  "markdown-it-dollarmath": "0.4.2",
  "mdurl": "1.0.1",
  "uc.micro": "1.0.6"
}
welcome[bot] commented 1 year ago

Thanks for opening your first issue here! Engagement like this is essential for open source projects! :hugs:
If you haven't done so already, check out EBP's Code of Conduct. Also, please try to follow the issue template as it helps other community members to contribute more effectively.
If your issue is a feature request, others may react to it, to raise its prominence (see Feature Voting).
Welcome to the EBP community! :tada: