Support light/dark themes as per Fandom's styles
This commit is contained in:
		
							parent
							
								
									92591a5eab
								
							
						
					
					
						commit
						9afccbb9cd
					
				
					 15 changed files with 157 additions and 18 deletions
				
			
		|  | @ -17,6 +17,7 @@ | ||||||
| (require-reloadable "src/page-proxy.rkt" page-proxy) | (require-reloadable "src/page-proxy.rkt" page-proxy) | ||||||
| (require-reloadable "src/page-redirect-wiki-home.rkt" redirect-wiki-home) | (require-reloadable "src/page-redirect-wiki-home.rkt" redirect-wiki-home) | ||||||
| (require-reloadable "src/page-search.rkt" page-search) | (require-reloadable "src/page-search.rkt" page-search) | ||||||
|  | (require-reloadable "src/page-set-user-settings.rkt" page-set-user-settings) | ||||||
| (require-reloadable "src/page-static.rkt" static-dispatcher) | (require-reloadable "src/page-static.rkt" static-dispatcher) | ||||||
| (require-reloadable "src/page-subdomain.rkt" subdomain-dispatcher) | (require-reloadable "src/page-subdomain.rkt" subdomain-dispatcher) | ||||||
| (require-reloadable "src/page-wiki.rkt" page-wiki) | (require-reloadable "src/page-wiki.rkt" page-wiki) | ||||||
|  | @ -40,6 +41,7 @@ | ||||||
|       page-not-found |       page-not-found | ||||||
|       page-proxy |       page-proxy | ||||||
|       page-search |       page-search | ||||||
|  |       page-set-user-settings | ||||||
|       page-wiki |       page-wiki | ||||||
|       page-file |       page-file | ||||||
|       redirect-wiki-home |       redirect-wiki-home | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								dist.rkt
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								dist.rkt
									
										
									
									
									
								
							|  | @ -11,6 +11,7 @@ | ||||||
| (require (only-in "src/page-proxy.rkt" page-proxy)) | (require (only-in "src/page-proxy.rkt" page-proxy)) | ||||||
| (require (only-in "src/page-redirect-wiki-home.rkt" redirect-wiki-home)) | (require (only-in "src/page-redirect-wiki-home.rkt" redirect-wiki-home)) | ||||||
| (require (only-in "src/page-search.rkt" page-search)) | (require (only-in "src/page-search.rkt" page-search)) | ||||||
|  | (require (only-in "src/page-set-user-settings.rkt" page-set-user-settings)) | ||||||
| (require (only-in "src/page-static.rkt" static-dispatcher)) | (require (only-in "src/page-static.rkt" static-dispatcher)) | ||||||
| (require (only-in "src/page-subdomain.rkt" subdomain-dispatcher)) | (require (only-in "src/page-subdomain.rkt" subdomain-dispatcher)) | ||||||
| (require (only-in "src/page-wiki.rkt" page-wiki)) | (require (only-in "src/page-wiki.rkt" page-wiki)) | ||||||
|  | @ -29,6 +30,7 @@ | ||||||
|     page-not-found |     page-not-found | ||||||
|     page-proxy |     page-proxy | ||||||
|     page-search |     page-search | ||||||
|  |     page-set-user-settings | ||||||
|     page-wiki |     page-wiki | ||||||
|     page-file |     page-file | ||||||
|     redirect-wiki-home |     redirect-wiki-home | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								info.rkt
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								info.rkt
									
										
									
									
									
								
							|  | @ -1,3 +1,3 @@ | ||||||
| #lang info | #lang info | ||||||
| 
 | 
 | ||||||
