├── .env.sample ├── .gitignore ├── Dockerfile ├── LICENSE ├── Procfile ├── README.md ├── console.janet ├── db ├── migrations │ ├── 20200512174722-create-table-account.sql │ ├── 20200512175404-create-table-package.sql │ ├── 20200512175708-create-table-binding.sql │ ├── 20200512175731-create-table-example.sql │ ├── 20200515161430-add-login-to-account.sql │ └── 20201209174006-create-table-link.sql ├── schema.sql └── sql │ ├── random.sql │ └── search.sql ├── docker-compose.yml ├── helpers.janet ├── main.janet ├── nginx.conf ├── post-receive-hook ├── project.janet ├── public ├── _app.js ├── _highlight.pack.js ├── _pylon.css ├── _water.css ├── ace │ ├── ace.js │ └── mode-clojure.js ├── alpine.min.js ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── app.css ├── apple-touch-icon.png ├── css │ ├── atom-one-dark.css │ └── atom-one-light.css ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── playground │ ├── janet.js │ ├── janet.wasm │ ├── jdocs_playground.js │ └── playground.js └── site.webmanifest ├── routes ├── bindings.janet ├── examples.janet ├── home.janet ├── playground.janet └── sessions.janet ├── seed.janet └── test └── server-test.janet /.env.sample: -------------------------------------------------------------------------------- 1 | DATABASE_URL=janetdocs.sqlite3 2 | ENCRYPTION_KEY=2af90dc50f5f09a15b30c463042d4e27f63382382a4e04e073b985b5d0779366 3 | JOY_ENV=development 4 | PORT=9001 5 | GITHUB_CLIENT_ID=123456 6 | GITHUB_CLIENT_SECRET=654321 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | /.env 3 | *.sqlite3 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.7 2 | 3 | RUN apk add --no-cache build-base curl curl-dev git 4 | 5 | # Create a non-root user to run the app as 6 | ARG USER=app 7 | ARG GROUP=app 8 | ARG UID=1101 9 | ARG GID=1101 10 | 11 | RUN addgroup -g $GID -S $GROUP 12 | RUN adduser -u $UID -S $USER -G $GROUP 13 | 14 | # Move to tmp and install janet 15 | RUN git clone https://github.com/janet-lang/janet.git /tmp/janet && \ 16 | cd /tmp/janet && \ 17 | make all test install 18 | 19 | RUN chmod 777 /usr/local/lib/janet 20 | 21 | # Use jpm to install joy 22 | RUN jpm install joy 23 | 24 | RUN chown -R $USER:$GROUP /usr/local/lib/janet 25 | 26 | # Create a place to mount or copy in your server 27 | RUN mkdir -p /var/app 28 | RUN chown -R $USER:$GROUP /var/app 29 | 30 | USER $USER 31 | WORKDIR /var/app 32 | COPY . ./ 33 | 34 | ARG DEPS=false 35 | USER root 36 | RUN jpm deps 37 | USER $USER 38 | 39 | EXPOSE 9003 40 | 41 | CMD ["janet", "main.janet"] 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Sean Walker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: janet main.janet 2 | release: cd /var/app && joy migrate 3 | seed: janet seed.janet 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # janetdocs 2 | 3 | A community documentation site for the [janet](https://janet-lang.org) programming language 4 | 5 | ## Install janet 6 | 7 | The first step is to get janet installed. 8 | 9 | This uses [homebrew](https://brew.sh) for simplicity, but feel free to come up with whatever vagrant, docker or nixOS thing you'd like: 10 | 11 | ```sh 12 | brew install janet 13 | ``` 14 | 15 | ## Get Started 16 | 17 | After janet is installed there are a few steps to get this project up and running: 18 | 19 | 1. Clone this repo 20 | 21 | ```sh 22 | git clone https://github.com/swlkr/janetdocs.git 23 | ``` 24 | 25 | 2. Move `.env.sample` to `.env` 26 | 27 | ```sh 28 | cd janetdocs 29 | mv `.env.sample` `.env` 30 | ``` 31 | 32 | 3. Change the github client and secret ids to something real 33 | 34 | You can create your own github oauth app or whatever it's called now to get your keys to get github sign in working 35 | 36 | 4. Install deps 37 | 38 | ```sh 39 | # make sure you're in the janetdocs directory 40 | jpm deps 41 | ``` 42 | 43 | 5. Migrate the database 44 | 45 | ```sh 46 | # make sure you're in the janetdocs directory 47 | joy migrate 48 | ``` 49 | 50 | 6. Seed the database with the docs 51 | 52 | ```sh 53 | # make sure you're in the janetdocs directory 54 | janet seed.janet 55 | ``` 56 | 57 | And that's it! You should be able to poke around at this point and see what's going on, by default the server starts on port 9001: 58 | 59 | ```sh 60 | # make sure you're in the janetdocs directory 61 | janet main.janet 62 | ``` 63 | -------------------------------------------------------------------------------- /console.janet: -------------------------------------------------------------------------------- 1 | (use joy) 2 | 3 | (import dotenv) 4 | (dotenv/load) 5 | 6 | (db/connect (env :database-url)) 7 | 8 | (repl nil 9 | (fn [_ y] (printf "%Q" y)) 10 | (fiber/getenv (fiber/current))) 11 | 12 | (db/disconnect) 13 | -------------------------------------------------------------------------------- /db/migrations/20200512174722-create-table-account.sql: -------------------------------------------------------------------------------- 1 | -- up 2 | create table account ( 3 | id integer primary key, 4 | email text, 5 | access_token text not null, 6 | created_at integer not null default(strftime('%s', 'now')), 7 | updated_at integer 8 | ) 9 | 10 | -- down 11 | drop table account -------------------------------------------------------------------------------- /db/migrations/20200512175404-create-table-package.sql: -------------------------------------------------------------------------------- 1 | -- up 2 | create table package ( 3 | id integer primary key, 4 | name text not null, 5 | url text not null, 6 | created_at integer not null default(strftime('%s', 'now')), 7 | updated_at integer 8 | ) 9 | 10 | -- down 11 | drop table package -------------------------------------------------------------------------------- /db/migrations/20200512175708-create-table-binding.sql: -------------------------------------------------------------------------------- 1 | -- up 2 | create table binding ( 3 | id integer primary key, 4 | name text not null, 5 | docstring text, 6 | package_id integer references package(id), 7 | created_at integer not null default(strftime('%s', 'now')), 8 | updated_at integer 9 | ) 10 | 11 | -- down 12 | drop table binding 13 | -------------------------------------------------------------------------------- /db/migrations/20200512175731-create-table-example.sql: -------------------------------------------------------------------------------- 1 | -- up 2 | create table example ( 3 | id integer primary key, 4 | body text not null, 5 | binding_id integer not null references binding(id), 6 | account_id integer not null references account(id), 7 | created_at integer not null default(strftime('%s', 'now')), 8 | updated_at integer 9 | ) 10 | 11 | -- down 12 | drop table example 13 | -------------------------------------------------------------------------------- /db/migrations/20200515161430-add-login-to-account.sql: -------------------------------------------------------------------------------- 1 | -- up 2 | alter table account add login text not null default '' 3 | 4 | -- down 5 | -------------------------------------------------------------------------------- /db/migrations/20201209174006-create-table-link.sql: -------------------------------------------------------------------------------- 1 | 2 | -- up 3 | CREATE TABLE link ( 4 | source integer not null references binding(id), 5 | target integer not null references binding(id), 6 | PRIMARY KEY (source, target) 7 | ); 8 | 9 | -- down 10 | DROP TABLE link; 11 | -------------------------------------------------------------------------------- /db/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE schema_migrations (version text primary key); 2 | CREATE TABLE account ( 3 | id integer primary key, 4 | email text, 5 | access_token text not null, 6 | created_at integer not null default(strftime('%s', 'now')), 7 | updated_at integer 8 | , login text not null default ''); 9 | CREATE TABLE package ( 10 | id integer primary key, 11 | name text not null, 12 | url text not null, 13 | created_at integer not null default(strftime('%s', 'now')), 14 | updated_at integer 15 | ); 16 | CREATE TABLE binding ( 17 | id integer primary key, 18 | name text not null, 19 | docstring text, 20 | package_id integer references package(id), 21 | created_at integer not null default(strftime('%s', 'now')), 22 | updated_at integer 23 | ); 24 | CREATE TABLE example ( 25 | id integer primary key, 26 | body text not null, 27 | binding_id integer not null references binding(id), 28 | account_id integer not null references account(id), 29 | created_at integer not null default(strftime('%s', 'now')), 30 | updated_at integer 31 | ); 32 | CREATE TABLE link ( 33 | source integer not null references binding(id), 34 | target integer not null references binding(id), 35 | PRIMARY KEY (source, target) 36 | ); 37 | -------------------------------------------------------------------------------- /db/sql/random.sql: -------------------------------------------------------------------------------- 1 | select 2 | * 3 | from 4 | binding 5 | where 6 | binding.id = (abs(random()) % (select (select max(binding.id) from binding) + 1)) 7 | -------------------------------------------------------------------------------- /db/sql/search.sql: -------------------------------------------------------------------------------- 1 | select 2 | binding.id, 3 | binding.name, 4 | binding.docstring, 5 | binding.package_id, 6 | package.name as package, 7 | count(example.id) as examples 8 | from 9 | binding 10 | left outer join 11 | package on binding.package_id = package.id 12 | left outer join 13 | example on example.binding_id = binding.id 14 | where 15 | binding.name like ? 16 | group by 17 | binding.id 18 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | web: 4 | tty: true 5 | env_file: .env 6 | volumes: 7 | - .:/var/app 8 | image: janetdocs 9 | ports: 10 | - "9003:9003" 11 | -------------------------------------------------------------------------------- /helpers.janet: -------------------------------------------------------------------------------- 1 | (import joy :prefix "") 2 | (import uri) 3 | 4 | 5 | (defn binding-header [binding] 6 | [:vstack {:spacing "xs"} 7 | [:h1 (binding :name)] 8 | [:strong (get-in binding [:package :name] (binding :package))] 9 | [:pre 10 | [:code {:class "clojure"} 11 | (binding :docstring)]]]) 12 | 13 | 14 | (defn binding-show-url [binding &opt url] 15 | (default url "") 16 | (def package (db/find :package (or (binding :package-id) 0))) 17 | 18 | (def name (string/replace "?" "_q" (binding :name))) 19 | 20 | (if package 21 | (string "/" (package :name) "/" name url) 22 | (string "/" (uri/escape name) url))) 23 | 24 | 25 | (defn singularize [str n] 26 | (if (one? n) 27 | (string/trimr str "s") 28 | str)) 29 | 30 | 31 | (defn confirm-modal [request & body] 32 | [:div {:x-data "{ modalOpen: false, action: '' }"} 33 | body 34 | [:div {:class "md-modal" ::class "{'md-show': modalOpen}" :x-show "modalOpen" :@click.away "modalOpen = false"} 35 | [:div {:class "md-content"} 36 | [:vstack {:align-x "center"} 37 | [:h3 "Are you sure?"] 38 | [:hstack {:spacing "l" :align-x "center"} 39 | (form-with request {:method "POST" :x-bind:action "action"} 40 | [:input {:type "hidden" :name "_method" :value "DELETE"}] 41 | [:button {:type "submit"} 42 | "Yes, do it"]) 43 | [:a {:href "#" :@click.prevent "modalOpen = false"} 44 | "No"]]]]] 45 | [:div {:class "md-overlay" ::class "{'md-show': modalOpen}"}]]) 46 | 47 | 48 | (defn delete-button [request action] 49 | (confirm-modal request 50 | [:a {:href "#" 51 | :@click.prevent (string/format "action = '%s'; modalOpen = true" action)} 52 | "Delete"])) 53 | 54 | 55 | (defn current-account [request] 56 | (def login (get-in request [:session :login] "")) 57 | (db/find-by :account :where {:login login})) 58 | 59 | 60 | (defn menu [request] 61 | (def session (get request :session {})) 62 | 63 | [:vstack {:spacing "l"} 64 | [:hstack {:stretch "" :spacing "s"} 65 | [:a {:href (url-for :home/index)} 66 | "JanetDocs"] 67 | [:spacer] 68 | [:a {:href (url-for :playground/home)} "Playground"] 69 | [:a {:href (url-for :examples/random)} 70 | "I'm feeling lucky"] 71 | 72 | (if (get session :login) 73 | [:hstack {:spacing "m"} 74 | (form-with request (action-for :sessions/destroy) 75 | [:input {:type "hidden" :name "_method" :value "delete"}] 76 | [:input {:type "submit" :value "Sign out"}])] 77 | 78 | [:hstack {:spacing "m"} 79 | [:a {:href (string/format "https://github.com/login/oauth/authorize?client_id=%s" 80 | (env :github-client-id))} 81 | "GitHub sign in"]])]]) 82 | 83 | 84 | (defn layout [{:body body :request request}] 85 | (text/html 86 | (doctype :html5) 87 | [:html {:lang "en"} 88 | [:head 89 | [:title "JanetDocs"] 90 | [:meta {:charset "utf-8"}] 91 | [:meta {:name "viewport" :content "width=device-width, initial-scale=1"}] 92 | [:meta {:name "csrf-token" :content (authenticity-token request)}] 93 | [:link {:rel "apple-touch-icon" :sizes "180x180" :href "/apple-touch-icon.png"}] 94 | [:link {:rel "icon" :type "image/png" :sizes "32x32" :href "/favicon-32x32.png"}] 95 | [:link {:rel "icon" :type "image/png" :sizes "16x16" :href "/favicon-16x16.png"}] 96 | [:link {:rel "manifest" :href "/site.webmanifest"}] 97 | [:link {:rel "stylesheet" :href "/css/atom-one-light.css" :media "(prefers-color-scheme: no-preference), (prefers-color-scheme: light)"}] 98 | [:link {:rel "stylesheet" :href "/css/atom-one-dark.css" :media "(prefers-color-scheme: dark)"}] 99 | [:link {:rel "stylesheet" :href "/_pylon.css"}] 100 | [:link {:rel "stylesheet" :href "/_water.css"}] 101 | [:link {:rel "stylesheet" :href "/app.css"}] 102 | [:script {:src "/_highlight.pack.js" :defer ""}] 103 | [:script {:src "/_app.js" :defer ""}] 104 | [:script {:src "/alpine.min.js" :defer ""}]] 105 | 106 | 107 | [:body 108 | [:vstack {:spacing "xl"} 109 | (menu request) 110 | body 111 | [:spacer]]]])) 112 | 113 | 114 | (defn /404 [request] 115 | (as-> (layout {:request request 116 | :body [:center 117 | [:h1 "Oops! 404!"]]}) ? 118 | (put ? :status 404))) 119 | -------------------------------------------------------------------------------- /main.janet: -------------------------------------------------------------------------------- 1 | (import joy :prefix "") 2 | (import ./helpers :prefix "") 3 | 4 | 5 | (defroutes routes 6 | [:get "/" :home/index] 7 | [:delete "/sessions" :sessions/destroy] 8 | [:get "/github-auth" :home/github-auth] 9 | [:post "/searches" :home/searches] 10 | [:get "/bindings/random" :examples/random] 11 | [:get "/bindings/:binding-id/examples/form" :examples/form] 12 | [:get "/bindings/:binding-id/examples/new" :examples/new] 13 | [:post "/bindings/:binding-id/examples" :examples/create] 14 | [:get "/examples/:id/edit" :examples/edit] 15 | [:patch "/examples/:id" :examples/patch] 16 | [:delete "/examples/:id" :examples/destroy] 17 | [:get "/export.json" :examples/export] 18 | [:get "/playground/example/:id" :playground/example] 19 | [:get "/playground" :playground/home] 20 | [:get "/*" :bindings/show]) 21 | 22 | 23 | (def app (app {:routes routes 24 | :layout layout 25 | :404 /404})) 26 | 27 | 28 | (defn main [& args] 29 | (db/connect (env :database-url)) 30 | (server app (env :port) "0.0.0.0") 31 | (db/disconnect)) 32 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | upstream janetdocs { 2 | server 127.0.0.1:9001; 3 | } 4 | 5 | server { 6 | 7 | server_name janetdocs.joyapps.xyz; 8 | 9 | access_log /var/log/nginx/janetdocs-access.log; 10 | error_log /var/log/nginx/janetdocs-error.log; 11 | 12 | keepalive_timeout 70; 13 | 14 | location / { 15 | gzip on; 16 | gzip_min_length 1100; 17 | gzip_buffers 4 32k; 18 | gzip_types text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml application/rss+xml font/truetype application/x-font-ttf font/opentype application/vnd.ms-fontobject image/svg+xml; 19 | gzip_vary on; 20 | gzip_comp_level 6; 21 | 22 | proxy_pass http://janetdocs; 23 | proxy_http_version 1.1; 24 | proxy_set_header Upgrade $http_upgrade; 25 | proxy_set_header Connection $http_connection; 26 | proxy_set_header Host $http_host; 27 | proxy_set_header X-Forwarded-Proto $scheme; 28 | proxy_set_header X-Forwarded-For $remote_addr; 29 | proxy_set_header X-Forwarded-Port $server_port; 30 | } 31 | 32 | location ~ \.(gif|jpg|png|js|css|svg|ico)$ { 33 | root /home/sean/janetdocs/public; 34 | } 35 | 36 | add_header Strict-Transport-Security "max-age=15724800; includeSubdomains" always; 37 | } 38 | -------------------------------------------------------------------------------- /post-receive-hook: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | app="janetdocs" 4 | working_tree="/home/sean/$app" 5 | port="9002" 6 | 7 | while read oldrev newrev ref 8 | do 9 | echo "Master ref received. Deploying master branch to production..." 10 | 11 | echo "Shutting down server..." 12 | pkill -f '$app' 13 | 14 | echo "Cloning new files" 15 | git --work-tree=$working_tree --git-dir=/home/sean/$app.git checkout -f 16 | cd $working_tree 17 | 18 | echo "Migrating database" 19 | DATABASE_URL=/home/sean/$app/$app-production.sqlite3 joy migrate 20 | 21 | # echo "Running jpm deps" 22 | # jpm deps 23 | 24 | echo "Starting server..." 25 | bash -c "exec -a $app janet main.janet $port &> app.log &" 26 | 27 | echo " /===============================" 28 | echo " | DEPLOYMENT COMPLETED" 29 | echo " | Target branch: master" 30 | echo " | Target folder: $working_tree" 31 | echo " \==============================" 32 | 33 | done 34 | 35 | exit 0 -------------------------------------------------------------------------------- /project.janet: -------------------------------------------------------------------------------- 1 | (declare-project 2 | :name "janetdocs" 3 | :description "JanetDocs is a community documentation site for the Janet programming language" 4 | :dependencies ["https://github.com/janet-lang/sqlite3" 5 | "https://github.com/joy-framework/dotenv" 6 | "https://github.com/joy-framework/http" 7 | "https://github.com/joy-framework/joy"] 8 | 9 | :author "Sean Walker" 10 | :license "MIT" 11 | :url "https://janetdocs.com" 12 | :repo "https://github.com/swlkr/janetdocs") 13 | 14 | (declare-executable 15 | :name "janetdocs" 16 | :entry "main.janet") 17 | 18 | (phony "server" [] 19 | (os/shell "janet main.janet")) 20 | 21 | (phony "watch" [] 22 | (os/shell "find . -name '*.janet' | entr -r -d janet main.janet")) 23 | -------------------------------------------------------------------------------- /public/_app.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | document.querySelectorAll('pre code').forEach((block) => { 3 | hljs.highlightBlock(block); 4 | }); 5 | 6 | setTimeout(function() { 7 | var params = new URLSearchParams(window.location.search) 8 | if(params.get('new') === '') { 9 | const ev = new Event('mouseenter'); 10 | document.getElementById('add-example').dispatchEvent(ev); 11 | 12 | const ev1 = new Event('click'); 13 | document.getElementById('add-example').dispatchEvent(ev1); 14 | } 15 | }, 10); 16 | }); 17 | 18 | function highlight() { 19 | document.querySelectorAll('pre code').forEach((block) => { 20 | hljs.highlightBlock(block); 21 | }); 22 | } 23 | 24 | function api(url, options) { 25 | var options = options || {}; 26 | options.headers = options.headers || {}; 27 | if(options.method.toLowerCase() !== 'get') { 28 | options['headers']['x-csrf-token'] = document.querySelector('meta[name="csrf-token"]').content; 29 | } 30 | options['headers']['x-requested-with'] = 'XMLHttpRequest' 31 | 32 | return fetch(url, options); 33 | } 34 | 35 | 36 | async function get(url, contentType) { 37 | var options = { 38 | method: 'get', 39 | headers: { 40 | 'content-type': 'application/json' 41 | } 42 | }; 43 | 44 | var response = await api(url, options); 45 | if(contentType === "text/html") { 46 | return await response.text(); 47 | } else { 48 | return await response.json(); 49 | } 50 | } 51 | 52 | 53 | async function post(url, body, contentType) { 54 | var options = { 55 | method: 'post', 56 | headers: { 57 | 'content-type': 'application/json' 58 | }, 59 | body: JSON.stringify(body) 60 | }; 61 | 62 | var response = await api(url, options); 63 | if(contentType === "text/html") { 64 | return await response.text(); 65 | } else { 66 | return await response.json(); 67 | } 68 | } 69 | 70 | 71 | function searcher(url) { 72 | return { 73 | token: '', 74 | results: '', 75 | 76 | search: async function() { 77 | var html = await post(url, { token: this.token }, "text/html"); 78 | this.results = html; 79 | 80 | setTimeout(function() { 81 | document.querySelectorAll('pre > code').forEach(function(el) { 82 | hljs.highlightBlock(el); 83 | }); 84 | }, 0) 85 | }, 86 | 87 | go: function() { 88 | Turbolinks.visit(document.querySelectorAll('.binding')[0].getAttribute('href')) 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /public/_highlight.pack.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highlight.js 10.0.3 (a4b1bd2d) 3 | License: BSD-3-Clause 4 | Copyright (c) 2006-2020, Ivan Sagalaev 5 | */ 6 | var hljs=function(){"use strict";function e(n){Object.freeze(n);var t="function"==typeof n;return Object.getOwnPropertyNames(n).forEach((function(r){!n.hasOwnProperty(r)||null===n[r]||"object"!=typeof n[r]&&"function"!=typeof n[r]||t&&("caller"===r||"callee"===r||"arguments"===r)||Object.isFrozen(n[r])||e(n[r])})),n}function n(e){return e.replace(/&/g,"&").replace(//g,">")}function t(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach((function(e){for(n in e)t[n]=e[n]})),t}function r(e){return e.nodeName.toLowerCase()}var a=Object.freeze({__proto__:null,escapeHTML:n,inherit:t,nodeStream:function(e){var n=[];return function e(t,a){for(var i=t.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=e(i,a),r(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n},mergeStreams:function(e,t,a){var i=0,s="",o=[];function l(){return e.length&&t.length?e[0].offset!==t[0].offset?e[0].offset"}function u(e){s+=""}function d(e){("start"===e.event?c:u)(e.node)}for(;e.length||t.length;){var g=l();if(s+=n(a.substring(i,g[0].offset)),i=g[0].offset,g===e){o.reverse().forEach(u);do{d(g.splice(0,1)[0]),g=l()}while(g===e&&g.length&&g[0].offset===i);o.reverse().forEach(c)}else"start"===g[0].event?o.push(g[0].node):o.pop(),d(g.splice(0,1)[0])}return s+n(a.substr(i))}});const i="",s=e=>!!e.kind;class o{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=n(e)}openNode(e){if(!s(e))return;let n=e.kind;e.sublanguage||(n=`${this.classPrefix}${n}`),this.span(n)}closeNode(e){s(e)&&(this.buffer+=i)}span(e){this.buffer+=``}value(){return this.buffer}}class l{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){let n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach(n=>this._walk(e,n)),e.closeNode(n)),e}static _collapse(e){e.children&&(e.children.every(e=>"string"==typeof e)?(e.text=e.children.join(""),delete e.children):e.children.forEach(e=>{"string"!=typeof e&&l._collapse(e)}))}}class c extends l{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){let t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new o(this,this.options).value()}finalize(){}}function u(e){return e&&e.source||e}const d="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",g={begin:"\\\\[\\s\\S]",relevance:0},h={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[g]},f={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[g]},p={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},m=function(e,n,r){var a=t({className:"comment",begin:e,end:n,contains:[]},r||{});return a.contains.push(p),a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|XXX):",relevance:0}),a},b=m("//","$"),v=m("/\\*","\\*/"),x=m("#","$");var _=Object.freeze({__proto__:null,IDENT_RE:"[a-zA-Z]\\w*",UNDERSCORE_IDENT_RE:"[a-zA-Z_]\\w*",NUMBER_RE:"\\b\\d+(\\.\\d+)?",C_NUMBER_RE:d,BINARY_NUMBER_RE:"\\b(0b[01]+)",RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",BACKSLASH_ESCAPE:g,APOS_STRING_MODE:h,QUOTE_STRING_MODE:f,PHRASAL_WORDS_MODE:p,COMMENT:m,C_LINE_COMMENT_MODE:b,C_BLOCK_COMMENT_MODE:v,HASH_COMMENT_MODE:x,NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?",relevance:0},C_NUMBER_MODE:{className:"number",begin:d,relevance:0},BINARY_NUMBER_MODE:{className:"number",begin:"\\b(0b[01]+)",relevance:0},CSS_NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},REGEXP_MODE:{begin:/(?=\/[^\/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[g,{begin:/\[/,end:/\]/,relevance:0,contains:[g]}]}]},TITLE_MODE:{className:"title",begin:"[a-zA-Z]\\w*",relevance:0},UNDERSCORE_TITLE_MODE:{className:"title",begin:"[a-zA-Z_]\\w*",relevance:0},METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0}}),E="of and for in not or if then".split(" ");function R(e,n){return n?+n:(t=e,E.includes(t.toLowerCase())?0:1);var t}const N=n,w=t,{nodeStream:y,mergeStreams:O}=a;return function(n){var r=[],a={},i={},s=[],o=!0,l=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,d="Could not find the language '{}', did you forget to load/include a language module?",g={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0,__emitter:c};function h(e){return g.noHighlightRe.test(e)}function f(e,n,t,r){var a={code:n,language:e};T("before:highlight",a);var i=a.result?a.result:p(a.language,a.code,t,r);return i.code=a.code,T("after:highlight",i),i}function p(e,n,r,i){var s=n;function l(e,n){var t=v.case_insensitive?n[0].toLowerCase():n[0];return e.keywords.hasOwnProperty(t)&&e.keywords[t]}function c(){null!=_.subLanguage?function(){if(""!==k){var e="string"==typeof _.subLanguage;if(!e||a[_.subLanguage]){var n=e?p(_.subLanguage,k,!0,E[_.subLanguage]):m(k,_.subLanguage.length?_.subLanguage:void 0);_.relevance>0&&(T+=n.relevance),e&&(E[_.subLanguage]=n.top),w.addSublanguage(n.emitter,n.language)}else w.addText(k)}}():function(){var e,n,t,r;if(_.keywords){for(n=0,_.lexemesRe.lastIndex=0,t=_.lexemesRe.exec(k),r="";t;){r+=k.substring(n,t.index);var a=null;(e=l(_,t))?(w.addText(r),r="",T+=e[1],a=e[0],w.addKeyword(t[0],a)):r+=t[0],n=_.lexemesRe.lastIndex,t=_.lexemesRe.exec(k)}r+=k.substr(n),w.addText(r)}else w.addText(k)}(),k=""}function h(e){e.className&&w.openNode(e.className),_=Object.create(e,{parent:{value:_}})}var f={};function b(n,t){var a,i=t&&t[0];if(k+=n,null==i)return c(),0;if("begin"==f.type&&"end"==t.type&&f.index==t.index&&""===i){if(k+=s.slice(t.index,t.index+1),!o)throw(a=Error("0 width match regex")).languageName=e,a.badRule=f.rule,a;return 1}if(f=t,"begin"===t.type)return function(e){var n=e[0],t=e.rule;return t.__onBegin&&(t.__onBegin(e)||{}).ignoreMatch?function(e){return 0===_.matcher.regexIndex?(k+=e[0],1):(B=!0,0)}(n):(t&&t.endSameAsBegin&&(t.endRe=RegExp(n.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),t.skip?k+=n:(t.excludeBegin&&(k+=n),c(),t.returnBegin||t.excludeBegin||(k=n)),h(t),t.returnBegin?0:n.length)}(t);if("illegal"===t.type&&!r)throw(a=Error('Illegal lexeme "'+i+'" for mode "'+(_.className||"")+'"')).mode=_,a;if("end"===t.type){var l=function(e){var n=e[0],t=s.substr(e.index),r=function e(n,t){if(function(e,n){var t=e&&e.exec(n);return t&&0===t.index}(n.endRe,t)){for(;n.endsParent&&n.parent;)n=n.parent;return n}if(n.endsWithParent)return e(n.parent,t)}(_,t);if(r){var a=_;a.skip?k+=n:(a.returnEnd||a.excludeEnd||(k+=n),c(),a.excludeEnd&&(k=n));do{_.className&&w.closeNode(),_.skip||_.subLanguage||(T+=_.relevance),_=_.parent}while(_!==r.parent);return r.starts&&(r.endSameAsBegin&&(r.starts.endRe=r.endRe),h(r.starts)),a.returnEnd?0:n.length}}(t);if(null!=l)return l}if("illegal"===t.type&&""===i)return 1;if(A>1e5&&A>3*t.index)throw Error("potential infinite loop, way more iterations than matches");return k+=i,i.length}var v=M(e);if(!v)throw console.error(d.replace("{}",e)),Error('Unknown language: "'+e+'"');!function(e){function n(n,t){return RegExp(u(n),"m"+(e.case_insensitive?"i":"")+(t?"g":""))}class r{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=function(e){return RegExp(e.toString()+"|").exec("").length-1}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);let e=this.regexes.map(e=>e[1]);this.matcherRe=n(function(e,n){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i0&&(a+="|"),a+="(";o.length>0;){var l=t.exec(o);if(null==l){a+=o;break}a+=o.substring(0,l.index),o=o.substring(l.index+l[0].length),"\\"==l[0][0]&&l[1]?a+="\\"+(+l[1]+s):(a+=l[0],"("==l[0]&&r++)}a+=")"}return a}(e),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;let n=this.matcherRe.exec(e);if(!n)return null;let t=n.findIndex((e,n)=>n>0&&null!=e),r=this.matchIndexes[t];return Object.assign(n,r)}}class a{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];let n=new r;return this.rules.slice(e).forEach(([e,t])=>n.addRule(e,t)),n.compile(),this.multiRegexes[e]=n,n}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){let n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;let t=n.exec(e);return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&(this.regexIndex=0)),t}}function i(e){let n=e.input[e.index-1],t=e.input[e.index+e[0].length];if("."===n||"."===t)return{ignoreMatch:!0}}if(e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");!function r(s,o){s.compiled||(s.compiled=!0,s.__onBegin=null,s.keywords=s.keywords||s.beginKeywords,s.keywords&&(s.keywords=function(e,n){var t={};return"string"==typeof e?r("keyword",e):Object.keys(e).forEach((function(n){r(n,e[n])})),t;function r(e,r){n&&(r=r.toLowerCase()),r.split(" ").forEach((function(n){var r=n.split("|");t[r[0]]=[e,R(r[0],r[1])]}))}}(s.keywords,e.case_insensitive)),s.lexemesRe=n(s.lexemes||/\w+/,!0),o&&(s.beginKeywords&&(s.begin="\\b("+s.beginKeywords.split(" ").join("|")+")(?=\\b|\\s)",s.__onBegin=i),s.begin||(s.begin=/\B|\b/),s.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin),s.end||s.endsWithParent||(s.end=/\B|\b/),s.end&&(s.endRe=n(s.end)),s.terminator_end=u(s.end)||"",s.endsWithParent&&o.terminator_end&&(s.terminator_end+=(s.end?"|":"")+o.terminator_end)),s.illegal&&(s.illegalRe=n(s.illegal)),null==s.relevance&&(s.relevance=1),s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((function(e){return function(e){return e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map((function(n){return t(e,{variants:null},n)}))),e.cached_variants?e.cached_variants:function e(n){return!!n&&(n.endsWithParent||e(n.starts))}(e)?t(e,{starts:e.starts?t(e.starts):null}):Object.isFrozen(e)?t(e):e}("self"===e?s:e)}))),s.contains.forEach((function(e){r(e,s)})),s.starts&&r(s.starts,o),s.matcher=function(e){let n=new a;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminator_end&&n.addRule(e.terminator_end,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(s))}(e)}(v);var x,_=i||v,E={},w=new g.__emitter(g);!function(){for(var e=[],n=_;n!==v;n=n.parent)n.className&&e.unshift(n.className);e.forEach(e=>w.openNode(e))}();var y,O,k="",T=0,L=0,A=0,B=!1;try{for(_.matcher.considerAll();A++,B?B=!1:(_.matcher.lastIndex=L,_.matcher.considerAll()),y=_.matcher.exec(s);)O=b(s.substring(L,y.index),y),L=y.index+O;return b(s.substr(L)),w.closeAllNodes(),w.finalize(),x=w.toHTML(),{relevance:T,value:x,language:e,illegal:!1,emitter:w,top:_}}catch(n){if(n.message&&n.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:n.message,context:s.slice(L-100,L+100),mode:n.mode},sofar:x,relevance:0,value:N(s),emitter:w};if(o)return{relevance:0,value:N(s),emitter:w,language:e,top:_,errorRaised:n};throw n}}function m(e,n){n=n||g.languages||Object.keys(a);var t=function(e){const n={relevance:0,emitter:new g.__emitter(g),value:N(e),illegal:!1,top:E};return n.emitter.addText(e),n}(e),r=t;return n.filter(M).filter(k).forEach((function(n){var a=p(n,e,!1);a.language=n,a.relevance>r.relevance&&(r=a),a.relevance>t.relevance&&(r=t,t=a)})),r.language&&(t.second_best=r),t}function b(e){return g.tabReplace||g.useBR?e.replace(l,(function(e,n){return g.useBR&&"\n"===e?"
":g.tabReplace?n.replace(/\t/g,g.tabReplace):""})):e}function v(e){var n,t,r,a,s,o=function(e){var n,t=e.className+" ";if(t+=e.parentNode?e.parentNode.className:"",n=g.languageDetectRe.exec(t)){var r=M(n[1]);return r||(console.warn(d.replace("{}",n[1])),console.warn("Falling back to no-highlight mode for this block.",e)),r?n[1]:"no-highlight"}return t.split(/\s+/).find(e=>h(e)||M(e))}(e);h(o)||(T("before:highlightBlock",{block:e,language:o}),g.useBR?(n=document.createElement("div")).innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n"):n=e,s=n.textContent,r=o?f(o,s,!0):m(s),(t=y(n)).length&&((a=document.createElement("div")).innerHTML=r.value,r.value=O(t,y(a),s)),r.value=b(r.value),T("after:highlightBlock",{block:e,result:r}),e.innerHTML=r.value,e.className=function(e,n,t){var r=n?i[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),e.includes(r)||a.push(r),a.join(" ").trim()}(e.className,o,r.language),e.result={language:r.language,re:r.relevance},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.relevance}))}function x(){if(!x.called){x.called=!0;var e=document.querySelectorAll("pre code");r.forEach.call(e,v)}}const E={disableAutodetect:!0,name:"Plain text"};function M(e){return e=(e||"").toLowerCase(),a[e]||a[i[e]]}function k(e){var n=M(e);return n&&!n.disableAutodetect}function T(e,n){var t=e;s.forEach((function(e){e[t]&&e[t](n)}))}Object.assign(n,{highlight:f,highlightAuto:m,fixMarkup:b,highlightBlock:v,configure:function(e){g=w(g,e)},initHighlighting:x,initHighlightingOnLoad:function(){window.addEventListener("DOMContentLoaded",x,!1)},registerLanguage:function(e,t){var r;try{r=t(n)}catch(n){if(console.error("Language definition for '{}' could not be registered.".replace("{}",e)),!o)throw n;console.error(n),r=E}r.name||(r.name=e),a[e]=r,r.rawDefinition=t.bind(null,n),r.aliases&&r.aliases.forEach((function(n){i[n]=e}))},listLanguages:function(){return Object.keys(a)},getLanguage:M,requireLanguage:function(e){var n=M(e);if(n)return n;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))},autoDetection:k,inherit:w,addPlugin:function(e,n){s.push(e)}}),n.debugMode=function(){o=!1},n.safeMode=function(){o=!0},n.versionString="10.0.3";for(const n in _)"object"==typeof _[n]&&e(_[n]);return Object.assign(n,_),n}({})}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);hljs.registerLanguage("clojure",function(){"use strict";return function(e){var t="def defonce defprotocol defstruct defmulti defmethod defn- defn defmacro deftype defrecord",n={"builtin-name":t+" cond apply if-not if-let if not not= = < > <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy first rest cons cast coll last butlast sigs reify second ffirst fnext nfirst nnext meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"},r="[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*",a={begin:r,relevance:0},s={className:"number",begin:"[-+]?\\d+(\\.\\d+)?",relevance:0},o=e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),i=e.COMMENT("#","$",{relevance:0}),c={className:"literal",begin:/\b(true|false|nil)\b/},d={begin:"[\\[\\{]",end:"[\\]\\}]"},l={className:"comment",begin:"\\^"+r},m=e.COMMENT("\\^\\{","\\}"),u={className:"symbol",begin:"[:]{1,2}"+r},p={begin:"\\(",end:"\\)"},f={endsWithParent:!0,relevance:0},h={keywords:n,lexemes:r,className:"name",begin:r,starts:f},y=[p,o,l,m,i,u,d,s,c,a],g={beginKeywords:t,lexemes:r,end:'(\\[|\\#|\\d|"|:|\\{|\\)|\\(|$)',contains:[{className:"title",begin:r,relevance:0,excludeEnd:!0,endsParent:!0}].concat(y)};return p.contains=[e.COMMENT("comment",""),g,h,f],f.contains=y,d.contains=y,m.contains=[d],{name:"Clojure",aliases:["clj"],illegal:/\S/,contains:[p,o,l,m,i,u,d,s,c]}}}()); 7 | -------------------------------------------------------------------------------- /public/_pylon.css: -------------------------------------------------------------------------------- 1 | /* pylon.css */ 2 | 3 | hstack{display:flex;align-self:stretch;align-items:center;flex-direction:row}hstack[spacing=xl]>*{margin-right:40px}hstack[spacing=l]>*{margin-right:28px}hstack[spacing=m]>*{margin-right:20px}hstack[spacing=s]>*{margin-right:15px}hstack[spacing=xs]>*{margin-right:10px}hstack[spacing=xxs]>*{margin-right:6px}hstack[spacing]>:last-child{margin-right:0}hstack[align-y=top]{align-items:flex-start}hstack[align-y=center]{align-items:center}hstack[align-y=bottom]{align-items:flex-end}hstack[align-x=left]{justify-content:flex-start}hstack[align-x=center]{justify-content:center}hstack[align-x=right]{justify-content:flex-end}vstack{display:flex;align-self:stretch;flex-direction:column}vstack[spacing=xl]>*{margin-bottom:40px}vstack[spacing=l]>*{margin-bottom:28px}vstack[spacing=m]>*{margin-bottom:20px}vstack[spacing=s]>*{margin-bottom:15px}vstack[spacing=xs]>*{margin-bottom:10px}vstack[spacing=xxs]>*{margin-bottom:6px}vstack[spacing]>:last-child{margin-bottom:0}vstack[align-x=left]{align-items:flex-start}vstack[align-x=center]{align-items:center}vstack[align-x=right]{align-items:flex-end}vstack[align-y=top]{justify-content:flex-start}vstack[align-y=center]{justify-content:center}vstack[align-y=bottom]{justify-content:flex-end}list{display:flex;align-self:stretch;flex:1 1 auto;flex-direction:column}list>*{border-bottom:1px solid #d9ddde}list>*,list vstack{margin:0}list>:last-child{border-bottom:none}list[spacing=xl]>*{padding:40px 0}list[spacing=l]>*{padding:28px 0}list[spacing=m]>*{padding:20px 0}list[spacing=s]>*{padding:15px 0}list[spacing=xs]>*{padding:10px 0}list[spacing=xxs]>*{padding:6px 0}list[align-x=left]{align-items:flex-start}list[align-x=center]{align-items:center}list[align-x=right]{align-items:flex-end}list[align-y=top]{justify-content:flex-start}list[align-y=center]{justify-content:center}list[align-y=bottom]{justify-content:flex-end}spacer{flex:1}divider{background-color:#d9ddde;align-self:stretch}vstack>divider{margin:10px 0;height:1px}vstack[spacing]>divider{margin-top:0}hstack>divider{margin:0 10px;width:1px}hstack[spacing]>divider{margin-left:0}divider+list{margin-top:calc(-1*10px)}text{line-height:auto}text[font=title]{font-size:24px;font-weight:600}text[font=caption]{color:#999;font-size:13px}text[bold]{font-weight:700}text[underline=true],text[underline]{text-decoration:underline}text[underline=false]{text-decoration:none}view{display:flex;height:100%}.pylon{height:100%;padding:0;margin:0}[debug] *{outline:1px solid #009ddc!important}[stretch]{align-self:stretch;flex:1 1 auto}vstack[stretch]{height:100%} 4 | -------------------------------------------------------------------------------- /public/_water.css: -------------------------------------------------------------------------------- 1 | /* water.css */ 2 | 3 | @charset "UTF-8"; 4 | 5 | html, body { 6 | height: 100%; 7 | } 8 | 9 | :root { 10 | --background-body: #ffffff; 11 | --background: #efefef; 12 | --background-alt: #f7f7f7; 13 | 14 | --text-main: #363636; 15 | --text-bright: #333333; 16 | --text-muted: #999999; 17 | --text-cta: #fff; 18 | 19 | --links: #B10DC9; 20 | --focus: #B10DC9; 21 | --border: #dbdbdb; 22 | --code: #333333; 23 | 24 | --animation-duration: 0.1s; 25 | --button-hover: #dddddd; 26 | 27 | --form-placeholder: #949494; 28 | --form-text: #333333; 29 | 30 | --variable: #39a33c; 31 | --highlight: #ffff00; 32 | } 33 | 34 | @media (prefers-color-scheme: dark) { 35 | :root { 36 | --background-body: #202b38; 37 | --background: #161f27; 38 | --background-alt: #1a242f; 39 | 40 | --text-main: #dbdbdb; 41 | --text-bright: #ffffff; 42 | --text-muted: #717880; 43 | --text-cta: #fff; 44 | 45 | --links: hsla(292, 88%, 82%, 1.0); 46 | --focus: hsla(292, 88%, 82%, 1.0); 47 | --border: #1a242f; 48 | --code: #ffbe85; 49 | 50 | --animation-duration: 0.1s; 51 | --button-hover: #324759; 52 | 53 | --form-placeholder: #a9a9a9; 54 | --form-text: #ffffff; 55 | 56 | --variable: #d941e2; 57 | --highlight: #efdb43; 58 | } 59 | } 60 | 61 | body { 62 | font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 63 | line-height: 1.4; 64 | 65 | color: var(--text-main); 66 | background: var(--background-body); 67 | 68 | text-rendering: optimizeLegibility; 69 | 70 | max-width: 800px; 71 | margin: 20px auto; 72 | padding: 0 10px; 73 | 74 | overflow-x: hidden; 75 | } 76 | 77 | button, input, textarea { 78 | transition: background-color var(--animation-duration) linear, 79 | border-color var(--animation-duration) linear, 80 | color var(--animation-duration) linear, 81 | box-shadow var(--animation-duration) linear, 82 | transform var(--animation-duration) ease; 83 | } 84 | 85 | h1 { 86 | font-size: 2.2em; 87 | margin-top: 0; 88 | } 89 | 90 | h1, 91 | h2, 92 | h3, 93 | h4, 94 | h5, 95 | h6 { 96 | margin-bottom: 12px; 97 | } 98 | 99 | h1, 100 | h2, 101 | h3, 102 | h4, 103 | h5, 104 | h6, 105 | strong { 106 | color: var(--text-bright); 107 | } 108 | 109 | h1, 110 | h2, 111 | h3, 112 | h4, 113 | h5, 114 | h6, 115 | b, 116 | strong, 117 | th { 118 | font-weight: 600; 119 | } 120 | 121 | q:before { 122 | content: none; 123 | } 124 | 125 | q:after { 126 | content: none; 127 | } 128 | 129 | blockquote , q{ 130 | border-left: 4px solid var(--focus); 131 | margin: 1.5em 0em; 132 | padding: 0.5em 1em; 133 | font-style: italic; 134 | } 135 | 136 | blockquote > footer { 137 | font-style: normal; 138 | border: 0; 139 | color: inherit; 140 | } 141 | 142 | blockquote cite { 143 | font-style: normal; 144 | } 145 | 146 | address { 147 | font-style: normal; 148 | } 149 | 150 | a[href^='mailto']::before { 151 | content: '📧 '; 152 | } 153 | 154 | a[href^='tel']::before { 155 | content: '📞 '; 156 | } 157 | 158 | a[href^='sms']::before { 159 | content: '💬 '; 160 | } 161 | 162 | mark { 163 | background-color: var(--highlight); 164 | border-radius: 2px; 165 | padding: 0px 2px 0px 2px; 166 | color: #000000; 167 | } 168 | 169 | button, select, 170 | input[type='submit'], 171 | input[type='button'], 172 | input[type='checkbox'], 173 | input[type='range'], 174 | input[type='radio'] { 175 | cursor: pointer; 176 | } 177 | 178 | input:not([type='checkbox']):not([type='radio']), 179 | select { 180 | box-sizing: border-box; 181 | display: block; 182 | width: 100%; 183 | } 184 | 185 | input:not([type='submit']), 186 | button, 187 | textarea, 188 | select { 189 | color: var(--form-text); 190 | background-color: var(--background); 191 | 192 | font-family: inherit; 193 | font-size: inherit; 194 | 195 | padding: 10px; 196 | 197 | border: none; 198 | border-radius: 6px; 199 | outline: none; 200 | } 201 | 202 | input[type='submit'] { 203 | width: auto; 204 | color: var(--links); 205 | background-color: transparent; 206 | 207 | font-family: inherit; 208 | font-size: inherit; 209 | 210 | padding: 10px; 211 | 212 | border: none; 213 | border-radius: 6px; 214 | outline: none; 215 | } 216 | 217 | input[type='submit']:hover { 218 | text-decoration: underline; 219 | } 220 | 221 | button, 222 | input[type='button'] { 223 | color: var(--text-cta); 224 | background-color: var(--links); 225 | } 226 | 227 | input, 228 | select, 229 | button, 230 | textarea { 231 | -webkit-appearance: none; 232 | } 233 | 234 | textarea { 235 | width: 100%; 236 | box-sizing: border-box; 237 | resize: vertical; 238 | } 239 | 240 | select { 241 | background: var(--background) var(--select-arrow) calc(100% - 12px) 50% / 12px no-repeat; 242 | padding-right: 35px; 243 | } 244 | 245 | select::-ms-expand { 246 | display: none; 247 | } 248 | 249 | select[multiple] { 250 | padding-right: 10px; 251 | background-image: none; 252 | overflow-y: auto; 253 | } 254 | 255 | button, 256 | input[type='button'] { 257 | padding: 15px 30px; 258 | } 259 | 260 | button:hover, 261 | input[type='button']:hover { 262 | background: var(--button-hover); 263 | } 264 | 265 | input:focus, 266 | select:focus, 267 | button:focus, 268 | textarea:focus { 269 | box-shadow: 0 0 0 2px var(--focus); 270 | } 271 | 272 | input[type='checkbox'], 273 | input[type='radio'] { 274 | position: relative; 275 | width: 14px; 276 | height: 14px; 277 | display: inline-block; 278 | vertical-align: middle; 279 | margin: 0; 280 | margin-right: 2px; 281 | } 282 | 283 | input[type='radio'] { 284 | border-radius: 50%; 285 | } 286 | 287 | input[type='checkbox']:checked, 288 | input[type='radio']:checked { 289 | background: var(--button-hover); 290 | } 291 | 292 | input[type='checkbox']:checked::before, 293 | input[type='radio']:checked::before { 294 | content: '•'; 295 | display: block; 296 | position: absolute; 297 | left: 50%; 298 | top: 50%; 299 | transform: translateX(-50%) translateY(-50%); 300 | } 301 | 302 | input[type='checkbox']:checked::before { 303 | content: '✔'; 304 | transform: translateY(-50%) translateY(0.5px) translateX(-6px); 305 | } 306 | 307 | input[type='checkbox']:active, 308 | input[type='radio']:active, 309 | input[type='button']:active, 310 | input[type='range']:active, 311 | button:active { 312 | transform: translateY(2px); 313 | } 314 | 315 | input:disabled, 316 | select:disabled, 317 | button:disabled, 318 | textarea:disabled { 319 | cursor: not-allowed; 320 | opacity: 0.5; 321 | } 322 | 323 | ::-webkit-input-placeholder { 324 | color: var(--form-placeholder); 325 | } 326 | 327 | ::-moz-placeholder { 328 | color: var(--form-placeholder); 329 | } 330 | 331 | ::-ms-input-placeholder { 332 | color: var(--form-placeholder); 333 | } 334 | 335 | ::placeholder { 336 | color: var(--form-placeholder); 337 | } 338 | 339 | fieldset { 340 | border: 1px var(--border) solid; 341 | border-radius: 6px; 342 | margin: 0; 343 | margin-bottom: 6px; 344 | padding: 20px; 345 | } 346 | 347 | legend { 348 | text-align: center; 349 | font-size: 0.9em; 350 | font-weight: 600; 351 | } 352 | 353 | input[type='range'] { 354 | margin: 10px 0; 355 | padding: 10px 0; 356 | background: transparent; 357 | } 358 | 359 | input[type='range']:focus { 360 | outline: none; 361 | } 362 | 363 | input[type='range']::-webkit-slider-runnable-track { 364 | width: 100%; 365 | height: 9.5px; 366 | transition: 0.2s; 367 | background: var(--background); 368 | border-radius: 3px; 369 | } 370 | 371 | input[type='range']::-webkit-slider-thumb { 372 | box-shadow: 0px 1px 1px #000000, 0px 0px 1px #0d0d0d; 373 | height: 20px; 374 | width: 20px; 375 | border-radius: 50%; 376 | background: var(--border); 377 | -webkit-appearance: none; 378 | margin-top: -7px; 379 | } 380 | 381 | input[type='range']:focus::-webkit-slider-runnable-track { 382 | background: var(--background); 383 | } 384 | 385 | input[type='range']::-moz-range-track { 386 | width: 100%; 387 | height: 9.5px; 388 | transition: 0.2s; 389 | background: var(--background); 390 | border-radius: 3px; 391 | } 392 | 393 | input[type='range']::-moz-range-thumb { 394 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; 395 | height: 20px; 396 | width: 20px; 397 | border-radius: 50%; 398 | background: var(--border); 399 | } 400 | 401 | input[type='range']::-ms-track { 402 | width: 100%; 403 | height: 9.5px; 404 | background: transparent; 405 | border-color: transparent; 406 | border-width: 16px 0; 407 | color: transparent; 408 | } 409 | 410 | input[type='range']::-ms-fill-lower { 411 | background: var(--background); 412 | border: 0.2px solid #010101; 413 | border-radius: 3px; 414 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; 415 | } 416 | 417 | input[type='range']::-ms-fill-upper { 418 | background: var(--background); 419 | border: 0.2px solid #010101; 420 | border-radius: 3px; 421 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; 422 | } 423 | 424 | input[type='range']::-ms-thumb { 425 | box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; 426 | border: 1px solid #000000; 427 | height: 20px; 428 | width: 20px; 429 | border-radius: 50%; 430 | background: var(--border); 431 | } 432 | 433 | input[type='range']:focus::-ms-fill-lower { 434 | background: var(--background); 435 | } 436 | 437 | input[type='range']:focus::-ms-fill-upper { 438 | background: var(--background); 439 | } 440 | 441 | a { 442 | text-decoration: none; 443 | color: var(--links); 444 | } 445 | 446 | a:hover { 447 | text-decoration: underline; 448 | } 449 | 450 | samp, time { 451 | background: var(--background); 452 | color: var(--code); 453 | padding: 2.5px 5px; 454 | border-radius: 6px; 455 | font-size: 1em; 456 | } 457 | 458 | pre { 459 | margin-top: 0; 460 | } 461 | 462 | pre > code { 463 | padding-top: 10px !important; 464 | padding: 10px; 465 | display: block; 466 | overflow-x: auto; 467 | } 468 | 469 | pre > code p { 470 | margin-bottom: 0; 471 | } 472 | 473 | var { 474 | color: var(--variable); 475 | font-style: normal; 476 | font-family: monospace; 477 | } 478 | 479 | kbd { 480 | background: var(--background); 481 | border: 1px solid var(--border); 482 | border-radius: 2px; 483 | color: var(--text-main); 484 | padding: 2px 4px 2px 4px; 485 | } 486 | 487 | img { 488 | max-width: 100%; 489 | height: auto; 490 | } 491 | 492 | hr { 493 | border: none; 494 | border-top: 1px solid var(--border); 495 | } 496 | 497 | table { 498 | border-collapse: collapse; 499 | margin-bottom: 10px; 500 | width: 100%; 501 | } 502 | 503 | td, 504 | th { 505 | padding: 6px; 506 | text-align: left; 507 | } 508 | 509 | thead { 510 | border-bottom: 1px solid var(--border); 511 | } 512 | 513 | tfoot { 514 | border-top: 1px solid var(--border); 515 | } 516 | 517 | tbody tr:nth-child(even) { 518 | background-color: var(--background-alt); 519 | } 520 | 521 | details { 522 | display: flex; 523 | flex-direction: column; 524 | align-items: flex-start; 525 | background-color: var(--background-alt); 526 | padding: 10px 10px 0; 527 | margin: 1em 0; 528 | border-radius: 6px; 529 | overflow: hidden; 530 | } 531 | 532 | details[open] { 533 | padding: 10px; 534 | } 535 | 536 | details > :last-child { 537 | margin-bottom: 0; 538 | } 539 | 540 | details[open] summary { 541 | margin-bottom: 10px; 542 | } 543 | 544 | summary { 545 | display: list-item; 546 | background-color: var(--background); 547 | padding: 10px; 548 | margin: -10px -10px 0; 549 | } 550 | 551 | details > :not(summary) { 552 | margin-top: 0; 553 | } 554 | 555 | summary::-webkit-details-marker { 556 | color: var(--text-main); 557 | } 558 | 559 | footer { 560 | border-top: 1px solid var(--background); 561 | padding-top: 10px; 562 | font-size: 0.8em; 563 | color: var(--text-muted); 564 | } 565 | 566 | aside { 567 | margin: 0; 568 | border-radius: 10px; 569 | background-color: var(--background-alt); 570 | padding: 20px; 571 | } 572 | -------------------------------------------------------------------------------- /public/ace/mode-clojure.js: -------------------------------------------------------------------------------- 1 | define("ace/mode/clojure_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){var e="* *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - -> ->> .. / < <= = == > > >= >= accessor aclone add-classpath add-watch agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq zero? zipmap",t="throw try var def do fn if let loop monitor-enter monitor-exit new quote recur set!",n="true false nil",r=this.createKeywordMapper({keyword:t,"constant.language":n,"support.function":e},"identifier",!1," ");this.$rules={start:[{token:"comment",regex:";.*$"},{token:"keyword",regex:"[\\(|\\)]"},{token:"keyword",regex:"[\\'\\(]"},{token:"keyword",regex:"[\\[|\\]]"},{token:"keyword",regex:"[\\{|\\}|\\#\\{|\\#\\}]"},{token:"keyword",regex:"[\\&]"},{token:"keyword",regex:"[\\#\\^\\{]"},{token:"keyword",regex:"[\\%]"},{token:"keyword",regex:"[@]"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language",regex:"[!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+||=|!=|<=|>=|<>|<|>|!|&&]"},{token:r,regex:"[a-zA-Z_$][a-zA-Z0-9_$\\-]*\\b"},{token:"string",regex:'"',next:"string"},{token:"constant",regex:/:[^()\[\]{}'"\^%`,;\s]+/},{token:"string.regexp",regex:'/#"(?:\\.|(?:\\")|[^""\n])*"/g'}],string:[{token:"constant.language.escape",regex:"\\\\.|\\\\$"},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}]}};r.inherits(s,i),t.ClojureHighlightRules=s}),define("ace/mode/matching_parens_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\)/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\))/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingParensOutdent=i}),define("ace/mode/clojure",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/clojure_highlight_rules","ace/mode/matching_parens_outdent"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./clojure_highlight_rules").ClojureHighlightRules,o=e("./matching_parens_outdent").MatchingParensOutdent,u=function(){this.HighlightRules=s,this.$outdent=new o,this.$behaviour=this.$defaultBehaviour};r.inherits(u,i),function(){this.lineCommentStart=";",this.minorIndentFunctions=["defn","defn-","defmacro","def","deftest","testing"],this.$toIndent=function(e){return e.split("").map(function(e){return/\s/.exec(e)?e:" "}).join("")},this.$calculateIndent=function(e,t){var n=this.$getIndent(e),r=0,i,s;for(var o=e.length-1;o>=0;o--){s=e[o],s==="("?(r--,i=!0):s==="("||s==="["||s==="{"?(r--,i=!1):(s===")"||s==="]"||s==="}")&&r++;if(r<0)break}if(!(r<0&&i))return r<0&&!i?this.$toIndent(e.substring(0,o+1)):r>0?(n=n.substring(0,n.length-t.length),n):n;o+=1;var u=o,a="";for(;;){s=e[o];if(s===" "||s===" ")return this.minorIndentFunctions.indexOf(a)!==-1?this.$toIndent(e.substring(0,u-1)+t):this.$toIndent(e.substring(0,o+1));if(s===undefined)return this.$toIndent(e.substring(0,u-1)+t);a+=e[o],o++}},this.getNextLineIndent=function(e,t,n){return this.$calculateIndent(t,n)},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.$id="ace/mode/clojure",this.snippetFileId="ace/snippets/clojure"}.call(u.prototype),t.Mode=u}); (function() { 2 | window.require(["ace/mode/clojure"], function(m) { 3 | if (typeof module == "object" && typeof exports == "object" && module) { 4 | module.exports = m; 5 | } 6 | }); 7 | })(); 8 | -------------------------------------------------------------------------------- /public/alpine.min.js: -------------------------------------------------------------------------------- 1 | (function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):(a=a||self,a.Alpine=b())})(this,function(){'use strict';function a(a,b,c){return b in a?Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0}):a[b]=c,a}function b(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);b&&(d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable})),c.push.apply(c,d)}return c}function c(c){for(var d,e=1;e{"loading"==document.readyState?document.addEventListener("DOMContentLoaded",a):a()})}function e(b){for(var c=b.concat(),a=0;a{const b=o(a.name),c=b.match(_),d=b.match(/:([a-zA-Z\-:]+)/),e=b.match(/\.[^.\]]+(?=[^\]]*$)/g)||[];return{type:c?c[1]:null,value:d?d[1]:null,modifiers:e.map(a=>a.replace(".","")),expression:a.value}}).filter(a=>!b||a.type===b)}function n(a){return["disabled","checked","required","readonly","hidden","open","selected","autofocus","itemscope","multiple","novalidate","allowfullscreen","allowpaymentrequest","formnovalidate","autoplay","controls","loop","muted","playsinline","default","ismap","reversed","async","defer","nomodule"].includes(a)}function o(a){return a.startsWith("@")?a.replace("@","x-on:"):a.startsWith(":")?a.replace(":","x-bind:"):a}function p(a,b,c=!1){if(c)return b();const d=m(a,"transition"),e=m(a,"show")[0];if(e&&e.modifiers.includes("transition")){let c=e.modifiers;if(c.includes("out")&&!c.includes("in"))return b();const d=c.includes("in")&&c.includes("out");c=d?c.filter((a,b)=>bb>c.indexOf("out")):c,s(a,c,d,b)}else 0{},d)}function s(a,b,c,d){const e=c?t(b,"duration",150):t(b,"duration",150)/2,f={duration:e,origin:t(b,"origin","center"),first:{opacity:1,scale:100},second:{opacity:0,scale:t(b,"scale",95)}};u(a,b,()=>{},d,f)}function t(a,b,c){if(-1===a.indexOf(b))return c;const d=a[a.indexOf(b)+1];if(!d)return c;if("scale"===b&&!z(d))return c;if("duration"===b){let a=d.match(/([0-9]+)ms/);if(a)return a[1]}return"origin"===b&&["top","right","left","center","bottom"].includes(a[a.indexOf(b)+2])?[d,a[a.indexOf(b)+2]].join(" "):d}function u(a,b,c,d,e){const f=a.style.opacity,g=a.style.transform,h=a.style.transformOrigin,i=!b.includes("opacity")&&!b.includes("scale"),j=i||b.includes("opacity"),k=i||b.includes("scale"),l={start(){j&&(a.style.opacity=e.first.opacity),k&&(a.style.transform=`scale(${e.first.scale/100})`)},during(){k&&(a.style.transformOrigin=e.origin),a.style.transitionProperty=[j?`opacity`:``,k?`transform`:``].join(" ").trim(),a.style.transitionDuration=`${e.duration/1e3}s`,a.style.transitionTimingFunction=`cubic-bezier(0.4, 0.0, 0.2, 1)`},show(){c()},end(){j&&(a.style.opacity=e.second.opacity),k&&(a.style.transform=`scale(${e.second.scale/100})`)},hide(){d()},cleanup(){j&&(a.style.opacity=f),k&&(a.style.transform=g),k&&(a.style.transformOrigin=h),a.style.transitionProperty=null,a.style.transitionDuration=null,a.style.transitionTimingFunction=null}};y(a,l)}function v(a,b,c){const d=(b.find(a=>"enter"===a.value)||{expression:""}).expression.split(" ").filter(a=>""!==a),e=(b.find(a=>"enter-start"===a.value)||{expression:""}).expression.split(" ").filter(a=>""!==a),f=(b.find(a=>"enter-end"===a.value)||{expression:""}).expression.split(" ").filter(a=>""!==a);x(a,d,e,f,c,()=>{})}function w(a,b,c){const d=(b.find(a=>"leave"===a.value)||{expression:""}).expression.split(" ").filter(a=>""!==a),e=(b.find(a=>"leave-start"===a.value)||{expression:""}).expression.split(" ").filter(a=>""!==a),f=(b.find(a=>"leave-end"===a.value)||{expression:""}).expression.split(" ").filter(a=>""!==a);x(a,d,e,f,()=>{},c)}function x(a,b,c,d,e,f){const g=a.__x_original_classes||[],h={start(){a.classList.add(...c)},during(){a.classList.add(...b)},show(){e()},end(){a.classList.remove(...c.filter(a=>!g.includes(a))),a.classList.add(...d)},hide(){f()},cleanup(){a.classList.remove(...b.filter(a=>!g.includes(a))),a.classList.remove(...d.filter(a=>!g.includes(a)))}};y(a,h)}function y(a,b){b.start(),b.during(),requestAnimationFrame(()=>{let c=1e3*+getComputedStyle(a).transitionDuration.replace(/,.*/,"").replace("s","");b.show(),requestAnimationFrame(()=>{b.end(),setTimeout(()=>{b.hide(),a.isConnected&&b.cleanup()},c)})})}function z(a){return!isNaN(a)}function A(a,b,c,d,e){"template"!==b.tagName.toLowerCase()&&console.warn("Alpine: [x-for] directive should only be added to