Copied the web directory to work on it locally.

This commit is contained in:
Eli Barzilay 2013-09-28 14:24:28 -04:00 committed by Matthew Flatt
parent 1736e367ef
commit 66c53fbd5c
57 changed files with 10086 additions and 0 deletions

47
new-racket-web/web/README Normal file
View File

@ -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 <dir>' 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 <some-file>'. 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.

View File

@ -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)

83
new-racket-web/web/build.rkt Executable file
View File

@ -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)) string<?))
(when (pair? paths)
(if (or (not warn?)
(begin (printf "Directory not empty, these will be deleted: ~a.\n"
(string-join paths ", "))
(printf "Continue? ") (flush-output)
(regexp-match? #rx" *[yY]" (read-line))))
(for-each delete-directory/files paths)
(raise-user-error 'build "Aborting."))))
(printf "Building ~a content...\n" build-mode)
(parameterize ([url-roots (and (eq? 'web build-mode) sites)])
(for ([extra (in-list extra-files)])
(if (file-exists? extra)
(dynamic-require `(file ,extra) #f)
(printf " ignoring missing extra file: ~a\n" extra)))
(parameterize ([current-directory output-dir])
(render-all)
(when distribute?
(printf "Distributing...\n")
(distribute (distributions)))))
(printf "Done.\n")

View File

@ -0,0 +1,29 @@
#lang racket/base
(require racket/system racket/list racket/promise)
(define rsync-exe (lazy (or (find-executable-path "rsync")
(error 'distribute "couldn't find `rsync'"))))
(define (rsync . args)
(unless (apply system* (force rsync-exe) args)
(error 'distribute "errors when running: rsync with ~s" args)))
(define (flatten-path path)
(define m (regexp-match #rx"^(.*?)/\\*(/.*|$)$" path))
(if m
(append-map
flatten-path
(sort (map (λ(p) (string-append
(cadr m) "/" (path-element->string p) (caddr m)))
(directory-list (cadr m)))
string<?))
(list path)))
(provide distribute)
;; see "../config.rkt" for a description of the specs
(define (distribute specs)
(for ([s (in-list specs)])
(let ([srcs (append-map flatten-path (cdr s))] [tgt (car s)])
(printf " to ~a\n" tgt)
(apply rsync "-aqz" "-e" "ssh" "--delete" `(,@srcs ,tgt)))))

View File

@ -0,0 +1,132 @@
#lang at-exp racket/base
(require scribble/html)
;; list of a header paragraphs and sub paragraphs (don't use `p' since it looks
;; like they should not be nested)
(provide parlist)
(define (parlist first . rest)
(list (div class: 'parlisttitle first)
(map (λ (p) (div class: 'parlistitem p)) rest)))
;; a div that is centered, but the text is still left-justified
(provide center-div)
(define (center-div . text)
(let-values ([(attrs body) (split-attributes+body text)])
(apply div align: 'center
(append attrs
(list (div align: 'left style: "display: inline-block;"
body))))))
;; a grayish tt text
(provide TT)
(define (TT . xs)
@tt[style: "background-color: #d8d8e8;"]{@xs})
(provide PRE)
(define (PRE . xs)
@pre[style: "background-color: #d8d8e8;"]{@xs})
;; some tags with convenient separators
(provide make-separated-tag (rename-out [the-separator ~])
p* ul* ol* dl*)
(struct separator ())
(define the-separator (separator))
(define (split-list-by-separator list)
;; The idea is to drop all whitespace around the separator, and then drop the
;; common leading all-space prefixes in each chunk, so the separators are
;; effectively ignored for indentation in the output. This is too much for
;; html output (leaving the whitespaces in what this is used for is
;; harmless), but it might be useful for some future application.
(define (drop-ws list left?)
(if (and (pair? list) (string? (car list)))
(let ([str (regexp-replace (if left? #rx"^[ \t\r\n]+" #rx"[ \t\r\n]+$")
(car list) "")])
(if (equal? "" str) (drop-ws (cdr list) left?) (cons str (cdr list))))
list))
(define (drop-indentation/reverse orig-text)
(define N #f)
(if (null? orig-text)
orig-text
(let loop ([text orig-text] [r '()])
(cond [(null? (cdr text))
(if N (cons (car text) r) (reverse orig-text))]
[(not (equal? "\n" (cadr text)))
(loop (cdr text) (cons (car text) r))]
[(not (and (string? (car text))
(regexp-match? #rx"^ +$" (car text))))
(reverse orig-text)]
[else (let ([len (string-length (cadr text))])
(set! N (if N (min len N) len))
(loop (cddr text)
(list* (λ () (make-string (- len N) #\space))
"\n" r)))]))))
(let loop ([list (drop-ws list #t)] [cur '()] [r '()])
(define (get-r) (cons (drop-indentation/reverse (drop-ws cur #f)) r))
(cond [(null? list) (reverse (get-r))]
[(separator? (car list)) (loop (drop-ws (cdr list) #t) '() (get-r))]
[else (loop (cdr list) (cons (car list) cur) r)])))
(define ((make-separated-tag wrapper #:newlines? [nls? #t] . tags) . body)
(let* ([chunks (split-list-by-separator body)]
[chunks (if (null? (car chunks)) (cdr chunks) chunks)]
[body (for/list ([text (in-list chunks)]
[tag (in-cycle (in-list tags))])
(apply tag text))]
[body (if nls? (add-newlines body) body)])
(wrapper body)))
(define p* (make-separated-tag values p))
(define ul* (make-separated-tag ul li))
(define ol* (make-separated-tag ol li))
(define dl* (make-separated-tag dl dt dd))
;; conditional display on screen or print
(provide printonly screenonly)
(define (printonly . body) (apply div class: 'printonly body))
(define (screenonly . body) (apply div class: 'screenonly body))
;; (sections) defines a `section' function and spits out a (delayed) table of
;; contents for all its future uses in the page.
(provide sections)
(require (for-syntax racket/base))
(define (section->label 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 #'())]))

View File

@ -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 <dir>"))
(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))

View File

@ -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)))

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,7 @@
#lang racket/base
(require scribble/html/lang
"layout.rkt" "resources.rkt" "extras.rkt" "links.rkt" "utils.rkt")
(provide (all-from-out scribble/html/lang
"layout.rkt" "resources.rkt" "extras.rkt" "links.rkt"
"utils.rkt"))

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

View File

@ -0,0 +1,155 @@
#lang at-exp racket/base
(require scribble/html)
;; These are some resources that are shared across different toplevel
;; sites. They could be included from a single place, but then when one
;; machine crashes the rest won't work right. (Note: do not add
;; resources that are specific to only one site here, do so in the
;; site's "resources.rkt" file)
(require "utils.rkt")
(provide make-resource-files
navbar-style page-sizes font-family) ; needed for the blog template
;; robots is passed as #:robots in define-context, and htaccess as #:htaccess;
;; they can be #t (the default) for the standard ones, or some text that gets
;; added to the standard contents -- which is the user-agent line and the
;; ErrorDocument respectively.
(define (make-resource-files page dir robots htaccess)
(define (copyfile file [target file])
(copyfile-resource (in-here file) (web-path dir target)))
(define (writefile file . contents)
(resource (web-path dir file) (file-writer output (list contents "\n"))))
`([logo ,(copyfile "logo.png")]
[icon ,(copyfile "plticon.ico")]
[style ,(writefile "plt.css" racket-style)]
;; the following resources are not used directly, so their names are
;; irrelevant
[verification:google
@,writefile["google5b2dc47c0b1b15cb.html"]{
google-site-verification: google5b2dc47c0b1b15cb.html}]
[verification:bing
@,writefile["BingSiteAuth.xml"]{
<?xml version="1.0"?>
<users><user>140BE58EEC31CB97382E1016E21C405A</user></users>}]
[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;
}
})

View File

@ -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))

View File

@ -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"])))

View File

@ -0,0 +1,3 @@
#lang racket/base
(require "index.rkt" "version.rkt")

View File

@ -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-" ; <package>-<version>-
"(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)] [<? (cdar fns)] [x1 (get i1)] [x2 (get i2)])
(or (<? x1 x2) (and (equal? x1 x2) (loop (cdr fns)))))))))))
(define-lazy all-releases ; still sorted from newest to oldest
(remove-duplicates (map installer-release all-installers)))
(define-lazy all-packages ; also sorted
(remove-duplicates (map installer-package all-installers)))
(define-lazy current-release (car all-releases))
(define package->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)]))

View File

@ -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<order.length@";" i++)
if (str.search(order[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@";" i<len@";" i++)
tmps[i]=[opts[i].text,opts[i].value,i];
tmps.sort(isBetter);
for (var i=0@";" i<len@";" i++) {
opts[i].text = tmps[i][0];
opts[i].value = tmps[i][1];
}
opts.selectedIndex = 0;
})();
@||})

View File

@ -0,0 +1,21 @@
#lang meta/web
(require "resources.rkt" "symlinks.rkt" "../www/download.rkt")
(provide index)
(define index
@page[#:link-title "Downloads" #:part-of 'download
#:description
@'{Download Racket, a modern dialect of Lisp/Scheme. @;
Available for Windows, Mac, Linux, and other Unix platforms. @;
Includes the DrRacket IDE.}]{
@div[style: "float: right;"]{@download-button}
Use these links to browse the download directories directly:
@ul{@li{Current @a[href: `(,installers "/recent")]{installers}
(or @a[href: installers]{all versions}).}
@li{Current documentation in
@a[href: `(,docs "/recent/html")]{HTML} and in
@a[href: `(,docs "/recent/pdf")]{PDF}
(or @a[href: docs]{all versions}).}
@li{Binary @a[href: libs]{libraries} mainly for GRacket
(installed during the build process).}}})

View File

@ -0,0 +1,79 @@
#lang meta/web
(require "resources.rkt" "data.rkt" "mirror-link.rkt")
(define (render-installer-page installer)
(define path (installer-path installer))
(define file (installer-file installer))
(define html-file (string-append (regexp-replace* #rx"\\." file "-") ".html"))
(define release (installer-release installer))
(define version (release-version release))
(define date (release-date-string release))
(define package (package->name (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))))))

View File

@ -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

View File

@ -0,0 +1,177 @@
#lang racket/base
#|
This file polls mirror links: (mirror-link <url> <size>) 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))]))

View File

@ -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)]))))

View File

@ -0,0 +1,3 @@
#lang meta/web
(define+provide-context "download")

View File

@ -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"))

View File

@ -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)))))))

View File

@ -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)])))

View File

@ -0,0 +1,3 @@
#lang racket/base
(require "lists.rkt" "bugs.rkt" "drracket.rkt")

View File

@ -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}.}})

View File

@ -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}|)

View File

@ -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.}})

View File

@ -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")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
#lang meta/web
;; This stub is to generate fancy directory listings with the Racket style
(require (prefix-in dnld: (only-in "../download/resources.rkt" the-resources)))
(define-context "stubs/dirlist" #:resources dnld:the-resources)
(define header+footer
(lazy (regexp-split #rx"{{{BODY}}}"
(xml->string @page[#:id 'browse-downloads
#:html-only #t
#:part-of 'download
"{{{BODY}}}"]))))
(define header
@plain[#:file "header.html" #:newline #f (car (force header+footer))])
(define footer
@plain[#:file "footer.html" #:newline #f (cadr (force header+footer))])

View File

@ -0,0 +1,11 @@
#lang meta/web
(require (prefix-in www: (only-in "../www/resources.rkt" the-resources)))
(define-context "stubs/docs" #:resources www:the-resources)
(provide documentation)
(define documentation
;; This is a stub page to get the header for tweaked doc pages
(page #:file "" #:link-title "Documentation" #:window-title "{{{TITLE}}}"
"\n{{{BODY}}}\n"))

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,633 @@
#lang meta/web
(define-context "stubs/mailman")
(define (MM . tag) @literal{<MM-@|tag|>})
(define (MM/ . tag) @literal{</MM-@|tag|>})
(define (MMform name . body)
(list @MM{@(and name (list name "-"))Form-Start} body @MM{Form-End}))
(define style-header
@style/inline{
h1 {
text-align: center;
background-color: #99ccff;
padding: 0.5em;
font-size: 150%;
font-weight: bold;
}
h2 {
text-align: left;
padding: 0.1em 0.5em;
background-color: #ffddaa;
font-size: 120%;
font-weight: bold;
}
.subp {
margin: 0.5ex 0 0.5ex 1em;
}})
(define (subp . body) (apply div class: 'subp body))
(define (graytd . body) (apply td bgcolor: "#dddddd" body))
;; this should move to common
(define HOLE (literal "<<<HOLE>>>"))
(define (split-template template #:encoder [encoder values] . files)
(define p
;; use `xml->string' only if the input is not a string, since `page%%'
;; below hacks up a string, so this avoids doing double-html encoding (this
;; won't be necessary if `page%%' is done properly)
(lazy (let* ([t (force template)]
[t (if (string? t) t (xml->string t))]
[t (regexp-split #rx"<<<HOLE>>>" t)])
(unless (= (length t) (length files))
(error 'split-template "got ~e parts, but expected ~e"
(length t) (length files)))
(map encoder t))))
(for/list ([f (in-list files)] [i (in-naturals)])
(plain #:file f #:newline #f (list-ref (force p) i))))
(define generic-templates
(split-template @page[#:html-only #t #:title HOLE
#:extra-headers style-header #:part-of 'community
HOLE]
"header1.html" "header2.html" "footer.html"))
(define (make-listinfo archive?)
@page[#:title @list{Mailing lists: @MM{List-Name}} #:part-of 'community
#:extra-headers style-header
#:file (if archive? "listinfo+archive.html" "listinfo.html")]{
@; --------------------
@comment{@||
Based on the Mailman file "listinfo.html", revision: 5865
Modified to fit the racket pages, add a mail-archive searchbox for
public lists.
@||}
@; --------------------
@h1{@MM{List-Name}: @MM{List-Description}}
@; --------------------
@h2{About the @MM{List-Name} list
@span[style: '("float: right; font-weight: normal; font-size: 80%;"
" margin-top: 4px;")]{
@MMform['Lang]{@MM{displang-box} @MM{list-langs}}}}
@subp{@MM{List-Info}}
@subp{To post a message to the list, send email to
@a[href: @list{mailto:@MM{Posting-Addr}}]{@MM{Posting-Addr}}.
You can subscribe to the list or change your existing subscription
options in the sections below.}
@subp{To see the collection of prior postings to the list, visit the
@MM{Archive}@MM{List-Name} archives@MM/{Archive}.
@MM{Restricted-List-Message}}
@when[archive?]{
@; This is the mail-archive search box
@form[action: "http://www.mail-archive.com/search" method: 'get]{@subp{
@input[type: 'hidden name: 'l value: @MM{Posting-Addr}]
Archives are also available at
@a[href: @list{http://www.mail-archive.com/@MM{Posting-Addr}/}]{
mail-archive.com},
search it here:
@input[type: 'text name: 'q value: "" size: 16]}
@subp{(@a[href: "/"]{More information} on other ways to use this list
and other public Racket lists.)}}}
@; --------------------
@h2{@a[name: 'subscribers]{@MM{List-Name} subscribers}}
@subp{@MMform['Options]{@MM{Editing-Options}}}
@; not needed: @subp{@MMform['Roster]{@MM{Roster-Option}}}
@; --------------------
@h2{Subscribing to @MM{List-Name}}
@subp{Subscribe to @MM{List-Name} by filling out the following form.
@MM{List-Subscription-Msg}}
@subp{
@MMform['Subscribe]{
@table[cellspacing: 2 cellpadding: 2 width: "90%" align: 'center]{
@tr{@graytd{Your email address:}
@td{@MM{Subscribe-Box}}
@td{@nbsp}}
@tr{@graytd{Your name (optional):}
@td{@MM{fullname-box}}
@td{@nbsp}}
@tr{@td[colspan: 3 style: "font-size: 82.5%;"]{
@p{You may enter a privacy password below. This provides
only mild security, but should prevent others from messing
with your subscription. @b{Do not use a valuable password}
as it will occasionally be emailed back to you in
cleartext.}
@p{If you choose not to enter a password, one will be
automatically generated for you, and it will be sent to you
once you've confirmed your subscription. You can always
request a mail-back of your password when you edit your
personal options.}
@MM{Reminder}}}
@tr{@graytd{Pick a password:}
@td{@MM{New-Password-Box}}
@td{@nbsp}}
@tr{@graytd{Reenter password to confirm:}
@td{@MM{Confirm-Password}}
@td{@nbsp}}
@tr{@graytd{Which language do you prefer to display your messages?}
@td{@MM{list-langs}}
@td{@nbsp}}
@MM{digest-question-start}
@tr{@td{Would you like to receive list mail batched in a daily
digest?}
@td{@MM{Undigest-Radio-Button} No
@MM{Digest-Radio-Button} Yes}
@td{@nbsp}}
@MM{digest-question-end}
@tr{@td[colspan: 3]{
@p[style: "text-align: center;"]{
@MM{Subscribe-Button}}}}}}}
@; --------------------
@h2{@nbsp}
@MM{Mailman-Footer}})
(define listinfos (map make-listinfo '(#t #f)))
(define subscribe
@page[#:title @list{@MM{List-Name} Subscription results} #:part-of 'community
#:extra-headers style-header]{
@; --------------------
@comment{@||
Based on the Mailman file "subscribe.html", revision: 3550
Modified to fit the racket pages
@||}
@; --------------------
@h1{@MM{List-Name} Subscription results}
@subp{@MM{Results}}
@MM{Mailman-Footer}})
(define options
@page[#:title @list{@MM{Presentable-User} membership configuration
for @MM{List-Name}}
#:part-of 'community
#:extra-headers style-header]{
@; --------------------
@comment{@||
Based on the Mailman file "options.html" (no revision specified)
Modified to fit the racket pages
@||}
@; --------------------
@h1{@MM{List-Name} mailing list membership configuration for
@MM{Presentable-User}}
@subp{@div[style: "float: right;"]{@MMform[#f]{@MM{logout-button}}}
@b{@MM{Presentable-User}}'s subscription status, password, and options
for the @MM{List-Name} mailing list.}
@subp{@MM{Case-Preserved-User}
@MM{Disabled-Notice}
@div[style: "background-color: #ffaaaa;"]{@MM{Results}}}
@(define (tablesec . body)
(apply table cellspacing: 5 cellpadding: 3 width: "100%" align: 'center
body))
@(define (h2sub . body)
@h2[style: "margin-bottom: 0; font-size: 100%;"]{@body})
@(define (center . body)
@div[style: "text-align: center; margin-top: 1ex;"]{@body})
@(define (global-checkbox button-name)
@div[align: 'right]{@MM{global-@|button-name|-button}@i{Set globally}})
@MMform[#f]{
@tablesec{
@tr{@td[colspan: 2]{
@h2sub{Changing your @MM{List-Name} membership information}
@subp{You can change the address that you are subscribed to the
mailing list with by entering the new address in the fields
below. Note that a confirmation email will be sent to the new
address, and the change must be confirmed before it is
processed.
@small{(Confirmations time out after about
@MM{pending-days}.)}}
@subp{You can also optionally set or change your real name
(i.e. @em{John Smith}).}
@subp{If you want to make the membership changes for all the
lists that you are subscribed to at @MM{host}, turn on the
@em{Change globally} check box.}}}
@tr{@td[align: 'center]{
@table[cellspacing: 2 cellpadding: 2 width: "80%"]{
@tr{@graytd[align: 'right]{New address:}
@td{@MM{new-address-box}}}
@tr{@graytd[align: 'right]{Again to confirm:}
@td{@MM{confirm-address-box}}}}}
@td[align: 'center]{
@table[cellspacing: 2 cellpadding: 2 width: "80%"]{
@tr{@graytd[align: 'right]{Your name (optional):}
@td{@MM{fullname-box}}}}}}
@tr{@td[colspan: 2 align: 'center]{@MM{change-address-button}}}
@tr{@td[colspan: 2 align: 'center]{
@MM{global-change-of-address}Change globally}}}
@tablesec{
@tr{@td[width: "50%"]{@h2sub{Unsubscribing from @MM{List-Name}}}
@td[width: "50%"]{@h2sub{Your other @MM{Host} subscriptions}}}
@tr{@td{Turn on the confirmation checkbox and hit this button to
unsubscribe from this mailing list.
@br
@strong{Warning:} This action will be taken immediately!
@center{@MM{Unsubscribe-Button}}}
@td{You can view a list of all the other mailing lists at
@MM{host} for which you are a member. Use this if you want to
make the same membership option changes to this other
subscriptions.
@center{@MM{Other-Subscriptions-Submit}}}}}
@tablesec{
@tr{@td[colspan: 2]{@h2sub{Your @MM{List-Name} Password}}}
@tr[valign: 'top]{
@td[width: "50%"]{
@h3{@a[name: "reminder"]{Forgotten Your Password?}}
Click this button to have your password emailed to your membership
address.
@br
@MM{Umbrella-Notice}
@center{@MM{Email-My-Pw}}}
@td[width: "50%"]{
@h3{@a[name: "changepw"]{Change Your Password}}
@table[cellspacing: 2 cellpadding: 2 width: "70%" align: 'center]{
@tr{@graytd[align: 'right]{New password:}
@td{@MM{New-Pass-Box}}}
@tr{@graytd[align: 'right]{Again to confirm:}
@td{@MM{Confirm-Pass-Box}}}}
@center{@MM{Change-Pass-Button}}
@center{@MM{global-pw-changes-button}Change globally}}}}
@tablesec{
@tr{@td[colspan: 2]{@h2sub{Your @MM{List-Name} Subscription Options}}}
@tr{@td[colspan: 2]{
@subp{@em{Current values are checked.}}
@subp{Note that some of the options have a @em{Set globally}
checkbox. Checking this field will cause the changes to be
made to every mailing list that you are a member of on
@MM{host}. Click on @em{List my other subscriptions} above to
see which other mailing lists you are subscribed to.}}}
@tr{@graytd[width: "80%"]{
@a[name: "disable"]{@strong{Mail delivery}} @br
Set this option to @em{Enabled} to receive messages posted to
this mailing list. Set it to @em{Disabled} if you want to stay
subscribed, but don't want mail delivered to you for a while
(e.g. you're reading the list elsewhere).}
@graytd[width: "20%"]{
@MM{delivery-enable-button}Enabled @br
@MM{delivery-disable-button}Disabled @br
@global-checkbox{deliver}}}
@tr{@graytd{@strong{Set Digest Mode} @br
If you turn digest mode on, you'll get posts bundled together
(usually one per day but possibly more on busy lists), instead of
singly when they're sent. If digest mode is changed from on to
off, you may receive one last digest.}
@graytd{
@MM{Undigest-Radio-Button}Off @br
@MM{Digest-Radio-Button}On}}
@tr{@graytd{@strong{Get MIME or Plain Text Digests?} @br
Your mail reader may or may not support MIME digests. In general
MIME digests are preferred, but if you have a problem reading
them, select plain text digests.}
@graytd{
@MM{Mime-Digests-Button}MIME @br
@MM{Plain-Digests-Button}Plain Text @br
@global-checkbox{mime}}}
@tr{@graytd{@strong{Receive your own posts to the list?} @br
Ordinarily, you will get a copy of every message you post to the
list. If you don't want to receive this copy, set this option to
@em{No}.}
@graytd{@MM{dont-receive-own-mail-button}No @br
@MM{receive-own-mail-button}Yes}}
@tr{@graytd{@strong{Receive acknowledgement mail when you send mail to
the list?}}
@graytd{
@MM{dont-ack-posts-button}No @br
@MM{ack-posts-button}Yes}}
@tr{@graytd{@strong{Get password reminder email for this list?} @br
Once a month, you will get an email containing a password
reminder for every list at this host to which you are subscribed.
You can turn this off on a per-list basis by selecting @em{No}
for this option. If you turn off password reminders for all the
lists you are subscribed to, no reminder email will be sent to
you.}
@graytd{
@MM{dont-get-password-reminder-button}No @br
@MM{get-password-reminder-button}Yes @p
@global-checkbox{remind}}}
@tr{@graytd{@strong{Conceal yourself from subscriber list?} @br
When someone views the list membership, your email address is
normally shown (in an obscured fashion to thwart spam
harvesters). If you do not want your email address to show up on
this membership roster at all, select @em{Yes} for this option.}
@graytd{
@MM{Public-Subscription-Button}No @br
@MM{Hide-Subscription-Button}Yes}}
@tr{@graytd{@strong{What language do you prefer?}}
@graytd{@MM{list-langs}}}
@tr{@graytd{@strong{Which topic categories would you like to subscribe
to?} @br
By selecting one or more topics, you can filter the traffic on
the mailing list, so as to receive only a subset of the messages.
If a message matches one of your selected topics, then you will
get the message,otherwise you will not.
@br
If a message does not match any topic, the delivery rule depends
on the setting of the option below. If you do not select any
topics of interest, you will get all the messages sent to the
mailing list.}
@graytd{@MM{topics}}}
@tr{@graytd{@strong{Do you want to receive messages that do not match
any topic filter?} @br
This option only takes effect if you've subscribed to at least
one topic above. It describes what the default delivery rule is
for messages that don't match any topic filter. Selecting
@em{No} says that if the message does not match any topic
filters, then you won't get the message, while selecting @em{Yes}
says to deliver such non-matching messages to you.
@br
If no topics of interest are selected above, then you will
receive every message sent to the mailing list.}
@graytd{
@MM{suppress-nonmatching-topics}No @br
@MM{receive-nonmatching-topics}Yes}}
@tr{@graytd{@strong{Avoid duplicate copies of messages?} @br
When you are listed explicitly in the @tt{To:} or @tt{Cc:}
headers of a list message, you can opt to not receive another
copy from the mailing list. Select @em{Yes} to avoid receiving
copies from the mailing list; select @em{No} to receive copies.
@br
If the list has member personalized messages enabled, and you
elect to receive copies, every copy will have a
@tt{X-Mailman-Copy: yes} header added to it.}
@graytd{
@MM{receive-duplicates-button}No @br
@MM{dont-receive-duplicates-button}Yes @br
@global-checkbox{nodupes}}}
@tr{@td[colspan: 2 align: 'center]{@MM{options-Submit-button}}}}}
@MM{Mailman-Footer}})
(define roster
@page[#:title @list{@MM{List-Name} subscribers}
#:part-of 'community
#:extra-headers style-header]{
@; --------------------
@comment{@||
Based on the Mailman file "roster.html", revision 3394
Modified to fit the racket pages
@||}
@; --------------------
@h1{@MM{List-Name} subscribers}
@; @p[align: 'right]{
@; @MM{lang-form-start}@MM{displang-box} @MM{list-langs}@MM{form-end}}
@p{Click on your address to visit your subscription options page.
@br
@i{(Parenthesized entries have list delivery disabled.)}}
@table[cellspacing: 4 cellpadding: 5 width: "80%" align: 'center]{
@thead{
@tr[valign: 'top]{
@graytd[width: "50%" align: 'center]{
@MM{Num-Reg-Users} Non-digested Members:}
@graytd[width: "50%" align: 'center]{
@MM{Num-Digesters} Digested Members:}}}
@tr[valign: 'top]{
@td{@MM{Regular-Users}}
@td{@MM{Digest-Users}}}}
@MM{Mailman-Footer}})
;; Files below go through "%(...)s" substitutions, so "%"s should be doubled to
;; avoid python errors -- hack this with regexps below. A proper solution
;; would be to use the improved feature that `with-writer' is not, then have
;; this code use it to add another substitution.
(define (encode-%s content)
(regexp-replace*
#rx"%[^(]"
(let ([c (force content)]) (if (string? c) c (xml->string c)))
"%\\0"))
(require (for-syntax racket/base))
(define-syntax (page%% stx)
(syntax-case stx ()
[(page%% #:html-only #t x ...)
#`(lazy (encode-%s (page #:html-only #t x ...)))]
[(page%% x ...)
(let ([id (or (syntax-property stx 'inferred-name)
(syntax-local-name))])
#`(plain #,@(if id #`(#:id '#,id) #`()) #:suffix "html" #:newline #f
(page%% #:html-only #t x ...)))]))
(define private
@page%%[#:title @list{%(realname)s private archives authentication}
#:part-of 'community
#:extra-headers
@list{@style-header
@script/inline{function sf(){document.f.adminpw.focus()@";"}}}
#:extra-body-attrs `(onLoad: "sf();")]{
@; --------------------
@comment{@||
Based on the Mailman file "private.html" (no revision specified)
Modified to fit the racket pages
@||}
@; --------------------
%(message)s
@form[method: 'post action: "%(action)s" name: "f"]{
@h1{%(realname)s private archives authentication}
@table[cellspacing: 4 cellpadding: 5 width: "80%" align: 'center]{
@tr{@td[align: 'right]{Email address:}
@td{@input[type: 'text name: 'username size: 30]}}
@tr{@td[align: 'right]{Password:}
@td{@input[type: 'password name: 'password size: 30]}}
@tr{@td[colspan: 2 align: 'middle]{
@input[type: 'submit name: 'submit value: "Let me in..."]}}}}
@p{@strong{Important:} From this point on, you must have cookies enabled in
your browser, otherwise you will have to re-authenticate with every
operation.}
@p{Session cookies are used in Mailman's private archive interface so that
you don't need to re-authenticate with every operation. This cookie will
expire automatically when you exit your browser, or you can explicitly
expire the cookie by visiting your member options page and clicking the
@em{Log out} button.}
@h2{Password reminder}
@p{If you don't remember your password, enter your email address above and
click the @em{Remind} button and your password will be emailed to you.}})
(define admlogin
@page%%[#:title @list{%(listname)s %(who)s Authentication}
#:part-of 'community
#:extra-headers
@list{@style-header
@script/inline{function sf(){document.f.adminpw.focus()@";"}}}
#:extra-body-attrs `(onLoad: "sf();")]{
@; --------------------
@comment{@||
Based on the Mailman file "admlogin.html" (no revision specified)
Modified to fit the racket pages
@||}
@; --------------------
%(message)s
@form[method: 'post action: "%(path)s" name: "f"]{
@h1{%(listname)s %(who)s authentication}
@table[cellspacing: 4 cellpadding: 5 width: "80%" align: 'center]{
@tr{@td[align: 'right]{List %(who)s Password:}
@td{@input[type: 'password name: 'adminpw size: 30]}}
@tr{@td[colspan: 2 align: 'middle]{
@input[type: 'submit name: 'admlogin value: "Let me in..."]}}}}
@p{@strong{Important:} From this point on, you must have cookies enabled in
your browser, otherwise no administrative changes will take effect.}
@p{Session cookies are used in Mailman's administrative interface so that
you don't need to re-authenticate with every administrative operation.
This cookie will expire automatically when you exit your browser, or you
can explicitly expire the cookie by hitting the @em{Logout} link under
@em{Other Administrative Activities} (which you'll see once you
successfully log in).}})
;; Archive templates
(define emptyarchive
@page%%[#:title @list{%(listname)s archives} #:part-of 'community
#:extra-headers style-header]{
@; --------------------
@comment{@||
Based on the Mailman file "emptyarchive.html" (no revision specified)
Modified to fit the racket pages
@||}
@; --------------------
@h1{%(listname)s archives}
@p{No messages have been posted to this list yet, so the archives are
currently empty. You can get @a[href: "%(listinfo)s"]{more information
about this list}.}})
(define archtocs
(let ([title @list{%(listname)s archives}]
[headers @list{@style-header
@;meta[name: 'robots content: "noindex,follow"]
%(meta)s}])
(define (content mbox?)
@list{
@; --------------------
@comment{@||
Based on the Mailman file "archtoc.html" and "archtocnombox.html"
(no revision specified)
Modified to fit the racket pages
@||}
@; --------------------
@h1{%(listname)s archives}
@p{You can get @;
@a[href: "%(listinfo)s"]{more information about this list}@;
@(when mbox?
@list{ or you can @;
@a[href: "%(fullarch)s"]{download the full raw archive} @;
(%(size)s)}).}
%(noarchive_msg)s
%(archive_listing_start)s
%(archive_listing)s
%(archive_listing_end)s})
(define archtoc.html
(@page%% #:title title #:part-of 'community #:extra-headers headers
(content #t)))
(define archtocnombox.html
(@page%% #:title title #:part-of 'community #:extra-headers headers
(content #f)))
(list archtoc.html archtocnombox.html)))
(define archlist-templates
(split-template
#:encoder encode-%s
@table[border: 2 bordercolor: "#888" cellspacing: 0 cellpadding: 5
align: 'center]{
@tr{@td{Archive}
@td{View by:}
@td{Downloadable version}}
@HOLE
@tr{@td[align: 'right]{%(archivelabel)s:}
@td{@a[href: "%(archive)s/thread.html"]{[Thread]} @;
@a[href: "%(archive)s/subject.html"]{[Subject]} @;
@a[href: "%(archive)s/author.html"]{[Author]} @;
@a[href: "%(archive)s/date.html"]{[Date]}}
%(textlink)s}
@HOLE}
"archliststart.html" "archtocentry.html" "archlistend.html"))
(define archiveidx-templates
(split-template
@page%%[#:html-only #t
#:title "%(listname)s %(archive)s archives by %(archtype)s"
#:part-of 'community
#:extra-headers @list{@style-header
@;meta[name: 'robots content: "noindex,follow"]
%(encoding)s}]{
@(define sorted-info
@ul{@li{@b{Messages sorted by:}
%(thread_ref)s %(subject_ref)s %(author_ref)s %(date_ref)s}
@li{@a[href: "%(listinfo)s"]{More info on this list...}}})
@a[name: "start"]
@h1{%(archive)s archives by %(archtype)s}
@sorted-info
@p{@b{Starting:} @i{%(firstdate)s}@br
@b{Ending:} @i{%(lastdate)s}@br
@b{Messages:} %(size)s}
@ul{
@|HOLE|@;
@li{@a[href: "%(filename)s" name: "%(sequence)i"]{%(subject)s},
@i{%(author)s}}
@HOLE}
@p{@a[name: "end"]{@b{Last message date:}} @i{%(lastdate)s}@br
@b{Archived on:} @i{%(archivedate)s}}
@sorted-info
@hr
@p[style: "text-align: right; font-size: x-small; font-style: italic;"]{
(This archive was generated by Pipermail %(version)s.)}}
"archidxhead.html" "archidxentry.html" "archidxfoot.html"))
(define article
@page%%[#:title @list{%(title)s}
#:part-of 'community
#:extra-headers
@list{@style-header
@link[rel: 'index href: "index.html"]
@link[rel: 'made
href: '@{mailto:%(email_url)s?Subject=%(subject_url)s&@;
In-Reply-To=%(in_reply_to_url)s}]
@;meta[name: 'robots content: "index,nofollow"]
@style/inline{pre { white-space: pre-wrap@";" }}
%(encoding)s
%(prev)s
%(next)s}]{
@(define sorted-by
@list{Messages sorted by: @;
@a[href: "date.html#%(sequence)s"]{[date]}
@a[href: "thread.html#%(sequence)s"]{[thread]}
@a[href: "subject.html#%(sequence)s"]{[subject]}
@a[href: "author.html#%(sequence)s"]{[author]}})
@(define navcell
(let ([n 0])
(λ () (set! n (add1 n))
@td{@ul[style: "font-size: x-small;"]{
@; need only one of these things, at the end
@(when (= n 2) (list "\n" @comment{threads} "\n"))@;
%(prev_wsubj)s
%(next_wsubj)s
@li{@sorted-by}}})))
@; --------------------
@; Based on the Mailman file "article.html" (no revision specified)
@; Modified to fit the racket pages
@; (This comment is not included on actual archive message pages)
@; --------------------
@h1{%(subject_html)s}
@table{@tr{@td{
From: @b{%(author_html)s} @;
(@a[href: '@{mailto:%(email_url)s?Subject=%(subject_url)s&@;
In-Reply-To=%(in_reply_to_url)s}
title: "%(subject_html)s"]{
%(email_html)s})@;
@br
Date: @i{%(datestr_html)s}}
@navcell}}
@hr
@comment{beginarticle}
%(body)s
@comment{endarticle}
@hr
@table{@tr{@td{Posted on the @;
@a[href: "%(listurl)s"]{%(listname)s mailing list}.}
@navcell}}})
;; Previously mailman had a "site" directory which would override the default
;; "en" files. I don't see this setup now, so a cheap hack is to create
;; symlinks to a directory with the original versions for all files that are
;; not generated above.
(define symlinks
(map (λ(f) (symlink (format "/etc/mailman/templates/en-orig/~a" f)))
'("admindbdetails.html" "admindbpreamble.html" "admindbsummary.html"
"adminsubscribeack.txt" "adminunsubscribeack.txt" "approve.txt"
"bounce.txt" "checkdbs.txt" "convert.txt" "cronpass.txt" "disabled.txt"
"headfoot.html" "help.txt" "invite.txt" "masthead.txt" "newlist.txt"
"nomoretoday.txt" "postack.txt" "postauth.txt" "postheld.txt"
"probe.txt" "refuse.txt" "subauth.txt" "subscribeack.txt" "unsub.txt"
"unsubauth.txt" "userpass.txt" "verify.txt")))

View File

@ -0,0 +1,17 @@
#lang meta/web
(define-context "stubs/planet")
(provide planet)
(define planet
@page[#:file "" #:link-title "PLaneT" #:window-title "{{{TITLE}}}"
#:extra-headers "{{{HEAD}}}"]{
@; This is a stub page to get the header for planet
{{{BODY}}}})
(define readme
@plain[#:file "README"]{
This directory contains files that are placed here automatically by
the web build process. The HTML file contains holes to be filled in
for the title, header, and body, and the other files are resources
that are used by the template.})

View File

@ -0,0 +1,299 @@
#lang meta/web
(require "git.rkt")
(define-context "stubs/pre")
(define temporary-outdated-warning
@div[style: "border: 1px dotted red; padding: 0ex 1ex"]{
@p*{
This page is not currently updating with new nightly builds, but it will
resume soon.
@~
Meanwhile, recent builds for various platforms are available from the
following sites:
@ul*{@~ @a[href: "http://www.cs.utah.edu/plt/snapshots/"]{
University of Utah}
@~ @a[href: "http://plt.eecs.northwestern.edu/snapshots/"]{
Northwestern University}}}})
(define (hole tag)
@list{@||
{{{@tag}}}
@||})
(define title-hole (list "Prebuilt:" (hole "TITLE")))
(define content-hole (hole "CONTENT"))
(define version-hole
(div style: "text-align: right; font-size: small; font-style: italic;"
(hole "VERSION")))
(define template
;; generic skeleton for all files that don't have a specific template below.
@page[#:window-title title-hole]{
@temporary-outdated-warning
@content-hole
@hr
@version-hole})
(provide index)
(define index
@page[#:file "" #:window-title "Prebuilt materials"]{
@temporary-outdated-warning
@p{This directory contains Racket materials that are built daily from the
development repository. See below for instructions.}
@hr
@content-hole
@hr
@p*{
The nightly-builds page is being built every night from the current @git,
which lets you use the latest material with close to zero hassle that is
normally associated with checking out the development tree. You can
choose whether you want to use the full source tree, which means that you
will get a lot more than you get with a standard distribution, or the
installers that contain the same material as a standard distribution.
@~
For the easiest way of getting a build, choose an installer for your
platform from the @a[href: "installers/"]{@tt{installers}} directory.
@~
For an approach that is more suitable for scripting, you should:
@ol*{@~ start at the @a[href: "binaries/"]{@tt{binaries}} subdirectory
for your platform,
@~ download the @tt{racket-...-full.tgz} file,
@~ unpack it with GNU Tar (or something compatible to it), for
example: "@tt{tar xzf racket-...-full.tgz}".}
Note that there are many other @tt{tgz} files that contain various
subsets of the tree, for example, you can get just the documentation
part, the clean @tt{plt/src} part, the full tree before any compilation,
documentation @tt{.plt} files, or for each platform a @tt{tgz} file that
contains just native-code binary files.
@~
It is also easy to setup a script that will automate the process of
retrieving the @tt{tgz} file, unpacking and installing it. This is
explained in more details in @script{scripts}. In addition to being
convenient for updating your tree, it can be used by an automatic job
scheduler (for example, a cron job on Unix) to make tree that is always
updated.}
@hr
@version-hole})
(define pre-installers
@page[#:file "pre-installers/" #:title "Nightly build pre-installers"]{
@temporary-outdated-warning
@p{This directory contains distribution packages in tgz format. They are
later converted to the actual platform-specific
@a[href: "../installers/"]{installers}.}
@hr
@content-hole
@hr
@version-hole})
(provide installers)
(define installers
@page[#:file "installers/" #:title "Nightly build installers"]{
@temporary-outdated-warning
@p{Pre-release software is built using actively developed sources.
Binaries are built nightly, and minute-by-minute changes are available
through @|git|.}
@; ----------------------------------------
@h2{Option 1: Installer}
@content-hole
@version-hole
@table[width: "80%" align: 'center]{
@tr{@td[valign: 'top]{Installers:}
@td{@nbsp}
@td{@dl*{@~ @b{Racket}
@~ Same as the normal distribution, containing the basic
systems and DrRacket.
@~ @b{Racket Textual}
@~ A small distribution that contains only Racket and
console applications based on it, including the Racket
web server. No docs and no GUI applications.
@~ @b{Racket Full}
@~ Contains the @i{complete} Racket tree from the
@git{repository}, including full documentation, full
source tree, libraries that are not completely stable,
and esoteric material.}}}
@tr{@td[colspan: 3]{
Note: the default installation directory contains the version
number to avoid clobbering a normal installation.
@small{(Under Windows, registry names are different, too.)}}}}
@; ----------------------------------------
@h2{Option 2: git Repository}
@p{Full source is available from the @git{repository}.}
@; ----------------------------------------
@h2{Option 3: Other}
@p{Want Racket sources from @git but don't want to build binaries?
Want to browse a @git checkout? The
@a[href: "../"]{nightly build page} has everything you
could want.}})
(provide (rename-out [docs* docs]))
(define (docs* #:sub [sub #f] . text)
(if sub
(apply a href: (list (url-of docs) sub "/") (if (null? text) sub text))
(apply docs text)))
(define docs
@page[#:file "docs/" #:title "Prebuilt documentation"]{
@temporary-outdated-warning
@p{This directory contains documentation files in all forms, compiled from
the current sources.}
@hr
@content-hole
@hr
@version-hole})
(define binaries
@page[#:file "binaries/" #:title "Prebuilt binaries"]{
@temporary-outdated-warning
@p{This directory contains a subdirectory for each supported platform.}
@hr
@content-hole
@hr
@version-hole})
(define script
@page[#:file "script.html" #:title "Using the nightly Racket builds"]{
@temporary-outdated-warning
@(define (url . s) @list{http://pre.racket-lang.org/@s})
@(define (pre* . text) (apply pre style: "margin-left: 2em;" text))
@p*{
Using the nightly builds to get the latest version is very simple, and
does not require git. If you use the @a[href: "installers"]{installers}
directory, then things are as simple as they are with a normal Racket
distribution the only slight difference is that by default the
directory name contains the version number, so it does not clobber an
official installation (this also works on Windows, where the registry
keys are separate for each nightly version).
@~
But there is a lot of material in here that might fit better a script
that updates a Racket tree automatically. For this, the only tools you
will need are GNU tar, a utility to fetch files from the web, and some
scripting facility. For example, assuming that your @tt{racket}
directory is in "@tt{$BASE}", retrieving the latest source tree is as
simple as:
@pre*{
cd $BASE
wget @url{racket-src.tgz} -O - | tar xzf -}
or with @tt{curl}:
@pre*{
cd $BASE
curl @url{racket-src.tgz} | tar xzf -}
@~
This will fetch and unpack the full @tt{racket} source tree at the
current directory, on top of any @tt{racket} directory that might happen
to be there. Since it probably doesn't make sense to have older binaries
and newer source files, it is a good idea to remove any previous tree (if
any):
@pre*{
cd $BASE
rm -rf racket
curl @url{racket-clean-tree.tgz} | tar xzf -}
@~
This is possible with any of the subsets that are packed as tgz files.
For example, to update just the binaries for OS X (over an existing
@tt{racket} tree):
@pre*{
cd $BASE
wget @url{binaries/i386-osx-mac/racket-i386-osx-mac-binaries.tgz} -O - \
|| tar xzf -}
To get a fully built tree for Windows:
@pre*{
cd $BASE
rm -rf racket
wget @url{binaries/i386-win32/racket-i386-win32-full.tgz} -O - \
|| tar xzf -
cd racket}
Note that there is no “install” step: the archive contains a ready-to-run
tree.
@~
Finally, there is a @tt{stamp} file in the nightly build directory that
can be used for scripts that periodically poll for new builds. This file
is updated last in the build process, so if a build fails it will stay
the same and not fool you into getting the same build. To demonstrate
using this, here is an @tt{sh} script that compares a local copy of the
@tt{stamp} file to the one on the web, and if there is any difference,
retrieves and installs the new full Windows build (assuming it is in my
home directory):
@pre*{
#!/bin/sh
cd
URL="@url{}"
touch stamp # make sure that it is there
if ! curl -s $URL/stamp | diff -q stamp - >/dev/null 2>&1; then
curl -s $URL/stamp > stamp # remember the new stamp
#----------
rm -rf racket
wget $URL/binaries/i386-win32/racket-i386-win32-full.tgz -O - @;
| tar xzf -
#----------
fi}
The marked part of this script can be replaced by any of the options
mentioned above, for other platforms or something other than retrieving a
full build.
@~
This script will retrieve and install a new build only when one is ready.
It is suitable for running periodically via a crontab entry. For
example, save it in @tt{~/bin/update-full-racket}, run @tt{crontab -e} to
edit your @tt{crontab} entries, and add a line that looks like this:
@pre*{13 */6 * * * ~/bin/update-full-racket}
This will run the script on the 13th minute of every sixth hour. It is
harmless to run it every hour, but there's no real need for it.
Currently, the nightly build process starts at 3:50am (EDT) and lasts for
about two hours, but every once in a while there would be additional
builds (eg, after a minor version change).}
@h3{A note about defensive scripting:}
@p{Writing scripts that work for you is easy. Making them robust enough to
be usable by others or by site-wide setups can be a delicate job you
have to plan for bad @tt{PATH} setting (for example, a cron job is
started in a pretty much bare environment), errors that happen in one
command etc. The following is just like the above script, modified to
be more robust in the following way:
@ol*{@~ The @tt{PATH} environment variable is explicitly set.
@~ Use variable definitions to make customization easy.
@~ Usages of @tt{$URL} and others are quoted in case they will ever
contain spaces.
@~ If we fail to retrieve a file, we quit the script.
@~ Use a temporary directory to retrieve the tree, and then move it
to its real place (so if it fails we don't end up with no
@tt{racket}) through renaming (if we delete @tt{racket} and then
rename the new one, we might fail halfway into the deletion).
@~ Also, there might be some binary process running from an old
file which might prevent removing the directory, so failure to
remove the old tree does not abort the script.
@~ The new stamp is remembered only if everything succeeded.}}
@hr
@pre*{
#!/bin/sh
PATH="/bin:/usr/bin"
# where is our racket tree placed?
MAINDIR="$HOME"
# where should the local stamp file copy be stored?
STAMP="$MAINDIR/stamp"
# where is the online stuff?
URL="@url{}"
cd "$MAINDIR"
touch "$STAMP" # make sure that it is there
curl -s "$URL/stamp" > "$STAMP-new"
if diff -q "$STAMP" "$STAMP-new" >/dev/null 2>&1; then
# nothing changed
rm "$STAMP-new"
else
#----------
mkdir "$MAINDIR/racket-temp-$$"
cd "$MAINDIR/racket-temp-$$"
wget "$URL/binaries/i386-win32/racket-i386-win32-full.tgz" -O - \
| tar xzf - \
|| exit 1
cd "$MAINDIR"
if [ -e "racket" ]; then mv "racket" "racket-temp-$$/racket-old"; fi \
&& mv "racket-temp-$$/racket" . \
|| exit 1
rm -rf "racket-temp-$$"
#----------
cd "$MAINDIR"
rm "$STAMP" # remember the new stamp only if no failure so far
mv "$STAMP-new" "$STAMP"
fi
}
@hr})

View File

@ -0,0 +1,11 @@
#lang meta/web
(require (prefix-in www: (only-in "../www/resources.rkt" the-resources)))
(define-context "stubs/wiki" #:resources www:the-resources)
(define template
(page #:title "{{{TITLE}}}"
#:extra-headers "{{{HEADERS}}}"
#:extra-body-attrs '(|{{{ATTRS}}}|: #t)
"{{{BODY}}}"))

View File

@ -0,0 +1,525 @@
<!doctype html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
<!--[if IE 9]> <html class="no-js ie9" lang="en"> <![endif]-->
<!-- Consider adding an manifest.appcache: h5bp.com/d/Offline -->
<!--[if gt IE 9]><!--> <html class="no-js" lang="en" itemscope itemtype="http://schema.org/Product"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<!-- Use the .htaccess and remove these lines to avoid edge case issues.
More info: h5bp.com/b/378 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>The Racket Language</title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<!-- Mobile viewport optimized: j.mp/bplateviewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
<!-- Place favicon.ico and apple-touch-icon.png in the root directory: mathiasbynens.be/notes/touch-icons -->
<!-- CSS: implied media=all -->
<!-- CSS concatenated and minified via ant build script-->
<!-- <link rel="stylesheet" href="css/minified.css"> -->
<!-- CSS imports non-minified for staging, minify before moving to production-->
<link rel="stylesheet" href="css/gumby.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/scribble.css">
<!-- end CSS-->
<!-- More ideas for your <head> here: h5bp.com/d/head-Tips -->
<!-- All JavaScript at the bottom, except for Modernizr / Respond.
Modernizr enables HTML5 elements & feature detects; Respond is a polyfill for min/max-width CSS3 Media Queries
For optimal performance, use a custom Modernizr build: www.modernizr.com/download/ -->
<script src="js/libs/modernizr-2.6.2.min.js"></script>
</head>
<body>
<div class="navbar" gumby-fixed="top" id="nav1">
<div class="row">
<a class="toggle" gumby-trigger="#nav1 > .row > ul" href="#"><i class="icon-menu"></i></a>
<a class="five columns logo" href="">
<img class="logo" src="img/logo.png" />
</a>
<ul class="five columns" >
<li><a href="https://pkg.racket-lang.org">Packages</a></li>
<li><a href="http://docs.racket-lang.org">Documentation</a></li>
<li><a href="http://blog.racket-lang.org">Blog</a></li>
<li>
<button class="medium metro info btn icon-left entypo icon-install">
<a href="#">Download</a>
</button>
</li>
</ul>
</div>
</div>
<div class="modal" id="modal1">
<div class="content unique_lines codesnip active">
<a class="close switch" gumby-trigger="|#modal1"><i class="icon-cancel" ></i></a>
<div class="row">
<div class="ten columns centered center-text">
<h4>Unique Lines</h4>
<pre style="font-size: 140%; font-family: 'Inconsolata';">
#lang <a href="http://docs.racket-lang.org/reference/index.html" class="codemodpath" rel="nofollow">racket</a>
<span class="codecomment">;; Report each unique line from stdin</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket/private/letstx-scheme..rkt)._let))" class="codelinkimportform" rel="nofollow">let</a> <span class="codeparenthesis">(</span><span class="codeparenthesis">[</span><span class="codeid">saw</span> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/hashtables.html#(def._((quote._~23~25kernel)._make-hash))" class="codelinkimportid" rel="nofollow">make-hash</a><span class="codeparenthesis">)</span><span class="codeparenthesis">]</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" class="codelinkimportform" rel="nofollow">for</a> <span class="codeparenthesis">(</span><span class="codeparenthesis">[</span><span class="codeid">line</span> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-lines))" class="codelinkimportid" rel="nofollow">in-lines</a><span class="codeparenthesis">)</span><span class="codeparenthesis">]</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/when_unless.html#(form._((lib._racket/private/letstx-scheme..rkt)._unless))" class="codelinkimportform" rel="nofollow">unless</a> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/hashtables.html#(def._((quote._~23~25kernel)._hash-ref))" class="codelinkimportid" rel="nofollow">hash-ref</a> <span class="codeid">saw</span> <span class="codeid">line</span> <span class="codeconstant">#f</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((lib._racket/private/misc..rkt)._displayln))" class="codelinkimportid" rel="nofollow">displayln</a> <span class="codeid">line</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/hashtables.html#(def._((quote._~23~25kernel)._hash-set!))"
class="codelinkimportid"
rel="nofollow">hash-set!</a> <span class="codeid">saw</span> <span class="codeid">line</span> <span class="codeconstant">#t</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span>
</pre>
</div>
</div>
<div class="row">
<div class="ten columns centered center-text">
<p>
Uses a hash table to record previously seen lines. You can run this program in DrRacket, but it makes more sense from the command line.
</p>
<p>
To run the example, install Racket, start DrRacket, paste the example
program into the top area in DrRacket, and click the Run
button. Alternatively, save the program to a file and run <code>racket</code> on
the file.
</p>
<p style="font-size: 80%">
Form and function names in the code are hyperlinked to
documentation, so click on them for more information.
</p>
</div>
</div>
</div>
<div class="content web_scraper codesnip">
<a class="close switch" gumby-trigger="|#modal1"><i class="icon-cancel" /></i></a>
<div class="row">
<div class="ten columns centered center-text">
<h4>Web scraper</h4>
<pre style="font-size: 140%; font-family: 'Inconsolata';">
#lang <a href="http://docs.racket-lang.org/reference/index.html" class="codemodpath" rel="nofollow">racket</a> <span class="codecomment">; Simple web scraper</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" class="codelinkimportform" rel="nofollow">require</a> <a href="http://docs.racket-lang.org/net/url.html" class="codemodpath" rel="nofollow">net/url</a> <a href="http://docs.racket-lang.org/net/uri-codec.html" class="codemodpath" rel="nofollow">net/uri-codec</a><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" class="codelinkimportform" rel="nofollow">define</a> <span class="codeparenthesis">(</span><span class="codeid">let-me-google-that-for-you</span> <span class="codeid">str</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket/private/letstx-scheme..rkt)._let*))" class="codelinkimportform" rel="nofollow">let*</a> <span class="codeparenthesis">(</span><span class="codeparenthesis">[</span><span class="codeid">g</span> <span class="codestring">"http://www.google.com/search?q="</span><span class="codeparenthesis">]</span>
<span class="codeparenthesis">[</span><span class="codeid">u</span> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/strings.html#(def._((quote._~23~25kernel)._string-append))" class="codelinkimportid" rel="nofollow">string-append</a> <span class="codeid">g</span> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/net/uri-codec.html#(def._((lib._net/uri-codec..rkt)._uri-encode))" class="codelinkimportid" rel="nofollow">uri-encode</a> <span class="codeid">str</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span><span class="codeparenthesis">]</span>
<span class="codeparenthesis">[</span><span class="codeid">rx</span> <span class="codestring">#rx"(?&lt;=&lt;h3 class=\"r\"&gt;).*?(?=&lt;/h3&gt;)"</span><span class="codeparenthesis">]</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/regexp.html#(def._((lib._racket/private/base..rkt)._regexp-match*))" class="codelinkimportid" rel="nofollow">regexp-match*</a> <span class="codeid">rx</span> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/net/url.html#(def._((lib._net/url..rkt)._get-pure-port))" class="codelinkimportid" rel="nofollow">get-pure-port</a> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/net/url.html#(def._((lib._net/url..rkt)._string-~3eurl))" class="codelinkimportid" rel="nofollow">string-&gt;url</a> <span class="codeid">u</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span>
</pre>
</div>
</div>
<div class="row">
<div class="ten columns centered center-text">
<p>
Add a call to <code>let-me-google-that-for-you</code> to get a list of search
results.
</p>
<p>
To run the example, install Racket, start DrRacket, paste the example
program into the top area in DrRacket, and click the Run
button. Alternatively, save the program to a file and run <code>racket</code> on
the file.
</p>
<p class="footnote" style="font-size: 80%">
Form and function names in the code are hyperlinked to
documentation, so click on them for more information.
</p>
</div>
</div>
</div>
</div>
<div class="row" >
<div class="ten columns centered">
<h2 style="font-size: 180%; margin-bottom: 10pt">
<strong>Racket</strong> &nbsp;&mdash;&nbsp;
<span style="font-style: italic">a programmable programming
language</span>
</h2>
</div></div>
<div class="row" >
<div class="eight columns centered" style="margin-bottom: 10pt; font-size: 120%; text-align:justify;">
Racket is a wide-spectrum programming language that inherits from Lisp
and Scheme but also provides dialects that support objects, types,
laziness, and many other paradigms. Racket's module system allows
programmers to write and link together components written in different
dialects. Racket's libraries range from web servers to distributed
computing and from databases to charts.
</div>
</div>
<!-- <div class="row" > -->
<!-- <div class="one columns"></div> -->
<!-- <div class="eight columns"><h2 style="font-size: 180%; -->
<!-- margin-bottom: -->
<!-- 10pt"></>Start -->
<!-- Quickly</h2></div> -->
<!-- <div class="three columns"><h2 style="font-size: 180%; -->
<!-- margin-bottom: -->
<!-- 10pt"></>News -->
<!-- </h2></div> -->
<!-- </div> -->
<!-- The other version of the buttons: -->
<!-- <div class="eight columns centered" -->
<!-- style="font-size: 140%; position: relative; -->
<!-- font-family: 'Inconsolata';"> -->
<!-- <a href="#" class="toggle" gumby-trigger=".unique_lines|.web_scraper"> -->
<!-- <img class="halign" src="img/prev.png" style="position: -->
<!-- absolute; top: 50%; left: -20%; margin-top: -25px"> -->
<!-- </a> -->
<!-- <a href="#" class="toggle" gumby-trigger=".unique_lines|.web_scraper"> -->
<!-- <img class="halign" src="img/next.png" -->
<!-- style="position: absolute; top: 50%; right: -20%; -->
<!-- margin-top: -->
<!-- -25px"> -->
<!-- </a> -->
<div id="topcontent">
<div class="row">
<div class="one columns">
</div>
<div class="seven columns" >
<h2 style="font-size: 180%;
margin-bottom:
10pt"></>Start
Quickly</h2>
<div style="position: relative; ">
<p class="metro primary btn"
style="position: absolute; top: -10%; right: 0%;" >
<a href="#" class="switch" gumby-trigger="#modal1"> <i class="icon-help"></i></a>
</p>
<a href="#" class="toggle narrow_only"
gumby-trigger=".unique_lines|.web_scraper" style="position: absolute; top: -40%; left: 35%">
<img src="img/prev.png" style="width: 50px">
</a>
<a href="#" class="toggle narrow_only"
gumby-trigger=".unique_lines|.web_scraper" style="position: absolute; top: -40%; right: 35%">
<img src="img/next.png" style="width: 50px">
</a>
<a href="#" class="toggle wide_only"
gumby-trigger=".unique_lines|.web_scraper" style="position: absolute; top: 40%; left: -15%">
<img src="img/prev.png" style="width: 50px">
</a>
<a href="#" class="toggle wide_only"
gumby-trigger=".unique_lines|.web_scraper" style="position: absolute; top: 40%; right: -15%">
<img src="img/next.png" style="width: 50px">
</a>
<pre class="codesnip active unique_lines" style="font-size: 140%;">
#lang <a href="http://docs.racket-lang.org/reference/index.html" class="codemodpath" rel="nofollow">racket</a>
<span class="codecomment">;; Report each unique line from stdin</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket/private/letstx-scheme..rkt)._let))" class="codelinkimportform" rel="nofollow">let</a> <span class="codeparenthesis">(</span><span class="codeparenthesis">[</span><span class="codeid">saw</span> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/hashtables.html#(def._((quote._~23~25kernel)._make-hash))" class="codelinkimportid" rel="nofollow">make-hash</a><span class="codeparenthesis">)</span><span class="codeparenthesis">]</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/for.html#(form._((lib._racket/private/base..rkt)._for))" class="codelinkimportform" rel="nofollow">for</a> <span class="codeparenthesis">(</span><span class="codeparenthesis">[</span><span class="codeid">line</span> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/sequences.html#(def._((lib._racket/private/base..rkt)._in-lines))" class="codelinkimportid" rel="nofollow">in-lines</a><span class="codeparenthesis">)</span><span class="codeparenthesis">]</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/when_unless.html#(form._((lib._racket/private/letstx-scheme..rkt)._unless))" class="codelinkimportform" rel="nofollow">unless</a> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/hashtables.html#(def._((quote._~23~25kernel)._hash-ref))" class="codelinkimportid" rel="nofollow">hash-ref</a> <span class="codeid">saw</span> <span class="codeid">line</span> <span class="codeconstant">#f</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/Writing.html#(def._((lib._racket/private/misc..rkt)._displayln))" class="codelinkimportid" rel="nofollow">displayln</a> <span class="codeid">line</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/hashtables.html#(def._((quote._~23~25kernel)._hash-set!))"
class="codelinkimportid"
rel="nofollow">hash-set!</a> <span class="codeid">saw</span> <span class="codeid">line</span> <span class="codeconstant">#t</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span>
</pre>
<pre class="codesnip web_scraper">
#lang <a href="http://docs.racket-lang.org/reference/index.html" class="codemodpath" rel="nofollow">racket</a> <span class="codecomment">; Simple web scraper</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/require.html#(form._((lib._racket/private/base..rkt)._require))" class="codelinkimportform" rel="nofollow">require</a> <a href="http://docs.racket-lang.org/net/url.html" class="codemodpath" rel="nofollow">net/url</a> <a href="http://docs.racket-lang.org/net/uri-codec.html" class="codemodpath" rel="nofollow">net/uri-codec</a><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))" class="codelinkimportform" rel="nofollow">define</a> <span class="codeparenthesis">(</span><span class="codeid">let-me-google-that-for-you</span> <span class="codeid">str</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/let.html#(form._((lib._racket/private/letstx-scheme..rkt)._let*))" class="codelinkimportform" rel="nofollow">let*</a> <span class="codeparenthesis">(</span><span class="codeparenthesis">[</span><span class="codeid">g</span> <span class="codestring">"http://www.google.com/search?q="</span><span class="codeparenthesis">]</span>
<span class="codeparenthesis">[</span><span class="codeid">u</span> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/strings.html#(def._((quote._~23~25kernel)._string-append))" class="codelinkimportid" rel="nofollow">string-append</a> <span class="codeid">g</span> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/net/uri-codec.html#(def._((lib._net/uri-codec..rkt)._uri-encode))" class="codelinkimportid" rel="nofollow">uri-encode</a> <span class="codeid">str</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span><span class="codeparenthesis">]</span>
<span class="codeparenthesis">[</span><span class="codeid">rx</span> <span class="codestring">#rx"(?&lt;=&lt;h3 class=\"r\"&gt;).*?(?=&lt;/h3&gt;)"</span><span class="codeparenthesis">]</span><span class="codeparenthesis">)</span>
<span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/reference/regexp.html#(def._((lib._racket/private/base..rkt)._regexp-match*))" class="codelinkimportid" rel="nofollow">regexp-match*</a> <span class="codeid">rx</span> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/net/url.html#(def._((lib._net/url..rkt)._get-pure-port))" class="codelinkimportid" rel="nofollow">get-pure-port</a> <span class="codeparenthesis">(</span><a href="http://docs.racket-lang.org/net/url.html#(def._((lib._net/url..rkt)._string-~3eurl))" class="codelinkimportid" rel="nofollow">string-&gt;url</a> <span class="codeid">u</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span><span class="codeparenthesis">)</span>
</pre>
</div>
</div>
<div class="one columns"> </div>
<div class="three columns" style="text-color: black">
<h2 style="font-size: 180%; margin-bottom: 10pt">News </h2>
<p>Racket version 5.3.5 has been released.</p>
<p>Racket videos are now available.</p>
<p><a href="racketcon.html">RacketCon 2013</a> will be in September in Boston.</p>
</div>
</div>
<div class="row">
<p class="twelve columns centered" style="text-align:justify;font-size: 120%; margin-top: 20pt; ">
<a href="http://docs.racket-lang.org/quick/">Draw more pictures</a> or
<a href="http://docs.racket-lang.org/more/">build a web server from scratch</a>. Racket includes both
<a href="http://docs.racket-lang.org/">batteries</a> and a <a href="http://docs.racket-lang.org/drracket/">programming environment</a>,
so <a href="http://docs.racket-lang.org/getting-started/">get started</a>!
</p>
</div>
</div>
<!-- below code snippets -->
<div class="row">
<div class="ten columns centered">
<h3 >Go Further</h3>
</div>
</div>
<div class="row" id="growboxes">
<div class="four columns">
<div class="panetitle">Grow your Program</div><p>Racket's
<a href="http://docs.racket-lang.org/guide/intro.html#(part._.Interacting_with_.Racket)">interactive mode</a>
encourages experimentation, and quick scripts easily compose into
larger systems. Small scripts and large systems both benefit from
<a href="http://docs.racket-lang.org/guide/performance.html">native-code JIT compilation</a>.
When a system gets too big to keep in your head, you can add
<a href="http://docs.racket-lang.org/ts-guide/index.html">static types</a>.</p>
</div>
<div class="four columns">
<div class="panetitle">Grow your Language</div><p><a href="http://docs.racket-lang.org/guide/languages.html">Extend Racket</a> whenever you need to.
Mold it to better suit your tasks without sacrificing
<a href="http://docs.racket-lang.org/guide/dialects.html">interoperability</a> with existing
libraries and without having to modify the
<a href="http://docs.racket-lang.org/guide/intro.html">tool chain</a>. When less is more, you can
remove parts of a language or start over and build a new one.</p>
</div>
<div class="four columns">
<div class="panetitle">Grow your Skills</div><p>Whether you're just <a href="http://htdp.org/">starting out</a>, want to know more about
programming language <a href="http://www.plai.org/">applications</a> or <a href="http://redex.racket-lang.org/">models</a>,
looking to <a href="http://docs.racket-lang.org/continue/">expand your horizons</a>, or ready to dive into
<a href="learning.html">research</a>, Racket can help you become a better programmer
and system builder.</p>
</div>
</div>
</div>
<div class="row">
<div class="ten columns centered">
<h3 >Documentation</h3>
</div>
</div>
<div class="row">
<div class="five columns">
<div class="panetitle">For getting started</div>
<p><a href="http://docs.racket-lang.org/quick/"><strong>Quick</strong>:
An Introduction to Racket with
Pictures</a>
gives you a taste of Racket.
</p>
<p><a href="http://docs.racket-lang.org/more/"><strong>More</strong>:
Systems Programming with Racket</a>
dives
much deeper and much faster, showing how to build a complete
continuation-based web server.</p>
<p><a href="http://docs.racket-lang.org/guide/"><strong>Guide</strong>:
Racket</a> starts with a tutorial on Racket basics, and then it
describes the rest of the Racket language.
</p>
</div>
<div class="five columns push_two">
<div class="panetitle">For experienced Racketeers</div>
<p>
<a href="http://docs.racket-lang.org/reference/"><strong>Reference</strong>:
Racket</a> provides comprehensive coverage of all of Racket.
</p>
<p><a href="http://docs.racket-lang.org/continue/"><strong>Continue</strong>:
Web Applications in Racket</a>
describes how to use the
Racket <a href="http://docs.racket-lang.org/web-server/">web
server</a> to build dynamic web applications.
</p>
<p><a href="http://docs.racket-lang.org/pkg/"><strong>Package
Management</strong></a> explains how to install
<a href="https://pkg.racket-lang.org">packages</a>, and how to
build and distribute your own.</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="ten columns centered">
<h3>Community</h3>
</div>
</div>
<div class=row>
<div class="four columns">
<div class="panetitle">News & Events</div>
<p><a href="racketcon.html">RacketCon</a> ? the annual
Racket meeting, coming up in September. Previously
in <a href="http://con.racket-lang.org/2012">2012</a>
and <a href="http://con.racket-lang.org/2012">2011</a>.</p>
<p><a href="http://blog.racket-lang.org/">Blog</a>
? announcements, helpful hints, and thoughtful rants.</p>
<p><a href="http://twitter.com/#!/racketlang">Twitter</a>
? short bits of Racket news.</p>
</div>
<div class="four columns">
<div class="panetitle">Discussion</div>
<p><a href="http://lists.racket-lang.org/">Mailing lists</a>
? discussion for using and developing Racket.</p>
<p><a href="http://racket-lang.org/irc-chat.html">IRC</a> ?
Chat in the <tt style="background-color: #d8d8e8;"><big><strong>#racket</strong></big></tt> channel on
<a href="http://freenode.net"><tt>freenode.net</tt></a> ? an informal
discussion channel for all things related to Racket.
(<a href="https://botbot.me/freenode/racket/">Browse the logs</a>.)</p>
<p><a href="http://racket-lang.org/people.html">People</a> ?
The people behind Racket.</p>
</div>
<div class="four columns">
<div class="panetitle">Contributing</div>
<p><a href="https://github.com/plt/racket/">Code</a>
? the Racket source code on GitHub.</p>
<p><a href="https://github.com/plt/racket/wiki">Wiki</a> ?
Useful pages
include <a href="https://github.com/plt/racket/wiki/Intro-Projects">Intro
Projects</a>
and <a href="https://github.com/plt/racket/wiki/Videos">Videos</a>,
including tutorials, interviews, and more.</p>
<p><a href="http://www.cs.utah.edu/plt/snapshots">Snapshot builds</a> ?
The freshest versions of Racket.</p>
<p><a href="http://bugs.racket-lang.org">Bug reports</a> ?
File, query and maybe fix existing reports.</p>
</div>
</div>
<div class="row">
<div class="ten columns centered">
<h3>Learning</h3>
</div>
</div>
<div class="row">
<div class="row">
<div class="two columns image rounded" style="margin-top: 2pt">
<a href="http://www.htdp.org"><img src="img/htdp-cover.gif" /></a>
</div>
<div class="four columns">
<div class="panetitle">How to Design Programs</div>
<p>A principled approach to program design</p>
<ul>
<li>Teaching language support built-in to DrRacket</li>
<li>Aimed at the programming novice</li>
</ul>
</div>
<div class="four columns">
<div class="panetitle">Realm of Racket</div>
<p>Learn Racket and programming, one game at a time</p>
<ul>
<li>Sample game code comes with the Racket distribution</li>
<li>For those just starting out with Racket</li>
</ul>
</div>
<div class="two columns image rounded" style="margin-top: 2pt">
<a href="http://www.realmofracket.com"><img src="img/racket_cover_web.png" /></a>
</div>
</div>
</div>
<div class="row">
<div class="row">
<div class="two columns image rounded" style="margin-top: 2pt">
<a href="http://cs.brown.edu/~sk/Publications/Books/ProgLangs/2007-04-26/">
<img src="img/plai-cover.jpg" />
</a>
</div>
<div class="four columns">
<div class="panetitle">PLAI</div>
<p>Foundations of programming languages</p>
<ul>
<li>Understand the features that make languages tick</li>
<li>For undergraduates, graduate students, and experts</li>
</ul>
</div>
<div class="four columns">
<div class="panetitle">Semantics Engineering with PLT Redex</div>
<p>Lightweight automation for semantics</p>
<ul>
<li>Model your own programming language semantics</li>
<li>For the working language engineer</li>
</ul>
</div>
<div class="two columns image rounded" style="margin-top: 2pt">
<a href="http://redex.racket-lang.org/">
<img src="img/redex-cover.jpg" />
</a>
</div>
</div>
</div>
<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="/js/libs/jquery-1.9.1.min.js"><\/script>')</script>
<script src="js/libs/gumby.min.js"></script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
<!-- end scripts-->
</body>
</html>

View File

@ -0,0 +1,5 @@
#lang racket/base
(require "index.rkt" "download.rkt" "community.rkt" "learning.rkt" "help.rkt"
"new-name.rkt" "web-copyright.rkt")
(provide (rename-out [index main]) download community learning help)

View File

@ -0,0 +1,118 @@
#lang meta/web
(require syntax-color/module-lexer setup/xref
scribble/xref scribble/tag)
(provide code)
(define doc-root "http://docs.racket-lang.org/")
(define expand-namespace (make-base-namespace))
(define xref (load-collections-xref))
(define (code . strs)
(define str
(let* ([str (string-append* strs)]
[N (- 6 (length (regexp-match-positions* "\n" str)))])
(cond [(N . > . 0) (string-append str (make-string N #\newline))]
[(N . < . 0) (error 'code "too many lines in example: ~e" str)]
[else str])))
(define bstr (string->bytes/utf-8 (regexp-replace* #rx"(?m:^$)" str "\xA0")))
(define in (open-input-bytes bstr))
(define (substring* bstr start [end (bytes-length bstr)])
(bytes->string/utf-8 (subbytes bstr start end)))
(define e
(parameterize ([read-accept-reader #t] [current-namespace expand-namespace])
(expand (read-syntax 'prog (open-input-bytes bstr)))))
(define ids
(let loop ([e e])
(cond
[(and (identifier? e) (syntax-original? e))
(define pos (sub1 (syntax-position e)))
(define b (identifier-binding e))
(define imp?
(and (list? b)
(let-values ([(name base) (module-path-index-split (car b))])
(or name base))))
(define tag (and imp? (xref-binding->definition-tag xref e 0)))
(list (list (cond [(not imp?) 'id]
[(not tag) 'importid]
[else (define-values [p a]
(xref-tag->path+anchor
xref tag #:external-root-url doc-root))
(cons (if (eq? (car tag) 'form)
'linkimportform 'linkimportid)
(if a (format "~a#~a" p a) p))])
pos (+ pos (syntax-span e)) 1))]
[(syntax? e)
(append (loop (syntax-e e))
(loop (or (syntax-property e 'origin) null))
(loop (or (syntax-property e 'disappeared-use) null)))]
[(pair? e) (append (loop (car e)) (loop (cdr e)))]
[else null])))
(define (link-mod mp-stx priority #:orig? [always-orig? #f])
(if (or always-orig? (syntax-original? mp-stx))
(let ([mp (syntax->datum mp-stx)])
(define-values [p a]
(xref-tag->path+anchor xref
(make-module-language-tag mp)
#:external-root-url doc-root))
(if p
(list (let ([pos (sub1 (syntax-position mp-stx))])
(list (cons 'modpath (if a (format "~a#~a" p a) p))
pos (+ pos (syntax-span mp-stx)) priority)))
null))
null))
(define mods
(let loop ([e e])
(syntax-case e (module #%require begin)
[(module name lang (mod-beg form ...))
(append* (link-mod #'lang 2) (map loop (syntax->list #'(form ...))))]
[(#%require spec ...)
(append-map (λ (spec)
;; Need to add support for renaming forms, etc.:
(if (module-path? (syntax->datum spec))
(link-mod spec 2)
null))
(syntax->list #'(spec ...)))]
[(begin form ...) (append-map loop (syntax->list #'(form ...)))]
[else null])))
(define language
(let ([m (regexp-match #rx"^#lang ([-a-zA-Z/._+]+)" bstr)])
(if m
(link-mod #:orig? #t
(datum->syntax #f
(string->symbol (bytes->string/utf-8 (cadr m)))
(vector 'in 1 6 7 (bytes-length (cadr m))))
3)
null)))
(define raw-tokens
(let loop ([mode #f])
(define-values [lexeme type data start end backup-delta mode*]
(module-lexer in 0 mode))
(if (eof-object? lexeme)
null
(cons (list type (sub1 start) (sub1 end) 0) (loop mode*)))))
(define tokens
(sort (append ids mods language
(filter (λ (x) (not (eq? (car x) 'symbol)))
;; Drop #lang entry:
(cdr raw-tokens)))
(λ (a b) (or (< (cadr a) (cadr b))
(and (= (cadr a) (cadr b))
(> (cadddr a) (cadddr b)))))))
(let loop ([pos 0] [tokens tokens])
(cond
[(null? tokens) (list (substring* bstr pos))]
[(eq? (caar tokens) 'white-space) (loop pos (cdr tokens))]
[(= pos (cadar tokens))
(define style (caar tokens))
(define s (substring* bstr (cadar tokens) (caddar tokens)))
(cons (if (pair? style)
(a href: (cdr style) class: @list{code@(car style)}
rel: 'nofollow s)
(span class: @list{code@style} s))
(loop (caddar tokens) (cdr tokens)))]
[(> pos (cadar tokens)) (loop pos (cdr tokens))]
[else (cons (substring* bstr pos (cadar tokens))
(loop (cadar tokens) tokens))])))

View File

@ -0,0 +1,47 @@
#lang meta/web
(require "resources.rkt" "people.rkt" "irc.rkt"
"../minis/lists.rkt" "../minis/bugs.rkt"
"../stubs/blog.rkt" "../stubs/git.rkt"
(prefix-in pre: "../stubs/pre.rkt"))
(provide community)
(define community
@page[#:window-title "Racket Community Resources" #:part-of 'community
#:description
@'{Racket-related community resources: mailing lists, IRC channel, @;
resources for developers, RacketCon, blog, and more.}]{
@mailing-lists-quick
@irc-quick
@parlist[@strong{RacketCon}
@text{@-rcon[] is our annual conference:
@-rcon[2012] and @-rcon[2011].}]
@parlist[@strong{PLT Design Inc.}
@text{@blog announcements, helpful hints, and thoughtful rants.}
@text{@a[href: "http://twitter.com/#!/racketlang"]{Twitter}
random Racket bits.}
@text{@people the people behind Racket.}]
@parlist[@strong{Wiki}
@text{@-wiki[#f]{Wiki pages}, including:}
@text{@-wiki{Intro Projects} Find a project to contribute,}
@text{@-wiki{Videos} Watch tutorials, interviews, and more.}]
@parlist[@strong{Development}
@text{@git (also available on
@a[href: "http://github.com/plt/racket/"]{GitHub}).}
@text{@pre:installers and @pre:index{more}.}
@text{@bug-reports create and query existing reports.}]
@parlist[@strong{Support}
@text{
Thanks to @a[href: "http://www.nsf.gov/"]{the NSF},
@a[href: "http://www.darpa.mil/"]{DARPA},
the
@a[href: "http://www.ed.gov/FIPSE/"]{
Fund for the Improvement of Postsecondary Education (FIPSE)}
at the @a[href: "http://www.ed.gov/"]{US Department of Education},
the @a[href: '("http://www.exxonmobil.com/Corporate/"
"community_foundation.aspx")]{Exxon Foundation},
CORD,partners of the Academy of Information Technology,
@a[href: "http://microsoft.com"]{Microsoft},
@a[href: "http://mozilla.org"]{Mozilla},
and @a[href: "http://google.com"]{Google}
for their generous support over the years.}]})

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@ -0,0 +1,42 @@
#lang meta/web
(require "resources.rkt" "../download/download-pages.rkt")
(provide download)
(define download
@page[#:link-title "Download" #:window-title "Download Racket"
#:file "download/" #:part-of 'download]{
@(render-download-page)})
(define images (list (copyfile (in-here "download.png"))
(copyfile (in-here "download-dark.png"))))
(provide download-button)
(define (download-button)
@text{
@script/inline[type: "text/javascript"]{
@; Don't load all images here -- it causes a delay when loading the
@; page instead, do it only when needed, and also set a timer to do it
@; after loading the page. This makes it so that there's almost never
@; a delay when loading the page, and also no delay when switching the
@; image.
var rollovers = false, the_download_button = false;
function init_rollovers() {
if (!rollovers) {
rollovers = [ new Image(), new Image() ];
rollovers[0].src = "@(car images)";
rollovers[1].src = "@(cadr images)";
the_download_button = document.getElementById("download_button");
}
}
function set_download_image(n) {
if (!rollovers) init_rollovers();
the_download_button.src = rollovers[n].src;
}
setTimeout(init_rollovers, 400);
}
@a[href: (url-of download)
onmouseover: "set_download_image(1);"
onmouseout: "set_download_image(0);"]{
@img[id: "download_button" src: (car images) style: "border-width: 0;"
alt: "Download Racket" title: "Download Racket"]}})

View File

@ -0,0 +1,38 @@
#lang meta/web
(require "resources.rkt" "community.rkt")
(provide help)
(define help
@page[#:link-title "Need Help?"]{
@parlist[@strong{Don't Panic!}
@text{Racket has a variety of resources designed to help you
with any problems you may have.}]
@parlist[@strong{Help Desk}
@text{Your first stop should always be with the help system that's
built into Racket and available from DrRacket's help menu
@strong{or by pressing F1 with the cursor on a search term}.
This documentation is customized for your installation, and
may include documentation for optional packages you've
installed. As a second line of defense, the documentation
for the core of the most recent version of Racket is
available @-docs{from this web site}.}
@text{Not sure what to search for? The documentation includes a
@guide{guide} (also located in your local copy of the
documentation) that provides a narrative introduction to many
of Racket's features.}]
@parlist[@strong{Learning how to Program}
@text{Try going through @|-htdp|.}]
@parlist[@strong{Searching the Web}
@text{Your favorite search engine may well provide answers for many
of your questions, in particular, try to search through
Racket questions on
@a[href: "http://stackoverflow.com/questions/tagged/racket"]{
stackoverflow}.}]
@parlist[@strong{The Mailing List}
@text{The @tt|{users@racket-lang.org}| mailing list is a great
source for answers to questions when the above resources
don't pan out@";" sign up for it in the @community area of
the website.}]
@br
@text{Thanks for using Racket!}})

View File

@ -0,0 +1,542 @@
#lang meta/web
(require "resources.rkt" "code.rkt" "download.rkt" "learning.rkt")
(define (doc path . text)
(apply a href: (list "http://docs.racket-lang.org/" path) text))
(struct example (code desc))
(define ((example-with-help . help) code desc)
(example code (list desc help)))
(define generic-example
@example-with-help{
@p{To run the example, install Racket, start DrRacket, paste the example
program into the top area in DrRacket, and click the Run button.
Alternatively, save the program to a file and run @tt{racket} on the
file.}})
(define cmdline-example
@example-with-help{
@p{This example is a command-line script. To run the example, install
Racket, paste the example program into a file, and run @tt{racket} on
the file with command-line arguments after the filename. Alternatively,
for a Unix installation, you can add @tt{#!/usr/bin/env racket} at the
top and make the file executable, and then you can run the file
directly.}})
(define scribble-example
@example-with-help{
@p{To run the example, install Racket, start DrRacket, and paste the
example program into the top area in DrRacket. When a program in a
Scribble language is opened in DrRacket, a @b{Scribble HTML} button
appears for rendering the document to HTML. Click it.}})
(define graphical-example
@example-with-help{
@p{To run the example, install Racket, start DrRacket, paste the example
program into the top area in DrRacket, and click the Run button.}})
(define desc div)
(define (elemcode . strs) (apply tt strs))
(define examples
@; --- Each example here should be at most 7 lines long ------------
(list
@; Candidates for initial example: --------------------------------
(list
(generic-example ; -----------------------------------------------
@code{#lang racket
;; Finds Racket sources in all subdirs
(for ([path (in-directory)])
(when (regexp-match? #rx"[.]rkt$" path)
(printf "source file: ~a\n" path)))}
@desc{The @elemcode{in-directory} function constructs a sequence that
walks a directory tree (starting with the current directory, by default)
and generates paths in the tree. The @elemcode{for} form binds
@elemcode{p} to each path in the sequence, and @elemcode{regexp-match?}
applies a pattern to the path.})
(generic-example ; -----------------------------------------------
@code{#lang web-server/insta
;; A "hello world" web server
(define (start request)
(response/xexpr
'(html
(body "Hello World"))))}
@desc{This example implements a web server using the
@elemcode{web-server/insta} language. Each time a connection is made to
the server, the @elemcode{start} function is called to get the HTML to
send back to the client.})
(generic-example ; -----------------------------------------------
@code{#lang racket ; An echo server
(define listener (tcp-listen 12345))
(let echo-server ()
(define-values (in out) (tcp-accept listener))
(thread (lambda () (copy-port in out)
(close-output-port out)))
(echo-server))}
@desc{Racket makes it easy to use TCP sockets and spawn threads to handle
them. This program starts a server at TCP port 12345 that echos
anything a client sends back to the client.})
(generic-example ; -----------------------------------------------
@code{#lang racket
;; Report each unique line from stdin
(let ([saw (make-hash)])
(for ([line (in-lines)])
(unless (hash-ref saw line #f)
(displayln line))
(hash-set! saw line #t)))}
@desc{Uses a hash table to record previously seen lines. You can run this
program in DrRacket, but it makes more sense from the command line.}))
@; Additional examples: -------------------------------------------
(list
(graphical-example ; ---------------------------------------------
@code{#lang racket ; A picture
(require 2htdp/image)
(let sierpinski ([n 8])
(if (zero? n)
(triangle 2 'solid 'red)
(let ([t (sierpinski (- n 1))])
(freeze (above t (beside t t))))))}
@desc{The @elemcode{2htdp/image} library provides easy-to-use functions
for constructing images, and DrRacket can display an image result as
easily as it can display a number result. In this case, a
@elemcode{sierpinski} function is defined and called (at the same time)
to generate a Sierpinski triangle of depth 8.})
(graphical-example ; ---------------------------------------------
@code{#lang racket/gui ; A GUI guessing game
(define f (new frame% [label "Guess"]))
(define n (random 5)) (send f show #t)
(define ((check i) btn evt)
(message-box "." (if (= i n) "Yes" "No")))
(for ([i (in-range 5)])
(make-object button% (format "~a" i) f (check i)))}
@desc{This simple guesing game demonstates Racket's class-based GUI
toolkit. The @elemcode{frame%} class implements a top-level window, and
@elemcode{button%} obviously implements a button. The @elemcode{check}
function defined here produces an function that is used for the button's
callback action.})
(generic-example ; -----------------------------------------------
@code{#lang racket ; Simple web scraper
(require net/url net/uri-codec)
(define (let-me-google-that-for-you str)
(let* ([g "http://www.google.com/search?q="]
[u (string-append g (uri-encode str))]
[rx #rx"(?<=<h3 class=\"r\">).*?(?=</h3>)"])
(regexp-match* rx (get-pure-port (string->url u)))))}
@desc{Add a call to @elemcode{let-me-google-that-for-you} to get a list of
search results.})
(cmdline-example ; -----------------------------------------------
@code{#lang racket
;; A dice-rolling command-line utility
(command-line
#:args (dice sides)
(for ([i (in-range (string->number dice))])
(displayln
(+ 1 (random (string->number sides))))))}
@desc{Playing a game but no dice on hand? Let Racket roll for you. The
@elemcode{command-line} form makes sure that the right number of
arguments are provided and automatically implements the @tt{--help}
switch.})
(generic-example ; -----------------------------------------------
@code{#lang racket
;; Print the Greek alphabet
(for ([i (in-range 25)])
(displayln
(integer->char
(+ i (char->integer #\u3B1)))))}
@desc{The only reason we use the encoded form of a character
@elemcode{#\u3B1} instead of the more direct form @elemcode{#\α} is that
we don't trust your browser to render it correctly. DrRacket is
perfectly happy with @elemcode{#\α}.})
(graphical-example ; ---------------------------------------------
@code{#lang htdp/bsl ; Any key inflates the balloon
(require 2htdp/image) (require 2htdp/universe)
(define (balloon b) (circle b "solid" "red"))
(define (blow-up b k) (+ b 5))
(define (deflate b) (max (- b 1) 1))
(big-bang 50 (on-key blow-up) (on-tick deflate)
(to-draw balloon 200 200))}
@desc{Racket's mission includes education at all levels. This program
uses the @elemcode{htdp/bsl} teaching language, the
@elemcode{2htdp/image} library for creating pictures in the teaching
languages, and the @elemcode{2htdp/universe} library for interactive
animations.})
(generic-example ; -----------------------------------------------
@code{#lang lazy
;; An infinite list:
(define fibs
(list* 1 1 (map + fibs (cdr fibs))))
@||
;; Print the 1000th Fibonacci number:
(print (list-ref fibs 1000))}
@desc{And now for something completely different. The @elemcode{lazy}
language is more like Haskell than Lisp, so feel free to build an
infinite list and look at only part of it.})
(generic-example ; -----------------------------------------------
@code{#lang typed/racket
;; Using higher-order occurrence typing
(define-type SrN (U String Number))
(: tog ((Listof SrN) -> String))
(define (tog l)
(apply string-append (filter string? l)))
(tog (list 5 "hello " 1/2 "world" (sqrt -1)))}
@desc{Racket's type system is designed to let you add types after you've
worked for a while in untyped mode even if your untyped program
wouldn't fit nicely in a conventional type system.})
(scribble-example ; ----------------------------------------------
@code|{#lang scribble/base
@; Generate a PDF or HTML document
@title{Bottles --- @italic{Abridged}}
@(apply itemlist
(for/list ([n (in-range 100 0 -1)])
@item{@(format "~a" n) bottles.}))}|
@desc{This program uses the @elemcode{scribble/base} language for
generating documents using a prose-friendly syntax.})
(graphical-example ; ---------------------------------------------
@code{#lang racket ; draw a graph of cos
(require plot) ; and deriv^3(cos)
(define ((deriv f) x)
(/ (- (f x) (f (- x 0.001))) 0.001))
(define (thrice f) (lambda (x) (f (f (f x)))))
(plot (list (function ((thrice deriv) sin) -5 5)
(function cos -5 5 #:color 'blue)))}
@desc{This program uses the @elemcode{plot} library to draw plots of
functions. Note that the plots are actual value, which DrRacket shows
in graphical form.})
(generic-example ; -----------------------------------------------
@code{#lang racket ; Sending email from racket
(require net/sendmail)
(sleep (* (- (* 60 4) 15) 60)) ; 4h - 15m
(send-mail-message
(getenv "EMAIL") "Parking meter alert!"
(list (getenv "EMAIL")) null null
'("Time to go out and move your car."))}
@desc{Racket comes with plenty of libraries.})
(generic-example ; -----------------------------------------------
@code{#lang scheme/base ; Simple use of the FFI
(require ffi/unsafe)
(define mci-send-string
(get-ffi-obj "mciSendStringA" "Winmm"
(_fun _string [_pointer = #f] [_int = 0]
[_pointer = #f] -> [ret : _int])))
(mci-send-string "play sound.wav wait")}
@desc{Using the FFI means that you're not limited to using Racket
libraries: pulling out a foreign function is easy, and can even be done
dynamically on the REPL.})
;; Is this effective without any highlights?
(generic-example ; -----------------------------------------------
@code{#lang datalog
ancestor(A, B) :- parent(A, B).
ancestor(A, B) :-
parent(A, C), D = C, ancestor(D, B).
parent(john, douglas).
parent(bob, john).
ancestor(A, B)?}
@desc{Racket is useful for building other languages. This example uses
the pre-packaged Racket implementation of Datalog, a logic programming
language. If you use this from DrRacket, you'll see that it provides
proper highlighting, Check Syntax, and a Datalog-specific REPL.})
#; ; Not easy to present something like this.
(generic-example ; -----------------------------------------------
@code{#lang racket
(provide (except-out (all-from-out racket)
#%top #%app)
(rename-out [top #%top] [app #%app]))
(define-syntax-rule (top . x) 'x)
(define-syntax-rule (app f . xs)
(if (hash? f) (hash-ref f . xs) (f . xs)))
}
@desc{TODO, and use this example:
@pre{#lang s-exp "foo"
(define x (make-hasheq))
(hash-set! x A B)
(x A)}})
)))
(define blurb "Racket is a programming language")
(provide set-news-flashes!)
(define news-flashes #f)
(define (set-news-flashes! . text)
(when news-flashes (error 'set-news-flashes! "text already set"))
(set! news-flashes text))
(provide index)
(define index
(page #:link-title "About" #:window-title "The Racket Language"
#:description
@'{Racket is a modern programming language in the Lisp/Scheme family, @;
suitable for a wide range of applications. @;
Racket provides a rich language extension API, the DrRacket @;
integrated development environment, and many batteries-included @;
libraries.}
#:extra-headers @list{@meta[name: "robots" content: "NOODP"]
@(lazy more.css)}
@div[class: 'leftpane]{
@span[style: "font-size: large; font-weight: bold;"]{Racket}
is a programming language.
@(and news-flashes (list br (div style: "width: 100%;" news-flashes)))}
@div[class: 'downloadbutton]{@download-button}
@div[class: 'aboutpane]{
@div[class: 'panetitle]{Start Quickly}
@div{@(apply slideshow-panel examples)}
@p{@doc["quick/"]{Draw more pictures} or
@doc["more/"]{build a web server from scratch}. Racket includes both
@doc[""]{batteries} and a @doc["drracket/"]{programming environment},
so @doc["getting-started/"]{get started}!}}
@((λ xs (table class: 'threepanes
(tr (map (λ (x) (td (div class: 'panetitle (car x)) (cdr x)))
xs))))
(list "Grow your Program"
@p{Racket's
@doc["guide/intro.html#(part._.Interacting_with_.Racket)"]{
interactive mode}
encourages experimentation, and quick scripts easily compose into
larger systems. Small scripts and large systems both benefit from
@doc["guide/performance.html"]{native-code JIT compilation}.
When a system gets too big to keep in your head, you can add
@doc["ts-guide/index.html"]{static types}.})
(list "Grow your Language"
@p{@doc["guide/languages.html"]{Extend Racket} whenever you need to.
Mold it to better suit your tasks without sacrificing
@doc["guide/dialects.html"]{interoperability} with existing
libraries and without having to modify the
@doc["guide/intro.html"]{tool chain}. When less is more, you can
remove parts of a language or start over and build a new one.})
(list "Grow your Skills"
@p{Whether you're just @-htdp{starting out}, want to know more about
programming language @-plai{applications} or @-redex{models},
looking to @continue{expand your horizons}, or ready to dive into
@learning{research}, Racket can help you become a better programmer
and system builder.}))))
(define index2
@page{
new stuff here
})
(define (slideshow-panel l1 l2)
(define l (append l1 l2))
(define button-ids+labels '())
;; this separator is shown in non-CSS browsers (e.g., textual ones)
(define invisible-separator @div[style: "display: none;"]{@br{}@hr{}})
(define (button txt tip id onclick)
(set! button-ids+labels (cons (cons id txt) button-ids+labels))
(a href: "#" id: id onclick: (list onclick "; return false;") title: tip
nbsp)) ; empty, filled by JS code, so JS-less browsers won't see it
(div class: 'slideshow
(div class: 'buttonpanel
@button["<" "Previous example" 'rewindbutton "rewind_show()"]
@button[">" "Next example" 'advancebutton "advance_show()"]
@button["?" "Explain this code" 'helpbutton "set_help(!help_showing)"]
(div class: 'hiddenhelp id: "helppanel" style: "display: none;"
(div class: 'helpcontent
@button["close" "Close help" 'closebutton "set_help(false)"]
(div id: 'helpdesc "") ; placeholder for the descriptions (see below)
@div[class: 'helptext]{
Form and function names in the code are hyperlinked to
documentation, so click on them for more information.})))
(for/list ([elem (in-list l)] [pos (in-naturals)])
@list{
@invisible-separator
@pre[class: 'slideshowframe id: @list{frame@pos}
style: @list{display: @(if (zero? pos) "block" "none")@";"}]{
@(example-code elem)}@;
@; have the descriptions appear in a logical place and then ...
@div[id: @list{helpframe@pos} style: "display: none;"]{
@(example-desc elem)}})
@invisible-separator
@script/inline[type: "text/javascript"]{
@; ... move them to a convenient-for-display place
var helpdesc = document.getElementById("helpdesc");
for (var i=0@";" i<@(length l)@";" i++) {
var help_item = document.getElementById("helpframe"+i);
help_item.parentNode.removeChild(help_item);
helpdesc.appendChild(help_item);
}
var showing = 0, help_showing = false;
var frame_s=new Array(), helpframe_s=new Array();
for (var i=0@";" i<@(length l)@";" i++) {
frame_s[i] = document.getElementById("frame" + i).style;
helpframe_s[i] = document.getElementById("helpframe" + i).style;
}
var advbutton_s = document.getElementById("advancebutton").style;
var rewbutton_s = document.getElementById("rewindbutton").style;
function set_display(disp) {
frame_s[showing].display = disp;
helpframe_s[showing].display = disp;
}
function change_show_to(new_showing) {
set_display("none");
showing = new_showing;
set_display("block");
rewbutton_s.color = (showing==0) ? "#aaaaaa" : "#444444";
advbutton_s.color =
(showing==@(sub1 (length l))) ? "#aaaaaa" : "#444444";
}
function advance_show() {
if (showing < @(sub1 (length l))) change_show_to(showing+1);
}
function rewind_show() {
if (showing > 0) change_show_to(showing-1);
}
var help_panel_s = document.getElementById("helppanel").style;
function set_help(show) {
help_panel_s.display = show ? "block" : "none";
help_showing = show;
}
change_show_to(Math.floor(Math.random() * @(length l1)));
@; display button texts now, instead of making it part of the html,
@; so it's not shown on JS-less browsers
@(add-newlines
(for/list ([id+label (in-list button-ids+labels)])
(let ([id (car id+label)] [label (cdr id+label)])
@list{document.getElementById("@id").textContent = "@label"@";"})))
}))
;; TODO
;; (define screenshots
;; (let ([image (copyfile (in-here "screenshot.jpg"))])
;; @a[href: screenshots]{
;; @img[src: image alt: "[screenshots]" border: 0
;; style: "margin-bottom: 2px;"]@;
;; @|br|@small{Screenshots}}))
;; (define tour-video
;; (page #:title "DrRacket Tour" #:file "tour.html"
;; (define (center . body)
;; (table align: 'center style: "margin: 3em 0em;"
;; (tr (td align: 'center body))))
;; ;; someone posted a comment saying that adding "&fmt=18" to the url
;; ;; shows a higher resolution video, but it looks exactly the same.
;; (define url "http://www.youtube.com/v/vgQO_kHl39g&hl=en")
;; @center{
;; @object[type: "application/x-shockwave-flash" data: url
;; width: (round (* 3/2 425)) height: (round (* 3/2 344))]{
;; @param[name: "movie" value: url]}}))
;; resources that are specific to the front page
(define loud (copyfile (in-here "loud.png")))
(define more.css
@plain[#:referrer (λ (url) (link rel: "stylesheet" type: "text/css"
href: url title: "default"))]{
.bodycontent {
background-image: url('@loud');
background-repeat: no-repeat;
background-position: center top;
}
.leftpane {
font-size: medium;
float: left;
width: 20%;
}
.aboutpane {
width: 56%;
margin-right: auto;
margin-left: auto;
}
.panetitle {
width: 100%;
font-size: large;
font-weight: bold;
color: #dd0000;
}
.threepanes {
width: 100%;
}
.threepanes td {
vertical-align: top;
margin: auto;
width: 30%;
padding: 0.5em;
}
.slideshow {
position: relative;
}
.slideshowframe {
height: 17ex;
}
.buttonpanel {
display: block;
position: absolute;
left: 100%;
top: -3ex;
width: 3em;
margin: 0em 0em 0em -5em;
}
#advancebutton, #rewindbutton, #helpbutton, #closebutton {
text-decoration: none;
border: 1px solid #ddddd;
font-weight: bold;
color: #44444;
background-color: #eeeee;
padding: 0px 1px 0px 1px;
}
#advancebutton, #rewindbutton {
margin: 0px 1px 0px 1px;
}
#helpbutton {
margin: 0px 1px 0px 10px;
}
.hiddenhelp {
width: 0em;
margin-left: 2em;
}
.helpcontent {
width: 20em;
background-color: #ffffee;
padding: 10px;
margin-top: 3px;
border: 1px solid black;
}
#closebutton {
font-size: small;
margin-bottom: 1em;
}
.helptext, #helpdesc {
margin-top: 0.5em;
}
.helptext {
font-size: small;
}
.downloadbutton {
position: relative;
float: right;
}
@;
.codecomment {
color: #c2741f;
}
.codeparenthesis {
color: #843c24;
}
.codeconstant, .codestring {
color: #228b22;
}
.codeid, .codemodpath {
color: #262680;
}
.codeimportid {
color: blue;
}
.codeimportform {
font-weight: bold;
}
.codelinkimportid {
color: blue;
text-decoration: none;
}
.codelinkimportform {
font-weight: bold;
color: black;
text-decoration: none;
}
.codelinkimportid:hover {
text-decoration: none;
}
.codelinkimportform:hover {
text-decoration: none;
}
.codemodpath:hover {
text-decoration: none;
}})

View File

@ -0,0 +1,42 @@
#lang meta/web
(require "resources.rkt")
(define webchat-link
"http://webchat.freenode.net?channels=racket&uio=OT10cnVlJjExPTIzNg6b")
(define irc-chat
@page[#:title "IRC" #:part-of 'community]{
@iframe[src: webchat-link width: "100%" height: "400"]})
(define log-header+footer
(lazy (regexp-split #rx"{{{BODY}}}"
(xml->string @page[#:id 'browse-downloads
#:html-only #t
#:part-of 'community
"{{{BODY}}}"]))))
(define header @plain[#:file "irc-logs/dummy/HEADER.html" #:newline #f
(car (force log-header+footer))])
(define footer @plain[#:file "irc-logs/dummy/README.html" #:newline #f
(cadr (force log-header+footer))])
(provide irc-logs)
(define irc-logs
(let ([base "/home/scheme/irc-logs"])
(define t (make-hash))
(λ (type . text)
(hash-ref! t type (λ() (a href: (symlink (format "~a/~a" base type)
(format "irc-logs/~a" type))
text))))))
(void (irc-logs ".htaccess"))
(provide irc-quick)
(define (irc-quick)
(define (chan name) @TT{@big{@strong{#@name}}})
@parlist[@strong{Discussion Channel}
@text{@irc-chat{Chat on IRC} in the @chan{racket} channel on
@a[href: "http://freenode.net"]{@tt{freenode.net}} an informal
discussion channel for all things related to Racket.
(@irc-logs['racket]{Browse the logs}.)
There is also @chan{racket-dev} (@irc-logs['racket-dev]{logs}), a channel
for notification bots.}])

View File

@ -0,0 +1,102 @@
#lang meta/web
(require "resources.rkt" "people.rkt" "techreports.rkt" "old-techreports.rkt")
(provide learning)
(define learning
@page[#:window-title "Racket Learning" #:part-of 'learning
#:description
'@{Racket-related learning resources. Introductions to Racket, @;
the Racket Guide, Computer Science textbooks that use Racket, @;
outreach programs, and graduate studies.}]{
@parlist[@strong{Resources for Learning}
(apply parlist @text{Documentation for getting started:} intros)
@text{@-htdp a textbook for introductory programming, but also
worthwhile for experience programmers who are new to “functional
programming.”}
@text{@-plai a textbook on programming languages.}]
@parlist[@strong{Videos}
@text{See the @-wiki["Videos"] page at the @|-wiki|.}]
@parlist[
@strong{Outreach}
@text{@-pbd a workshop to train teachers using @-htdp in the
classroom.}
@text{@-bootstrap a curriculum for middle-school students.}]
@(apply parlist @strong{PLT Publications}
(cons techreports
(for*/list ([place (in-list all-places)]
[pubs (in-value (place-pubs place))]
#:when pubs)
@a[href: pubs]{@(place-name place)})))
@parlist[@strong{Graduate Study}
@text{We welcome applications from students interested in
@|graduate-study|.}]})
(define graduate-study
@page[#:file "common-plt-app.html" #:part-of 'learning]{
@(define (box-style border-width color)
@list{border: @|border-width|px solid black; padding: 5px; @;
background: @|color|@";"})
@(define place-names
(add-between
(sort (map (λ (p)
(regexp-replace #rx", [A-Z][A-Z]$" (place-location p) ""))
all-places)
string<?)
" / "))
@(define responsible-people
(add-between
(for/list ([person (sort (map (compose car place-people) all-places)
string<? #:key person-name)])
@a[href: (person-url person)]{
@(regexp-replace #rx" .*$" (person-name person) "")})
", "))
@h1{Graduate Study with PLT}
@p{An open letter to graduate applicants:}
@div[style: (box-style 3 "#dddddd")]{
@p*{
Dear Prospective Graduate Student,
@|br br|
Thank you for your interest in working with PLT. We get several
inquiries every year from students interested in working with one or more
of us. We're flattered and, of course, interested in your applications.
Because you are more interested in PLT than in our specific institutions,
we have created the following common application form. By filling it in
once, you can automatically apply to all current PLT institutions.
@~ @|style: (box-style 1 "#bbbbbb")|@;
Yes, we know you don't like @place-names (circle those applicable). But
we like them, or we wouldn't be living there. Think about the message
you're sending by rejecting our choices. Moreover, we think very highly
of our colleagues—more highly than we think of your judgment in this
matter—so for your own good, we're going to forward your application to
them anyway.
@~ How many years have you programmed in Scheme?
@~ How many years have you programmed in Racket?
@~ If the two numbers above are not identical, justify.
@~ How many Racket Web applications have you written?
@~ What problems did you find with the Racket Web server in the process?
Please list bug report numbers.
@~ Which wheels did you inadvertently reinvent?
@~ Do you prefer your calculi Classic or Featherweight?
@~ Should types be intervals or ideals?
@~ In your opinion, which Barendregt proof has the highest hours spent
understanding-to-symbols ratio?
@~ Which is your favorite combinator?
@~ Thank you for your interest. Don't be a cat squandering the popcorn.
@~ @|align: 'right|
—Shriram, Outreach Coordinator, PLT}}
@p{Seriously, we @em{do} enjoy working with graduate students. If you are
inspired by the PLT project and want to drive the next generation of
innovation, you should strongly consider graduate study with us. We
look forward to hearing from you. All of us, no matter where we may
live.}
@p[align: 'right]{—@responsible-people}})
;; redirection page for the previous name of this page
(define outreach+research
@page[#:part-of 'learning
#:title "Outreach & Research"
#:link-title @list{Outreach@|nbsp|&@|nbsp|Research}
#:extra-headers
@meta[http-equiv: "refresh" content: "0;url=learning.html"]]{
Moved.})

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -0,0 +1,171 @@
#lang meta/web
(require "resources.rkt")
(define name i)
(define (url str) (tt (a href: str str)))
(define styles
@style/inline{
.nestedheading {
text-align: center;
font-weight: bold;
font-size: large;
}
.nested {
width: 80%;
margin-left: auto;
margin-right: auto;
margin-top: 1em;
margin-bottom: 1em;
}
.faqsection {
margin-left: auto;
margin-right: auto;
margin-top: 2em;
width: 90%;
}
.faqques {
font-weight: bold;
margin-top: 1em;
margin-bottom: 1em;
}
.faqans {
margin-left: 1em;
}})
(define ((FAQ tag . ques) . answer)
@div[class: 'faqentry]{
@div[class: 'faqques]{@a[name: tag]{@ques}}
@div[class: 'faqans]{@answer}})
(define (heading . text)
(apply div class: 'nestedheading text))
(define (nested . text)
(apply div class: 'nested text))
(define new-name
@page[#:title "From PLT Scheme to Racket"]{
@styles
@heading{PLT Scheme is a Racket}
@nested{Sure, it has parentheses, uses the keyword @tt{lambda}, provides
lexical scope, and emphasizes macros but don't be fooled. PLT Scheme
is no minimalist embodiment of 1930s math or 1970s technology. PLT
Scheme is a cover for a gang of academic hackers who want to fuse
cutting-edge programming-language research with everyday programming.
They draw you in with the promise of a simple and polite little Scheme,
but soon you'll find yourself using modules, contracts, keyword
arguments, classes, static types, and even curly braces.}
@heading{Racket is a Scheme}
@nested{Racket is still a dialect of Lisp and a descendant of Scheme. The
tools developed by PLT will continue to support R5RS, R6RS, the old
@tt{mzscheme} environment, Typed Scheme, and more. At the same time,
instead of having to say “PLT's main variant of Scheme, programmers can
now simply say “Racket” to refer to the specific descendant of Scheme
that powers PLT's languages and libraries.}
@div[class: 'faqsection]{
@heading{Anticipated Questions}
@@FAQ['why]{Why change the name?}{
@p*{
The @name{Scheme} part of the name @name{PLT Scheme} is misleading, and
it is often an obstacle to explaining and promoting PLT research and
tools.
@~
For example, when you type “scheme” into Google, the first hit is a
Wikipedia entry written from an R5RS perspective. That's appropriate
for a Wikipedia page on Scheme, but it's not a good introduction to PLT
Scheme. As long as we call our language @name{Scheme}, we struggle to
explain our language, and we are usually forced to start the
explanation with a disclaimer. At the same time, to the degree that
the PLT community has defined @name{Scheme} through market share,
publications, and educational outreach, we interfere with everyone
else's ability to define @name{Scheme} and many have a valid claim to
that ability.
@~
By switching to @name{Racket}, we expect to resolve this communication
problem.}}
@@FAQ['what]{What will the change look like?}{
@p*{
@name{DrScheme} becomes @name{DrRacket}. The @tt{mzscheme} executable
becomes @tt{racket}, and @tt{mred} becomes @tt{gracket} (following a
common convention for “GUI @tt{racket}). We change each @tt{#lang
scheme} to @tt{#lang racket} in the Racket distribution, although
@tt{#lang scheme} will be supported for backward compatibility. The
@url{http://plt-scheme.org} site will be replaced by
@url{http://racket-lang.org}. The @tt{plt-scheme} mailing list becomes
the @tt{racket} mailing list (@tt|{users@racket-lang.org}|).
@~
The Racket site and documentation will note that Racket is a descendant
of Scheme, but most current uses of the word “Scheme” (which implicitly
mean PLT Scheme) will be replaced by “Racket.”
@~
Racket programmers are @name{Racketeers}, of course.}}
@@FAQ['scheme]{Does this mean that PLT will no longer implement Scheme?}{
@p*{
There will be little difference between the current @tt{#lang scheme}
and the new @tt{#lang racket}, but the latter will become the preferred
form.
@~
In addition, PLT will continue to support standards such as R5RS and
R6RS. The transition from/to various Scheme languages to/from Racket
will be as easy/difficult as before.}}
@@FAQ['transition]{What happens to all of the old programs, scripts,
address books, bookmarks, papers, etc. that refer to @name{PLT Scheme}
instead of @name{Racket}?}{
@p*{
Old executables, web sites, mailing addresses, and module names will
forward to the new ones. We will work to make the transition as
painless as possible and to preserve old references for as long as
possible.}}
@@FAQ['edu]{How can I tell my department that we should teach with Racket
instead of Scheme? They've never heard of @name{Racket}.}{
@p*{
If you felt comfortable claiming that PLT Scheme was Scheme before,
then you can still say that you want to teach with Scheme, even if the
environment is called @name{DrRacket}. Racket is a descendant of
Scheme, just like PLT Scheme was.}}
@@FAQ['brand]{Aren't you worried that you will lose brand recognition by
switching from the name @name{Scheme} to @name{Racket}?}{
@p*{
Yes. Nevertheless, we think the long-term benefit of a new name will
outweigh the short-term difficulties of changing.}}
@@FAQ['plt]{Instead of picking a new name, why not just call the language
@name{PLT}?}{
@p*{
Some of us tried that, informally. It felt awkward, because we use
@name{PLT} to refer to a group of people, and because we have used
@name{PLT} as a modifier for @name{Scheme} and other nouns. Switching
the language name from one noun to another sounds better, it's clearer,
and it's easier to explain.}}
@@FAQ['suggestions]{Couldn't you find a better name?
@name{[Insert name here]} would be better.}{
@p*{
Thank you for the suggestion. The name @name{Racket} meets some basic
criteria: it isn't used already, it's easy to pronounce and spell, and
it has a vague connection to the word “scheme.” Mostly, though, we
just like it.}}
}})

View File

@ -0,0 +1,482 @@
#lang meta/web
;; Old style TR entries
;; This code is intended only to keep the old techreports/ page up for
;; old links.
(require "resources.rkt" "techreports.rkt" "people.rkt"
(prefix-in - version/utils))
;; ----------------------------------------------------------------------------
;; Data
(define last-old-tr "4.9")
;; This list is fixed to these versions (since this is an old page, no
;; need to update with new versions)
(define versions+dates
'(["4.2.5" "April" "2010"]
["4.2.4" "January" "2010"]
["4.2.3" "December" "2009"]
["4.2.2" "October" "2009"]
["4.2.1" "July" "2009"]
["4.2" "June" "2009"]
["4.1.5" "March" "2009"]
["4.1.4" "January" "2009"]
["4.1.3" "November" "2008"]
["4.1.2" "October" "2008"]
["4.1.1" "October" "2008"]
["4.1" "August" "2008"]
["4.0.2" "July" "2008"]
["4.0.1" "June" "2008"]
["4.0" "June" "2008"]
["372" "December" "2007"]
["371" "August" "2007"]
["370" "May" "2007"]
["360" "November" "2006"]
["352" "July" "2006"]
["351" "July" "2006"]
["350" "June" "2006"]
["301" "January" "2006"]
["300" "December" "2005"]
["209" "December" "2004"]
["208" "August" "2004"]
["207" "May" "2004"]
["206p1" "January" "2004"]
["206" "January" "2004"]
["205" "August" "2003"]
["204" "May" "2003"]
["203" "December" "2002"]
["202" "August" "2002"]
["201" "July" "2002"]
["200" "June" "2002"]
["103p1" "August" "2001"]
["103" "September" "2000"]
["053" "July" "1998"]
))
(define authors
'([plt "PLT"]
[ff mflatt robby]
[fplt mflatt plt]
[rplt robby plt]
[ffplt ff plt]
[ffc ff clements]
[fb mflatt eli]
[dorai "Dorai Sitaram"]
[wright "Andrew K. Wright"]
[flanagan "Cormac Flanagan"]
[web burns gregp jay]
[burns "Mike Burns"]
[gregp "Greg Pettyjohn"]
[dyoo "Danny Yoo"]
[ym dyoo jay]
[kathyg "Kathryn E. Gray"]
[jacobm "Jacob Matthews"]
[sowens "Scott Owens"]
[plot alex raymond]
[alex "Alexander Friedman"]
[raymond "Jamie Raymond"]
[dskippy "Mike T. McHenry"]
[ptg "Paul Graunke"]
[ryanc "Ryan Culpepper"]
[steck "Paul Steckler"]
[samth "Sam Tobin-Hochstadt"]
[gcooper "Greg Cooper"]))
(define doc-defs
;; each item is:
;; (docname [docnum] versions author title . attrs)
;; docname: a symbol for the name of the document
;; docnum: an optional integer used in the TR number (docname used otherwise)
;; versions: version range specification (see `versions->pred' below)
;; author: is a symbol from the `authors' table
;; title: is a string (no braces)
`(;; old versions
(mzscheme 1 "...*" mflatt "PLT MzScheme: Language Manual")
(mred 2 "...*" ff "PLT MrEd: Graphical Toolbox Manual")
(drscheme 3 "...*" robby "PLT DrScheme: Programming Environment Manual"
[#:note ("See also:"
"R. B. Findler, J. Clements, C. Flanagan, M. Flatt,"
"S. Krishnamurthi, P. Steckler and M. Felleisen."
"DrScheme: A programming environment for Scheme,"
"Journal of Functional Programming,"
"12(2):159--182, March 2002."
"http://www.ccs.neu.edu/scheme/pubs/")])
(mzlib 4 "200...*" plt "PLT MzLib: Libraries Manual")
(framework "...*" plt "PLT Framework: GUI Application Framework")
(tools "...*" robby "PLT Tools: DrScheme Extension Manual")
(web-server "300...*" web "Web Server Manual")
(mrlib "207...*" plt "PLT MrLib: Graphical Libraries Manual")
(plot "207...*" plot "PLoT Manual")
(mzc "...*" plt "PLT mzc: MzScheme Compiler Manual")
(insidemz "...*" mflatt "Inside PLT MzScheme")
(foreign "...*" eli "PLT Foreign Interface Manual")
(misclib "...*" plt "PLT Miscellaneous Libraries: Reference Manual")
(tex2page "200...*" dorai "TeX2page")
(t-y-scheme "200...*" dorai "Teach Yourself Scheme in Fixnum Days"
[type "Introduction"])
(match "103p1" wright "Pattern Matching for Scheme")
(mrspidey "103p1" flanagan "PLT MrSpidey: Static Debugger Manual")
;; new Scheme versions
(quick "*...!" mflatt
"Quick: An Introduction to PLT Scheme with Pictures"
[type "Introduction"])
(more "*...!" plt "More: Systems Programming with PLT Scheme"
[type "Introduction"])
(continue "4.1.1..." ym "Continue: Web Applications in PLT Scheme"
[type "Introduction"])
(guide "*...!" ffplt "Guide: PLT Scheme" [type "Introduction"])
(reference "*...!" fplt "Reference: PLT Scheme")
(htdp-langs "*...!" plt "How to Design Programs Languages")
(htdc "*...!" kathyg "How to Design Classes Languages")
(teachpack "*...!" plt "Teachpacks")
(eopl "*...!" plt "Essentials of Programming Languages Language")
(drscheme "*...!" rplt "DrScheme: PLT Programming Environment")
(mzc "*...!" plt "mzc: PLT Compilation and Packaging")
(setup-plt "*...!" plt "setup-plt: PLT Configuration and Installation")
(planet "*...!" jacobm "PLaneT: Automatic Package Distribution")
(redex "4.1...!" robby "Redex: Debugging Operational Semantics")
(scribble "*...!" fb "Scribble: PLT Documentation Tool")
(slideshow "*...!" ff "Slideshow: PLT Figure and Presentation Tools")
(web-server "*...!" jay "Web Server: PLT HTTP Server")
(tools "*...!" robby "Plugins: Extending DrScheme")
(gui "*...!" ffc "GUI: PLT Graphics Toolkit")
(framework "*...!" ff "Framework: PLT GUI Application Framework")
(sgl "*...!" sowens "GL: 3-D Graphics")
(plot "*...!" plot "PLoT: Graph Plotting")
(browser "*...!" plt "Browser: Simple HTML Rendering")
(cards "*...!" plt "Cards: Virtual Playing Cards Library")
(embedded-gui "*...!" dskippy "Embedded GUI: Widgets within editor<%>")
(games "*...!" plt "Games: Fun Examples")
(gl-board-game "*...!" plt "GL Board Game: 3-D Game Support")
(mrlib "*...!" plt "MrLib: Extra GUI Libraries")
(string-constants "*...!" plt "String Constants: GUI Internationalization")
(syntax-color "*...!" sowens "Syntax Color: Utilities")
(turtles "*...!" plt "Turtle Graphics")
(net "*...!" plt "Net: PLT Networking Libraries")
(openssl "*...!" plt "OpenSSL")
(file "*...!" plt "File: PLT File Format Libraries")
(html "*...!" plt "HTML: Parsing Library")
(parser-tools "*...!" sowens "Parser Tools: lex and yacc-style Parsing")
(xml "*...!" ptg "XML: Parsing and Writing")
(config "*...!" plt "Config: Installation and Search Paths")
(dynext "*...!" plt "Dynext: Running a C Compiler/Linker")
(errortrace "*...!" plt "Errortrace: Debugging and Profiling")
(macro-debugger "*...!" ryanc "Macro Debugger")
(make "*...!" plt "Make: Dependency Manager")
(readline "*...!" plt "Readline: Terminal Interaction")
(slatex-wrap "*...!" plt "SLaTeX Wrapper")
(trace "*...!" plt "Trace: Instrumentation to Show Function Calls")
(version "*...!" plt "Version: PLT Version Checking")
(foreign "*...!" eli "FFI: PLT Scheme Foreign Interface")
(inside "*...!" mflatt "Inside: PLT Scheme C API")
(cffi "*...!" mflatt "c-lambda: C FFI via mzc")
(mysterx "*...!" steck "MysterX: Using Windows COM Objects in Scheme")
(mzcom "*...!" steck "MzCOM: Scheme as a Windows COM Object")
(srfi "*...!" plt "SRFIs: Libraries")
(swindle "*...!" plt "Swindle")
(syntax "*...!" plt "Syntax: Meta-Programming Helpers")
(typed-scheme "*...!" samth "Typed Scheme: Scheme with Static Types")
(frtime "*...!" gcooper "FrTime: A Language for Reactive Programs")
(lazy "*...!" eli "Lazy Scheme")
(r5rs "*...!" plt "R5RS: Legacy Standard Language"
[#:note ("See also:"
"Rickard Kelsey and William Clinger"
"and Jonathan Rees (Editors)"
"Revised$^5$ Report of the Algorithmic Language Scheme"
"ACM SIGPLAN Notices"
"33(9):26--76, 1998")])
(graphics "*...!" plt "Graphics: Legacy Library")
(mzlib "*...!" plt "MzLib: Legacy PLT Libraries")
(preprocessor "*...!" eli "mzpp and mztext: Preprocessors")
(mzscheme "*...!" plt "MzScheme: Legacy Module Language")
(algol60 "*...!" plt "Algol 60")
(honu "*...!" plt "Honu")
(test-box-recovery "*...!" plt "Test Box Recovery Tool")
;; Racket versions
(quick "!..." mflatt
"Quick: An Introduction to Racket with Pictures"
[type "Introduction"])
(more "!..." plt "More: Systems Programming with Racket"
[type "Introduction"])
(guide "!..." ffplt "Guide: Racket" [type "Introduction"])
(reference "!..." fplt "Reference: Racket")
(drracket "!..." rplt "DrRacket: Programming Environment")
(scribble "!..." fb "Scribble: Racket Documentation Tool")
(slideshow "!..." ff "Slideshow: Racket Figure and Presentation Tools")
(web-server "!..." jay "Web Server: Racket HTTP Server")
(foreign "!..." eli "FFI: Racket Foreign Interface")
(inside "!..." mflatt "Inside: Racket C API")
;; Both Scheme and Racket
(r6rs "*..." plt "R6RS: Standard Language"
[#:note ("See also:"
"Michael Sperber and R. Kent Dybvig and Matthew Flatt"
"and Anton Van Straaten (Editors)"
"Revised$^6$ Report of the Algorithmic Language Scheme"
"September 2007")])
;; (article fcffksf:drscheme
;; [author "Robert Bruce Findler and John Clements and Cormac Flanagan"
;; "and Matthew Flatt and Shriram Krishnamurthi"
;; "and Paul Steckler and Matthias Felleisen"]
;; [title "{DrScheme}: A Programming Environment for {Scheme}"]
;; [volume 12]
;; [number 2]
;; [pages "159--182"]
;; [month "March"]
;; [journal "Journal of Functional Programming"]
;; [year "2002"])
))
;; ----------------------------------------------------------------------------
;; Bib stuff
;; bib values are hash tables mapping field names (symbols) to strings.
;; Keywords can also be used for the field names, which makes them meta-fields
;; that are not included in the usual bib printout. Two of them are required:
;; - #:type the type of the entry (a symbol: 'article, 'techreport, etc)
;; - #:key the label for the entry
(define bib-fields
'(author editor title booktitle journal
edition volume number series
chapter pages
type
school institution organization
publisher howpublished
address
month year
key
crossref
url
note
eprint))
(define meta-field? keyword?)
(define key->number
(let ([t (for/hash ([k bib-fields] [i (in-naturals)]) (values k i))])
(λ (key) (hash-ref t key
(λ () (error 'key->number "unknown field name: ~e" key))))))
;; converts the hash to an alist with the order specified by bib-fields
(define (bib->alist bib)
(sort (filter-not (compose meta-field? car) (hash-map bib cons))
< #:key (compose key->number car) #:cache-keys? #t))
(define (display* . xs)
(for-each display xs))
(define (display-attr attr)
(let* ([prefix (format " ~a = {" (car attr))]
[sep (lazy (string-append "\n" (make-string (string-length prefix)
#\space)))])
(display* prefix
(if (regexp-match? #rx"\n" (cdr attr))
(regexp-replace* #rx"\n" (cdr attr) (force sep))
(cdr attr))
"}")))
(define (display-bib bib)
(display* "@" (hash-ref bib '#:type) "{" (hash-ref bib '#:key))
(for ([attr (bib->alist bib)]) (display* ",\n") (display-attr attr))
(display* "\n}\n"))
(define (with-braces str) (regexp-replace* #px"\\b\\w+[A-Z]\\w*" str "{\\0}"))
(define (without-braces str) (regexp-replace* #rx"[{}]+" str ""))
(define (bib-author bib)
(let ([authors (regexp-split #rx"[ \t\n]+and[ \t\n]+"
(hash-ref bib 'author))])
(case (length authors)
[(0) "???"]
[(1) (car authors)]
[(2) (apply format "~a and ~a" authors)]
[(3) (apply format "~a, ~a, and ~a" authors)]
[else (format "~a et al" (car authors))])))
;; processes the (key val ...) alist to a hash of (key . val) by combining the
;; possibly multiple values for each key (each value becomes a line)
(define (bib type key attrs)
(define t (make-hasheq))
(hash-set! t '#:type type)
(hash-set! t '#:key key)
(for ([a attrs])
(define (err) (error 'make-bib "bad attribute: ~e" a))
(unless (and (pair? a) (pair? (cdr a)) (list? (cdr a))) (err))
(let ([key (car a)])
(unless (hash-ref t key #f) ; previous keys take precedence
(cond [(symbol? key)
;; turn non-strings to strings, join multiple strings, normalize
;; spaces
(let* ([val (cdr a)]
[val (map (λ (x) (if (string? x) x (format "~a" x))) val)]
[val (string-append* (add-between val "\n"))]
[val (regexp-replace* #rx"\t" val " ")]
[val (regexp-replace* #rx" +" val " ")]
[val (regexp-replace #rx"^ +" val "")]
[val (regexp-replace #rx" +$" val "")]
[val (regexp-replace* #rx"(?: *\r?\n *)+" val "\n")])
(hash-set! t key val))]
[(and (meta-field? key) (null? (cddr a)))
(hash-set! t key (cadr a))]
[else (err)]))))
t)
;; ----------------------------------------------------------------------------
;; Version etc
;; Use this instead of the built-in one, to make sure that we only deal
;; with known versions.
(define version->integer
(let ([t (for*/hash ([v (in-list (map car versions+dates))])
(values v (-version->integer (regexp-replace #rx"^0+" v ""))))])
(λ (ver)
(hash-ref t ver
(λ () (error 'version->integer "unknown pltreport version: ~e" ver))))))
;; "V...V" version range
;; "...V", "V..." open-ended version range
;; "..." all versions
;; "V" specific version
;; "" no versions
;; V can be `*': a number between the v3 docs and the v4 docs
;; V can be `!': a number between the last PLT Scheme and the first Racket
(define v:3->4 (-version->integer "379"))
(define v:4->5 (-version->integer "4.3"))
(define (versions->pred str)
(let* ([str (regexp-replace* #rx" +" str " ")]
[str (regexp-replace #rx"^ +" str "")]
[str (regexp-replace #rx" +$" str "")]
[l (regexp-split #rx" *[.][.][.] *" str)]
[l (map (λ (x)
(cond [(equal? "" x) #f]
[(equal? "*" x) v:3->4]
[(equal? "!" x) v:4->5]
[(version->integer x)]
[else (error 'versions->pred "bad version: ~e" x)]))
l)])
(apply
(case-lambda [(ver)
(if ver
(λ (v) (equal? ver (version->integer v)))
(λ (v) #f))]
[(from to)
(let ([from (or from -inf.0)]
[to (or to +inf.0)])
(λ (v) (<= from (version->integer v) to)))]
[_ (error 'versions->pred "bad versions spec: ~e" str)])
l)))
;; ----------------------------------------------------------------------------
;; Authors
(define authors*
(let ([t (make-hasheq)])
(for ([a authors])
(hash-set! t (car a)
((if (and (= 2 (length a)) (string? (cadr a))) cadr cdr) a)))
t))
(define (author->string author)
(let ([r (hash-ref authors* author
(λ () (person-bibname (find-person author))))])
(if (string? r)
r
(let ([r (string-join (map author->string r) " and ")])
(hash-set! authors* author r)
r))))
;; ----------------------------------------------------------------------------
;; Main
(define doc-defs*
(for/list ([d doc-defs])
(apply
(λ (docname docnum versions author title . attrs)
`(,(versions->pred versions)
[#:docname ,docname]
[#:number-template ,(format "PLT-TR~~a-~a-v~~a" (or docnum docname))]
[title ,(with-braces title)]
[author ,(author->string author)]
,@attrs))
(if (number? (cadr d)) d (list* (car d) #f (cdr d))))))
(define last-old-tr-version (-version->integer last-old-tr))
(define bibs
(for/list ([ver (in-list (map car versions+dates))]
[month (in-list (map cadr versions+dates))]
[year (in-list (map caddr versions+dates))]
#:when (<= (version->integer ver) last-old-tr-version)
[doc (in-list doc-defs*)]
#:when ((car doc) ver))
(define attrs (cdr doc))
(define (get key [dflt #f]) (cond [(assq key attrs) => cadr] [else dflt]))
(define docname (get '#:docname))
(define number (format (get '#:number-template) year ver))
(define key (regexp-replace* #rx":" (string-downcase number) "_"))
(define old? (< (version->integer ver) v:4->5))
(define site (if old? "plt-scheme" "racket-lang"))
(define note
(let ([n1 (format "\\url{http://~a.org/techreports/}" site)]
[n2 (get '#:note #f)])
(if n2 (cons (string-append n1 ";") n2) (list n1))))
(define maybe-s (if old? "" "s"))
(define (mk-url dir sfx)
(format "http://download.~a.org/doc~a/~a/~a/~a~a"
site maybe-s ver dir docname sfx))
(define pdf-url (mk-url "pdf" ".pdf"))
(define pdf-html (mk-url "html" "/"))
(bib 'techreport key
`(,@attrs
[year ,year]
[month ,month]
[institution "PLT Design Inc."]
[type "Reference Manual"]
[number ,number]
[#:version ,ver]
[url ,pdf-url]
[#:pdf-url ,pdf-url]
[#:html-url ,pdf-html]
[note ,@note]))))
(define old-techreports
@page[#:file "techreports/" #:title "Old PLT Technical Reports"
#:part-of 'learning
#:extra-headers
@script/inline[type: "text/javascript"]{
function show_bib(n) {
var s = document.getElementById("bibrow"+n).style;
s.display = (s.display == "table-row") ? "none" : "table-row";
}}]{
@p{@strong{Note:} the entries on this page are outdated, please see the new
@techreports page.}
@p{PLT publishes technical reports about some of its tools and libraries so
that scholars who wish to give proper credit to some of our innovations
have a definite citation. Each entry below provides the full pdf and a
bibtex entry; some of the bibtex entries provide additional citations to
published papers.}
@table[width: "98%" cellspacing: 0 cellpadding: 6 border: 0
align: 'center style: "font-size: 75%;"]{
@(for/list ([bib (in-list bibs)] [n (in-naturals)])
(define bgcolor (if (even? n) "#e0e0e0" "white"))
(define bibtext
(parameterize ([current-output-port (open-output-string)])
(display-bib bib)
(get-output-string (current-output-port))))
@list{
@tr[valign: 'top bgcolor: bgcolor]{
@td[style: "white-space: nowrap;"]{@(hash-ref bib 'number)}
@td[align: 'left]{@i{@(without-braces (hash-ref bib 'title))}}
@td{@(bib-author bib)}
@td{@a[href: @list{javascript: show_bib(@n)@";"}]{[bib]}@|nbsp|@;
@a[href: (hash-ref bib '#:pdf-url)]{[pdf]}@|nbsp|@;
@a[href: (hash-ref bib '#:html-url)]{[html]}}}
@tr[valign: 'top bgcolor: bgcolor
id: @list{bibrow@n} style: "display: none;"]{
@td{}@td[colspan: 3]{@pre{@bibtext}}}})}})

View File

@ -0,0 +1,108 @@
#lang meta/web
(require "resources.rkt")
(define (make-all place person)
;; The first person in a place is the one responsible for it
(list
(place ; -------------------------------------------------------------------
'neu "Northeastern University"
#:location "Boston, MA"
#:url "http://www.ccs.neu.edu/racket/"
#:pubs "http://www.ccs.neu.edu/racket/pubs/"
(person 'matthias "Matthias Felleisen"
#:url "http://www.ccs.neu.edu/home/matthias/")
(person 'eli "Eli Barzilay"
#:url "http://barzilay.org/"))
(place ; -------------------------------------------------------------------
'utah "University of Utah"
#:location "Salt Lake City, UT"
#:url "http://www.cs.utah.edu/plt/"
#:pubs "http://www.cs.utah.edu/plt/publications/"
(person 'mflatt "Matthew Flatt"
#:url "http://www.cs.utah.edu/~mflatt/"))
(place ; -------------------------------------------------------------------
'nwu "Northwestern University"
#:location "Evanston, IL"
#:url "http://plt.eecs.northwestern.edu/"
#:pubs "http://www.eecs.northwestern.edu/~robby/pubs/"
(person 'robby "Robby Findler"
#:bibname "Robert Bruce Findler"
#:url "http://www.eecs.northwestern.edu/~robby/"))
(place ; -------------------------------------------------------------------
'brown "Brown University"
#:location "Providence, RI"
#:url "http://www.cs.brown.edu/research/plt/"
#:pubs "http://www.cs.brown.edu/~sk/Publications/Papers/"
(person 'shriram "Shriram Krishnamurthi"
#:url "http://www.cs.brown.edu/~sk/"))
(place ; -------------------------------------------------------------------
'byu "Brigham Young University"
#:location "Provo, UT"
#:url "http://faculty.cs.byu.edu/~jay/"
#:pubs "http://faculty.cs.byu.edu/~jay/home/#(part._pubs)"
(person 'jay "Jay McCarthy"
#:url "http://faculty.cs.byu.edu/~jay/"))
(place ; -------------------------------------------------------------------
'calpoly "California Polytechnic State University"
#:location "San Luis Obispo, CA"
#:url "http://users.csc.calpoly.edu/~clements/"
#:pubs "http://www.brinckerhoff.org/clements/papers/"
(person 'clements "John Clements"
#:url "http://users.csc.calpoly.edu/~clements/"))
(place ; -------------------------------------------------------------------
'wpi "Worcester Polytechnic Institute"
#:location "Worcester, MA"
#:url "http://web.cs.wpi.edu/~kfisler/"
(person 'kathi "Kathi Fisler"
#:url "http://web.cs.wpi.edu/~kfisler/"))))
;; ----------------------------------------------------------------------------
(struct person (nick name url bibname place) #:prefab)
(struct place (nick name location url pubs people) #:prefab)
(provide (struct-out place) all-places find-place
(struct-out person) all-people find-person)
(define-values (all-places find-place all-people find-person)
(let ()
(define places0
(make-all
;; make a place
(λ (nick name #:location loc #:url url #:pubs [pubs #f] . people)
(place nick name loc url pubs people))
;; make a person
(λ (nick name #:url url #:bibname [bibname name])
(person nick name url bibname (make-placeholder #f)))))
(for* ([place (in-list places0)]
[person (in-list (place-people place))])
(placeholder-set! (person-place person) place))
(define places (make-reader-graph places0))
(define people (append-map place-people places))
(when (ormap (λ (p) (null? (place-people p))) places)
(error 'places "all places should have people in them"))
(define (make-finder what xs get-nick)
(define t (make-hasheq))
(for ([x (in-list xs)])
(hash-update! t (get-nick x)
(λ (old) (if old (error what "got duplicate nicks") x))
#f))
(λ (nick) (or (hash-ref t nick #f)
(error what "nick not found: ~s" nick))))
(values places (make-finder 'places places place-nick)
people (make-finder 'people people person-nick))))
(provide people)
(define people
@page[#:window-title "Racket People: The PLT Group" #:part-of 'community
#:description "PLT: the group that is the Racket development team."]{
@p{“PLT” refers to the group that is the core of the Racket development
team. PLT consists of numerous people distributed across several
different universities in the USA:
@(ul (map (λ (p) @li{@a[href: (place-url p)]{
@(place-name p), @(place-location p)}})
all-places))}
@p{Also, Racket is supported by a band of volunteers who contribute not
only code and documentation but also infectious enthusiasm—too many to
name but whose help and encouragement make this fun and worthwhile.}})

View File

@ -0,0 +1,3 @@
#lang meta/web
(define+provide-context "www")

View File

@ -0,0 +1,105 @@
#lang meta/web
;; New style TR entries
(require "resources.rkt" "people.rkt" "../download/data.rkt")
(define (-all-techreports-)
(list (TR 1 'reference "Reference: Racket" '(mflatt plt)
#:description "Racket Programming Language")
(TR 2 'drracket "DrRacket: Programming Environment" '(robby plt)
#:description "DrRacket API"
#:note
@list{
Preferred generic citation:
@blockquote[style: "margin-top: 0.5ex; margin-bottom: 0.5ex;"]{
R. B. Findler, J. Clements, C. Flanagan, M. Flatt,
S. Krishnamurthi, P. Steckler and M. Felleisen. @br
@i{DrScheme: A programming environment for Scheme.} @br
Journal of Functional Programming, 12(2): 159182, March 2002.}
Please cite the DrRacket technical report only if internal
details of DrRacket are concerned, otherwise use the DrScheme
reference.})
(TR 3 'gui "GUI: Racket Graphics Toolkit" '(mflatt robby clements)
#:description "Racket Graphics Toolkit")))
(define (doc-url doc [fmt 'html] [ver 'recent])
(format "http://download.racket-lang.org/docs/~a/~a/~a~a" ver fmt doc
(if (eq? 'html fmt) "" (format ".~a" fmt))))
(define (TR num docname title authors* #:description [desc title]
#:note [note #f])
(define tr-name @list{PLT-TR-2010-@num})
(define author-strings
(map (λ (a) (if (eq? 'plt a) "PLT" (person-bibname (find-person a))))
authors*))
(define (link fmt [ver 'recent]) @a[href: (doc-url docname fmt ver)]{[@fmt]})
(define (title-line link?)
@list{@big{@b{@(if link? cite-page values){@tr-name}}}
@|nbsp nbsp| @small{@link['html] @link['pdf]}})
(define (content)
@list{@(add-between author-strings " and ") @br
@i{@title} @br
PLT Technical Report #@num @br
@(and note @div[style: "margin-top: 1ex; font-size: small;"]{
@note})})
(define ((refblock . title) . body)
@list{@h2{@title}
@blockquote{@PRE{@body}}})
(define cite-page
@page[#:file (format "tr~a/" num) #:title tr-name #:part-of 'learning]{
@h1{@title-line[#f]}
@p*{@blockquote{@big{@content}}
@~ For citations of the @desc, please use @TT{\cite{plt-tr@num}} in
LaTeX, or @TT|{@cite[plt-tr1]}| in Scribble, using the definitions
below.
@~ For references to specific releases and/or chapters, use
@TT{\cite[Version M.N]{plt-tr@num}} or
@TT|{@cite[(in-bib plt-tr|@num "Version M.N")]}| instead. The
year in the bibliographic entry should be 2010 regardless of the
version's date.}
@@refblock{BibTeX}|{
@techreport{plt-tr|@num,
title = {|@title},
author = {|@(add-between author-strings " and ")},
number = {|@tr-name},
institution = {PLT Inc.},
year = {2010},
note = {\url{|@(url-of cite-page #t)}}
}}|
@@refblock{Scribble}|{
(define plt-tr|@num
(make-bib #:title "|@title"
#:author |@(format "~s" (cons 'authors author-strings))
#:date "2010"
#:location (techrpt-location #:institution "PLT Inc."
#:number "|@tr-name")
#:url "|@(url-of cite-page #t)"))}|
@h2{Specific Versions}
@blockquote{
@table[frame: 'box rules: 'rows cellpadding: 10]{
@(for/list ([r (in-list all-releases)])
(define v (release-version r))
@tr{@td{@b{@v} @br @small{(@(release-date-string r))}}
@td{@TT{\cite[Version @v]{plt-tr@num}} @br
@TT|{@cite[(in-bib plt-tr|@num "Version |@v")]}|}
@td{@link['html v], @link['pdf v]}})}
@p{@small{Reminder: the release dates should not be included in the
entry or the citation.}}}})
@list{@dt{@title-line[#t]}
@dd[style: "margin-bottom: 1.5ex;"]{
@content}})
(provide techreports)
(define techreports
@page[#:file "tr/" #:title "PLT Technical Reports" #:part-of 'learning]{
@p*{
@~ For citations of generic pieces of the Racket infrastructure, please use
@TT{\cite{plt-tr1}}, @TT{\cite{plt-tr2}}, etc. in LaTeX, or
@TT|{@cite[plt-tr1]}|, @TT|{@cite[plt-tr2]}|, etc. in Scribble, with the
BibTeX and Scribble entries provided in the web pages below.
@~ For references to specific releases and/or chapters of the language, use
@TT{\cite[Version M.N]{plt-tr1}} or
@TT|{@cite[(in-bib plt-tr1 "Version M.N")]}|
instead.}
@dl{@(add-newlines (-all-techreports-))}})

View File

@ -0,0 +1,12 @@
#lang meta/web
(require "resources.rkt")
(provide web-copyright)
(define web-copyright
@page{
The text of this website is available for modification and reuse
under the terms of the Creative Commons Attribution-Sharealike 3.0
Unported License and the GNU Free Documentation
License (unversioned, with no invariant sections, front-cover texts,
or back-cover texts).})