| (define build-deps '("rackunit-lib" "web-server-lib" "http-easy-lib" "html-parsing" "html-writing" "json-pointer" "ini-lib" "memo")) | (define build-deps '("rackunit-lib" "web-server-lib" "http-easy-lib" "html-parsing" "html-writing" "json-pointer" "ini-lib" "memo" "net-cookies-lib")) | ||||||
|  |  | ||||||
|  | @ -1,8 +1,10 @@ | ||||||
| #lang racket/base | #lang racket/base | ||||||
| (require racket/list | (require racket/file | ||||||
|  |          racket/list | ||||||
|          racket/string |          racket/string | ||||||
|          json |          json | ||||||
|          (prefix-in easy: net/http-easy) |          (prefix-in easy: net/http-easy) | ||||||
|  |          html-parsing | ||||||
|          html-writing |          html-writing | ||||||
|          web-server/http |          web-server/http | ||||||
|          "config.rkt" |          "config.rkt" | ||||||
|  | @ -34,6 +36,11 @@ | ||||||
|         (header #"Link" (string->bytes/latin-1 link-header)))) |         (header #"Link" (string->bytes/latin-1 link-header)))) | ||||||
| (define timeouts (easy:make-timeout-config #:lease 5 #:connect 5)) | (define timeouts (easy:make-timeout-config #:lease 5 #:connect 5)) | ||||||
| 
 | 
 | ||||||
|  | (define theme-icons | ||||||
|  |   (for/hasheq ([theme '(default light dark)]) | ||||||
|  |     (values theme | ||||||
|  |             (html->xexp (file->string (format "static/icon-theme-~a.svg" theme) #:mode 'binary))))) | ||||||
|  | 
 | ||||||
| (define (application-footer source-url #:license [license-in #f]) | (define (application-footer source-url #:license [license-in #f]) | ||||||
|   (define license (or license-in license-default)) |   (define license (or license-in license-default)) | ||||||
|   `(footer (@ (class "custom-footer")) |   `(footer (@ (class "custom-footer")) | ||||||
|  | @ -98,24 +105,27 @@ | ||||||
| 
 | 
 | ||||||
| (define (generate-wiki-page | (define (generate-wiki-page | ||||||
|          content |          content | ||||||
|  |          #:req req | ||||||
|          #:source-url source-url |          #:source-url source-url | ||||||
|          #:wikiname wikiname |          #:wikiname wikiname | ||||||
|          #:title title |          #:title title | ||||||
|          #: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]) | ||||||
|   (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 (required-styles origin) |   (define (required-styles origin) | ||||||
|     (map (λ (dest-path) |     (map (λ (dest-path) | ||||||
|            (define url (format dest-path origin)) |            (define url (format dest-path origin)) | ||||||
|            (if (config-true? 'strict_proxy) |            (if (config-true? 'strict_proxy) | ||||||
|                (u-proxy-url url) |                (u-proxy-url url) | ||||||
|                url)) |                url)) | ||||||
|          '(#;"~a/load.php?lang=en&modules=skin.fandomdesktop.styles&only=styles&skin=fandomdesktop" |          `(#;"~a/load.php?lang=en&modules=skin.fandomdesktop.styles&only=styles&skin=fandomdesktop" | ||||||
|            #;"~a/load.php?lang=en&modules=ext.gadget.dungeonsWiki%2CearthWiki%2Csite-styles%2Csound-styles&only=styles&skin=fandomdesktop" |            #;"~a/load.php?lang=en&modules=ext.gadget.dungeonsWiki%2CearthWiki%2Csite-styles%2Csound-styles&only=styles&skin=fandomdesktop" | ||||||
|            #;"~a/load.php?lang=en&modules=site.styles&only=styles&skin=fandomdesktop" |            #;"~a/load.php?lang=en&modules=site.styles&only=styles&skin=fandomdesktop" | ||||||
|            ; combine the above entries into a single request for potentially extra speed - fandom.com doesn't even do this! |            ; combine the above entries into a single request for potentially extra speed - fandom.com doesn't even do this! | ||||||
|            "~a/wikia.php?controller=ThemeApi&method=themeVariables" |            ,(format "~~a/wikia.php?controller=ThemeApi&method=themeVariables&variant=~a" (user-cookies^-theme user-cookies)) | ||||||
|            "~a/load.php?lang=en&modules=skin.fandomdesktop.styles%7Cext.fandom.PortableInfoboxFandomDesktop.css%7Cext.fandom.GlobalComponents.CommunityHeaderBackground.css%7Cext.gadget.site-styles%2Csound-styles%7Csite.styles&only=styles&skin=fandomdesktop"))) |            "~a/load.php?lang=en&modules=skin.fandomdesktop.styles%7Cext.fandom.PortableInfoboxFandomDesktop.css%7Cext.fandom.GlobalComponents.CommunityHeaderBackground.css%7Cext.gadget.site-styles%2Csound-styles%7Csite.styles&only=styles&skin=fandomdesktop"))) | ||||||
|   `(*TOP* |   `(*TOP* | ||||||
|     (*DECL* DOCTYPE html) |     (*DECL* DOCTYPE html) | ||||||
|  | @ -155,7 +165,22 @@ | ||||||
|                                            (label (@ (for "bw-search-input")) "Search ") |                                            (label (@ (for "bw-search-input")) "Search ") | ||||||
|                                            (div (@ (id "bw-pr-search-input")) |                                            (div (@ (id "bw-pr-search-input")) | ||||||
|                                                 (input (@ (type "text") (name "q") (id "bw-search-input") (autocomplete "off")))) |                                                 (input (@ (type "text") (name "q") (id "bw-search-input") (autocomplete "off")))) | ||||||
|                                            (div (@ (class "bw-ss__container") (id "bw-pr-search-suggestions")))))) |                                            (div (@ (class "bw-ss__container") (id "bw-pr-search-suggestions")))) | ||||||
|  |                                      (div (@ (class "bw-theme__select")) | ||||||
|  |                                           (span (@ (class "bw-theme__main-label")) "Page theme") | ||||||
|  |                                           (div (@ (class "bw-theme__items")) | ||||||
|  |                                            ,@(for/list ([theme '(default light dark)]) | ||||||
|  |                                                (define class | ||||||
|  |                                                  (if (equal? theme (user-cookies^-theme user-cookies)) | ||||||
|  |                                                      "bw-theme__item bw-theme__item--selected" | ||||||
|  |                                                      "bw-theme__item")) | ||||||
|  |                                                `(a (@ (href ,(user-cookies-setter-url | ||||||
|  |                                                               req | ||||||
|  |                                                               (struct-copy user-cookies^ user-cookies | ||||||
|  |                                                                            [theme theme]))) (class ,class)) | ||||||
|  |                                                    (div (@ (class "bw-theme__icon-container")) | ||||||
|  |                                                     ,(hash-ref theme-icons theme)) | ||||||
|  |                                                    ,(format "~a" theme))))))) | ||||||
|                            (div (@ (id "content") #;(class "page-content")) |                            (div (@ (id "content") #;(class "page-content")) | ||||||
|                                 (div (@ (id "mw-content-text")) |                                 (div (@ (id "mw-content-text")) | ||||||
|                                      ,content)) |                                      ,content)) | ||||||
|  | @ -179,11 +204,11 @@ | ||||||
|                                  page)))) |                                  page)))) | ||||||
|                "/proxy?dest=https%3A%2F%2Ftest.fandom.com"))) |                "/proxy?dest=https%3A%2F%2Ftest.fandom.com"))) | ||||||
| 
 | 
 | ||||||
| (define (generate-redirect dest) | (define (generate-redirect dest #:headers [headers-in '()]) | ||||||
|   (define dest-bytes (string->bytes/utf-8 dest)) |   (define dest-bytes (string->bytes/utf-8 dest)) | ||||||
|   (response/output |   (response/output | ||||||
|    #:code 302 |    #:code 302 | ||||||
|    #:headers (list (header #"Location" dest-bytes)) |    #:headers (append (list (header #"Location" dest-bytes)) headers-in) | ||||||
|    (λ (out) |    (λ (out) | ||||||
|      (write-html |      (write-html | ||||||
|       `(html |       `(html | ||||||
|  |  | ||||||
							
								
								
									
										34
									
								
								src/data.rkt
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								src/data.rkt
									
										
									
									
									
								
							|  | @ -1,6 +1,9 @@ | ||||||
| #lang racket/base | #lang racket/base | ||||||
| (require racket/list | (require racket/list | ||||||
|          racket/match |          racket/match | ||||||
|  |          web-server/http/request-structs | ||||||
|  |          net/url-string | ||||||
|  |          (only-in net/cookies/server cookie-header->alist cookie->set-cookie-header make-cookie) | ||||||
|          (prefix-in easy: net/http-easy) |          (prefix-in easy: net/http-easy) | ||||||
|          memo |          memo | ||||||
|          "static-data.rkt" |          "static-data.rkt" | ||||||
|  | @ -11,11 +14,16 @@ | ||||||
|  (struct-out siteinfo^) |  (struct-out siteinfo^) | ||||||
|  (struct-out license^) |  (struct-out license^) | ||||||
|  (struct-out head-data^) |  (struct-out head-data^) | ||||||
|  |  (struct-out user-cookies^) | ||||||
|  siteinfo-fetch |  siteinfo-fetch | ||||||
|  siteinfo-default |  siteinfo-default | ||||||
|  license-default |  license-default | ||||||
|  head-data-getter |  head-data-getter | ||||||
|  head-data-default) |  head-data-default | ||||||
|  |  user-cookies-getter | ||||||
|  |  user-cookies-default | ||||||
|  |  user-cookies-setter | ||||||
|  |  user-cookies-setter-url) | ||||||
| 
 | 
 | ||||||
| (struct siteinfo^ (sitename basepage license) #:transparent) | (struct siteinfo^ (sitename basepage license) #:transparent) | ||||||
| (struct license^ (text url) #:transparent) | (struct license^ (text url) #:transparent) | ||||||
|  | @ -61,3 +69,27 @@ | ||||||
|       (set! this-data data)) |       (set! this-data data)) | ||||||
|     ;; then no matter what, return the best information we have so far |     ;; then no matter what, return the best information we have so far | ||||||
|     this-data)) |     this-data)) | ||||||
|  | 
 | ||||||
|  | (struct user-cookies^ (theme) #:prefab) | ||||||
|  | (define user-cookies-default (user-cookies^ 'default)) | ||||||
|  | (define (user-cookies-getter req) | ||||||
|  |   (define cookie-header (headers-assq* #"cookie" (request-headers/raw req))) | ||||||
|  |   (define cookies-alist (if cookie-header (cookie-header->alist (header-value cookie-header) bytes->string/utf-8) null)) | ||||||
|  |   (define cookies-hash | ||||||
|  |     (for/hasheq ([pair cookies-alist]) | ||||||
|  |       (match pair | ||||||
|  |         [(cons "theme" (and theme (or "light" "dark" "default"))) | ||||||
|  |          (values 'theme (string->symbol theme))] | ||||||
|  |         [_ (values #f #f)]))) | ||||||
|  |   (user-cookies^ | ||||||
|  |    (hash-ref cookies-hash 'theme (user-cookies^-theme user-cookies-default)))) | ||||||
|  | 
 | ||||||
|  | (define (user-cookies-setter user-cookies) | ||||||
|  |   (map (λ (c) (header #"Set-Cookie" (cookie->set-cookie-header c))) | ||||||
|  |        (list (make-cookie "theme" (symbol->string (user-cookies^-theme user-cookies)) | ||||||
|  |                           #:path "/" | ||||||
|  |                           #:max-age (* 60 60 24 365 10))))) | ||||||
|  | 
 | ||||||
|  | (define (user-cookies-setter-url req new-settings) | ||||||
|  |   (format "/set-user-settings?~a"  (params->query `(("ref" . ,(url->string (request-uri req))) | ||||||
|  |                                                     ("new_settings" . ,(format "~a" new-settings)))))) | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ | ||||||
|    (pathprocedure:make "/" (hash-ref ds 'page-home)) |    (pathprocedure:make "/" (hash-ref ds 'page-home)) | ||||||
|    (pathprocedure:make "/proxy" (hash-ref ds 'page-proxy)) |    (pathprocedure:make "/proxy" (hash-ref ds 'page-proxy)) | ||||||
|    (pathprocedure:make "/search" (hash-ref ds 'page-global-search)) |    (pathprocedure:make "/search" (hash-ref ds 'page-global-search)) | ||||||
|  |    (pathprocedure:make "/set-user-settings" (hash-ref ds 'page-set-user-settings)) | ||||||
|    (pathprocedure:make "/buddyfight/wiki/It_Doesn't_Work!!" (hash-ref ds 'page-it-works)) |    (pathprocedure:make "/buddyfight/wiki/It_Doesn't_Work!!" (hash-ref ds 'page-it-works)) | ||||||
|    (filter:make (pregexp (format "^/~a/wiki/Category:.+$" px-wikiname)) (lift:make (hash-ref ds 'page-category))) |    (filter:make (pregexp (format "^/~a/wiki/Category:.+$" px-wikiname)) (lift:make (hash-ref ds 'page-category))) | ||||||
|    (filter:make (pregexp (format "^/~a/wiki/File:.+$" px-wikiname)) (lift:make (hash-ref ds 'page-file))) |    (filter:make (pregexp (format "^/~a/wiki/File:.+$" px-wikiname)) (lift:make (hash-ref ds 'page-file))) | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ | ||||||
|     '#hasheq((batchcomplete . #t) (continue . #hasheq((cmcontinue . "page|4150504c45|41473") (continue . "-||"))) (query . #hasheq((categorymembers . (#hasheq((ns . 0) (pageid . 25049) (title . "Item (entity)")) #hasheq((ns . 0) (pageid . 128911) (title . "3D")) #hasheq((ns . 0) (pageid . 124018) (title . "A Very Fine Item")) #hasheq((ns . 0) (pageid . 142208) (title . "Amethyst Shard")) #hasheq((ns . 0) (pageid . 121612) (title . "Ankle Monitor"))))))))) |     '#hasheq((batchcomplete . #t) (continue . #hasheq((cmcontinue . "page|4150504c45|41473") (continue . "-||"))) (query . #hasheq((categorymembers . (#hasheq((ns . 0) (pageid . 25049) (title . "Item (entity)")) #hasheq((ns . 0) (pageid . 128911) (title . "3D")) #hasheq((ns . 0) (pageid . 124018) (title . "A Very Fine Item")) #hasheq((ns . 0) (pageid . 142208) (title . "Amethyst Shard")) #hasheq((ns . 0) (pageid . 121612) (title . "Ankle Monitor"))))))))) | ||||||
| 
 | 
 | ||||||
| (define (generate-results-page | (define (generate-results-page | ||||||
|  |          #:req req | ||||||
|          #:source-url source-url |          #:source-url source-url | ||||||
|          #:wikiname wikiname |          #:wikiname wikiname | ||||||
|          #:title title |          #:title title | ||||||
|  | @ -38,6 +39,7 @@ | ||||||
|          #:siteinfo [siteinfo #f]) |          #:siteinfo [siteinfo #f]) | ||||||
|   (define members (jp "/query/categorymembers" members-data)) |   (define members (jp "/query/categorymembers" members-data)) | ||||||
|   (generate-wiki-page |   (generate-wiki-page | ||||||
|  |    #:req req | ||||||
|    #:source-url source-url |    #:source-url source-url | ||||||
|    #:wikiname wikiname |    #:wikiname wikiname | ||||||
|    #:title title |    #:title title | ||||||
|  | @ -96,6 +98,7 @@ | ||||||
|     (define page (html->xexp page-html)) |     (define page (html->xexp page-html)) | ||||||
|     (define head-data ((head-data-getter wikiname) page-data)) |     (define head-data ((head-data-getter wikiname) page-data)) | ||||||
|     (define body (generate-results-page |     (define body (generate-results-page | ||||||
|  |                   #:req req | ||||||
|                   #:source-url source-url |                   #:source-url source-url | ||||||
|                   #:wikiname wikiname |                   #:wikiname wikiname | ||||||
|                   #:title title |                   #:title title | ||||||
|  |  | ||||||
|  | @ -51,7 +51,8 @@ | ||||||
|     [(regexp-match? #rx"(?i:^video/)" content-type) `(video (@ (src ,maybe-proxied-url) (controls)))] |     [(regexp-match? #rx"(?i:^video/)" content-type) `(video (@ (src ,maybe-proxied-url) (controls)))] | ||||||
|     [else `""])) |     [else `""])) | ||||||
| 
 | 
 | ||||||
| (define (generate-results-page #:source-url source-url | (define (generate-results-page #:req req | ||||||
|  |                                #:source-url source-url | ||||||
|                                #:wikiname wikiname |                                #:wikiname wikiname | ||||||
|                                #:title title |                                #:title title | ||||||
|                                #:media-detail media-detail |                                #:media-detail media-detail | ||||||
|  | @ -68,6 +69,7 @@ | ||||||
|   (define maybe-proxied-raw-image-url |   (define maybe-proxied-raw-image-url | ||||||
|     (if (config-true? 'strict_proxy) (u-proxy-url raw-image-url) raw-image-url)) |     (if (config-true? 'strict_proxy) (u-proxy-url raw-image-url) raw-image-url)) | ||||||
|   (generate-wiki-page |   (generate-wiki-page | ||||||
|  |    #:req req | ||||||
|    #:source-url source-url |    #:source-url source-url | ||||||
|    #:wikiname wikiname |    #:wikiname wikiname | ||||||
|    #:title title |    #:title title | ||||||
|  | @ -125,7 +127,8 @@ | ||||||
|                          #f |                          #f | ||||||
|                          (url-content-type (jp "/imageUrl" media-detail)))) |                          (url-content-type (jp "/imageUrl" media-detail)))) | ||||||
|                    (define body |                    (define body | ||||||
|                      (generate-results-page #:source-url source-url |                      (generate-results-page #:req req | ||||||
|  |                                             #:source-url source-url | ||||||
|                                             #:wikiname wikiname |                                             #:wikiname wikiname | ||||||
|                                             #:title title |                                             #:title title | ||||||
|                                             #:media-detail media-detail |                                             #:media-detail media-detail | ||||||
|  |  | ||||||
|  | @ -25,9 +25,10 @@ | ||||||
|   (define search-json-data |   (define search-json-data | ||||||
|     '#hasheq((batchcomplete . #t) (query . #hasheq((search . (#hasheq((ns . 0) (pageid . 219) (size . 1482) (snippet . "") (timestamp . "2022-08-21T08:54:23Z") (title . "Gacha Capsule") (wordcount . 214)) #hasheq((ns . 0) (pageid . 201) (size . 1198) (snippet . "") (timestamp . "2022-07-11T17:52:47Z") (title . "Badges") (wordcount . 181))))))))) |     '#hasheq((batchcomplete . #t) (query . #hasheq((search . (#hasheq((ns . 0) (pageid . 219) (size . 1482) (snippet . "") (timestamp . "2022-08-21T08:54:23Z") (title . "Gacha Capsule") (wordcount . 214)) #hasheq((ns . 0) (pageid . 201) (size . 1198) (snippet . "") (timestamp . "2022-07-11T17:52:47Z") (title . "Badges") (wordcount . 181))))))))) | ||||||
| 
 | 
 | ||||||
| (define (generate-results-page dest-url wikiname query data #:siteinfo [siteinfo #f]) | (define (generate-results-page req dest-url wikiname query data #:siteinfo [siteinfo #f]) | ||||||
|   (define search-results (jp "/query/search" data)) |   (define search-results (jp "/query/search" data)) | ||||||
|   (generate-wiki-page |   (generate-wiki-page | ||||||
|  |    #:req req | ||||||
|    #:source-url dest-url |    #:source-url dest-url | ||||||
|    #:wikiname wikiname |    #:wikiname wikiname | ||||||
|    #:title query |    #:title query | ||||||
|  | @ -74,7 +75,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 #:siteinfo siteinfo)) |     (define body (generate-results-page req dest-url wikiname query data #:siteinfo siteinfo)) | ||||||
|     (when (config-true? 'debug) |     (when (config-true? '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 | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								src/page-set-user-settings.rkt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/page-set-user-settings.rkt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | #lang racket/base | ||||||
|  | (require racket/dict | ||||||
|  |          net/url | ||||||
|  |          web-server/http | ||||||
|  |          "application-globals.rkt" | ||||||
|  |          "data.rkt" | ||||||
|  |          "url-utils.rkt" | ||||||
|  |          "xexpr-utils.rkt") | ||||||
|  | 
 | ||||||
|  | (provide | ||||||
|  |  page-set-user-settings) | ||||||
|  | 
 | ||||||
|  | (define (page-set-user-settings req) | ||||||
|  |   (response-handler | ||||||
|  |    (define ref (dict-ref (url-query (request-uri req)) 'ref)) | ||||||
|  |    (define new-settings (read (open-input-string (dict-ref (url-query (request-uri req)) 'new_settings)))) | ||||||
|  |    (define headers (user-cookies-setter new-settings)) | ||||||
|  |    (generate-redirect ref #:headers headers))) | ||||||
|  | @ -276,6 +276,7 @@ | ||||||
| 
 | 
 | ||||||
| (define (page-wiki req) | (define (page-wiki req) | ||||||
|   (define wikiname (path/param-path (first (url-path (request-uri req))))) |   (define wikiname (path/param-path (first (url-path (request-uri req))))) | ||||||
|  |   (define user-cookies (user-cookies-getter req)) | ||||||
|   (define origin (format "https://~a.fandom.com" wikiname)) |   (define origin (format "https://~a.fandom.com" wikiname)) | ||||||
|   (define path (string-join (map path/param-path (cddr (url-path (request-uri req)))) "/")) |   (define path (string-join (map path/param-path (cddr (url-path (request-uri req)))) "/")) | ||||||
|   (define source-url (format "https://~a.fandom.com/wiki/~a" wikiname path)) |   (define source-url (format "https://~a.fandom.com/wiki/~a" wikiname path)) | ||||||
|  | @ -290,7 +291,9 @@ | ||||||
|                                          ("formatversion" . "2") |                                          ("formatversion" . "2") | ||||||
|                                          ("format" . "json"))))) |                                          ("format" . "json"))))) | ||||||
|               (log-outgoing dest-url) |               (log-outgoing dest-url) | ||||||
|               (easy:get dest-url #:timeouts timeouts)] |               (easy:get dest-url | ||||||
|  |                         #:timeouts timeouts | ||||||
|  |                         #:headers `#hasheq((cookie . ,(format "theme=~a" (user-cookies^-theme user-cookies)))))] | ||||||
|     [siteinfo (siteinfo-fetch wikiname)]) |     [siteinfo (siteinfo-fetch wikiname)]) | ||||||
| 
 | 
 | ||||||
|    (cond |    (cond | ||||||
|  | @ -307,6 +310,7 @@ | ||||||
|              (define body |              (define body | ||||||
|                (generate-wiki-page |                (generate-wiki-page | ||||||
|                 (update-tree-wiki page wikiname) |                 (update-tree-wiki page wikiname) | ||||||
|  |                 #:req req | ||||||
|                 #:source-url source-url |                 #:source-url source-url | ||||||
|                 #:wikiname wikiname |                 #:wikiname wikiname | ||||||
|                 #:title title |                 #:title title | ||||||
|  | @ -317,9 +321,9 @@ | ||||||
|                (build-headers |                (build-headers | ||||||
|                 always-headers |                 always-headers | ||||||
|                 (when redirect-msg |                 (when redirect-msg | ||||||
|                     (let* ([dest (get-attribute 'href (bits->attributes ((query-selector (λ (t a c) (eq? t 'a)) redirect-msg))))] |                   (let* ([dest (get-attribute 'href (bits->attributes ((query-selector (λ (t a c) (eq? t 'a)) redirect-msg))))] | ||||||
|                            [value (bytes-append #"0;url=" (string->bytes/utf-8 dest))]) |                          [value (bytes-append #"0;url=" (string->bytes/utf-8 dest))]) | ||||||
|                       (header #"Refresh" value))))) |                     (header #"Refresh" value))))) | ||||||
|              (when (config-true? 'debug) |              (when (config-true? '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 | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								static/icon-theme-dark.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								static/icon-theme-dark.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <svg fill="currentColor" width="32" height="32" version="1.1" viewBox="0 0 8.46667 8.46667" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -288.533)"><path transform="matrix(.264583 0 0 .264583 0 288.533)" d="m23.0039 3.875-1.31445 2.27344a11 11 0 013.31055 7.85156 11 11 0 01-11 11 11 11 0 01-7.85938-3.30664l-2.26172 1.30859c2.93591 5.08516 8.77013 7.80476 14.5527 6.78516 5.78263-1.01964 10.3378-5.57482 11.3574-11.3574 1.01965-5.7826-1.7-11.6188-6.78516-14.5547z" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" shape-rendering="auto" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;paint-order:stroke fill markers;shape-padding:0;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/><circle cx="2.11667" cy="290.65" r=".529167" style="paint-order:stroke fill markers"/><circle cx="1.5875" cy="292.237" r=".529167" style="paint-order:stroke fill markers"/><circle cx="3.70417" cy="290.121" r=".529167" style="paint-order:stroke fill markers"/></g></svg> | ||||||
| After Width: | Height: | Size: 1.3 KiB | 
							
								
								
									
										2
									
								
								static/icon-theme-default.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								static/icon-theme-default.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <svg width="32" height="32" fill="currentColor" version="1.1" viewBox="0 0 8.46667 8.46667" xmlns="http://www.w3.org/2000/svg"><path d="m4.23242.5295c-2.03949 0-3.70313 1.66559-3.70313 3.70508 0 2.03948 1.66364 3.70312 3.70313 3.70312 2.03949 0 3.70508-1.66364 3.70508-3.70312 0-2.03949-1.66559-3.70508-3.70508-3.70508zm0 1.05859c1.46752 0 2.64648 1.17897 2.64648 2.64649s-1.17896 2.64453-2.64648 2.64453c-1.46752 0-2.64453-1.17701-2.64453-2.64453s1.17701-2.64649 2.64453-2.64649z" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" shape-rendering="auto" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;paint-order:stroke fill markers;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/><path d="m4.23333 2.64583a1.5875 1.5875 0 00-1.495 1.05937h2.99a1.5875 1.5875 0 00-1.495-1.05937zm-1.495 2.11563a1.5875 1.5875 0 001.495 1.05937 1.5875 1.5875 0 001.495-1.05937h-2.99z" style="paint-order:stroke fill markers"/></svg> | ||||||
| After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										2
									
								
								static/icon-theme-light.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								static/icon-theme-light.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <svg fill="currentColor" width="32" height="32" version="1.1" viewBox="0 0 8.46667 8.46667" xmlns="http://www.w3.org/2000/svg"><path d="m6.87891 4.23458c1e-7.46447-.121282.92002-.353516 1.32226l.916016.5293c.325095-.56308.496094-1.20137.496094-1.85156z" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" shape-rendering="auto" solid-style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;paint-order:stroke fill markers;shape-padding:0;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/><circle cx="4.23333" cy="4.234" r="2.11093" style="paint-order:stroke fill markers"/><g shape-rendering="auto"><path d="m5.55695 6.52551c-.402234.23223-.858376.35329-1.32285.35329l-.0003772 1.05794c.650186 0 1.28846-.17106 1.85154-.49615z" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" solid-style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;paint-order:stroke fill markers;shape-padding:0;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/><path d="m2.91165 6.52543c-.402243-.23223-.737813-.56603-.970048-.96827l-.916389.52865c.325097.56308.794061 1.03129 1.35714 1.35639z" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" solid-style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;paint-order:stroke fill markers;shape-padding:0;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/><path d="m1.58789 4.23458c-1e-7-.46447.121282-.92198.353516-1.32422l-.916016-.5293c-.325095.56308-.496094 1.20333-.496094 1.85352z" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" solid-style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;paint-order:stroke fill markers;shape-padding:0;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/><path d="m2.91046 1.94167c.402243-.23224.858389-.35329 1.32285-.35329l-.0005978-1.05964c-.650195 1e-5-1.28847.17106-1.85155.49616z" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" solid-style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;paint-order:stroke fill markers;shape-padding:0;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/><path d="m5.55547 1.9423c.402243.23223.736121.56504.968351.96728l.916397-.52864c-.325092-.56309-.792372-1.03031-1.35545-1.35541z" color-rendering="auto" dominant-baseline="auto" image-rendering="auto" solid-style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;paint-order:stroke fill markers;shape-padding:0;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/></g></svg> | ||||||
| After Width: | Height: | Size: 3.8 KiB | 
|  | @ -51,7 +51,7 @@ p { | ||||||
| .custom-top { | .custom-top { | ||||||
|     display: flex; |     display: flex; | ||||||
|     flex-wrap: wrap; |     flex-wrap: wrap; | ||||||
|     align-items: baseline; |     align-items: center; | ||||||
|     justify-content: space-between; |     justify-content: space-between; | ||||||
| } | } | ||||||
| .page-title { | .page-title { | ||||||
|  | @ -227,6 +227,7 @@ figcaption, .lightbox-caption, .thumbcaption { | ||||||
|     display: grid; |     display: grid; | ||||||
|     grid-template-columns: auto 1fr; |     grid-template-columns: auto 1fr; | ||||||
|     grid-gap: 0px 5px; |     grid-gap: 0px 5px; | ||||||
|  |     align-items: baseline; | ||||||
| } | } | ||||||
| .bw-ss__container { | .bw-ss__container { | ||||||
|     grid-column: 2; |     grid-column: 2; | ||||||
|  | @ -282,6 +283,47 @@ figcaption, .lightbox-caption, .thumbcaption { | ||||||
|     text-align: left; |     text-align: left; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* (breezewiki) theme selector */ | ||||||
|  | .bw-theme__select { | ||||||
|  |     display: grid; | ||||||
|  |     grid-template-columns: auto auto; | ||||||
|  |     grid-gap: 0px 5px; | ||||||
|  |     justify-content: right; | ||||||
|  |     align-items: baseline; | ||||||
|  |     margin-top: 4px; | ||||||
|  | } | ||||||
|  | .bw-theme__items { | ||||||
|  |     display: flex; | ||||||
|  | } | ||||||
|  | .bw-theme__item { | ||||||
|  |     display: flex; | ||||||
|  |     align-items: baseline; | ||||||
|  |     padding: 2px; | ||||||
|  |     border: 1px solid var(--theme-border-color); | ||||||
|  |     border-right-width: 0px; | ||||||
|  |     background-color: var(--custom-table-background); | ||||||
|  |     color: var(--theme-page-text-color); | ||||||
|  |     transition: none; | ||||||
|  | } | ||||||
|  | .bw-theme__item:hover, .bw-theme__item:focus { | ||||||
|  |     /* background-color: var(--theme-page-background-color); */ | ||||||
|  |     color: var(--theme-accent-color); | ||||||
|  | } | ||||||
|  | .bw-theme__item:first-child { | ||||||
|  |     border-radius: 4px 0px 0px 4px; | ||||||
|  | } | ||||||
|  | .bw-theme__item:last-child { | ||||||
|  |     border-radius: 0px 4px 4px 0px; | ||||||
|  |     border-right-width: 1px; | ||||||
|  | } | ||||||
|  | .bw-theme__item--selected, .bw-theme__item--selected:hover, .bw-theme__item--selected:focus { | ||||||
|  |     background-color: var(--theme-accent-color); | ||||||
|  |     color: var(--theme-accent-label-color); | ||||||
|  | } | ||||||
|  | .bw-theme__icon-container svg { | ||||||
|  |     vertical-align: middle; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* nintendo independent wiki alliance notice */ | /* nintendo independent wiki alliance notice */ | ||||||
| .niwa__notice { | .niwa__notice { | ||||||
|     background: #fdedd8; |     background: #fdedd8; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue