Compare commits

..

No commits in common. "301636d59791b8aa3648bb12ced2f2d35adba420" and "b18a31df4afd296540ed733698b996f2c3979212" have entirely different histories.

12 changed files with 23 additions and 509 deletions

3
.gitignore vendored
View file

@ -10,9 +10,6 @@
# Compiled # Compiled
compiled compiled
/breezewiki
/dist
/breezewiki-dist
# Personal # Personal
/config.ini /config.ini

View file

@ -10,33 +10,23 @@
(prefix-in filter: web-server/dispatchers/dispatch-filter) (prefix-in filter: web-server/dispatchers/dispatch-filter)
(prefix-in files: web-server/dispatchers/dispatch-files) (prefix-in files: web-server/dispatchers/dispatch-files)
"src/config.rkt" "src/config.rkt"
"src/reloadable.rkt" "src/page-category.rkt"
"src/server-utils.rkt") "src/page-not-found.rkt"
"src/page-proxy.rkt"
(define-syntax-rule (require-reloadable filename varname) "src/page-wiki.rkt"
(define varname "src/page-search.rkt")
(reloadable-entry-point->procedure
(make-reloadable-entry-point (quote varname) filename))))
(require-reloadable "src/page-category.rkt" page-category)
(require-reloadable "src/page-home.rkt" page-home)
(require-reloadable "src/page-not-found.rkt" page-not-found)
(require-reloadable "src/page-proxy.rkt" page-proxy)
(require-reloadable "src/page-search.rkt" page-search)
(require-reloadable "src/page-wiki.rkt" page-wiki)
(when (not (config-true? 'debug))
(set-reload-poll-interval! #f))
(reload!)
(define-runtime-path path-static "static") (define-runtime-path path-static "static")
(define mime-types
(hash #".css" #"text/css"
#".svg" #"image/svg+xml"))
(serve/launch/wait (serve/launch/wait
#:listen-ip (if (config-true? 'debug) "127.0.0.1" #f) #:listen-ip (if (config-true? 'debug) "127.0.0.1" #f)
#:port (string->number (config-get 'port)) #:port (string->number (config-get 'port))
(λ (quit) (λ (quit)
(sequencer:make (sequencer:make
(pathprocedure:make "/" page-home)
(pathprocedure:make "/proxy" page-proxy) (pathprocedure:make "/proxy" page-proxy)
(filter:make #rx"^/[a-z-]+/wiki/Category:.+$" (lift:make page-category)) (filter:make #rx"^/[a-z-]+/wiki/Category:.+$" (lift:make page-category))
(filter:make #rx"^/[a-z-]+/wiki/.+$" (lift:make page-wiki)) (filter:make #rx"^/[a-z-]+/wiki/.+$" (lift:make page-wiki))
@ -48,6 +38,6 @@
(struct-copy url u [path (cdr (url-path u))]))) (struct-copy url u [path (cdr (url-path u))])))
#:path->mime-type #:path->mime-type
(lambda (u) (lambda (u)
(ext->mime-type (path-get-extension u))) (hash-ref mime-types (path-get-extension u)))
#:cache-no-cache (config-true? 'debug) #;"browser applies heuristics if unset")) #:cache-no-cache (config-true? 'debug) #;"browser applies heuristics if unset"))
(lift:make page-not-found)))) (lift:make page-not-found))))

View file

@ -1,43 +0,0 @@
#lang racket/base
(require racket/path
racket/runtime-path
net/url
web-server/servlet-dispatch
web-server/dispatchers/filesystem-map
(prefix-in pathprocedure: web-server/dispatchers/dispatch-pathprocedure)
(prefix-in sequencer: web-server/dispatchers/dispatch-sequencer)
(prefix-in lift: web-server/dispatchers/dispatch-lift)
(prefix-in filter: web-server/dispatchers/dispatch-filter)
(prefix-in files: web-server/dispatchers/dispatch-files)
"src/config.rkt"
"src/server-utils.rkt")
(require (only-in "src/page-category.rkt" page-category))
(require (only-in "src/page-home.rkt" page-home))
(require (only-in "src/page-not-found.rkt" page-not-found))
(require (only-in "src/page-proxy.rkt" page-proxy))
(require (only-in "src/page-search.rkt" page-search))
(require (only-in "src/page-wiki.rkt" page-wiki))
(define-runtime-path path-static "static")
(serve/launch/wait
#:listen-ip (if (config-true? 'debug) "127.0.0.1" #f)
#:port (string->number (config-get 'port))
(λ (quit)
(sequencer:make
(pathprocedure:make "/" page-home)
(pathprocedure:make "/proxy" page-proxy)
(filter:make #rx"^/[a-z-]+/wiki/Category:.+$" (lift:make page-category))
(filter:make #rx"^/[a-z-]+/wiki/.+$" (lift:make page-wiki))
(filter:make #rx"^/[a-z-]+/search$" (lift:make page-search))
(filter:make #rx"^/static/" (files:make
#:url->path
(lambda (u)
((make-url->path path-static)
(struct-copy url u [path (cdr (url-path u))])))
#:path->mime-type
(lambda (u)
(ext->mime-type (path-get-extension u)))
#:cache-no-cache (config-true? 'debug) #;"browser applies heuristics if unset"))
(lift:make page-not-found))))

View file

@ -1,77 +0,0 @@
#lang racket/base
(require html-writing
web-server/http
"xexpr-utils.rkt"
"config.rkt")
(provide
page-home)
(module+ test
(require rackunit))
(define examples
'(("crosscode" "CrossCode_Wiki")
("minecraft" "Bricks")
("undertale" "Hot_Dog...%3F")
("tardis" "Eleanor_Blake")
("fireemblem" "God-Shattering_Star")
("fallout" "Pip-Boy_3000")))
(define content
`((h2 "BreezeWiki makes wiki pages on Fandom readable")
(p "It removes ads, videos, and suggested content, leaving you with a clean page that doesn't consume all your data.")
(p "If you're looking for an \"alternative\" to Fandom for writing pages, you should look elsewhere. BreezeWiki only lets you read existing pages.")
(p "BreezeWiki can also be called an \"alternative frontend for Fandom\".")
(h2 "Example pages")
(ul
,@(map (λ (x)
`(li (a (@ (href ,(apply format "/~a/wiki/~a" x)))
,(apply format "~a: ~a" x))))
examples))
(h2 "How to use")
(p "While browsing any page on Fandom, you can replace \"fandom.com\" in the address bar with \"breezewiki.com\" to see the BreezeWiki version of that page.")
(p "After that, you can click the links to navigate around the pages.")
(p "To get back to Fandom, click the link that's at the bottom of the page.")))
(define body
`(html
(head
(meta (@ (name ")viewport") (content "width=device-width, initial-scale=1")))
(title "About | BreezeWiki")
(link (@ (rel "stylesheet") (type "text/css") (href "/static/internal.css")))
(link (@ (rel "stylesheet") (type "text/css") (href "/static/main.css"))))
(body (@ (class "skin-fandomdesktop theme-fandomdesktop-light internal"))
(div (@ (class "main-container"))
(div (@ (class "fandom-community-header__background tileBoth header")))
(div (@ (class "page"))
(main (@ (class "page__main"))
(div (@ (class "custom-top"))
(h1 (@ (class "page-title"))
"About BreezeWiki"))
(div (@ (id "content") #;(class "page-content"))
(div (@ (id "mw-content-text"))
,@content))
(footer (@ (class "custom-footer"))
(div (@ (class "internal-footer"))
(img (@ (class "my-logo") (src "/static/breezewiki.svg")))
,(if (config-get 'instance-is-official)
`(p ,(format "This instance is run by the ~a developer, " (config-get 'application-name))
(a (@ (href "https://cadence.moe/contact"))
"Cadence."))
`(p
,(format "This unofficial instance is based off the ~a source code, but is not controlled by the code developer." (config-get 'application-name))))
(p "Text content on wikis run by Fandom is available under the Creative Commons Attribution-Share Alike License 3.0 (Unported), "
(a (@ (href "https://www.fandom.com/licensing")) "see license info.")
" Media files and official Fandom documents have different copying restrictions.")
(p ,(format "Fandom is a trademark of Fandom, Inc. ~a is not affiliated with Fandom." (config-get 'application-name)))))))))))
(module+ test
(check-not-false (xexp->html body)))
(define (page-home req)
(response/output
#:code 200
(λ (out)
(write-html body out))))

View file

@ -69,7 +69,7 @@
(define data (easy:response-json dest-res)) (define data (easy:response-json dest-res))
(define body (generate-results-page dest-url wikiname query data)) (define body (generate-results-page dest-url wikiname query data))
(when (config-true? 'debug) (when (config-get 'debug)
; used for its side effects ; used for its side effects
; convert to string with error checking, error will be raised if xexp is invalid ; convert to string with error checking, error will be raised if xexp is invalid
(xexp->html body)) (xexp->html body))

View file

@ -168,9 +168,8 @@
(λ (v) (and (has-class? "animated" attributes) (λ (v) (and (has-class? "animated" attributes)
((length v) . > . 1))) ((length v) . > . 1)))
(λ (v) (λ (v)
`((span (@ (class "animated-slot__outer") (style ,(format "--steps: ~a" (length v)))) `((span (@ (class "animated-slot") (style ,(format "--steps: ~a" (length v))))
(span (@ (class "animated-slot__inner")) ,@v)))))
,@v))))))
children))])) children))]))
tree)) tree))
(module+ test (module+ test

View file

@ -1,150 +0,0 @@
#lang racket/base
;;; Source: https://github.com/tonyg/racket-reloadable/blob/master/reloadable/main.rkt
;;; Source commit: cae2a14 from 24 May 2015
;;; Source license: LGPL 3 or later
(provide (struct-out reloadable-entry-point)
reload-poll-interval
set-reload-poll-interval!
reload-failure-retry-delay
reload!
make-reloadable-entry-point
lookup-reloadable-entry-point
reloadable-entry-point->procedure
make-persistent-state)
(require racket/set)
(require racket/string)
(require racket/match)
(require racket/rerequire)
(define reload-poll-interval 0.5) ;; seconds
(define reload-failure-retry-delay (make-parameter 5)) ;; seconds
(struct reloadable-entry-point (name
module-path
identifier-symbol
on-absent
[value #:mutable])
#:prefab)
(define reloadable-entry-points (make-hash))
(define persistent-state (make-hash))
(define (set-reload-poll-interval! v)
(set! reload-poll-interval v))
(define (reloader-main)
(let loop ()
(match (sync (handle-evt (thread-receive-evt)
(lambda (_) (thread-receive)))
(if reload-poll-interval
(handle-evt (alarm-evt (+ (current-inexact-milliseconds)
(* reload-poll-interval 1000)))
(lambda (_) (list #f 'reload)))
never-evt))
[(list ch 'reload)
(define result (do-reload!))
(when (not result) (sleep (reload-failure-retry-delay)))
(when ch (channel-put ch result))])
(loop)))
(define reloader-thread (thread reloader-main))
(define (reloader-rpc . request)
(define ch (make-channel))
(thread-send reloader-thread (cons ch request))
(channel-get ch))
(define (reload!) (reloader-rpc 'reload))
(define first-load? #t)
(define (say-loading-once! port)
(when first-load?
(display "loading support files" port)
(set! first-load? #f)))
(define (handle-loader-output)
(define i (thread-receive))
(define real-error-port (thread-receive))
(say-loading-once! real-error-port)
(let loop ()
(let ([line (read-line i)])
(cond
[(eof-object? line)
(void)]
[(string-contains? line "[load")
(display "." real-error-port)
(loop)]
[#t
(displayln line real-error-port)
(loop)]))))
;; Only to be called from reloader-main
(define (do-reload!)
(define module-paths (for/set ((e (in-hash-values reloadable-entry-points)))
(reloadable-entry-point-module-path e)))
(with-handlers ((exn:fail?
(lambda (e)
(log-error "*** WHILE RELOADING CODE***\n~a"
(parameterize ([current-error-port (open-output-string)])
((error-display-handler) (exn-message e) e)
(get-output-string (current-error-port))))
#f)))
(for ((module-path (in-set module-paths)))
(let ([real-error-port (current-error-port)])
(define-values (i o) (make-pipe))
(parameterize ([current-error-port o])
(define new-thread (thread handle-loader-output))
(thread-send new-thread i)
(thread-send new-thread real-error-port)
(dynamic-rerequire module-path #:verbosity 'all))))
(for ((e (in-hash-values reloadable-entry-points)))
(match-define (reloadable-entry-point _ module-path identifier-symbol on-absent _) e)
(define new-value (if on-absent
(dynamic-require module-path identifier-symbol on-absent)
(dynamic-require module-path identifier-symbol)))
(set-reloadable-entry-point-value! e new-value))
#t))
(define (make-reloadable-entry-point name module-path [identifier-symbol name]
#:on-absent [on-absent #f])
(define key (list module-path name))
(hash-ref reloadable-entry-points
key
(lambda ()
(define e (reloadable-entry-point name module-path identifier-symbol on-absent #f))
(hash-set! reloadable-entry-points key e)
e)))
(define (lookup-reloadable-entry-point name module-path)
(hash-ref reloadable-entry-points
(list module-path name)
(lambda ()
(error 'lookup-reloadable-entry-point
"Reloadable-entry-point ~a not found in module ~a"
name
module-path))))
(define (reloadable-entry-point->procedure e)
(make-keyword-procedure
(lambda (keywords keyword-values . positionals)
(keyword-apply (reloadable-entry-point-value e)
keywords
keyword-values
positionals))))
(define (make-persistent-state name initial-value-thunk)
(hash-ref persistent-state
name
(lambda ()
(define value (initial-value-thunk))
(define handler
(case-lambda
[() value]
[(new-value)
(set! value new-value)
value]))
(hash-set! persistent-state name handler)
handler)))

View file

@ -1,16 +0,0 @@
#lang racket/base
(provide
ext->mime-type)
(module+ test
(require rackunit))
(define hash-ext-mime-type
(hash #".css" #"text/css"
#".svg" #"image/svg+xml"
#".png" #"image/png"))
(define (ext->mime-type ext)
(hash-ref hash-ext-mime-type ext))
(module+ test
(check-equal? (ext->mime-type #".png") #"image/png"))

View file

@ -195,7 +195,6 @@
#:mime-type #"text/plain" #:mime-type #"text/plain"
(λ (out) (λ (out)
(for ([port (list (current-output-port) out)]) (for ([port (list (current-output-port) out)])
(parameterize ([current-error-port out]) (displayln "Exception raised in Racket code at response generation time:" port)
(displayln "Exception raised in Racket code at response generation time:" (current-error-port)) (displayln (exn-message e) port)))))])
((error-display-handler) (exn-message e) e))))))])
body ...)) body ...))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,173 +0,0 @@
:root {
--theme-body-dynamic-color-1: #fff;
--theme-body-dynamic-color-1--rgb: 255,255,255;
--theme-body-dynamic-color-2: #e6e6e6;
--theme-body-dynamic-color-2--rgb: 230,230,230;
--theme-page-dynamic-color-1: #000;
--theme-page-dynamic-color-1--rgb: 0,0,0;
--theme-page-dynamic-color-1--inverted: #fff;
--theme-page-dynamic-color-1--inverted--rgb: 255,255,255;
--theme-page-dynamic-color-2: #3a3a3a;
--theme-page-dynamic-color-2--rgb: 58,58,58;
--theme-sticky-nav-dynamic-color-1: #000;
--theme-sticky-nav-dynamic-color-1--rgb: 0,0,0;
--theme-sticky-nav-dynamic-color-2: #3a3a3a;
--theme-sticky-nav-dynamic-color-2--rgb: 58,58,58;
--theme-link-dynamic-color-1: #000;
--theme-link-dynamic-color-1--rgb: 0,0,0;
--theme-link-dynamic-color-2: #3a3a3a;
--theme-link-dynamic-color-2--rgb: 58,58,58;
--theme-accent-dynamic-color-1: #fff;
--theme-accent-dynamic-color-1--rgb: 255,255,255;
--theme-accent-dynamic-color-2: #e6e6e6;
--theme-accent-dynamic-color-2--rgb: 230,230,230;
--theme-body-background-color: #286cab;
--theme-body-background-color--rgb: 40,108,171;
--theme-body-text-color: #fff;
--theme-body-text-color--rgb: 255,255,255;
--theme-body-text-color--hover: #cccccc;
--theme-sticky-nav-background-color: #ffffff;
--theme-sticky-nav-background-color--rgb: 255,255,255;
--theme-sticky-nav-text-color: #000;
--theme-sticky-nav-text-color--hover: #333333;
--theme-page-background-color: #ffffff;
--theme-page-background-color--rgb: 255,255,255;
--theme-page-background-color--secondary: #f2f2f2;
--theme-page-background-color--secondary--rgb: 242,242,242;
--theme-page-text-color: #3a3a3a;
--theme-page-text-color--rgb: 58,58,58;
--theme-page-text-color--hover: #6d6d6d;
--theme-page-text-mix-color: #9d9d9d;
--theme-page-text-mix-color-95: #f5f5f5;
--theme-page-accent-mix-color: #b6b6b6;
--theme-page-headings-font: 'Rubik';
--theme-link-color: #8a8a8a;
--theme-link-color--rgb: 138,138,138;
--theme-link-color--hover: #565656;
--theme-link-label-color: #000;
--theme-accent-color: #6c6c6c;
--theme-accent-color--rgb: 108,108,108;
--theme-accent-color--hover: #9f9f9f;
--theme-accent-label-color: #fff;
--theme-border-color: #cecece;
--theme-border-color--rgb: 206,206,206;
--theme-alert-color: #bf0017;
--theme-alert-color--rgb: 191,0,23;
--theme-alert-color--hover: #59000a;
--theme-alert-color--secondary: #bf0017;
--theme-alert-label: #fff;
--theme-warning-color: #cf721c;
--theme-warning-color--rgb: 207,114,28;
--theme-warning-color--secondary: #ce711b;
--theme-warning-label: #000;
--theme-success-color: #0c742f;
--theme-success-color--rgb: 12,116,47;
--theme-success-color--secondary: #0c742f;
--theme-success-label: #fff;
--theme-message-color: #753369;
--theme-message-label: #fff;
--theme-community-header-color: #000000;
--theme-community-header-color--hover: #333333;
--theme-background-image-opacity: 100%;
--theme-page-text-opacity-factor: 0.85;
--theme-body-text-opacity-factor: 0.7;
}
.skin-fandomdesktop .CodeMirror{
--codemirror-yellow: #a88d00;
--codemirror-light-blue: #0096fb;
--codemirror-blue: #08f;
--codemirror-green: #290;
--codemirror-red: #f50;
--codemirror-dark-red: #a11;
--codemirror-purple: #80c;
--codemirror-pink: #e0e;
--codemirror-light-gray: #929292;
--codemirror-gray: #789797;
}
.mw-highlight {
--pygments-background: #f4f3f4;
--pygments-err: #f00;
--pygments-c: #408080;
--pygments-k: #008000;
--pygments-o: #666;
--pygments-ch: #408080;
--pygments-cm: #408080;
--pygments-cp: #b17300;
--pygments-cpf: #408080;
--pygments-c1: #408080;
--pygments-cs: #408080;
--pygments-gd: #a00000;
--pygments-gr: #f00;
--pygments-gh: #000080;
--pygments-gi: #009500;
--pygments-go: #808080;
--pygments-gp: #000080;
--pygments-gu: #800080;
--pygments-gt: #04d;
--pygments-kc: #008000;
--pygments-kd: #008000;
--pygments-kn: #008000;
--pygments-kp: #008000;
--pygments-kr: #008000;
--pygments-kt: #b00040;
--pygments-m: #666;
--pygments-s: #ba2121;
--pygments-na: #768826;
--pygments-nb: #008000;
--pygments-nc: #00f;
--pygments-no: #800;
--pygments-nd: #a2f;
--pygments-ni: #7f7f7f;
--pygments-ne: #d2413a;
--pygments-nf: #00f;
--pygments-nl: #818100;
--pygments-nn: #00f;
--pygments-nt: #008000;
--pygments-nv: #19177c;
--pygments-ow: #a2f;
--pygments-w: #808080;
--pygments-mb: #666;
--pygments-mf: #666;
--pygments-mh: #666;
--pygments-mi: #666;
--pygments-mo: #666;
--pygments-sa: #ba2121;
--pygments-sb: #ba2121;
--pygments-sc: #ba2121;
--pygments-dl: #ba2121;
--pygments-sd: #ba2121;
--pygments-s2: #ba2121;
--pygments-se: #b62;
--pygments-sh: #ba2121;
--pygments-si: #b68;
--pygments-sx: #008000;
--pygments-sr: #b68;
--pygments-s1: #ba2121;
--pygments-ss: #19177c;
--pygments-bp: #008000;
--pygments-fm: #00f;
--pygments-vc: #19177c;
--pygments-vg: #19177c;
--pygments-vi: #19177c;
--pygments-vm: #19177c;
--pygments-il: #666;
}
body {
background: linear-gradient(to bottom, rgba(225, 133, 155, 0) 15%, rgba(225, 133, 155, 0.8)), url(/static/internal-background.png);
min-height: 100vh;
padding: 4px;
margin: 0;
}
.page__main {
border-radius: 3px;
padding: 24px 36px;
}
.internal-footer {
max-width: 700px;
}

View file

@ -81,6 +81,9 @@ p {
background-color: var(--theme-page-background-color); background-color: var(--theme-page-background-color);
padding: 3vw; padding: 3vw;
} }
.page table {
color: var(--theme-page-text-color); /* no idea why this needs to be specified, it should inherit from .page */
}
/* table of contents */ /* table of contents */
.toc { .toc {
@ -115,20 +118,6 @@ p {
overflow: auto; overflow: auto;
} }
/* table overrides for dark theme pages */
/* these colours look good in all wikis I tried. colours that don't look good:
--theme-page-background-color--secondary is bad for fallout
--theme-page-accent-mix-color is bad for minecraft */
.wikitable > tr > th, .wikitable > * > tr > th, .va-table th {
background-color: var(--theme-page-dynamic-color-1--inverted);
}
.wikitable td, .va-table td {
background-color: var(--theme-page-text-mix-color-95);
}
.page table {
color: var(--theme-page-text-color); /* no idea why this needs to be specified, it should inherit from .page */
}
/* float right. reorganised from their sheet */ /* float right. reorganised from their sheet */
.tright { .tright {
clear: right; clear: right;
@ -137,7 +126,7 @@ p {
} }
/* indicate wikipedia links */ /* indicate wikipedia links */
.extiw::after, .external::after { .extiw::after {
vertical-align: super; vertical-align: super;
content: "[🡕]"; content: "[🡕]";
font-family: serif; font-family: serif;
@ -184,23 +173,22 @@ figcaption, .lightbox-caption, .thumbcaption {
#mw-content-text .animated > :not(.animated-active), #mw-content-text .animated > .animated-subframe > :not(.animated-active) { #mw-content-text .animated > :not(.animated-active), #mw-content-text .animated > .animated-subframe > :not(.animated-active) {
display: inline-block; display: inline-block;
} }
.animated-slot__outer { .animated-slot {
display: inline-block; display: inline-block;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
width: 32px; width: 32px;
height: 32px; height: 32px;
} }
.animated-slot__inner { .animated-slot > * {
display: inline-block;
animation: slide-up calc(var(--steps) * 1s) steps(var(--steps)) infinite; animation: slide-up calc(var(--steps) * 1s) steps(var(--steps)) infinite;
} }
@keyframes slide-up { @keyframes slide-up {
0% { 0% {
margin-top: 0px; transform: translateY(0);
} }
100% { 100% {
margin-top: calc(-34px * var(--steps)); transform: translateY(calc(-34px * var(--steps)));
} }
} }