Compare commits
2 Commits
61e3e255ea
...
d6a7449d4a
| Author | SHA1 | Date | |
|---|---|---|---|
| d6a7449d4a | |||
| 3c51066fad |
54
class.rkt
Normal file
54
class.rkt
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#lang racket/base
|
||||||
|
|
||||||
|
(require "keystore.rkt"
|
||||||
|
racket/class
|
||||||
|
)
|
||||||
|
|
||||||
|
(provide keystore%)
|
||||||
|
|
||||||
|
|
||||||
|
(define keystore%
|
||||||
|
(class object%
|
||||||
|
(init-field
|
||||||
|
[file (error "provide a filename using a path, string or use a symbol")]
|
||||||
|
)
|
||||||
|
|
||||||
|
(super-new)
|
||||||
|
|
||||||
|
(define ksh (ks-open file))
|
||||||
|
|
||||||
|
(define/public (handle)
|
||||||
|
ksh)
|
||||||
|
|
||||||
|
(define/public (set! key val)
|
||||||
|
(ks-set! ksh key val)
|
||||||
|
this)
|
||||||
|
|
||||||
|
(define/public (get key . default-val)
|
||||||
|
(if (null? default-val)
|
||||||
|
(ks-get ksh key)
|
||||||
|
(ks-get ksh key (car default-val))))
|
||||||
|
|
||||||
|
(define/public (drop! key)
|
||||||
|
(ks-drop! ksh key)
|
||||||
|
this)
|
||||||
|
|
||||||
|
(define/public (exists? key)
|
||||||
|
(ks-exists? ksh key))
|
||||||
|
|
||||||
|
(define/public (glob gl)
|
||||||
|
(ks-keys-glob ksh gl))
|
||||||
|
|
||||||
|
(define/public (glob-kv gl)
|
||||||
|
(ks-key-values-glob ksh gl))
|
||||||
|
|
||||||
|
(define/public (keys-glob gl)
|
||||||
|
(ks-keys-glob ksh gl))
|
||||||
|
|
||||||
|
(define/public (keys)
|
||||||
|
(ks-keys ksh))
|
||||||
|
|
||||||
|
(define/public (key-values)
|
||||||
|
(ks-key-values ksh))
|
||||||
|
)
|
||||||
|
)
|
||||||
37
info.rkt
Normal file
37
info.rkt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#lang info
|
||||||
|
|
||||||
|
(define pkg-authors '(hnmdijkema))
|
||||||
|
(define version "0.1.1")
|
||||||
|
(define license 'MIT)
|
||||||
|
(define collection "keystore")
|
||||||
|
(define pkg-desc "keystore - A keystore for keys/values using the racket db/sqlite module as basis")
|
||||||
|
|
||||||
|
(define scribblings
|
||||||
|
'(
|
||||||
|
("scrbl/keystore.scrbl" () (library) "keystore")
|
||||||
|
("scrbl/class.scrbl" () (library) "keystore/class")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(define deps
|
||||||
|
'("racket/base"
|
||||||
|
"racket/class"
|
||||||
|
"db"
|
||||||
|
"racket/contract"
|
||||||
|
"racket/serialize"
|
||||||
|
"racket/port"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(define build-deps
|
||||||
|
'("racket-doc"
|
||||||
|
"draw-doc"
|
||||||
|
"rackunit-lib"
|
||||||
|
"scribble-lib"
|
||||||
|
"db"
|
||||||
|
"racket/port"
|
||||||
|
"racket/contract"
|
||||||
|
"racket/serialize"
|
||||||
|
"racket/class"
|
||||||
|
))
|
||||||
|
|
||||||
135
keystore.rkt
Normal file
135
keystore.rkt
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#lang racket/base
|
||||||
|
|
||||||
|
(require racket/contract
|
||||||
|
racket/serialize
|
||||||
|
racket/port
|
||||||
|
db
|
||||||
|
)
|
||||||
|
|
||||||
|
(provide ks-open
|
||||||
|
ks-set!
|
||||||
|
ks-get
|
||||||
|
ks-drop!
|
||||||
|
ks-exists?
|
||||||
|
ks-keys
|
||||||
|
ks-keys-glob
|
||||||
|
ks-key-values-glob
|
||||||
|
ks-key-values
|
||||||
|
ks-key-values-raw
|
||||||
|
ks-keys-raw
|
||||||
|
)
|
||||||
|
|
||||||
|
(define-struct keystore
|
||||||
|
(file path dbh)
|
||||||
|
#:transparent
|
||||||
|
)
|
||||||
|
|
||||||
|
(define/contract (ks-open file)
|
||||||
|
(-> (or/c path? string? symbol?) keystore?)
|
||||||
|
(let ((path (if (symbol? file)
|
||||||
|
(build-path (find-system-path 'cache-dir) (format "ks-~a.db" file))
|
||||||
|
(build-path file))))
|
||||||
|
(let ((dbh (sqlite3-connect #:database path #:mode 'create)))
|
||||||
|
(query-exec dbh "CREATE TABLE IF NOT EXISTS keystore(key varchar primary key, value varchar, str_key varchar);")
|
||||||
|
(query-exec dbh "CREATE INDEX IF NOT EXISTS keystore_idx on keystore(str_key);")
|
||||||
|
(make-keystore file path dbh))))
|
||||||
|
|
||||||
|
(define/contract (ks-set! ksh key value)
|
||||||
|
(-> keystore? any/c any/c boolean?)
|
||||||
|
(ks-set!* (keystore-dbh ksh) (value->string key) (format "~a" key) (value->string value)))
|
||||||
|
|
||||||
|
(define/contract (ks-exists? ksh key)
|
||||||
|
(-> keystore? any/c boolean?)
|
||||||
|
(ks-exists?* (keystore-dbh ksh) (value->string key)))
|
||||||
|
|
||||||
|
(define/contract (ks-get ksh key . default-value)
|
||||||
|
(-> keystore? any/c ... any/c any/c)
|
||||||
|
(ks-get* (keystore-dbh ksh) (value->string key) default-value))
|
||||||
|
|
||||||
|
(define/contract (ks-drop! ksh key)
|
||||||
|
(-> keystore? any/c boolean?)
|
||||||
|
(ks-drop!* (keystore-dbh ksh) (value->string key)))
|
||||||
|
|
||||||
|
(define/contract (ks-key-values-glob ksh gl)
|
||||||
|
(-> keystore? string? list?)
|
||||||
|
(map (λ (row)
|
||||||
|
(cons (string->value (vector-ref row 0)) (string->value (vector-ref row 1))))
|
||||||
|
(query-rows (keystore-dbh ksh)
|
||||||
|
"SELECT key, value FROM keystore WHERE str_key GLOB $1"
|
||||||
|
(string-downcase gl))))
|
||||||
|
|
||||||
|
(define/contract (ks-keys-glob ksh sqlite-like)
|
||||||
|
(-> keystore? string? list?)
|
||||||
|
(map (λ (row)
|
||||||
|
(string->value (vector-ref row 0)))
|
||||||
|
(query-rows (keystore-dbh ksh)
|
||||||
|
"SELECT key FROM keystore WHERE str_key GLOB $1"
|
||||||
|
(string-downcase sqlite-like))))
|
||||||
|
|
||||||
|
(define/contract (ks-keys ksh)
|
||||||
|
(-> keystore? list?)
|
||||||
|
(ks-keys* (keystore-dbh ksh)))
|
||||||
|
|
||||||
|
(define/contract (ks-key-values ksh)
|
||||||
|
(-> keystore? list?)
|
||||||
|
(ks-key-values* (keystore-dbh ksh)))
|
||||||
|
|
||||||
|
(define/contract (ks-keys-raw ksh)
|
||||||
|
(-> keystore? list?)
|
||||||
|
(map vector->list
|
||||||
|
(query-rows (keystore-dbh ksh) "SELECT key, str_key FROM keystore")))
|
||||||
|
|
||||||
|
(define/contract (ks-key-values-raw ksh)
|
||||||
|
(-> keystore? list?)
|
||||||
|
(map vector->list
|
||||||
|
(query-rows (keystore-dbh ksh) "SELECT key, str_key, value FROM keystore")))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Internal working
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
|
||||||
|
(define (ks-set!* dbh key str-key value)
|
||||||
|
(query-exec dbh "INSERT OR REPLACE INTO keystore VALUES($1, $2, $3)"
|
||||||
|
key value (string-downcase str-key))
|
||||||
|
#t)
|
||||||
|
|
||||||
|
(define (ks-exists?* dbh key)
|
||||||
|
(> (query-value dbh "SELECT COUNT(*) FROM keystore WHERE key = $1" key) 0))
|
||||||
|
|
||||||
|
(define (ks-get* dbh key default-value)
|
||||||
|
(if (ks-exists?* dbh key)
|
||||||
|
(string->value (query-value dbh "SELECT value FROM keystore WHERE key = $1" key))
|
||||||
|
(if (null? default-value)
|
||||||
|
'ks-nil
|
||||||
|
(car default-value))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(define (ks-drop!* dbh key)
|
||||||
|
(query-exec dbh "DELETE FROM keystore WHERE key = $1" key)
|
||||||
|
#t)
|
||||||
|
|
||||||
|
(define (ks-keys* dbh)
|
||||||
|
(map (λ (row)
|
||||||
|
(string->value (vector-ref row 0)))
|
||||||
|
(query-rows dbh "SELECT key FROM keystore")))
|
||||||
|
|
||||||
|
(define (ks-key-values* dbh)
|
||||||
|
(map (λ (row)
|
||||||
|
(cons (string->value (vector-ref row 0))
|
||||||
|
(string->value (vector-ref row 1))))
|
||||||
|
(query-rows dbh "SELECT key, value FROM keystore")))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; serialization
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(define (value->string v)
|
||||||
|
(call-with-output-string
|
||||||
|
(λ (out) (write (serialize v) out))))
|
||||||
|
|
||||||
|
(define (string->value v)
|
||||||
|
(deserialize
|
||||||
|
(call-with-input-string v (λ (in) (read in)))))
|
||||||
|
|
||||||
7
main.rkt
Normal file
7
main.rkt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#lang racket/base
|
||||||
|
|
||||||
|
|
||||||
|
(require "keystore.rkt")
|
||||||
|
|
||||||
|
(provide (all-from-out "keystore.rkt"))
|
||||||
|
|
||||||
5
scrbl/.gitignore
vendored
Normal file
5
scrbl/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
*.html
|
||||||
|
*.js
|
||||||
|
*.css
|
||||||
|
*~
|
||||||
|
*.bak
|
||||||
6
scrbl/class.html
Normal file
6
scrbl/class.html
Normal file
File diff suppressed because one or more lines are too long
108
scrbl/class.scrbl
Normal file
108
scrbl/class.scrbl
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
#lang scribble/manual
|
||||||
|
|
||||||
|
@(require (for-label racket/base
|
||||||
|
racket/class
|
||||||
|
"../keystore.rkt"
|
||||||
|
"../class.rkt"))
|
||||||
|
|
||||||
|
@title{Keystore Class}
|
||||||
|
|
||||||
|
@defmodule[keystore/class]
|
||||||
|
|
||||||
|
An object-oriented wrapper around @racketmodname[keystore]. It provides
|
||||||
|
a small class interface to the persistent key–value store.
|
||||||
|
|
||||||
|
@defclass[keystore% object% ()]{
|
||||||
|
|
||||||
|
A keystore class backed by SQLite.
|
||||||
|
|
||||||
|
@defconstructor[([file (or/c path? string? symbol?)])]{
|
||||||
|
|
||||||
|
Opens or creates a keystore using @racket[file]. The meaning of
|
||||||
|
@racket[file] is the same as for @racket[ks-open].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(handle) keystore?]{
|
||||||
|
|
||||||
|
Returns the underlying keystore handle.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(set! [key any/c] [value any/c]) (is-a?/c keystore%)]{
|
||||||
|
|
||||||
|
Stores @racket[value] under @racket[key]. Returns the object itself,
|
||||||
|
so method calls may be nested.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(get [key any/c] [default any/c] ...) any/c]{
|
||||||
|
|
||||||
|
Retrieves the value associated with @racket[key]. If no value is found,
|
||||||
|
the optional default is returned; otherwise @racket['ks-nil] is returned.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(drop! [key any/c]) (is-a?/c keystore%)]{
|
||||||
|
|
||||||
|
Removes @racket[key] from the store and returns the object itself.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(exists? [key any/c]) boolean?]{
|
||||||
|
|
||||||
|
Returns @racket[#t] if @racket[key] exists, and @racket[#f] otherwise.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(glob [pattern string?]) (listof any/c)]{
|
||||||
|
|
||||||
|
Returns keys matching @racket[pattern].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(glob-kv [pattern string?]) (listof (cons/c any/c any/c))]{
|
||||||
|
|
||||||
|
Returns key–value pairs matching @racket[pattern].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(keys-glob [pattern string?]) (listof any/c)]{
|
||||||
|
|
||||||
|
Alias for @racket[glob].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(keys) (listof any/c)]{
|
||||||
|
|
||||||
|
Returns all keys.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(key-values) (listof (cons/c any/c any/c))]{
|
||||||
|
|
||||||
|
Returns all key–value pairs.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Examples}
|
||||||
|
|
||||||
|
@subsection{Basic Usage}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(define ks (new keystore% [file 'demo]))
|
||||||
|
|
||||||
|
(send ks set! 'a 42)
|
||||||
|
(send ks set! "b" '(1 2 3))
|
||||||
|
|
||||||
|
(send ks get 'a) ; => 42
|
||||||
|
(send ks get 'missing) ; => 'ks-nil
|
||||||
|
(send ks get 'missing 0) ; => 0
|
||||||
|
]
|
||||||
|
|
||||||
|
@subsection{Nested Calls}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(define ks (new keystore% [file 'demo]))
|
||||||
|
|
||||||
|
(send (send (send ks set! 'a 1)
|
||||||
|
set! 'b 2)
|
||||||
|
drop! 'a)
|
||||||
|
]
|
||||||
|
|
||||||
|
@subsection{Glob Queries}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(send ks glob "*b*")
|
||||||
|
(send ks glob-kv "*b*")
|
||||||
|
]
|
||||||
119
scrbl/class.scrbl~
Normal file
119
scrbl/class.scrbl~
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#lang scribble/manual
|
||||||
|
|
||||||
|
@title{Keystore Class}
|
||||||
|
|
||||||
|
@defmodule[keystore/class]
|
||||||
|
|
||||||
|
An object-oriented wrapper around @racketmodname[keystore], providing
|
||||||
|
a small fluent interface for working with a persistent key–value store.
|
||||||
|
|
||||||
|
@section{Class}
|
||||||
|
|
||||||
|
@defclass[keystore% object% ()]{
|
||||||
|
|
||||||
|
Creates a keystore instance backed by SQLite.
|
||||||
|
|
||||||
|
@defconstructor[([file (or/c path? string? symbol?)])]{
|
||||||
|
|
||||||
|
Opens or creates a keystore using @racket[file]. The interpretation
|
||||||
|
of @racket[file] is identical to @racket[ks-open].
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Methods}
|
||||||
|
|
||||||
|
@defmethod[(handle) keystore?]{
|
||||||
|
|
||||||
|
Returns the underlying keystore handle as produced by @racket[ks-open].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(set! [key any/c] [value any/c]) (is-a?/c keystore%)]{
|
||||||
|
|
||||||
|
Stores @racket[value] under @racket[key]. The method returns the
|
||||||
|
instance itself, allowing chaining.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(get [key any/c] [default any/c] ...) any/c]{
|
||||||
|
|
||||||
|
Retrieves the value associated with @racket[key]. If no value is found,
|
||||||
|
the optional default is returned; otherwise @racket['ks-nil] is returned.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(drop! [key any/c]) (is-a?/c keystore%)]{
|
||||||
|
|
||||||
|
Removes @racket[key] and returns the instance.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(exists? [key any/c]) boolean?]{
|
||||||
|
|
||||||
|
Checks whether @racket[key] exists.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(keys) (listof any/c)]{
|
||||||
|
|
||||||
|
Returns all keys.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(key-values) (listof (cons/c any/c any/c))]{
|
||||||
|
|
||||||
|
Returns all key–value pairs.
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Glob Queries}
|
||||||
|
|
||||||
|
Glob operations match against the lowercase string representation of keys.
|
||||||
|
|
||||||
|
@defmethod[(glob [pattern string?]) (listof any/c)]{
|
||||||
|
|
||||||
|
Returns keys matching @racket[pattern].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(keys-glob [pattern string?]) (listof any/c)]{
|
||||||
|
|
||||||
|
Alias for @racket[glob].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defmethod[(glob-kv [pattern string?])
|
||||||
|
(listof (cons/c any/c any/c))]{
|
||||||
|
|
||||||
|
Returns key–value pairs matching @racket[pattern].
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Examples}
|
||||||
|
|
||||||
|
@subsection{Basic Usage}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(define ks (new keystore% [file 'demo]))
|
||||||
|
|
||||||
|
(send ks set! 'a 42)
|
||||||
|
(send ks set! "b" '(1 2 3))
|
||||||
|
|
||||||
|
(send ks get 'a) ; => 42
|
||||||
|
(send ks get 'missing) ; => 'ks-nil
|
||||||
|
(send ks get 'missing 0) ; => 0
|
||||||
|
]
|
||||||
|
|
||||||
|
@subsection{Chaining}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(define ks (new keystore% [file 'demo]))
|
||||||
|
|
||||||
|
(send ks
|
||||||
|
set! 'a 1)
|
||||||
|
set! 'b 2)
|
||||||
|
drop! 'a))
|
||||||
|
]
|
||||||
|
|
||||||
|
@subsection{Glob Queries}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(send ks glob "*b*")
|
||||||
|
(send ks glob-kv "*b*")
|
||||||
|
]
|
||||||
|
|
||||||
|
@section{Notes}
|
||||||
|
|
||||||
|
This class is a thin wrapper around @racketmodname[keystore]. All
|
||||||
|
semantics, including serialization and glob matching, are inherited
|
||||||
|
directly from the underlying functional API.
|
||||||
|
}
|
||||||
139
scrbl/keystore.scrbl
Normal file
139
scrbl/keystore.scrbl
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#lang scribble/manual
|
||||||
|
|
||||||
|
@title{Keystore}
|
||||||
|
|
||||||
|
@defmodule[keystore]
|
||||||
|
|
||||||
|
A small persistent key–value store backed by SQLite. Keys and values
|
||||||
|
may be arbitrary Racket values and are stored using transparent
|
||||||
|
serialization.
|
||||||
|
|
||||||
|
@section{Overview}
|
||||||
|
|
||||||
|
The keystore provides persistent storage with automatic
|
||||||
|
serialization and deserialization. Keys are additionally stored in a
|
||||||
|
stringified lowercase form, which allows glob-style queries.
|
||||||
|
|
||||||
|
@section{Structure}
|
||||||
|
|
||||||
|
@defstruct*[keystore
|
||||||
|
([file any/c]
|
||||||
|
[path path?]
|
||||||
|
[dbh any/c])]{
|
||||||
|
|
||||||
|
Represents an open keystore. The @racket[file] field contains the
|
||||||
|
original argument, @racket[path] is the resolved database path, and
|
||||||
|
@racket[dbh] is the SQLite connection.
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Opening}
|
||||||
|
|
||||||
|
@defproc[(ks-open [file (or/c path? string? symbol?)]) keystore?]{
|
||||||
|
|
||||||
|
Opens or creates a keystore. When @racket[file] is a symbol, a cache
|
||||||
|
location is used; otherwise it is interpreted as a filesystem path.
|
||||||
|
The database schema is created automatically if it does not yet exist.
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Basic Operations}
|
||||||
|
|
||||||
|
@defproc[(ks-set! [ks keystore?] [key any/c] [value any/c]) boolean?]{
|
||||||
|
|
||||||
|
Stores @racket[value] under @racket[key], replacing any existing value.
|
||||||
|
The function always returns @racket[#t].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-get [ks keystore?] [key any/c] [default any/c] ...) any/c]{
|
||||||
|
|
||||||
|
Retrieves the value associated with @racket[key]. If the key is not
|
||||||
|
present, the provided default value is returned when given; otherwise
|
||||||
|
the symbol @racket['ks-nil] is returned.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-exists? [ks keystore?] [key any/c]) boolean?]{
|
||||||
|
|
||||||
|
Returns @racket[#t] if the key exists, and @racket[#f] otherwise.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-drop! [ks keystore?] [key any/c]) boolean?]{
|
||||||
|
|
||||||
|
Removes the key from the store. The function always returns @racket[#t].
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Enumeration}
|
||||||
|
|
||||||
|
@defproc[(ks-keys [ks keystore?]) (listof any/c)]{
|
||||||
|
|
||||||
|
Returns all keys in the store.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-key-values [ks keystore?]) (listof (cons/c any/c any/c))]{
|
||||||
|
|
||||||
|
Returns all key–value pairs as cons cells.
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Glob Queries}
|
||||||
|
|
||||||
|
Glob queries operate on a lowercase string representation of keys.
|
||||||
|
|
||||||
|
@defproc[(ks-keys-glob [ks keystore?] [pattern string?]) (listof any/c)]{
|
||||||
|
|
||||||
|
Returns all keys whose string form matches @racket[pattern].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-key-values-glob [ks keystore?] [pattern string?])
|
||||||
|
(listof (cons/c any/c any/c))]{
|
||||||
|
|
||||||
|
Returns key–value pairs whose keys match @racket[pattern].
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Raw Access}
|
||||||
|
|
||||||
|
@defproc[(ks-keys-raw [ks keystore?]) list?]{
|
||||||
|
|
||||||
|
Returns raw key rows in the form:
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(list key-string str-key)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-key-values-raw [ks keystore?]) list?]{
|
||||||
|
|
||||||
|
Returns raw key–value rows in the form:
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(list key-string str-key value-string)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Examples}
|
||||||
|
|
||||||
|
@subsection{Basic Usage}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(define ks (ks-open 'demo))
|
||||||
|
|
||||||
|
(ks-set! ks 'a 42)
|
||||||
|
(ks-set! ks "b" '(1 2 3))
|
||||||
|
|
||||||
|
(ks-get ks 'a) ; => 42
|
||||||
|
(ks-get ks 'missing) ; => 'ks-nil
|
||||||
|
(ks-get ks 'missing 0) ; => 0
|
||||||
|
]
|
||||||
|
|
||||||
|
@subsection{Enumeration Example}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(ks-keys ks)
|
||||||
|
;; => '(a "b")
|
||||||
|
|
||||||
|
(ks-key-values ks)
|
||||||
|
;; => '((a . 42) ("b" . (1 2 3)))
|
||||||
|
]
|
||||||
|
|
||||||
|
@subsection{Glob Query Example}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(ks-keys-glob ks "*b*")
|
||||||
|
]
|
||||||
139
scrbl/keystore.scrbl~
Normal file
139
scrbl/keystore.scrbl~
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#lang scribble/manual
|
||||||
|
|
||||||
|
@title{Keystore}
|
||||||
|
|
||||||
|
@defmodule[keystore]
|
||||||
|
|
||||||
|
A small persistent key–value store backed by SQLite. Keys and values
|
||||||
|
may be arbitrary Racket values and are stored using transparent
|
||||||
|
serialization.
|
||||||
|
|
||||||
|
@section{Overview}
|
||||||
|
|
||||||
|
The keystore provides persistent storage with automatic
|
||||||
|
serialization and deserialization. Keys are additionally stored in a
|
||||||
|
stringified lowercase form, which allows glob-style queries.
|
||||||
|
|
||||||
|
@section{Structure}
|
||||||
|
|
||||||
|
@defstruct*[keystore
|
||||||
|
([file any/c]
|
||||||
|
[path path?]
|
||||||
|
[dbh any/c])]{
|
||||||
|
|
||||||
|
Represents an open keystore. The @racket[file] field contains the
|
||||||
|
original argument, @racket[path] is the resolved database path, and
|
||||||
|
@racket[dbh] is the SQLite connection.
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Opening}
|
||||||
|
|
||||||
|
@defproc[(ks-open [file (or/c path? string? symbol?)]) keystore?]{
|
||||||
|
|
||||||
|
Opens or creates a keystore. When @racket[file] is a symbol, a cache
|
||||||
|
location is used; otherwise it is interpreted as a filesystem path.
|
||||||
|
The database schema is created automatically if it does not yet exist.
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Basic Operations}
|
||||||
|
|
||||||
|
@defproc[(ks-set! [ks keystore?] [key any/c] [value any/c]) boolean?]{
|
||||||
|
|
||||||
|
Stores @racket[value] under @racket[key], replacing any existing value.
|
||||||
|
The function always returns @racket[#t].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-get [ks keystore?] [key any/c] [default any/c] ...) any/c]{
|
||||||
|
|
||||||
|
Retrieves the value associated with @racket[key]. If the key is not
|
||||||
|
present, the provided default value is returned when given; otherwise
|
||||||
|
the symbol @racket['ks-nil] is returned.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-exists? [ks keystore?] [key any/c]) boolean?]{
|
||||||
|
|
||||||
|
Returns @racket[#t] if the key exists, and @racket[#f] otherwise.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-drop! [ks keystore?] [key any/c]) boolean?]{
|
||||||
|
|
||||||
|
Removes the key from the store. The function always returns @racket[#t].
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Enumeration}
|
||||||
|
|
||||||
|
@defproc[(ks-keys [ks keystore?]) (listof any/c)]{
|
||||||
|
|
||||||
|
Returns all keys in the store.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-key-values [ks keystore?]) (listof (cons/c any/c any/c))]{
|
||||||
|
|
||||||
|
Returns all key–value pairs as cons cells.
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Glob Queries}
|
||||||
|
|
||||||
|
Glob queries operate on a lowercase string representation of keys.
|
||||||
|
|
||||||
|
@defproc[(ks-keys-glob [ks keystore?] [pattern string?]) (listof any/c)]{
|
||||||
|
|
||||||
|
Returns all keys whose string form matches @racket[pattern].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-key-values-glob [ks keystore?] [pattern string?])
|
||||||
|
(listof (cons/c any/c any/c))]{
|
||||||
|
|
||||||
|
Returns key–value pairs whose keys match @racket[pattern].
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Raw Access}
|
||||||
|
|
||||||
|
@defproc[(ks-keys-raw [ks keystore?]) list?]{
|
||||||
|
|
||||||
|
Returns raw key rows in the form:
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(list key-string str-key)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
@defproc[(ks-key-values-raw [ks keystore?]) list?]{
|
||||||
|
|
||||||
|
Returns raw key–value rows in the form:
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(list key-string str-key value-string)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
@section{Examples}
|
||||||
|
|
||||||
|
@subsection{Basic Usage}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(define ks (ks-open 'demo))
|
||||||
|
|
||||||
|
(ks-set! ks 'a 42)
|
||||||
|
(ks-set! ks "b" '(1 2 3))
|
||||||
|
|
||||||
|
(ks-get ks 'a) ; => 42
|
||||||
|
(ks-get ks 'missing) ; => 'ks-nil
|
||||||
|
(ks-get ks 'missing 0) ; => 0
|
||||||
|
]
|
||||||
|
|
||||||
|
@subsection{Enumeration}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(ks-keys ks)
|
||||||
|
;; => '(a "b")
|
||||||
|
|
||||||
|
(ks-key-values ks)
|
||||||
|
;; => '((a . 42) ("b" . (1 2 3)))
|
||||||
|
]
|
||||||
|
|
||||||
|
@subsection{Glob Queries}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(ks-keys-glob ks "*b*")
|
||||||
|
]
|
||||||
251
scrbl/manual-fonts.css
Normal file
251
scrbl/manual-fonts.css
Normal file
File diff suppressed because one or more lines are too long
326
scrbl/manual-racket.css
Normal file
326
scrbl/manual-racket.css
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
/* See the beginning of "manual.css". */
|
||||||
|
|
||||||
|
/* Monospace: */
|
||||||
|
|
||||||
|
.RktIn, .RktRdr, .RktPn, .RktMeta,
|
||||||
|
.RktMod, .RktKw, .RktVar, .RktSym,
|
||||||
|
.RktRes, .RktOut, .RktCmt, .RktVal,
|
||||||
|
.RktBlk, .RktErr {
|
||||||
|
font-family: 'Fira-Mono', monospace;
|
||||||
|
white-space: inherit;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this selctor grabs the first linked Racket symbol
|
||||||
|
in a definition box (i.e., the symbol being defined) */
|
||||||
|
a.RktValDef, a.RktStxDef, a.RktSymDef,
|
||||||
|
span.RktValDef, span.RktStxDef, span.RktSymDef
|
||||||
|
{
|
||||||
|
font-size: 1.1rem;
|
||||||
|
color: black;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.inheritedlbl {
|
||||||
|
font-family: 'Fira', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RBackgroundLabelInner {
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Inherited methods, left margin */
|
||||||
|
|
||||||
|
.inherited {
|
||||||
|
width: 95%;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
text-align: left;
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inherited td {
|
||||||
|
font-size: 82%;
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
text-indent: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inheritedlbl {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Racket text styles */
|
||||||
|
|
||||||
|
.RktIn {
|
||||||
|
color: #cc6633;
|
||||||
|
background-color: #eee;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktInBG {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.refcolumn .RktInBG {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktRdr {
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktPn {
|
||||||
|
color: #843c24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktMeta {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktMod {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktOpt {
|
||||||
|
color: black;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktKw {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktErr {
|
||||||
|
color: red;
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktVar {
|
||||||
|
position: relative;
|
||||||
|
left: -1px; font-style: italic;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SVInsetFlow .RktVar {
|
||||||
|
font-weight: 400;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.RktSym {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.RktValLink, .RktStxLink, .RktModLink {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #07A;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for syntax links within headings */
|
||||||
|
h1 a.RktStxLink, h2 a.RktStxLink, h3 a.RktStxLink, h4 a.RktStxLink, h5 a.RktStxLink,
|
||||||
|
h1 a.RktValLink, h2 a.RktValLink, h3 a.RktValLink, h4 a.RktValLink, h5 a.RktValLink,
|
||||||
|
h1 .RktSym, h2 .RktSym, h3 .RktSym, h4 .RktSym, h5 .RktSym,
|
||||||
|
h1 .RktMod, h2 .RktMod, h3 .RktMod, h4 .RktMod, h5 .RktMod,
|
||||||
|
h1 .RktVal, h2 .RktVal, h3 .RktVal, h4 .RktVal, h5 .RktVal,
|
||||||
|
h1 .RktPn, h2 .RktPn, h3 .RktPn, h4 .RktPn, h5 .RktPn {
|
||||||
|
color: #333;
|
||||||
|
font-size: 1.50rem;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toptoclink .RktStxLink, .toclink .RktStxLink,
|
||||||
|
.toptoclink .RktValLink, .toclink .RktValLink,
|
||||||
|
.toptoclink .RktModLink, .toclink .RktModLink {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocset .RktValLink, .tocset .RktStxLink, .tocset .RktModLink, .tocset .RktSym {
|
||||||
|
color: black;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocset td a.tocviewselflink .RktValLink,
|
||||||
|
.tocset td a.tocviewselflink .RktStxLink,
|
||||||
|
.tocset td a.tocviewselflink .RktMod,
|
||||||
|
.tocset td a.tocviewselflink .RktSym {
|
||||||
|
font-weight: lighter;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.RktRes {
|
||||||
|
color: #0000af;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktOut {
|
||||||
|
color: #960096;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktCmt {
|
||||||
|
color: #c2741f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktVal {
|
||||||
|
color: #228b22;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Some inline styles */
|
||||||
|
|
||||||
|
.together { /* for definitions grouped together in one box */
|
||||||
|
width: 100%;
|
||||||
|
border-top: 2px solid white;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody > tr:first-child > td > .together {
|
||||||
|
border-top: 0px; /* erase border on first instance of together */
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktBlk {
|
||||||
|
white-space: pre;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlighted {
|
||||||
|
font-size: 1rem;
|
||||||
|
background-color: #fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.defmodule {
|
||||||
|
font-family: 'Fira-Mono', monospace;
|
||||||
|
padding: 0.25rem 0.75rem 0.25rem 0.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #ebf0f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.defmodule a {
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.defmodule td span.hspace:first-child {
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.defmodule .RpackageSpec .Smaller,
|
||||||
|
.defmodule .RpackageSpec .stt {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make parens ordinary color in defmodule */
|
||||||
|
.defmodule .RktPn {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.specgrammar {
|
||||||
|
float: none;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.RBibliography td {
|
||||||
|
vertical-align: text-top;
|
||||||
|
padding-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leftindent {
|
||||||
|
margin-left: 2rem;
|
||||||
|
margin-right: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.insetpara {
|
||||||
|
margin-left: 1em;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SCodeFlow .Rfilebox {
|
||||||
|
margin-left: -1em; /* see 17.2 of guide, module languages */
|
||||||
|
}
|
||||||
|
|
||||||
|
.Rfiletitle {
|
||||||
|
text-align: right;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SCodeFlow .Rfiletitle {
|
||||||
|
border-top: 1px dotted gray;
|
||||||
|
border-right: 1px dotted gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.Rfilename {
|
||||||
|
border-top: 0;
|
||||||
|
border-right: 0;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Rfilecontent {
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RpackageSpec {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* For background labels */
|
||||||
|
|
||||||
|
.RBackgroundLabel {
|
||||||
|
float: right;
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RBackgroundLabelInner {
|
||||||
|
position: relative;
|
||||||
|
width: 25em;
|
||||||
|
left: -25.5em;
|
||||||
|
top: 0.20rem; /* sensitive to monospaced font choice */
|
||||||
|
text-align: right;
|
||||||
|
z-index: 0;
|
||||||
|
font-weight: 300;
|
||||||
|
font-family: 'Fira-Mono', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.RpackageSpec .Smaller {
|
||||||
|
font-weight: 300;
|
||||||
|
font-family: 'Fira-Mono', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RForeground {
|
||||||
|
position: relative;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* For section source modules & tags */
|
||||||
|
|
||||||
|
.RPartExplain {
|
||||||
|
background: #eee;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-top: 0.2rem;
|
||||||
|
padding: 0.2rem;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
250
scrbl/manual-racket.js
Normal file
250
scrbl/manual-racket.js
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
/* For the Racket manual style */
|
||||||
|
|
||||||
|
AddOnLoad(function() {
|
||||||
|
/* Look for header elements that have x-source-module and x-part tag.
|
||||||
|
For those elements, add a hidden element that explains how to
|
||||||
|
link to the section, and set the element's onclick() to display
|
||||||
|
the explanation. */
|
||||||
|
var tag_names = ["h1", "h2", "h3", "h4", "h5"];
|
||||||
|
for (var j = 0; j < tag_names.length; j++) {
|
||||||
|
elems = document.getElementsByTagName(tag_names[j]);
|
||||||
|
for (var i = 0; i < elems.length; i++) {
|
||||||
|
var elem = elems.item(i);
|
||||||
|
AddPartTitleOnClick(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// cache of source urls
|
||||||
|
var cache = {};
|
||||||
|
|
||||||
|
function ParseSource(source, mod_path, single_collection) {
|
||||||
|
|
||||||
|
var source_url = new URL(source);
|
||||||
|
|
||||||
|
if (source_url.protocol == "github:") {
|
||||||
|
// browser URL parser only works with http(s) URLs
|
||||||
|
source_url = new URL("https" + source.substring(6));
|
||||||
|
var host = source_url.host;
|
||||||
|
var url_path = source_url.pathname.substring(1).split("/");
|
||||||
|
if (!(url_path.length >= 2)) return null;
|
||||||
|
var user = url_path.shift();
|
||||||
|
var repo = url_path.shift();
|
||||||
|
var branch = url_path.shift();
|
||||||
|
var source_path = url_path.join("/");
|
||||||
|
}
|
||||||
|
else if (("https:" == source_url.protocol) || ("git:" == source_url.protocol)) {
|
||||||
|
// browser URL parser only works with http(s) URLs
|
||||||
|
if ("git:" == source_url.protocol)
|
||||||
|
source_url = new URL("https" + source.substring(3));
|
||||||
|
|
||||||
|
var host = source_url.host;
|
||||||
|
var source_path = source_url.searchParams.get("path");
|
||||||
|
var branch = (source_url.hash || "#master").substring(1);
|
||||||
|
var url_path = source_url.pathname.substring(1).split("/");
|
||||||
|
if (url_path.length < 2) throw [source_url.pathname, url_path];
|
||||||
|
var user = url_path.shift();
|
||||||
|
var repo = url_path.shift();
|
||||||
|
var mtch = repo.match(/(.*)\.git$/);
|
||||||
|
if (mtch) repo = mtch[1];
|
||||||
|
|
||||||
|
}
|
||||||
|
else return null;
|
||||||
|
|
||||||
|
var mod_path_re = /^\(lib "(.+)"\)$/;
|
||||||
|
|
||||||
|
var mod_path_elems = mod_path && mod_path.match(mod_path_re)[1].split("/");
|
||||||
|
|
||||||
|
if (!user || !repo || !mod_path_elems)
|
||||||
|
return null;
|
||||||
|
if (single_collection)
|
||||||
|
mod_path_elems.shift();
|
||||||
|
|
||||||
|
var file_path = mod_path_elems.join("/");
|
||||||
|
|
||||||
|
|
||||||
|
if (source_path) {
|
||||||
|
file_path = source_path + "/" + file_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { user: user,
|
||||||
|
repo: repo,
|
||||||
|
file_path: file_path,
|
||||||
|
branch: branch,
|
||||||
|
host: host };
|
||||||
|
}
|
||||||
|
|
||||||
|
function AddSourceElement(pkg_url, info) {
|
||||||
|
info.appendChild(document.createTextNode("Document source "));
|
||||||
|
var url_line = document.createElement("div");
|
||||||
|
var a = document.createElement("a");
|
||||||
|
a.href = pkg_url;
|
||||||
|
a.style.whiteSpace = "nowrap";
|
||||||
|
a.appendChild(document.createTextNode(pkg_url));
|
||||||
|
addSpan(url_line, "\xA0", "RktRdr");
|
||||||
|
url_line.appendChild(a);
|
||||||
|
info.appendChild(url_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
var prefixes = { "github.com": "tree",
|
||||||
|
"gitlab.com": "-/blob" };
|
||||||
|
|
||||||
|
|
||||||
|
function AddSourceUrl(source, mod_path, collection, info) {
|
||||||
|
// multi is encoded as an array, empty as false
|
||||||
|
single_collection = (typeof collection === "string");
|
||||||
|
|
||||||
|
var parsed = source && mod_path && ParseSource(source, mod_path, single_collection);
|
||||||
|
|
||||||
|
if (!parsed) return;
|
||||||
|
|
||||||
|
prefix = prefixes.hasOwnProperty(parsed.host) && prefixes[parsed.host];
|
||||||
|
if (!prefix) return;
|
||||||
|
|
||||||
|
var correct_url = "https://" + [parsed.host, parsed.user, parsed.repo, prefix, parsed.branch, parsed.file_path].join("/");
|
||||||
|
|
||||||
|
if (info) AddSourceElement(correct_url, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSpan(dest, str, cn) {
|
||||||
|
var s = document.createElement("span");
|
||||||
|
s.className = cn;
|
||||||
|
s.style.whiteSpace = "nowrap";
|
||||||
|
s.appendChild(document.createTextNode(str));
|
||||||
|
dest.appendChild(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// test cases
|
||||||
|
if (false) {
|
||||||
|
console.log(ParseSource("git://gitlab.com/benn/foo?path=xxx",
|
||||||
|
'(lib "asn1/scribblings/asn1.scrbl")',
|
||||||
|
false))
|
||||||
|
console.log(ParseSource("github://github.com/carl-eastlund/mischief/master",
|
||||||
|
'(lib "asn1/scribblings/asn1.scrbl")',
|
||||||
|
false))
|
||||||
|
console.log(ParseSource("github://github.com/carl-eastlund/mischief/stable/dir",
|
||||||
|
'(lib "asn1/scribblings/asn1.scrbl")',
|
||||||
|
false))
|
||||||
|
|
||||||
|
console.log(ParseSource("git://github.com/racket/racket/?path=pkgs/racket-doc",
|
||||||
|
'(lib "asn1/scribblings/asn1.scrbl")',
|
||||||
|
false));
|
||||||
|
|
||||||
|
console.log(ParseSource("git://github.com/rmculpepper/asn1.git?path=asn1-doc",
|
||||||
|
'(lib "asn1/scribblings/asn1.scrbl")',
|
||||||
|
true));
|
||||||
|
console.log(ParseSource("git://github.com/rmculpepper/asn1",
|
||||||
|
'(lib "asn1/scribblings/asn1.scrbl")',
|
||||||
|
true));
|
||||||
|
console.log(ParseSource("git://github.com/rmculpepper/asn1",
|
||||||
|
'(lib "asn1/scribblings/asn1.scrbl")',
|
||||||
|
false));
|
||||||
|
}
|
||||||
|
|
||||||
|
function AddPartTitleOnClick(elem) {
|
||||||
|
var mod_path = elem.getAttribute("x-source-module");
|
||||||
|
var tag = elem.getAttribute("x-part-tag");
|
||||||
|
var source_pkg = elem.getAttribute("x-source-pkg");
|
||||||
|
|
||||||
|
// create here to share
|
||||||
|
var info = document.createElement("div");
|
||||||
|
|
||||||
|
|
||||||
|
// tag is not needed, but this way we can add the element in only one place
|
||||||
|
// avoid failing on browser that don't have `fetch`
|
||||||
|
if (mod_path && source_pkg && tag && window.fetch) {
|
||||||
|
|
||||||
|
var cached = cache[mod_path]
|
||||||
|
if (cached) {
|
||||||
|
AddSourceElement(cached[0], mod_path, cached[1], info);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fetch("https://pkgs.racket-lang.org/pkg/" + source_pkg + ".json")
|
||||||
|
.then(function (response) { return response.json(); })
|
||||||
|
.then(function (data) {
|
||||||
|
var vers = data["versions"] || {};
|
||||||
|
var def = vers["default"] || {};
|
||||||
|
var source = def["source"] || undefined;
|
||||||
|
var collection = data["collection"];
|
||||||
|
if (source) {
|
||||||
|
cache[mod_path] = [source, collection];
|
||||||
|
AddSourceUrl(source, mod_path, collection, info);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mod_path && tag) {
|
||||||
|
// Might not be present:
|
||||||
|
var prefixes = elem.getAttribute("x-part-prefixes");
|
||||||
|
|
||||||
|
info.className = "RPartExplain";
|
||||||
|
|
||||||
|
/* The "top" tag refers to a whole document: */
|
||||||
|
var is_top = (tag == "\"top\"");
|
||||||
|
info.appendChild(document.createTextNode("Link to this "
|
||||||
|
+ (is_top ? "document" : "section")
|
||||||
|
+ " with "));
|
||||||
|
|
||||||
|
/* Break `secref` into two lines if the module path and tag
|
||||||
|
are long enough: */
|
||||||
|
var is_long = (is_top ? false : ((mod_path.length
|
||||||
|
+ tag.length
|
||||||
|
+ (prefixes ? (16 + prefixes.length) : 0))
|
||||||
|
> 60));
|
||||||
|
|
||||||
|
var line1 = document.createElement("div");
|
||||||
|
var line1x = ((is_long && prefixes) ? document.createElement("div") : line1);
|
||||||
|
var line2 = (is_long ? document.createElement("div") : line1);
|
||||||
|
|
||||||
|
/* Construct a `secref` call with suitable syntax coloring: */
|
||||||
|
addSpan(line1, "\xA0@", "RktRdr");
|
||||||
|
addSpan(line1, (is_top ? "other-doc" : "secref"), "RktSym");
|
||||||
|
addSpan(line1, "[", "RktPn");
|
||||||
|
if (!is_top)
|
||||||
|
addSpan(line1, tag, "RktVal");
|
||||||
|
if (is_long) {
|
||||||
|
/* indent additional lines: */
|
||||||
|
if (prefixes)
|
||||||
|
addSpan(line1x, "\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0", "RktPn");
|
||||||
|
addSpan(line2, "\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0", "RktPn");
|
||||||
|
}
|
||||||
|
if (prefixes) {
|
||||||
|
addSpan(line1x, " #:tag-prefixes ", "RktPn");
|
||||||
|
addSpan(line1x, "'", "RktVal");
|
||||||
|
addSpan(line1x, prefixes, "RktVal");
|
||||||
|
}
|
||||||
|
if (!is_top)
|
||||||
|
addSpan(line2, " #:doc ", "RktPn");
|
||||||
|
addSpan(line2, "'", "RktVal");
|
||||||
|
addSpan(line2, mod_path, "RktVal");
|
||||||
|
addSpan(line2, "]", "RktPn");
|
||||||
|
|
||||||
|
info.appendChild(line1);
|
||||||
|
if (is_long)
|
||||||
|
info.appendChild(line1x);
|
||||||
|
if (is_long)
|
||||||
|
info.appendChild(line2);
|
||||||
|
|
||||||
|
info.style.display = "none";
|
||||||
|
|
||||||
|
/* Add the new element afterthe header: */
|
||||||
|
var n = elem.nextSibling;
|
||||||
|
if (n)
|
||||||
|
elem.parentNode.insertBefore(info, n);
|
||||||
|
else
|
||||||
|
elem.parentNode.appendChild(info);
|
||||||
|
|
||||||
|
/* Clicking the information button shows the explanation element: */
|
||||||
|
const heading = elem.querySelector('.heading-source');
|
||||||
|
if (heading) {
|
||||||
|
heading.onclick = function () {
|
||||||
|
if (info.style.display === "none")
|
||||||
|
info.style.display = "block";
|
||||||
|
else
|
||||||
|
info.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
814
scrbl/manual-style.css
Normal file
814
scrbl/manual-style.css
Normal file
@@ -0,0 +1,814 @@
|
|||||||
|
|
||||||
|
/* See the beginning of "scribble.css".
|
||||||
|
This file is used by the `scribble/manual` language, along with
|
||||||
|
"manual-racket.css". */
|
||||||
|
|
||||||
|
@import url("manual-fonts.css");
|
||||||
|
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all {html {font-size: 15px;}}
|
||||||
|
@media all and (max-width:940px){html {font-size: 14px;}}
|
||||||
|
@media all and (max-width:850px){html {font-size: 13px;}}
|
||||||
|
@media all and (max-width:830px){html {font-size: 12px;}}
|
||||||
|
@media all and (max-width:740px){html {font-size: 11px;}}
|
||||||
|
|
||||||
|
/* CSS seems backward: List all the classes for which we want a
|
||||||
|
particular font, so that the font can be changed in one place. (It
|
||||||
|
would be nicer to reference a font definition from all the places
|
||||||
|
that we want it.)
|
||||||
|
|
||||||
|
As you read the rest of the file, remember to double-check here to
|
||||||
|
see if any font is set. */
|
||||||
|
|
||||||
|
/* Monospace: */
|
||||||
|
.maincolumn, .refpara, .refelem, .tocset, .stt, .hspace, .refparaleft, .refelemleft {
|
||||||
|
font-family: 'Fira-Mono', monospace;
|
||||||
|
white-space: inherit;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable heading-source */
|
||||||
|
.button-group > .heading-source {
|
||||||
|
visibility: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* embolden the "Racket Guide" and "Racket Reference" links on the TOC */
|
||||||
|
/* there isn't an obvious tag in the markup that designates the top TOC page, which is called "start.scrbl" */
|
||||||
|
/* nor a tag that designates these two links as special */
|
||||||
|
/* so we'll use this slightly tortured sibling selector that hooks onto the h1 tag */
|
||||||
|
h1[x-source-module='(lib "scribblings/main/start.scrbl")'] ~ table a[href="guide/index.html"],
|
||||||
|
h1[x-source-module='(lib "scribblings/main/start.scrbl")'] ~ table a[href="reference/index.html"] {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
h1 .stt {
|
||||||
|
font-size: 2.3rem;
|
||||||
|
/* prevent automatic bolding from h1 */
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toptoclink .stt {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
.toclink .stt {
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RpackageSpec .stt {
|
||||||
|
font-weight: 300;
|
||||||
|
font-family: 'Fira-Mono', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 .stt, h3 .stt, h4 .stt, h5 .stt {
|
||||||
|
color: #333;
|
||||||
|
font-size: 1.65rem;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Serif: */
|
||||||
|
.main, .refcontent, .tocview, .tocsub, .sroman, i {
|
||||||
|
font-family: 'Charter-Racket', serif;
|
||||||
|
font-size: 1.18rem;
|
||||||
|
/* Don't use font-feature-settings with Charter,
|
||||||
|
it fouls up loading for reasons mysterious */
|
||||||
|
/* font-feature-settings: 'tnum' 1, 'liga' 0; */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Sans-serif: */
|
||||||
|
.version, .versionNoNav, .ssansserif, .navfamily, .famlink {
|
||||||
|
font-family: 'Fira', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* used mostly for DrRacket menu commands */
|
||||||
|
.ssansserif {
|
||||||
|
font-family: 'Fira', sans-serif;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocset .ssansserif {
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
|
||||||
|
p, .SIntrapara {
|
||||||
|
display: block;
|
||||||
|
margin: 0 0 1em 0;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compact {
|
||||||
|
padding: 0 0 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style-position: outside;
|
||||||
|
margin-left: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6, h7, h8 {
|
||||||
|
font-family: 'Fira', sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
color: #333;
|
||||||
|
margin-top: inherit;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
line-height: 1.25;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
h2, h3, h4, h5, h6, h7, h8 {
|
||||||
|
border-top: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
h1 { /* per-page main title */
|
||||||
|
font-family: 'Cooper-Hewitt';
|
||||||
|
margin-top: 4rem;
|
||||||
|
font-size: 2.3rem;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1.2;
|
||||||
|
width: 90%;
|
||||||
|
/* a little nudge to make text visually lower than 4rem rule in left margin */
|
||||||
|
position: relative;
|
||||||
|
top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2, h3, h4, h5, h6, h7, h8 {
|
||||||
|
margin-top: 2em;
|
||||||
|
padding-top: 0.1em;
|
||||||
|
margin-bottom: 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Main */
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: black;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maincolumn {
|
||||||
|
width: auto;
|
||||||
|
margin-top: 4rem;
|
||||||
|
margin-left: 17rem;
|
||||||
|
margin-right: 2rem;
|
||||||
|
margin-bottom: 10rem; /* to avoid fixed bottom nav bar */
|
||||||
|
max-width: 700px;
|
||||||
|
min-width: 370px; /* below this size, code samples don't fit */
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, .toclink, .toptoclink, .tocviewlink, .tocviewselflink, .tocviewtoggle, .plainlink,
|
||||||
|
.techinside, .techoutside:hover, .techinside:hover {
|
||||||
|
color: #07A;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Navigation */
|
||||||
|
|
||||||
|
.navsettop, .navsetbottom {
|
||||||
|
left: 0;
|
||||||
|
width: 15rem;
|
||||||
|
height: 6rem;
|
||||||
|
font-family: 'Fira', sans-serif;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
border-bottom: 0px solid hsl(216, 15%, 70%);
|
||||||
|
background-color: inherit;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navsettop {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 2;
|
||||||
|
background: #a7b0be;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navsettop a, .navsetbottom a {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navsettop a:hover, .navsetbottom a:hover {
|
||||||
|
background: hsl(216, 78%, 95%);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navleft, .navright {
|
||||||
|
position: static;
|
||||||
|
float: none;
|
||||||
|
margin: 0;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.navleft a {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navright a {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navleft a, .navright a, .navright span {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.5rem;
|
||||||
|
min-width: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.navright {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.navsetbottom {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nonavigation {
|
||||||
|
color: #889;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchform {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
height: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nosearchform {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchbox {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
width: 12rem;
|
||||||
|
margin: 1rem;
|
||||||
|
padding: 0.25rem 0.4rem ;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-color: white;
|
||||||
|
font-family: 'Fira-Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#search_box {
|
||||||
|
font-family: 'Fira-Mono', monospace;
|
||||||
|
font-size: 1rem;
|
||||||
|
padding: 0.25rem 0.3rem ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default to local view. Global will specialize */
|
||||||
|
.plt_global_only { display: none; }
|
||||||
|
.plt_local_only { display: block; }
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Version */
|
||||||
|
|
||||||
|
.versionbox {
|
||||||
|
position: absolute;
|
||||||
|
float: none;
|
||||||
|
top: 0.25rem;
|
||||||
|
left: 17rem;
|
||||||
|
z-index: 11000;
|
||||||
|
height: 2em;
|
||||||
|
font-size: 70%;
|
||||||
|
font-weight: lighter;
|
||||||
|
width: inherit;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.version, .versionNoNav {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
.version:before, .versionNoNav:before {
|
||||||
|
content: "v";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Language Family */
|
||||||
|
|
||||||
|
.navfamily {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
left: 100%;
|
||||||
|
margin-top: -4.75em;
|
||||||
|
margin-right: -15em;
|
||||||
|
font-size: 70%;
|
||||||
|
font-weight: lighter;
|
||||||
|
height: auto;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Margin notes */
|
||||||
|
|
||||||
|
/* cancel scribble.css styles: */
|
||||||
|
.refpara, .refelem {
|
||||||
|
position: static;
|
||||||
|
float: none;
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcolumn {
|
||||||
|
position: static;
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
font-size: inherit;
|
||||||
|
margin: 2rem;
|
||||||
|
margin-left: 2rem;
|
||||||
|
padding: 0.5em;
|
||||||
|
padding-left: 0.75em;
|
||||||
|
padding-right: 1em;
|
||||||
|
background: hsl(60, 29%, 94%);
|
||||||
|
border: 1px solid #ccb;
|
||||||
|
border-left: 0.4rem solid #ccb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* slightly different handling for margin-note* on narrow screens */
|
||||||
|
@media all and (max-width:1340px) {
|
||||||
|
span.refcolumn {
|
||||||
|
float: right;
|
||||||
|
width: 50%;
|
||||||
|
margin-left: 1rem;
|
||||||
|
margin-bottom: 0.8rem;
|
||||||
|
margin-top: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navfamily {
|
||||||
|
position: static;
|
||||||
|
margin: -4.75em 0em 0em 0em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcontent, .refcontent p {
|
||||||
|
line-height: 1.5;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcontent p + p {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcontent a {
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refpara, .refparaleft {
|
||||||
|
top: -1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media all and (max-width:600px) {
|
||||||
|
.refcolumn {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media all and (min-width:1340px) {
|
||||||
|
.refcolumn {
|
||||||
|
margin: 0 -22.5rem 1rem 0;
|
||||||
|
float: right;
|
||||||
|
clear: right;
|
||||||
|
width: 18rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcontent {
|
||||||
|
font-family: 'Fira', sans-serif;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.refparaleft, .refelemleft {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
right: 2em;
|
||||||
|
height: 0em;
|
||||||
|
width: 13em;
|
||||||
|
margin: 0em 0em 0em 0em;
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcolumnleft {
|
||||||
|
background-color: hsl(60, 29%, 94%);
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 13em;
|
||||||
|
font-size: 85%;
|
||||||
|
border: 0.5em solid hsl(60, 29%, 94%);
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Table of contents, left margin */
|
||||||
|
|
||||||
|
.tocset {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 2;
|
||||||
|
overflow-y: scroll;
|
||||||
|
float: none;
|
||||||
|
left: 0;
|
||||||
|
top: 0rem;
|
||||||
|
bottom: 0;
|
||||||
|
width: 14rem;
|
||||||
|
padding: 0rem 0.5rem 0.5rem 0.5rem;
|
||||||
|
background-color: hsl(216, 15%, 70%);
|
||||||
|
border-top: 6rem solid hsl(216, 15%, 70%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocset td {
|
||||||
|
vertical-align: text-top;
|
||||||
|
padding-bottom: 0.4rem;
|
||||||
|
padding-left: 0.2rem;
|
||||||
|
line-height: 1.1;
|
||||||
|
font-family: 'Fira', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocset td a {
|
||||||
|
color: black;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tocview {
|
||||||
|
text-align: left;
|
||||||
|
background-color: inherit;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tocview td, .tocsub td {
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tocview table, .tocsub table {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocset td a.tocviewselflink {
|
||||||
|
font-weight: lighter;
|
||||||
|
font-size: 110%; /* monospaced styles below don't need to enlarge */
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewselflink {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsub {
|
||||||
|
text-align: left;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewlist, .tocsublist {
|
||||||
|
margin-left: 0.2em;
|
||||||
|
margin-right: 0.2em;
|
||||||
|
padding-top: 0.2em;
|
||||||
|
padding-bottom: 0.2em;
|
||||||
|
}
|
||||||
|
.tocviewlist table {
|
||||||
|
font-size: 82%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewlisttopspace {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewsublist, .tocviewsublistonly, .tocviewsublisttop, .tocviewsublistbottom {
|
||||||
|
margin-left: 0.4em;
|
||||||
|
border-left: 1px solid #99a;
|
||||||
|
padding-left: 0.8em;
|
||||||
|
}
|
||||||
|
.tocviewsublist {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.tocviewsublist table,
|
||||||
|
.tocviewsublistonly table,
|
||||||
|
.tocviewsublisttop table,
|
||||||
|
.tocviewsublistbottom table,
|
||||||
|
table.tocsublist {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewsublist td,
|
||||||
|
.tocviewsublistbottom td,
|
||||||
|
.tocviewsublisttop td,
|
||||||
|
.tocsub td,
|
||||||
|
.tocviewsublistonly td {
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shrink the monospaced text (`stt`) within nav */
|
||||||
|
.tocviewsublist td .stt,
|
||||||
|
.tocviewsublistbottom td .stt,
|
||||||
|
.tocviewsublisttop td .stt,
|
||||||
|
.tocsub td .stt,
|
||||||
|
.tocviewsublistonly td .stt {
|
||||||
|
font-size: 95%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tocviewtoggle {
|
||||||
|
font-size: 75%; /* looks better, and avoids bounce when toggling sub-sections due to font alignments */
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsublist td {
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
padding-top: 0.25rem;
|
||||||
|
text-indent: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsublinknumber {
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsublink {
|
||||||
|
font-size: 82%;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsubseclink {
|
||||||
|
font-size: 100%;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsubnonseclink {
|
||||||
|
font-size: 82%;
|
||||||
|
text-decoration: none;
|
||||||
|
margin-left: 1rem;
|
||||||
|
padding-left: 0;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the label "on this page" */
|
||||||
|
.tocsubtitle {
|
||||||
|
display: block;
|
||||||
|
font-size: 62%;
|
||||||
|
font-family: 'Fira', sans-serif;
|
||||||
|
font-weight: bolder;
|
||||||
|
font-style: normal;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toptoclink {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 110%;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toclink {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Some inline styles */
|
||||||
|
|
||||||
|
.indexlink {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin-left: 2em;
|
||||||
|
margin-right: 2em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SCodeFlow {
|
||||||
|
border-left: 1px dotted black;
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-right: 1em;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
margin-left: 0em;
|
||||||
|
margin-right: 2em;
|
||||||
|
white-space: nowrap;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SCodeFlow img {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* put a little air between lines of code sample */
|
||||||
|
/* Fira Mono appears taller than Source Code Pro */
|
||||||
|
.SCodeFlow td {
|
||||||
|
padding-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boxed {
|
||||||
|
margin: 0;
|
||||||
|
margin-top: 2em;
|
||||||
|
padding: 0.25em;
|
||||||
|
padding-top: 0.3em;
|
||||||
|
padding-bottom: 0.4em;
|
||||||
|
background: #f3f3f3;
|
||||||
|
box-sizing:border-box;
|
||||||
|
border-top: 1px solid #99b;
|
||||||
|
background: hsl(216, 78%, 95%);
|
||||||
|
background: -moz-linear-gradient(to bottom left, hsl(0, 0%, 99%) 0%, hsl(216, 62%, 95%) 100%);
|
||||||
|
background: -webkit-linear-gradient(to bottom left, hsl(0, 0%, 99%) 0%, hsl(216, 62%, 95%) 100%);
|
||||||
|
background: -o-linear-gradient(to bottom left, hsl(0, 0%, 99%) 0%, hsl(216, 62%, 95%) 100%);
|
||||||
|
background: -ms-linear-gradient(to bottom left, hsl(0, 0%, 99%) 0%, hsl(216, 62%, 95%) 100%);
|
||||||
|
background: linear-gradient(to bottom left, hsl(0, 0%, 99%) 0%, hsl(216, 62%, 95%) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote > blockquote.SVInsetFlow {
|
||||||
|
/* resolves issue in e.g. /reference/notation.html */
|
||||||
|
margin-top: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leftindent .SVInsetFlow { /* see e.g. section 4.5 of Racket Guide */
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SVInsetFlow a, .SCodeFlow a {
|
||||||
|
color: #07A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SubFlow {
|
||||||
|
display: block;
|
||||||
|
margin: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boxed {
|
||||||
|
width: 100%;
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.techoutside { text-decoration: none; }
|
||||||
|
|
||||||
|
.SAuthorListBox {
|
||||||
|
position: static;
|
||||||
|
float: none;
|
||||||
|
font-family: 'Fira', sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 110%;
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
width: 30rem;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.author > a { /* email links within author block */
|
||||||
|
font-weight: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SAuthorList {
|
||||||
|
font-size: 82%;
|
||||||
|
}
|
||||||
|
.SAuthorList:before {
|
||||||
|
content: "by ";
|
||||||
|
}
|
||||||
|
.author {
|
||||||
|
display: inline;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* phone + tablet styles */
|
||||||
|
|
||||||
|
@media all and (max-width:720px){
|
||||||
|
|
||||||
|
|
||||||
|
@media all and (max-width:720px){
|
||||||
|
|
||||||
|
@media all {html {font-size: 15px;}}
|
||||||
|
@media all and (max-width:700px){html {font-size: 14px;}}
|
||||||
|
@media all and (max-width:630px){html {font-size: 13px;}}
|
||||||
|
@media all and (max-width:610px){html {font-size: 12px;}}
|
||||||
|
@media all and (max-width:550px){html {font-size: 11px;}}
|
||||||
|
@media all and (max-width:520px){html {font-size: 10px;}}
|
||||||
|
|
||||||
|
.navsettop, .navsetbottom {
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 4rem;
|
||||||
|
border: 0;
|
||||||
|
background-color: hsl(216, 15%, 70%);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsetoverlay .navsettop {
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navleft {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchform {
|
||||||
|
display: inline;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchbox {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navleft .tocsettoggle {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navright {
|
||||||
|
margin-right: 1.3rem;
|
||||||
|
border: 0px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navsetbottom {
|
||||||
|
display: block;
|
||||||
|
margin-top: 8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocset {
|
||||||
|
display: none;
|
||||||
|
border-top-width: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsetoverlay .tocset {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.versionbox {
|
||||||
|
top: 4.5rem;
|
||||||
|
left: 1rem; /* same distance as main-column */
|
||||||
|
z-index: 1;
|
||||||
|
height: 2em;
|
||||||
|
font-size: 70%;
|
||||||
|
font-weight: lighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navfamily {
|
||||||
|
position: static;
|
||||||
|
margin: -3.25em 0em 0em 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maincolumn {
|
||||||
|
margin-left: 1em;
|
||||||
|
margin-top: 7rem;
|
||||||
|
margin-bottom: 0rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print styles : hide the navigation elements */
|
||||||
|
@media print {
|
||||||
|
.tocset,
|
||||||
|
.navsettop,
|
||||||
|
.navsetbottom { display: none; }
|
||||||
|
.maincolumn {
|
||||||
|
width: auto;
|
||||||
|
margin-right: 13em;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
251
scrbl/racket.css
Normal file
251
scrbl/racket.css
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
|
||||||
|
/* See the beginning of "scribble.css". */
|
||||||
|
|
||||||
|
/* Monospace: */
|
||||||
|
.RktIn, .RktRdr, .RktPn, .RktMeta,
|
||||||
|
.RktMod, .RktKw, .RktVar, .RktSym,
|
||||||
|
.RktRes, .RktOut, .RktCmt, .RktVal,
|
||||||
|
.RktBlk {
|
||||||
|
font-family: monospace;
|
||||||
|
white-space: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Serif: */
|
||||||
|
.inheritedlbl {
|
||||||
|
font-family: serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sans-serif: */
|
||||||
|
.RBackgroundLabelInner {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Inherited methods, left margin */
|
||||||
|
|
||||||
|
.inherited {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
text-align: left;
|
||||||
|
background-color: #ECF5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inherited td {
|
||||||
|
font-size: 82%;
|
||||||
|
padding-left: 1em;
|
||||||
|
text-indent: -0.8em;
|
||||||
|
padding-right: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inheritedlbl {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Racket text styles */
|
||||||
|
|
||||||
|
.RktIn {
|
||||||
|
color: #cc6633;
|
||||||
|
background-color: #eeeeee;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktInBG {
|
||||||
|
background-color: #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktRdr {
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktPn {
|
||||||
|
color: #843c24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktMeta {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktMod {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktOpt {
|
||||||
|
color: black;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktKw {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktErr {
|
||||||
|
color: red;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktVar {
|
||||||
|
color: #262680;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktSym {
|
||||||
|
color: #262680;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktSymDef { /* used with RktSym at def site */
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktValLink {
|
||||||
|
text-decoration: none;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktValDef { /* used with RktValLink at def site */
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktModLink {
|
||||||
|
text-decoration: none;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktStxLink {
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktStxDef { /* used with RktStxLink at def site */
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktRes {
|
||||||
|
color: #0000af;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktOut {
|
||||||
|
color: #960096;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktCmt {
|
||||||
|
color: #c2741f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktVal {
|
||||||
|
color: #228b22;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Some inline styles */
|
||||||
|
|
||||||
|
.together {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prototype, .argcontract, .RBoxed {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prototype td {
|
||||||
|
vertical-align: text-top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktBlk {
|
||||||
|
white-space: inherit;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktBlk tr {
|
||||||
|
white-space: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RktBlk td {
|
||||||
|
vertical-align: baseline;
|
||||||
|
white-space: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.argcontract td {
|
||||||
|
vertical-align: text-top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlighted {
|
||||||
|
background-color: #ddddff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.defmodule {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #F5F5DC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.specgrammar {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RBibliography td {
|
||||||
|
vertical-align: text-top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leftindent {
|
||||||
|
margin-left: 1em;
|
||||||
|
margin-right: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.insetpara {
|
||||||
|
margin-left: 1em;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Rfilebox {
|
||||||
|
}
|
||||||
|
|
||||||
|
.Rfiletitle {
|
||||||
|
text-align: right;
|
||||||
|
margin: 0em 0em 0em 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Rfilename {
|
||||||
|
border-top: 1px solid #6C8585;
|
||||||
|
border-right: 1px solid #6C8585;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
background-color: #ECF5F5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Rfilecontent {
|
||||||
|
margin: 0em 0em 0em 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RpackageSpec {
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* For background labels */
|
||||||
|
|
||||||
|
.RBackgroundLabel {
|
||||||
|
float: right;
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RBackgroundLabelInner {
|
||||||
|
position: relative;
|
||||||
|
width: 25em;
|
||||||
|
left: -25.5em;
|
||||||
|
top: 0px;
|
||||||
|
text-align: right;
|
||||||
|
color: white;
|
||||||
|
z-index: 0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RForeground {
|
||||||
|
position: relative;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* History */
|
||||||
|
|
||||||
|
.SHistory {
|
||||||
|
font-size: 82%;
|
||||||
|
}
|
||||||
263
scrbl/scribble-common.js
Normal file
263
scrbl/scribble-common.js
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
// Common functionality for PLT documentation pages
|
||||||
|
|
||||||
|
// Page Parameters ------------------------------------------------------------
|
||||||
|
|
||||||
|
var plt_root_as_query = false;
|
||||||
|
|
||||||
|
function GetURL() {
|
||||||
|
return new URL(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetPageArgs() {
|
||||||
|
return GetURL().searchParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetPageQueryString() {
|
||||||
|
return GetPageArgs().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetPageArg(key, def) {
|
||||||
|
return GetPageArgs().get(key) || def;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MergePageArgsIntoLink(a) {
|
||||||
|
if ((GetPageArgs().size === 0 || !a.dataset.pltdoc) && !plt_root_as_query) return;
|
||||||
|
a.href = MergePageArgsIntoUrl(a.href);
|
||||||
|
}
|
||||||
|
|
||||||
|
function MergePageArgsIntoUrl(href) {
|
||||||
|
const url = new URL(href, window.location.href);
|
||||||
|
MergePageArgsIntoUrlObject(url);
|
||||||
|
return url.href;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MergePageArgsIntoUrlObject(url) {
|
||||||
|
for (const [key, val] of GetPageArgs()) {
|
||||||
|
if (key[0] == "q") continue; // use "q" to mean "don't propagate automatcially"
|
||||||
|
if (url.searchParams.has(key)) continue;
|
||||||
|
url.searchParams.append(key, val)
|
||||||
|
}
|
||||||
|
if (plt_root_as_query && !url.searchParams.has("PLT_Root")) {
|
||||||
|
url.searchParams.append("PLT_Root", plt_root_as_query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cookies --------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Actually, try localStorage (a la HTML 5), first.
|
||||||
|
|
||||||
|
function GetCookie(key, def) {
|
||||||
|
try {
|
||||||
|
var v = localStorage[key];
|
||||||
|
if (!v) v = def;
|
||||||
|
return v;
|
||||||
|
} catch (e) {
|
||||||
|
var i, cookiestrs;
|
||||||
|
try {
|
||||||
|
if (document.cookie.length <= 0) return def;
|
||||||
|
cookiestrs = document.cookie.split(/; */);
|
||||||
|
} catch (e) { return def; }
|
||||||
|
for (i = 0; i < cookiestrs.length; i++) {
|
||||||
|
var cur = cookiestrs[i];
|
||||||
|
var eql = cur.indexOf('=');
|
||||||
|
if (eql >= 0 && cur.substring(0,eql) == key)
|
||||||
|
return unescape(cur.substring(eql+1));
|
||||||
|
}
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetCookie(key, val) {
|
||||||
|
try {
|
||||||
|
localStorage[key] = val;
|
||||||
|
} catch(e) {
|
||||||
|
var d = new Date();
|
||||||
|
d.setTime(d.getTime()+(365*24*60*60*1000));
|
||||||
|
try {
|
||||||
|
document.cookie =
|
||||||
|
key + "=" + escape(val) + "; expires="+ d.toGMTString() + "; path=/";
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// note that this always stores a directory name, ending with a "/"
|
||||||
|
function SetPLTRoot(ver, relative) {
|
||||||
|
var root = location.protocol + "//" + location.host
|
||||||
|
+ NormalizePath(location.pathname.replace(/[^\/]*$/, relative));
|
||||||
|
if (location.protocol == "file:") {
|
||||||
|
// local storage or cookies are not going to work in modern browsers,
|
||||||
|
// so add a query parameter to all URLs
|
||||||
|
plt_root_as_query=root
|
||||||
|
} else {
|
||||||
|
SetCookie("PLT_Root."+ver, root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// adding index.html works because of the above
|
||||||
|
function GotoPLTRoot(ver, root_relative, here_to_root_relative) {
|
||||||
|
// the relative path is optional, default goes to the toplevel start page
|
||||||
|
if (!root_relative) root_relative = "index.html";
|
||||||
|
if (here_to_root_relative == undefined) here_to_root_relative = "../"
|
||||||
|
var famroot = false;
|
||||||
|
if (root_relative == "index.html") {
|
||||||
|
famroot = (GetPageArg("fam", false) ? GetPageArg("famroot", false) : false)
|
||||||
|
if (famroot) {
|
||||||
|
root_relative = famroot + "/index.html";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var u = GetRootPath(ver);
|
||||||
|
if (u == null) {
|
||||||
|
if (famroot) {
|
||||||
|
location = MergePageArgsIntoUrl(here_to_root_relative + famroot + "/index.html");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// no cookie and no famroot => follow href, instead
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
location = MergePageArgsIntoUrl(u + root_relative);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetRootPath(ver) {
|
||||||
|
var u = GetCookie("PLT_Root."+ver, null);
|
||||||
|
if (u != null)
|
||||||
|
return u;
|
||||||
|
|
||||||
|
// via query argument? (especially for `file://` URLs)
|
||||||
|
u = GetPageArg("PLT_Root", null)
|
||||||
|
if (u != null)
|
||||||
|
return u;
|
||||||
|
|
||||||
|
// use root specified by local-redirect wrapper, if present
|
||||||
|
if (typeof user_doc_root != "undefined")
|
||||||
|
return user_doc_root;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utilities ------------------------------------------------------------------
|
||||||
|
|
||||||
|
var normalize_rxs = [/\/\/+/g, /\/\.(\/|$)/, /\/[^\/]*\/\.\.(\/|$)/];
|
||||||
|
function NormalizePath(path) {
|
||||||
|
var tmp, i;
|
||||||
|
for (i = 0; i < normalize_rxs.length; i++)
|
||||||
|
while ((tmp = path.replace(normalize_rxs[i], "/")) != path) path = tmp;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `noscript' is problematic in some browsers (always renders as a
|
||||||
|
// block), use this hack instead (does not always work!)
|
||||||
|
// document.write("<style>mynoscript { display:none; }</style>");
|
||||||
|
|
||||||
|
// Interactions ---------------------------------------------------------------
|
||||||
|
|
||||||
|
function DoSearchKey(event, field, ver, top_path) {
|
||||||
|
var val = field.value;
|
||||||
|
if (event && event.key === 'Enter') {
|
||||||
|
var u = GetRootPath(ver);
|
||||||
|
if (u == null) u = top_path; // default: go to the top path
|
||||||
|
u += "search/index.html?q=" + encodeURIComponent(val);
|
||||||
|
u = MergePageArgsIntoUrl(u);
|
||||||
|
location = u;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function TocviewToggle(glyph, id) {
|
||||||
|
var s = document.getElementById(id).style;
|
||||||
|
var expand = s.display == "none";
|
||||||
|
s.display = expand ? "block" : "none";
|
||||||
|
glyph.innerHTML = expand ? "▼" : "►";
|
||||||
|
}
|
||||||
|
|
||||||
|
function TocsetToggle() {
|
||||||
|
document.body.classList.toggle("tocsetoverlay");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page Init ------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Note: could make a function that inspects and uses window.onload to chain to
|
||||||
|
// a previous one, but this file needs to be required first anyway, since it
|
||||||
|
// contains utilities for all other files.
|
||||||
|
var on_load_funcs = [];
|
||||||
|
function AddOnLoad(fun) { on_load_funcs.push(fun); }
|
||||||
|
window.onload = function() {
|
||||||
|
for (var i=0; i<on_load_funcs.length; i++) on_load_funcs[i]();
|
||||||
|
};
|
||||||
|
|
||||||
|
AddOnLoad(function(){
|
||||||
|
var links = document.getElementsByTagName("a");
|
||||||
|
for (var i=0; i<links.length; i++) MergePageArgsIntoLink(links[i]);
|
||||||
|
var label = GetPageArg("ctxtname",false);
|
||||||
|
if (!label) return;
|
||||||
|
var indicator = document.getElementById("contextindicator");
|
||||||
|
if (!indicator) return;
|
||||||
|
indicator.innerHTML = label;
|
||||||
|
indicator.style.display = "block";
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pressing "S" or "s" focuses on the "...search manuals..." text field
|
||||||
|
AddOnLoad(function(){
|
||||||
|
window.addEventListener("keyup", function(e) {
|
||||||
|
if ((e.key === 's' || e.key === 'S') && e.target === document.body) {
|
||||||
|
var searchBox = document.getElementById('searchbox');
|
||||||
|
if (searchBox) {
|
||||||
|
searchBox.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddOnLoad(function(){
|
||||||
|
var es = document.getElementsByClassName("family-navigation");
|
||||||
|
if (es.length > 0) {
|
||||||
|
var fams = es[0].dataset.familynav.split(/,/);
|
||||||
|
var fam = GetPageArg("famroot", false) && GetPageArg("fam", false);
|
||||||
|
if (!fam) fam = "Racket";
|
||||||
|
if (fams.indexOf(fam) == -1) {
|
||||||
|
for (var i=0; i < es.length; i++) {
|
||||||
|
es[i].style.display = "inline-block";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddOnLoad(function(){
|
||||||
|
var es = document.getElementsByClassName("navfamily");
|
||||||
|
for (var i=0; i < es.length; i++) {
|
||||||
|
var e = es[i];
|
||||||
|
if (e.dataset.fam != undefined) {
|
||||||
|
var fams = e.dataset.fam.split(/,/);
|
||||||
|
var fam = GetPageArg("fam", false);
|
||||||
|
if (!fam) fam = "Racket";
|
||||||
|
var link = document.createElement('a');
|
||||||
|
var root = GetRootPath(e.dataset.version)
|
||||||
|
var family_url;
|
||||||
|
if (root == null) {
|
||||||
|
family_url = new URL(e.dataset.famPath + "family/index.html", window.location.href);
|
||||||
|
} else {
|
||||||
|
family_url = new URL(root + "family/index.html", window.location.href);
|
||||||
|
}
|
||||||
|
family_url.searchParams.append("qfrom", window.location.href)
|
||||||
|
MergePageArgsIntoUrlObject(family_url);
|
||||||
|
if (fams.indexOf(fam) == -1) {
|
||||||
|
var nav_as = document.createElement('div');
|
||||||
|
link.textContent = "navigating as " + fam;
|
||||||
|
link.href = family_url
|
||||||
|
nav_as.appendChild(link)
|
||||||
|
e.appendChild(nav_as)
|
||||||
|
} else {
|
||||||
|
var link = document.createElement('a');
|
||||||
|
var span = e.children[0]
|
||||||
|
link.textContent = span.textContent;
|
||||||
|
link.href = family_url
|
||||||
|
span.textContent = ''; // Clear span
|
||||||
|
e.removeChild(span);
|
||||||
|
link.appendChild(span);
|
||||||
|
e.appendChild(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
578
scrbl/scribble.css
Normal file
578
scrbl/scribble.css
Normal file
@@ -0,0 +1,578 @@
|
|||||||
|
|
||||||
|
/* This file is used by default by all Scribble documents.
|
||||||
|
See also "manual.css", which is added by default by the
|
||||||
|
`scribble/manual` language. */
|
||||||
|
|
||||||
|
/* CSS seems backward: List all the classes for which we want a
|
||||||
|
particular font, so that the font can be changed in one place. (It
|
||||||
|
would be nicer to reference a font definition from all the places
|
||||||
|
that we want it.)
|
||||||
|
|
||||||
|
As you read the rest of the file, remember to double-check here to
|
||||||
|
see if any font is set. */
|
||||||
|
|
||||||
|
/* Monospace: */
|
||||||
|
.maincolumn, .refpara, .refelem, .tocset, .stt, .hspace, .refparaleft, .refelemleft, .reffootnote {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Serif: */
|
||||||
|
.main, .refcontent, .tocview, .tocsub, .sroman, i {
|
||||||
|
font-family: serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sans-serif: */
|
||||||
|
.version, .versionNoNav, .ssansserif, .navfamily {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
.ssansserif {
|
||||||
|
font-size: 80%;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emphasis: alternate italics and normal as we nest */
|
||||||
|
.emph {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.emph .emph {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
.emph .emph .emph {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.emph .emph .emph .emph {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
.emph .emph .emph .emph .emph {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.emph .emph .emph .emph .emph .emph {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
|
||||||
|
p, .SIntrapara {
|
||||||
|
display: block;
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 { /* per-page main title */
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2, h3, h4, h5, h6, h7, h8 {
|
||||||
|
margin-top: 1.75em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.17em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.00em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 0.83em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SSubSubSubSection {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.83em; /* should match h5; from HTML 4 reference */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Needed for browsers like Opera, and eventually for HTML 4 conformance.
|
||||||
|
This means that multiple paragraphs in a table element do not have a space
|
||||||
|
between them. */
|
||||||
|
table p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Main */
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: black;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maincolumn {
|
||||||
|
width: 43em;
|
||||||
|
margin-right: -40em;
|
||||||
|
margin-left: 15em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Navigation */
|
||||||
|
|
||||||
|
.navsettop, .navsetbottom {
|
||||||
|
background-color: #f0f0e0;
|
||||||
|
padding: 0.25em 0 0.25em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navsettop {
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
border-bottom: 2px solid #e0e0c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navsetbottom {
|
||||||
|
margin-top: 2em;
|
||||||
|
border-top: 2px solid #e0e0c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navleft {
|
||||||
|
margin-left: 1ex;
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.navright {
|
||||||
|
margin-right: 1ex;
|
||||||
|
position: relative;
|
||||||
|
float: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.nonavigation {
|
||||||
|
color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navleft .tocsettoggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchform {
|
||||||
|
display: inline;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nosearchform {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchbox {
|
||||||
|
width: 16em;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
background-color: #eee;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchbox::placeholder {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contextindicator {
|
||||||
|
position: fixed;
|
||||||
|
background-color: #c6f;
|
||||||
|
color: #000;
|
||||||
|
font-family: monospace;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 2px 10px;
|
||||||
|
display: none;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Version */
|
||||||
|
|
||||||
|
.versionbox {
|
||||||
|
position: relative;
|
||||||
|
float: right;
|
||||||
|
left: 2em;
|
||||||
|
height: 0em;
|
||||||
|
width: 13em;
|
||||||
|
margin: 0em -13em 0em 0em;
|
||||||
|
}
|
||||||
|
.version {
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
.versionNoNav {
|
||||||
|
font-size: xx-small; /* avoid overlap with author */
|
||||||
|
}
|
||||||
|
|
||||||
|
.version:before, .versionNoNav:before {
|
||||||
|
content: "Version ";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Language Family */
|
||||||
|
|
||||||
|
.navfamily {
|
||||||
|
float: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
left: 2em;
|
||||||
|
height: 0em;
|
||||||
|
width: 13em;
|
||||||
|
margin: 0em -13em 0em 0em;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
.docfamily:after {
|
||||||
|
content: " language family";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Margin notes */
|
||||||
|
|
||||||
|
.refpara, .refelem, .reffootnote {
|
||||||
|
position: relative;
|
||||||
|
float: right;
|
||||||
|
left: 2em;
|
||||||
|
height: 0em;
|
||||||
|
width: 13em;
|
||||||
|
margin: 0em -13em 0em 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refpara, .refparaleft, .reffootnote {
|
||||||
|
top: -1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcolumn {
|
||||||
|
background-color: #F5F5DC;
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 13em;
|
||||||
|
font-size: 85%;
|
||||||
|
border: 0.5em solid #F5F5DC;
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
white-space: normal; /* in case margin note is inside code sample */
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcontent {
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcontent p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refparaleft, .refelemleft {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
right: 2em;
|
||||||
|
height: 0em;
|
||||||
|
width: 13em;
|
||||||
|
margin: 0em 0em 0em -13em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refcolumnleft {
|
||||||
|
background-color: #F5F5DC;
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 13em;
|
||||||
|
font-size: 85%;
|
||||||
|
border: 0.5em solid #F5F5DC;
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Table of contents, inline */
|
||||||
|
|
||||||
|
.toclink {
|
||||||
|
text-decoration: none;
|
||||||
|
color: blue;
|
||||||
|
font-size: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toptoclink {
|
||||||
|
text-decoration: none;
|
||||||
|
color: blue;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Table of contents, left margin */
|
||||||
|
|
||||||
|
.tocset {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
width: 12.5em;
|
||||||
|
margin-right: 2em;
|
||||||
|
}
|
||||||
|
.tocset td {
|
||||||
|
vertical-align: text-top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocview {
|
||||||
|
text-align: left;
|
||||||
|
background-color: #f0f0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsub {
|
||||||
|
text-align: left;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
background-color: #f0f0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewlist, .tocsublist {
|
||||||
|
margin-left: 0.2em;
|
||||||
|
margin-right: 0.2em;
|
||||||
|
padding-top: 0.2em;
|
||||||
|
padding-bottom: 0.2em;
|
||||||
|
}
|
||||||
|
.tocviewlist table {
|
||||||
|
font-size: 82%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewlisttopspace {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewsublist, .tocviewsublistonly, .tocviewsublisttop, .tocviewsublistbottom {
|
||||||
|
margin-left: 0.4em;
|
||||||
|
border-left: 1px solid #bbf;
|
||||||
|
padding-left: 0.8em;
|
||||||
|
}
|
||||||
|
.tocviewsublist {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.tocviewsublist table,
|
||||||
|
.tocviewsublistonly table,
|
||||||
|
.tocviewsublisttop table,
|
||||||
|
.tocviewsublistbottom table {
|
||||||
|
font-size: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewtitle * {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewlink {
|
||||||
|
text-decoration: none;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewselflink {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocviewtoggle {
|
||||||
|
text-decoration: none;
|
||||||
|
color: blue;
|
||||||
|
font-size: 75%; /* looks better, and avoids bounce when toggling sub-sections due to font alignments */
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsublist td {
|
||||||
|
padding-left: 1em;
|
||||||
|
text-indent: -1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsublinknumber {
|
||||||
|
font-size: 82%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsublink {
|
||||||
|
font-size: 82%;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsubseclink {
|
||||||
|
font-size: 82%;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsubnonseclink {
|
||||||
|
font-size: 82%;
|
||||||
|
text-decoration: none;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tocsubtitle {
|
||||||
|
font-size: 82%;
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
/* Some inline styles */
|
||||||
|
|
||||||
|
.indexlink {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nobreak {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre { margin-left: 2em; }
|
||||||
|
blockquote { margin-left: 2em; }
|
||||||
|
|
||||||
|
ol { list-style-type: decimal; }
|
||||||
|
ol ol { list-style-type: lower-alpha; }
|
||||||
|
ol ol ol { list-style-type: lower-roman; }
|
||||||
|
ol ol ol ol { list-style-type: upper-alpha; }
|
||||||
|
|
||||||
|
.SCodeFlow {
|
||||||
|
display: block;
|
||||||
|
margin-left: 1em;
|
||||||
|
margin-bottom: 0em;
|
||||||
|
margin-right: 1em;
|
||||||
|
margin-top: 0em;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SVInsetFlow {
|
||||||
|
display: block;
|
||||||
|
margin-left: 0em;
|
||||||
|
margin-bottom: 0em;
|
||||||
|
margin-right: 0em;
|
||||||
|
margin-top: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SubFlow {
|
||||||
|
display: block;
|
||||||
|
margin: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boxed {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #E8E8FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hspace {
|
||||||
|
}
|
||||||
|
|
||||||
|
.slant {
|
||||||
|
font-style: oblique;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badlink {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plainlink {
|
||||||
|
text-decoration: none;
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.techoutside { text-decoration: underline; color: #b0b0b0; }
|
||||||
|
.techoutside:hover { text-decoration: underline; color: blue; }
|
||||||
|
|
||||||
|
/* .techinside:hover doesn't work with FF, .techinside:hover>
|
||||||
|
.techinside doesn't work with IE, so use both (and IE doesn't
|
||||||
|
work with inherit in the second one, so use blue directly) */
|
||||||
|
.techinside { color: black; }
|
||||||
|
.techinside:hover { color: blue; }
|
||||||
|
.techoutside:hover>.techinside { color: inherit; }
|
||||||
|
|
||||||
|
.SCentered {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageleft {
|
||||||
|
float: left;
|
||||||
|
margin-right: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Smaller {
|
||||||
|
font-size: 82%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Larger {
|
||||||
|
font-size: 122%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A hack, inserted to break some Scheme ids: */
|
||||||
|
.mywbr {
|
||||||
|
display: inline-block;
|
||||||
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
font-size: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compact li p {
|
||||||
|
margin: 0em;
|
||||||
|
padding: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noborder img {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SVerbatim {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SAuthorListBox {
|
||||||
|
position: relative;
|
||||||
|
float: right;
|
||||||
|
left: 2em;
|
||||||
|
top: -2.25em;
|
||||||
|
height: 0em;
|
||||||
|
width: 13em;
|
||||||
|
margin: 0em -13em 0em 0em;
|
||||||
|
}
|
||||||
|
.SAuthorList {
|
||||||
|
font-size: 82%;
|
||||||
|
}
|
||||||
|
.SAuthorList:before {
|
||||||
|
content: "by ";
|
||||||
|
}
|
||||||
|
.author {
|
||||||
|
display: inline;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print styles : hide the navigation elements */
|
||||||
|
@media print {
|
||||||
|
.tocset,
|
||||||
|
.navsettop,
|
||||||
|
.navsetbottom { display: none; }
|
||||||
|
.maincolumn {
|
||||||
|
width: auto;
|
||||||
|
margin-right: 13em;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Begin headings */
|
||||||
|
|
||||||
|
/* Hide the button group by default, but show them on hovering the heading title */
|
||||||
|
.button-group {
|
||||||
|
padding-left: 0.3em;
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.heading:hover > .button-group {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group > a {
|
||||||
|
margin: 0 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group > a, .button-group > a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-anchor {
|
||||||
|
font-size: 60%;
|
||||||
|
/* A trick to color an emoji from https://stackoverflow.com/questions/32413731/color-for-unicode-emoji */
|
||||||
|
color: transparent;
|
||||||
|
text-shadow: 0 0 0 gray;
|
||||||
|
vertical-align: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-source {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user