first commit
This commit is contained in:
commit
a9af55fb0b
9 changed files with 238 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.make.*
|
||||||
|
app.js
|
||||||
|
elm-stuff/
|
||||||
|
error.txt
|
2
.watchmakerc
Normal file
2
.watchmakerc
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
extensions:
|
||||||
|
- .elm
|
11
Makefile
Normal file
11
Makefile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
DIRNAME=$(notdir $(CURDIR))
|
||||||
|
|
||||||
|
ELMS=$(wildcard src/*.elm)
|
||||||
|
|
||||||
|
app.js: src/App.elm $(ELMS)
|
||||||
|
-elm make $< --output=$@ 2> error.txt
|
||||||
|
@cat error.txt
|
||||||
|
|
||||||
|
upload: app.js index.html style.css
|
||||||
|
rsync -avz . clpland:~/domains/somethingorotherwhatever.com/html/$(DIRNAME)
|
||||||
|
@echo "Uploaded to https://somethingorotherwhatever.com/$(DIRNAME)"
|
25
elm.json
Normal file
25
elm.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"type": "application",
|
||||||
|
"source-directories": [
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"elm-version": "0.19.1",
|
||||||
|
"dependencies": {
|
||||||
|
"direct": {
|
||||||
|
"elm/browser": "1.0.2",
|
||||||
|
"elm/core": "1.0.5",
|
||||||
|
"elm/html": "1.0.0",
|
||||||
|
"elm/svg": "1.0.1",
|
||||||
|
"elm/time": "1.0.0"
|
||||||
|
},
|
||||||
|
"indirect": {
|
||||||
|
"elm/json": "1.1.3",
|
||||||
|
"elm/url": "1.0.0",
|
||||||
|
"elm/virtual-dom": "1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test-dependencies": {
|
||||||
|
"direct": {},
|
||||||
|
"indirect": {}
|
||||||
|
}
|
||||||
|
}
|
23
index.html
Normal file
23
index.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<title>Elm app by clp</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Elm app by clp</h1>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<p>This is an app which will either load succesfully, and you'll wonder whether you saw this text at all, or fail ignominiously, showing you only this text.</p>
|
||||||
|
<p>On balance of probabilities: I'm sorry I couldn't be bothered to make this work for you.</p>
|
||||||
|
</main>
|
||||||
|
<footer>Made by <a href="https://somethingorotherwhatever.com">clp</a></footer>
|
||||||
|
|
||||||
|
<script src="app.js"></script>
|
||||||
|
<script src="load-app.js" type="module"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
10
load-app.js
Normal file
10
load-app.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import show_error from './show-error.mjs';
|
||||||
|
async function init_app() {
|
||||||
|
const compilation_error = await show_error;
|
||||||
|
if(compilation_error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const app = Elm.App.init({node: document.body, flags: {}});
|
||||||
|
}
|
||||||
|
|
||||||
|
init_app();
|
21
show-error.mjs
Normal file
21
show-error.mjs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
export default fetch('/error.txt').then(r=>{
|
||||||
|
if(r.ok) {
|
||||||
|
return r.text();
|
||||||
|
} else {
|
||||||
|
throw('');
|
||||||
|
}
|
||||||
|
}).then(text => {
|
||||||
|
if(!text) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
document.body.innerHTML = '';
|
||||||
|
const error_show = document.createElement('pre');
|
||||||
|
error_show.setAttribute('id','build-error');
|
||||||
|
error_show.style.background = 'black';
|
||||||
|
error_show.style.color = 'white';
|
||||||
|
error_show.style.padding = '1em';
|
||||||
|
error_show.style['font-size'] = '16px';
|
||||||
|
error_show.textContent = text;
|
||||||
|
document.body.appendChild(error_show);
|
||||||
|
return true;
|
||||||
|
}).catch(e => false);
|
128
src/App.elm
Normal file
128
src/App.elm
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
module App exposing (..)
|
||||||
|
|
||||||
|
import Browser
|
||||||
|
import Html as H exposing (Html)
|
||||||
|
import Html.Attributes as HA
|
||||||
|
import Html.Events as HE
|
||||||
|
import Svg
|
||||||
|
import Svg.Attributes as SA
|
||||||
|
import Time exposing (Posix)
|
||||||
|
|
||||||
|
main = Browser.document
|
||||||
|
{ init = init
|
||||||
|
, update = update
|
||||||
|
, subscriptions = subscriptions
|
||||||
|
, view = view
|
||||||
|
}
|
||||||
|
|
||||||
|
type alias Model = { time: Posix }
|
||||||
|
|
||||||
|
init_model = { time = Time.millisToPosix 0 }
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= Tick Posix
|
||||||
|
|
||||||
|
init : () -> (Model, Cmd msg)
|
||||||
|
init _ = (init_model, Cmd.none)
|
||||||
|
|
||||||
|
update msg model = case msg of
|
||||||
|
Tick time -> ({ model | time = time }, Cmd.none)
|
||||||
|
|
||||||
|
subscriptions model = Time.every 50 Tick
|
||||||
|
|
||||||
|
ff = String.fromFloat
|
||||||
|
|
||||||
|
view model =
|
||||||
|
let
|
||||||
|
time = model.time
|
||||||
|
zone = Time.utc
|
||||||
|
now = (toFloat <| Time.posixToMillis time) / 1000
|
||||||
|
|
||||||
|
num_arms = 10
|
||||||
|
|
||||||
|
r_for n = 1 - 0.9*n/num_arms
|
||||||
|
period_for n = 10 ^ ((toFloat num_arms) - n)
|
||||||
|
|
||||||
|
arm n =
|
||||||
|
let
|
||||||
|
period = period_for n
|
||||||
|
an = (now / period - 0.25) * 2 * pi
|
||||||
|
r = r_for n
|
||||||
|
in
|
||||||
|
Svg.line
|
||||||
|
[ SA.x1 "0"
|
||||||
|
, SA.y1 "0"
|
||||||
|
, SA.x2 <| ff <| (*) r <| cos an
|
||||||
|
, SA.y2 <| ff <| (*) r <| sin an
|
||||||
|
, SA.strokeWidth "0.01"
|
||||||
|
, SA.stroke "black"
|
||||||
|
-- , SA.strokeDasharray <| (ff dash) ++ " " ++ (ff dash)
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
arms = List.map (toFloat >> arm) (List.range 0 num_arms)
|
||||||
|
|
||||||
|
tick ii =
|
||||||
|
let
|
||||||
|
i = toFloat ii
|
||||||
|
an = 2 * pi * (i / 10 - 0.25)
|
||||||
|
r = 1
|
||||||
|
in
|
||||||
|
Svg.line
|
||||||
|
[ SA.x1 "0"
|
||||||
|
, SA.y1 "0"
|
||||||
|
, SA.x2 <| ff <| (*) r <| cos an
|
||||||
|
, SA.y2 <| ff <| (*) r <| sin an
|
||||||
|
, SA.strokeWidth "0.01"
|
||||||
|
, SA.stroke "#eee"
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
|
||||||
|
inner_circle n =
|
||||||
|
let
|
||||||
|
fn = toFloat n
|
||||||
|
period = period_for fn
|
||||||
|
r = (r_for fn)
|
||||||
|
num_ticks = (floor period)
|
||||||
|
in
|
||||||
|
Svg.g
|
||||||
|
[]
|
||||||
|
[ Svg.circle
|
||||||
|
[ SA.r <| ff r
|
||||||
|
, SA.strokeWidth "0.002"
|
||||||
|
, SA.stroke "gray"
|
||||||
|
, SA.fill "none"
|
||||||
|
]
|
||||||
|
[]
|
||||||
|
, Svg.text_
|
||||||
|
[ SA.x "0"
|
||||||
|
, SA.y <| ff (-r)
|
||||||
|
, SA.fontSize "0.03"
|
||||||
|
, SA.textAnchor "middle"
|
||||||
|
]
|
||||||
|
[ Svg.text <| ff <| period]
|
||||||
|
]
|
||||||
|
|
||||||
|
circles = List.map (inner_circle) (List.range 0 num_arms)
|
||||||
|
in
|
||||||
|
{
|
||||||
|
title = "Unix epoch clock",
|
||||||
|
body =
|
||||||
|
[ Svg.svg
|
||||||
|
[ HA.attribute "viewBox" "-1.2 -1.2 2.4 2.6"]
|
||||||
|
[ Svg.g [] (List.map tick (List.range 0 9))
|
||||||
|
, Svg.g [] circles
|
||||||
|
, Svg.g [] arms
|
||||||
|
, Svg.text_
|
||||||
|
[ SA.x "0"
|
||||||
|
, SA.y "1.1"
|
||||||
|
, SA.textAnchor "middle"
|
||||||
|
, SA.dominantBaseline "central"
|
||||||
|
, SA.fontSize "0.1"
|
||||||
|
, SA.stroke "white"
|
||||||
|
, SA.strokeWidth "0.02"
|
||||||
|
, SA.style "paint-order: stroke fill"
|
||||||
|
]
|
||||||
|
[ Svg.text <| String.fromInt <| floor <| (\n -> (toFloat n)/1000) <| Time.posixToMillis model.time ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
14
style.css
Normal file
14
style.css
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
width: 100svw;
|
||||||
|
height: 100svh;
|
||||||
|
display: grid;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
grid-template: 1fr / 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue