diff --git a/compiler/builtins/docs/Bool.roc b/compiler/builtins/docs/Bool.roc index 5a4e4814df..077909e84d 100644 --- a/compiler/builtins/docs/Bool.roc +++ b/compiler/builtins/docs/Bool.roc @@ -55,12 +55,14 @@ and : Bool, Bool -> Bool ## ## In some languages, `&&` and `||` are special-cased in the compiler to skip ## evaluating the expression after the operator under certain circumstances. -## # In Roc, this is not the case. See the performance notes for #Bool.and for details. +## # In Roc, this is not the case. See the performance notes for [Bool.and] for details. or : Bool, Bool -> Bool ## Exclusive or xor : Bool, Bool -> Bool +# TODO: removed `'` from signature because parser does not support it yet +# Original signature: `isEq : 'val, 'val -> Bool` ## Returns `True` if the two values are *structurally equal*, and `False` otherwise. ## ## `a == b` is shorthand for `Bool.isEq a b` @@ -71,20 +73,18 @@ xor : Bool, Bool -> Bool ## 2. Private tags are equal if they are the same tag, in the same module, and also their contents (if any) are equal. ## 3. Records are equal if all their fields are equal. ## 4. Collections ([Str], [List], [Dict], and [Set]) are equal if they are the same length, and also all their corresponding elements are equal. -## 5. #Num values are equal if their numbers are equal, with one exception: if both arguments to `isEq` are *NaN*, then `isEq` returns `False`. See [Num.isNaN] for more about *NaN*. +## 5. [Num] values are equal if their numbers are equal, with one exception: if both arguments to `isEq` are *NaN*, then `isEq` returns `False`. See [Num.isNaN] for more about *NaN*. ## ## Note that `isEq` takes `'val` instead of `val`, which means `isEq` does not ## accept arguments whose types contain functions. -# TODO: removed `'` from signature because parser does not support it yet -# Original signature: `isEq : 'val, 'val -> Bool` isEq : val, val -> Bool -## Calls #eq on the given values, then calls #not on the result. +# TODO: removed `'` from signature because parser does not support it yet +# Original signature: `isNotEq : 'val, 'val -> Bool` +## Calls [isEq] on the given values, then calls [not] on the result. ## ## `a != b` is shorthand for `Bool.isNotEq a b` ## ## Note that `isNotEq` takes `'val` instead of `val`, which means `isNotEq` does not ## accept arguments whose types contain functions. -# TODO: removed `'` from signature because parser does not support it yet -# Original signature: `isNotEq : 'val, 'val -> Bool` isNotEq : val, val -> Bool diff --git a/www/build.sh b/www/build.sh new file mode 100755 index 0000000000..ffdae71a9b --- /dev/null +++ b/www/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +rm -rf build/ +cp -r public/ build/ diff --git a/www/netlify.toml b/www/netlify.toml new file mode 100644 index 0000000000..0e3070a0f6 --- /dev/null +++ b/www/netlify.toml @@ -0,0 +1,30 @@ +# This is the file that generates and deploys https://www.roc-lang.org, +# which is served on Netlify. +# +# Netlify's docs for how this configuration file works: +# https://docs.netlify.com/routing/headers/#syntax-for-the-netlify-configuration-file +[build] + publish = "build/" + command = "bash build.sh" + +[[headers]] + for = "/*" + [headers.values] + X-Frame-Options = "DENY" + X-XSS-Protection = "1; mode=block" + Content-Security-Policy = "default-src 'self'; img-src *;" + X-Content-Type-Options = "nosniff" + +# Redirect roc-lang.org/authors to the AUTHORS file in this repo +# +# This is referenced in the LICENSE file, which says to see roc-lang.org/authors +# for a list of authors! +[[redirects]] + from = "/authors" + to = "https://github.com/rtfeldman/roc/blob/trunk/AUTHORS" + force = true + status = 302 # TODO once the repo is public, use status = 200 and this URL: + # https://raw.githubusercontent.com/rtfeldman/roc/trunk/AUTHORS + # + # This way, roc-lang.org/authors will show the authors directly, + # proxied from the current AUTHORS file on GitHub, no redirects. diff --git a/www/public/favicon.svg b/www/public/favicon.svg new file mode 100644 index 0000000000..e0cff74b57 --- /dev/null +++ b/www/public/favicon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/www/public/index.html b/www/public/index.html new file mode 100644 index 0000000000..442e9d266f --- /dev/null +++ b/www/public/index.html @@ -0,0 +1,23 @@ + + + + + + + The Roc Programming Language + + + + + + + +

