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

mdoc.js: support ES modules and SmallModulesFor #638

Open
armanbilge opened this issue Apr 5, 2022 · 3 comments
Open

mdoc.js: support ES modules and SmallModulesFor #638

armanbilge opened this issue Apr 5, 2022 · 3 comments

Comments

@armanbilge
Copy link
Contributor

armanbilge commented Apr 5, 2022

Scala.js 1.10.0 added ModuleSplitStyle.SmallModulesFor to enable fast, iterative development of Scala.js apps.

The typical usage pattern is to list the application’s packages as argument. This way, often-changing classes receive independent, small modules, while the stable classes coming from libraries are bundled together as much as possible.

https://www.scala-js.org/news/2022/04/04/announcing-scalajs-1.10.0/#new-module-split-style-smallmodulesforpackages

IIUC all mdocs are compiled under the mdoc package so I expect that would be the argument to use for this setting. Then, mdoc --watch can provide a supercharged dev cycle.

@armanbilge
Copy link
Contributor Author

armanbilge commented Apr 5, 2022

Btw, I don't think this should be too hard to support. I think the key change here is adding support for ESModules, which means:

  1. supporting multiple JS file output from the linker
  2. Using in the browser with <script type="module" src="..."></script>

After enabling ES modules for (the non-mdoc part of) my project, the only change I had to make was (2).

@Quafadas
Copy link
Contributor

Quafadas commented Jul 5, 2024

I did a little investigation on this, as it's something I would like... from the outside, it doesn't look tooooo hard to get ESModules working.

In the first instance the module emitted by the linker, seems fine... as arman pointed out.

Let's assume we ran mdoc, on readme.md. I think the readme.js file emitted, should change to say.

<div id="mdoc-html-run1" data-mdoc-js></div>
<script type="module" src="readme.md.js"></script>
<script type="module" src="mdoc.js"></script>

instead of

<div id="mdoc-html-run1" data-mdoc-js></div>
<script type="text/javascript" src="readme.md.js" defer></script>
<script type="text/javascript" src="mdoc.js" defer></script>

So that change seems easy enough (famous last words). To keep the CLI working nicely however, I think it may also be necessary, to alter mdoc.js. Currently, it looks like this.

import { mdoc_js_run0 } from "./readme.md.js";

(function (global) {
  function findDivs() {
    return Array.from(global.document.querySelectorAll("div[data-mdoc-js]"));
  }

  function loadAll(scope) {    
    findDivs().forEach(function (el) {
      const idNum = el.getAttribute("id");
      console.log(idNum);
      var id = el.getAttribute("id").replace("-html-", "_js_");
      // eval(id)(el);
      mdoc_js_run0(el);
    });s
  }

  loadAll(global);
})(window);

I would propose, to make it look like this;

(function (global) {
  function findDivs() {
    return Array.from(global.document.querySelectorAll("div[data-mdoc-js]"));
  }

  function loadAll(scope) {
    findDivs().forEach(function (el) {

      var id = el.getAttribute("id").replace("-html-", "_js_");

      // https://stackoverflow.com/questions/2033711/how-can-i-attach-meta-data-to-a-dom-node
      const moduleName = el.getAttribute("data-mdoc-module-name");

      import(moduleName).then(function (module) {
      //import("./readme.md.js").then(function (module) {
        module[id](el);
      });
    });
  }

  loadAll(global);
})(window);

This would dynamically load the module, and then run the function it exports. i.e. preserve the existing live reload CLI functionality.

As things stand, it would require emitting an extra attribute on each of the divs that mdoc adds.

<div id="mdoc-html-run0" data-mdoc-js></div> would need to become

<div id="mdoc-html-run0" data-mdoc-js data-mdoc-module-name="readme.md.js" ></div>

I believe this would solve the ESModule problem, which I think is the key first step. It should be relatively simpler to then follow through on the SmallestModuleFor and EsModuleImportMap pieces later...

@Quafadas
Copy link
Contributor

Quafadas commented Jul 5, 2024

Here's my initial experiment in this.

https://github.com/Quafadas/mdoc_test

@Quafadas Quafadas mentioned this issue Jul 5, 2024
3 tasks
tgodzik pushed a commit that referenced this issue Jul 9, 2024
Add basic support for ES modules related to #638
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

No branches or pull requests

2 participants