Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempting to run mathjax from PythonMonkey: export declarations may only appear the top level of a module...etc. #452

Open
connorferster opened this issue Oct 31, 2024 · 5 comments

Comments

@connorferster
Copy link

connorferster commented Oct 31, 2024

Issue type

Bug

How did you install PythonMonkey?

Installed from pip

OS platform and distribution

Linux Ubuntu 22.04

Python version (python --version)

3.11

PythonMonkey version (pip show pythonmonkey)

1.0.0

Bug Description

Hi PythonMonkey maintainers!

I love what you have done with this library and have been following it for the last year (congrats on v1.0!). I am quite comfortable in Python but I am a Javascript noob (please bear with me).

My use case is to try and run mathjax from Python. Here is what I am trying to do (see First attempt, below).

This fails when it tries to access the export {init} from the "node-main.js" submodule. (See stack trace below).

So, I tried creating an external submodule that executes .init within the Javascript (see Second attempt, below).

This runs the init (success!) but gets stuck on the export within my "tex2svg.js" sub module.

Am I doing this wrong or is this actually a bug? Any help or insight is deeply appreciated.

Standalone code to reproduce the issue

First attempt

import pythonmonkey as pym

# I have used npm to install `mathjax-full` into the CWD
mathjax = pym.require("mathjax-full")

Second attempt

import pythonmonkey as pym

pym.require("../tex2svg.js")

Relevant log output or backtrace

#### First attempt (Using `pym.require('mathjax-full')`):


---------------------------------------------------------------------------
SpiderMonkeyError                         Traceback (most recent call last)
Cell In[6], line 1
----> 1 pym.require("mathjax-full")

File ~/miniforge3/envs/pymonkey/lib/python3.11/site-packages/pythonmonkey/require.py:429, in require(moduleIdentifier)
    427 if not os.path.exists(filename):
    428   filename = os.path.join(os.getcwd(), "__main_virtual__")
--> 429 return createRequire(filename)(moduleIdentifier)

SpiderMonkeyError: Error in file /home/connorferster/MCco/mathjax-pymonkey/node_modules/mathjax-full/components/src/node-main/node-main.js, on line 83, column 1:
export {init};
^
SyntaxError: export declarations may only appear at top level of a module parsing /home/connorferster/MCco/mathjax-pymonkey/node_modules/mathjax-full/components/src/node-main/node-main.js

Second attempt (Using pym.require("../tex2svg.js")):

---------------------------------------------------------------------------
SpiderMonkeyError                         Traceback (most recent call last)
Cell In[5], line 1
----> 1 pym.require("../tex2svg.js")

File ~/miniforge3/envs/pymonkey/lib/python3.11/site-packages/pythonmonkey/require.py:429, in require(moduleIdentifier)
    427 if not os.path.exists(filename):
    428   filename = os.path.join(os.getcwd(), "__main_virtual__")
--> 429 return createRequire(filename)(moduleIdentifier)

SpiderMonkeyError: Error in file /home/connorferster/MCco/mathjax-pymonkey/tex2svg.js, on line 137, column 1:
export const tex2svgexport = MathJax.tex2svgPromise
^
SyntaxError: export declarations may only appear at top level of a module parsing /home/connorferster/MCco/mathjax-pymonkey/tex2svg.js

Additional info if applicable

Here is the contents of my javascript submodule ("tex2svg.js"):

#! /usr/bin/env -S node -r esm

const PACKAGESA = 'base, autoload, require, ams, newcommand';
const CSSA = [
  'svg a{fill:blue;stroke:blue}',
  '[data-mml-node="merror"]>g{fill:red;stroke:red}',
  '[data-mml-node="merror"]>rect[data-background]{fill:yellow;stroke:none}',
  '[data-frame],[data-line]{stroke-width:70px;fill:none}',
  '.mjx-dashed{stroke-dasharray:140}',
  '.mjx-dotted{stroke-linecap:round;stroke-dasharray:0,140}',
  'use[data-c]{stroke-width:3px}'
].join('');

const ex = 8
const em = 16
const inline = true
const width = 16 * 80
const styles = true
const container = true
const fontCache = true
const assistiveMml = false
const dist = false

//
// Load MathJax and initialize MathJax and typeset the given math
//

require('mathjax-full').init({
    //
    //  The MathJax configuration
    //
    options: {
        enableAssistiveMml: assistiveMml
    },
    loader: {
        source: require('mathjax-full/components/src/source.js').source,
        load: ['adaptors/liteDOM', 'tex-svg']
    },
    tex: {
        packages: PACKAGESA,
    },
    svg: {
        fontCache: fontCache
    },
    startup: {
        typeset: false
    }
})

export const tex2svgexport = MathJax.tex2svgPromise

What branch of PythonMonkey were you developing on? (If applicable)

No response

@wiwichips
Copy link
Collaborator

wiwichips commented Oct 31, 2024

Glad to hear your in interest in the project!!

Initial roadblocks with your mathjax-full journey:

  • PythonMonkey doesn't support ESMs ( in JavaScript there are mainly two different module systems, CommonJS (CJS) and ECMAScript Modules (ESM) - in PythonMonkey we only have an implementation for CJS modules )
  • PythonMonkey doesn't have implementations for everything in NodeJS' standard library, so libraries which rely on many NodeJS libraries such as os, process, aren't available for use!
  • Similarly, PythonMonkey doesn't have all the browser specific stuff either - so code that works in the browser doesn't necessarily work in PythonMonkey!

You can sort of think of PythonMonkey more like a full JavaScript runtime, it just happens to be used as a Python library with easy to use high level bindings. Like other JavaScript runtimes, (Firefox, Chrome, Node, Bun, etc) there are compatibility issues between them due to different APIs being available.

HOWEVER!!!!!

If you're willing to put a little work into polyfilling the environment, you may be able to get things running smoothly which were originally meant to run in a different environment (like NodeJS or the browser) --- we did that to port https://socket.io/ to Python, and our Python SDK for distributed computing is also just a port of our JS SDK using PythonMonkey via polyfilling.

I played around with your example code but eventually came across errors due to mathjax-full using Node standard libraries like path. You may have more luck if you use the browser bundle https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js but when I tried it just now I got errors from the HTML dom not being present ): - so it'd have to take a little bit more work, or maybe some webpack incantations.

@connorferster
Copy link
Author

Wow! Thank you for such a detailed (and fast) response. I see the problem more clearly now. Thank you, again, for this response.

@connorferster
Copy link
Author

I played around with your example code but eventually came across errors due to mathjax-full using Node standard libraries like path.

How did you get around the export error to hit this error?

@wiwichips
Copy link
Collaborator

wiwichips commented Oct 31, 2024

How did you get around the export error to hit this error?

I modified the code in the node module lol

I changed

export {init};

to

exports.init = init;

in file node_modules/mathjax-full/components/src/node-main/node-main.js

Not sure if that's the best path to start going down, but it's just something I played around with

@connorferster
Copy link
Author

Excellent, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Backlog
Development

No branches or pull requests

2 participants