Work in Progress

+

Roc's initial release is still under development, and this website is a placeholder until that release is ready.

+

In the meantime, if you'd like to learn more about Roc, here are some videos:

+ + + diff --git a/www/public/license/index.html b/www/public/license/index.html new file mode 100644 index 0000000000..4eea2d8c39 --- /dev/null +++ b/www/public/license/index.html @@ -0,0 +1,29 @@ + + + + + + Roc's license: The Universal Permissive License (UPL), Version 1.0 + + + + + +
Copyright (c) 2019 Richard Feldman and subsequent Roc authors <https://roc-lang.org/authors>
+
+The Universal Permissive License (UPL), Version 1.0
+
+Subject to the condition set forth below, permission is hereby granted to any person obtaining a copy of this software, associated documentation and/or data (collectively the "Software"), free of charge and under any and all copyright rights in the Software, and any and all patent rights owned or freely licensable by each licensor hereunder covering either (i) the unmodified Software as contributed to or provided by such licensor, or (ii) the Larger Works (as defined below), to deal in both
+
+(a) the Software, and
+
+(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with the Software (each a “Larger Work” to which the Software is contributed by such licensors),
+
+without restriction, including without limitation the rights to copy, create derivative works of, display, perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, and have sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either these or other terms.
+
+This license is subject to the following condition:
+
+The above copyright notice and either this complete permission notice or at a minimum a reference to the UPL must be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ diff --git a/www/public/logo.svg b/www/public/logo.svg new file mode 100644 index 0000000000..bb673d5013 --- /dev/null +++ b/www/public/logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/www/public/search.js b/www/public/search.js new file mode 100644 index 0000000000..0bc719563b --- /dev/null +++ b/www/public/search.js @@ -0,0 +1,38 @@ +(function() { + let sidebar = document.getElementById("sidebar-nav"); + let searchBox = document.getElementById("module-search"); + + function search() { + let text = searchBox.value.toLowerCase(); // Search is case-insensitive. + + if (text === "") { + // Un-hide everything + sidebar.querySelectorAll(".sidebar-entry a").forEach((entry) => entry.classList.remove("hidden")); + + // Re-hide all the sub-entries except for those of the first module + sidebar.querySelectorAll(".sidebar-entry:not(:first-of-type) .sidebar-sub-entries a").forEach((entry) => entry.classList.add("hidden")); + } else { + // First, show/hide all the sub-entries within each module (top-level functions etc.) + sidebar.querySelectorAll(".sidebar-sub-entries a").forEach((entry) => { + if (entry.textContent.toLowerCase().includes(text)) { + entry.classList.remove("hidden"); + } else { + entry.classList.add("hidden"); + } + }); + + // Then, show/hide modules based on whether they match, or any of their sub-entries matched + sidebar.querySelectorAll(".sidebar-module-link").forEach((entry) => { + if (entry.textContent.toLowerCase().includes(text) || entry.parentNode.querySelectorAll(".sidebar-sub-entries a:not(.hidden)").length > 0) { + entry.classList.remove("hidden"); + } else { + entry.classList.add("hidden"); + } + }); + } + } + + searchBox.addEventListener("input", search); + + search(); +})(); diff --git a/www/public/styles.css b/www/public/styles.css new file mode 100644 index 0000000000..27f88aacd1 --- /dev/null +++ b/www/public/styles.css @@ -0,0 +1,479 @@ +:root { + --link-color: #612bde; + --code-link-color: #5721d4; + --text-color: #333333; + --code-color: #222222; + --code-bg-color: #eeeeee; + --body-bg-color: #fdfdfd; + --border-color: #e9e9e9; + --faded-color: #4c4c4c; + --monospace-font; + --font-sans: -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif; + --font-mono: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; + --top-header-height: 67px; + --sidebar-width: 280px; + --top-bar-bg: #8257e5; + --top-bar-fg: #ffffff; + --nav-link-hover-color: #000000; +} + +a { + color: #972395; +} + +.logo { + padding: 2px 8px; +} + +.logo svg { + height: 48px; + width: 48px; + fill: var(--top-bar-fg); +} + +.logo:hover { + text-decoration: none; +} + +.logo svg:hover { + fill: var(--nav-link-hover-color); +} + +.pkg-full-name { + color: var(--text-color); + display: flex; + align-items: center; + font-size: 32px; + margin: 0 8px; + font-weight: normal; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + height: 100%; +} + +.pkg-full-name a { + padding-top: 12px; + padding-bottom: 16px; +} + +a { + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +.pkg-and-logo { + min-width: 0; /* necessary for text-overflow: ellipsis to work in descendants */ + display: flex; + align-items: center; + height: 100%; + background-color: var(--top-bar-bg); +} + +.pkg-and-logo a, .pkg-and-logo a:visited { + color: var(--top-bar-fg); +} + +.pkg-and-logo a:hover { + color: var(--nav-link-hover-color); + text-decoration: none; +} + +.main-container { + min-width: 0; /* necessary for text-overflow: ellipsis to work in descendants */ +} + +.search-button { + flex-shrink: 0; /* always shrink the package name before these; they have a relatively constrained length */ + padding: 12px 18px; + margin-right: 42px; + display: none; /* only show this in the mobile view */ +} + +.version { + padding: 18px 10px; + min-width: 48px; + margin-right: 8px; +} + +body { + display: grid; + grid-template-columns: [before-sidebar] 1fr [sidebar] var(--sidebar-width) [main-content] fit-content(calc(1280px - var(--sidebar-width))) [end] 1fr; + grid-template-rows: [top-header] var(--top-header-height) [above-footer] auto [footer] auto; + box-sizing: border-box; + margin: 0; + padding: 0; + font-family: var(--font-sans); + color: var(--text-color); + background-color: var(--body-bg-color); +} + +main { + grid-column-start: main-content; + grid-column-end: main-content; + grid-row-start: above-footer; + grid-row-end: above-footer; + box-sizing: border-box; + position: relative; + font-size: 18px; + line-height: 1.85em; + margin-top: 2px; + padding: 48px; +} + +#sidebar-nav { + grid-column-start: sidebar; + grid-column-end: sidebar; + grid-row-start: above-footer; + grid-row-end: above-footer; + position: relative; + display: flex; + flex-direction: column; + box-sizing: border-box; + padding-left: 56px; + padding-top: 6px; + width: 100%; +} + +.top-header-extension { + grid-column-start: before-sidebar; + grid-column-end: sidebar; + grid-row-start: top-header; + grid-row-end: top-header; + background-color: var(--top-bar-bg); +} + +.top-header { + grid-column-start: sidebar; + grid-column-end: end; + grid-row-start: top-header; + grid-row-end: top-header; + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: nowrap; + flex-grow: 1; + box-sizing: border-box; + font-family: var(--font-sans); + font-size: 24px; + height: 100%; + min-width: 0; /* necessary for text-overflow: ellipsis to work in descendants */ +} + +.top-header-triangle { + /* This used to be a clip-path, but Firefox on Android (at least as of early 2020) + * rendered the page extremely slowly in that version. With this approach it's super fast. + */ + width: 0; + height: 0; + border-style: solid; + border-width: var(--top-header-height) 0 0 48px; + border-color: transparent transparent transparent var(--top-bar-bg); +} + +p { + overflow-wrap: break-word; + margin: 24px 0; +} + +footer { + grid-column-start: main-content; + grid-column-end: main-content; + grid-row-start: footer; + grid-row-end: footer; + max-width: var(--main-content-max-width); + font-size: 14px; + box-sizing: border-box; + padding: 16px; +} + +footer p { + display: inline-block; + margin-top: 0; + margin-bottom: 8px; +} + +.content { + box-sizing: border-box; + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.sidebar-entry ul { + list-style-type: none; + margin: 0; +} + +.sidebar-entry a { + box-sizing: border-box; + min-height: 48px; + min-width: 48px; + padding: 12px 16px; + font-family: var(--font-mono); +} + +.sidebar-sub-entries a { + display: block; + line-height: 24px; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + padding-left: 36px; +} + +.module-name { + font-size: 56px; + line-height: 1em; + font-family: var(--font-mono); + font-weight: bold; + margin-top: 18px; + margin-bottom: 48px; +} + +.module-name a, .module-name a:visited { + color: inherit; +} + +.sidebar-module-link { + box-sizing: border-box; + font-size: 18px; + line-height: 24px; + font-family: var(--font-mono); + font-weight: bold; + display: block; + width: 100%; + padding: 8px 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +a, a:visited { + color: var(--link-color); +} + +h3 { + font-size: 32px; + margin: 48px 0 24px 0; +} + +h4 { + font-size: 24px; +} + +.type-def { + font-size: 24px; + color: var(--link-color); +} + +.code-snippet { + padding: 12px 16px; + display: block; + box-sizing: border-box; + font-family: var(--font-mono); + background-color: var(--code-bg-color); +} + +code { + font-family: var(--font-mono); + color: var(--code-color); + background-color: var(--code-bg-color); + padding: 2px 8px; + display: inline-block; +} + +code a { + color: var(--code-link-color); +} + +code a:visited { + color: var(--code-link-color); +} + +pre { + margin: 36px 0; + padding: 8px; + box-sizing: border-box; + background-color: var(--code-bg-color); + overflow-x: auto; +} + +pre code { + padding: 6px 8px; +} + +.hidden { + /* Use !important to win all specificity fights. */ + display: none !important; +} + +#module-search:placeholder-shown { + padding: 0; + opacity: 0; + height: 0; +} + +#module-search, #module-search:focus { + opacity: 1; + padding: 12px 16px; + height: 48px; +} + +/* Show the "Search" label link when the text input has a placeholder */ +#module-search:placeholder-shown + #search-link { + display: flex; +} + +/* Hide the "Search" label link when the text input has focus */ +#module-search:focus + #search-link { + display: none; +} + +#module-search { + display: block; + box-sizing: border-box; + background-color: var(--code-bg-color); + width: 100%; + box-sizing: border-box; + font-size: 18px; + line-height: 18px; + margin-top: 6px; + border: none; + color: var(--faded-color); + background-color: var(--code-bg-color); + font-family: var(--font-serif); +} + +#module-search::placeholder { + color: var(--faded-color); + opacity: 1; +} + +#search-link { + box-sizing: border-box; + display: none; + align-items: center; + font-size: 18px; + line-height: 18px; + padding: 12px 16px; + height: 48px; + cursor: pointer; + color: var(--link-color); +} + +#search-link:hover { + text-decoration: underline; +} + +@media (prefers-color-scheme: dark) { + :root { + --body-bg-color: #303030; + --code-bg-color: #393939; + --border-color: #555555; + --code-color: #eeeeee; + --text-color: #cccccc; + --logo-solid: #777777; + --faded-color: #bbbbbb; + --link-color: #c5a8ff; + --code-link-color: #b894ff; + --top-bar-bg: #6845b9; + --top-bar-fg: #eeeeee; + } + + html { + scrollbar-color: #444444 #2f2f2f; + } +} + +@media only screen and (max-device-width: 480px) { + .search-button { + display: block; /* This is only visible in mobile. */ + } + + .top-header { + width: auto; + } + + .pkg-full-name { + margin-left: 8px; + margin-right: 12px; + font-size: 24px; + padding-bottom: 14px; + } + + .pkg-full-name a { + vertical-align: middle; + padding: 18px 0; + } + + .logo { + padding-left: 2px; + width: 50px; + height: 54px; + } + + .version { + margin: 0; + font-weight: normal; + font-size: 18px; + padding-bottom: 16px; + } + + .module-name { + font-size: 36px; + margin-top: 8px; + margin-bottom: 8px; + max-width: calc(100% - 18px); + overflow: hidden; + text-overflow: ellipsis; + } + + main { + padding: 18px; + font-size: 16px; + } + + .container { + margin: 0; + min-width: 320px; + max-width: 100%; + } + + .content { + flex-direction: column; + } + + .sidebar { + margin-top: 0; + padding-left: 0; + width: auto; + } + + #sidebar-heading { + font-size: 24px; + margin: 16px; + } + + h3 { + font-size: 18px; + margin: 0; + padding: 0; + } + + h4 { + font-size: 16px; + } + + .top-header { + justify-content: space-between; + } + + .content { + /* Display the sidebar below
without affecting tab index */ + flex-direction: column-reverse; + } +}