To give some ideas, here’s how I would approach it:
-- public/index.html
<html>
...
<script src="./Index.js">
...
<!-- Identify the elements which you want to embellish with JS/PS. -->
<div data-ps-widget="ABC"/>
Will probably need to bundle “public/index.js”.
// public/index.js
// Now import and activate all the widgets that appear on "index.html"
var ABC = require("../ps-output/Widget.ABC/index.js");
document.on("load", function() {
document.querySelectorAll('[data-ps-widget]')
.forEach(function(el) {
if (el.getAttribute('data-foo') == "ABC") {
ABC.render(el);
}
if (el.getAttribute('data-foo') == "DEF") {
// Activate multiple widgets on one page if you'd like.
// DEF.render(el);
}
});
});
-- module Widget.ABC where
-- This is a common interface for a component.
// render :: HTMLElement -> Effect Unit
render el = do
-- Activate the component.
-- For example, a spork app.
-- Copied from https://github.com/natefaubion/purescript-spork/blob/master/examples/todo-mvc/src/Main.purs
storedModel ← ...
inst ←
App.make
(liftNat runEffect `merge` never)
(app storedModel)
el
inst.run
void $ hashes \oldHash newHash →
F.for_ (routeAction newHash) \i → do
inst.push i
inst.run
where
app ∷ Maybe StoredModel → App.App Effect (Const Void) Model Action
app storedModel = ...
If Widget.ABC renders a data-ps-widget="DEF" element, this won’t activate it.
This is intended to inspire you with one way to do this. To do that, I think you’ll need to have Widget.ABC execute some code which is like that “public/index.js” file whenever it wants to render a child Spork app, which seems complicated in my mind. Another way would be to use a UI library which supports child components, like Halogen, as I would guess that would be more simple.