diff --git a/src/application-globals.rkt b/src/application-globals.rkt index de60820..a413785 100644 --- a/src/application-globals.rkt +++ b/src/application-globals.rkt @@ -203,10 +203,11 @@ `(script (@ (type "module") (src ,(get-static-url "search-suggestions.js")))) "") (script (@ (type "module") (src ,(get-static-url "countdown.js")))) + (script (@ (defer) (src ,(get-static-url "tabs.js")))) (link (@ (rel "icon") (href ,(u (λ (v) (config-true? 'strict_proxy)) (λ (v) (u-proxy-url v)) (head-data^-icon-url head-data)))))) - (body (@ (class ,(head-data^-body-class head-data))) + (body (@ (class ,(head-data^-body-class head-data) " bw-tabs-nojs")) ,(let ([extension-eligible? (cond/var [(not req) #f] diff --git a/src/page-wiki-offline.rkt b/src/page-wiki-offline.rkt index 1d0323b..906718d 100644 --- a/src/page-wiki-offline.rkt +++ b/src/page-wiki-offline.rkt @@ -98,16 +98,19 @@ #:head-data head-data #:siteinfo (siteinfo-fetch wikiname) )) - (define redirect-msg ((query-selector (attribute-selector 'class "redirectMsg") body))) (define redirect-query-parameter (dict-ref (url-query (request-uri req)) 'redirect "yes")) + (define redirect-msg ((query-selector (attribute-selector 'class "redirectMsg") body))) + (define redirect-msg-a (if redirect-msg + ((query-selector (λ (t a c) (eq? t 'a)) redirect-msg)) + #f)) (define headers (build-headers always-headers ; redirect-query-parameter: only the string "no" is significant: ; https://github.com/Wikia/app/blob/fe60579a53f16816d65dad1644363160a63206a6/includes/Wiki.php#L367 - (when (and redirect-msg + (when (and redirect-msg-a (not (equal? redirect-query-parameter "no"))) - (let* ([dest (get-attribute 'href (bits->attributes ((query-selector (λ (t a c) (eq? t 'a)) redirect-msg))))] + (let* ([dest (get-attribute 'href (bits->attributes redirect-msg-a))] [value (bytes-append #"0;url=" (string->bytes/utf-8 dest))]) (header #"Refresh" value))))) (when (config-true? 'debug) @@ -123,7 +126,8 @@ ;; page not found on disk, perhaps it's a redirect? redirects are stored in the database (var target (query-maybe-value* "select redirect from page where wikiname = ? and basename = ?" wikiname basename)) [target - (generate-redirect (basename->name-for-query target))] + ; don't url decode the target, or Category: pages will be interpreted as a protocol + (generate-redirect (format "/~a/wiki/~a" wikiname (regexp-replace* #rx"#" target "/")))] ;; breezewiki doesn't have the page archived, see if we can make a network request for it [(not (config-true? 'feature_offline::only)) diff --git a/src/page-wiki.rkt b/src/page-wiki.rkt index 8df701c..ae060d4 100644 --- a/src/page-wiki.rkt +++ b/src/page-wiki.rkt @@ -80,16 +80,19 @@ #:title title #:head-data head-data #:siteinfo siteinfo)) - (define redirect-msg ((query-selector (attribute-selector 'class "redirectMsg") body))) (define redirect-query-parameter (dict-ref (url-query (request-uri req)) 'redirect "yes")) + (define redirect-msg ((query-selector (attribute-selector 'class "redirectMsg") body))) + (define redirect-msg-a (if redirect-msg + ((query-selector (λ (t a c) (eq? t 'a)) redirect-msg)) + #f)) (define headers (build-headers always-headers ; redirect-query-parameter: only the string "no" is significant: ; https://github.com/Wikia/app/blob/fe60579a53f16816d65dad1644363160a63206a6/includes/Wiki.php#L367 - (when (and redirect-msg + (when (and redirect-msg-a (not (equal? redirect-query-parameter "no"))) - (let* ([dest (get-attribute 'href (bits->attributes ((query-selector (λ (t a c) (eq? t 'a)) redirect-msg))))] + (let* ([dest (get-attribute 'href (bits->attributes redirect-msg-a))] [value (bytes-append #"0;url=" (string->bytes/utf-8 dest))]) (header #"Refresh" value))))) (when (config-true? 'debug) diff --git a/static/main.css b/static/main.css index e3c0070..f3e65ff 100644 --- a/static/main.css +++ b/static/main.css @@ -202,11 +202,11 @@ figcaption, .lightbox-caption, .thumbcaption { padding: 0; } -/* show tabs always */ -.wds-tabs__wrapper { +/* show tabs if tabs.js isn't loaded */ +.bw-tabs-nojs .wds-tabs__wrapper { display: none; } -.wds-tab__content { +.bw-tabs-nojs .wds-tab__content { display: block; } @@ -218,6 +218,13 @@ a.ext-audiobutton { /* see hearthstone/wiki/Diablo_(Duels_hero) */ display: inline !important; } +/* hide slideshows since they're broken + * example: ben10/wiki/Celestialsapien_(Classic)#Powers_and_Abilities + */ +.wikia-slideshow { + display: none; +} + /* animated slots */ #mw-content-text .animated > :not(.animated-active), #mw-content-text .animated > .animated-subframe > :not(.animated-active) { display: inline-block; diff --git a/static/tabs.js b/static/tabs.js new file mode 100644 index 0000000..a077efe --- /dev/null +++ b/static/tabs.js @@ -0,0 +1,74 @@ +"use strict"; + +let tabToFind = location.hash.length > 1 ? location.hash.substring(1) : null; +for (let tabber of document.body.querySelectorAll(".wds-tabber")) { + let [tabs, contents] = getTabs(tabber); + + for (let i in tabs) { + let tab = tabs[i]; + let content = contents[i]; + + tab.addEventListener("click", function(e) { + setCurrentTab(tabber, tab, content); + e.preventDefault(); + }); + if (tab.dataset.hash === tabToFind) { + setCurrentTab(tabber, tab, content); + } + } +} +document.body.classList.remove("bw-tabs-nojs"); + + + +function getTabs(tabber) { + let tabs = []; + let contents = []; + + for (let i of tabber.querySelector(".wds-tabs__wrapper").querySelectorAll(".wds-tabs__tab")) { + tabs.push(i); + } + for (let i of tabber.children) { + if (!i.matches(".wds-tab__content")) { + continue; + } + contents.push(i); + } + + return [tabs, contents]; +} + +function getCurrentTab(tabber) { + let tab = null; + let content = null; + + tab = tabber.querySelector(".wds-tabs__wrapper").querySelector(".wds-tabs__tab.wds-is-current"); + for (let i of tabber.children) { + if (!i.matches(".wds-tab__content.wds-is-current")) { + continue; + } + content = i; + break; + } + + return [tab, content]; +} + +function setCurrentTab(tabber, tab, content) { + let [currentTab, currentContent] = getCurrentTab(tabber); + if (currentTab) { + currentTab.classList.remove("wds-is-current"); + } + if (currentContent) { + currentContent.classList.remove("wds-is-current"); + } + + tab.classList.add("wds-is-current"); + content.classList.add("wds-is-current"); + if (tab.dataset.hash) { + let fragment = "#" + tab.dataset.hash; + if (location.hash !== fragment) { + history.pushState(null, "", fragment); + } + } +}