Refactor jsonp js for cuteness
This commit is contained in:
parent
048709b2d1
commit
1dd90f5a7d
5 changed files with 106 additions and 44 deletions
|
|
@ -163,11 +163,13 @@
|
||||||
#:head-data [head-data-in #f]
|
#:head-data [head-data-in #f]
|
||||||
#:siteinfo [siteinfo-in #f]
|
#:siteinfo [siteinfo-in #f]
|
||||||
#:user-cookies [user-cookies-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 siteinfo (or siteinfo-in siteinfo-default))
|
||||||
(define head-data (or head-data-in ((head-data-getter wikiname))))
|
(define head-data (or head-data-in ((head-data-getter wikiname))))
|
||||||
(define user-cookies (or user-cookies-in (user-cookies-getter req)))
|
(define user-cookies (or user-cookies-in (user-cookies-getter req)))
|
||||||
(define origin (format "https://~a.fandom.com" wikiname))
|
(define origin (format "https://~a.fandom.com" wikiname))
|
||||||
|
(define path (or path-in ""))
|
||||||
(define required-styles
|
(define required-styles
|
||||||
(cond
|
(cond
|
||||||
[online-styles
|
[online-styles
|
||||||
|
|
@ -197,7 +199,8 @@
|
||||||
(link (@ (rel "stylesheet") (type "text/css") (href ,(get-static-url "main.css"))))
|
(link (@ (rel "stylesheet") (type "text/css") (href ,(get-static-url "main.css"))))
|
||||||
(script "const BWData = "
|
(script "const BWData = "
|
||||||
,(jsexpr->string (hasheq 'wikiname wikiname
|
,(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)
|
,(if (config-true? 'feature_search_suggestions)
|
||||||
`(script (@ (type "module") (src ,(get-static-url "search-suggestions.js"))))
|
`(script (@ (type "module") (src ,(get-static-url "search-suggestions.js"))))
|
||||||
"")
|
"")
|
||||||
|
|
|
||||||
|
|
@ -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 "internal.css"))))
|
||||||
(link (@ (rel "stylesheet") (type "text/css") (href ,(get-static-url "main.css"))))
|
(link (@ (rel "stylesheet") (type "text/css") (href ,(get-static-url "main.css"))))
|
||||||
(link (@ (rel "icon") (href ,(head-data^-icon-url head-data-default))))
|
(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"))
|
(body (@ (class "skin-fandomdesktop theme-fandomdesktop-light internal"))
|
||||||
(div (@ (class "main-container"))
|
(div (@ (class "main-container"))
|
||||||
(div (@ (class "fandom-community-header__background tileBoth header")))
|
(div (@ (class "fandom-community-header__background tileBoth header")))
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
("prop" . "text|headhtml|langlinks")
|
("prop" . "text|headhtml|langlinks")
|
||||||
("formatversion" . "2")
|
("formatversion" . "2")
|
||||||
("format" . "json")
|
("format" . "json")
|
||||||
("callback" . "wikiPageCallback")))))
|
("callback" . "proxy.wikipage")))))
|
||||||
(define siteinfo-script-url
|
(define siteinfo-script-url
|
||||||
(format "https://~a.fandom.com/api.php?~a"
|
(format "https://~a.fandom.com/api.php?~a"
|
||||||
wikiname
|
wikiname
|
||||||
|
|
@ -39,27 +39,29 @@
|
||||||
("siprop" . "general|rightsinfo")
|
("siprop" . "general|rightsinfo")
|
||||||
("format" . "json")
|
("format" . "json")
|
||||||
("formatversion" . "2")
|
("formatversion" . "2")
|
||||||
("callback" . "siteinfoCallback")))))
|
("callback" . "proxy.siteinfo")))))
|
||||||
|
|
||||||
(define body
|
(define body
|
||||||
(generate-wiki-page
|
(generate-wiki-page
|
||||||
`(div
|
`(div
|
||||||
(noscript "You have to enable JavaScript to load wiki pages. Sorry!")
|
(noscript "You have to enable JavaScript to load wiki pages. Sorry!")
|
||||||
(div (@ (id "loading")))
|
(div (@ (id "loading")))
|
||||||
(progress (@ (id "progress") (style "margin-bottom: 50vh")))
|
(div (@ (id "progress-bar") (style "margin-bottom: 50vh"))
|
||||||
(script ,(format #<<END
|
(progress))
|
||||||
var wikiname = ~v;
|
(script #<<END
|
||||||
var path = ~v;
|
var jsonpData = {}
|
||||||
|
var proxy = new Proxy(jsonpData, {get(obj, prop) { return value => obj[prop] = value }})
|
||||||
END
|
END
|
||||||
wikiname path))
|
)
|
||||||
(script (@ (src ,(get-static-url "jsonp.js"))))
|
|
||||||
(script (@ (async) (src ,wiki-page-script-url)))
|
(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
|
#:req req
|
||||||
#:source-url source-url
|
#:source-url source-url
|
||||||
#:wikiname wikiname
|
#:wikiname wikiname
|
||||||
#:title (url-segments->guess-title segments)
|
#:title (url-segments->guess-title segments)
|
||||||
#:siteinfo siteinfo-default))
|
#:siteinfo siteinfo-default
|
||||||
|
#:path path))
|
||||||
(when (config-true? 'debug)
|
(when (config-true? 'debug)
|
||||||
(xexp->html body))
|
(xexp->html body))
|
||||||
(response/output
|
(response/output
|
||||||
|
|
|
||||||
|
|
@ -97,9 +97,27 @@
|
||||||
|
|
||||||
(define (page-wiki-with-data req)
|
(define (page-wiki-with-data req)
|
||||||
(response-handler
|
(response-handler
|
||||||
|
(let/cc return
|
||||||
(define post-data/bytes (request-post-data/raw req))
|
(define post-data/bytes (request-post-data/raw req))
|
||||||
(when (not post-data/bytes)
|
(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 (bytes->string/utf-8 post-data/bytes))
|
||||||
(define post-data (string->jsexpr post-data/string))
|
(define post-data (string->jsexpr post-data/string))
|
||||||
(define wikiname (jp "/wikiname" post-data))
|
(define wikiname (jp "/wikiname" post-data))
|
||||||
|
|
@ -109,7 +127,7 @@
|
||||||
#:wikiname wikiname
|
#:wikiname wikiname
|
||||||
#:source-url (format "https://~a.fandom.com/wiki/~a" wikiname path)
|
#:source-url (format "https://~a.fandom.com/wiki/~a" wikiname path)
|
||||||
#:data (jp "/data" post-data)
|
#: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 (take-json-rewrite-and-return-page #:req req #:wikiname wikiname #:source-url source-url #:data data #:siteinfo siteinfo)
|
||||||
(define title (jp "/parse/title" data ""))
|
(define title (jp "/parse/title" data ""))
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,40 @@
|
||||||
const loading = document.getElementById("loading")
|
import {h, htm, render, signal, computed, effect} from "./preact.js"
|
||||||
loading.textContent = "Loading, please wait..."
|
const html = htm.bind(h)
|
||||||
const progress = document.getElementById("progress")
|
|
||||||
|
|
||||||
let wikiPage = null
|
// *** Loading indicator
|
||||||
function wikiPageCallback(data) {
|
|
||||||
wikiPage = data
|
|
||||||
cont()
|
|
||||||
}
|
|
||||||
|
|
||||||
let siteinfo = null
|
render(html`Loading, please wait...`, document.getElementById("loading"))
|
||||||
function siteinfoCallback(data) {
|
|
||||||
siteinfo = data
|
// *** 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()
|
cont()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// *** Data upload and download
|
||||||
|
|
||||||
async function cont() {
|
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();
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
|
@ -46,14 +65,34 @@ async function cont() {
|
||||||
document.head.appendChild(imported)
|
document.head.appendChild(imported)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const redirectTo = document.querySelector("#content .redirectMsg a")
|
||||||
|
if (redirectTo) {
|
||||||
|
redirectTo.click()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
xhr.open("POST", "/api/render/wiki")
|
xhr.open("POST", "/api/render/wiki")
|
||||||
xhr.responseType = "document"
|
xhr.responseType = "document"
|
||||||
xhr.send(JSON.stringify({
|
xhr.send(JSON.stringify({
|
||||||
data: wikiPage,
|
data: jsonpData.wikipage,
|
||||||
siteinfo,
|
siteinfo: jsonpData.siteinfo,
|
||||||
wikiname,
|
wikiname: BWData.wikiname,
|
||||||
path
|
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)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue