I wanted to follow up on this. I didn’t make much progress but want to document where I got stuck.
There are a few choices to make. First, to use dune or not. In @dbuenzli’s advice, he doesn’t use dune, but plain js_of_ocaml / META files. I’ve been using dune, like it a lot, and am not so familiar with META files / findlib, so I prefer to use dune if possible (note that where I got stuck applies to both the dune approach and the META approach). Let’s explore what this looks like using dune.
Here’s a simple dune file I’ll try using for the view:
If we try building with (js_of_ocaml (javascript_files codemirror-view.js))
, we get:
js_of_ocaml example/index.bc.runtime.js (exit 1)
(cd _build/default/example && /Users/joel/.opam/4.12.0/bin/js_of_ocaml build-runtime --pretty --source-map-inline -o index.bc.runtime.js ../view/codemirror-view.js)
/Users/joel/.opam/4.12.0/bin/js_of_ocaml: Error: cannot parse file "/Users/joel/code/ocaml/codemirror/_build/default/view/codemirror-view.js" (orig:"/Users/joel/code/ocaml/codemirror/_build/default/view/codemirror-view.js" from l:1, c:7)
codemirror-view.js
is the file directly from the CodeMirror source on NPM. I guess it’s understandable that it doesn’t quite work because it uses JS modules. Here’s the first line:
import { MapMode, Text as Text$1, Facet, ChangeSet, Transaction, EditorSelection, CharCategory, EditorState, Prec, StateEffect, combineConfig } from '@codemirror/state';
Fine, let’s use Babel to transform this to ES5 (npx babel codemirror-view.js --out-file codemirror-view-babel.js --presets @babel/preset-env
). We also change the js_of_ocaml
clause to (js_of_ocaml (javascript_files codemirror-view-babel.js))
:
js_of_ocaml example/index.bc.runtime.js (exit 1)
(cd _build/default/example && /Users/joel/.opam/4.12.0/bin/js_of_ocaml build-runtime --pretty --source-map-inline -o index.bc.runtime.js ../view/codemirror-view-babel.js)
/Users/joel/.opam/4.12.0/bin/js_of_ocaml: Error: cannot parse file "/Users/joel/code/ocaml/codemirror/_build/default/view/codemirror-view-babel.js" (orig:"/Users/joel/code/ocaml/codemirror/_build/default/view/codemirror-view-babel.js" from l:236, c:12)
This time, the js_of_ocaml parser trips on a getter:
dom.focus(preventScrollSupported == null ? {
get preventScroll() {
preventScrollSupported = { preventScroll: true };
return true;
}
} : undefined);
I was a bit surprised to see this in the Babel output, but according to MDN this syntax is in ES2015, so I guess it’s fine. I couldn’t find any Babel preset that doesn’t output a getter. So I guess we’re stuck here.
Aside: Someone else hit the same problem with js_of_ocaml. It also can’t parse trailing commas. The advice on GitHub is “A workaround is to not pass that file to jsoo and bundle it later”. So the js_of_ocaml parser is a bit outdated. I’m curious, why does it parse JS in the first place?
Trying to take @hhugo’s advice from GitHub, I commented out the js_of_ocaml
clause (as in the current checked-in dune file). This time the build works (great!), but the CodeMirror sources aren’t linked at all. This requires the user to figure out how to link / bundle them by hand, which doesn’t exactly “just work”.
So it seems like the crux of the problem is the js_of_ocaml parser’s incompatibility with JS modules. Has anyone figured out a way to work around this?