mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
Reproduce roc check
bug
To repro: run `roc check` in www/wip_new_website/
This commit is contained in:
parent
563713b4b8
commit
34ef8436b5
4 changed files with 332 additions and 13 deletions
|
@ -3,5 +3,105 @@ app "helloWorld"
|
||||||
imports [pf.Stdout]
|
imports [pf.Stdout]
|
||||||
provides [main] to pf
|
provides [main] to pf
|
||||||
|
|
||||||
|
Section : [Desc (List Token) Str, Indent, Outdent, Newline]
|
||||||
|
Token : [Kw Str, Ident Str, Str Str, Num Str]
|
||||||
|
|
||||||
main =
|
main =
|
||||||
Stdout.line "Hello, World!"
|
output =
|
||||||
|
# subject = "Awesome Programmer"
|
||||||
|
#
|
||||||
|
# helloWorld =
|
||||||
|
# Str.withCapacity 45
|
||||||
|
# |> Str.concat greeting
|
||||||
|
# |> Str.concat ", "
|
||||||
|
# |> Str.concat subject
|
||||||
|
# |> Str.concat "!"
|
||||||
|
sectionsToStr [
|
||||||
|
Desc [Ident "subject", Kw "=", Str "Awesome Programmer"] "<p>This assigns the name <code class=\"ident\">subject</code> to the string \"Awesome programmer\".</p><p>In Roc, assignments are always constant, which means writing <code class=\"ident\">subject =</code> again in the same scope would give an error.</p><p><a href=\"https://www.roc-lang.org/tutorial#naming-things\">Learn more about naming things</a></p>",
|
||||||
|
Newline,
|
||||||
|
Newline,
|
||||||
|
Desc [Ident "helloWorld", Kw "="] "<p>This assigns the name <code class=\"ident\">helloWorld</code> to the value returned by this chain of function calls.</p><p>In Roc, assignments are always constant, which means writing <code class=\"ident\">helloWorld =</code> again in the same scope would give an error.</p><p><a href=\"https://www.roc-lang.org/tutorial#naming-things\">Learn more about naming things</a></p>",
|
||||||
|
Indent,
|
||||||
|
Desc [Ident "Str.withCapacity", Num "45"] "<p>This calls the <a href=\"https://www.roc-lang.org/builtins/Str#withCapacity\"><code class=\"ident\">Str.withCapacity</code> function</a> passing <code class=\"ident\">45</code> as its argument.</p><p>This creates a new string with capacity for 45 bytes without needing to allocate more space.</p>",
|
||||||
|
Newline,
|
||||||
|
Desc [Kw "|>", Ident "Str.concat", Ident "greeting"] "<p>This calls the <a href=\"https://www.roc-lang.org/builtins/Str#concat\"><code class=\"ident\">Str.concat</code> function</a> passing <code class=\"ident\">greeting</code> as its second argument, and the output of the pipeline up to this point as its first argument.</p>",
|
||||||
|
]
|
||||||
|
|
||||||
|
Stdout.line output
|
||||||
|
|
||||||
|
tokensToStr : List Token -> Str
|
||||||
|
tokensToStr = \tokens ->
|
||||||
|
List.walk tokens "" \buf, token ->
|
||||||
|
bufWithSpace =
|
||||||
|
if Str.isEmpty buf then
|
||||||
|
buf
|
||||||
|
else
|
||||||
|
Str.concat buf " "
|
||||||
|
|
||||||
|
when token is
|
||||||
|
Kw str ->
|
||||||
|
Str.concat bufWithSpace "<span class=\"kw\">\(str)</span>"
|
||||||
|
|
||||||
|
Num str ->
|
||||||
|
Str.concat bufWithSpace "<span class=\"literal\">\(str)</span>"
|
||||||
|
|
||||||
|
Str str ->
|
||||||
|
Str.concat bufWithSpace "<span class=\"literal\">\"\(str)\"</span>"
|
||||||
|
|
||||||
|
Ident str ->
|
||||||
|
html =
|
||||||
|
List.walk (Str.split str ".") "" \accum, ident ->
|
||||||
|
identHtml = "<span class=\"ident\">\(ident)</span>"
|
||||||
|
|
||||||
|
if Str.isEmpty accum then
|
||||||
|
identHtml
|
||||||
|
else
|
||||||
|
"\(accum)<span class=\"kw\">.</span>\(identHtml)"
|
||||||
|
|
||||||
|
Str.concat bufWithSpace html
|
||||||
|
|
||||||
|
sectionsToStr : List Section -> Str
|
||||||
|
sectionsToStr = \sections ->
|
||||||
|
answer = List.walk sections { buf: "", count: 0, indent: 0 } \{ buf, count, indent }, section ->
|
||||||
|
bufWithSpace =
|
||||||
|
if Str.isEmpty buf then
|
||||||
|
buf
|
||||||
|
else if buf |> Str.endsWith "\n" then
|
||||||
|
Str.concat buf (Str.repeat " " indent)
|
||||||
|
else
|
||||||
|
Str.concat buf " "
|
||||||
|
|
||||||
|
(afterSpaces, nextCount) =
|
||||||
|
when section is
|
||||||
|
Newline | Indent | Outdent ->
|
||||||
|
# Indent and outdent changes happen on the next iteration,
|
||||||
|
# so we only need a newline for them here.
|
||||||
|
(Str.concat buf "\n", count)
|
||||||
|
|
||||||
|
Desc tokens str ->
|
||||||
|
html = radio count (tokensToStr tokens) str
|
||||||
|
|
||||||
|
(Str.concat bufWithSpace html, count + 1)
|
||||||
|
|
||||||
|
nextIndent =
|
||||||
|
when section is
|
||||||
|
Indent -> indent + 4
|
||||||
|
Outdent -> indent - 4
|
||||||
|
Newline | Desc _ _ -> indent
|
||||||
|
|
||||||
|
{
|
||||||
|
buf: afterSpaces,
|
||||||
|
count: nextCount,
|
||||||
|
indent: nextIndent
|
||||||
|
}
|
||||||
|
|
||||||
|
answer.buf
|
||||||
|
|
||||||
|
radio : U16, Str, Str -> Str
|
||||||
|
radio = \index, labelHtml, descHtml ->
|
||||||
|
# The first radio button should always be checked, and none of the others should be.
|
||||||
|
checkedHtml = if index == 0 then " checked" else ""
|
||||||
|
|
||||||
|
"""
|
||||||
|
<input class="interactive-radio" type="radio" name="r" id="r\(Num.toStr index)" autocomplete=\"off\"\(checkedHtml)><label for="r\(Num.toStr index)" title="Tap to learn about this syntax">\(labelHtml)</label><div class="interactive-desc">\(descHtml)</div>
|
||||||
|
"""
|
||||||
|
|
151
www/wip_new_website/InteractiveExample.roc
Normal file
151
www/wip_new_website/InteractiveExample.roc
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
interface InteractiveExample
|
||||||
|
exposes [view]
|
||||||
|
imports [pf.Html.{ pre, samp }, pf.Html.Attributes.{ class }]
|
||||||
|
|
||||||
|
Section : [Desc (List Token) Str, Indent, Outdent, Newline]
|
||||||
|
Token : [Kw Str, Ident Str, Str Str, Num Str, Comment Str, ParensAround (List Token), Lambda (List Token)]
|
||||||
|
|
||||||
|
view : Html.Node
|
||||||
|
view =
|
||||||
|
output =
|
||||||
|
# # Select anything here to see an explanation.
|
||||||
|
# main =
|
||||||
|
# cacheUserInfo (Path.fromStr "url.txt")
|
||||||
|
# |> Task.onErr handleErr
|
||||||
|
#
|
||||||
|
# cacheUserInfo = \filename ->
|
||||||
|
# url <- File.readUtf8 filename |> Task.await
|
||||||
|
# { username, email } <- Http.get url Json.codec |> Task.await
|
||||||
|
#
|
||||||
|
# File.writeUtf8 (Path.fromStr "\(username).txt") email
|
||||||
|
#
|
||||||
|
# handleUrl = \err ->
|
||||||
|
# when err is
|
||||||
|
# HttpErr url _ -> Stderr.line "Error fetching URL \(url)"
|
||||||
|
# FileReadErr path _ -> Stderr.line "Error reading \(Path.display path)"
|
||||||
|
# FileWriteErr path _ -> Stderr.line "Error writing \(Path.display path)"
|
||||||
|
sectionsToStr [
|
||||||
|
Desc [Comment "<span class='desktop'>Click anything here to see an explanation.</span><span class='mobile'>Tap anything here to\n# see an explanation.</span>"] "<p>Comments in Roc begin with a <code>#</code> and go to the end of the line.</p>",
|
||||||
|
Newline,
|
||||||
|
Desc [Ident "main", Kw "="] "<p>This begins the definition of <code class=\"ident\">main</code>, which is the code our program will run when it starts up.</p><p>In Roc, assignments are always constant, which means writing <code class=\"ident\">main =</code> again in the same scope would give an error.</p><p><a href=\"https://www.roc-lang.org/tutorial#naming-things\">Learn more about naming things</a></p>",
|
||||||
|
Indent,
|
||||||
|
Desc [Ident "cacheUserInfo", Str "\"url.txt\""] "<p>This calls the <code class=\"ident\">cacheUserInfo</code> function, passing the string <code class=\"str\">\"url.txt\"</code> as an argument.</p><p>In Roc, function arguments are separated with spaces and/or newlines. Parentheses are only used in nested function calls.</p>",
|
||||||
|
Newline,
|
||||||
|
Desc [Kw "|>", Ident "Task.onErr", Ident "handleErr"] "<p>TODO</p>",
|
||||||
|
Outdent,
|
||||||
|
Newline,
|
||||||
|
# Desc [Ident "cacheUserInfo", Kw "=", Lambda [Ident "filename"]] "<p>TODO</p>",
|
||||||
|
# Indent,
|
||||||
|
# Desc [Ident "url", Kw "<-", Ident "File.readUtf8", Ident "filename"] "<p>TODO backpassing</p>",
|
||||||
|
# Desc [Kw "|>", Ident "Task.await"] "<p>TODO Task.await</p>",
|
||||||
|
# Newline,
|
||||||
|
# Desc [Literal "{", Ident "username", Literal ",", Ident "email", Literal "}", Kw "<-"] "<p>TODO record destructuring and backpassing</p>",
|
||||||
|
]
|
||||||
|
|
||||||
|
pre [] [
|
||||||
|
samp [class "interactive-example"] [
|
||||||
|
Html.text output,
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
tokensToStr : List Token -> Str
|
||||||
|
tokensToStr = \tokens ->
|
||||||
|
List.walk tokens "" tokenToStr
|
||||||
|
|
||||||
|
tokenToStr : Str, Token -> Str
|
||||||
|
tokenToStr = \buf, token ->
|
||||||
|
bufWithSpace =
|
||||||
|
if Str.isEmpty buf then
|
||||||
|
buf
|
||||||
|
else
|
||||||
|
Str.concat buf " "
|
||||||
|
|
||||||
|
when token is
|
||||||
|
ParensAround wrapped ->
|
||||||
|
# Don't put spaces after opening parens or before closing parens
|
||||||
|
bufWithSpace
|
||||||
|
|> Str.concat "<span class=\"kw\">(</span>"
|
||||||
|
|> Str.concat (tokensToStr wrapped)
|
||||||
|
|> Str.concat "<span class=\"kw\">)</span>"
|
||||||
|
|
||||||
|
Lambda args ->
|
||||||
|
# Don't put spaces after opening parens or before closing parens
|
||||||
|
argsWithCommas =
|
||||||
|
args
|
||||||
|
|> List.map \t -> tokenToStr "" t
|
||||||
|
|> Str.joinWith "<span class=\"literal\">,</span> "
|
||||||
|
|
||||||
|
bufWithSpace
|
||||||
|
|> Str.concat "<span class=\"kw\">\\</span>"
|
||||||
|
|> Str.concat argsWithCommas
|
||||||
|
|> Str.concat "<span class=\"kw\"> -></span>"
|
||||||
|
|
||||||
|
Kw str ->
|
||||||
|
Str.concat bufWithSpace "<span class=\"kw\">\(str)</span>"
|
||||||
|
|
||||||
|
Num str ->
|
||||||
|
Str.concat bufWithSpace "<span class=\"literal\">\(str)</span>"
|
||||||
|
|
||||||
|
Str str ->
|
||||||
|
Str.concat bufWithSpace "<span class=\"literal\">\(str)</span>"
|
||||||
|
|
||||||
|
Comment str ->
|
||||||
|
Str.concat bufWithSpace "<span class=\"comment\"># \(str)</span>"
|
||||||
|
|
||||||
|
Ident str ->
|
||||||
|
html =
|
||||||
|
List.walk (Str.split str ".") "" \accum, ident ->
|
||||||
|
identHtml = "<span class=\"ident\">\(ident)</span>"
|
||||||
|
|
||||||
|
if Str.isEmpty accum then
|
||||||
|
identHtml
|
||||||
|
else
|
||||||
|
"\(accum)<span class=\"kw\">.</span>\(identHtml)"
|
||||||
|
|
||||||
|
Str.concat bufWithSpace html
|
||||||
|
|
||||||
|
sectionsToStr : List Section -> Str
|
||||||
|
sectionsToStr = \sections ->
|
||||||
|
answer = List.walk sections { buf: "", count: 0, indent: 0 } \{ buf, count, indent }, section ->
|
||||||
|
bufWithSpace =
|
||||||
|
if Str.isEmpty buf then
|
||||||
|
buf
|
||||||
|
else if buf |> Str.endsWith "\n" then
|
||||||
|
Str.concat buf (Str.repeat " " indent)
|
||||||
|
else
|
||||||
|
Str.concat buf " "
|
||||||
|
|
||||||
|
(afterSpaces, nextCount) =
|
||||||
|
when section is
|
||||||
|
Newline | Indent | Outdent ->
|
||||||
|
# Indent and outdent changes happen on the next iteration,
|
||||||
|
# so we only need a newline for them here.
|
||||||
|
(Str.concat buf "\n", count)
|
||||||
|
|
||||||
|
Desc tokens str ->
|
||||||
|
html = radio count (tokensToStr tokens) str
|
||||||
|
|
||||||
|
(Str.concat bufWithSpace html, count + 1)
|
||||||
|
|
||||||
|
nextIndent =
|
||||||
|
when section is
|
||||||
|
Indent -> indent + 4
|
||||||
|
Outdent -> indent - 4
|
||||||
|
Newline | Desc _ _ -> indent
|
||||||
|
|
||||||
|
{
|
||||||
|
buf: afterSpaces,
|
||||||
|
count: nextCount,
|
||||||
|
indent: nextIndent,
|
||||||
|
}
|
||||||
|
|
||||||
|
answer.buf
|
||||||
|
|
||||||
|
radio : U16, Str, Str -> Str
|
||||||
|
radio = \index, labelHtml, descHtml ->
|
||||||
|
# The first radio button should always be checked, and none of the others should be.
|
||||||
|
checkedHtml = if index == 0 then " checked" else ""
|
||||||
|
|
||||||
|
"""
|
||||||
|
<input class="interactive-radio" type="radio" name="r" id="r\(Num.toStr index)" autocomplete=\"off\"\(checkedHtml)><label for="r\(Num.toStr index)" title="Tap to learn about this syntax">\(labelHtml)</label><div class="interactive-desc">\(descHtml)</div>
|
||||||
|
"""
|
|
@ -3,6 +3,7 @@ app "roc-website"
|
||||||
imports [
|
imports [
|
||||||
pf.Html.{ html, head, body, footer, div, main, text, nav, a, link, meta },
|
pf.Html.{ html, head, body, footer, div, main, text, nav, a, link, meta },
|
||||||
pf.Html.Attributes.{ content, name, id, href, rel, lang, class, title, charset, color },
|
pf.Html.Attributes.{ content, name, id, href, rel, lang, class, title, charset, color },
|
||||||
|
InteractiveExample,
|
||||||
]
|
]
|
||||||
provides [transformFileContent] to pf
|
provides [transformFileContent] to pf
|
||||||
|
|
||||||
|
@ -35,6 +36,12 @@ transformFileContent = \page, htmlContent ->
|
||||||
|
|
||||||
view : Str, Str -> Html.Node
|
view : Str, Str -> Html.Node
|
||||||
view = \page, htmlContent ->
|
view = \page, htmlContent ->
|
||||||
|
mainBody =
|
||||||
|
if page == "index.html" then
|
||||||
|
[text htmlContent, InteractiveExample.view]
|
||||||
|
else
|
||||||
|
[text htmlContent]
|
||||||
|
|
||||||
html [lang "en"] [
|
html [lang "en"] [
|
||||||
head [] [
|
head [] [
|
||||||
meta [charset "utf-8"] [],
|
meta [charset "utf-8"] [],
|
||||||
|
@ -50,15 +57,13 @@ view = \page, htmlContent ->
|
||||||
],
|
],
|
||||||
body [] [
|
body [] [
|
||||||
viewNavbar page,
|
viewNavbar page,
|
||||||
main [] [
|
main [] mainBody,
|
||||||
text htmlContent,
|
|
||||||
],
|
|
||||||
footer [] [
|
footer [] [
|
||||||
div [id "footer"] [
|
div [id "footer"] [
|
||||||
text " powered by ",
|
text " powered by ",
|
||||||
a [href "https://www.netlify.com"] [text "Netlify"],
|
a [href "https://www.netlify.com"] [text "Netlify"],
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
# TODO - add site.js if needed
|
# TODO - add site.js if needed
|
||||||
# script [src "/site.js"] [],
|
# script [src "/site.js"] [],
|
||||||
|
@ -81,17 +86,22 @@ viewNavbar = \page ->
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
rocLogo : Html.Node
|
||||||
rocLogo =
|
rocLogo =
|
||||||
(Html.element "svg") [
|
(Html.element "svg")
|
||||||
|
[
|
||||||
(Html.attribute "viewBox") "0 -6 51 58",
|
(Html.attribute "viewBox") "0 -6 51 58",
|
||||||
(Html.attribute "xmlns") "http://www.w3.org/2000/svg",
|
(Html.attribute "xmlns") "http://www.w3.org/2000/svg",
|
||||||
(Html.attribute "aria-labelledby") "logo-link",
|
(Html.attribute "aria-labelledby") "logo-link",
|
||||||
(Html.attribute "role") "img",
|
(Html.attribute "role") "img",
|
||||||
class "roc-logo"
|
class "roc-logo",
|
||||||
] [
|
]
|
||||||
|
[
|
||||||
(Html.element "title") [id "logo-link"] [text "Return to Roc Home"],
|
(Html.element "title") [id "logo-link"] [text "Return to Roc Home"],
|
||||||
(Html.element "polygon") [
|
(Html.element "polygon")
|
||||||
|
[
|
||||||
(Html.attribute "role") "presentation",
|
(Html.attribute "role") "presentation",
|
||||||
(Html.attribute "points") "0,0 23.8834,3.21052 37.2438,19.0101 45.9665,16.6324 50.5,22 45,22 44.0315,26.3689 26.4673,39.3424 27.4527,45.2132 17.655,53 23.6751,22.7086",
|
(Html.attribute "points") "0,0 23.8834,3.21052 37.2438,19.0101 45.9665,16.6324 50.5,22 45,22 44.0315,26.3689 26.4673,39.3424 27.4527,45.2132 17.655,53 23.6751,22.7086",
|
||||||
] [],
|
]
|
||||||
|
[],
|
||||||
]
|
]
|
||||||
|
|
|
@ -63,6 +63,17 @@ footer {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Used for e.g. displaying the instruction "Click" on desktop and "Touch" on mobile.
|
||||||
|
* When we think we're on mobile (based on max-width), we can switch the instruction.
|
||||||
|
*/
|
||||||
|
.desktop {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
section p:last-child {
|
section p:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
@ -303,6 +314,14 @@ li {
|
||||||
|
|
||||||
/* Mobile-friendly screen width */
|
/* Mobile-friendly screen width */
|
||||||
@media only screen and (max-width: 1024px) {
|
@media only screen and (max-width: 1024px) {
|
||||||
|
/* Used for e.g. displaying the instruction "Click" on desktop and "Touch" on mobile. */
|
||||||
|
.desktop {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
p,
|
p,
|
||||||
aside,
|
aside,
|
||||||
|
@ -759,3 +778,42 @@ code .dim {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
margin-bottom: 2em;
|
margin-bottom: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Interactive example on homepage */
|
||||||
|
|
||||||
|
.interactive-example {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 800px;
|
||||||
|
padding-right: 300px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interactive-example label:hover,
|
||||||
|
.interactive-radio:checked+label {
|
||||||
|
background-color: turquoise;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interactive-desc {
|
||||||
|
display: none;
|
||||||
|
background-color: #ddd;
|
||||||
|
padding: 8px 16px;
|
||||||
|
margin-top: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interactive-radio {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.interactive-radio:checked+label+.interactive-desc {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 300px;
|
||||||
|
width: 300px;
|
||||||
|
white-space: normal;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue