Init
Signed-off-by: Skylar "The Cobra" Widulski <cobra@vern.cc>
This commit is contained in:
commit
fdaa3ae41d
|
@ -0,0 +1 @@
|
|||
*.swp
|
|
@ -0,0 +1,56 @@
|
|||
;; Copyright (C) 2023 Skylar Widulski <cobra@vern.cc>
|
||||
;;
|
||||
;; This file is part of MeMe
|
||||
;;
|
||||
;; MeMe is free software: you can redistribute it and/or modify it under the
|
||||
;; terms of the GNU Affero General Public License as published by the Free
|
||||
;; Software Foundation, either version 3 of the License, or (at your option) any
|
||||
;; later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
|
||||
;; for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU Affero General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (meme)
|
||||
#:use-module (meme regex)
|
||||
#:use-module (meme templates)
|
||||
#:use-module (meme pages)
|
||||
#:use-module (meme scraping)
|
||||
#:use-module (web server)
|
||||
#:use-module (web uri)
|
||||
#:use-module (web request)
|
||||
#:use-module (web http)
|
||||
#:use-module (ice-9 textual-ports))
|
||||
|
||||
(define (handler request request-body)
|
||||
(let ((uri (request-uri request))
|
||||
(path (uri-path (request-uri request)))
|
||||
(path-components
|
||||
(split-and-decode-uri-path
|
||||
(uri-path
|
||||
(request-uri request)))))
|
||||
(cond
|
||||
((equal? path "/style.css")
|
||||
(values '((content-type . (text/css)))
|
||||
(call-with-input-file "static/style.css" get-string-all)))
|
||||
((equal? path "/proxy")
|
||||
(proxy-page (uri-query uri)))
|
||||
((or (equal? path "/")
|
||||
(equal? (car path-components)
|
||||
"page"))
|
||||
(article-list-page path))
|
||||
(else (error-page 404)))))
|
||||
|
||||
|
||||
(if (not (provided? 'regex))
|
||||
(begin
|
||||
(display "A POSIX regex library is required")
|
||||
(newline)
|
||||
(quit 1)))
|
||||
|
||||
(run-server handler 'http '(#:port 8003
|
||||
#:addr 0))
|
|
@ -0,0 +1,69 @@
|
|||
;; Copyright (C) 2023 Skylar Widulski <cobra@vern.cc>
|
||||
;;
|
||||
;; This file is part of MeMe
|
||||
;;
|
||||
;; MeMe is free software: you can redistribute it and/or modify it under the
|
||||
;; terms of the GNU Affero General Public License as published by the Free
|
||||
;; Software Foundation, either version 3 of the License, or (at your option) any
|
||||
;; later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
|
||||
;; for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU Affero General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (meme pages)
|
||||
#:use-module (meme templates)
|
||||
#:use-module (web response)
|
||||
#:use-module (web client)
|
||||
#:use-module (ice-9 receive)
|
||||
#:export (error-page
|
||||
article-list-page
|
||||
proxy-page))
|
||||
|
||||
(define base-url "https://knowyourmeme.com")
|
||||
|
||||
(define good-response
|
||||
(build-response #:code 200
|
||||
#:headers `((content-type . (text/html)))))
|
||||
|
||||
(define (error-page code)
|
||||
(values (build-response #:code code
|
||||
#:headers `((content-type . (text/html)))) (error-template code)))
|
||||
|
||||
(define (article-list-page path)
|
||||
(let ((resp "")
|
||||
(body ""))
|
||||
(receive (_resp _body) (http-request (string-append base-url path))
|
||||
(set! resp _resp)
|
||||
(set! body _body))
|
||||
(if (equal? (response-code resp) 200)
|
||||
(begin
|
||||
(values good-response (article-list-template body)))
|
||||
|
||||
(error-page (response-code resp)))))
|
||||
|
||||
(define (proxy-page query)
|
||||
(let ((resp "")
|
||||
(body "")
|
||||
(url ""))
|
||||
(map (lambda (p)
|
||||
(if (equal? (car p) "url")
|
||||
(set! url (cadr p))))
|
||||
(map (lambda (s)
|
||||
(string-split s #\=))
|
||||
(string-split (substring query 0) #\&)))
|
||||
(if (equal? (substring url 0 22) "https://i.kym-cdn.com/")
|
||||
(begin
|
||||
(receive (_resp _body) (http-request url)
|
||||
(set! resp _resp)
|
||||
(set! body _body))
|
||||
(if (equal? (response-code resp) 200)
|
||||
(values (build-response #:code 200
|
||||
#:headers `((content-type . ,(response-content-type resp))))
|
||||
body)
|
||||
(error-page 404)))
|
||||
(error-page 400))))
|
|
@ -0,0 +1,58 @@
|
|||
;; Copyright (C) 2023 Skylar Widulski <cobra@vern.cc>
|
||||
;;
|
||||
;; This file is part of MeMe
|
||||
;;
|
||||
;; MeMe is free software: you can redistribute it and/or modify it under the
|
||||
;; terms of the GNU Affero General Public License as published by the Free
|
||||
;; Software Foundation, either version 3 of the License, or (at your option) any
|
||||
;; later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
|
||||
;; for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU Affero General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (meme regex)
|
||||
#:use-module (ice-9 regex)
|
||||
#:export (no-post-regex
|
||||
leaderboard-regex
|
||||
trending-section-regex
|
||||
trending-regex
|
||||
articles-section-regex
|
||||
articles-regex
|
||||
sidebar-section-regex
|
||||
sidebar-gallery-regex
|
||||
sidebar-trending-regex
|
||||
pagination-regex))
|
||||
|
||||
(define no-post-regex (make-regexp "([^<>]*)[<>]"))
|
||||
|
||||
(define leaderboard-regex
|
||||
(make-regexp "<li data-index='[0-9]+'> <article class='rel c entry' id='([^']*)'> <a href=\"([^\"]*)\" class=\"photo left\" target=\"_self\"><img alt=\"[^\"]*\" fetchpriority=\"low\" height=\"112\" src=\"([^\"]*)\" title=\"[^\"]*\" width=\"198\" /> <div class='info abs'> <div class='c'> ([^<]*) </div> </div> </a></article> </li>"))
|
||||
|
||||
(define trending-section-regex
|
||||
(make-regexp "<section id=\"trending-bar\">(.*)</section>"))
|
||||
|
||||
(define trending-regex
|
||||
(make-regexp "<a href=\"([^\"]*)\" title=\"[^\"]*\">([^<>]*)</a>"))
|
||||
|
||||
(define articles-section-regex
|
||||
(make-regexp "<div class='newsfeed' id='feed_items'>([^<>]*)</div>"))
|
||||
|
||||
(define articles-regex
|
||||
(make-regexp "<article class='nf_item [^']* c' data-title=['\"][^=]*['\"] data-type='[^']*' id='([^']*)'>\n<div class='c rel'>\n(<div class=\"faves abs\"><div class='fave'>\n<a href=\"[^\"]*\" class=\"favorite\" data-item-id=\"[^\"]*\" data-item-type=\"[^\"]*\" data-method=\"post\" data-remote=\"true\" rel=\"nofollow\" title=\"[^\"]*\"><span class=\"num\">([^<>]*)</span>\n</a></div>\n</div>\n|)<section>\n<h1><a href=\"([^\"]*)\" class=\"newsfeed-title\" title=\"([^\"]*)\">[^<>]*</a></h1>\n(<div class='media'>\n)?<div class=\"media\">(<a href=\"([^\"]*)\" class=\"stamp newsfeed-stamp label( newsfeed-stamp-tooltip)?\" rel=\"nofollow\" style=\"background-color: #[^\"]*\" target=\"_self\" title=\"([^\"]*)\">([^<>]*)</a>)? ?<a href=\"[^\"]*\" class=\"newsfeed-image\" rel=\"nofollow\">(<div class=\"play large-video\"></div>\n)?<picture><source srcset=\"([^\"]*)\" /><img alt=\"[^\"]*\" class=\"newsfeed_photo\" data-src=\"[^\"]*\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" title=\"[^\"]*\" width=\"680\" /></picture></a></div>\n(</div>\n)?<br>\n<div class=\"summary\">(<p>([^\x02]*)\x02</p>)?</div>\n<p class=\"left_aligned_timestamp\"><em>([^<>]*)</em></p>\n<p><a href=\"[^\"]*\" class=\"comments_count newsfeed-comments\" rel=\"nofollow\">([^<>]*) comments</a></p>\n</section>\n</div>\n</article>"))
|
||||
|
||||
(define sidebar-section-regex
|
||||
(make-regexp "<aside class='right' id='sidebar'>\n*(.*)</aside>"))
|
||||
|
||||
(define sidebar-gallery-regex
|
||||
(make-regexp "<div class='sidebar_box c' id='[^']*'> <h3> ([^<>]*) </h3> <table> <tr class='row-[0-9]+'> <td> <a href=\"([^\"]*)\"><img alt=\"([^\"]*)\"( class=\"top-gallery-thumbnail\")? data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> <h4> <a href=\"[^\"]*\">([^<>]*)</a> </h4> </td> <td> <a href=\"([^\"]*)\"><img alt=\"([^\"]*)\"( class=\"top-gallery-thumbnail\")? data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> <h4> <a href=\"[^\"]*\">([^<>]*)</a> </h4> </td> </tr> <tr class='row-[0-9]+'> <td> <a href=\"([^\"]*)\"><img alt=\"([^\"]*)\"( class=\"top-gallery-thumbnail\")? data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> <h4> <a href=\"[^\"]*\">([^<>]*)</a> </h4> </td> <td> <a href=\"([^\"]*)\"><img alt=\"([^\"]*)\"( class=\"top-gallery-thumbnail\")? data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> <h4> <a href=\"[^\"]*\">([^<>]*)</a> </h4> </td> </tr> </table> </div>"))
|
||||
|
||||
(define sidebar-trending-regex
|
||||
(make-regexp "<div class='sidebar_box' id='[^']*'> <h3> <a href=\"([^\"]*)\">([^<>]*)</a> </h3> <table> <tr> <td> <a href=\"([^\"]*)\"><img alt=\"[^\"]*\" data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> </td> <td> <a href=\"([^\"]*)\"><img alt=\"[^\"]*\" data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> </td> <td> <a href=\"([^\"]*)\"><img alt=\"[^\"]*\" data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> </td> </tr> <tr> <td> <a href=\"([^\"]*)\"><img alt=\"[^\"]*\" data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> </td> <td> <a href=\"([^\"]*)\"><img alt=\"[^\"]*\" data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> </td> <td> <a href=\"([^\"]*)\"><img alt=\"[^\"]*\" data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> </td> </tr> <tr> <td> <a href=\"([^\"]*)\"><img alt=\"[^\"]*\" data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> </td> <td> <a href=\"([^\"]*)\"><img alt=\"[^\"]*\" data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> </td> <td> <a href=\"([^\"]*)\"><img alt=\"[^\"]*\" data-src=\"([^\"]*)\" height=\"[^\"]*\" loading=\"lazy\" src=\"[^\"]*\" width=\"[^\"]*\" /></a> </td> </tr> </table> </div>"))
|
||||
|
||||
(define pagination-regex
|
||||
(make-regexp "(<div class=\"pagination\">[^\n]*</div>)</div>"))
|
|
@ -0,0 +1,101 @@
|
|||
;; Copyright (C) 2023 Skylar Widulski <cobra@vern.cc>
|
||||
;;
|
||||
;; This file is part of MeMe
|
||||
;;
|
||||
;; MeMe is free software: you can redistribute it and/or modify it under the
|
||||
;; terms of the GNU Affero General Public License as published by the Free
|
||||
;; Software Foundation, either version 3 of the License, or (at your option) any
|
||||
;; later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
|
||||
;; for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU Affero General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (meme scraping)
|
||||
#:use-module (meme regex)
|
||||
#:use-module (ice-9 regex)
|
||||
#:use-module (ice-9 string-fun)
|
||||
#:export (get-leaderboard
|
||||
get-trending
|
||||
get-articles
|
||||
get-sidebar-gallery
|
||||
get-sidebar-trending
|
||||
get-pagination))
|
||||
|
||||
(define (no-post reg)
|
||||
(regexp-substitute/global #f no-post-regex reg 1))
|
||||
|
||||
(define (get-leaderboard body)
|
||||
(map (lambda (s)
|
||||
(string-split s #\x01))
|
||||
(string-split
|
||||
(no-post
|
||||
(regexp-substitute/global #f leaderboard-regex body
|
||||
1 "\x01" 2 "\x01" 3 "\x01" 4 "\x00" 'post))
|
||||
#\x00)))
|
||||
|
||||
(define (get-trending body)
|
||||
(map (lambda (s)
|
||||
(string-split s #\x01))
|
||||
(string-split
|
||||
(no-post
|
||||
(regexp-substitute/global #f trending-regex
|
||||
(regexp-substitute/global
|
||||
#f trending-section-regex body 1)
|
||||
1 "\x01" 2 "\x00" 'post))
|
||||
#\x00)))
|
||||
|
||||
(define (get-articles body)
|
||||
(map (lambda (s)
|
||||
(string-split s #\x01))
|
||||
(string-split
|
||||
(no-post
|
||||
(regexp-substitute/global #f articles-regex
|
||||
(regexp-substitute/global
|
||||
#f articles-section-regex
|
||||
(string-replace-substring
|
||||
body
|
||||
"</p></div>"
|
||||
"\x02</p></div>") 1)
|
||||
1 "\x01" 3 "\x01" 4 "\x01" 5 "\x01"
|
||||
8 "\x01" 10 "\x01" 11 "\x01" 13 "\x01"
|
||||
16 "\x01" 17 "\x01" 18 "\x00" 'post))
|
||||
#\x00)))
|
||||
|
||||
(define (get-sidebar-gallery body)
|
||||
(map (lambda (s)
|
||||
(string-split s #\x01))
|
||||
(string-split
|
||||
(no-post
|
||||
(regexp-substitute/global #f sidebar-gallery-regex
|
||||
(regexp-substitute/global
|
||||
#f sidebar-section-regex body 1)
|
||||
1 "\x01" 2 "\x01" 3 "\x01" 5 "\x01"
|
||||
6 "\x01" 7 "\x01" 8 "\x01" 10 "\x01"
|
||||
11 "\x01" 12 "\x01" 13 "\x01" 15 "\x01"
|
||||
16 "\x01" 17 "\x01" 18 "\x01" 20 "\x01"
|
||||
21 "\x00" 'post))
|
||||
#\x00)))
|
||||
|
||||
(define (get-sidebar-trending body)
|
||||
(map (lambda (s)
|
||||
(string-split s #\x01))
|
||||
(string-split
|
||||
(no-post
|
||||
(regexp-substitute/global #f sidebar-trending-regex
|
||||
(regexp-substitute/global
|
||||
#f sidebar-section-regex body 1)
|
||||
1 "\x01" 2 "\x01" 3 "\x01" 4 "\x01"
|
||||
5 "\x01" 6 "\x01" 7 "\x01" 8 "\x01"
|
||||
9 "\x01" 10 "\x01" 11 "\x01" 12 "\x01"
|
||||
13 "\x01" 14 "\x01" 15 "\x01" 16 "\x01"
|
||||
17 "\x01" 18 "\x01" 19 "\x01" 20 "\x00"
|
||||
'post))
|
||||
#\x00)))
|
||||
|
||||
(define (get-pagination body)
|
||||
(regexp-substitute/global #f pagination-regex body 1))
|
|
@ -0,0 +1,274 @@
|
|||
;; Copyright (C) 2023 Skylar Widulski <cobra@vern.cc>
|
||||
;;
|
||||
;; This file is part of MeMe
|
||||
;;
|
||||
;; MeMe is free software: you can redistribute it and/or modify it under the
|
||||
;; terms of the GNU Affero General Public License as published by the Free
|
||||
;; Software Foundation, either version 3 of the License, or (at your option) any
|
||||
;; later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
|
||||
;; for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU Affero General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (meme templates)
|
||||
#:use-module (meme scraping)
|
||||
#:use-module (htmlprag)
|
||||
#:export (error-template
|
||||
article-list-template))
|
||||
|
||||
(define (proxy url)
|
||||
(string-append "/proxy?url=" url))
|
||||
|
||||
(define (html-head title)
|
||||
`(head (title ,title)
|
||||
(meta (@ (charset "UTF-8")))
|
||||
(meta (@ (name "viewport") (content "width=device-width")))
|
||||
(link (@ (rel "stylesheet") (href "/style.css")))
|
||||
(link (@ (rel "icon") (type "image/png") (href "/favicon.png")))))
|
||||
|
||||
(define heading
|
||||
`(header
|
||||
(div (@ (class "box heading"))
|
||||
(ul (@ (class "navbar"))
|
||||
(li (@ (class "home"))
|
||||
(a (@ (href "/")) "home"))
|
||||
(li (@ (class "memes"))
|
||||
(a (@ (href "/memes")) "memes")
|
||||
(div (@ (class "dropdown box"))
|
||||
(ul
|
||||
(li (a (@ (href "/memes/submissions")) "submissions"))
|
||||
(li (a (@ (href "/memes/researching")) "researching"))
|
||||
(li (a (@ (href "/memes/newsworthy")) "newsworthy"))
|
||||
(li (a (@ (href "/memes/popular")) "popular"))
|
||||
(li (a (@ (href "/memes/deadpool")) "deadpool"))
|
||||
(li (a (@ (href "/memes/all")) "all")))))
|
||||
(li (@ (class "categories"))
|
||||
(a (@ (href "/categories")) "categories")
|
||||
(div (@ (class "dropdown box"))
|
||||
(ul
|
||||
(li (a (@ (href "/categories/culture")) "cultures"))
|
||||
(li (a (@ (href "/categories/event")) "events"))
|
||||
(li (a (@ (href "/categories/meme")) "memes"))
|
||||
(li (a (@ (href "/categories/person")) "people"))
|
||||
(li (a (@ (href "/categories/site")) "sites"))
|
||||
(li (a (@ (href "/categories/subculture"))
|
||||
"subcultures")))))
|
||||
(li (@ (class "news"))
|
||||
(a (@ (href "/news")) "news"))
|
||||
(li (@ (class "images"))
|
||||
(a (@ (href "/photos")) "images")
|
||||
(div (@ (class "dropdown box"))
|
||||
(ul
|
||||
(li (a (@ (href "/photos/trending")) "trending"))
|
||||
(li (a (@ (href "/photos/most-commented"))
|
||||
"most comments"))
|
||||
(li (a (@ (href "/photos/most-favorited"))
|
||||
"most favorites"))
|
||||
(li (a (@ (href "/photos/most-liked")) "most likes"))
|
||||
(li (a (@ (href "/photos/least-liked")) "least likes"))
|
||||
(li (a (@ (href "/photos/most-viewed")) "most views"))
|
||||
(li (a (@ (href "/photos/templates")) "template")))))
|
||||
(li (@ (class "videos"))
|
||||
(a (@ (href "/videos")) "videos")
|
||||
(div (@ (class "dropdown box"))
|
||||
(ul
|
||||
(li (a (@ (href "/videos/trending")) "trending"))
|
||||
(li (a (@ (href "/videos/most-commemted"))
|
||||
"most comments"))
|
||||
(li (a (@ (href "/videos/most-favorited"))
|
||||
"most favorites"))
|
||||
(li (a (@ (href "/videos/most-liked")) "most likes"))
|
||||
(li (a (@ (href "/videos/most-viewed"))
|
||||
"most views")))))
|
||||
(li (@ (class "editorials"))
|
||||
(a (@ (href "/editorials")) "editorial")
|
||||
(div (@ (class "dropdown box"))
|
||||
(ul
|
||||
(li (a (@ (href "/editorials/interviews"))
|
||||
"interviews"))
|
||||
(li (a (@ (href "/editorials/in-the-media"))
|
||||
"in the media"))
|
||||
(li (a (@ (href "/editorials/white-papers"))
|
||||
"white papers"))
|
||||
(li (a (@ (href "/editorials/episode-notes"))
|
||||
"episode notes"))
|
||||
(li (a (@ (href "/editorials/behind-the-scenes"))
|
||||
"behind the scenes"))
|
||||
(li (a (@ (href "/editorials/meme-review"))
|
||||
"meme review"))
|
||||
(li (a (@ (href "/editorials/collections"))
|
||||
"collections"))
|
||||
(li (a (@ (href "/editorials/poll")) "poll"))
|
||||
(li (a (@ (href "/editorials/guides")) "guides"))
|
||||
(li (a (@ (href "/editorials/meme-insider"))
|
||||
"meme-insider"))
|
||||
(li (a (@ (href "/editorials/insights"))
|
||||
"insights")))))
|
||||
(li (@ (class "episodes"))
|
||||
(a (@ (href "/episodes"))))))))
|
||||
|
||||
(define (leaderboard-as-sxml leaderboard)
|
||||
`(div (@ (class "leaderboard box"))
|
||||
(ul (@ (class "leaderboard"))
|
||||
,(map (lambda (l)
|
||||
(if (equal? (length l) 4)
|
||||
`(li (@ (id ,(car l)))
|
||||
(a (@ (href ,(cadr l)))
|
||||
(img (@ (src ,(proxy (caddr l)))
|
||||
(alt ,(cadddr l))))
|
||||
(p (@ (class "tooltip box")) ,(cadddr l))))
|
||||
`()))
|
||||
leaderboard))))
|
||||
|
||||
(define (trending-as-sxml trending)
|
||||
`(div (@ (class "trending box"))
|
||||
(p "trending:")
|
||||
,(map (lambda (l)
|
||||
(if (equal? (length l) 2)
|
||||
`(p (a (@ (href ,(car l))) ,(html->shtml (cadr l))))
|
||||
`()))
|
||||
trending)))
|
||||
|
||||
(define (articles-as-sxml articles)
|
||||
`(div (@ (class "articles box"))
|
||||
(ul (@ (class "articles-list"))
|
||||
,(map (lambda (l)
|
||||
(if (equal? (length l) 11)
|
||||
`(li (@ (class "article"))
|
||||
(a (@ (href ,(caddr l)))
|
||||
(h1 ,(html->shtml (cadddr l)))
|
||||
(img (@ (src ,(proxy (car (list-tail l 7))))
|
||||
(alt ,(cadddr l))))
|
||||
,(if (not (equal? (car (list-tail l 8)) "#f"))
|
||||
`(p ,(html->shtml (car (list-tail l 8))))
|
||||
`())
|
||||
(ul (@ (class "rl"))
|
||||
(li (@ (class "list-date"))
|
||||
(i ,(car (list-tail l 9))))
|
||||
(li (@ (class "list-favcom"))
|
||||
,(string-append
|
||||
(if (not (equal? (cadr l) "#f"))
|
||||
(string-append (cadr l)
|
||||
" favorites, ")
|
||||
"")
|
||||
(car (list-tail l 10))
|
||||
" comments"))))
|
||||
(hr))
|
||||
`()))
|
||||
articles))))
|
||||
|
||||
(define (sidebar-gallery-as-sxml sidebar-gallery)
|
||||
`(div (@ (class "sidebar box"))
|
||||
,(map (lambda (l)
|
||||
(if (equal? (length l) 17)
|
||||
`(div
|
||||
(h3 ,(html->shtml (car l)))
|
||||
(table (@ (class "gallery"))
|
||||
(tr (td (a (@ (href ,(cadr l)))
|
||||
(img (@ (src ,(proxy (cadddr l)))
|
||||
(alt ,(caddr l))))
|
||||
(p (b ,(html->shtml
|
||||
(car (list-tail l 4)))))))
|
||||
(td (a (@ (href ,(car (list-tail l 5))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car (list-tail l 7))))
|
||||
(alt ,(car (list-tail l 6)))))
|
||||
(p (b ,(html->shtml
|
||||
(car (list-tail l 8))))))))
|
||||
(tr (td (a (@ (href ,(car (list-tail l 9))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car (list-tail l 11))))
|
||||
(alt ,(car (list-tail l 10)))))
|
||||
(p (b ,(html->shtml
|
||||
(car (list-tail l 12)))))))
|
||||
(td (a (@ (href ,(car (list-tail l 13))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car (list-tail l 15))))
|
||||
(alt ,(car (list-tail l 14)))))
|
||||
(p (b ,(html->shtml
|
||||
(car (list-tail l 16))))))))))
|
||||
`()))
|
||||
sidebar-gallery)))
|
||||
|
||||
(define (sidebar-trending-as-sxml sidebar-trending)
|
||||
`(div (@ (class "sidebar box"))
|
||||
,(map (lambda (l)
|
||||
(if (equal? (length l) 20)
|
||||
`(div
|
||||
(h3 (a (@ (href ,(car l)))
|
||||
,(cadr l)))
|
||||
(table (@ (class "trending-images"))
|
||||
(tr (td (a (@ (href ,(caddr l)))
|
||||
(img (@ (src ,(proxy (cadddr l)))))))
|
||||
(td (a (@ (href ,(car (list-tail l 4))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car (list-tail l 5))))))))
|
||||
(td (a (@ (href ,(car (list-tail l 6))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car (list-tail l 7)))))))))
|
||||
(tr (td (a (@ (href ,(car (list-tail l 8))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car (list-tail l 9))))))))
|
||||
(td (a (@ (href ,(car (list-tail l 10))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car (list-tail l 11))))))))
|
||||
(td (a (@ (href ,(car (list-tail l 12))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car
|
||||
(list-tail l 13)))))))))
|
||||
(tr (td (a (@ (href ,(car (list-tail l 14))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car (list-tail l 15))))))))
|
||||
(td (a (@ (href ,(car (list-tail l 16))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car (list-tail l 17))))))))
|
||||
(td (a (@ (href ,(car (list-tail l 18))))
|
||||
(img (@ (src
|
||||
,(proxy
|
||||
(car
|
||||
(list-tail l 19)))))))))))
|
||||
`()))
|
||||
sidebar-trending)))
|
||||
|
||||
(define (pagination-as-sxml pagination)
|
||||
`(div (@ (class "pagination box"))
|
||||
,(html->shtml pagination)))
|
||||
|
||||
|
||||
|
||||
(define (error-template code)
|
||||
(shtml->html
|
||||
`(html ,(html-head (string-append (number->string code) " | MeMe"))
|
||||
(body
|
||||
,heading
|
||||
(center
|
||||
(h1 (@ (class "error")) ,(number->string code)))))))
|
||||
|
||||
(define (article-list-template body)
|
||||
(shtml->html
|
||||
`(html ,(html-head "MeMe")
|
||||
(body
|
||||
,heading
|
||||
,(leaderboard-as-sxml (get-leaderboard body))
|
||||
,(trending-as-sxml (get-trending body))
|
||||
(div (@ (class "left"))
|
||||
,(articles-as-sxml (get-articles body))
|
||||
,(pagination-as-sxml (get-pagination body)))
|
||||
(div (@ (class "right"))
|
||||
,(sidebar-gallery-as-sxml (get-sidebar-gallery body))
|
||||
,(sidebar-trending-as-sxml (get-sidebar-trending body)))))))
|
|
@ -0,0 +1,172 @@
|
|||
body {
|
||||
font-family: Fira Sans, Liberation Sans, DejaVu Sans, sans-serif;
|
||||
font-size: 1.1em;
|
||||
line-height: 1.5em;
|
||||
color: #ffc8dd;
|
||||
background-color: #2e2016;
|
||||
hyphens: auto;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
line-height: 1.5em;
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
h1.error {
|
||||
line-height: 0;
|
||||
font-size: 20em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #ff99c8;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.box {
|
||||
border: 5px solid #c6888d;
|
||||
border-radius: 5px;
|
||||
margin: 1%;
|
||||
background-color: #473032;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.left {
|
||||
margin: 1%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 60%;
|
||||
float: left;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.right {
|
||||
margin: 1%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 34%;
|
||||
float: right;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.sidebar.box,
|
||||
.articles.box,
|
||||
.pagination.box {
|
||||
margin: 0 0 5% 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.trending.box,
|
||||
.leaderboard.box,
|
||||
.heading.box {
|
||||
line-height: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.leaderboard.box p {
|
||||
line-height: 1.1em;
|
||||
}
|
||||
|
||||
ul.navbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
list-style-type: none;
|
||||
align-items: center;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.dropdown,
|
||||
.tooltip {
|
||||
display: none;
|
||||
position: absolute;
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
padding: 0.5% 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
div.dropdown ul {
|
||||
list-style-type: none;
|
||||
margin-left: -20%;
|
||||
}
|
||||
|
||||
ul.navbar li:hover div.dropdown,
|
||||
div.dropdown:hover,
|
||||
ul.leaderboard li:hover p {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul.leaderboard {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
list-style-type: none;
|
||||
align-items: center;
|
||||
margin: 0%;
|
||||
padding: 1% 0;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
div.trending p {
|
||||
display: inline-block;
|
||||
padding: 0 1%;
|
||||
}
|
||||
|
||||
ul.articles-list {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
li.article img {
|
||||
max-width: 80%;
|
||||
}
|
||||
|
||||
li.article hr {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
ul.rl {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
list-style-type: none;
|
||||
margin-left: -40px;
|
||||
margin-right: 10%;
|
||||
}
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table.gallery tr td {
|
||||
width: 50%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.gallery img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.trending-images tr td {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
table.trending-images img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.articles.box {
|
||||
margin-bottom: 1%;
|
||||
}
|
||||
|
||||
.pagination.box {
|
||||
text-align: center;
|
||||
margin-top: 0;
|
||||
}
|
Loading…
Reference in New Issue