Skip to content

Commit 577b16c

Browse files
author
Jonathan D.A. Jewell
committed
Use dom-mounter generated artifact for ABI validation in content mounts
1 parent 8eafbb2 commit 577b16c

5 files changed

Lines changed: 96 additions & 132 deletions

File tree

src/content.res

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ let renderPanel = (~title: string, ~detail: string): unit => {
4444
++ "</div>"
4545
++ "</section>"
4646

47-
SafeDOM.mountWhenReady(
47+
ProvenMount.mountWhenReady(
4848
"#blocky-writer-overlay",
4949
html,
5050
~onSuccess={_ => ()},

src/core/ProvenMount.res

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/* SPDX-License-Identifier: AGPL-3.0-or-later WITH Palimpsest */
2+
/* ABI validation is consumed directly from generated artifact:
3+
/mnt/eclipse/repos/rescript-ecosystem/packages/web/dom-mounter/src/SafeDOM.res.js
4+
FFI stays local. */
5+
6+
type mountResult =
7+
| Mounted(Dom.element)
8+
| NotFound(string)
9+
| Failed(string)
10+
11+
type validatedSelector
12+
type validatedHtml
13+
14+
@module("../../../rescript-ecosystem/packages/web/dom-mounter/src/SafeDOM.res.js")
15+
@scope("ProvenSelector")
16+
external validateSelector: string => result<validatedSelector, string> = "validate"
17+
18+
@module("../../../rescript-ecosystem/packages/web/dom-mounter/src/SafeDOM.res.js")
19+
@scope("ProvenSelector")
20+
external selectorToString: validatedSelector => string = "toString"
21+
22+
@module("../../../rescript-ecosystem/packages/web/dom-mounter/src/SafeDOM.res.js")
23+
@scope("ProvenHTML")
24+
external validateHtml: string => result<validatedHtml, string> = "validate"
25+
26+
@module("../../../rescript-ecosystem/packages/web/dom-mounter/src/SafeDOM.res.js")
27+
@scope("ProvenHTML")
28+
external htmlToString: validatedHtml => string = "toString"
29+
30+
let findElement = (selector: string): option<Dom.element> =>
31+
Webapi.Dom.document->Webapi.Dom.Document.querySelector(selector)
32+
33+
let mountInnerHtml = (element: Dom.element, html: string): mountResult => {
34+
try {
35+
element->Webapi.Dom.Element.setInnerHTML(html)
36+
Mounted(element)
37+
} catch {
38+
| _ => Failed("Mount operation failed")
39+
}
40+
}
41+
42+
let mountValidated = (
43+
selector: validatedSelector,
44+
html: validatedHtml,
45+
): mountResult => {
46+
let selectorValue = selectorToString(selector)
47+
let htmlValue = htmlToString(html)
48+
switch findElement(selectorValue) {
49+
| Some(element) => mountInnerHtml(element, htmlValue)
50+
| None => NotFound(selectorValue)
51+
}
52+
}
53+
54+
let mountString = (selector: string, html: string): mountResult => {
55+
switch validateSelector(selector) {
56+
| Error(error) => Failed("Invalid selector: " ++ error)
57+
| Ok(validSelector) =>
58+
switch validateHtml(html) {
59+
| Error(error) => Failed("Invalid HTML: " ++ error)
60+
| Ok(validHtml) => mountValidated(validSelector, validHtml)
61+
}
62+
}
63+
}
64+
65+
let mountSafe = (
66+
selector: string,
67+
html: string,
68+
~onSuccess: Dom.element => unit,
69+
~onError: string => unit,
70+
): unit => {
71+
switch mountString(selector, html) {
72+
| Mounted(element) => onSuccess(element)
73+
| NotFound(value) => onError("Mount point not found: " ++ value)
74+
| Failed(value) => onError(value)
75+
}
76+
}
77+
78+
let domReadyState: unit => string = %raw(`() => document.readyState`)
79+
let onDOMContentLoaded: (unit => unit) => unit = %raw(`(callback) => document.addEventListener("DOMContentLoaded", callback)`)
80+
81+
let onDOMReady = (callback: unit => unit): unit => {
82+
let state = domReadyState()
83+
if state == "complete" || state == "interactive" {
84+
callback()
85+
} else {
86+
onDOMContentLoaded(callback)
87+
}
88+
}
89+
90+
let mountWhenReady = (
91+
selector: string,
92+
html: string,
93+
~onSuccess: Dom.element => unit,
94+
~onError: string => unit,
95+
): unit => onDOMReady(() => mountSafe(selector, html, ~onSuccess, ~onError))

src/core/SafeDOM.res

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/core/SafeDOMABI.res

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/core/SafeDOMFFI.res

Lines changed: 0 additions & 75 deletions
This file was deleted.

0 commit comments

Comments
 (0)