├── .github
└── FUNDING.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build-docs.sh
├── demo
├── demo.png
└── demo.rkt
├── docs
├── index.html
├── manual-fonts.css
├── manual-racket.css
├── manual-racket.js
├── manual-style.css
├── racket.css
├── scribble-common.js
└── scribble.css
├── info.rkt
├── main.rkt
├── private
├── web-view.rkt
├── webkit.rkt
└── wkwebview.rkt
└── scribblings
└── web-view.scrbl
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | \#*
3 | .\#*
4 | .DS_Store
5 | compiled/
6 | /doc/
7 | *.dmg
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: c
2 |
3 | # Based on: https://github.com/greghendershott/travis-racket
4 |
5 | env:
6 | global:
7 | # Supply a global RACKET_DIR environment variable. This is where
8 | # Racket will be installed. A good idea is to use ~/racket because
9 | # that doesn't require sudo to install.
10 | - RACKET_DIR=~/racket
11 | matrix:
12 | # Supply at least one RACKET_VERSION environment variable. This is
13 | # used by the install-racket.sh script (run at before_install,
14 | # below) to select the version of Racket to download and install.
15 | #
16 | # Supply more than one RACKET_VERSION (as in the example below) to
17 | # create a Travis-CI build matrix to test against multiple Racket
18 | # versions.
19 | - RACKET_VERSION=6.12
20 | - RACKET_VERSION=7.0
21 | - RACKET_VERSION=7.1
22 | - RACKET_VERSION=7.2
23 | - RACKET_VERSION=HEAD
24 |
25 | matrix:
26 | allow_failures:
27 | # - env: RACKET_VERSION=HEAD
28 | fast_finish: true
29 |
30 | before_install:
31 | - git clone https://github.com/greghendershott/travis-racket.git ~/travis-racket
32 | - cat ~/travis-racket/install-racket.sh | bash # pipe to bash not sh!
33 | - export PATH="${RACKET_DIR}/bin:${PATH}" #install-racket.sh can't set for us
34 |
35 | install:
36 | - raco pkg install --auto --name web-view
37 |
38 | before_script:
39 |
40 | # Here supply steps such as raco make, raco test, etc. You can run
41 | # `raco pkg install --deps search-auto` to install any required
42 | # packages without it getting stuck on a confirmation prompt.
43 | script:
44 | - raco test -x -p web-view
45 |
46 | after_success:
47 | - raco setup --check-pkg-deps --pkgs web-view
48 | - raco pkg install --auto cover cover-coveralls
49 | - raco cover -b -f coveralls -d $TRAVIS_BUILD_DIR/coverage .
50 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | web-view
2 |
3 | MIT License
4 |
5 | Copyright (c) 2019 agarzia
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | web-view%
2 | ========
3 |
4 | 
5 |
6 | A Racket package to provide a `web-view%` control to applications based on Racket GUI Toolkit.
7 |
8 | There is some minimal [documentation available](https://soapdog.github.io/racket-web-view/).
9 |
10 | This repo is also available at [sourcehut](https://git.sr.ht/~soapdog/racket-web-view).
11 |
12 | ## What works
13 |
14 | You can create a `web-view%`, set its URL and the page loads. You can navigate as well.
15 |
16 | ## What doesn't work
17 |
18 | Everything else.
19 |
20 | Also, at the moment it is macOS only. It wraps around WKWebView.
21 |
22 | # Demo
23 |
24 | Install the package with the following command on the checkout folder for this repo:
25 |
26 | ```
27 | $ raco pkg install
28 | ```
29 |
30 | You can run a demo with by loading `demo/demo.rkt`.
31 |
32 | # Sample code:
33 |
34 | ```
35 | (define web-view
36 | (new web-view%
37 | [parent panel]))
38 |
39 | (send web-view set-url "https://racket-lang.org")
40 | ```
41 |
42 | ---
43 |
44 |
--------------------------------------------------------------------------------
/build-docs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cd ./scribblings
4 | scribble --htmls ++main-xref-in --redirect-main http://docs.racket-lang.org/ --dest ../docs/ ./web-view.scrbl
5 | cd ../docs
6 | mv ./web-view/* ./
7 | rm -rf ./web-view
8 | cd ..
--------------------------------------------------------------------------------
/demo/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/soapdog/racket-web-view/fa16e0c31b5a3e75c543df3107d8c8a230a10934/demo/demo.png
--------------------------------------------------------------------------------
/demo/demo.rkt:
--------------------------------------------------------------------------------
1 | #lang at-exp racket/gui
2 |
3 | (require web-view)
4 |
5 | (define frame
6 | (new frame%
7 | [label "Demo Browser"]
8 | [width 800]
9 | [height 600]
10 | [x 100]
11 | [y 100]))
12 |
13 | (define toolbar
14 | (new horizontal-panel%
15 | [parent frame]
16 | [min-height 40]
17 | [stretchable-height #f]))
18 |
19 | (define (go-to-url button event)
20 | (send web-view set-url (send address-bar get-value)))
21 |
22 | (define test-html @string-append{
23 |
It Works
24 | This is a test of setting the HTML text of the browser to a string
25 | instead of a URL.
26 | })
27 |
28 | (define (test-text button event)
29 | (send web-view set-html-text test-html ""))
30 |
31 | (define (go-forward button event)
32 | (send web-view go-forward))
33 |
34 | (define (go-back button event)
35 | (send web-view go-back))
36 |
37 | (define (reload button event)
38 | (send web-view reload))
39 |
40 | (define address-bar
41 | (new text-field%
42 | [parent toolbar]
43 | [label "URL"]))
44 |
45 | (define go-button
46 | (new button%
47 | [parent toolbar]
48 | [label "Go"]
49 | [callback go-to-url]))
50 |
51 |
52 | (define go-back-button
53 | (new button%
54 | [parent toolbar]
55 | [label "<"]
56 | [callback go-back]))
57 |
58 | (define go-forward-button
59 | (new button%
60 | [parent toolbar]
61 | [label ">"]
62 | [callback go-forward]))
63 |
64 | (define reload-button
65 | (new button%
66 | [parent toolbar]
67 | [label "reload"]
68 | [callback reload]))
69 |
70 | (define test-text-button
71 | (new button%
72 | [parent toolbar]
73 | [label "text"]
74 | [callback test-text]))
75 |
76 | (define (resize-browser w h)
77 | (send web-view on-size w h))
78 |
79 | (send frame show #t)
80 | (send frame create-status-line)
81 |
82 | (define (status-change status)
83 | (begin0
84 | (send frame set-status-text status)))
85 |
86 | ; needs to be after parent show so that we have parents dimensions
87 | (define web-view
88 | (new web-view%
89 | [parent frame]
90 | [on-status-change status-change]))
91 |
92 | (send web-view set-url "https://racket-lang.org")
93 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 | A Racket GUI widget to display web pages 7.4
A Racket GUI widget to display web pages
This module contains a Web View to be used with Racket GUI Toolkit. At the moment it works only with macOS because it wraps WKWebView from WebKit.
There is a Demo Browser available on the Github Repository .
A widget to display web pages.
Construct a new widget.
The on-status-change procedure is used to receive navigation events from the web view.
Set the URL for the web view.
Get the current URL loaded in the web view.
Navigates forward.
Navigates backward.
Reloads the current page.
Sets the HTML text being used by the web view. Any relative url will be relative to the specified base url.
--------------------------------------------------------------------------------
/docs/manual-racket.css:
--------------------------------------------------------------------------------
1 | /* See the beginning of "manual.css". */
2 |
3 | /* Monospace: */
4 |
5 | .RktIn, .RktRdr, .RktPn, .RktMeta,
6 | .RktMod, .RktKw, .RktVar, .RktSym,
7 | .RktRes, .RktOut, .RktCmt, .RktVal,
8 | .RktBlk, .RktErr {
9 | font-family: 'Fira-Mono', monospace;
10 | white-space: inherit;
11 | font-size: 1rem;
12 | line-height: 1.5;
13 |
14 | }
15 |
16 | /* this selctor grabs the first linked Racket symbol
17 | in a definition box (i.e., the symbol being defined) */
18 | a.RktValDef, a.RktStxDef, a.RktSymDef,
19 | span.RktValDef, span.RktStxDef, span.RktSymDef
20 | {
21 | font-size: 1.1rem;
22 | color: black;
23 | font-weight: 500;
24 | }
25 |
26 |
27 | .inheritedlbl {
28 | font-family: 'Fira', sans-serif;
29 | }
30 |
31 | .RBackgroundLabelInner {
32 | font-family: inherit;
33 | }
34 |
35 | /* ---------------------------------------- */
36 | /* Inherited methods, left margin */
37 |
38 | .inherited {
39 | width: 95%;
40 | margin-top: 0.5em;
41 | text-align: left;
42 | background-color: inherit;
43 | }
44 |
45 | .inherited td {
46 | font-size: 82%;
47 | padding-left: 0.5rem;
48 | line-height: 1.3;
49 | text-indent: 0;
50 | padding-right: 0;
51 | }
52 |
53 | .inheritedlbl {
54 | font-style: normal;
55 | }
56 |
57 | /* ---------------------------------------- */
58 | /* Racket text styles */
59 |
60 | .RktIn {
61 | color: #cc6633;
62 | background-color: #eee;
63 | }
64 |
65 | .RktInBG {
66 | background-color: #eee;
67 | }
68 |
69 |
70 | .refcolumn .RktInBG {
71 | background-color: white;
72 | }
73 |
74 | .RktRdr {
75 | }
76 |
77 | .RktPn {
78 | color: #843c24;
79 | }
80 |
81 | .RktMeta {
82 | color: black;
83 | }
84 |
85 | .RktMod {
86 | color: inherit;
87 | }
88 |
89 | .RktOpt {
90 | color: black;
91 | }
92 |
93 | .RktKw {
94 | color: black;
95 | }
96 |
97 | .RktErr {
98 | color: red;
99 | font-style: italic;
100 | font-weight: 400;
101 | }
102 |
103 | .RktVar {
104 | position: relative;
105 | left: -1px; font-style: italic;
106 | color: #444;
107 | }
108 |
109 | .SVInsetFlow .RktVar {
110 | font-weight: 400;
111 | color: #444;
112 | }
113 |
114 |
115 | .RktSym {
116 | color: inherit;
117 | }
118 |
119 |
120 |
121 | .RktValLink, .RktStxLink, .RktModLink {
122 | text-decoration: none;
123 | color: #07A;
124 | font-size: 1rem;
125 | }
126 |
127 | /* for syntax links within headings */
128 | h2 a.RktStxLink, h3 a.RktStxLink, h4 a.RktStxLink, h5 a.RktStxLink,
129 | h2 a.RktValLink, h3 a.RktValLink, h4 a.RktValLink, h5 a.RktValLink,
130 | h2 .RktSym, h3 .RktSym, h4 .RktSym, h5 .RktSym,
131 | h2 .RktMod, h3 .RktMod, h4 .RktMod, h5 .RktMod,
132 | h2 .RktVal, h3 .RktVal, h4 .RktVal, h5 .RktVal,
133 | h2 .RktPn, h3 .RktPn, h4 .RktPn, h5 .RktPn {
134 | color: #333;
135 | font-size: 1.50rem;
136 | font-weight: 400;
137 | }
138 |
139 | .toptoclink .RktStxLink, .toclink .RktStxLink,
140 | .toptoclink .RktValLink, .toclink .RktValLink,
141 | .toptoclink .RktModLink, .toclink .RktModLink {
142 | color: inherit;
143 | }
144 |
145 | .tocset .RktValLink, .tocset .RktStxLink, .tocset .RktModLink, .tocset .RktSym {
146 | color: black;
147 | font-weight: 400;
148 | font-size: 0.9rem;
149 | }
150 |
151 | .tocset td a.tocviewselflink .RktValLink,
152 | .tocset td a.tocviewselflink .RktStxLink,
153 | .tocset td a.tocviewselflink .RktMod,
154 | .tocset td a.tocviewselflink .RktSym {
155 | font-weight: lighter;
156 | color: white;
157 | }
158 |
159 |
160 | .RktRes {
161 | color: #0000af;
162 | }
163 |
164 | .RktOut {
165 | color: #960096;
166 | }
167 |
168 | .RktCmt {
169 | color: #c2741f;
170 | }
171 |
172 | .RktVal {
173 | color: #228b22;
174 | }
175 |
176 | /* ---------------------------------------- */
177 | /* Some inline styles */
178 |
179 | .together { /* for definitions grouped together in one box */
180 | width: 100%;
181 | border-top: 2px solid white;
182 | }
183 |
184 | tbody > tr:first-child > td > .together {
185 | border-top: 0px; /* erase border on first instance of together */
186 | }
187 |
188 | .RktBlk {
189 | white-space: pre;
190 | text-align: left;
191 | }
192 |
193 | .highlighted {
194 | font-size: 1rem;
195 | background-color: #fee;
196 | }
197 |
198 | .defmodule {
199 | font-family: 'Fira-Mono', monospace;
200 | padding: 0.25rem 0.75rem 0.25rem 0.5rem;
201 | margin-bottom: 1rem;
202 | width: 100%;
203 | background-color: #ebf0f4;
204 | }
205 |
206 | .defmodule a {
207 | color: #444;
208 | }
209 |
210 |
211 | .defmodule td span.hspace:first-child {
212 | position: absolute;
213 | width: 0;
214 | display: inline-block;
215 | }
216 |
217 | .defmodule .RpackageSpec .Smaller,
218 | .defmodule .RpackageSpec .stt {
219 | font-size: 1rem;
220 | }
221 |
222 | /* make parens ordinary color in defmodule */
223 | .defmodule .RktPn {
224 | color: inherit;
225 | }
226 |
227 | .specgrammar {
228 | float: none;
229 | padding-left: 1em;
230 | }
231 |
232 |
233 | .RBibliography td {
234 | vertical-align: text-top;
235 | padding-top: 1em;
236 | }
237 |
238 | .leftindent {
239 | margin-left: 2rem;
240 | margin-right: 0em;
241 | }
242 |
243 | .insetpara {
244 | margin-left: 1em;
245 | margin-right: 1em;
246 | }
247 |
248 | .SCodeFlow .Rfilebox {
249 | margin-left: -1em; /* see 17.2 of guide, module languages */
250 | }
251 |
252 | .Rfiletitle {
253 | text-align: right;
254 | background-color: #eee;
255 | }
256 |
257 | .SCodeFlow .Rfiletitle {
258 | border-top: 1px dotted gray;
259 | border-right: 1px dotted gray;
260 | }
261 |
262 |
263 | .Rfilename {
264 | border-top: 0;
265 | border-right: 0;
266 | padding-left: 0.5em;
267 | padding-right: 0.5em;
268 | background-color: inherit;
269 | }
270 |
271 | .Rfilecontent {
272 | margin: 0.5em;
273 | }
274 |
275 | .RpackageSpec {
276 | padding-right: 0;
277 | }
278 |
279 | /* ---------------------------------------- */
280 | /* For background labels */
281 |
282 | .RBackgroundLabel {
283 | float: right;
284 | width: 0px;
285 | height: 0px;
286 | }
287 |
288 | .RBackgroundLabelInner {
289 | position: relative;
290 | width: 25em;
291 | left: -25.5em;
292 | top: 0.20rem; /* sensitive to monospaced font choice */
293 | text-align: right;
294 | z-index: 0;
295 | font-weight: 300;
296 | font-family: 'Fira-Mono', monospace;
297 | font-size: 0.9rem;
298 | color: gray;
299 | }
300 |
301 |
302 | .RpackageSpec .Smaller {
303 | font-weight: 300;
304 | font-family: 'Fira-Mono', monospace;
305 | font-size: 0.9rem;
306 | }
307 |
308 | .RForeground {
309 | position: relative;
310 | left: 0px;
311 | top: 0px;
312 | z-index: 1;
313 | }
314 |
315 | /* ---------------------------------------- */
316 | /* For section source modules & tags */
317 |
318 | .RPartExplain {
319 | background: #eee;
320 | font-size: 0.9rem;
321 | margin-top: 0.2rem;
322 | padding: 0.2rem;
323 | text-align: left;
324 | }
325 |
--------------------------------------------------------------------------------
/docs/manual-racket.js:
--------------------------------------------------------------------------------
1 | /* For the Racket manual style */
2 |
3 | AddOnLoad(function() {
4 | /* Look for header elements that have x-source-module and x-part tag.
5 | For those elements, add a hidden element that explains how to
6 | link to the section, and set the element's onclick() to display
7 | the explanation. */
8 | var tag_names = ["h1", "h2", "h3", "h4", "h5"];
9 | for (var j = 0; j < tag_names.length; j++) {
10 | elems = document.getElementsByTagName(tag_names[j]);
11 | for (var i = 0; i < elems.length; i++) {
12 | var elem = elems.item(i);
13 | AddPartTitleOnClick(elem);
14 | }
15 | }
16 | })
17 |
18 | function AddPartTitleOnClick(elem) {
19 | var mod_path = elem.getAttribute("x-source-module");
20 | var tag = elem.getAttribute("x-part-tag");
21 | if (mod_path && tag) {
22 | // Might not be present:
23 | var prefixes = elem.getAttribute("x-part-prefixes");
24 |
25 | var info = document.createElement("div");
26 | info.className = "RPartExplain";
27 |
28 | /* The "top" tag refers to a whole document: */
29 | var is_top = (tag == "\"top\"");
30 | info.appendChild(document.createTextNode("Link to this "
31 | + (is_top ? "document" : "section")
32 | + " with "));
33 |
34 | /* Break `secref` into two lines if the module path and tag
35 | are long enough: */
36 | var is_long = (is_top ? false : ((mod_path.length
37 | + tag.length
38 | + (prefixes ? (16 + prefixes.length) : 0))
39 | > 60));
40 |
41 | var line1 = document.createElement("div");
42 | var line1x = ((is_long && prefixes) ? document.createElement("div") : line1);
43 | var line2 = (is_long ? document.createElement("div") : line1);
44 |
45 | function add(dest, str, cn) {
46 | var s = document.createElement("span");
47 | s.className = cn;
48 | s.style.whiteSpace = "nowrap";
49 | s.appendChild(document.createTextNode(str));
50 | dest.appendChild(s);
51 | }
52 | /* Construct a `secref` call with suitable syntax coloring: */
53 | add(line1, "\xA0@", "RktRdr");
54 | add(line1, (is_top ? "other-doc" : "secref"), "RktSym");
55 | add(line1, "[", "RktPn");
56 | if (!is_top)
57 | add(line1, tag, "RktVal");
58 | if (is_long) {
59 | /* indent additional lines: */
60 | if (prefixes)
61 | add(line1x, "\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0", "RktPn");
62 | add(line2, "\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0", "RktPn");
63 | }
64 | if (prefixes) {
65 | add(line1x, " #:tag-prefixes ", "RktPn");
66 | add(line1x, "'", "RktVal");
67 | add(line1x, prefixes, "RktVal");
68 | }
69 | if (!is_top)
70 | add(line2, " #:doc ", "RktPn");
71 | add(line2, "'", "RktVal");
72 | add(line2, mod_path, "RktVal");
73 | add(line2, "]", "RktPn");
74 |
75 | info.appendChild(line1);
76 | if (is_long)
77 | info.appendChild(line1x);
78 | if (is_long)
79 | info.appendChild(line2);
80 |
81 | info.style.display = "none";
82 |
83 | /* Add the new element afterthe header: */
84 | var n = elem.nextSibling;
85 | if (n)
86 | elem.parentNode.insertBefore(info, n);
87 | else
88 | elem.parentNode.appendChild(info);
89 |
90 | /* Clicking the header shows the explanation element: */
91 | elem.onclick = function () {
92 | if (info.style.display == "none")
93 | info.style.display = "block";
94 | else
95 | info.style.display = "none";
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/docs/manual-style.css:
--------------------------------------------------------------------------------
1 |
2 | /* See the beginning of "scribble.css".
3 | This file is used by the `scribble/manual` language, along with
4 | "manual-racket.css". */
5 |
6 | @import url("manual-fonts.css");
7 |
8 | * {
9 | margin: 0;
10 | padding: 0;
11 | }
12 |
13 | @media all {html {font-size: 15px;}}
14 | @media all and (max-width:940px){html {font-size: 14px;}}
15 | @media all and (max-width:850px){html {font-size: 13px;}}
16 | @media all and (max-width:830px){html {font-size: 12px;}}
17 | @media all and (max-width:740px){html {font-size: 11px;}}
18 |
19 | /* CSS seems backward: List all the classes for which we want a
20 | particular font, so that the font can be changed in one place. (It
21 | would be nicer to reference a font definition from all the places
22 | that we want it.)
23 |
24 | As you read the rest of the file, remember to double-check here to
25 | see if any font is set. */
26 |
27 | /* Monospace: */
28 | .maincolumn, .refpara, .refelem, .tocset, .stt, .hspace, .refparaleft, .refelemleft {
29 | font-family: 'Fira-Mono', monospace;
30 | white-space: inherit;
31 | font-size: 1rem;
32 | }
33 |
34 | /* embolden the "Racket Guide" and "Racket Reference" links on the TOC */
35 | /* there isn't an obvious tag in the markup that designates the top TOC page, which is called "start.scrbl" */
36 | /* nor a tag that designates these two links as special */
37 | /* so we'll use this slightly tortured sibling selector that hooks onto the h2 tag */
38 | h2[x-source-module='(lib "scribblings/main/start.scrbl")'] ~ table a[href="guide/index.html"],
39 | h2[x-source-module='(lib "scribblings/main/start.scrbl")'] ~ table a[href="reference/index.html"] {
40 | font-weight: bold;
41 | }
42 |
43 |
44 | h2 .stt {
45 | font-size: 2.3rem;
46 | /* prevent automatic bolding from h2 */
47 | font-weight: 400;
48 | }
49 |
50 | .toptoclink .stt {
51 | font-size: inherit;
52 | }
53 | .toclink .stt {
54 | font-size: 90%;
55 | }
56 |
57 | .RpackageSpec .stt {
58 | font-weight: 300;
59 | font-family: 'Fira-Mono', monospace;
60 | font-size: 0.9rem;
61 | }
62 |
63 | h3 .stt, h4 .stt, h5 .stt {
64 | color: #333;
65 | font-size: 1.65rem;
66 | font-weight: 400;
67 | }
68 |
69 |
70 | /* Serif: */
71 | .main, .refcontent, .tocview, .tocsub, .sroman, i {
72 | font-family: 'Charter-Racket', serif;
73 | font-size: 1.18rem;
74 | /* Don't use font-feature-settings with Charter,
75 | it fouls up loading for reasons mysterious */
76 | /* font-feature-settings: 'tnum' 1, 'liga' 0; */
77 | }
78 |
79 |
80 | /* Sans-serif: */
81 | .version, .versionNoNav, .ssansserif {
82 | font-family: 'Fira', sans-serif;
83 | }
84 |
85 | /* used mostly for DrRacket menu commands */
86 | .ssansserif {
87 | font-family: 'Fira', sans-serif;
88 | font-size: 0.9em;
89 | }
90 |
91 | .tocset .ssansserif {
92 | font-size: 100%;
93 | }
94 |
95 | /* ---------------------------------------- */
96 |
97 | p, .SIntrapara {
98 | display: block;
99 | margin: 0 0 1em 0;
100 | line-height: 1.4;
101 | }
102 |
103 | .compact {
104 | padding: 0 0 1em 0;
105 | }
106 |
107 | li {
108 | list-style-position: outside;
109 | margin-left: 1.2em;
110 | }
111 |
112 | h1, h2, h3, h4, h5, h6, h7, h8 {
113 | font-family: 'Fira', sans-serif;
114 | font-weight: 300;
115 | font-size: 1.6rem;
116 | color: #333;
117 | margin-top: inherit;
118 | margin-bottom: 1rem;
119 | line-height: 1.25;
120 |
121 | }
122 |
123 | h3, h4, h5, h6, h7, h8 {
124 | border-top: 1px solid black;
125 | }
126 |
127 |
128 |
129 | h2 { /* per-page main title */
130 | font-family: 'Cooper-Hewitt';
131 | margin-top: 4rem;
132 | font-size: 2.3rem;
133 | font-weight: bold;
134 | line-height: 1.2;
135 | width: 90%;
136 | /* a little nudge to make text visually lower than 4rem rule in left margin */
137 | position: relative;
138 | top: 6px;
139 | }
140 |
141 | h3, h4, h5, h6, h7, h8 {
142 | margin-top: 2em;
143 | padding-top: 0.1em;
144 | margin-bottom: 0.75em;
145 | }
146 |
147 | /* ---------------------------------------- */
148 | /* Main */
149 |
150 | body {
151 | color: black;
152 | background-color: white;
153 | }
154 |
155 | .maincolumn {
156 | width: auto;
157 | margin-top: 4rem;
158 | margin-left: 17rem;
159 | margin-right: 2rem;
160 | margin-bottom: 10rem; /* to avoid fixed bottom nav bar */
161 | max-width: 700px;
162 | min-width: 370px; /* below this size, code samples don't fit */
163 | }
164 |
165 | a {
166 | text-decoration: inherit;
167 | }
168 |
169 | a, .toclink, .toptoclink, .tocviewlink, .tocviewselflink, .tocviewtoggle, .plainlink,
170 | .techinside, .techoutside:hover, .techinside:hover {
171 | color: #07A;
172 | }
173 |
174 | a:hover {
175 | text-decoration: underline;
176 | }
177 |
178 |
179 | /* ---------------------------------------- */
180 | /* Navigation */
181 |
182 | .navsettop, .navsetbottom {
183 | left: 0;
184 | width: 15rem;
185 | height: 6rem;
186 | font-family: 'Fira', sans-serif;
187 | font-size: 0.9rem;
188 | border-bottom: 0px solid hsl(216, 15%, 70%);
189 | background-color: inherit;
190 | padding: 0;
191 | }
192 |
193 | .navsettop {
194 | position: absolute;
195 | top: 0;
196 | left: 0;
197 | margin-bottom: 0;
198 | border-bottom: 0;
199 | }
200 |
201 | .navsettop a, .navsetbottom a {
202 | color: black;
203 | }
204 |
205 | .navsettop a:hover, .navsetbottom a:hover {
206 | background: hsl(216, 78%, 95%);
207 | text-decoration: none;
208 | }
209 |
210 | .navleft, .navright {
211 | position: static;
212 | float: none;
213 | margin: 0;
214 | white-space: normal;
215 | }
216 |
217 |
218 | .navleft a {
219 | display: inline-block;
220 | }
221 |
222 | .navright a {
223 | display: inline-block;
224 | text-align: center;
225 | }
226 |
227 | .navleft a, .navright a, .navright span {
228 | display: inline-block;
229 | padding: 0.5rem;
230 | min-width: 1rem;
231 | }
232 |
233 |
234 | .navright {
235 | height: 2rem;
236 | white-space: nowrap;
237 | }
238 |
239 |
240 | .navsetbottom {
241 | display: none;
242 | }
243 |
244 | .nonavigation {
245 | color: #889;
246 | }
247 |
248 | .searchform {
249 | display: block;
250 | margin: 0;
251 | padding: 0;
252 | border-bottom: 1px solid #eee;
253 | height: 4rem;
254 | }
255 |
256 | .nosearchform {
257 | margin: 0;
258 | padding: 0;
259 | height: 4rem;
260 | }
261 |
262 | .searchbox {
263 | font-size: 0.9rem;
264 | width: 12rem;
265 | margin: 1rem;
266 | padding: 0.25rem 0.4rem ;
267 | vertical-align: middle;
268 | background-color: white;
269 | font-family: 'Fira-Mono', monospace;
270 | }
271 |
272 |
273 | #search_box {
274 | font-family: 'Fira-Mono', monospace;
275 | font-size: 1rem;
276 | padding: 0.25rem 0.3rem ;
277 | }
278 |
279 | /* Default to local view. Global will specialize */
280 | .plt_global_only { display: none; }
281 | .plt_local_only { display: block; }
282 |
283 | /* ---------------------------------------- */
284 | /* Version */
285 |
286 | .versionbox {
287 | position: absolute;
288 | float: none;
289 | top: 0.25rem;
290 | left: 17rem;
291 | z-index: 11000;
292 | height: 2em;
293 | font-size: 70%;
294 | font-weight: lighter;
295 | width: inherit;
296 | margin: 0;
297 | }
298 | .version, .versionNoNav {
299 | font-size: inherit;
300 | }
301 | .version:before, .versionNoNav:before {
302 | content: "v.";
303 | }
304 |
305 |
306 | /* ---------------------------------------- */
307 | /* Margin notes */
308 |
309 | /* cancel scribble.css styles: */
310 | .refpara, .refelem {
311 | position: static;
312 | float: none;
313 | height: auto;
314 | width: auto;
315 | margin: 0;
316 | }
317 |
318 | .refcolumn {
319 | position: static;
320 | display: block;
321 | width: auto;
322 | font-size: inherit;
323 | margin: 2rem;
324 | margin-left: 2rem;
325 | padding: 0.5em;
326 | padding-left: 0.75em;
327 | padding-right: 1em;
328 | background: hsl(60, 29%, 94%);
329 | border: 1px solid #ccb;
330 | border-left: 0.4rem solid #ccb;
331 | }
332 |
333 |
334 | /* slightly different handling for margin-note* on narrow screens */
335 | @media all and (max-width:1340px) {
336 | span.refcolumn {
337 | float: right;
338 | width: 50%;
339 | margin-left: 1rem;
340 | margin-bottom: 0.8rem;
341 | margin-top: 1.2rem;
342 | }
343 |
344 | }
345 |
346 | .refcontent, .refcontent p {
347 | line-height: 1.5;
348 | margin: 0;
349 | }
350 |
351 | .refcontent p + p {
352 | margin-top: 1em;
353 | }
354 |
355 | .refcontent a {
356 | font-weight: 400;
357 | }
358 |
359 | .refpara, .refparaleft {
360 | top: -1em;
361 | }
362 |
363 |
364 | @media all and (max-width:600px) {
365 | .refcolumn {
366 | margin-left: 0;
367 | margin-right: 0;
368 | }
369 | }
370 |
371 |
372 | @media all and (min-width:1340px) {
373 | .refcolumn {
374 | margin: 0 -22.5rem 1rem 0;
375 | float: right;
376 | clear: right;
377 | width: 18rem;
378 | }
379 | }
380 |
381 | .refcontent {
382 | font-family: 'Fira', sans-serif;
383 | font-size: 1rem;
384 | line-height: 1.6;
385 | margin: 0 0 0 0;
386 | }
387 |
388 |
389 | .refparaleft, .refelemleft {
390 | position: relative;
391 | float: left;
392 | right: 2em;
393 | height: 0em;
394 | width: 13em;
395 | margin: 0em 0em 0em -13em;
396 | }
397 |
398 | .refcolumnleft {
399 | background-color: hsl(60, 29%, 94%);
400 | display: block;
401 | position: relative;
402 | width: 13em;
403 | font-size: 85%;
404 | border: 0.5em solid hsl(60, 29%, 94%);
405 | margin: 0 0 0 0;
406 | }
407 |
408 |
409 | /* ---------------------------------------- */
410 | /* Table of contents, left margin */
411 |
412 | .tocset {
413 | position: absolute;
414 | float: none;
415 | left: 0;
416 | top: 0rem;
417 | width: 14rem;
418 | padding: 7rem 0.5rem 0.5rem 0.5rem;
419 | background-color: hsl(216, 15%, 70%);
420 | margin: 0;
421 |
422 | }
423 |
424 | .tocset td {
425 | vertical-align: text-top;
426 | padding-bottom: 0.4rem;
427 | padding-left: 0.2rem;
428 | line-height: 1.1;
429 | font-family: 'Fira', sans-serif;
430 | }
431 |
432 | .tocset td a {
433 | color: black;
434 | font-weight: 400;
435 | }
436 |
437 |
438 | .tocview {
439 | text-align: left;
440 | background-color: inherit;
441 | }
442 |
443 |
444 | .tocview td, .tocsub td {
445 | line-height: 1.3;
446 | }
447 |
448 |
449 | .tocview table, .tocsub table {
450 | width: 90%;
451 | }
452 |
453 | .tocset td a.tocviewselflink {
454 | font-weight: lighter;
455 | font-size: 110%; /* monospaced styles below don't need to enlarge */
456 | color: white;
457 | }
458 |
459 | .tocviewselflink {
460 | text-decoration: none;
461 | }
462 |
463 | .tocsub {
464 | text-align: left;
465 | margin-top: 0.5em;
466 | background-color: inherit;
467 | }
468 |
469 | .tocviewlist, .tocsublist {
470 | margin-left: 0.2em;
471 | margin-right: 0.2em;
472 | padding-top: 0.2em;
473 | padding-bottom: 0.2em;
474 | }
475 | .tocviewlist table {
476 | font-size: 82%;
477 | }
478 |
479 | .tocviewlisttopspace {
480 | margin-bottom: 1em;
481 | }
482 |
483 | .tocviewsublist, .tocviewsublistonly, .tocviewsublisttop, .tocviewsublistbottom {
484 | margin-left: 0.4em;
485 | border-left: 1px solid #99a;
486 | padding-left: 0.8em;
487 | }
488 | .tocviewsublist {
489 | margin-bottom: 1em;
490 | }
491 | .tocviewsublist table,
492 | .tocviewsublistonly table,
493 | .tocviewsublisttop table,
494 | .tocviewsublistbottom table,
495 | table.tocsublist {
496 | font-size: 1rem;
497 | }
498 |
499 | .tocviewsublist td,
500 | .tocviewsublistbottom td,
501 | .tocviewsublisttop td,
502 | .tocsub td,
503 | .tocviewsublistonly td {
504 | font-size: 90%;
505 | }
506 |
507 | /* shrink the monospaced text (`stt`) within nav */
508 | .tocviewsublist td .stt,
509 | .tocviewsublistbottom td .stt,
510 | .tocviewsublisttop td .stt,
511 | .tocsub td .stt,
512 | .tocviewsublistonly td .stt {
513 | font-size: 95%;
514 | }
515 |
516 |
517 | .tocviewtoggle {
518 | font-size: 75%; /* looks better, and avoids bounce when toggling sub-sections due to font alignments */
519 | }
520 |
521 | .tocsublist td {
522 | padding-left: 0.5rem;
523 | padding-top: 0.25rem;
524 | text-indent: 0;
525 | }
526 |
527 | .tocsublinknumber {
528 | font-size: 100%;
529 | }
530 |
531 | .tocsublink {
532 | font-size: 82%;
533 | text-decoration: none;
534 | }
535 |
536 | .tocsubseclink {
537 | font-size: 100%;
538 | text-decoration: none;
539 | }
540 |
541 | .tocsubnonseclink {
542 | font-size: 82%;
543 | text-decoration: none;
544 | margin-left: 1rem;
545 | padding-left: 0;
546 | display: inline-block;
547 | }
548 |
549 | /* the label "on this page" */
550 | .tocsubtitle {
551 | display: block;
552 | font-size: 62%;
553 | font-family: 'Fira', sans-serif;
554 | font-weight: bolder;
555 | font-style: normal;
556 | letter-spacing: 2px;
557 | text-transform: uppercase;
558 | margin: 0.5em;
559 | }
560 |
561 | .toptoclink {
562 | font-weight: bold;
563 | font-size: 110%;
564 | margin-bottom: 0.5rem;
565 | margin-top: 1.5rem;
566 | display: inline-block;
567 | }
568 |
569 | .toclink {
570 | font-size: inherit;
571 | }
572 |
573 | /* ---------------------------------------- */
574 | /* Some inline styles */
575 |
576 | .indexlink {
577 | text-decoration: none;
578 | }
579 |
580 | pre {
581 | margin-left: 2em;
582 | }
583 |
584 | blockquote {
585 | margin-left: 2em;
586 | margin-right: 2em;
587 | margin-bottom: 1em;
588 | }
589 |
590 | .SCodeFlow {
591 | border-left: 1px dotted black;
592 | padding-left: 1em;
593 | padding-right: 1em;
594 | margin-top: 1em;
595 | margin-bottom: 1em;
596 | margin-left: 0em;
597 | margin-right: 2em;
598 | white-space: nowrap;
599 | line-height: 1.5;
600 | }
601 |
602 | .SCodeFlow img {
603 | margin-top: 0.5em;
604 | margin-bottom: 0.5em;
605 | }
606 |
607 | /* put a little air between lines of code sample */
608 | /* Fira Mono appears taller than Source Code Pro */
609 | .SCodeFlow td {
610 | padding-bottom: 1px;
611 | }
612 |
613 | .boxed {
614 | margin: 0;
615 | margin-top: 2em;
616 | padding: 0.25em;
617 | padding-top: 0.3em;
618 | padding-bottom: 0.4em;
619 | background: #f3f3f3;
620 | box-sizing:border-box;
621 | border-top: 1px solid #99b;
622 | background: hsl(216, 78%, 95%);
623 | background: -moz-linear-gradient(to bottom left, hsl(0, 0%, 99%) 0%, hsl(216, 62%, 95%) 100%);
624 | background: -webkit-linear-gradient(to bottom left, hsl(0, 0%, 99%) 0%, hsl(216, 62%, 95%) 100%);
625 | background: -o-linear-gradient(to bottom left, hsl(0, 0%, 99%) 0%, hsl(216, 62%, 95%) 100%);
626 | background: -ms-linear-gradient(to bottom left, hsl(0, 0%, 99%) 0%, hsl(216, 62%, 95%) 100%);
627 | background: linear-gradient(to bottom left, hsl(0, 0%, 99%) 0%, hsl(216, 62%, 95%) 100%);
628 | }
629 |
630 | blockquote > blockquote.SVInsetFlow {
631 | /* resolves issue in e.g. /reference/notation.html */
632 | margin-top: 0em;
633 | }
634 |
635 | .leftindent .SVInsetFlow { /* see e.g. section 4.5 of Racket Guide */
636 | margin-top: 1em;
637 | margin-bottom: 1em;
638 | }
639 |
640 | .SVInsetFlow a, .SCodeFlow a {
641 | color: #07A;
642 | }
643 |
644 | .SubFlow {
645 | display: block;
646 | margin: 0em;
647 | }
648 |
649 | .boxed {
650 | width: 100%;
651 | background-color: inherit;
652 | }
653 |
654 | .techoutside { text-decoration: none; }
655 |
656 | .SAuthorListBox {
657 | position: static;
658 | float: none;
659 | font-family: 'Fira', sans-serif;
660 | font-weight: 300;
661 | font-size: 110%;
662 | margin-top: 1rem;
663 | margin-bottom: 2rem;
664 | width: 30rem;
665 | height: auto;
666 | }
667 |
668 | .author > a { /* email links within author block */
669 | font-weight: inherit;
670 | color: inherit;
671 | }
672 |
673 | .SAuthorList {
674 | font-size: 82%;
675 | }
676 | .SAuthorList:before {
677 | content: "by ";
678 | }
679 | .author {
680 | display: inline;
681 | white-space: nowrap;
682 | }
683 |
684 | /* phone + tablet styles */
685 |
686 | @media all and (max-width:720px){
687 |
688 |
689 | @media all and (max-width:720px){
690 |
691 | @media all {html {font-size: 15px;}}
692 | @media all and (max-width:700px){html {font-size: 14px;}}
693 | @media all and (max-width:630px){html {font-size: 13px;}}
694 | @media all and (max-width:610px){html {font-size: 12px;}}
695 | @media all and (max-width:550px){html {font-size: 11px;}}
696 | @media all and (max-width:520px){html {font-size: 10px;}}
697 |
698 | .navsettop, .navsetbottom {
699 | display: block;
700 | position: absolute;
701 | width: 100%;
702 | height: 4rem;
703 | border: 0;
704 | background-color: hsl(216, 15%, 70%);
705 | }
706 |
707 | .searchform {
708 | display: inline;
709 | border: 0;
710 | }
711 |
712 | .navright {
713 | position: absolute;
714 | right: 1.5rem;
715 | margin-top: 1rem;
716 | border: 0px solid red;
717 | }
718 |
719 | .navsetbottom {
720 | display: block;
721 | margin-top: 8rem;
722 | }
723 |
724 | .tocset {
725 | display: none;
726 | }
727 |
728 | .tocset table, .tocset tbody, .tocset tr, .tocset td {
729 | display: inline;
730 | }
731 |
732 | .tocview {
733 | display: none;
734 | }
735 |
736 | .tocsub .tocsubtitle {
737 | display: none;
738 | }
739 |
740 | .versionbox {
741 | top: 4.5rem;
742 | left: 1rem; /* same distance as main-column */
743 | z-index: 11000;
744 | height: 2em;
745 | font-size: 70%;
746 | font-weight: lighter;
747 | }
748 |
749 |
750 | .maincolumn {
751 | margin-left: 1em;
752 | margin-top: 7rem;
753 | margin-bottom: 0rem;
754 | }
755 |
756 | }
757 |
758 | }
759 |
760 | /* print styles : hide the navigation elements */
761 | @media print {
762 | .tocset,
763 | .navsettop,
764 | .navsetbottom { display: none; }
765 | .maincolumn {
766 | width: auto;
767 | margin-right: 13em;
768 | margin-left: 0;
769 | }
770 | }
771 |
--------------------------------------------------------------------------------
/docs/racket.css:
--------------------------------------------------------------------------------
1 |
2 | /* See the beginning of "scribble.css". */
3 |
4 | /* Monospace: */
5 | .RktIn, .RktRdr, .RktPn, .RktMeta,
6 | .RktMod, .RktKw, .RktVar, .RktSym,
7 | .RktRes, .RktOut, .RktCmt, .RktVal,
8 | .RktBlk {
9 | font-family: monospace;
10 | white-space: inherit;
11 | }
12 |
13 | /* Serif: */
14 | .inheritedlbl {
15 | font-family: serif;
16 | }
17 |
18 | /* Sans-serif: */
19 | .RBackgroundLabelInner {
20 | font-family: sans-serif;
21 | }
22 |
23 | /* ---------------------------------------- */
24 | /* Inherited methods, left margin */
25 |
26 | .inherited {
27 | width: 100%;
28 | margin-top: 0.5em;
29 | text-align: left;
30 | background-color: #ECF5F5;
31 | }
32 |
33 | .inherited td {
34 | font-size: 82%;
35 | padding-left: 1em;
36 | text-indent: -0.8em;
37 | padding-right: 0.2em;
38 | }
39 |
40 | .inheritedlbl {
41 | font-style: italic;
42 | }
43 |
44 | /* ---------------------------------------- */
45 | /* Racket text styles */
46 |
47 | .RktIn {
48 | color: #cc6633;
49 | background-color: #eeeeee;
50 | }
51 |
52 | .RktInBG {
53 | background-color: #eeeeee;
54 | }
55 |
56 | .RktRdr {
57 | }
58 |
59 | .RktPn {
60 | color: #843c24;
61 | }
62 |
63 | .RktMeta {
64 | color: black;
65 | }
66 |
67 | .RktMod {
68 | color: black;
69 | }
70 |
71 | .RktOpt {
72 | color: black;
73 | }
74 |
75 | .RktKw {
76 | color: black;
77 | }
78 |
79 | .RktErr {
80 | color: red;
81 | font-style: italic;
82 | }
83 |
84 | .RktVar {
85 | color: #262680;
86 | font-style: italic;
87 | }
88 |
89 | .RktSym {
90 | color: #262680;
91 | }
92 |
93 | .RktSymDef { /* used with RktSym at def site */
94 | }
95 |
96 | .RktValLink {
97 | text-decoration: none;
98 | color: blue;
99 | }
100 |
101 | .RktValDef { /* used with RktValLink at def site */
102 | }
103 |
104 | .RktModLink {
105 | text-decoration: none;
106 | color: blue;
107 | }
108 |
109 | .RktStxLink {
110 | text-decoration: none;
111 | color: black;
112 | }
113 |
114 | .RktStxDef { /* used with RktStxLink at def site */
115 | }
116 |
117 | .RktRes {
118 | color: #0000af;
119 | }
120 |
121 | .RktOut {
122 | color: #960096;
123 | }
124 |
125 | .RktCmt {
126 | color: #c2741f;
127 | }
128 |
129 | .RktVal {
130 | color: #228b22;
131 | }
132 |
133 | /* ---------------------------------------- */
134 | /* Some inline styles */
135 |
136 | .together {
137 | width: 100%;
138 | }
139 |
140 | .prototype, .argcontract, .RBoxed {
141 | white-space: nowrap;
142 | }
143 |
144 | .prototype td {
145 | vertical-align: text-top;
146 | }
147 |
148 | .RktBlk {
149 | white-space: inherit;
150 | text-align: left;
151 | }
152 |
153 | .RktBlk tr {
154 | white-space: inherit;
155 | }
156 |
157 | .RktBlk td {
158 | vertical-align: baseline;
159 | white-space: inherit;
160 | }
161 |
162 | .argcontract td {
163 | vertical-align: text-top;
164 | }
165 |
166 | .highlighted {
167 | background-color: #ddddff;
168 | }
169 |
170 | .defmodule {
171 | width: 100%;
172 | background-color: #F5F5DC;
173 | }
174 |
175 | .specgrammar {
176 | float: right;
177 | }
178 |
179 | .RBibliography td {
180 | vertical-align: text-top;
181 | }
182 |
183 | .leftindent {
184 | margin-left: 1em;
185 | margin-right: 0em;
186 | }
187 |
188 | .insetpara {
189 | margin-left: 1em;
190 | margin-right: 1em;
191 | }
192 |
193 | .Rfilebox {
194 | }
195 |
196 | .Rfiletitle {
197 | text-align: right;
198 | margin: 0em 0em 0em 0em;
199 | }
200 |
201 | .Rfilename {
202 | border-top: 1px solid #6C8585;
203 | border-right: 1px solid #6C8585;
204 | padding-left: 0.5em;
205 | padding-right: 0.5em;
206 | background-color: #ECF5F5;
207 | }
208 |
209 | .Rfilecontent {
210 | margin: 0em 0em 0em 0em;
211 | }
212 |
213 | .RpackageSpec {
214 | padding-right: 0.5em;
215 | }
216 |
217 | /* ---------------------------------------- */
218 | /* For background labels */
219 |
220 | .RBackgroundLabel {
221 | float: right;
222 | width: 0px;
223 | height: 0px;
224 | }
225 |
226 | .RBackgroundLabelInner {
227 | position: relative;
228 | width: 25em;
229 | left: -25.5em;
230 | top: 0px;
231 | text-align: right;
232 | color: white;
233 | z-index: 0;
234 | font-weight: bold;
235 | }
236 |
237 | .RForeground {
238 | position: relative;
239 | left: 0px;
240 | top: 0px;
241 | z-index: 1;
242 | }
243 |
244 | /* ---------------------------------------- */
245 | /* History */
246 |
247 | .SHistory {
248 | font-size: 82%;
249 | }
250 |
--------------------------------------------------------------------------------
/docs/scribble-common.js:
--------------------------------------------------------------------------------
1 | // Common functionality for PLT documentation pages
2 |
3 | // Page Parameters ------------------------------------------------------------
4 |
5 | var page_query_string = location.search.substring(1);
6 |
7 | var page_args =
8 | ((function(){
9 | if (!page_query_string) return [];
10 | var args = page_query_string.split(/[&;]/);
11 | for (var i=0; i= 0) args[i] = [a.substring(0,p), a.substring(p+1)];
15 | else args[i] = [a, false];
16 | }
17 | return args;
18 | })());
19 |
20 | function GetPageArg(key, def) {
21 | for (var i=0; i= 0 && cur.substring(0,eql) == key)
78 | return unescape(cur.substring(eql+1));
79 | }
80 | return def;
81 | }
82 | }
83 |
84 | function SetCookie(key, val) {
85 | try {
86 | localStorage[key] = val;
87 | } catch(e) {
88 | var d = new Date();
89 | d.setTime(d.getTime()+(365*24*60*60*1000));
90 | try {
91 | document.cookie =
92 | key + "=" + escape(val) + "; expires="+ d.toGMTString() + "; path=/";
93 | } catch (e) {}
94 | }
95 | }
96 |
97 | // note that this always stores a directory name, ending with a "/"
98 | function SetPLTRoot(ver, relative) {
99 | var root = location.protocol + "//" + location.host
100 | + NormalizePath(location.pathname.replace(/[^\/]*$/, relative));
101 | SetCookie("PLT_Root."+ver, root);
102 | }
103 |
104 | // adding index.html works because of the above
105 | function GotoPLTRoot(ver, relative) {
106 | var u = GetCookie("PLT_Root."+ver, null);
107 | if (u == null) return true; // no cookie: use plain up link
108 | // the relative path is optional, default goes to the toplevel start page
109 | if (!relative) relative = "index.html";
110 | location = u + relative;
111 | return false;
112 | }
113 |
114 | // Utilities ------------------------------------------------------------------
115 |
116 | var normalize_rxs = [/\/\/+/g, /\/\.(\/|$)/, /\/[^\/]*\/\.\.(\/|$)/];
117 | function NormalizePath(path) {
118 | var tmp, i;
119 | for (i = 0; i < normalize_rxs.length; i++)
120 | while ((tmp = path.replace(normalize_rxs[i], "/")) != path) path = tmp;
121 | return path;
122 | }
123 |
124 | // `noscript' is problematic in some browsers (always renders as a
125 | // block), use this hack instead (does not always work!)
126 | // document.write("");
127 |
128 | // Interactions ---------------------------------------------------------------
129 |
130 | function DoSearchKey(event, field, ver, top_path) {
131 | var val = field.value;
132 | if (event && event.keyCode == 13) {
133 | var u = GetCookie("PLT_Root."+ver, null);
134 | if (u == null) u = top_path; // default: go to the top path
135 | u += "search/index.html?q=" + encodeURIComponent(val);
136 | u = MergePageArgsIntoUrl(u);
137 | location = u;
138 | return false;
139 | }
140 | return true;
141 | }
142 |
143 | function TocviewToggle(glyph, id) {
144 | var s = document.getElementById(id).style;
145 | var expand = s.display == "none";
146 | s.display = expand ? "block" : "none";
147 | glyph.innerHTML = expand ? "▼" : "►";
148 | }
149 |
150 | // Page Init ------------------------------------------------------------------
151 |
152 | // Note: could make a function that inspects and uses window.onload to chain to
153 | // a previous one, but this file needs to be required first anyway, since it
154 | // contains utilities for all other files.
155 | var on_load_funcs = [];
156 | function AddOnLoad(fun) { on_load_funcs.push(fun); }
157 | window.onload = function() {
158 | for (var i=0; i
415 | .techinside doesn't work with IE, so use both (and IE doesn't
416 | work with inherit in the second one, so use blue directly) */
417 | .techinside { color: black; }
418 | .techinside:hover { color: blue; }
419 | .techoutside:hover>.techinside { color: inherit; }
420 |
421 | .SCentered {
422 | text-align: center;
423 | }
424 |
425 | .imageleft {
426 | float: left;
427 | margin-right: 0.3em;
428 | }
429 |
430 | .Smaller {
431 | font-size: 82%;
432 | }
433 |
434 | .Larger {
435 | font-size: 122%;
436 | }
437 |
438 | /* A hack, inserted to break some Scheme ids: */
439 | .mywbr {
440 | display: inline-block;
441 | height: 0;
442 | width: 0;
443 | font-size: 1px;
444 | }
445 |
446 | .compact li p {
447 | margin: 0em;
448 | padding: 0em;
449 | }
450 |
451 | .noborder img {
452 | border: 0;
453 | }
454 |
455 | .SVerbatim {
456 | white-space: nowrap;
457 | }
458 |
459 | .SAuthorListBox {
460 | position: relative;
461 | float: right;
462 | left: 2em;
463 | top: -2.5em;
464 | height: 0em;
465 | width: 13em;
466 | margin: 0em -13em 0em 0em;
467 | }
468 | .SAuthorList {
469 | font-size: 82%;
470 | }
471 | .SAuthorList:before {
472 | content: "by ";
473 | }
474 | .author {
475 | display: inline;
476 | white-space: nowrap;
477 | }
478 |
479 | /* print styles : hide the navigation elements */
480 | @media print {
481 | .tocset,
482 | .navsettop,
483 | .navsetbottom { display: none; }
484 | .maincolumn {
485 | width: auto;
486 | margin-right: 13em;
487 | margin-left: 0;
488 | }
489 | }
490 |
--------------------------------------------------------------------------------
/info.rkt:
--------------------------------------------------------------------------------
1 | #lang info
2 | (define collection "web-view")
3 | (define deps '("gui-lib"
4 | "base"))
5 | (define build-deps '("at-exp-lib"
6 | "gui-doc"
7 | "scribble-lib" "racket-doc" "rackunit-lib"))
8 | (define scribblings '(("scribblings/web-view.scrbl" ())))
9 | (define pkg-desc "A web-view control to be used with Racket GUI toolkit applications")
10 | (define version "0.1")
11 | (define pkg-authors '(agarzia))
12 |
--------------------------------------------------------------------------------
/main.rkt:
--------------------------------------------------------------------------------
1 | #lang racket/base
2 |
3 | (module+ test
4 | (require rackunit))
5 |
6 | ;; Notice
7 | ;; To install (from within the package directory):
8 | ;; $ raco pkg install
9 | ;; To install (once uploaded to pkgs.racket-lang.org):
10 | ;; $ raco pkg install <>
11 | ;; To uninstall:
12 | ;; $ raco pkg remove <>
13 | ;; To view documentation:
14 | ;; $ raco docs <>
15 | ;;
16 | ;; For your convenience, we have included LICENSE-MIT and LICENSE-APACHE files.
17 | ;; If you would prefer to use a different license, replace those files with the
18 | ;; desired license.
19 | ;;
20 | ;; Some users like to add a `private/` directory, place auxiliary files there,
21 | ;; and require them in `main.rkt`.
22 | ;;
23 | ;; See the current version of the racket style guide here:
24 | ;; http://docs.racket-lang.org/style/index.html
25 |
26 | ;; Code here
27 |
28 | (require "private/web-view.rkt")
29 |
30 | (provide web-view%)
31 |
32 |
33 | (module+ test
34 | ;; Any code in this `test` submodule runs when this file is run using DrRacket
35 | ;; or with `raco test`. The code here does not run when this file is
36 | ;; required by another module.
37 |
38 | )
39 |
40 | (module+ main
41 | ;; (Optional) main submodule. Put code here if you need it to be executed when
42 | ;; this file is run using DrRacket or the `racket` executable. The code here
43 | ;; does not run when this file is required by another module. Documentation:
44 | ;; http://docs.racket-lang.org/guide/Module_Syntax.html#%28part._main-and-test%29
45 |
46 | )
47 |
--------------------------------------------------------------------------------
/private/web-view.rkt:
--------------------------------------------------------------------------------
1 | #lang racket
2 |
3 | (require
4 | racket/class
5 | racket/gui
6 | "webkit.rkt"
7 | "wkwebview.rkt")
8 |
9 | (define web-view%
10 | (class panel%
11 | (init parent [on-status-change #f])
12 |
13 | (super-new [parent parent])
14 |
15 | (define current-operating-system (system-type 'os))
16 |
17 | (if (not (member current-operating-system (list 'macosx)))
18 | (error 'not-implemented "web-view% not implemented for ~a" current-operating-system)
19 | #t)
20 |
21 | (define webview
22 | (new wk-web-view%
23 | [parent this]
24 | [on-status-change on-status-change]))
25 |
26 | (define/public (get-debug-info)
27 | current-operating-system)
28 |
29 | (define/public (set-url url)
30 | (send webview set-url url))
31 |
32 | (define/override (on-size w h)
33 | (send webview on-size w h))
34 |
35 | (define/public (get-url)
36 | (send webview get-url))
37 |
38 | (define/public (can-handle-url? url)
39 | (send webview can-handle-url? url))
40 |
41 | (define/public (go-forward)
42 | (send webview go-forward))
43 |
44 | (define/public (go-back)
45 | (send webview go-back))
46 |
47 | (define/public (reload)
48 | (send webview reload))
49 |
50 | (define/public (set-html-text text base-url)
51 | (send webview set-html-text text base-url))
52 |
53 | ))
54 |
55 | (provide web-view%)
--------------------------------------------------------------------------------
/private/webkit.rkt:
--------------------------------------------------------------------------------
1 | #lang racket/gui
2 |
3 | ; This was my initial version. It is based on deprecated WebView from code found on:
4 | ; https://gist.github.com/nickmain/5136923
5 | ;
6 | ; I've switched to WKWebView. Check wkwebkit.rkt
7 |
8 | (require framework)
9 | (require ffi/unsafe)
10 | (require ffi/unsafe/objc)
11 | (require racket/class)
12 |
13 | (ffi-lib "/System/Library/Frameworks/WebKit.framework/WebKit")
14 | (import-class WebView)
15 | (import-class NSURLRequest)
16 | (import-class NSURL)
17 | (import-class NSString)
18 | (import-class NSObject)
19 |
20 |
21 | (define webkit-view%
22 | (class object%
23 | (super-new)
24 |
25 | (init parent)
26 |
27 | (define current-url #f)
28 |
29 | (define-objc-class MyWebFrameLoadDelegate NSObject
30 | []
31 | (- _void (webView: [_id wv] didFinishLoadForFrame: [_id wf])
32 | (print "page loaded")))
33 |
34 | (define-cstruct _NSPoint ([x _double*]
35 | [y _double*]))
36 |
37 | (define-cstruct _NSSize ([width _double*]
38 | [height _double*]))
39 |
40 | (define-cstruct _NSRect ([origin _NSPoint]
41 | [size _NSSize]))
42 |
43 |
44 | (define webview-x (send parent get-x))
45 | (define webview-y (send parent get-y))
46 | (define webview-width (send parent get-width))
47 | (define webview-height (send parent get-height))
48 |
49 | ;(print (format "creating webkit-view x:~a, y:~a, height:~a, width:~a ~%" webview-x webview-y webview-height webview-width))
50 |
51 | (define webview
52 | (tell (tell WebView alloc)
53 | initWithFrame: #:type _NSRect (make-NSRect (make-NSPoint webview-x webview-y) (make-NSSize webview-width webview-height))
54 | frameName: #f
55 | groupName: #f))
56 |
57 | (define client-view (send parent get-client-handle))
58 | (tell client-view addSubview: webview)
59 |
60 | (define (release id-ptr) (tell id-ptr release))
61 |
62 | (define main-frame
63 | (tell webview mainFrame))
64 |
65 | (define delegate
66 | (tell (tell MyWebFrameLoadDelegate alloc) init))
67 |
68 | (tell webview setFrameLoadDelegate: delegate)
69 |
70 | (define/public (get-url)
71 | current-url)
72 |
73 | (define/public (set-url given-url)
74 | (set! current-url given-url)
75 | (let* ([url-string (tell (tell NSString alloc)
76 | initWithUTF8String: #:type _string given-url)]
77 | [url (tell NSURL URLWithString: url-string)]
78 | [req (tell NSURLRequest requestWithURL: url)])
79 | (tell main-frame loadRequest: req)
80 | (release url-string)))
81 |
82 | (define/public (on-status-change status)
83 | (displayln (format "webkit-view status change: ~a" status)))
84 |
85 | ))
86 |
87 | (provide webkit-view%)
--------------------------------------------------------------------------------
/private/wkwebview.rkt:
--------------------------------------------------------------------------------
1 | #lang racket/gui
2 | (require framework)
3 | (require ffi/unsafe)
4 | (require ffi/unsafe/objc)
5 | (require ffi/unsafe/nsstring)
6 | (require racket/class)
7 |
8 | (ffi-lib "/System/Library/Frameworks/WebKit.framework/WebKit")
9 | (import-class WKWebView)
10 | (import-class WKWebViewConfiguration)
11 | (import-class NSURLRequest)
12 | (import-class NSURL)
13 | (import-class NSView)
14 | (import-class NSString)
15 | (import-class NSObject)
16 | (import-protocol WKNavigationDelegate)
17 |
18 |
19 | (define wk-web-view%
20 | (class object%
21 | (super-new)
22 |
23 | (init parent [on-status-change #f])
24 |
25 | (define-cstruct _NSPoint ([x _double*]
26 | [y _double*]))
27 |
28 | (define-cstruct _NSSize ([width _double*]
29 | [height _double*]))
30 |
31 | (define-cstruct _CGRect ([origin _NSPoint]
32 | [size _NSSize]))
33 |
34 | (define webview-x (send parent get-x))
35 |
36 | (define webview-y (send parent get-y))
37 |
38 | (define webview-width (send parent get-width))
39 |
40 | (define webview-height (send parent get-height))
41 |
42 | (define configuration
43 | (tell (tell WKWebViewConfiguration alloc) init))
44 |
45 | (define (release id-ptr) (tell id-ptr release))
46 |
47 | (define (make-rect)
48 | (make-CGRect (make-NSPoint webview-x webview-y) (make-NSSize webview-width webview-height)))
49 |
50 | (define webview
51 | (tell (tell WKWebView alloc)
52 | initWithFrame: #:type _CGRect (make-rect)
53 | configuration: configuration))
54 |
55 | (define-objc-class WebViewDelegate NSObject
56 | #:protocols (WKNavigationDelegate)
57 | []
58 | (- _void (webView: [_id view] didCommitNavigation: [_id navigation])
59 | (if (not (false? on-status-change)) (on-status-change "loading...") #f))
60 | (- _void (webView: [_id view] didFinishNavigation: [_id navigation])
61 | (if (not (false? on-status-change)) (on-status-change "page loaded" ) #f)))
62 |
63 | (define delegate
64 | (tell (tell WebViewDelegate alloc) init))
65 |
66 | (tell (send parent get-client-handle) addSubview: webview)
67 |
68 | (tellv webview setNavigationDelegate: delegate)
69 |
70 | (define/public (get-title)
71 | (tell #:type _NSString webview title))
72 |
73 | (define/public (get-url)
74 | (define url
75 | (tell webview URL))
76 | (tell #:type _NSString url absoluteString))
77 |
78 | (define/public (set-url given-url)
79 | (let* ([url-string (tell (tell NSString alloc)
80 | initWithUTF8String: #:type _string given-url)]
81 | [url (tell NSURL URLWithString: url-string)]
82 | [req (tell NSURLRequest requestWithURL: url)])
83 | (tell webview loadRequest: req)
84 | (release url-string)))
85 |
86 | (define/public (can-handle-url? given-url)
87 | (let* ([url-string (tell (tell NSString alloc)
88 | initWithUTF8String: #:type _string given-url)])
89 | (define ret (tell webview handlesURLScheme: url-string ))
90 | (release url-string)
91 | ret))
92 |
93 | (define/public (go-forward)
94 | (tell webview goForward))
95 |
96 | (define/public (go-back)
97 | (tell webview goBack))
98 |
99 | (define/public (reload)
100 | (tell webview reload))
101 |
102 | (define/public (set-html-text text base-url)
103 | (let* ([url-string (tell (tell NSString alloc)
104 | initWithUTF8String: #:type _string base-url)]
105 | [url (tell NSURL URLWithString: url-string)]
106 | [html (tell (tell NSString alloc)
107 | initWithUTF8String: #:type _string text)])
108 | (tell webview loadHTMLString: html baseURL: url)))
109 |
110 | (define/public (on-size w h)
111 | (tellv webview setFrame:
112 | #:type _CGRect (make-CGRect (make-NSPoint 0 0)
113 | (make-NSSize w h))))
114 |
115 | ))
116 |
117 | (provide wk-web-view%)
--------------------------------------------------------------------------------
/scribblings/web-view.scrbl:
--------------------------------------------------------------------------------
1 | #lang scribble/manual
2 | @require[@for-label[web-view
3 | racket/class
4 | racket/base
5 | racket/gui]]
6 |
7 | @title{A Racket GUI widget to display web pages}
8 | @author{Andre Alves Garzia}
9 |
10 | @defmodule[web-view]
11 |
12 | This module contains a Web View to be used with Racket GUI Toolkit. At the moment it works only with macOS because it wraps @hyperlink["https://developer.apple.com/documentation/webkit/wkwebview?language=objc"]{WKWebView} from WebKit.
13 |
14 | There is a @hyperlink["https://github.com/soapdog/racket-web-view/blob/master/demo/demo.rkt"]{Demo Browser available on the Github Repository}.
15 |
16 | @defclass[web-view% object% ()]{
17 |
18 | A widget to display web pages.
19 |
20 | @defconstructor[([parent (or/c (is-a?/c frame%)
21 | (is-a?/c dialog%)
22 | (is-a?/c panel%)
23 | (is-a?/c pane%))]
24 | [on-status-change ((is-a?/c button%) (is-a?/c control-event%) . -> . any) (lambda (b e) (void))])]{
25 |
26 | Construct a new widget.
27 |
28 | The @racket[on-status-change] procedure is used to receive navigation events from the web view.
29 |
30 | }
31 |
32 | @defmethod*[([(set-url [url string?]) any/c])]{
33 |
34 | Set the URL for the web view.
35 |
36 | }
37 |
38 | @defmethod*[([(get-url) string?])]{
39 |
40 | Get the current URL loaded in the web view.
41 |
42 | }
43 |
44 |
45 | @defmethod*[([(go-forward) any/c])]{
46 |
47 | Navigates forward.
48 |
49 | }
50 |
51 |
52 | @defmethod*[([(go-back) any/c])]{
53 |
54 | Navigates backward.
55 |
56 | }
57 |
58 |
59 | @defmethod*[([(reload) any/c])]{
60 |
61 | Reloads the current page.
62 |
63 | }
64 |
65 | @defmethod*[([(set-html-text [text string?] [base-url string?]) any/c])]{
66 |
67 | Sets the HTML text being used by the web view. Any relative url will be relative to the specified base url.
68 |
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------