diff --git a/rcon/2025/.gitignore b/rcon/2025/.gitignore new file mode 100644 index 00000000..e90722f8 --- /dev/null +++ b/rcon/2025/.gitignore @@ -0,0 +1 @@ +/index.html diff --git a/rcon/2025/index.rkt b/rcon/2025/index.rkt new file mode 100644 index 00000000..5feb1461 --- /dev/null +++ b/rcon/2025/index.rkt @@ -0,0 +1,440 @@ +#lang at-exp racket/base + +(require racket/match + racket/string + xml + txexpr + (prefix-in gregor: gregor) + "lib.rkt") + +(define-div main + [font-family "'Montserrat', sans-serif"] + [background "blue"] + [color "black"] + [margin "0px"]) + +(define-div content + ,@centered + [background "white"] + [margin-left "10ex"] + [margin-right "10ex"] + [padding-top "2ex"] + [padding-bottom "2ex"]) + +(define-div column + ,@centered + [max-width "45em"]) + +(define-div banner + [padding-top "1ex"] + ,@centered) + +(define-div title-container + [display inline-block] + (margin-left auto) + (margin-right auto) + [text-align left] + [margin-bottom "1em"]) + +(define-div title-append + [display flex]) + +(define-div pagetitle + [font-size "40pt"] + [font-family ,monospace]) + +(define header-font + `(#;[font-weight "bold"])) + +(define-div subtitle + ,@centered + [font-size "32pt"] + [font-weight "bold"] + ,@header-font) + +(define-div subsubtitle + ,@centered + [font-size "20pt"] + ,@header-font) + +(define-div section + [margin-top "3em"]) +(define-div sectionHeader + [font-size "24pt"] + [margin-bottom "1em"] + [background "#CCCCEE"] + [margin-left "-10ex"] + [margin-right "-10ex"] + ,@header-font) + +(define-div speaker-a + [color "firebrick"]) +(define-a unaffiliated + [color "inherit"]) +(define-a h-card + [color "inherit"]) + +(define-span activity) + +(define-div talk + [font-weight bold] + #; + [font-style "italic"] + [font-size "24pt"] + [margin-top "0.25em"] + [margin-bottom "0.5em"] + [color "gray"]) + +(define-div place + [font-weight bold] + #; + [font-style "italic"] + [font-size "24pt"] + [margin-top "0.25em"] + [color "gray"]) + +(define-div place-address + [margin-bottom "0.5em"]) + +(define-div abstract + [text-align "left"] + [margin-left "5em"] + [margin-right "5em"]) + +(define-div paragraph + [text-align "left"]) +(define-div center + [text-align "center"]) +(define para paragraph) + +(define-div plain) + +(define-div joint + [color "gray"]) + +(define-div larger + [font-size "24pt"]) + +(define-div featuring + [white-space "nowrap"] + [font-size "18pt"] + [margin-top "1em"] + [color "blue"]) + +(define-span featured + [font-weight bold]) + +(define-span bold + [font-weight bold]) + +(define-span emph + [font-style "italic"]) +(define-span book-title + [font-style "italic"]) + +(define-span tt + [font-family ,monospace]) + +(define-span faded + [color "gray"]) + +(define-span nop) + +(define-div talk-time-div + [font-weight bold] + [position absolute] + [color "gray"]) + +(define-div live-link + [position absolute] + [right 0] + [top 0]) + +(define-div speech + [margin-top "3em"] + [position relative]) + +(define-div first-speech + [margin-top "1em"] + [position relative]) + +(define-div bio-div + [margin-top "0.5em"] + [text-align "left"] + [margin-left "5em"] + [margin-right "5em"]) + + +(define-span bio-label + [font-weight "bold"] + [color "gray"]) + +(define-div keynote-speaker + [font-size "24pt"] + [font-weight "bold"]) + +(define-div nb + [text-align "center"] + [font-style "italic"]) + +(define-div p-location + [font-size "24pt"] + [font-weight "bold"]) + +(define-div specific-location + [font-size "18pt"] + [margin-top "0.25em"]) + +(define-div specific-location-cotd + [font-size "18pt"]) + +(define-div picture + [margin-top "2em"]) + +(define (script . contents) + `(script ,@(map (λ (x) (cdata #f #f x)) contents))) + +(define (code content) + `(code () ,content)) + +;; ------------------------------------------------------------ + +(define (speaker #:person? [person? #t] + #:url [url #f] + #:affiliation [affiliation #f] + . x) + (when (and person? (not (non-empty-string? url))) + (error "Every person needs a URL")) + (define span-kids + (cond [(not person?) + x] + [(not (non-empty-string? url)) + (error "Every person needs a URL")] + [else + (define name (apply string-append x)) + (define attrs + (append (list (list 'href url) + (list 'title name)) + (cond [(non-empty-string? affiliation) + (list (list 'class "h-card"))] + [else + (list (list 'class "unaffiliated"))]))) + (cond [(non-empty-string? affiliation) + (list (txexpr* 'a attrs + (bold name) + " (" + (txexpr* 'span + (list (list 'class "p-org")) + affiliation) + ")"))] + [else + (list (txexpr* 'a attrs (bold name)))])])) + (txexpr 'span + (list (list 'class "speaker-a")) + span-kids)) +(define (lecture #:when when + #:who who + #:link [l #f] + #:what [what ""] + #:more [more ""] + #:even-more [even-more ""] + #:bio [bio #f] + #:first? [first? #f]) + ((if first? first-speech speech) when + who + (if l + (live-link "" (a #:href l "talk video")) + "") + what + more + even-more + (or bio ""))) + +(define (hallway when) + (lecture #:when when #:who @speaker[#:person? #f]{@activity{Hallway}})) + +(define (doors-open when) + (lecture #:when when #:who @speaker[#:person? #f]{@activity{Doors Open}} + #:first? #t)) + +(define (social #:when when #:where [where ""] #:more [more ""]) + (lecture #:when when #:who @speaker[#:person? #f]{@activity{Evening Social}} + #:what where + #:more more)) + +(define (coffee when) + (lecture #:when when #:who @speaker[#:person? #f]{@activity{Coffee}})) + +(define (break when) + (lecture #:when when #:who @speaker[#:person? #f]{@activity{Break}})) + +(define (lunch when) + (lecture #:when when #:who @speaker[#:person? #f]{@activity{Lunch}})) + +(define (keynote when #:who who #:what what #:more more #:link [link #f] + #:desc [desc "Keynote"]) + (lecture #:when when #:who @speaker[#:person? #f]{@activity{@desc}} + #:what (keynote-speaker who) #:link link #:more what + #:even-more more)) + +(define (bio . contents) + (apply bio-div @bio-label{Bio: } contents)) + +(define (q content) + `(q () ,content)) + +(define (at-where name addr) + `(div () + (div ,name) + (div ,addr))) + +(define saturday (gregor:date 2025 10 4)) +(define sunday (gregor:date 2025 10 5)) +(define location "Boston, Massachusetts, USA") + +(define (meta #:itemprop [itemprop #f] + content) + (define elem (txexpr* 'meta (list (list 'content content)))) + (cond [(non-empty-string? itemprop) + (attr-set elem 'itemprop itemprop)] + [else elem])) + +(define slot-number 0) +(define (talk-time dtime) + (set! slot-number (add1 slot-number)) + (local-require racket/string gregor) + (match-define (list day times) (string-split dtime ",")) + (define d (match day + ["Saturday" saturday] + ["Sunday" sunday])) + (define t (parse-time times " h:mmaa")) + (define tz (with-timezone (on-date t d) "America/Boston")) + (define m (adjust-timezone tz "Etc/UTC")) + (talk-time-div + `(span ([data-slot-time ,(moment->iso8601 m)]) + ,(~t tz "EEEE, h:mma zz")))) + +(define nb-breakfast + @nb{Breakfast won’t be served, so please eat before coming to the event.}) + +;; ------------------------------------------------------------ + +(define page + (html #:lang "en" + (head + (head-meta #:http-equiv "content-type" #:content "text/html; charset=utf-8") + (link #:href fonts-url + #:rel "stylesheet") + (style (cdata #f #f (classes->string))) + (style (cdata #f #f "a { text-decoration: none; } ")) + `(script ([src "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"]) "") + `(script ([src "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js"]) "") + `(script ([src "https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.34/moment-timezone-with-data-10-year-range.js"]) "") + @title{(fifteenth RacketCon)} + @script{ +$(document).ready(function () { + $("[data-slot-time]").each(function() { + var date = new Date($(this).data("slot-time")); + var localTime = moment.tz(date, "America/Boston").format("dddd, h:mma zz") + $(this).html(localTime); }); }); }) + (body + #:class "main h-event" + #:itemscope "" + #:itemtype "https://schema.org/Event" + (meta #:itemprop "startDate" (gregor:~t saturday "y-MM-d")) + (meta #:itemprop "endDate" (gregor:~t sunday "y-MM-d")) + (meta #:itemprop "location" location) +(content + (banner + (title-container + (title-append + @pagetitle[(img #:style "width:140px; float: right" + #:src "https://racket-lang.org/img/racket-logo.svg" + #:alt "The Racket logo")] + @pagetitle["(fifteenth" (br) 'nbsp "RacketCon)" 'nbsp 'nbsp 'nbsp])) + @subtitle{October 4-5, 2025} + @subtitle{@p-location{UMass Boston}} + @specific-location{Boston, Massachusetts, USA} + ) + +(txexpr* 'time `((class "dt-start") (hidden "") (datetime ,(gregor:~t saturday "y-MM-dd")))) +(txexpr* 'time `((class "dt-end") (hidden "") (datetime ,(gregor:~t sunday "y-MM-dd")))) + +(column + + ;; @featuring{Special Guests TBC} + + (section + @para{RacketCon is a public gathering dedicated to fostering a + vibrant, innovative, and inclusive community around the Racket + programming language. We aim to create an exciting and enjoyable + conference open to anyone interested in Racket, filled with inspiring + content, reaching and engaging both the Racket community and the + wider programming world.}) + + (section + @sectionHeader{Call for Presentations} + + @para{We are looking for @emph{you!} If you have an idea for a presentation you’d like to give, please write to @(a #:href "mailto:con-organizers@racket-lang.org" #:title "Send mail to the RacketCon organizer" "the RacketCon organizers") for consideration. All Racket-y ideas are welcome. We’d love to have you!} + + ) + + (section + @sectionHeader{Program} + + + @para{We are looking for @emph{you!} If you have an idea for a presentation you’d like to give, please write to @(a #:href "mailto:con-organizers@racket-lang.org" #:title "Send mail to the RacketCon organizer" "the RacketCon organizers") for consideration. All Racket-y ideas are welcome. We’d love to have you!} + + ) + + (section + @sectionHeader{Registration} + @paragraph{Complete this form to be notified when registration opens, @a[#:href "https://forms.gle/omJAjAQ6xJLjsw3z8"]{Register your interest in RacketCon}. (Yes, we are planning to livestream for those who cannot attend in person, but please register so we can keep you informed.)} + ) + + (section + @sectionHeader{Accommodation} + @paragraph{At this stage, we have not made accomodation arrangements. If you would like to be notified please use the @a[#:href "https://forms.gle/omJAjAQ6xJLjsw3z8"]{Register your interest in RacketCon} form.} + ) + + (section + @sectionHeader{Friendly Policy} + @paragraph{The proceedings of RacketCon will take place under the Racket @(a #:href "https://racket-lang.org/friendly.html" "Friendly Environment Policy").} + ) + + (section + @sectionHeader{Organization} + @paragraph{The RacketCon 2025 is organised by a team of volunteers: + Stephen De Gabrielle, Robby Findler, Jacqueline Firth, Matthew Flatt, + Ben Greenman, Siddhartha Kasivajhula, Bogdan Popa, Sam Tobin-Hochstadt + and @a[#:href "https://forms.gle/omJAjAQ6xJLjsw3z8"]{Your name here} + with local arrangements by Stephen Chang. + The organizers may be reached at @(a #:href "mailto:con-organizers@racket-lang.org" "con-organizers@racket-lang.org").} + ) + + (section + @sectionHeader{Previous RacketCons} + @(apply larger + (cdr + (apply + append + (for/list ([year '(2024 2023 2022 2021 2020 2019 2018 2017 2016 2015 2014 2013 2012 2011)]) + (list " ∙ " + (a #:href (format "https://con.racket-lang.org/~a/" year) + (format "~a" year))))))))))))) + +;; ------------------------------------------------------------ + +(provide make) +(define (make p) + (with-output-to-file + (build-path p "index.html") + #:exists 'replace + (λ () + (displayln "") + (write-xexpr page)))) + +(module+ main + (require racket/runtime-path) + (define-runtime-path here ".") + (make here)) diff --git a/rcon/2025/lib.rkt b/rcon/2025/lib.rkt new file mode 100644 index 00000000..c5299263 --- /dev/null +++ b/rcon/2025/lib.rkt @@ -0,0 +1,103 @@ +#lang at-exp racket/base +(require xml + (for-syntax racket/base)) +(provide (all-defined-out)) + +(define fonts-url "https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&family=Source+Code+Pro:ital,wght@0,200..900;1,200..900&display=swap") + +(define monospace + "'Source Code Pro', monospace") + +(define-syntax-rule (define-tag* tag name extra ...) + (define name + (make-keyword-procedure + (lambda (kws kw-args . content) + (define attribs + (append + `(extra ...) + (for/list ([kw (in-list kws)] + [kw-arg (in-list kw-args)]) + `[,(string->symbol (keyword->string kw)) + ,kw-arg]))) + `(tag ,attribs . ,(decode content)))))) +(define-syntax-rule (define-tag name) + (define-tag* name name)) + +(define-tag html) +(define-tag head) +(define-tag* meta head-meta) +(define-tag link) +(define-tag style) +(define-tag title) +(define-tag body) +(define-tag img) +(define-tag a) +(define-tag ul) +(define-tag li) +(define-tag br) +(define-tag em) + +(define (decode l) + (let loop ([l l]) + (cond + [(null? l) null] + [(string? (car l)) + (append (decode-string (car l)) + (loop (cdr l)))] + [else (cons (car l) (loop (cdr l)))]))) + +(define (decode-string s) + (cond + [(regexp-match-positions #rx"'" s) + => (lambda (m) + (append (decode-string (substring s 0 (caar m))) + (list 'rsquo) + (decode-string (substring s (cdar m)))))] + [else (list s)])) + + +;; ------------------------------------------------------------ + +(define classes-b (box '())) + +(define (classes->string) + (define o (open-output-string)) + (parameterize ([current-output-port o]) + (for ([c (in-list (unbox classes-b))]) + (printf ".~a {\n" (car c)) + (for ([p (in-list (cdr c))]) + (printf "~a: ~a;\n" + (car p) (cadr p))) + (printf "}\n"))) + (get-output-string o)) + +(begin-for-syntax + (struct div (function-id class-id) + #:property prop:procedure + (lambda (self stx) + (syntax-case stx () + [(_ arg ...) #`(#,(div-function-id self) arg ...)] + [_ (div-function-id self)])))) + +(define-syntax-rule (define-styled tag name desc ...) + (begin + (define-tag* tag div-function + [class ,(symbol->string 'name)]) + (define div-class `(name desc ...)) + (set-box! classes-b (cons div-class (unbox classes-b))) + (define-syntax name (div (quote-syntax div-function) + (quote-syntax div-class))))) + +(define-syntax-rule (define-div name desc ...) + (define-styled div name desc ...)) + +(define-syntax-rule (define-a name desc ...) + (define-styled a name desc ...)) + +(define-syntax-rule (define-span name desc ...) + (define-styled span name desc ...)) + +(define centered + `((text-align center) + (margin-left auto) + (margin-right auto))) diff --git a/rcon/all.rkt b/rcon/all.rkt index a9e9ab04..5b61d163 100755 --- a/rcon/all.rkt +++ b/rcon/all.rkt @@ -68,7 +68,13 @@ (require (prefix-in 2024: "2024/index.rkt")) (define-runtime-path 2024-dir "2024") (2024:make 2024-dir) -(copy-con-site! 2024-dir 2024 #:current #t) ; change to `#:current` needs change in "sync.rkt" +(copy-con-site! 2024-dir 2024) + +;; 2025 +(require (prefix-in 2025: "2025/index.rkt")) +(define-runtime-path 2025-dir "2025") +(2025:make 2025-dir) +(copy-con-site! 2025-dir 2025 #:current #t) ; change to `#:current` needs change in "sync.rkt" ;; A `#:current #t` above causes that year's content to be copied to ;; the root directory instead of the year's subdiredtory, except that