Js_of_ocaml & require

What is the proper way to access a third party javascript library in js_of_ocaml? I see the binding guidance, but in JS you usually do something like:

foo = require('something')

I see you can also link your code against JS code but I’m not sure exactly what that means for this case.

You would do the same:

let foo = Js.Unsafe.js_expr "require('something')"

But you get a completely unconstrained object that can be misused in various ways. That is where the documentation about binding javascript code becomes relevant. You need to write an object type that reflects the content of the loaded file in the OCaml world:

class type something = object
   ... (* see documentation of js_of_ocaml *)
end
let foo : something Js.t = Js.Unsafe.js_expr "require('something')"
1 Like

It turns out I’m more confused than I thought I was.

I have a JS library that I would like to use in the frontend. So I build it with npm install and now I have the .min.js I want to use. So I took that and included it in my call to js_of_ocaml:

js_of_ocaml mything.byte something.min.js

How do I access the things in something.min.js though? I actually don’t know a lot about how the ecosystem works, so perhaps this minified code is only meant to be used in Node? could I just included it in a script in HTML rather than compile it in jsoo?

The bytecode file should appear last in the command line invocation. You can either ask js_of_ocaml to bundle the external js for you or just include the external js in its own script tag.

@orbitz I think what you’re asking is, how do I include this library in my program and then call stuff in it.

I’ve sorted this stuff out by stumbling ass backwards. I don’t know if it’s right necessarily, but it certainly works. Here’s an example using two different third-party .js files.

In my index.html I have two script tags to load the libraries (assume they’re the minified versions) before loading my compiled .ml:

<script language="javascript" src="/js/showdown.release.c6379016.js" type="text/javascript"></script>
<script language="javascript" src="/js/xss.release.4947ff98.js" type="text/javascript"></script>

Here in my main .ml file we have two different ways of binding to those libraries, one which calls filterXSS in that xss sanitizing library, and another for producing html from markdown by creating a showdown converter object.

let to_s = Js.to_string ;;

let sanitize html =                                                             
  Js.Unsafe.fun_call (Js.Unsafe.js_expr "filterXSS") [|Js.Unsafe.inject html|]  
;;

let format_message =
  let converter =
    Js.Unsafe.js_expr "new showdown.Converter({simplifiedAutoLink: true, strikethrough: true, openLinksInNewWindow: true, simpleLineBreaks: true, tables: true, emoji: true,      smoothPreview: true})"
  in
  fun m ->
     let html = converter##makeHtml (js m) in
     to_s (sanitize html)
;;

I’m open to the right way of doing this, but I also only had so much time to struggle while scratching my head, unfortunately.

2 Likes

This is where I ended up going. I was hoping I could bundle the code with my code but I couldn’t figure out how to call it, so I sourced it in the HTML like you did. Works good enough!