From f56532c0221c027a369c453a80772b570a9410a1 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Sat, 5 Jun 2010 14:09:40 -0400 Subject: [PATCH] Main page works. --- collects/meta/web/common/layout.rkt | 26 +- collects/meta/web/common/links.rkt | 27 +- collects/meta/web/www/code.rkt | 134 ++++++ collects/meta/web/www/download-dark.png | Bin 0 -> 9970 bytes collects/meta/web/www/download.png | Bin 0 -> 10022 bytes collects/meta/web/www/index.rkt | 589 +++++++++++++++++++++++- 6 files changed, 752 insertions(+), 24 deletions(-) create mode 100644 collects/meta/web/www/code.rkt create mode 100644 collects/meta/web/www/download-dark.png create mode 100644 collects/meta/web/www/download.png diff --git a/collects/meta/web/common/layout.rkt b/collects/meta/web/common/layout.rkt index 66093763f3..2334a3a285 100644 --- a/collects/meta/web/common/layout.rkt +++ b/collects/meta/web/common/layout.rkt @@ -19,6 +19,15 @@ [body #`(lambda () (text #,@xs))]) #'(layouter id ... x ... body))]))) +(define (id->file who id sfx dir) + (let* ([f (and id (symbol->string (force id)))] + [f (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 f) f))) + ;; 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 @@ -28,12 +37,7 @@ (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 (if (and id suffix) - (let ([f (format "~a.~a" (force id) suffix)]) - (if dir (web-path dir f) f)) - (error 'plain - "missing `#:file', or `#:id' and `#:suffix'"))] + #:file [file (id->file 'plain id suffix dir)] #:referrer [referrer (lambda (url) (error 'plain "no referrer for ~e" file))] @@ -48,15 +52,13 @@ (syntax-case stx () [(_ . xs) (process-contents 'page #'page* stx #'xs)])) (define (page* #:id [id #f] #:dir [dir #f] - #:file [file (if id - (format "~a.html" (force id)) - (error 'page "missing `#:file' or `#:id'"))] + #:file [file (id->file 'page id "html" dir)] #: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 `#:file' or `#:title'"))] + (error 'page "missing `#:id' or `#:title'"))] #:link-title [linktitle label] #:window-title [wintitle @list{Racket: @label}] #:full-width [full-width #f] @@ -79,9 +81,7 @@ @(if body-attrs (apply body `(,@body-attrs ,content)) (body content))})) - (define this - (resource (if dir (web-path dir file) file) - (file-writer output-xml page) referrer)) + (define this (resource file (file-writer output-xml page) referrer)) this) (provide set-navbar!) diff --git a/collects/meta/web/common/links.rkt b/collects/meta/web/common/links.rkt index 048c9e66af..6136312853 100644 --- a/collects/meta/web/common/links.rkt +++ b/collects/meta/web/common/links.rkt @@ -2,22 +2,26 @@ (define-syntax-rule (define* 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* -planet @a[href: "http://planet.racket-lang.org/"]{PLaneT}) +(define* -planet @make-link["http://planet.racket-lang.org/"]{PLaneT}) (define doc-url "http://docs.racket-lang.org/") -(define* -docs @a[href: doc-url]{Documentation}) +(define* -docs @make-link[doc-url]{Documentation}) (define-syntax-rule (define-doc-link id desc) - (define* id @a[href: `(,doc-url id "/")]{ + (define* id @make-link[`(,doc-url id "/")]{ @strong{@(string-titlecase (symbol->string 'id))}: @desc})) @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)) @@ -25,22 +29,25 @@ ;; External links (define* -htdp - @a[href: "http://www.htdp.org/"]{@i{How to Design Programs}}) + @make-link["http://www.htdp.org/"]{@i{How to Design Programs}}) + +(define* -redex + @make-link["http://redex.plt-scheme.org/"]{Redex}) (define* -teachscheme - @a[href: "http://www.teach-scheme.org/"]{TeachScheme!}) + @make-link["http://www.teach-scheme.org/"]{TeachScheme!}) (define* -cookbook - @a[href: "http://schemecookbook.org/"]{Schematics Scheme Cookbook}) + @make-link["http://schemecookbook.org/"]{Schematics Scheme Cookbook}) (define* -schematics - @a[href: "http://sourceforge.net/projects/schematics/"]{Schematics}) + @make-link["http://sourceforge.net/projects/schematics/"]{Schematics}) (define* -schemers - @a[href: "http://schemers.org/"]{@tt{schemers.org}}) + @make-link["http://schemers.org/"]{@tt{schemers.org}}) (define* -plai - @a[href: "http://www.plai.org/"]{ + @make-link["http://www.plai.org/"]{ @i{Programming Languages: Application and Interpretation}}) -(define* -bootstrap @a[href: "http://www.bootstrapworld.org/"]{Bootstrap}) +(define* -bootstrap @make-link["http://www.bootstrapworld.org/"]{Bootstrap}) diff --git a/collects/meta/web/www/code.rkt b/collects/meta/web/www/code.rkt new file mode 100644 index 0000000000..af387bc0de --- /dev/null +++ b/collects/meta/web/www/code.rkt @@ -0,0 +1,134 @@ +#lang at-exp s-exp "shared.rkt" + +(require syntax-color/module-lexer + setup/xref + scribble/xref) + +(provide code) + +(define doc-root "http://docs.racket-lang.org/") + +(define expand-namespace (make-base-namespace)) +(define xref (load-collections-xref)) + +(define (code . strs) + (let* ([str (apply string-append strs)] + [bstr (string->bytes/utf-8 + (regexp-replace* #rx"(?m:^$)" str "\xA0"))] + [in (open-input-bytes bstr)]) + (let* ([tokens + (let loop ([mode #f]) + (let-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)))))] + [substring* (lambda (bstr start [end (bytes-length bstr)]) + (bytes->string/utf-8 (subbytes bstr start end)))] + [e (parameterize ([read-accept-reader #t] + [current-namespace expand-namespace]) + (expand (read-syntax 'prog (open-input-bytes bstr))))] + [ids (let loop ([e e]) + (cond + [(and (identifier? e) + (syntax-original? e)) + (let ([pos (sub1 (syntax-position e))] + [b (identifier-binding e)]) + (list (list (if (and (list? b) + (let-values ([(name base) (module-path-index-split (car b))]) + (or name base))) + (let ([tag (xref-binding->definition-tag xref e 0)]) + (if tag + (cons (if (eq? (car tag) 'form) + 'linkimportform + 'linkimportid) + (let-values ([(p a) (xref-tag->path+anchor + xref tag + #:external-root-url doc-root)]) + (format "~a#~a" p a))) + 'importid)) + 'id) + 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]))] + [link-mod (lambda (mp-stx priority #:orig? [always-orig? #f]) + (if (or always-orig? + (syntax-original? mp-stx)) + (let ([mp (syntax->datum mp-stx)]) + (let-values ([(p a) + (xref-tag->path+anchor + xref + `(mod-path ,(format "~s" mp)) + #:external-root-url doc-root)]) + (if p + (list (let ([pos (sub1 (syntax-position mp-stx))]) + (list (cons 'modpath (format "~a#~a" p a)) + pos + (+ pos (syntax-span mp-stx)) + priority))) + null))) + null))] + [mods (let loop ([e e]) + (syntax-case e (module require begin) + [(module name lang (mod-beg form ...)) + (apply append + (link-mod #'lang 2) + (map loop (syntax->list #'(form ...))))] + [(#%require spec ...) + (apply append + (map (lambda (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 ...) + (apply append + (map loop (syntax->list #'(form ...))))] + [else null]))] + [language (if (regexp-match? #rx"^#lang " bstr) + (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)) + null)] + [tokens (sort (append ids + mods + language + (filter (lambda (x) (not (eq? (car x) 'symbol))) + ;; Drop #lang entry: + (cdr tokens))) + (lambda (a b) + (or (< (cadr a) (cadr b)) + (and (= (cadr a) (cadr b)) + (> (cadddr a) (cadddr b))))))]) + (apply pre (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)) + (cons (let ([style (caar tokens)] + [s (substring* bstr (cadar tokens) (caddar tokens))]) + (if (pair? style) + (a href: (cdr style) class: (format "code~a" (car style)) s) + (span class: (format "code~a" 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))])))))) diff --git a/collects/meta/web/www/download-dark.png b/collects/meta/web/www/download-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..d73b9d6e63c30f872c8aab0b417f32f65165f90f GIT binary patch literal 9970 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 B*c|`> literal 0 HcmV?d00001 diff --git a/collects/meta/web/www/download.png b/collects/meta/web/www/download.png new file mode 100644 index 0000000000000000000000000000000000000000..56d925bfe96e5f317fdb7021b9bf73b58932d0b5 GIT binary patch literal 10022 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%0Ay)ynJiCV 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 b_#I6FJuu4gkU|Q2{tZS!R#m22$~@$M55v0g literal 0 HcmV?d00001 diff --git a/collects/meta/web/www/index.rkt b/collects/meta/web/www/index.rkt index de62d4b04e..bd9b8607e8 100644 --- a/collects/meta/web/www/index.rkt +++ b/collects/meta/web/www/index.rkt @@ -1,6 +1,593 @@ #lang at-exp s-exp "shared.rkt" +(require "code.rkt" "outreach+research.rkt" racket/string) + +(define (doc s) + (string-append "http://docs.racket-lang.org/" s)) + +(define-struct example (code desc)) +(define-struct (cmdline-example example) ()) +(define-struct (scribble-example example) ()) +(define-struct (graphical-example example) ()) + +(define (desc . strs) (apply div strs)) +(define (elemcode . strs) (apply tt strs)) + (provide index) (define index (page #:link-title "About" #:window-title "Racket" - "TODO")) + #:extra-headers (delay more.css) + (div class: 'whatpane + @span{@span[class: 'whatb]{Racket} is a programming language.}) + (div class: 'aboutpane + (div class: 'panetitle "Start Quickly") + (div class: 'downloadbutton download-plt) + (alts-panel + @; --- Each example here should be exactly 7 lines long --- + @; Candidates for initial example: ------------------------ + (list + (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.}) + (example + @code{ + #lang web-server/insta + ;; A "hello world" web server + (define (start request) + '(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. + }) + (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. + }) + (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 6]) + (if (zero? n) + (triangle 2 'solid 'red) + (let ([next (sierpinski (- n 1))]) + (above next (beside next next))))) + } + @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 6. + }) + (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. + }) + (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"(?<=

).*?(?=

)"]) + (regexp-match* rx (get-pure-port (string->url g))))) + } + @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. + }) + (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. + }) + (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. + }) + (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 @|ndash| 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. + }) + )) + @p{@a[href: (doc "quick/")]{Draw more pictures} or + @a[href: (doc "more/")]{build a web server from scratch}. + Racket includes both @a[href: (doc "")]{batteries} + and a @a[href: (doc "drracket/")]{programming environment}, + so @a[href: (doc "getting-started/index.html")]{get started}!}) + (table class: 'threepanes + (tr + (td + (div class: 'panetitle "Grow your Program") + @p{Racket's + @a[href: (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 @a[href: + (doc "guide/performance.html")]{native-code JIT compilation}. When + a system gets too big to keep in your head, you can add + @a[href: (doc "ts-guide/index.html")]{static types}.}) + (td + (div class: 'panetitle "Grow your Language") + @p{@a[href: (doc "guide/languages.html")]{Extend Racket} whenever + you need to. Mold it to better suit your tasks without + sacrificing + @a[href: (doc "guide/dialects.html")]{interoperability} with + existing libraries and without having to modify the + @a[href: (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.}) + (td + (div class: 'panetitle "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 @outreach+research{research}, Racket can + help you become a better programmer and system builder.}))))) + +(define (alts-panel l1 l2) + (define l (append l1 l2)) + (apply div class: 'slideshow + @script/inline[type: "text/javascript"]{ + var showing = 0; + var help_showing = false; + var kind = [ @(string-join (for/list ([i (in-list l)]) + (cond + [(cmdline-example? i) "\"cmd\""] + [(scribble-example? i) "\"scrib\""] + [(graphical-example? i) "\"dr\""] + [else "\"any\""])) + ",") ]; + function change_show_to(new_showing) { + elem = document.getElementById("frame" + showing); + elem.style.display = "none"; + elem = document.getElementById("helpframe" + showing); + elem.style.display = "none"; + elem = document.getElementById("howto" + kind[showing]); + elem.style.display = "none"; + showing = new_showing; + elem = document.getElementById("frame" + showing); + elem.style.display = "block"; + elem = document.getElementById("helpframe" + showing); + elem.style.display = "block"; + elem = document.getElementById("howto" + kind[showing]); + elem.style.display = "block"; + elem = document.getElementById("rewindbutton"); + elem.style.color = ((showing == 0) ? "#aaa" : "#444"); + elem = document.getElementById("advancebutton"); + elem.style.color = ((showing == @(sub1 (length l))) ? "#aaa" : "#444"); + } + function change_show(amt) { + change_show_to((showing + amt + @(length l)) % @(length l)); + } + function advance_show() { + if (showing < @(sub1 (length l))) change_show(1); + return false; + } + function rewind_show() { + if (showing > 0) change_show(-1); + return false; + } + function show_help() { + elem = document.getElementById("helppanel"); + elem.style.display = "block"; + help_showing = true; + return false; + } + function hide_help() { + elem = document.getElementById("helppanel"); + elem.style.display = "none"; + help_showing = false; + return false; + } + function toggle_help() { + if (help_showing) + return hide_help(); + else + return show_help(); + } + } + (div + class: 'buttonpanel + (a href: "#" + id: "rewindbutton" + class: 'slideshowbutton + onclick: "return rewind_show()" + style: "color: #aaa;" + "<") + (a href: "#" + id: "advancebutton" + class: 'slideshowbutton + onclick: "return advance_show()" + ">") + (a href: "#" + class: 'slideshowhbutton + onclick: "return toggle_help()" + "?") + (div class: 'hiddenhelp + id: "helppanel" + style: "display: none" + (div class: 'helpcontent + (a href: "#" + class: 'closebutton + onclick: "return hide_help()" + "close") + (apply div class: 'helpdesc + (for/list ([elem l] + [pos (in-naturals)]) + (div class: 'helpdeskframe + id: (format "helpframe~a" pos) + style: "display: none" + (example-desc elem)))) + @div[class: 'helptext]{Form and function names in the code + are hyperlinked to documentation, so click on them + for more information.} + @div[class: 'helptext + id: "howtoany"]{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.} + @div[class: 'helptext + style: "display: none" + id: "howtodr"]{To run the example, install Racket, + start DrRacket, paste the example program + into the top area in DrRacket, + and click the Run button.} + @div[class: 'helptext + id: "howtoscrib"]{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.} + @div[class: 'helptext + style: "display: none" + id: "howtocmd"]{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.}))) + (append + (for/list ([elem l] + [pos (in-naturals)]) + (div class: 'slideshowframe + id: (format "frame~a" pos) + style: (format "display: ~a" (if (zero? pos) "block" "none")) + (example-code elem))) + (list + @script/inline[type: "text/javascript"]{ + change_show_to(Math.floor(Math.random()* @(length l1))); + })))) + +;; TODO +;; (define screenshots +;; (let ([image (copyfile (in-here "screenshot.jpg"))]) +;; @a[href: "http://plt-scheme.org/screenshots/"]{ +;; @img[src: image alt: "[screenshots]" border: 0 +;; style: "margin-bottom: 2px;"]@; +;; @|br|@small{Screenshots}})) + +;; (define tour-video +;; (page #:title "DrScheme 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]}})) + +(define download-plt + (let ([img1 (copyfile (in-here "download.png"))] + [img2 (copyfile (in-here "download-dark.png"))]) + (list + @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 = "@img1"; + rollovers[1].src = "@img2"; + 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: "http://download.plt-scheme.org/drscheme/" + onmouseover: "set_download_image(1);" + onmouseout: "set_download_image(0);"]{ + @img[id: "download_button" border: "0" src: img1 + alt: "Download PLT Scheme" title: "Download PLT Scheme"]}))) + +(define more.css + @plain[#:referrer (lambda (url) (link rel: "stylesheet" type: "text/css" + href: url title: "default"))]{ + .whatpane { + font-size: medium; + float: left; + width: 20%; + } + .whatb { + font-size: large; + font-weight: bold; + } + .aboutpane { + width: 56%; + margin-right: auto; + margin-left: auto; + } + .panetitle { + width: 100%; + font-size: large; + font-weight: bold; + color: #D00; + } + .threepanes { + width: 100%; + } + .threepanes td { + vertical-align: top; + align: center; + width: 30%; + padding: 0.5em; + } + .slideshow { + position: relative; + } + .buttonpanel { + display: block; + position: absolute; + left: 100%; + top: -3ex; + width: 3em; + margin: 0em 0em 0em -5em; + } + .slideshowbutton, .slideshowhbutton { + text-decoration: none; + border: 1px solid #ddd; + font-weight: bold; + color: #444; + padding: 0px 1px 0px 1px; + } + .slideshowbutton { + margin: 0px 1px 0px 1px; + } + .slideshowhbutton { + margin: 0px 1px 0px 10px; + } + .hiddenhelp { + width: 0em; + margin-left: 2em; + } + .helpcontent { + width: 20em; + background-color: #FFE; + 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; + left: 1em; + top: -1em; + height: 0em; + width: 1em; + margin: 0em -1em 0em 0em; + } + @; + .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; + }})