Refactor jsonp js for cuteness

This commit is contained in:
Cadence Ember 2025-11-05 16:35:17 +13:00
parent 048709b2d1
commit 1dd90f5a7d
5 changed files with 106 additions and 44 deletions

View file

@ -163,11 +163,13 @@
#:head-data [head-data-in #f]
#:siteinfo [siteinfo-in #f]
#:user-cookies [user-cookies-in #f]
#:online-styles [online-styles #t])
#:online-styles [online-styles #t]
#:path [path-in #f])
(define siteinfo (or siteinfo-in siteinfo-default))
(define head-data (or head-data-in ((head-data-getter wikiname))))
(define user-cookies (or user-cookies-in (user-cookies-getter req)))
(define origin (format "https://~a.fandom.com" wikiname))
(define path (or path-in ""))
(define required-styles
(cond
[online-styles
@ -197,7 +199,8 @@
(link (@ (rel "stylesheet") (type "text/css") (href ,(get-static-url "main.css"))))
(script "const BWData = "
,(jsexpr->string (hasheq 'wikiname wikiname
'strict_proxy (config-true? 'strict_proxy))))
'strict_proxy (config-true? 'strict_proxy)
'path path)))
,(if (config-true? 'feature_search_suggestions)
`(script (@ (type "module") (src ,(get-static-url "search-suggestions.js"))))
"")

View file

@ -92,7 +92,7 @@
(link (@ (rel "stylesheet") (type "text/css") (href ,(get-static-url "internal.css"))))
(link (@ (rel "stylesheet") (type "text/css") (href ,(get-static-url "main.css"))))
(link (@ (rel "icon") (href ,(head-data^-icon-url head-data-default))))
(script (@ (defer) (src "/static/captcha.js")))
(script (@ (defer) (src ,(get-static-url "captcha.js"))))
(body (@ (class "skin-fandomdesktop theme-fandomdesktop-light internal"))
(div (@ (class "main-container"))
(div (@ (class "fandom-community-header__background tileBoth header")))

View file

@ -30,7 +30,7 @@
("prop" . "text|headhtml|langlinks")
("formatversion" . "2")
("format" . "json")
("callback" . "wikiPageCallback")))))
("callback" . "proxy.wikipage")))))
(define siteinfo-script-url
(format "https://~a.fandom.com/api.php?~a"
wikiname
@ -39,27 +39,29 @@
("siprop" . "general|rightsinfo")
("format" . "json")
("formatversion" . "2")
("callback" . "siteinfoCallback")))))
("callback" . "proxy.siteinfo")))))
(define body
(generate-wiki-page
`(div
(noscript "You have to enable JavaScript to load wiki pages. Sorry!")
(div (@ (id "loading")))
(progress (@ (id "progress") (style "margin-bottom: 50vh")))
(script ,(format #<<END
var wikiname = ~v;
var path = ~v;
(div (@ (id "progress-bar") (style "margin-bottom: 50vh"))
(progress))
(script #<<END
var jsonpData = {}
var proxy = new Proxy(jsonpData, {get(obj, prop) { return value => obj[prop] = value }})
END
wikiname path))
(script (@ (src ,(get-static-url "jsonp.js"))))
)
(script (@ (async) (src ,wiki-page-script-url)))
(script (@ (async) (src ,siteinfo-script-url))))
(script (@ (async) (src ,siteinfo-script-url)))
(script (@ (type "module") (src ,(get-static-url "jsonp.js")))))
#:req req
#:source-url source-url
#:wikiname wikiname
#:title (url-segments->guess-title segments)
#:siteinfo siteinfo-default))
#:siteinfo siteinfo-default
#:path path))
(when (config-true? 'debug)
(xexp->html body))
(response/output

View file

@ -97,9 +97,27 @@
(define (page-wiki-with-data req)
(response-handler
(let/cc return
(define post-data/bytes (request-post-data/raw req))
(when (not post-data/bytes)
(raise-user-error 'page-wiki-with-data "POST requests only, please."))
(return (response/jsexpr
#:code 400
#:headers always-headers
'#hasheq((error .
#hasheq((code . "breezewiki")
(info . "POST requests only, please.")))))))
(define origin-header
(or (headers-assq* #"origin" (request-headers/raw req))
(headers-assq* #"referer" (request-headers/raw req))))
(when (or (not origin-header) (not (string-prefix? (bytes->string/latin-1 (header-value origin-header)) (config-get 'canonical_origin))))
(return (response/jsexpr
#:code 400
#:headers always-headers
'#hasheq((error .
#hasheq((code . "breezewiki")
(info . "Origin/Referer header failed validation - cross-origin requests are not allowed here")))))))
(define post-data/string (bytes->string/utf-8 post-data/bytes))
(define post-data (string->jsexpr post-data/string))
(define wikiname (jp "/wikiname" post-data))
@ -109,7 +127,7 @@
#:wikiname wikiname
#:source-url (format "https://~a.fandom.com/wiki/~a" wikiname path)
#:data (jp "/data" post-data)
#:siteinfo (data->siteinfo (jp "/siteinfo" post-data)))))
#:siteinfo (data->siteinfo (jp "/siteinfo" post-data))))))
(define (take-json-rewrite-and-return-page #:req req #:wikiname wikiname #:source-url source-url #:data data #:siteinfo siteinfo)
(define title (jp "/parse/title" data ""))

View file

@ -1,21 +1,40 @@
const loading = document.getElementById("loading")
loading.textContent = "Loading, please wait..."
const progress = document.getElementById("progress")
import {h, htm, render, signal, computed, effect} from "./preact.js"
const html = htm.bind(h)
let wikiPage = null
function wikiPageCallback(data) {
wikiPage = data
// *** Loading indicator
render(html`Loading, please wait...`, document.getElementById("loading"))
// *** Progress bar
const progress = signal(null)
const progressBar = document.getElementById("progress-bar")
while (progressBar.childNodes[0] !== undefined) progressBar.childNodes[0].remove() // clear out loading indicators
render(html`<progress value="${progress}" max="1"></progress>`, progressBar)
// *** Incoming data processing
// Handle case where data is immediately available
cont()
// Handle case where data may become available in the future
window.proxy = new Proxy(jsonpData, {
get(obj, prop) {
return value => {
obj[prop] = value
cont()
}
let siteinfo = null
function siteinfoCallback(data) {
siteinfo = data
cont()
}
})
// *** Data upload and download
async function cont() {
if (!(wikiPage && siteinfo)) return
if (jsonpData.wikipage?.error) return error(jsonpData.wikipage)
if (jsonpData.siteinfo?.error) return error(jsonpData.siteinfo)
if (!(jsonpData.wikipage && jsonpData.siteinfo)) return
const xhr = new XMLHttpRequest();
@ -46,14 +65,34 @@ async function cont() {
document.head.appendChild(imported)
}
}
const redirectTo = document.querySelector("#content .redirectMsg a")
if (redirectTo) {
redirectTo.click()
}
})
xhr.open("POST", "/api/render/wiki")
xhr.responseType = "document"
xhr.send(JSON.stringify({
data: wikiPage,
siteinfo,
wikiname,
path
data: jsonpData.wikipage,
siteinfo: jsonpData.siteinfo,
wikiname: BWData.wikiname,
path: BWData.path
}));
}
function error(data) {
const eContent = document.getElementById("content")
while (eContent.childNodes[0] !== undefined) eContent.childNodes[0].remove() // clear out loading indicators
document.title = `Error | BreezeWiki`
render(html`
${data.error.code === "missingtitle"
? html`<p><strong>This page doesn't exist on Fandom.</strong></p>`
: html`
<p>BreezeWiki wasn't able to load this page.</p>
<p><strong>${data.error.code}: ${data.error.info}</strong></p>
`
}
<p><small><a href="/${BWData.wikiname}/wiki/Main_Page">Return to the homepage?</a></small></p>
`, eContent)
}