From 66c53fbd5cbf4abb5b62dbd7e3c9724b05d45dc3 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Sat, 28 Sep 2013 14:24:28 -0400 Subject: [PATCH] Copied the web directory to work on it locally. --- new-racket-web/web/README | 47 + new-racket-web/web/all.rkt | 5 + new-racket-web/web/build.rkt | 83 + new-racket-web/web/common/distribute.rkt | 29 + new-racket-web/web/common/extras.rkt | 132 + new-racket-web/web/common/layout.rkt | 253 ++ new-racket-web/web/common/links.rkt | 64 + new-racket-web/web/common/logo.png | Bin 0 -> 6717 bytes new-racket-web/web/common/main.rkt | 7 + new-racket-web/web/common/plticon.ico | Bin 0 -> 318 bytes new-racket-web/web/common/resources.rkt | 155 + new-racket-web/web/common/utils.rkt | 52 + new-racket-web/web/config.rkt | 29 + new-racket-web/web/download/all.rkt | 3 + new-racket-web/web/download/data.rkt | 264 ++ .../web/download/download-pages.rkt | 249 ++ new-racket-web/web/download/index.rkt | 21 + .../web/download/installer-pages.rkt | 79 + new-racket-web/web/download/installers.txt | 382 +++ new-racket-web/web/download/mirror-link.rkt | 177 + new-racket-web/web/download/release-info.rkt | 60 + new-racket-web/web/download/resources.rkt | 3 + new-racket-web/web/download/symlinks.rkt | 13 + new-racket-web/web/download/version.rkt | 7 + new-racket-web/web/lang/reader.rkt | 18 + new-racket-web/web/minis/all.rkt | 3 + new-racket-web/web/minis/bugs.rkt | 265 ++ new-racket-web/web/minis/drracket.rkt | 154 + new-racket-web/web/minis/lists.rkt | 168 + new-racket-web/web/stubs/all.rkt | 9 + new-racket-web/web/stubs/blog.rkt | 1084 ++++++ new-racket-web/web/stubs/dirlist.rkt | 19 + new-racket-web/web/stubs/docs.rkt | 11 + new-racket-web/web/stubs/git.rkt | 2939 +++++++++++++++++ new-racket-web/web/stubs/gitweb-logo.png | Bin 0 -> 2767 bytes new-racket-web/web/stubs/mailman.rkt | 633 ++++ new-racket-web/web/stubs/planet.rkt | 17 + new-racket-web/web/stubs/pre.rkt | 299 ++ new-racket-web/web/stubs/wiki.rkt | 11 + new-racket-web/web/www/NEW.html | 525 +++ new-racket-web/web/www/all.rkt | 5 + new-racket-web/web/www/code.rkt | 118 + new-racket-web/web/www/community.rkt | 47 + new-racket-web/web/www/download-dark.png | Bin 0 -> 9493 bytes new-racket-web/web/www/download.png | Bin 0 -> 9564 bytes new-racket-web/web/www/download.rkt | 42 + new-racket-web/web/www/help.rkt | 38 + new-racket-web/web/www/index.rkt | 542 +++ new-racket-web/web/www/irc.rkt | 42 + new-racket-web/web/www/learning.rkt | 102 + new-racket-web/web/www/loud.png | Bin 0 -> 9395 bytes new-racket-web/web/www/new-name.rkt | 171 + new-racket-web/web/www/old-techreports.rkt | 482 +++ new-racket-web/web/www/people.rkt | 108 + new-racket-web/web/www/resources.rkt | 3 + new-racket-web/web/www/techreports.rkt | 105 + new-racket-web/web/www/web-copyright.rkt | 12 + 57 files changed, 10086 insertions(+) create mode 100644 new-racket-web/web/README create mode 100644 new-racket-web/web/all.rkt create mode 100755 new-racket-web/web/build.rkt create mode 100644 new-racket-web/web/common/distribute.rkt create mode 100644 new-racket-web/web/common/extras.rkt create mode 100644 new-racket-web/web/common/layout.rkt create mode 100644 new-racket-web/web/common/links.rkt create mode 100644 new-racket-web/web/common/logo.png create mode 100644 new-racket-web/web/common/main.rkt create mode 100644 new-racket-web/web/common/plticon.ico create mode 100644 new-racket-web/web/common/resources.rkt create mode 100644 new-racket-web/web/common/utils.rkt create mode 100644 new-racket-web/web/config.rkt create mode 100644 new-racket-web/web/download/all.rkt create mode 100644 new-racket-web/web/download/data.rkt create mode 100644 new-racket-web/web/download/download-pages.rkt create mode 100644 new-racket-web/web/download/index.rkt create mode 100644 new-racket-web/web/download/installer-pages.rkt create mode 100644 new-racket-web/web/download/installers.txt create mode 100644 new-racket-web/web/download/mirror-link.rkt create mode 100644 new-racket-web/web/download/release-info.rkt create mode 100644 new-racket-web/web/download/resources.rkt create mode 100644 new-racket-web/web/download/symlinks.rkt create mode 100644 new-racket-web/web/download/version.rkt create mode 100644 new-racket-web/web/lang/reader.rkt create mode 100644 new-racket-web/web/minis/all.rkt create mode 100644 new-racket-web/web/minis/bugs.rkt create mode 100644 new-racket-web/web/minis/drracket.rkt create mode 100644 new-racket-web/web/minis/lists.rkt create mode 100644 new-racket-web/web/stubs/all.rkt create mode 100644 new-racket-web/web/stubs/blog.rkt create mode 100644 new-racket-web/web/stubs/dirlist.rkt create mode 100644 new-racket-web/web/stubs/docs.rkt create mode 100644 new-racket-web/web/stubs/git.rkt create mode 100644 new-racket-web/web/stubs/gitweb-logo.png create mode 100644 new-racket-web/web/stubs/mailman.rkt create mode 100644 new-racket-web/web/stubs/planet.rkt create mode 100644 new-racket-web/web/stubs/pre.rkt create mode 100644 new-racket-web/web/stubs/wiki.rkt create mode 100644 new-racket-web/web/www/NEW.html create mode 100644 new-racket-web/web/www/all.rkt create mode 100644 new-racket-web/web/www/code.rkt create mode 100644 new-racket-web/web/www/community.rkt create mode 100644 new-racket-web/web/www/download-dark.png create mode 100644 new-racket-web/web/www/download.png create mode 100644 new-racket-web/web/www/download.rkt create mode 100644 new-racket-web/web/www/help.rkt create mode 100644 new-racket-web/web/www/index.rkt create mode 100644 new-racket-web/web/www/irc.rkt create mode 100644 new-racket-web/web/www/learning.rkt create mode 100644 new-racket-web/web/www/loud.png create mode 100644 new-racket-web/web/www/new-name.rkt create mode 100644 new-racket-web/web/www/old-techreports.rkt create mode 100644 new-racket-web/web/www/people.rkt create mode 100644 new-racket-web/web/www/resources.rkt create mode 100644 new-racket-web/web/www/techreports.rkt create mode 100644 new-racket-web/web/www/web-copyright.rkt diff --git a/new-racket-web/web/README b/new-racket-web/web/README new file mode 100644 index 0000000000..58e23c53bd --- /dev/null +++ b/new-racket-web/web/README @@ -0,0 +1,47 @@ +Sources: +======== + +* common: specific code for the racket web pages. + +* www: actual content of main site. + +* download: content of download site (only installer pages and such) + +* */all.rkt: files that just require all the necessary modules to build + the whole site or sub-sites + +* */resources.rkt: files that define the resources for a site (icon, + css, logo) + +* minis: smaller one-source-file sites + +* stubs: template "sites" that are intended to be hooked into other + systems to get the racket look. + +To build: +========= + +* Run `build.rkt' as the main entry point to building the web pages. + (Use `-h' as usual.) + +* You need to choose `-w' or `-l' for a web or local mode respectively. + The difference is that in local mode inter-site links are set up as + relative links so you can see all sites from the resulting + directories, and this is what you usually need to test things out. + (You will still need to deal with an occasional addition of + "index.html" which is not done when looking at file:// URLs.) + +* Use `-o ' to specify a directory where the built contents is + placed, otherwise the content will be placed in the current directory. + (Use `-f' in scripts to avoid answering the question about deleting + existing files.) + +* If you're not running from a git repository, you will also need to set + a $GIT_DIR environment variable otherwise the resulting build will not + have release information for the various builds. (This doesn't matter + if you're not working on download pages.) + +* You can also include more files that hook additional contents with + with `-e '. These files are required dynamically, and they + set things up to add more content building. The common example here + is "web/all.rkt" in iplt. diff --git a/new-racket-web/web/all.rkt b/new-racket-web/web/all.rkt new file mode 100644 index 0000000000..8b50d015d8 --- /dev/null +++ b/new-racket-web/web/all.rkt @@ -0,0 +1,5 @@ +#lang meta/web + +(require "www/all.rkt" "download/all.rkt" "minis/all.rkt" "stubs/all.rkt") +(set-navbar! (list main download documentation planet community learning) + main help) diff --git a/new-racket-web/web/build.rkt b/new-racket-web/web/build.rkt new file mode 100755 index 0000000000..f88fb0cf35 --- /dev/null +++ b/new-racket-web/web/build.rkt @@ -0,0 +1,83 @@ +#!/bin/sh +#| -*- scheme -*- +exe="racket"; +if [ -x "$PLTHOME/bin/racket" ]; then exe="$PLTHOME/bin/racket"; fi +exec "$exe" "$0" "$@" +|# + +#lang racket/base + +(require racket/cmdline racket/runtime-path racket/file scribble/html + "common/distribute.rkt" "config.rkt" "all.rkt") + +(define build-mode #f) +(define output-dir (current-directory)) +(define distribute? #f) +(define warn? #t) +(define extra-files '()) + +(command-line + #:once-any + [("-l" "--local") + "local mode: create content that is viewable in the build directory" + " (all links are relative) " + (set! build-mode 'local)] + [("-w" "--web") + "web mode: create content that is viewable on the Racket web pages" + (set! build-mode 'web)] + #:once-each + [("-o" "--output") dir + "output directory" + " (defaults to the current directory)" + (unless (directory-exists? dir) + (printf "Creating \"~a\"\n" dir) (make-directory dir)) + (set! output-dir dir)] + [("-f" "--force") + "avoid warning about directory cleanup" + (set! warn? #f)] + [("-d" "--dist") + "distribute resulting content" + " (will only work with the right access to the servers)" + (set! distribute? #t)] + #:multi + [("-e" "--extra") extra + "extra file to render more content" + (set! extra-files (cons extra extra-files))] + #:help-labels + " ** Note: set $KNOWN_MIRRORS_FILE to a file if you want to poll mirror" + " links (see top comment in \"download/mirror-link.rkt\").") + +(unless build-mode (raise-user-error 'build "build mode not specified")) + +(define-runtime-path here ".") +(let ([build (file-or-directory-identity output-dir)]) + (let loop ([dir here]) + (if (equal? build (file-or-directory-identity dir)) + (raise-user-error 'build + "might clobber sources, refusing to build (use `-o')") + (let-values ([(base name dir?) (split-path dir)]) + (when base (loop base)))))) + +(parameterize ([current-directory output-dir]) + (define paths (sort (map path->string (directory-list)) stringstring p) (caddr m))) + (directory-list (cadr m))) + stringlabel title) + (regexp-replace* #rx"[^a-z0-9_]+" (string-downcase title) "_")) +(define (make-sectioner #:toc? [toc? #t] + #:newpages? [newpages? #f] + #:show-section-in-subtitle [sec-in-subsec? #t]) + (define sections '()) + (define cur-sec #f) + (define subsections '()) + (define (->li/reverse items [more-style #f]) + (ul style: more-style (add-newlines (map li (reverse items))))) + (define (collect-subs) + (when (pair? subsections) + (set! sections + (cons (list (car sections) + (->li/reverse subsections "font-size: small;")) + (cdr sections))) + (set! subsections '()))) + (define ((add-section sub?) #:newpage? [newpage? newpages?] . title) + (let* ([title* (if sub? (list cur-sec ": " title) title)] + [label (section->label (xml->string title*))]) + (unless sub? (collect-subs) (set! cur-sec title)) + (let ([title (a href: (list "#" label) style: "text-decoration: none;" + title)]) + (if sub? + (set! subsections (cons title subsections)) + (set! sections (cons title sections)))) + ((if sub? h2 h1) + (a name: label + style: (and newpage? (pair? (cdr sections)) + "page-break-before: always;") + (if sec-in-subsec? title* title))))) + (values (add-section #f) (add-section #t) + (and toc? (λ () (collect-subs) (->li/reverse sections))))) +(define-syntax (sections stx) + (define (make-it stx args) + (with-syntax ([sec (datum->syntax stx 'section)] + [sub (datum->syntax stx 'subsection)] + [(x ...) args]) + #'(begin (define-values [sec sub toc] (make-sectioner x ...)) + toc))) + (syntax-case stx () + [(s x ...) (make-it #'s #'(x ...))] + [_ (identifier? stx) (make-it stx #'())])) diff --git a/new-racket-web/web/common/layout.rkt b/new-racket-web/web/common/layout.rkt new file mode 100644 index 0000000000..a2a97930e7 --- /dev/null +++ b/new-racket-web/web/common/layout.rkt @@ -0,0 +1,253 @@ +#lang at-exp racket/base + +(require scribble/html (for-syntax racket/base syntax/name syntax/parse) + "utils.rkt" "resources.rkt") + +(define-for-syntax (process-contents who layouter stx xs) + (let loop ([xs xs] [kws '()] [id? #f]) + (syntax-case xs () + [(k v . xs) (keyword? (syntax-e #'k)) + (loop #'xs (list* #'v #'k kws) (or id? (eq? '#:id (syntax-e #'k))))] + [_ (with-syntax ([layouter layouter] + [(x ...) (reverse kws)] + [(id ...) + (if id? + '() + (let ([name (or (syntax-property stx 'inferred-name) + (syntax-local-name))]) + (if name (list '#:id `',name) '())))] + ;; delay body, allow definitions + [body #`(λ () (begin/text #,@xs))]) + #'(layouter id ... x ... body))]))) + +(define (get-path who id file sfx dir) + (define file* + (or file + (let ([f (and id (symbol->string (force id)))]) + (cond [(and f (regexp-match #rx"[.]" f)) f] + [(and f sfx) + (string-append f (regexp-replace #rx"^[.]?" sfx "."))] + [else (error who "missing `#:file', or `#:id'~a" + (if sfx "" " and `#:suffix'"))])))) + (if dir (web-path dir file*) file*)) + +;; The following are not intended for direct use, see +;; `define+provide-context' below (it could be used with #f for the +;; directory if this ever gets used for a flat single directory web +;; page.) + +;; for plain text files +(define-syntax (plain stx) + (syntax-case stx () [(_ . xs) (process-contents 'plain #'plain* stx #'xs)])) +(define (plain* #:id [id #f] #:suffix [suffix #f] + #:dir [dir #f] #:file [file #f] + #:referrer [referrer values] + #:newline [newline? #t] + content) + (resource/referrer (get-path 'plain id file suffix dir) + (file-writer output (list content (and newline? "\n"))) + referrer)) + +;; page layout function +(define-syntax (page stx) + (syntax-case stx () [(_ . xs) (process-contents 'page #'page* stx #'xs)])) +(define (page* #:id [id #f] #:dir [dir #f] #:file [file #f] + ;; if this is true, return only the html -- don't create + ;; a resource -- therefore no file is made, and no links + ;; to it can be made (useful only for stub templates) + #:html-only [html-only? #f] + #:title [label (if id + (let* ([id (->string (force id))] + [id (regexp-replace #rx"^.*/" id "")] + [id (regexp-replace #rx"-" id " ")]) + (string-titlecase id)) + (error 'page "missing `#:id' or `#:title'"))] + #:link-title [linktitle label] + #:window-title [wintitle @list{Racket: @label}] + ;; can be #f (default), 'full: full page (and no div), + ;; otherwise, a css width + #:width [width #f] + #:description [description #f] ; for a meta tag + #:extra-headers [extra-headers #f] + #:extra-body-attrs [body-attrs #f] + #:resources resources0 ; see below + #:referrer [referrer + (λ (url . more) + (a href: url (if (null? more) linktitle more)))] + ;; will be used instead of `this' to determine navbar highlights + #:part-of [part-of #f] + content0) + (define (page) + (define desc + (and description (meta name: 'description content: description))) + (define headers + (if (and extra-headers desc) + (list desc "\n" extra-headers) + (or desc extra-headers))) + (define resources (force resources0)) + (define head (resources 'head wintitle headers)) + (define navbar (resources 'navbar (or part-of this))) + (define content + (list navbar "\n" + (case width + [(full) content0] + [(#f) (div class: 'bodycontent content0)] + [else (div class: 'bodycontent style: @list{width: @|width|@";"} + content0)]))) + @xhtml{@|| + @head + @(if body-attrs + (apply body `(,@body-attrs ,content)) + (body content)) + @||}) + (define this (and (not html-only?) + (resource/referrer (get-path 'page id file "html" dir) + (file-writer output-xml page) + referrer))) + (when this (pages->part-of this (or part-of this))) + (or this page)) + +;; maps pages to their parts, so symbolic values can be used to determine it +(define pages->part-of + (let ([t (make-hasheq)]) + (case-lambda [(page) (hash-ref t page page)] + [(page part-of) (hash-set! t page part-of)]))) + +(provide set-navbar!) +(define-syntax-rule (set-navbar! pages top help) + (if (unbox navbar-info) + ;; since generation is delayed, it won't make sense to change the navbar + (error 'set-navbar! "called twice") + (set-box! navbar-info (list (lazy pages) (lazy top) (lazy help))))) + +(define navbar-info (box #f)) +(define (navbar-maker logo) + (define pages-promise + (lazy (car (or (unbox navbar-info) + (error 'navbar "no navbar info set"))))) + (define top-promise (lazy (cadr (unbox navbar-info)))) + (define help-promise (lazy (caddr (unbox navbar-info)))) + (define pages-parts-of-promise + (lazy (map pages->part-of (force pages-promise)))) + (define (middle-text size x) + (span style: `("font-size: ",size"px; vertical-align: middle;") + class: 'navtitle + x)) + (define OPEN + (list (middle-text 100 "(") + (middle-text 80 "(") + (middle-text 60 "(") + (middle-text 40 nbsp))) + (define CLOSE + (list (middle-text 80 "Racket") + (middle-text 40 nbsp) + (middle-text 60 ")") + (middle-text 80 ")") + (middle-text 100 ")"))) + (define (header-cell logo) + (td (a href: (url-of (force top-promise)) + OPEN + (img src: logo alt: "[logo]" + style: '("vertical-align: middle; " + "margin: 13px 0.25em 0 0; border: 0;")) + CLOSE))) + (define (links-table this) + (table width: "100%" + (tr (map (λ (nav navpart) + (td class: 'navlinkcell + (span class: 'navitem + (span class: (if (eq? (pages->part-of this) navpart) + 'navcurlink 'navlink) + nav)))) + (force pages-promise) + (force pages-parts-of-promise))))) + (λ (this) + (div class: 'racketnav + (div class: 'navcontent + (table border: 0 cellspacing: 0 cellpadding: 0 width: "100%" + (tr (header-cell logo) + (td class: 'helpiconcell + (let ([help (force help-promise)]) + (span class: 'helpicon (if (eq? this help) nbsp help))))) + (tr (td colspan: 2 (links-table this)))))))) + +(define (html-favicon-maker icon) + (define headers + @list{@link[rel: "icon" href: icon type: "image/ico"] + @link[rel: "shortcut icon" href: icon]}) + (λ () headers)) + +(define (html-head-maker style favicon) + (define headers + @list{ + @meta[name: "generator" content: "Racket"] + @meta[http-equiv: "Content-Type" content: "text/html; charset=utf-8"] + @favicon + @link[rel: "stylesheet" type: "text/css" href: style title: "default"]}) + (λ (title* more-headers) + (head "\n" (title title*) + "\n" headers + (and more-headers (list "\n" more-headers)) + "\n"))) + +(define (make-resources files) + (define (getfile what) (cadr (assq what files))) + (define favicon (html-favicon-maker (getfile 'icon))) + (define make-head (html-head-maker (getfile 'style) favicon)) + (define make-navbar (navbar-maker (getfile 'logo))) + (λ (what . more) + (apply (case what + [(head) make-head] + [(navbar) make-navbar] + [(favicon-headers) favicon] + [(icon-path logo-path style-path) + (λ () (let* ([x (symbol->string what)] + [x (regexp-replace #rx"-path$" x "")]) + (url-of (getfile (string->symbol x)))))] + [else (error 'resources "internal error")]) + more))) + +;; `define+provide-context' should be used in each toplevel directory (= each +;; site) to have its own resources (and possibly other customizations). +(provide define+provide-context define-context) +(define-for-syntax (make-define+provide-context stx provide?) + (syntax-parse stx + [(_ (~or (~optional dir:expr) + (~optional (~seq #:resources resources)) + (~optional (~seq #:robots robots) #:defaults ([robots #'#t])) + (~optional (~seq #:htaccess htaccess) #:defaults ([htaccess #'#t]))) + ...) + (unless (attribute dir) + (raise-syntax-error 'define-context "missing ")) + (with-syntax ([page-id (datum->syntax stx 'page)] + [plain-id (datum->syntax stx 'plain)] + [copyfile-id (datum->syntax stx 'copyfile)] + [symlink-id (datum->syntax stx 'symlink)] + [resources-id (datum->syntax stx 'the-resources)]) + (with-syntax ([provides (if provide? + #'(provide page-id plain-id copyfile-id + symlink-id resources-id) + #'(begin))] + [resources + (or (attribute resources) + #'(make-resources + (make-resource-files + (λ (id . content) + (page* #:id id #:dir dir + #:resources (lazy resources-id) + content)) + dir robots htaccess)))]) + #'(begin (define resources-id resources) + (define-syntax-rule (page-id . xs) + (page #:resources resources-id #:dir dir . xs)) + (define-syntax-rule (plain-id . xs) + (plain #:dir dir . xs)) + (define (copyfile-id source [target #f]) + (copyfile-resource source target #:dir dir)) + (define (symlink-id source [target #f]) + (symlink-resource source target #:dir dir)) + provides)))])) +(define-syntax (define+provide-context stx) + (make-define+provide-context stx #t)) +(define-syntax (define-context stx) + (make-define+provide-context stx #f)) diff --git a/new-racket-web/web/common/links.rkt b/new-racket-web/web/common/links.rkt new file mode 100644 index 0000000000..742b8366a2 --- /dev/null +++ b/new-racket-web/web/common/links.rkt @@ -0,0 +1,64 @@ +#lang at-exp racket/base + +(require scribble/html) + +(define-syntax define* + (syntax-rules () + [(_ (id . xs) E ...) (begin (define (id . xs) E ...) (provide id))] + [(_ id E) (begin (define id E) (provide id))])) + +(define ((make-link url . text) . alternate) + (a href: url (if (null? alternate) text alternate))) + +;; ---------------------------------------------------------------------------- +;; Pages that are made outside of this system + +(define doc-url "http://docs.racket-lang.org/") + +(define* -docs @make-link[doc-url]{Documentation}) + +(define-syntax-rule (define-doc-link id desc) + (define* id @make-link[`(,doc-url id "/")]{ + @strong{@(string-titlecase (symbol->string 'id))}: @desc @; + @nbsp @small{@a[href: `(,doc-url "pdf/" id ".pdf")]{[pdf]}}})) + +@define-doc-link[quick]{An Introduction to Racket with Pictures} +@define-doc-link[more ]{Systems Programming with Racket} +@define-doc-link[guide]{Racket} +@define-doc-link[continue]{Continue} + +(define* intros (list quick more guide)) + +;; ---------------------------------------------------------------------------- +;; External links + +(define* -htdp + @make-link["http://htdp.org/"]{@i{How to Design Programs}}) + +(define* -redex + @make-link["http://redex.racket-lang.org/"]{Redex}) + +(define* -pbd + @make-link["http://programbydesign.org/"]{Program by Design}) + +(define* -schemers + @make-link["http://schemers.org/"]{@tt{schemers.org}}) + +(define* -plai + @make-link["http://www.plai.org/"]{ + @i{Programming Languages: Application and Interpretation}}) + +(define* -bootstrap @make-link["http://www.bootstrapworld.org/"]{Bootstrap}) + +(define* (-rcon [year #f] . text) + (define years '(2013 2012 2011)) + (a href: (list "http://con.racket-lang.org/" + (and year (not (eq? year (car years))) (list year "/"))) + (cond [(pair? text) text] + [(not year) "RacketCon"] + [else year]))) + +(define* (-wiki [page #f] . text) + (a href: (list "https://github.com/plt/racket/wiki" + (and page (list "/" (regexp-replace #rx" " page "-")))) + (if (null? text) (or page "Racket wiki") text))) diff --git a/new-racket-web/web/common/logo.png b/new-racket-web/web/common/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4e53f004449d1ff353cc84d4d795396ff4833acc GIT binary patch literal 6717 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 + 140BE58EEC31CB97382E1016E21C405A}] + [robots + ;; #t (the default) => no-op file, good to avoid error-log lines + ,(let* ([t (if (eq? #t robots) "Disallow:" robots)] + [t (and t (list "User-agent: *\n" t))]) + (and t (writefile "robots.txt" t)))] + ;; Seems like there are still some clients that look for a favicon.ico file + [favicon ,(copyfile "plticon.ico" "favicon.ico")] + [404 + @,page['page-not-found]{ + @h1[style: '("text-align: center; margin: 3em 0 1em 0;")]{ + Page not found} + @(λ xs (table align: 'center (tr (td (pre xs))))){ + > (@a[href: "/"]{(uncaught-exception-handler)} + (*(+(*)(*(+(*)(*)(*)(*)(*))(+(*)(*)(*)(*)(*))(+(*)(*)(*)(*))))@; + (+(*)(*)(*)(*)))) + uncaught exception: 404}}] + ;; set the 404 page in htaccess instead of in the conf file, so we get it + ;; only in sites that we generate here + [.htaccess + ,(let* ([t (and htaccess "ErrorDocument 404 /page-not-found.html")] + [t (if (boolean? htaccess) t (list htaccess "\n" t))]) + (and t (writefile ".htaccess" t)))])) + +(define page-sizes + @list{ + margin-left: auto; + margin-right: auto; + width: 45em; + }) +(define font-family + @list{ + font-family: Optima, Arial, Verdana, Helvetica, sans-serif; + }) + +(define navbar-style + ;; All of these are made to apply only inside `racketnav', so the styles can + ;; be used in places with their own CSS (eg, blog.racket-lang.org) + @list{ + .racketnav { + background-color: #000000; + color: #ffffff; + margin-bottom: 1em; + padding: 0.5em 0em; + white-space: nowrap; + } + .racketnav a { + color: #ffffff; + text-decoration: none; + } + .racketnav .navcontent { + @page-sizes + @font-family + } + .racketnav .navtitle { + font-size: xx-large; + font-weight: bold; + } + .racketnav .navitem { + text-decoration: none; + font-size: 88%; + } + .racketnav .navlink a { + padding: 0em 1em; + } + .racketnav .navcurlink a { + padding: 0em 1em; + background-color: #555555; + } + .racketnav .navlink a:hover, + .racketnav .navcurlink a:hover { + background-color: #888888; + } + .racketnav .navlinkcell { + text-align: center; + } + .racketnav .helpiconcell { + text-align: right; + vertical-align: top; + } + .racketnav .helpicon { + font-weight: bold; + font-size: 88%; + } + }) + +(define racket-style + @list{ + @; ---- generic styles ---- + html { + overflow-y: scroll; + } + body { + color: black; + background-color: white; + @font-family + margin: 0px; + padding: 0px; + } + a { + text-decoration: none; + } + a:hover { + text-decoration: underline; + } + @; ---- content styles ---- + .bodycontent { + @page-sizes + } + @; ---- styles for the navbar ---- + @navbar-style + @; ---- styles for extras ---- + .parlisttitle { + margin-bottom: 0.5em; + } + .parlistitem { + margin-bottom: 0.5em; + margin-left: 2em; + } + }) diff --git a/new-racket-web/web/common/utils.rkt b/new-racket-web/web/common/utils.rkt new file mode 100644 index 0000000000..9e81172f84 --- /dev/null +++ b/new-racket-web/web/common/utils.rkt @@ -0,0 +1,52 @@ +#lang at-exp racket/base + +(require scribble/html (for-syntax scheme/base)) + +(provide in-here) +(define-syntax (in-here stx) + (syntax-case stx () + [(_ path paths ...) + (let ([src (let-values ([(dir name dir?) + (split-path (syntax-source stx))]) + (or dir (raise-syntax-error + 'in-here "missing source information" stx)))]) + #`(build-path '#,src path paths ...))])) + +(provide web-path) +(define (web-path . xs) + (string-join xs "/")) + +(provide ->string) +(define (->string x) + (cond [(string? x) x] + [(path? x) (path->string x)] + [(bytes? x) (bytes->string/utf-8 x)] + [(symbol? x) (symbol->string x)] + [(number? x) (number->string x)] + [else (error '->string "don't know what to do with ~e" x)])) + +;; resources with a specific referrer; if the referrer is `values', +;; return a plain resource (which behaves the same) +(provide resource/referrer url-of) +(struct referable (referrer resource) #:property prop:procedure 0) +(define (resource/referrer path renderer referrer) + (define url (resource path renderer)) + (if (eq? referrer values) + url + (referable (λ args (apply referrer (url) args)) url))) +(define (url-of referable [absolute? #f]) + (cond [(referable? referable) ((referable-resource referable) absolute?)] + [(resource? referable) (referable absolute?)] + [else (raise-type-error 'url-of "referable" referable)])) + +;; simple file resources +(define ((make-path-resourcer file-op) source [target #f] #:dir [dir #f]) + (let ([target (or target (let-values ([(base file dir?) (split-path source)]) + (path->string file)))]) + (resource (if (eq? void file-op) + (void) (if dir (web-path dir target) target)) + (λ (file) (file-op source file))))) + +(provide copyfile-resource symlink-resource) +(define copyfile-resource (make-path-resourcer copy-file)) +(define symlink-resource (make-path-resourcer make-file-or-directory-link)) diff --git a/new-racket-web/web/config.rkt b/new-racket-web/web/config.rkt new file mode 100644 index 0000000000..5ce7108694 --- /dev/null +++ b/new-racket-web/web/config.rkt @@ -0,0 +1,29 @@ +#lang racket/base + +(provide sites) +(define sites + '(("www" "http://racket-lang.org/") + ("download" "http://download.racket-lang.org/") + ("bugs" "http://bugs.racket-lang.org/") + ("lists" "http://lists.racket-lang.org/") + ("drracket" "http://drracket.org/") + ;; stubs usually use absolute paths for resources, since they're + ;; templates that often get used in sub-dir pages too + ("stubs/planet" "http://planet.racket-lang.org/" abs) + ("stubs/pre" "http://pre.racket-lang.org/" abs) + ("stubs/git" "http://git.racket-lang.org/" abs) + ("stubs/blog" "http://blog.racket-lang.org/" abs) + ("stubs/mailman" "http://lists.racket-lang.org/" abs) + ("stubs/dirlist" "http://download.racket-lang.org/" abs) + ("stubs/docs" "http://docs.racket-lang.org/" abs) + ("stubs/wiki" "http://wiki.racket-lang.org/" abs))) + +(provide distributions) +(define distributions + (make-parameter + ;; Each is a "hostname:dest-path", and then a list of directories to put in + ;; that path. Warning: distributed directories are replicated from the + ;; source, including removing material that is not distributed. A directory + ;; can also have "*" parts which will be expanded recursively -- useful to + ;; avoid deletions in case a target directory has additional materials. + '(["winooski:/www" "www" "download" "bugs" "lists" "drracket" "stubs"]))) diff --git a/new-racket-web/web/download/all.rkt b/new-racket-web/web/download/all.rkt new file mode 100644 index 0000000000..e4a1a410d0 --- /dev/null +++ b/new-racket-web/web/download/all.rkt @@ -0,0 +1,3 @@ +#lang racket/base + +(require "index.rkt" "version.rkt") diff --git a/new-racket-web/web/download/data.rkt b/new-racket-web/web/download/data.rkt new file mode 100644 index 0000000000..f21ee91a88 --- /dev/null +++ b/new-racket-web/web/download/data.rkt @@ -0,0 +1,264 @@ +#lang racket/base + +(define -platform-names- + `(;; source platforms + ["win" "Windows"] + ["mac" "Mac OS X"] + ["unix" "Unix"] + ;; binary platforms + ["i386-win32" "Windows (x86, 32-bit)"] + ["x86_64-win32" "Windows (x64, 64-bit)"] + ["(ppc|i386|x86_64)-osx-mac" + ,(λ (_ cpu) + (format "Mac OS X (~a)" + (cond + [(equal? cpu "ppc") "PPC"] + [(equal? cpu "i386") "Intel 32-bit"] + [(equal? cpu "x86_64") "Intel 64-bit"] + [else (error "unregonized cpu!")])))] + ["(ppc|68k)-mac-classic" "Macintosh Classic (\\1)"] + ["(ppc|i386)-darwin" + ,(λ (_ cpu) + (format "Darwin (~a)" + (if (equal? cpu "ppc") "PPC" "Intel")))] + ["i386-linux(-gcc2)?" "Linux i386"] + ["i386-linux-fc([0-9]+)" "Linux i386 (Fedora Core \\1)"] + ["(i386|x86_64)-linux-f([0-9]+)" "Linux \\1 (Fedora \\2)"] + ["(i386|x86_64)-linux-debian" "Linux \\1 (Debian Stable)"] + ["(i386|x86_64)-linux-debian-([a-zA-Z0-9]+)" "Linux \\1 (Debian \\2)"] + ["(i386|x86_64)-linux-ubuntu([0-9]+)" "Linux \\1 (Ubuntu \\2)"] + ["(i386|x86_64)-linux-ubuntu-([a-z]+)" "Linux \\1 (Ubuntu \\2)"] + ["(i386|x86_64)-linux-ubuntu.*" "Linux \\1 (Ubuntu)"] + ["(i386|x86_64)-freebsd" "FreeBSD \\1"] + ["sparc-solaris" "Sparc Solaris (SunOS)"] + ["i386-kernel" "x86 Standalone Kernel"] + )) + +(define -file-type-names- + '(["sh" "Self-extracting shell script"] + ["exe" "Windows Installer"] + ["tgz" "Gzipped TAR Archive"] + ["zip" "Zipped Archive"] + ["dmg" "Disk Image"] + ["plt" "Racket Package"] + ["sit" "StuffIt Archive"])) + +(define -mirrors- + ;; This is a sequence of + ;; (location url reposnisble-name email [techincal-contact]) + '(["Main download (USA, Massachusetts, Northeastern University)" + "http://download.racket-lang.org/installers/" + "Eli Barzilay" + "eli@barzilay.org"] + ["USA, Illinois (Northwestern University)" + "http://www.eecs.northwestern.edu/racket/" + "Robby Findler" + "robby@eecs.northwestern.edu"] + ["USA, Utah (University of Utah)" + "http://www.cs.utah.edu/plt/installers/" + "Matthew Flatt" + "mflatt@cs.utah.edu"] + ["Canada, Ontario (University of Waterloo)" + "http://mirror.csclub.uwaterloo.ca/racket/racket-installers/" + "Systems Committee" + "syscom@csclub.uwaterloo.ca"] + ["Germany (Universität Tübingen)" + "http://mirror.informatik.uni-tuebingen.de/mirror/racket/" + "Marcus Crestani" + "crestani@informatik.uni-tuebingen.de"] + ["Belgium (Infogroep, Vrije Universiteit Brussel)" + "http://racket.infogroep.be/" + "Infogroep" + "research@infogroep.be"] + #; + ["Turkey, Istanbul (Bilgi University)" + "http://russell.cs.bilgi.edu.tr/racket-installers/" + "Onur Gungor" + "onurgu@cs.bilgi.edu.tr"] + #; + ["Austria (Vienna University of Technology)" + "http://gd.tuwien.ac.at/languages/scheme/plt/" + "Rudolf Ladner" + "ladner@zid.tuwien.ac.at"] + #; ; Scheme guy left + ["France (Institut Pasteur)" + "ftp://ftp.pasteur.fr/pub/computing/Scheme/plt-scheme/" + "Marc Badouin" + "babafou@pasteur.fr" + "Pasteur Institute FTP ftpmain@pasteur.fr"] + #; ; ftp down (permanently?) + ["Mexico (Wish Computing)" + "ftp://morpheus.wish.com.mx/pub/plt/" + "Francisco Solsona" + "solsona@acm.org"] + )) + +;; Used to sort packages when more then one is rendered on a page (delayed) +(define (-installer-orders-) + `((,installer-package ,eq? (racket racket-textual)) + (,installer-binary? ,eq? (#t #f)) + (,installer-platform ,regexp-match? + (#px"\\bwin(32)?\\b" #px"\\bmac\\b" #px"\\blinux\\b" #px"")) + (,installer-platform ,regexp-match? + (#px"\\bi386\\b" #px"\\bx86_64\\b" #px"\\bppc\\b" #px"")))) + +;; ---------------------------------------------------------------------------- + +(provide (struct-out mirror) mirrors + (struct-out release) (struct-out installer) + all-installers current-release all-releases all-packages + package->name platform->name suffix->name + set-announcements-file!) + +(require racket/list racket/file version/utils racket/runtime-path + racket/promise "release-info.rkt") + +;; ---------------------------------------------------------------------------- +;; Mirror information + +(struct mirror (location url person email)) + +(define mirrors + (map (λ (m) (mirror (car m) (regexp-replace #rx"/?$" (cadr m) "/") + (caddr m) (cadddr m))) + -mirrors-)) + +;; ---------------------------------------------------------------------------- +;; Release information + +(struct release (version date date-string announcement)) + +(define announcements #f) +(define (set-announcements-file! file) + (set! announcements #t)) + +(define version->release + (let ([t (make-hash)] + [months '#("January" "February" "March" "April" "May" "June" "July" + "August" "September" "October" "November" "December")]) + (λ (v) + (hash-ref! t v + (λ () + (define info (get-version-tag-info v)) + (if info + (let* ([tagger (car info)] + [date (cadr info)] + [announcement (caddr info)] + [year (date-year date)] + [month (vector-ref months (sub1 (date-month date)))]) + (release v date (format "~a ~a" month year) announcement)) + (release v #f "(unknown date)" "(no release text found)"))))))) + +;; ---------------------------------------------------------------------------- +;; Installer information + +(define-runtime-path installers-data "installers.txt") + +(struct installer + (path ; path to file from the installers directory + file ; just the file name + release ; the release that this installer comes from + size ; size in bytes + package ; package kind symbol 'racket or 'racket-textual + binary? ; #t = binary distribution, #f = source distribution + platform ; platform name string (generic for srcs, cpu-os for bins) + suffix)) ; string + +(define installer-rx + (pregexp (string-append + "^" + "([0-9.]+)" ; size + "\t" + "(" ; path + "([0-9p.]+)" ; version + "/" + "(racket(?:-textual)?)" ; package + "/(" ; file + "\\4-\\3-" ; -- + "(bin|src)-" ; binary/source + "([^.]+)" ; platform + "\\." + "([a-z]+)" ; suffix + "))$"))) + +(define (make-installer size path version package file type platform suffix) + (installer path file (version->release version) (string->number size) + (string->symbol package) (equal? "bin" type) platform suffix)) + +(define (parse-installers in) + (port-count-lines! in) + (for/list ([line (in-lines in)] [num (in-naturals 1)]) + (apply make-installer + (cdr (or (regexp-match installer-rx line) + (error 'installers "bad installer data line#~a: ~s" + num line)))))) + +(define (order->precedes order) + (define =? (car order)) + (define l (cadr order)) + (define (num-of x) + (let loop ([l l] [n 0]) + (cond [(null? l) + (error 'precedes "could not find ~s in precedence list: ~s" x l)] + [(=? (car l) x) n] + [else (loop (cdr l) (add1 n))]))) + (λ (x y) (< (num-of x) (num-of y)))) + +;; use this to avoid parsing the installers until generation starts +(define-syntax-rule (define-lazy name expr) + (begin (define p (lazy expr)) + (define-syntax name + (syntax-id-rules (set!) + [(set! _ x) (error 'name "unmodifiable binding")] + [(_ x (... ...)) ((force p) x (... ...))] + [_ (force p)])))) + +;; sorted by version (newest first), and then by -installer-orders- +(define-lazy all-installers + (sort + (call-with-input-file installers-data parse-installers) + (let ([fns `([,(λ (i) + (version->integer (release-version (installer-release i)))) + . ,>] + ,@(map (λ (o) (cons (car o) (order->precedes (cdr o)))) + (-installer-orders-)))]) + (λ (i1 i2) + (let loop ([fns fns]) + (if (null? fns) + #f + (let* ([get (caar fns)] [name + (let ([t (make-hasheq)]) + (λ (package) + (hash-ref! t package + (λ () (string-titlecase + (regexp-replace #rx"-" (symbol->string package) " "))))))) + +(define platform-names + (for/list ([pn (in-list -platform-names-)]) + (list (regexp (string-append "^" (car pn) "$")) (cadr pn)))) + +(define platform->name + (let ([t (make-hash)]) + (λ (platform) + (hash-ref! t platform + (λ () (or (for/or ([pn (in-list platform-names)]) + ;; find out if a regexp applied by checking if the result + ;; is different (relies on regexp-replace returning the + ;; same string when fails) + (let ([new (regexp-replace (car pn) platform (cadr pn))]) + (and (not (eq? new platform)) new))) + (error 'platform->name "unrecognized platform: ~e" + platform))))))) + +(define (suffix->name suffix) + (cond [(assoc suffix -file-type-names-) => cadr] + [else (error 'suffix->name "unrecognized suffix: ~e" suffix)])) diff --git a/new-racket-web/web/download/download-pages.rkt b/new-racket-web/web/download/download-pages.rkt new file mode 100644 index 0000000000..4da2410a65 --- /dev/null +++ b/new-racket-web/web/download/download-pages.rkt @@ -0,0 +1,249 @@ +#lang meta/web + +(require "resources.rkt" "data.rkt" "installer-pages.rkt" "symlinks.rkt" + (prefix-in pre: "../stubs/pre.rkt")) + +(provide render-download-page) +(define (render-download-page [release current-release] [package 'racket]) + (define version (release-version release)) + @center-div{ + @h2{@(package->name package) v@version (@(release-date-string release))} + @div[id: "download_panel" align: "center" style: "display: none;"]{ + @input[type: 'submit value: "Download" onclick: "do_jump();" + style: '("font-size: 200%; font-weight: bolder;" + " letter-spacing: 0.2em;" + " margin: 0.5ex 0 1ex 0; width: 100%;")] + @br + @div{ + Platform: + @select[id: "platform_selector" + onchange: "selection_changed();" + onkeypress: "selection_changed();"]{ + @(for/list ([i (in-list all-installers)] + #:when (and (equal? release (installer-release i)) + (equal? package (installer-package i)))) + (installer->page i 'render-option))}} + @|br br| + @(let* ([sep @list{@nbsp @bull @nbsp}] + [links (λ links @(tr (td (div style: "margin: 1ex 4ex;" + (add-between links sep)))))] + [docs @list{@|docs|/@|version|/html}]) + @table[style: "text-align: center; font-size: small;" + frame: 'hsides rules: 'rows]{ + @links[@list{Release: @nbsp @(release-page release){Announcement}} + @a[href: @list{@|docs|/release/}]{Notes} + @a[href: @docs]{Documentation}] + @links[@license{License} + all-version-pages + @pre:installers{Nightly Installers}]}) + @br + @div[id: "linux_explain" + style: '("font-size: 75%; display: none; width: 28em;" + " margin-top: 1ex; text-align: center;")]{ + @b{Note about the Linux installers:} if you don't see an option for + your particular platform, try other Linux installers, starting from + similar ones. Very often, a build on one Linux variant will work on + others too.}} + @downloader-script + @noscript{ + Installers are available for the following platforms: + @ul{@(for/list ([i (in-list all-installers)] + #:when (and (equal? release (installer-release i)) + (equal? package (installer-package i)))) + @li{@(installer->page i 'only-platform)})}}}) + +(define (release-page* rel) + (define ver (release-version rel)) + (define title @list{v@ver Release Notes}) + @page[#:file (format "v~a.html" ver) #:title title #:part-of 'download]{ + @table[align: 'center]{ + @tr{@td{@h2{Release Announcements for Version @ver}}} + @tr{@td{@pre{@release-announcement[rel]}}}} + }) +(define release-page + (let ([t (make-hash)]) + (λ (rel) (hash-ref! t rel (λ () (release-page* rel)))))) + +(define all-version-pages + (let () + (define (make-page rel pkg) + (define ver (release-version rel)) + (define file (format "~a-v~a.html" pkg ver)) + (define title @list{Download @(package->name pkg) v@ver}) + @page[#:file file #:title title #:part-of 'download]{ + @(render-download-page rel pkg)}) + (define style + @style/inline[type: 'text/css]{ + .version-row { + background-color: #ffffc0; + } + .version-row:hover { + background-color: #e0e0a0; + } + .version-row a { + text-decoration: none; + } + .version-row a:hover { + background-color: #eeee22; + }}) + @page[#:id 'all-versions #:title "All Versions" #:part-of 'download + #:extra-headers style]{ + @table[align: 'center cellspacing: 0 cellpadding: 4 frame: 'box + rules: 'groups]{ + @thead{ + @tr{@td{@nbsp @strong{Version & Release Notes}} + @(map (λ (p) @th[align: 'center]{@(package->name p)}) + all-packages) + @td{@strong{Documentation}}}} + @(let ([sep (tr style: "height: 4px; margin: 0; padding: 0;" + (td) (map (λ (_) (td)) all-packages))]) + (define (cell rel pkg) + @td[align: 'center]{ + @nbsp @(make-page rel pkg){[download]} @nbsp}) + @tbody{ + @sep + @(for/list ([r (in-list all-releases)]) + (define ver (release-version r)) + @list{ + @tr[class: 'version-row]{ + @td{@|nbsp nbsp| @strong{Version @ver}, + @(release-page r){@release-date-string[r]} @nbsp} + @(map (λ (p) (cell r p)) all-packages) + @td{@nbsp @a[href: @list{@|docs|/@|ver|/html}]{[HTML]} @; + @nbsp @a[href: @list{@|docs|/@|ver|/pdf}]{[PDF]} @; + @nbsp}} + @sep})}) + @tfoot{ + @tr[class: 'version-row]{ + @td[align: 'center colspan: 3]{@pre:installers} + @td{@nbsp @pre:docs[#:sub 'html]{[HTML]} @; + @nbsp @pre:docs[#:sub 'pdf]{[PDF]} @nbsp}}}}})) + +(define license + @page[#:title "Software License" #:part-of 'download]{ + @p*{ + @~ Racket is distributed under the + @a[href: "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html#SEC1"]{ + GNU Lesser General Public License (LGPL)}. + @~ Our primary goal is to help as many people as possible use and + contribute to Racket. We encourage anyone to develop any kind of + software, with any kind of license, using Racket. + @~ We have chosen the LGPL as the license for Racket, which makes it + possible for for people to create software with Racket, and to allow us + to build on existing libraries that use the LGPL, such as the Lightning + assembler and the GMP math library. The basic requirement of the LGPL + is that you make your changes to Racket available, and that you let + other people use your software with new versions of Racket. + @~ Since the LGPL license that Racket uses was originally designed for C + programs, parts of it require some interpretation to apply to Racket in + detail. The following is how the Racket maintainers interpret the + license. + @~ @ul*{ + @~ First, if you distribute your Racket application in source form or as + compiled bytecode files, the Racket license does not restrict you at + all. + @~ Second, if you distribute your Racket application as compiled binary + generated by @tt{raco exe}, there are no requirements placed on the + licensing of your software. However, the LGPL requires that you make + it possible to re-link your software with modified versions of + Racket. This means, basically, that you need to provide the compiled + bytecode files used to produce the compiled binary, if requested by + someone who got your software from you. Note that this does @em{not} + mean that your software has to be made open source, nor do you have + to give the source code to anyone, nor do you have to make the + compiled bytecode files available to the public or let other people + redistribute them. Furthermore, this is not revealing any more of + your source code than the @tt{raco exe} format, since the bytecode is + embedded in an extractable way in the resulting executable.} + @~ We are, of course, not lawyers, and this should not be taken as legal + advice. However, we wanted to make it clear that Racket is an + appropriate building block for all kinds of software, and to clarify how + we view the license of Racket.}}) + +(define downloader-script + @script/inline[type: 'text/javascript]{@|| + var do_jump, selection_changed; + (function() { + // show the download panel, since JS is obviously working + document.getElementById("download_panel").style.display = "block"; + // + var selector = document.getElementById("platform_selector"); + // jump to the selected item + do_jump = function() { + location.href = selector[selector.selectedIndex].value; + } + // returns an ordering for the platform names, an array of regexps + // note that the entries are sorted in a good order, so return an order + // that only brings the locally desired entries to the top + function getPlatformOrder() { + var p = navigator.platform; + var l = function(str) { return p.indexOf(str) != -1@";" } + var Win = /Windows/, + Mac = /Mac/, + MacIntel = /Mac.*Intel/, + MacPPC = /Mac.*PPC/, + Linux = /Linux/, + Linux64 = /Linux.*x86_64/, + Linux32 = /Linux.*i386/, + Unix = /Unix/, + Solaris = /Solaris/; + if (p == null) return []; + else if (l("SunOS")) return [Solaris, Unix]; + @; Note about Windows 64: seems like the best guess could be done by + @; checking that the platform has "Win64" or navigator.userAgent has + @; either "Win64" or "WOW64". But the 32 build might be better for many + @; people anyway, so keep things as is for now. (With the `Win' filter + @; which will get the 32 version first and the 64 second.) + else if (l("Win")) return [Win]; + else if (l("Mac")) return [(l("Intel")?MacIntel:MacPPC), Mac, Unix]; + else if (l("Linux")) { + // also show the linux explanation if it's a linux + document.getElementById("linux_explain").style.display = "block"; + return [(l("_64")?Linux64:Linux32), Linux, Unix]; + } else return []; + } + // show the linux explanation on change too (do it with a timeout so it + // changes even when the arrow keys are used to move the selection -- since + // then onchange is called only on blur) + linux_expl_s = document.getElementById("linux_explain").style; + selection_changed_timer = false; + selection_changed = function() { + if (selection_changed_timer) clearTimeout(selection_changed_timer); + selection_changed_timer = setTimeout(do_selection_changed, 250); + } + function do_selection_changed() { + linux_expl_s.display = + (selector[selector.selectedIndex].text.search(/Linux/) >= 0) ? + "block" : "none"; + } + // + var opts = selector.options; + var len = opts.length; + // get the order and a make a sorting function + var order = getPlatformOrder(); + function getOrder(str) { + for (var i=0@";" i= 0) return i; + return 999; + } + function isBetter(opt1,opt2) { + // sort first by the order, then by how they were placed originally + var ord1 = getOrder(opt1[0]), ord2 = getOrder(opt2[0]); + if (ord1 < ord2) return -1; + else if (ord1 > ord2) return +1; + else if (opt1[2] < opt2[2]) return -1; + else if (opt1[2] > opt2[2]) return +1; + else return 0; + } + // sort the options, need to use a temporary array + var tmps = new Array(len); + for (var i=0@";" iname (installer-package installer))) + (define size (installer-size installer)) + (define type (if (installer-binary? installer) "" " source")) + (define platform (platform->name (installer-platform installer))) + (define title @text{Download @package v@|version type| for @platform}) + (define suffix-desc (suffix->name (installer-suffix installer))) + (define human-size + (let ([mb (/ size (* 1024 1024))]) + (if (< mb 10) + (let-values ([(q r) (quotient/remainder (round (* mb 10)) 10)]) + (format "~a.~aM" q r)) + (format "~aM" (round mb))))) + (define (row label text) + @tr[valign: 'top]{ + @td[align: 'right]{@b{@label}:} + @td{@nbsp} + @td[align: 'left]{@text}}) + (define (this url [mode #f]) + (case mode + [(only-platform) (a href: url platform type)] + [(render-option) (option value: url platform type)] + [(#f) @a[href: url]{@title}] + [else (error 'installer-page "unknown mode: ~e" mode)])) + @page[#:file html-file #:title title #:referrer this #:part-of 'download]{ + @table[width: "90%" align: 'center]{ + @tr[valign: 'top]{ + @td[width: "50%"]{ + @table{@(row "Package" package) + @(row "Version" @list{@version (@date)}) + @(row "Platform" (list platform type)) + @(row "Type" suffix-desc) + @(row "File" file) + @(row "Size" @span[title: @list{Exact size: @size bytes}]{ + @human-size})}} + @td[width: "50%"]{ + Download links: + @div[style: "font-size: 75%; text-align: right; float: right;"]{ + (Choose the nearest site)} + @ul{@(let ([mirrors + (filter-map + (λ (m) + (define url + (mirror-link + (string-append (mirror-url m) path) + size + (λ () (format "~a <~a>" + (mirror-person m) + (mirror-email m))))) + (and url @li{@a[href: url]{@(mirror-location m)}})) + mirrors)]) + (case (length mirrors) + [(0) (error 'installer-page "no available mirror for: ~e" + path)] + [(1) (list mirrors + @li{@small{(no additional mirrors, yet)}})] + [else mirrors]))}}}} + @;TODO: decide whether this is really needed + @; (looks redundant now that all of the installers are pretty standard) + @;section{Installation instructions} + @;(bundle-installation-instructions bundle) + }) + +(provide installer->page) +(define installer->page + (let ([t (make-hasheq)]) + (λ (inst . more) + (let ([page (hash-ref! t inst (λ () (render-installer-page inst)))]) + (if (null? more) page (apply page more)))))) diff --git a/new-racket-web/web/download/installers.txt b/new-racket-web/web/download/installers.txt new file mode 100644 index 0000000000..78b46fa76d --- /dev/null +++ b/new-racket-web/web/download/installers.txt @@ -0,0 +1,382 @@ +9300697 5.0.1/racket-textual/racket-textual-5.0.1-bin-i386-linux-debian.sh +9304219 5.0.1/racket-textual/racket-textual-5.0.1-bin-i386-linux-f12.sh +9313351 5.0.1/racket-textual/racket-textual-5.0.1-bin-i386-linux-ubuntu-jaunty.sh +9598271 5.0.1/racket-textual/racket-textual-5.0.1-bin-i386-osx-mac.dmg +7195260 5.0.1/racket-textual/racket-textual-5.0.1-bin-i386-win32.exe +9275500 5.0.1/racket-textual/racket-textual-5.0.1-bin-ppc-darwin.sh +9590434 5.0.1/racket-textual/racket-textual-5.0.1-bin-ppc-osx-mac.dmg +9428494 5.0.1/racket-textual/racket-textual-5.0.1-bin-x86_64-linux-f7.sh +5832011 5.0.1/racket-textual/racket-textual-5.0.1-src-mac.dmg +5714125 5.0.1/racket-textual/racket-textual-5.0.1-src-unix.tgz +7115859 5.0.1/racket-textual/racket-textual-5.0.1-src-win.zip +48280952 5.0.1/racket/racket-5.0.1-bin-i386-linux-debian.sh +48274719 5.0.1/racket/racket-5.0.1-bin-i386-linux-f12.sh +48321280 5.0.1/racket/racket-5.0.1-bin-i386-linux-ubuntu-jaunty.sh +49529404 5.0.1/racket/racket-5.0.1-bin-i386-osx-mac.dmg +29974852 5.0.1/racket/racket-5.0.1-bin-i386-win32.exe +48227579 5.0.1/racket/racket-5.0.1-bin-ppc-darwin.sh +49553958 5.0.1/racket/racket-5.0.1-bin-ppc-osx-mac.dmg +48582065 5.0.1/racket/racket-5.0.1-bin-x86_64-linux-f7.sh +17343846 5.0.1/racket/racket-5.0.1-src-mac.dmg +17272590 5.0.1/racket/racket-5.0.1-src-unix.tgz +20625477 5.0.1/racket/racket-5.0.1-src-win.zip +9753004 5.0.2/racket-textual/racket-textual-5.0.2-bin-i386-linux-debian.sh +9759330 5.0.2/racket-textual/racket-textual-5.0.2-bin-i386-linux-f12.sh +9769701 5.0.2/racket-textual/racket-textual-5.0.2-bin-i386-linux-ubuntu-jaunty.sh +10061865 5.0.2/racket-textual/racket-textual-5.0.2-bin-i386-osx-mac.dmg +7483846 5.0.2/racket-textual/racket-textual-5.0.2-bin-i386-win32.exe +9723983 5.0.2/racket-textual/racket-textual-5.0.2-bin-ppc-darwin.sh +10054183 5.0.2/racket-textual/racket-textual-5.0.2-bin-ppc-osx-mac.dmg +9889541 5.0.2/racket-textual/racket-textual-5.0.2-bin-x86_64-linux-f7.sh +5939776 5.0.2/racket-textual/racket-textual-5.0.2-src-mac.dmg +5815219 5.0.2/racket-textual/racket-textual-5.0.2-src-unix.tgz +7283576 5.0.2/racket-textual/racket-textual-5.0.2-src-win.zip +50263773 5.0.2/racket/racket-5.0.2-bin-i386-linux-debian.sh +50264748 5.0.2/racket/racket-5.0.2-bin-i386-linux-f12.sh +50304157 5.0.2/racket/racket-5.0.2-bin-i386-linux-ubuntu-jaunty.sh +51514800 5.0.2/racket/racket-5.0.2-bin-i386-osx-mac.dmg +31130193 5.0.2/racket/racket-5.0.2-bin-i386-win32.exe +50204906 5.0.2/racket/racket-5.0.2-bin-ppc-darwin.sh +51567239 5.0.2/racket/racket-5.0.2-bin-ppc-osx-mac.dmg +50579715 5.0.2/racket/racket-5.0.2-bin-x86_64-linux-f7.sh +17699549 5.0.2/racket/racket-5.0.2-src-mac.dmg +17622692 5.0.2/racket/racket-5.0.2-src-unix.tgz +21092427 5.0.2/racket/racket-5.0.2-src-win.zip +9015818 5.0/racket-textual/racket-textual-5.0-bin-i386-linux-debian.sh +9025266 5.0/racket-textual/racket-textual-5.0-bin-i386-linux-f12.sh +9039169 5.0/racket-textual/racket-textual-5.0-bin-i386-linux-ubuntu-jaunty.sh +9324539 5.0/racket-textual/racket-textual-5.0-bin-i386-osx-mac.dmg +7023498 5.0/racket-textual/racket-textual-5.0-bin-i386-win32.exe +8999839 5.0/racket-textual/racket-textual-5.0-bin-ppc-darwin.sh +9330306 5.0/racket-textual/racket-textual-5.0-bin-ppc-osx-mac.dmg +9159233 5.0/racket-textual/racket-textual-5.0-bin-x86_64-linux-f7.sh +5539138 5.0/racket-textual/racket-textual-5.0-src-mac.dmg +5408767 5.0/racket-textual/racket-textual-5.0-src-unix.tgz +7041524 5.0/racket-textual/racket-textual-5.0-src-win.zip +46469932 5.0/racket/racket-5.0-bin-i386-linux-debian.sh +46483844 5.0/racket/racket-5.0-bin-i386-linux-f12.sh +46515740 5.0/racket/racket-5.0-bin-i386-linux-ubuntu-jaunty.sh +47637362 5.0/racket/racket-5.0-bin-i386-osx-mac.dmg +28973247 5.0/racket/racket-5.0-bin-i386-win32.exe +46418573 5.0/racket/racket-5.0-bin-ppc-darwin.sh +47693225 5.0/racket/racket-5.0-bin-ppc-osx-mac.dmg +46784914 5.0/racket/racket-5.0-bin-x86_64-linux-f7.sh +16727955 5.0/racket/racket-5.0-src-mac.dmg +16661627 5.0/racket/racket-5.0-src-unix.tgz +20043612 5.0/racket/racket-5.0-src-win.zip +10608594 5.1.1/racket-textual/racket-textual-5.1.1-bin-i386-linux-f12.sh +10617031 5.1.1/racket-textual/racket-textual-5.1.1-bin-i386-linux-ubuntu-jaunty.sh +10944378 5.1.1/racket-textual/racket-textual-5.1.1-bin-i386-osx-mac.dmg +7871781 5.1.1/racket-textual/racket-textual-5.1.1-bin-i386-win32.exe +10563612 5.1.1/racket-textual/racket-textual-5.1.1-bin-ppc-darwin.sh +10925675 5.1.1/racket-textual/racket-textual-5.1.1-bin-ppc-osx-mac.dmg +10777466 5.1.1/racket-textual/racket-textual-5.1.1-bin-x86_64-linux-f14.sh +6088017 5.1.1/racket-textual/racket-textual-5.1.1-src-mac.dmg +5972450 5.1.1/racket-textual/racket-textual-5.1.1-src-unix.tgz +7072928 5.1.1/racket-textual/racket-textual-5.1.1-src-win.zip +51562160 5.1.1/racket/racket-5.1.1-bin-i386-linux-f12.sh +51583365 5.1.1/racket/racket-5.1.1-bin-i386-linux-ubuntu-jaunty.sh +53227597 5.1.1/racket/racket-5.1.1-bin-i386-osx-mac.dmg +33299725 5.1.1/racket/racket-5.1.1-bin-i386-win32.exe +51319041 5.1.1/racket/racket-5.1.1-bin-ppc-darwin.sh +54275107 5.1.1/racket/racket-5.1.1-bin-ppc-osx-mac.dmg +51928808 5.1.1/racket/racket-5.1.1-bin-x86_64-linux-f14.sh +16221515 5.1.1/racket/racket-5.1.1-src-mac.dmg +15884853 5.1.1/racket/racket-5.1.1-src-unix.tgz +19117693 5.1.1/racket/racket-5.1.1-src-win.zip +10294418 5.1.2/racket-textual/racket-textual-5.1.2-bin-i386-linux-f12.sh +10305056 5.1.2/racket-textual/racket-textual-5.1.2-bin-i386-linux-ubuntu-jaunty.sh +10649433 5.1.2/racket-textual/racket-textual-5.1.2-bin-i386-osx-mac.dmg +7735142 5.1.2/racket-textual/racket-textual-5.1.2-bin-i386-win32.exe +10229144 5.1.2/racket-textual/racket-textual-5.1.2-bin-ppc-darwin.sh +10600014 5.1.2/racket-textual/racket-textual-5.1.2-bin-ppc-osx-mac.dmg +10465204 5.1.2/racket-textual/racket-textual-5.1.2-bin-x86_64-linux-debian-lenny.sh +10476031 5.1.2/racket-textual/racket-textual-5.1.2-bin-x86_64-linux-debian-squeeze.sh +10474930 5.1.2/racket-textual/racket-textual-5.1.2-bin-x86_64-linux-f14.sh +10849704 5.1.2/racket-textual/racket-textual-5.1.2-bin-x86_64-osx-mac.dmg +8035589 5.1.2/racket-textual/racket-textual-5.1.2-bin-x86_64-win32.exe +5927007 5.1.2/racket-textual/racket-textual-5.1.2-src-mac.dmg +5814309 5.1.2/racket-textual/racket-textual-5.1.2-src-unix.tgz +6858089 5.1.2/racket-textual/racket-textual-5.1.2-src-win.zip +50068153 5.1.2/racket/racket-5.1.2-bin-i386-linux-f12.sh +50101512 5.1.2/racket/racket-5.1.2-bin-i386-linux-ubuntu-jaunty.sh +51665644 5.1.2/racket/racket-5.1.2-bin-i386-osx-mac.dmg +32577645 5.1.2/racket/racket-5.1.2-bin-i386-win32.exe +49784628 5.1.2/racket/racket-5.1.2-bin-ppc-darwin.sh +52725371 5.1.2/racket/racket-5.1.2-bin-ppc-osx-mac.dmg +50416939 5.1.2/racket/racket-5.1.2-bin-x86_64-linux-debian-lenny.sh +50437726 5.1.2/racket/racket-5.1.2-bin-x86_64-linux-debian-squeeze.sh +50446330 5.1.2/racket/racket-5.1.2-bin-x86_64-linux-f14.sh +51976069 5.1.2/racket/racket-5.1.2-bin-x86_64-osx-mac.dmg +33226602 5.1.2/racket/racket-5.1.2-bin-x86_64-win32.exe +16293184 5.1.2/racket/racket-5.1.2-src-mac.dmg +15960181 5.1.2/racket/racket-5.1.2-src-unix.tgz +19203148 5.1.2/racket/racket-5.1.2-src-win.zip +10277328 5.1.3/racket-textual/racket-textual-5.1.3-bin-i386-linux-f12.sh +10286517 5.1.3/racket-textual/racket-textual-5.1.3-bin-i386-linux-ubuntu-jaunty.sh +10646200 5.1.3/racket-textual/racket-textual-5.1.3-bin-i386-osx-mac.dmg +7721338 5.1.3/racket-textual/racket-textual-5.1.3-bin-i386-win32.exe +10209882 5.1.3/racket-textual/racket-textual-5.1.3-bin-ppc-darwin.sh +10578888 5.1.3/racket-textual/racket-textual-5.1.3-bin-ppc-osx-mac.dmg +10445665 5.1.3/racket-textual/racket-textual-5.1.3-bin-x86_64-linux-debian-lenny.sh +10458130 5.1.3/racket-textual/racket-textual-5.1.3-bin-x86_64-linux-debian-squeeze.sh +10458009 5.1.3/racket-textual/racket-textual-5.1.3-bin-x86_64-linux-f14.sh +10844242 5.1.3/racket-textual/racket-textual-5.1.3-bin-x86_64-osx-mac.dmg +8024578 5.1.3/racket-textual/racket-textual-5.1.3-bin-x86_64-win32.exe +5909369 5.1.3/racket-textual/racket-textual-5.1.3-src-mac.dmg +5795883 5.1.3/racket-textual/racket-textual-5.1.3-src-unix.tgz +6840314 5.1.3/racket-textual/racket-textual-5.1.3-src-win.zip +50047413 5.1.3/racket/racket-5.1.3-bin-i386-linux-f12.sh +50082199 5.1.3/racket/racket-5.1.3-bin-i386-linux-ubuntu-jaunty.sh +51638634 5.1.3/racket/racket-5.1.3-bin-i386-osx-mac.dmg +32548344 5.1.3/racket/racket-5.1.3-bin-i386-win32.exe +49765546 5.1.3/racket/racket-5.1.3-bin-ppc-darwin.sh +52694190 5.1.3/racket/racket-5.1.3-bin-ppc-osx-mac.dmg +50391225 5.1.3/racket/racket-5.1.3-bin-x86_64-linux-debian-lenny.sh +50405579 5.1.3/racket/racket-5.1.3-bin-x86_64-linux-debian-squeeze.sh +50431407 5.1.3/racket/racket-5.1.3-bin-x86_64-linux-f14.sh +51949468 5.1.3/racket/racket-5.1.3-bin-x86_64-osx-mac.dmg +33194397 5.1.3/racket/racket-5.1.3-bin-x86_64-win32.exe +16270003 5.1.3/racket/racket-5.1.3-src-mac.dmg +15939654 5.1.3/racket/racket-5.1.3-src-unix.tgz +19185643 5.1.3/racket/racket-5.1.3-src-win.zip +10661589 5.1/racket-textual/racket-textual-5.1-bin-i386-linux-f12.sh +10674322 5.1/racket-textual/racket-textual-5.1-bin-i386-linux-ubuntu-jaunty.sh +11019666 5.1/racket-textual/racket-textual-5.1-bin-i386-osx-mac.dmg +7899916 5.1/racket-textual/racket-textual-5.1-bin-i386-win32.exe +10627504 5.1/racket-textual/racket-textual-5.1-bin-ppc-darwin.sh +11009730 5.1/racket-textual/racket-textual-5.1-bin-ppc-osx-mac.dmg +10835079 5.1/racket-textual/racket-textual-5.1-bin-x86_64-linux-f14.sh +6064958 5.1/racket-textual/racket-textual-5.1-src-mac.dmg +5945844 5.1/racket-textual/racket-textual-5.1-src-unix.tgz +6071742 5.1/racket-textual/racket-textual-5.1-src-win.zip +51529968 5.1/racket/racket-5.1-bin-i386-linux-f12.sh +51560486 5.1/racket/racket-5.1-bin-i386-linux-ubuntu-jaunty.sh +53300468 5.1/racket/racket-5.1-bin-i386-osx-mac.dmg +33200268 5.1/racket/racket-5.1-bin-i386-win32.exe +51306060 5.1/racket/racket-5.1-bin-ppc-darwin.sh +54367850 5.1/racket/racket-5.1-bin-ppc-osx-mac.dmg +51892721 5.1/racket/racket-5.1-bin-x86_64-linux-f14.sh +16095941 5.1/racket/racket-5.1-src-mac.dmg +15759982 5.1/racket/racket-5.1-src-unix.tgz +17987080 5.1/racket/racket-5.1-src-win.zip +10268779 5.2.1/racket-textual/racket-textual-5.2.1-bin-i386-linux-f12.sh +10279415 5.2.1/racket-textual/racket-textual-5.2.1-bin-i386-linux-ubuntu-karmic.sh +10829117 5.2.1/racket-textual/racket-textual-5.2.1-bin-i386-osx-mac.dmg +7719949 5.2.1/racket-textual/racket-textual-5.2.1-bin-i386-win32.exe +10766423 5.2.1/racket-textual/racket-textual-5.2.1-bin-ppc-osx-mac.dmg +10453826 5.2.1/racket-textual/racket-textual-5.2.1-bin-x86_64-linux-debian-squeeze.sh +10458751 5.2.1/racket-textual/racket-textual-5.2.1-bin-x86_64-linux-f14.sh +10960644 5.2.1/racket-textual/racket-textual-5.2.1-bin-x86_64-osx-mac.dmg +8048658 5.2.1/racket-textual/racket-textual-5.2.1-bin-x86_64-win32.exe +5944766 5.2.1/racket-textual/racket-textual-5.2.1-src-mac.dmg +5822408 5.2.1/racket-textual/racket-textual-5.2.1-src-unix.tgz +6874674 5.2.1/racket-textual/racket-textual-5.2.1-src-win.zip +58246608 5.2.1/racket/racket-5.2.1-bin-i386-linux-f12.sh +58279927 5.2.1/racket/racket-5.2.1-bin-i386-linux-ubuntu-karmic.sh +60604498 5.2.1/racket/racket-5.2.1-bin-i386-osx-mac.dmg +39516478 5.2.1/racket/racket-5.2.1-bin-i386-win32.exe +61654421 5.2.1/racket/racket-5.2.1-bin-ppc-osx-mac.dmg +58616709 5.2.1/racket/racket-5.2.1-bin-x86_64-linux-debian-squeeze.sh +58626727 5.2.1/racket/racket-5.2.1-bin-x86_64-linux-f14.sh +60847004 5.2.1/racket/racket-5.2.1-bin-x86_64-osx-mac.dmg +40203933 5.2.1/racket/racket-5.2.1-bin-x86_64-win32.exe +17941288 5.2.1/racket/racket-5.2.1-src-mac.dmg +17211427 5.2.1/racket/racket-5.2.1-src-unix.tgz +20641716 5.2.1/racket/racket-5.2.1-src-win.zip +10072568 5.2/racket-textual/racket-textual-5.2-bin-i386-linux-f12.sh +10087724 5.2/racket-textual/racket-textual-5.2-bin-i386-linux-ubuntu-karmic.sh +10419223 5.2/racket-textual/racket-textual-5.2-bin-i386-osx-mac.dmg +7639819 5.2/racket-textual/racket-textual-5.2-bin-i386-win32.exe +10001213 5.2/racket-textual/racket-textual-5.2-bin-ppc-darwin.sh +10368884 5.2/racket-textual/racket-textual-5.2-bin-ppc-osx-mac.dmg +10243046 5.2/racket-textual/racket-textual-5.2-bin-x86_64-linux-debian-lenny.sh +10256265 5.2/racket-textual/racket-textual-5.2-bin-x86_64-linux-debian-squeeze.sh +10259861 5.2/racket-textual/racket-textual-5.2-bin-x86_64-linux-f14.sh +10631349 5.2/racket-textual/racket-textual-5.2-bin-x86_64-osx-mac.dmg +7965785 5.2/racket-textual/racket-textual-5.2-bin-x86_64-win32.exe +5926754 5.2/racket-textual/racket-textual-5.2-src-mac.dmg +5806691 5.2/racket-textual/racket-textual-5.2-src-unix.tgz +6846137 5.2/racket-textual/racket-textual-5.2-src-win.zip +54306960 5.2/racket/racket-5.2-bin-i386-linux-f12.sh +54333056 5.2/racket/racket-5.2-bin-i386-linux-ubuntu-karmic.sh +56070009 5.2/racket/racket-5.2-bin-i386-osx-mac.dmg +36205596 5.2/racket/racket-5.2-bin-i386-win32.exe +54161422 5.2/racket/racket-5.2-bin-ppc-darwin.sh +57109008 5.2/racket/racket-5.2-bin-ppc-osx-mac.dmg +54654394 5.2/racket/racket-5.2-bin-x86_64-linux-debian-lenny.sh +54678069 5.2/racket/racket-5.2-bin-x86_64-linux-debian-squeeze.sh +54685565 5.2/racket/racket-5.2-bin-x86_64-linux-f14.sh +56380421 5.2/racket/racket-5.2-bin-x86_64-osx-mac.dmg +36902485 5.2/racket/racket-5.2-bin-x86_64-win32.exe +16601808 5.2/racket/racket-5.2-src-mac.dmg +16260740 5.2/racket/racket-5.2-src-unix.tgz +19575041 5.2/racket/racket-5.2-src-win.zip +11552351 5.3.1/racket-textual/racket-textual-5.3.1-bin-i386-linux-f12.sh +11570689 5.3.1/racket-textual/racket-textual-5.3.1-bin-i386-linux-ubuntu-karmic.sh +12143855 5.3.1/racket-textual/racket-textual-5.3.1-bin-i386-osx-mac.dmg +8803203 5.3.1/racket-textual/racket-textual-5.3.1-bin-i386-win32.exe +12081255 5.3.1/racket-textual/racket-textual-5.3.1-bin-ppc-osx-mac.dmg +11748331 5.3.1/racket-textual/racket-textual-5.3.1-bin-x86_64-linux-debian-squeeze.sh +11757467 5.3.1/racket-textual/racket-textual-5.3.1-bin-x86_64-linux-f14.sh +12278659 5.3.1/racket-textual/racket-textual-5.3.1-bin-x86_64-osx-mac.dmg +9171125 5.3.1/racket-textual/racket-textual-5.3.1-bin-x86_64-win32.exe +6254337 5.3.1/racket-textual/racket-textual-5.3.1-src-mac.dmg +6134415 5.3.1/racket-textual/racket-textual-5.3.1-src-unix.tgz +7252130 5.3.1/racket-textual/racket-textual-5.3.1-src-win.zip +64527997 5.3.1/racket/racket-5.3.1-bin-i386-linux-f12.sh +64562401 5.3.1/racket/racket-5.3.1-bin-i386-linux-ubuntu-karmic.sh +67179194 5.3.1/racket/racket-5.3.1-bin-i386-osx-mac.dmg +43655604 5.3.1/racket/racket-5.3.1-bin-i386-win32.exe +67981764 5.3.1/racket/racket-5.3.1-bin-ppc-osx-mac.dmg +64911589 5.3.1/racket/racket-5.3.1-bin-x86_64-linux-debian-squeeze.sh +64927156 5.3.1/racket/racket-5.3.1-bin-x86_64-linux-f14.sh +67721160 5.3.1/racket/racket-5.3.1-bin-x86_64-osx-mac.dmg +44343519 5.3.1/racket/racket-5.3.1-bin-x86_64-win32.exe +19042596 5.3.1/racket/racket-5.3.1-src-mac.dmg +18296513 5.3.1/racket/racket-5.3.1-src-unix.tgz +21668825 5.3.1/racket/racket-5.3.1-src-win.zip +11948337 5.3.2/racket-textual/racket-textual-5.3.2-bin-i386-linux-f12.sh +11962344 5.3.2/racket-textual/racket-textual-5.3.2-bin-i386-linux-ubuntu-karmic.sh +15258690 5.3.2/racket-textual/racket-textual-5.3.2-bin-i386-osx-mac.dmg +9034873 5.3.2/racket-textual/racket-textual-5.3.2-bin-i386-win32.exe +15168349 5.3.2/racket-textual/racket-textual-5.3.2-bin-ppc-osx-mac.dmg +12150829 5.3.2/racket-textual/racket-textual-5.3.2-bin-x86_64-linux-debian-squeeze.sh +12155747 5.3.2/racket-textual/racket-textual-5.3.2-bin-x86_64-linux-f14.sh +15373372 5.3.2/racket-textual/racket-textual-5.3.2-bin-x86_64-osx-mac.dmg +9405386 5.3.2/racket-textual/racket-textual-5.3.2-bin-x86_64-win32.exe +5432417 5.3.2/racket-textual/racket-textual-5.3.2-src-mac.dmg +6220657 5.3.2/racket-textual/racket-textual-5.3.2-src-unix.tgz +7345556 5.3.2/racket-textual/racket-textual-5.3.2-src-win.zip +80046600 5.3.2/racket/racket-5.3.2-bin-i386-linux-f12.sh +80071196 5.3.2/racket/racket-5.3.2-bin-i386-linux-ubuntu-karmic.sh +77185236 5.3.2/racket/racket-5.3.2-bin-i386-osx-mac.dmg +53476867 5.3.2/racket/racket-5.3.2-bin-i386-win32.exe +73863798 5.3.2/racket/racket-5.3.2-bin-ppc-osx-mac.dmg +80444872 5.3.2/racket/racket-5.3.2-bin-x86_64-linux-debian-squeeze.sh +80455630 5.3.2/racket/racket-5.3.2-bin-x86_64-linux-f14.sh +77714727 5.3.2/racket/racket-5.3.2-bin-x86_64-osx-mac.dmg +54173869 5.3.2/racket/racket-5.3.2-bin-x86_64-win32.exe +17441261 5.3.2/racket/racket-5.3.2-src-mac.dmg +18903002 5.3.2/racket/racket-5.3.2-src-unix.tgz +22453626 5.3.2/racket/racket-5.3.2-src-win.zip +11948492 5.3.3/racket-textual/racket-textual-5.3.3-bin-i386-linux-f12.sh +11964412 5.3.3/racket-textual/racket-textual-5.3.3-bin-i386-linux-ubuntu-karmic.sh +15256661 5.3.3/racket-textual/racket-textual-5.3.3-bin-i386-osx-mac.dmg +9035043 5.3.3/racket-textual/racket-textual-5.3.3-bin-i386-win32.exe +15168071 5.3.3/racket-textual/racket-textual-5.3.3-bin-ppc-osx-mac.dmg +12151112 5.3.3/racket-textual/racket-textual-5.3.3-bin-x86_64-linux-debian-squeeze.sh +12158241 5.3.3/racket-textual/racket-textual-5.3.3-bin-x86_64-linux-f14.sh +15374489 5.3.3/racket-textual/racket-textual-5.3.3-bin-x86_64-osx-mac.dmg +9406684 5.3.3/racket-textual/racket-textual-5.3.3-bin-x86_64-win32.exe +5432743 5.3.3/racket-textual/racket-textual-5.3.3-src-mac.dmg +6220717 5.3.3/racket-textual/racket-textual-5.3.3-src-unix.tgz +7345556 5.3.3/racket-textual/racket-textual-5.3.3-src-win.zip +80042709 5.3.3/racket/racket-5.3.3-bin-i386-linux-f12.sh +80064095 5.3.3/racket/racket-5.3.3-bin-i386-linux-ubuntu-karmic.sh +77158882 5.3.3/racket/racket-5.3.3-bin-i386-osx-mac.dmg +53475451 5.3.3/racket/racket-5.3.3-bin-i386-win32.exe +77805576 5.3.3/racket/racket-5.3.3-bin-ppc-osx-mac.dmg +80441231 5.3.3/racket/racket-5.3.3-bin-x86_64-linux-debian-squeeze.sh +80445042 5.3.3/racket/racket-5.3.3-bin-x86_64-linux-f14.sh +77740581 5.3.3/racket/racket-5.3.3-bin-x86_64-osx-mac.dmg +54177148 5.3.3/racket/racket-5.3.3-bin-x86_64-win32.exe +17441645 5.3.3/racket/racket-5.3.3-src-mac.dmg +18903284 5.3.3/racket/racket-5.3.3-src-unix.tgz +22453769 5.3.3/racket/racket-5.3.3-src-win.zip +12320423 5.3.4/racket-textual/racket-textual-5.3.4-bin-i386-linux-f12.sh +12334215 5.3.4/racket-textual/racket-textual-5.3.4-bin-i386-linux-ubuntu-karmic.sh +15652299 5.3.4/racket-textual/racket-textual-5.3.4-bin-i386-osx-mac.dmg +9278646 5.3.4/racket-textual/racket-textual-5.3.4-bin-i386-win32.exe +15553227 5.3.4/racket-textual/racket-textual-5.3.4-bin-ppc-osx-mac.dmg +12545952 5.3.4/racket-textual/racket-textual-5.3.4-bin-x86_64-linux-debian-squeeze.sh +12547477 5.3.4/racket-textual/racket-textual-5.3.4-bin-x86_64-linux-f14.sh +15778683 5.3.4/racket-textual/racket-textual-5.3.4-bin-x86_64-osx-mac.dmg +9656737 5.3.4/racket-textual/racket-textual-5.3.4-bin-x86_64-win32.exe +5514976 5.3.4/racket-textual/racket-textual-5.3.4-src-mac.dmg +6314719 5.3.4/racket-textual/racket-textual-5.3.4-src-unix.tgz +7450712 5.3.4/racket-textual/racket-textual-5.3.4-src-win.zip +81404184 5.3.4/racket/racket-5.3.4-bin-i386-linux-f12.sh +81442144 5.3.4/racket/racket-5.3.4-bin-i386-linux-ubuntu-karmic.sh +78402102 5.3.4/racket/racket-5.3.4-bin-i386-osx-mac.dmg +54269511 5.3.4/racket/racket-5.3.4-bin-i386-win32.exe +79000954 5.3.4/racket/racket-5.3.4-bin-ppc-osx-mac.dmg +81847504 5.3.4/racket/racket-5.3.4-bin-x86_64-linux-debian-squeeze.sh +81863215 5.3.4/racket/racket-5.3.4-bin-x86_64-linux-f14.sh +78954459 5.3.4/racket/racket-5.3.4-bin-x86_64-osx-mac.dmg +54968330 5.3.4/racket/racket-5.3.4-bin-x86_64-win32.exe +17824228 5.3.4/racket/racket-5.3.4-src-mac.dmg +19314579 5.3.4/racket/racket-5.3.4-src-unix.tgz +22930176 5.3.4/racket/racket-5.3.4-src-win.zip +12292655 5.3.5/racket-textual/racket-textual-5.3.5-bin-i386-linux-f12.sh +15648971 5.3.5/racket-textual/racket-textual-5.3.5-bin-i386-osx-mac.dmg +9278714 5.3.5/racket-textual/racket-textual-5.3.5-bin-i386-win32.exe +15550280 5.3.5/racket-textual/racket-textual-5.3.5-bin-ppc-osx-mac.dmg +12518673 5.3.5/racket-textual/racket-textual-5.3.5-bin-x86_64-linux-debian-squeeze.sh +12500092 5.3.5/racket-textual/racket-textual-5.3.5-bin-x86_64-linux-f18.sh +12514647 5.3.5/racket-textual/racket-textual-5.3.5-bin-x86_64-linux-ubuntu-precise.sh +15777345 5.3.5/racket-textual/racket-textual-5.3.5-bin-x86_64-osx-mac.dmg +9653899 5.3.5/racket-textual/racket-textual-5.3.5-bin-x86_64-win32.exe +5514952 5.3.5/racket-textual/racket-textual-5.3.5-src-mac.dmg +6264428 5.3.5/racket-textual/racket-textual-5.3.5-src-unix.tgz +7450709 5.3.5/racket-textual/racket-textual-5.3.5-src-win.zip +80912617 5.3.5/racket/racket-5.3.5-bin-i386-linux-f12.sh +78333891 5.3.5/racket/racket-5.3.5-bin-i386-osx-mac.dmg +54222087 5.3.5/racket/racket-5.3.5-bin-i386-win32.exe +78969552 5.3.5/racket/racket-5.3.5-bin-ppc-osx-mac.dmg +81335329 5.3.5/racket/racket-5.3.5-bin-x86_64-linux-debian-squeeze.sh +81315398 5.3.5/racket/racket-5.3.5-bin-x86_64-linux-f18.sh +81340721 5.3.5/racket/racket-5.3.5-bin-x86_64-linux-ubuntu-precise.sh +78898223 5.3.5/racket/racket-5.3.5-bin-x86_64-osx-mac.dmg +54926791 5.3.5/racket/racket-5.3.5-bin-x86_64-win32.exe +17939101 5.3.5/racket/racket-5.3.5-src-mac.dmg +19260480 5.3.5/racket/racket-5.3.5-src-unix.tgz +23057646 5.3.5/racket/racket-5.3.5-src-win.zip +12295243 5.3.6/racket-textual/racket-textual-5.3.6-bin-i386-linux-f12.sh +15658693 5.3.6/racket-textual/racket-textual-5.3.6-bin-i386-osx-mac.dmg +9277473 5.3.6/racket-textual/racket-textual-5.3.6-bin-i386-win32.exe +15558719 5.3.6/racket-textual/racket-textual-5.3.6-bin-ppc-osx-mac.dmg +12518633 5.3.6/racket-textual/racket-textual-5.3.6-bin-x86_64-linux-debian-squeeze.sh +12502053 5.3.6/racket-textual/racket-textual-5.3.6-bin-x86_64-linux-f18.sh +12514865 5.3.6/racket-textual/racket-textual-5.3.6-bin-x86_64-linux-ubuntu-precise.sh +15785347 5.3.6/racket-textual/racket-textual-5.3.6-bin-x86_64-osx-mac.dmg +9655376 5.3.6/racket-textual/racket-textual-5.3.6-bin-x86_64-win32.exe +5518958 5.3.6/racket-textual/racket-textual-5.3.6-src-mac.dmg +6266358 5.3.6/racket-textual/racket-textual-5.3.6-src-unix.tgz +7452375 5.3.6/racket-textual/racket-textual-5.3.6-src-win.zip +80959315 5.3.6/racket/racket-5.3.6-bin-i386-linux-f12.sh +78522953 5.3.6/racket/racket-5.3.6-bin-i386-osx-mac.dmg +54275461 5.3.6/racket/racket-5.3.6-bin-i386-win32.exe +79152425 5.3.6/racket/racket-5.3.6-bin-ppc-osx-mac.dmg +81401477 5.3.6/racket/racket-5.3.6-bin-x86_64-linux-debian-squeeze.sh +81379740 5.3.6/racket/racket-5.3.6-bin-x86_64-linux-f18.sh +81399545 5.3.6/racket/racket-5.3.6-bin-x86_64-linux-ubuntu-precise.sh +79072519 5.3.6/racket/racket-5.3.6-bin-x86_64-osx-mac.dmg +54977925 5.3.6/racket/racket-5.3.6-bin-x86_64-win32.exe +17944355 5.3.6/racket/racket-5.3.6-src-mac.dmg +19278914 5.3.6/racket/racket-5.3.6-src-unix.tgz +23080500 5.3.6/racket/racket-5.3.6-src-win.zip +11235593 5.3/racket-textual/racket-textual-5.3-bin-i386-linux-f12.sh +11248024 5.3/racket-textual/racket-textual-5.3-bin-i386-linux-ubuntu-karmic.sh +11806657 5.3/racket-textual/racket-textual-5.3-bin-i386-osx-mac.dmg +8616632 5.3/racket-textual/racket-textual-5.3-bin-i386-win32.exe +11733097 5.3/racket-textual/racket-textual-5.3-bin-ppc-osx-mac.dmg +11429790 5.3/racket-textual/racket-textual-5.3-bin-x86_64-linux-debian-squeeze.sh +11433426 5.3/racket-textual/racket-textual-5.3-bin-x86_64-linux-f14.sh +11944406 5.3/racket-textual/racket-textual-5.3-bin-x86_64-osx-mac.dmg +8985418 5.3/racket-textual/racket-textual-5.3-bin-x86_64-win32.exe +6200415 5.3/racket-textual/racket-textual-5.3-src-mac.dmg +6076092 5.3/racket-textual/racket-textual-5.3-src-unix.tgz +7163517 5.3/racket-textual/racket-textual-5.3-src-win.zip +63546257 5.3/racket/racket-5.3-bin-i386-linux-f12.sh +63584563 5.3/racket/racket-5.3-bin-i386-linux-ubuntu-karmic.sh +66195664 5.3/racket/racket-5.3-bin-i386-osx-mac.dmg +43257532 5.3/racket/racket-5.3-bin-i386-win32.exe +66989480 5.3/racket/racket-5.3-bin-ppc-osx-mac.dmg +63926568 5.3/racket/racket-5.3-bin-x86_64-linux-debian-squeeze.sh +63943730 5.3/racket/racket-5.3-bin-x86_64-linux-f14.sh +66712297 5.3/racket/racket-5.3-bin-x86_64-osx-mac.dmg +43943553 5.3/racket/racket-5.3-bin-x86_64-win32.exe +18849342 5.3/racket/racket-5.3-src-mac.dmg +18111154 5.3/racket/racket-5.3-src-unix.tgz +21394184 5.3/racket/racket-5.3-src-win.zip diff --git a/new-racket-web/web/download/mirror-link.rkt b/new-racket-web/web/download/mirror-link.rkt new file mode 100644 index 0000000000..82b965dd8f --- /dev/null +++ b/new-racket-web/web/download/mirror-link.rkt @@ -0,0 +1,177 @@ +#lang racket/base + +#| + +This file polls mirror links: (mirror-link ) will return the +url only if it is live, and its size fits the expected size. Otherwise +it returns #f, or #t in some rare cases where the size is not known from +the poll. + +This is done only if the "KNOWN_MIRRORS_FILE" environment variable is +set, otherwise all mirror links are included. If the variable is set, +it should point at a cache file that holds information about polls, used +to avoid re-polling all links all the time. + +Polling a URL can result in one of four options: +1. The URL doesn't seem to exist. In this case, the link is not shown, + and the URL will be re-polled if a web-page build is done 15 + minutes (or more) later. +2. The URL exists, but no size information is available (via a HEAD + query, or via an FTP directory listing). The link will be shown in + this case, but it will be re-polled two days later. (With a 1..2 + random factor, and a nightly build that happens at the same time, + this will be around 3-5 days.) So far, all mirrors provide size + information, so this works fine. +3. The URL exists and we get its size, but the size does not match. The + URL is not shown, and will be re-polled in an hour. The assumption + here is either bad synchronization, or we caught it in progress. +4. The size is correct, so the URL is shown. This case still leads to + re-polling, but only after a month. The reason for this is in case a + mirror is not maintained -- we'll want the links to eventually + disappear. + +|# + +(require net/url net/ftp net/sendmail) + +;; the mirrors file has (list url secs result) entries containing the url as a +;; string, the time it was checked (the result of `current-seconds'), and the +;; result of the `verify-*' function. +(define known-mirrors-file + (let ([f (getenv "KNOWN_MIRRORS_FILE")]) (and (not (equal? "" f)) f))) +(define known-mirrors + (if (and known-mirrors-file (file-exists? known-mirrors-file)) + (call-with-input-file* known-mirrors-file + (λ (inp) (for/list ([x (in-producer read eof inp)]) x))) + '())) + +;; main entry to getting a known entry result: given the url, return the +;; remembered result unless it doesn't exist or it expired; in those cases use +;; the thunk to get a current result and remember it; note that expiration +;; times are different for different results, and the decision whether to check +;; one is randomized (cheaply, since it'll be sensitive to how frequently a +;; build is done -- usually by the nightly build). +(define (known-mirror-get url size thunk get-responsible-email) + (define entry (assoc url known-mirrors)) + (define last-time (and entry (cadr entry))) + (define result (and entry (caddr entry))) + (define R (+ 1 (random))) ; random 1..2 number, to avoid congestion + (define new + (and (cond + ;; failed, check again after 15 minutes (to accomodate re-runs after + ;; a release was done) + [(eq? #f result) + (or (not entry) ; actually missing => try now + (current-time . > . (+ last-time (* 15 60 R))))] + ;; known but without a size to verify, check again after two days + [(eq? #t result) + (current-time . > . (+ last-time (* 2 24 60 60 R)))] + ;; has a bad size, check again after an hour + [(not (= result size)) + (current-time . > . (+ last-time (* 60 60 R)))] + ;; otherwise check again after a month + [else (current-time . > . (+ last-time (* 30 24 60 60 R)))]) + (list url current-time (thunk)))) + (when new + ;; keep them sorted by time + (set! known-mirrors + `(,@(if entry (remq entry known-mirrors) known-mirrors) ,new)) + (call-with-output-file* known-mirrors-file #:exists 'truncate + (λ (outp) (for ([entry (in-list known-mirrors)]) + (fprintf outp "~s\n" entry))))) + (when (and new ; we computed a new value + (equal? result size) ; we had a good result + (not (equal? (caddr new) size))) ; but now it's bad + ;; this means that a good mirror just went bad => nag someone + (send-mail-message + "eli@barzilay.org" "*** Mirror Link Down ***" + ;; FIXME: if these messages are useful, change it to nag the mirror owner + ;; instead of a fixed email -- use (list (get-responsible-email)) + '("eli@barzilay.org") '() '() + `("A mirror link that used to be fine is now broken:" + ,(format " ~a" url) + ,(format "The expected size is ~a, we now have ~a" size (caddr new)) + "" + "This mirror will not be listed for now, until a re-poll finds it" + "working."))) + (if new (caddr new) result)) + +;; use the time when the file is loaded (no point for a finer granularity) +(define current-time (current-seconds)) + +(provide mirror-link) +(define (mirror-link url size get-responsible-email) + (and (or (not known-mirrors-file) ; no file => don't check, just use all + (let ([r (known-mirror-get url size (λ () (validate url size)) + get-responsible-email)]) + (or (eq? r #t) (equal? r size)))) + url)) + +(define (validate url size) + (eprintf " checking ~a\n" url) + ((case (string->symbol (cadr (or (regexp-match #rx"^([^:]*):" url) + (error 'mirror-link "bad url: ~a" url)))) + [(http https) verify-http] + [(ftp) verify-ftp] + [else (error 'mirror-link "unrecognizable url scheme: ~a\n" url)]) + url)) + +;; Verifiers return #f for failures, #t for dumb success (= didn't get size), +;; and a number for success with the remote file's size. +;; +;; Note: if `net/url' gets to deal with `ftp://' URLs, then only a +;; single verification function will be needed. But for that it will +;; need to mimic HEAD requests too. + +(define-syntax-rule (with-handlers+timeout name body ...) + (let ([cust (make-custodian)] [ch (make-channel)]) + (parameterize ([current-custodian cust]) + (thread (λ () (channel-put ch (with-handlers ([exn:fail? exn-message]) + body ...))))) + (begin0 (or (sync/timeout 20 ch) (format "~a connection timeout" name)) + (custodian-shutdown-all cust)))) + +(define (verify-http url) + (define (check-contents inp) + (define status (read-line inp)) + (define status* (regexp-match #rx"^HTTP/[0-9.]+ ([0-9]+)" status)) + (cond [(not status*) + (eprintf "WARNING: bad status line for ~a:\n ~s\n" url status) + #f] + [(not (regexp-match #rx"^2..$" (cadr status*))) + (eprintf "WARNING: bad status code for ~a: ~s\n" url (cadr status*)) + #f] + [else + (or (for/or ([line (in-lines inp)]) + (cond [(regexp-match #rx"^(?i:content-length: *([0-9]+) *)$" + line) + => (compose string->number cadr)] + [else #f])) + (begin (eprintf "WARNING: no `content-length' for ~a\n" url) + #t))])) + (define r + (with-handlers+timeout 'http + (call/input-url (string->url url) head-impure-port check-contents))) + (if (string? r) + (begin (eprintf "WARNING: failure getting http info for ~a (~a)\n" url r) + #f) + r)) + +(define (verify-ftp url) + (define-values [host port? path] + (apply values + (cdr (or (regexp-match #rx"^ftp://([^/:]+)(?::([0-9]+))?(/.*)$" url) + (error 'verify-ftp "bad ftp url: ~a" url))))) + (define port (or port? 21)) + (define r + (with-handlers+timeout 'ftp + (define c (ftp-establish-connection host port "anonymous" "anonymous@")) + (begin0 (ftp-directory-list c path) (ftp-close-connection c)))) + (cond [(not (and (list? r) (= 1 (length r)) (list? (car r)))) + (eprintf "WARNING: failure getting ftp info for ~a~a\n" + url (if (string? r) (format " (~a)" r) "")) + #f] + [(not (= 4 (length (car r)))) + (eprintf "WARNING: no size for: ~a\n" url) + #t] + [else (string->number (list-ref (car r) 3))])) diff --git a/new-racket-web/web/download/release-info.rkt b/new-racket-web/web/download/release-info.rkt new file mode 100644 index 0000000000..f8c5ad001c --- /dev/null +++ b/new-racket-web/web/download/release-info.rkt @@ -0,0 +1,60 @@ +#lang racket/base + +(require racket/system racket/port racket/match racket/runtime-path + racket/promise) + +(define-runtime-path THIS-GIT "../../../../../.git") + +(define (warn fmt . xs) + (eprintf "Warning: ~a\a\n" (apply format fmt xs)) + (flush-output (current-error-port)) + (sleep 1) + #f) + +(define git* + (lazy + (define exe (or (find-executable-path "git") + (warn "no `git' executable => no release info"))) + (define (try dir) (and dir (directory-exists? dir) dir)) + (define dir (and exe (or (ormap try (list (getenv "GIT_DIR") THIS-GIT)) + (warn "no git dir found => no release info\n (~a)" + "set $GIT_DIR to a racket repo .git dir")))) + (define nowhere (open-output-nowhere)) + (and dir (λ args (define o (open-output-string)) + (parameterize ([current-directory dir] + [current-output-port o] + [current-error-port nowhere]) + (and (apply system* exe "--no-pager" args) + (get-output-string o))))))) + +(provide get-version-tag-info) +(define (get-version-tag-info version) + (define git (force git*)) + (let/ec return + (unless git (return #f)) + (define (bad . args) (apply warn args) (return #f)) + (define (try fmt) + (let* ([tag (format fmt version)] + [text (and (git "cat-file" "-e" tag) + (git "cat-file" "tag" tag))]) + (and text (cons tag text)))) + (let* ([text (or (try "v~a") (try "old-v~a") + (bad "no git info for ~s (missing tag)" version))] + [tag (car text)] + [text (cdr text)] + [check (λ (x) (or x (bad "malformed git info for ~s" tag)))] + [sep (check (regexp-match-positions #rx"\n\n" text))] + [meta (map (λ (h) + (let ([m (check (regexp-match-positions #rx" " h))]) + (list (string->symbol (substring h 0 (caar m))) + (substring h (cdar m))))) + (regexp-split #rx"\n" (substring text 0 (caar sep))))] + [text (substring text (cdar sep))]) + (match meta + [`((object ,_) (type "commit") (tag ,_) + (tagger ,(regexp #rx"^(.* <.*>) ([0-9]+) ([-+]?[0-9][0-9])00$" + (list _ tagger date ofs)))) + ;; ignore the time offset (it probably depends on where the tag + ;; was made) + (list tagger (seconds->date (string->number date)) text)] + [_ (check #f)])))) diff --git a/new-racket-web/web/download/resources.rkt b/new-racket-web/web/download/resources.rkt new file mode 100644 index 0000000000..d087ca00f7 --- /dev/null +++ b/new-racket-web/web/download/resources.rkt @@ -0,0 +1,3 @@ +#lang meta/web + +(define+provide-context "download") diff --git a/new-racket-web/web/download/symlinks.rkt b/new-racket-web/web/download/symlinks.rkt new file mode 100644 index 0000000000..bc47d9f74f --- /dev/null +++ b/new-racket-web/web/download/symlinks.rkt @@ -0,0 +1,13 @@ +#lang meta/web + +(require "resources.rkt") + +(provide (all-defined-out)) + +(define (in-ftp . paths) + (string-join (cons "/var/ftp/pub/racket" paths) "/")) + +(define docs (symlink "/www/docs")) +(define installers (symlink (in-ftp "installers"))) +(define libs (symlink (in-ftp "libs/tags") "libs")) +(define stubs (symlink "/www/stubs")) diff --git a/new-racket-web/web/download/version.rkt b/new-racket-web/web/download/version.rkt new file mode 100644 index 0000000000..88e63e95df --- /dev/null +++ b/new-racket-web/web/download/version.rkt @@ -0,0 +1,7 @@ +#lang meta/web + +(require "resources.rkt" "data.rkt") + +(define version.txt + (plain (lazy (let ([v (release-version current-release)]) + (format "~s" `((recent ,v) (stable ,v))))))) diff --git a/new-racket-web/web/lang/reader.rkt b/new-racket-web/web/lang/reader.rkt new file mode 100644 index 0000000000..15b850f781 --- /dev/null +++ b/new-racket-web/web/lang/reader.rkt @@ -0,0 +1,18 @@ +#lang s-exp syntax/module-reader +meta/web/common/main + +;; Similar to `#lang scribble/html', but with a plain scribble reader +;; (not the inside one). + +#:read scribble:read +#:read-syntax scribble:read-syntax +#:info (web-reader-info) + +(require (prefix-in scribble: scribble/reader)) + +(define (web-reader-info) + (lambda (key defval default) + (case key + [(color-lexer) + (dynamic-require 'syntax-color/scribble-lexer 'scribble-lexer)] + [else (default key defval)]))) diff --git a/new-racket-web/web/minis/all.rkt b/new-racket-web/web/minis/all.rkt new file mode 100644 index 0000000000..f5c71bb862 --- /dev/null +++ b/new-racket-web/web/minis/all.rkt @@ -0,0 +1,3 @@ +#lang racket/base + +(require "lists.rkt" "bugs.rkt" "drracket.rkt") diff --git a/new-racket-web/web/minis/bugs.rkt b/new-racket-web/web/minis/bugs.rkt new file mode 100644 index 0000000000..37c4181bae --- /dev/null +++ b/new-racket-web/web/minis/bugs.rkt @@ -0,0 +1,265 @@ +#lang meta/web + +(define-context "bugs") + +(define planet-bugs "http://planet.racket-lang.org/trac/newticket") + +;; a starred option is the default +(define platform-options + '([* "...or choose" ""] + ["Windows 7/Vista, 32-bit" windows-7-32] + ["Windows 7/Vista, 64-bit" windows-7-64] + ["Windows Vista" windows-vista] + ["Windows XP" windows-xp] + ["Windows 2000" windows-2000] + ["Windows NT" windows-nt] + ["Windows 95/98/Me" windows-9x] + ["Mac OS X PowerPC (MacOS X)" mac-ppc-osx] + ["Mac OS X Intel (MacOS X)" mac-i386-osx] + ["Linux, Fedora/RedHat based" linux-fedora] + ["Linux, Ubuntu/Debian based" linux-ubuntu] + ["Linux, other distro" linux-other] + ["Sun Solaris" solaris] + ;; ["Sun Solaris 8" solaris-8] + ;; ["Sun Solaris, other version" solaris-other] + ["Other Unix" unix-other] + ;; ["Macintosh PowerPC (MacOS Classic)" mac-ppc-macos] + ;; ["Macintosh 68K" mac-68k] + ;; ["BeOS" beos] + ;; ["MzScheme kernel" mzkernel] + )) +(define severity-options + '([ "Critical" critical] + [* "Serious" serious] + [ "Non-critical" non-critical])) +(define bug-class-options + '([* "Software Bug" sw-bug] + [ "Documentation Bug" doc-bug] + [ "Change Request" change-request] + [ "Support" support])) + +(require (only-in "../www/download.rkt" download)) + +(define (cgi-link from . to) + (apply symlink (format "/www/cgi-bin/~a" from) to)) +(define bug-report-cgi (cgi-link "bug-report" "bug-report.cgi")) +(define bug-report-captcha (cgi-link "bug-report-captcha")) + +(provide captcha-file+num captcha-text) +(define captcha-file+num (make-parameter #f)) +(define captcha-text (make-parameter #f)) +(define captcha-text-file + @plain[#:file "captcha-text" #:newline #f (or (captcha-text) "")]) + +(define query (cgi-link "gnatsweb" "query")) + +(define (bugs-script) + @script/inline{ + var bugform = null; + var browser_platform = ""; + var params = new Array(); + var cookies = new Array(); + @|| + function initBugData() { + bugform = document.getElementById("BugForm"); + if (navigator.platform && navigator.platform != "") + browser_platform = navigator.platform; + if (navigator.cpuClass && navigator.cpuClass != "") + browser_platform += " / " + navigator.cpuClass; + if (navigator.userAgent && navigator.userAgent != "") + browser_platform += " / " + navigator.userAgent; + if (location.search.length > 0) { + var paramstrs = location.search.substring(1).split(@"/[;&]/"); + for (var i in paramstrs) { + var param = paramstrs[i].split(/=/); + if (param.length == 2) + params[param[0]] = unescape(param[1]).replace(/\+/g," "); + } + } + if (document.cookie.length > 0) { + var cookiestrs = document.cookie.split(@"/; */"); + for (var i in cookiestrs) { + var eql = cookiestrs[i].indexOf('='); + if (eql >= 0) + cookies[cookiestrs[i].substring(0,eql)] = + unescape(cookiestrs[i].substring(eql+1)); + } + } + if (params["v"]) bugform.version.value = params["v"]; + DoUserFields(RestoreUserField); + if (bugform.platform.value == "") { + if (bugform.platform_options.selectedIndex == 0) UpdatePlatformUser(); + else UpdatePlatformOptions(); + } + if (bugform.email.value == "") bugform.email.focus(); + else if (bugform.name.value == "") bugform.name.focus(); + else bugform.subject.focus(); + } + @|| + function SaveUserField(field, name) { + if (field.value != "") { + var d = new Date(); + d.setTime(d.getTime()+(365*24*60*60*1000)); + document.cookie = name + "=" + escape(field.value) + + "; expires="+ d.toGMTString() + + "; path=/"; + } + } + function RestoreUserField(field, name) { + if (field.value == "" && cookies[name]) field.value = cookies[name]; + } + function DoUserFields(op) { + op(bugform.email, "email"); + op(bugform.name, "name"); + op(bugform.version, "version"); + op(bugform.platform, "platform"); + op(bugform.platform_user, "platform_user"); + op(bugform.platform_options, "platform_options"); + } + @|| + function CheckSubmit() { + DoUserFields(SaveUserField); + if (bugform.email.value == "") { + window.alert("Please enter an Email"); + return false; + } + if (bugform.subject.value == "" && bugform.description.value == "") { + window.alert("Please enter a summary and/or a description" + + " of your bug"); + return false; + } + if (bugform.version.value == "") { + window.alert("Please enter your Racket version"); + return false; + } + return true; + } + @|| + var old_platform_user = null; + function UpdatePlatformUser() { + var newval = bugform.platform_user.value; + if (old_platform_user != newval) { + if (newval == "" && old_platform_user != browser_platform) { + newval = browser_platform; + bugform.platform_user.value = browser_platform; + bugform.platform_user.select(); + } + bugform.platform.value = newval; + bugform.platform_options.selectedIndex = 0; + bugform.platform_user.focus(); + old_platform_user = newval; + } + } + @|| + function UpdatePlatformOptions() { + var d = new Date(); + var opts = bugform.platform_options; + var newval = opts.options[opts.selectedIndex].value; + if (newval == "") { + bugform.platform.value = browser_platform; + bugform.platform_user.value = old_platform_user = browser_platform; + } else { + bugform.platform.value = newval; + bugform.platform_user.value = old_platform_user = "...or type"; + } + bugform.platform_user.select(); + opts.focus(); + }}) + +(provide (rename-out [index bug-reports])) +(define index + @page[#:title "Bug Reports" #:extra-headers bugs-script + #:extra-body-attrs `(onLoad: "initBugData();")]{ + @p[style: '("padding: 5px; color: #aa0000; background-color: #ffffee;" + " border: 1px solid; font-weight: bold;")]{ + If you can, please use the “Submit Bug Report” item in DrRacket's Help + menu. It works better than this page, because it helps you supply + precise information about your Racket installation and working + environment.} + @p{@strong{Note:} Bug reports for PLaneT packages are submitted on the + @a[href: planet-bugs]{PLaneT server}.} + @p{Before submitting a bug report, you may wish to: + @ul{@li{Consult the @-docs,} + @li{@download a newer Racket version if there is one (Racket + displays its version number on startup),} + @li{@a[href: (list query "/")]{Query existing bug reports}.}}} + @(define (mk-options opts) + (for/list ([s (in-list opts)]) + (if (eq? '* (car s)) + @option[selected: 'true value: (caddr s)]{@(cadr s)} + @option[value: (cadr s)]{@(car s)}))) + @(define (field name mode html-mode html-title . args) + (define title (and html-title (b html-title ":"))) + (define html-input + (case mode + [(text) + (let ([args (if (memq value: args) args (list* value: "" args))]) + (apply input type: 'text name: name args))] + [(textarea) + (apply textarea name: name style: "font-family: monospace;" args)] + [(options) + (if (null? args) + (error 'field "internal error (missing options)") + (apply select name: name + `(,@(cdr args) ,(mk-options (car args)))))] + [else (error 'field "internal error")])) + (case html-mode + [(line) (list (and title (list title " ")) html-input br)] + [(br) (list (and title (list title br)) html-input br br)] + [(tr) (tr (td title) (td html-input))] + [(as-is) (list (and title (list title " ")) html-input)] + [else (error 'field "internal error")])) + @form[action: bug-report-cgi method: 'post id: 'BugForm + ;; enctype: "multipart/form-data" + style: '("border: 2px solid #4444ff; padding: 6px;" + " background-color: #eeeeff;") + onsubmit: "return CheckSubmit();"]{ + @input[type: 'hidden name: 'cont value: thanks] + @field['name 'text 'br "Your name" size: 40] + @field['email 'text 'br "Your e-mail address" size: 40] + @field['subject 'text 'br "Summary of the problem" size: 60] + @table{ + @field['version 'text 'tr "Version" size: 14] + @; Note: if this is ever used to produce something that + @; help/bug-report.rkt can parse, then the following three + @; fields are actually a single editable drop-down called + @; "platform". + @tr{@td{@b{Platform:}} + @td{@field['platform_user 'text 'as-is #f value: #f size: 30 + onchange: "UpdatePlatformUser();" + onkeyup: "UpdatePlatformUser();"]@; + @|nbsp|@; + @field['platform_options 'options 'as-is #f platform-options + onchange: "UpdatePlatformOptions();"]@; + @input[type: 'hidden name: 'platform]}} + @field['severity 'options 'tr "Severity" severity-options] + @field['class 'options 'tr "Class" bug-class-options]} + @br + @field['description 'textarea 'br "Description of the problem" + rows: 12 cols: 70] + @field['how-to-repeat 'textarea 'br + '("If possible, please give a short sequence of steps to" + " reproduce the problem") + rows: 8 cols: 70] + @; An attachement requires a cgi script that can deal with input + @; that is in "multipart/form-data" format. + @; @field['file 'attachment 'line "Attachment" size: 20] + @(let* ([c (captcha-file+num)] + [n (and c (cdr c))] + [c (and c (img src: (cgi-link (car c)) align: "middle"))]) + (and c @field['captcha 'text 'line + @list{Please type @c and then a “@tt{*@n}”} + size: 10])) + @input[type: 'submit value: "Submit"]}}) + +(define thanks + @page[#:title "Thanks!" #:extra-headers bugs-script #:referrer values]{ + @p{@strong{Thanks!}} + @p{Your Racket bug report has been submitted.} + @p{You should receive an email confirming your report in a few minutes. + The confirmation will be sent to the email address you specified in + your report.} + @p{If you do not receive such confirmation, please report the problem to + @tt{@small{racket@"@"racket-lang.org}} + or to the Racket + @a[href: "http://lists.racket-lang.org/users/"]{mailing list}.}}) diff --git a/new-racket-web/web/minis/drracket.rkt b/new-racket-web/web/minis/drracket.rkt new file mode 100644 index 0000000000..b8fa71ed2a --- /dev/null +++ b/new-racket-web/web/minis/drracket.rkt @@ -0,0 +1,154 @@ +#lang meta/web + +(define-context "drracket") + +;; This just shows an ascii logo and redirects to the main page. Thanks +;; to Can Burak Cilingir for both the logo and the drracket.org domain +;; name. + +(define index + (page #:title "DrRacket" #:extra-headers (lazy headers) (center-div logo))) + +(require (only-in "../www/all.rkt" main)) + +(define (logo) + (define (text->lines text) + (cond [(null? text) '()] + [(null? (cdr text)) + (if (equal? "\n" (car text)) '() text)] + [(equal? "\n" (cadr text)) + (cons (car text) (text->lines (cddr text)))] + [else + (text->lines (cons (string-append (car text) (cadr text)) + (cddr text)))])) + (define (do-line chars colors) + (let loop ([chars (map (λ (c) (if (eq? #\space c) nbsp c)) + (string->list chars))] + [colors (string->list colors)]) + (let* ([class (car colors)] + [n (for/or ([color (in-list (cdr colors))] [i (in-naturals 1)]) + (and (not (equal? class color)) i))] + [block (if n (take chars n) chars)] + [block (if (eq? #\space class) + block (span class: (list "c" class) block))]) + (if n + (cons block (loop (drop chars n) (drop colors n))) + (list block))))) + (pre style: "font-family: monospace, fixed; font-weight: bold;" + (add-newlines (map do-line (text->lines char-matrix) + (text->lines color-matrix))))) + +(define (headers) + (list + (style/inline type: 'text/css + (add-newlines (map (λ (c) @list{.c@(car c) { + color: #@(cadr c); + background-color: #@(caddr c); + }}) + colors))) + (meta http-equiv: "refresh" + content: (list "2;URL=" (url-of main))))) + +(define char-matrix + @list|{ + 88XSS% + .888;@88@:88@XXS%tt + 8@Xt tX88X X88@XS%%t:. + 8%:.. ::t@88;88@XX%%t;:.. + @t. 8: :X@ %888XX%%t;:. : + 8 . . . 8 .S8%888@XS%%t;:. .S + @ .:8S888@XStt;;:. .; + X. . 8. :% ;888XS%tt;::. .t + @: . . . . 8% t@8X88@X%%;;::. :t + 8: . % .SX%88@XStt;::.. .;S + 8S . . S .%S8888XS%t;::.. .:tX + 8; . . . . S 8; t@8@X@XS%t;::.. .:;S + @@: . . . 8.8 8..%@8X8@XStt;:... .:;%@ + @X: . . . ;8 8XS88@X88%%;::.. ..;%@ + @@: . . . X;.% 888Xtt88St;::.. .:;tX + @8; . .X..X ;@St; .8;;:.. ..:;%@ + X8S. . . . 8 8 ;S8;;. 8X::. ...;t%@ + %@@%. . X ; %%% :. ;tX%;:. ..:;tS8 + tX8X;. . 8. .X .S@888@.:t%%@;: ..::t%S8 + :%X8Xt:. . .8 . 8 ;X8888X8:;%S@X t...::;tS@@ + ;%@88%t;:.. . ; S :S@8888XXXX%SX888::.::;t%X8 + .;tX@8@XS%ttt:t%X .tX@8888@XS%%SS@@88888.:;t%S8X + :t%X8888@@:8888 S@888888XXS%t;tSX88888@@t;t%S@8 + :;t%S@88t%%% ;8888@@@SS%%t;;:::;8@88@XX @%X@8 + . :;t%S:....8@@@XSSS%%tt;:::....S8@8XS X S@8 + :. .:@t%;:.8%%%%ttt;;:::.... ;SXS X 8S + t:. 88X@8@;;;;;;;:::... ..:.:8 X S8 + 8X@88X%::.::::... ...:::;tt;. .S8 + 88X:.:.........::::;;;tt%%SS@;8@ + 8SS%tt;;;;;;t;tttt%%SSX@88X + @@XXSSSSSSSSXX@@888@ + @@8888XS}|) + +(define colors + '([a "000" "00a"] + [b "000" "555"] + [c "000" "a00"] + [d "00a" "000"] + [e "00a" "555"] + [f "00a" "55f"] + [g "0aa" "555"] + [h "555" "000"] + [i "555" "00a"] + [j "555" "a00"] + [k "555" "aaa"] + [l "55f" "00a"] + [m "55f" "aaa"] + [n "a00" "000"] + [o "a00" "555"] + [p "a00" "f55"] + [q "a0a" "555"] + [r "a0a" "55f"] + [s "a0a" "a00"] + [t "a0a" "aaa"] + [u "a0a" "f55"] + [v "a50" "555"] + [w "a50" "a00"] + [x "a50" "aaa"] + [y "a50" "f55"] + [z "aaa" "555"] + [0 "aaa" "f55"] + [1 "aaa" "fff"] + [2 "f55" "a00"] + [3 "f55" "aaa"] + [4 "f5f" "f55"] + [5 "fff" "aaa"])) + +(define color-matrix + @list|{ + ifllll + qktx555155kflllllllg + 2pppppppp5111155fllllllllll + pppppppppppp511111kffllllllllllv + ppppppppppppppp1111115ffllllllllllla + jpppppppppppppppp0111111rfflllllllllliaa + ppppppppppppppppppp1111111ffllllllllllllaa + pppppppppppppppppppp11111115ffllllllllllliaa + ppppppppppppppppppppp11111111mfflllllllllllaaa + pppppppppppppppppppppp111111115fflllllllllllaaaa + 2ppppppppppppppppppppp31111111115flllllllllllaaaaa + pppppppppppppppppppppp115p1111111kfllllllllllaaaaa + 2ppppppppppppppppppppp111ppp1111155fllllllllllaaaaaa + 2pppppppppppppppppppp511ppppp1111555ifllllllllaaaaaa + 2ppppppppppppppppppp3114pppppp111555kllllllllaaaaaaa + 2pppppppppppppppppp3113pppppppp155555qfllllllaaaaaaa + 2ppppppppppppppppp0111pppppppppk155555illllliaaaaaaa + 22ppppppppppppppp3111ppppppppppp555kkkklillaaaaaaaaa + 222ppppppppppppp01113pppppppppppp5kkkkkklilaaaaaaaaa + 2222ppppppppppp01111pppppppppp222kkkkkkkqliaaaaaaaad + 2222pppppppppp1111ppppppppp222222kkkkkkkqlaaaaaaaa + 22222pppppppu1111yppppppp22222222okkkkkzkiiaaaaaad + 222222ppppy1511kppppp222222222222zkkzzzzziaaaaad + 22222222255555p22222222222222222skzzzzzzgiaaad + c2222225555k222222222222222222w2okzzzzgzgaad + cc222zkkkkqp222222222222222jjjwjzzzqzqqved + ccjqkkkkk222222222222222wjcccccjqzqqqqbh + ozzzzzj2j2j2j2j2w22jccccccccccqvqqbh + ojjjccccjcccccccccccccccccccjgbh + cccccccccccccccccccccccccnn + cccccccccccccccccnnn + nncnnnnn}|) diff --git a/new-racket-web/web/minis/lists.rkt b/new-racket-web/web/minis/lists.rkt new file mode 100644 index 0000000000..9de048d5db --- /dev/null +++ b/new-racket-web/web/minis/lists.rkt @@ -0,0 +1,168 @@ +#lang meta/web + +(provide mailing-lists-quick) + +(define-context "lists") + +(struct ML (name gmane-name google-name description)) + +(define MLs + (list (ML "users" "user" "racket-users" + @text{A discussion list for all things related to Racket. + Ask your questions here!}) + (ML "announce" "announce" #f + @text{A low-volume, moderated list for announcements, only. + @small{(These are posted on the @TT{users} list too, no need + to subscribe to both.)}}) + (ML "dev" "devel" #f + @text{A mailing list for Racket development. + @small{(For people who want to see how the sausages are made + — and help make them.)}}))) + +(define lists + @page[#:title "Mailing Lists" #:file "" #:part-of 'community + #:description + @'{Racket mailing lists for users, developers, announcements, and more.} + (define (list-cells what) (map (λ (r) (r what)) list-renderers)) + ]{ + @p{This is the Racket mailing list server. We have several public mailing + lists, some are listed below with several mirrors for each one. The + complete list of public mailing lists is available on + @a[href: "listinfo"]{this page}.} + @(define gap1 (tr (map (λ (_) @td{@div[style: "height: 1ex;"]{}}) MLs))) + @(define gap2 (tr (map (λ (_) @td{}) MLs))) + @(define (sec . text) + @list{@gap1 + @tr{@td[style: '("background-color: #dddddd; font-weight: bold;" + " padding: 0;") + colspan: (length MLs)]{@text}} + @gap2}) + @table[style: "width: 100%; margin: auto; text-align: center;" + frame: 'box rules: 'cols cellpadding: 5]{ + @tr[style: "border-bottom: 1px solid; background-color: #ccccff;"]{ + @(list-cells 'header-cell)} + @tr[valign: 'top style: "text-align: left;"]{@(list-cells 'description)} + @tr{@(list-cells 'main-page-cell)} + @tr{@(list-cells 'graph-cell)} + @sec{Subscription: enter your email here to subscribe to a mailing list} + @tr{@(list-cells 'subscribe-cell)} + @sec{Gmane Mirror} + @tr{@(list-cells 'gmane-cell)} + @sec{Archive at mail-archive.com} + @tr{@(list-cells 'mail-archive-cell)} + @sec{Google group mirror} + @tr{@(list-cells 'google-cell)}}}) + +(define (list-renderer ml) + (define name (ML-name ml)) + (define at-domain "@racket-lang.org") + (define email (list name at-domain)) + (define description (ML-description ml)) + (define gmane + (let ([gm (ML-gmane-name ml)]) + (and gm @list{gmane.comp.lang.racket.@(ML-gmane-name ml)}))) + (define (gmane-link base . body) + (unless gmane + (error 'list-renderer "internal error: no gmane info for ~a" name)) + (let* ([path (if (pair? base) (list "/" (cdr base) "/") "/")] + [base (if (pair? base) (car base) base)] + [pfx (if (regexp-match? #rx"://" base) base (list "http://" base))]) + @a[href: (list pfx ".gmane.org" path gmane)]{@body})) + (define (mail-archive-link suffix . body) + @a[href: (list "http://www.mail-archive.com/" email "/" suffix)]{@body}) + (define google-groups-url + (let ([g (ML-google-name ml)]) + (and g (list "http://groups.google.com/group/" g "/")))) + (define ((mk-form make) url #:method [method 'get] . body) + (make @form[action: url method: method + style: "display: inline; clear: none;"]{ + @div{@body}})) + (define (mk-subscribe mk) + @(mk-form mk)[(list (url-of lists #t) name "/subscribe") #:method 'post]{ + @input[type: 'text name: 'email size: 20 value: "" + placeholder: "Email to Subscribe" + title: @list{Enter your email to subscribe + to the "@name" mailing list.}]}) + (define form-cell (mk-form td)) + (λ (what) + (case what + [(header-cell) + @th[style: "width: 33%;"]{ + @; the mixed styles will help against some spam harvesting too + @span[style: '("font-size: x-large;" + " font-family: monospace; font-weight: bold;")]{ + @TT{@name}@; + @span[style: "font-size: small;"]{@at-domain}}}] + [(description) @td{@description}] + [(main-page-cell) + @td{@a[href: (list name "/")]{@big{@b{@TT{@name}}} page} + @bull + @a[href: (list name "/archive/")]{archive}}] + [(graph-cell) + @td{@img[src: (list "http://gmane.org/plot-rate.php?group=" gmane) + style: "width: 80%;"]}] + [(subscribe-cell) (mk-subscribe td)] + [(google-cell) + (if google-groups-url + @form-cell[(list google-groups-url "search")]{ + @a[href: google-groups-url]{ + @(string-titlecase + (regexp-replace* #rx"-" (ML-google-name ml) " "))} + @br + @span[style: "white-space: nowrap;"]{ + Search: @input[type: 'text name: 'q value: "" size: 20].}} + @td{@small{—none—}})] + [(mail-archive-cell) + @form-cell["http://www.mail-archive.com/search"]{ + @input[type: 'hidden name: 'l value: email] + @mail-archive-link["info.html"]{Archive} + @bull + @mail-archive-link[""]{Browse} + @bull + @mail-archive-link["maillist.xml"]{RSS} + @br + @span[style: "white-space: nowrap;"]{ + Search: @input[type: 'text name: 'q value: "" size: 20].}}] + [(gmane-cell) + @form-cell["http://search.gmane.org/"]{ + @input[type: 'hidden name: 'group value: gmane] + @gmane-link["dir"]{@TT{@gmane}} + @br + @gmane-link["news"]{threaded} + @bull + @gmane-link["blog"]{blog} + @bull + @gmane-link["nntp://news"]{newsgroup} + @br + Feed: + @gmane-link['("rss" "messages/complete")]{messages} + @bull + @gmane-link['("rss" "topics/complete")]{topics} + @br + @;Excerpt feed: + @;@gmane-link['("rss" "messages/excerpts")]{messages} + @;@bull + @;@gmane-link['("rss" "topics/excerpts")]{topics} + @;@br + @span[style: "white-space: nowrap;"]{ + Search: @input[type: 'text name: 'query value: "" size: 20].}}] + [(quick) + @text{ + @big{@TT{@b{@name}}@small{@tt{@at-domain}}} + @div[style: "margin-left: 2em;"]{ + @description + @br + @div[style: "float: right;"]{@(mk-subscribe values)} + [@a[href: (list (url-of lists) name "/")]{list page}, + @gmane-link["dir"]{gmane mirror}, + @mail-archive-link[""]{mail-archive}@; + @(and google-groups-url + @text{, @a[href: google-groups-url]{google group mirror}})]}}] + [else (error 'list-cell "internal error")]))) + +(define list-renderers (map list-renderer MLs)) + +(define (mailing-lists-quick) + @text{@(apply parlist @strong{Mailing Lists} + (map (λ (r) (r 'quick)) list-renderers)) + @p{See the @lists{mailing list server} for more details.}}) diff --git a/new-racket-web/web/stubs/all.rkt b/new-racket-web/web/stubs/all.rkt new file mode 100644 index 0000000000..ee25c0ca8c --- /dev/null +++ b/new-racket-web/web/stubs/all.rkt @@ -0,0 +1,9 @@ +#lang racket/base + +(provide documentation planet) + +(require "docs.rkt" ; for the doc tweaking script + "planet.rkt" "blog.rkt" ; these need to be copied to the service + "pre.rkt" "git.rkt" ; / these are used on the + "mailman.rkt" "dirlist.rkt" ; \ server directly + "wiki.rkt") diff --git a/new-racket-web/web/stubs/blog.rkt b/new-racket-web/web/stubs/blog.rkt new file mode 100644 index 0000000000..99e7ca49ec --- /dev/null +++ b/new-racket-web/web/stubs/blog.rkt @@ -0,0 +1,1084 @@ +#lang meta/web + +(require (prefix-in www: (only-in "../www/resources.rkt" the-resources)) + racket/port) + +(define-context "stubs/blog" #:resources www:the-resources) + +(define racket-css + @text{ + @;{ + Instead of hiding the blogger navbar (and eliminate what it is used for), + just make it appear below the Racket bar, and make it transparent. The + next one is supposed to make it get back to being opaque when the mouse + hovers on it, but it doesn't seem to work on IE. + ;} + #navbar-iframe { + position: absolute; + top: 160px; right: 0px; + opacity: 0.33; filter: alpha(opacity=33); + } + #navbar-iframe:hover { + opacity: 1.0; filter: alpha(opacity=100); + } + /* --- navbar styles --- */ + @navbar-style + }) + +(define (get-resource-text . args) + (let ([str (xml->string (apply www:the-resources args))]) + ;; due to some obscure xml issue the `nbsp' entity is not recognized + ;; in blogger pages + (regexp-replace* #rx" " str "\\ "))) + +(define (racket-navbar) (get-resource-text 'navbar 'community)) +(define (racket-favicon) (get-resource-text 'favicon-headers)) + +(provide blog) +(define blog + @plain[#:file "" #:referrer (λ (u) @a[href: u]{Blog})]{ +@; This is the blogger style template file, with one hole for the CSS and one +@; for the navbar, and a few more tweaks (first by soegaard and then by eli). +@; + + + + + +<data:blog.pageTitle/> + + + + + + + + + + + + + + + +*/ + +/* Use this with templates/template-twocol.html */ + +body { + background: $bgcolor; + margin: 0; + color: $textcolor; + // ELI: I don't know why this was here, it was butchering the whole layout + // font: x-small Georgia Serif; + // font-size/* */:/**/small; + // font-size: /**/small; + // text-align: center; + } +a:link { + color: $linkcolor; + text-decoration: none; +} +a:visited { + color: $visitedlinkcolor; + text-decoration: none; +} +a:hover { + color: $titlecolor; + text-decoration: underline; +} +a img { + border-width: 0; +} + +/* Header +----------------------------------------------- */ + +/* ELI: seems like this has no effect on anything */ + +#header-wrapper { + width: 800px; /* this used to be 660 [soegaard] */ + margin: 0 auto 10px; + border: 1px solid $bordercolor; +} + +#header-inner { + background-position: center; + margin-left: auto; + margin-right: auto; +} + +#header { + margin: 5px; + border: 1px solid $bordercolor; + text-align: center; + color: $pagetitlecolor; +} + +#header h1 { + margin: 5px 5px 0; + padding:15px 20px .25em; + line-height: 1.2em; + text-transform: uppercase; + letter-spacing: .2em; + font: $pagetitlefont; +} + +#header a { + color: $pagetitlecolor; + text-decoration: none; +} + +#header a:hover { + color: $pagetitlecolor; +} + +#header .description { + margin: 0 5px 5px; + padding: 0 20px 15px; + max-width: 840px; /* this used to be 700 [soegaard] */ + text-transform: uppercase; + letter-spacing: .2em; + line-height: 1.4em; + font: $descriptionfont; + color: $descriptioncolor; +} + +#header img { + margin-left: auto; + margin-right: auto; +} + +/* Wrappers +----------------------------------------------- */ + +/* The whole main area */ +#outer-wrapper { + // ELI: + margin-top: 0; + margin-bottom: 0; + @page-sizes + padding: 10px; + text-align: left; + font: $bodyfont; + } + +/* The text area */ +#main-wrapper { + width: 63%; /* used to be 410px [soegaard,ELI] */ + float: left; + word-wrap: break-word; /* fix for long text breaking sidebar float in IE */ + overflow: hidden; /* fix for long non-text content breaking IE sidebar float */ + } + +/* Sidebar stuff */ +#sidebar-wrapper { + width: 33%; /* used to be 220px [ELI] */ + font-size: 87.5%; /* ELI */ + float: right; + word-wrap: break-word; /* fix for long text breaking sidebar float in IE */ + overflow: hidden; /* fix for long non-text content breaking IE sidebar float */ +} + +/* Headings +----------------------------------------------- */ + +h2 { + margin: 1.5em 0 .75em; + font: $headerfont; + line-height: 1.4em; + text-transform: uppercase; + letter-spacing: .2em; + color: $sidebarcolor; +} + + +/* Posts +----------------------------------------------- */ +h2.date-header { + margin: 1.5em 0 .5em; +} + +.post { + margin: .5em 0 1.5em; + border-bottom: 1px dotted $bordercolor; + padding-bottom: 1.5em; +} +.post h3 { + margin: .25em 0 0; + padding: 0 0 4px; + font-size: 140%; + font-weight: normal; + line-height: 1.4em; + color: $titlecolor; +} + +.post h3 a, .post h3 a:visited, .post h3 strong { + display: block; + text-decoration: none; + color: $titlecolor; + font-weight: normal; +} + +.post h3 strong, .post h3 a:hover { + color: $textcolor; +} + +.post p { + margin: 0 0 .75em; + line-height: 1.6em; +} + +.post-footer { + margin: .75em 0; + color: $sidebarcolor; + text-transform: uppercase; + letter-spacing: .1em; + font: $postfooterfont; + line-height: 1.4em; +} + +.comment-link { + margin-left: .6em; +} +.post img { + padding: 4px; + border: 1px solid $bordercolor; +} +.post blockquote { + margin: 1em 20px; +} +.post blockquote p { + margin: .75em 0; +} + +.post-header-line-1 { /* add some vertical space after author [soegaard] */ + margin-bottom: .6em; + font-style: italic; +} + +/* Comments +----------------------------------------------- */ +#comments h4 { + margin: 1em 0; + font-weight: bold; + line-height: 1.4em; + text-transform: uppercase; + letter-spacing: .2em; + color: $sidebarcolor; +} + +#comments-block { + margin: 1em 0 1.5em; + line-height: 1.6em; +} +#comments-block .comment-author { + margin: .5em 0; +} +#comments-block .comment-body { + margin: .25em 0 0; +} +#comments-block .comment-footer { + margin: -.25em 0 2em; + line-height: 1.4em; + text-transform: uppercase; + letter-spacing: .1em; +} +#comments-block .comment-body p { + margin: 0 0 .75em; +} +.deleted-comment { + font-style: italic; + color: gray; +} + +#blog-pager-newer-link { + float: left; +} + +#blog-pager-older-link { + float: right; +} + +#blog-pager { + text-align: center; +} + +.feed-links { + clear: both; + line-height: 2.5em; +} + +/* Sidebar Content +----------------------------------------------- */ +.sidebar { + color: $sidebartextcolor; + line-height: 1.5em; +} + +.sidebar ul { + list-style: none; + margin: 0 0 0; + padding: 0 0 0; +} +.sidebar li { + margin: 0; + padding: 0 0 .25em 15px; + text-indent: -15px; + line-height: 1.5em; +} + +.sidebar .widget, .main .widget { + border-bottom: 1px dotted $bordercolor; + margin: 0 0 1.5em; + padding: 0 0 1.5em; +} + +.main .Blog { + border-bottom-width: 0; +} + + +/* Profile +----------------------------------------------- */ +.profile-img { + float: left; + margin: 0 5px 5px 0; + padding: 4px; + border: 1px solid $bordercolor; +} + +.profile-data { + margin: 0; + text-transform: uppercase; + letter-spacing: .1em; + font: $postfooterfont; + color: $sidebarcolor; + font-weight: bold; + line-height: 1.6em; +} + +.profile-datablock { + margin: .5em 0 .5em; +} + +.profile-textblock { + margin: 0.5em 0; + line-height: 1.6em; +} + +.profile-link { + font: $postfooterfont; + text-transform: uppercase; + letter-spacing: .1em; +} + +/* Colors for highlighting via http://www.scheme.dk/paste/ */ + +.scheme { color: brown; margin: 4pt; } /* background punctuation */ +.scheme .keyword { color: rgb(68,0,203); font-weight: bold; } +.scheme .builtin { color: navy; } +.scheme .variable { color: black; } +.scheme .global { color: purple; } +.scheme .selfeval { color: green; } +.scheme .comment { color: teal; } + +/* Footer +----------------------------------------------- */ +#footer { + width: 660px; + clear: both; + margin: 0 auto; + padding-top: 15px; + line-height: 1.6em; + text-transform: uppercase; + letter-spacing: .1em; + text-align: center; +} + +/** Page structure tweaks for layout editor wireframe */ +body#layout #header { + margin-left: 0px; + margin-right: 0px; +} + +/*** Racket CSS begin ***/ +@racket-css +/*** Racket CSS end ***/ + +]]> + +@racket-favicon + + + + + + +@racket-navbar + + +
+ + + + +
+ +
+ +
+ +
+ + + +
+ + + + + + + + + + + +
+
+ + + + + + + + + + + +

+ +
+ + + +
+ + +
+ +
+ + +

+ + + + + + + + + +

+ + +
+ +
+

+
+
+ +
+ + + +
+
+ +
+
+
+
+
+
+
+
+ + + +
+ +

+

+ +
+