init commit

This commit is contained in:
2025-07-26 03:35:08 -04:00
commit 378c8e09fb
24 changed files with 1733 additions and 0 deletions

5
.formatter.exs Normal file
View File

@@ -0,0 +1,5 @@
[
import_deps: [],
plugins: [Phoenix.LiveView.HTMLFormatter],
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

26
.gitignore vendored Normal file
View File

@@ -0,0 +1,26 @@
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where third-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
# Ignore package tarball (built via "mix hex.build").
tableau_new-*.tar
# Temporary files, for example, from tests.
/tmp/

28
README.md Normal file
View File

@@ -0,0 +1,28 @@
# llmex
## Getting Started
Once you bootstrap and enter your project, fetch your dependencies and start the build server. The server is available at http://localhost:4999
```shell
cd llmex
mix deps.get
mix tableau.server
```
## Draft Posts and WIP Pages
Posts and pages that are not ready for production can be saved to the `_drafts` and `_wip` directories respectively.
These are controlled via application configuration, as seen in `config/dev.exs` and `config/prod.exs`
## Production Builds
To build for production, run the `mix build` alias to build your site and compile any assets (depends on what asset you chose when generating your site).
Running your build with `MIX_ENV=prod` is important so that the live reload JS script is not loaded, and also allows you to configure your app differently in dev vs prod, like showing future posts in dev, but not in prod.
```shell
MIX_ENV=prod mix build
```

0
_pages/.keep Normal file
View File

0
_posts/.keep Normal file
View File

0
_site/.keep Normal file
View File

669
_site/css/simple.css Normal file
View File

@@ -0,0 +1,669 @@
/* Copied from the origin (https://github.com/artalar/mono) for fast interaction and fixing. Reatom docs is a good playground form mono. */
.mono-all,
.mono,
.mono-all *,
.mono:before,
.mono-all *:before,
.mono:after,
.mono-all *:after {
color: var(--mono-main, #111111);
background-color: var(--mono-back, #eeeeee);
font-family: "Roboto Mono", monospace;
line-height: 2.5rem;
font-size: 1.2rem;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.mono::selection,
.mono-all *::selection {
color: var(--mono-back);
background-color: var(--mono-main);
}
a.mono,
.mono-all a {
position: relative;
/* margin-right: 0.5rem; */
text-decoration: none;
outline: none;
border-bottom: 0.25rem solid var(--mono-main);
}
a.mono:hover,
.mono-all a:hover {
border-bottom-width: 0.5rem;
}
a.mono:visited,
.mono-all a:visited {
border-bottom: 0.1rem solid var(--mono-main);
}
a.mono:after,
.mono-all a:after {
content: "00";
color: transparent;
background-color: var(--mono-main);
clip-path: polygon(25% 25%, 75% 50%, 25% 75%);
}
a.mono:focus:after,
.mono-all a:focus:after {
clip-path: polygon(
0 0,
20% 20%,
20% 80%,
80% 50%,
20% 20%,
0 0,
100% 0,
100% 100%,
0 100%
);
background-color: unset;
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 5px
);
}
a.mono:active:after,
.mono-all a:active:after {
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 7px
);
}
b.mono,
.mono-all b {
font-weight: 600;
border: 0.2rem solid var(--mono-main);
}
body.mono,
body.mono-all,
.mono-all body {
margin: 0;
position: relative;
min-width: min(calc(100vw + 20rem), 85rem);
scroll-snap-type: x mandatory;
display: flex;
}
main.mono,
.mono-all main {
scroll-snap-align: start;
margin: auto;
width: min(100vw, 65rem);
display: flex;
flex-direction: column;
padding: 0 1rem;
}
aside.mono,
.mono-all aside {
position: sticky;
top: 0;
display: flex;
flex-direction: column;
width: 20rem;
min-width: 20rem;
max-width: 20rem;
max-height: 100vh;
overflow-y: scroll;
padding: 1rem;
}
/* TODO: stick it bottom */
footer.mono,
.mono-all footer {
width: 100%;
display: flex;
justify-content: center;
margin-top: auto;
padding: 1rem;
border-top: 1px solid var(--mono-main);
}
blockquote.mono,
.mono-all blockquote {
position: relative;
margin: 2rem;
margin-left: 3rem;
}
blockquote.mono:before,
.mono-all blockquote:before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 1rem;
width: 3rem;
background-color: var(--mono-main);
clip-path: polygon(
0 0,
calc(100% - 0.25rem) 0,
calc(100% - 0.25rem) 0.25rem,
100% 0.25rem,
100% calc(100% - 0.25rem),
1rem calc(100% - 0.25rem),
1rem 100%,
0.25rem 100%,
0.25rem calc(100% - 0.25rem),
0 calc(100% - 0.25rem)
);
}
button.mono,
.mono-all button {
position: relative;
outline: none;
margin-top: 0.4rem;
margin-bottom: 0.2rem;
border: 0.2rem solid var(--mono-main);
border-top: none;
height: 2rem;
min-width: 5rem;
color: var(--mono-main);
background-color: var(--mono-back);
font-weight: 600;
display: inline-flex;
justify-content: center;
align-items: center;
}
button.mono + button.mono,
.mono-all button + button {
margin-left: 1rem;
}
button.mono:before,
.mono-all button:before {
content: "";
position: absolute;
top: -0.4rem;
left: -0.2rem;
width: calc(100% + 0.4rem);
height: 0.8rem;
background-color: var(--mono-main);
clip-path: polygon(
0 30%,
calc(100% - 0.8rem) 30%,
calc(100% - 0.8rem) 0%,
100% 50%,
calc(100% - 0.8rem) 100%,
calc(100% - 0.8rem) 70%,
0 70%
);
}
button.mono:focus:after,
.mono-all button:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.8rem);
height: calc(100% + 0.8rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 5px
);
clip-path: polygon(
calc(100% - 0.5rem) 0.25rem,
calc(100% - 0.5rem) calc(100% - 0.5rem),
0.25rem calc(100% - 0.5rem),
0.25rem 100%,
100% 100%,
100% 0.25rem
);
}
button.mono:active:after,
.mono-all button:active:after {
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 7px
);
}
:not(pre) > code.mono,
.mono-all :not(pre) > code {
border: 1px dashed var(--mono-main);
padding: 0 0.25rem;
}
:not(pre) > code.mono:before,
.mono-all :not(pre) > code:before,
:not(pre) > code.mono:after,
.mono-all :not(pre) > code:after {
font-weight: bold;
color: var(--mono-back);
background-color: var(--mono-main);
/* fix empty space when scale */
box-shadow: 0 0 0 1px var(--mono-main);
/* FIXME: does not work */
transform: scaleX(0.5);
}
details.mono,
.mono-all details {
margin: 1rem 0;
padding: 1rem;
padding-left: 1.5rem;
border: 0.2rem solid var(--mono-main);
overflow-x: hidden;
}
details[open].mono summary.mono,
.mono-all details[open] summary {
margin-bottom: 0.5rem;
}
details[open].mono summary.mono::before,
.mono-all details[open] summary::before {
transform: rotate(180deg);
}
h1.mono,
.mono-all h1,
h2.mono,
.mono-all h2,
h3.mono,
.mono-all h3,
h4.mono,
.mono-all h4 {
border-left: 4px solid var(--mono-main);
border-top: 2px solid var(--mono-main);
padding-top: 0.2em;
padding-left: 0.3em;
margin: 3rem 0 1rem;
}
h1.mono,
.mono-all h1 {
margin-top: 2rem;
font-size: 2.2em;
}
h2.mono,
.mono-all h2 {
font-size: 1.6em;
}
h3.mono,
.mono-all h3 {
font-size: 1.2em;
}
input[type="checkbox"].mono,
.mono-all input[type="checkbox"] {
position: relative;
top: 0.5em;
margin: 0;
width: 1.5rem;
height: 1.5rem;
margin-right: 0.5rem;
margin-bottom: 1rem;
border-radius: 50%;
box-shadow: inset 0 0 0 1rem var(--mono-main);
outline: none;
cursor: pointer;
}
input[type="checkbox"].mono:before,
.mono-all input[type="checkbox"]:before {
position: absolute;
content: "";
left: 0.125rem;
top: 0.125rem;
width: 1.25rem;
height: 1.25rem;
background-color: var(--mono-back);
border: 0.25rem solid var(--mono-back);
}
input[type="checkbox"].mono:checked:before,
.mono-all input[type="checkbox"]:checked:before {
background-color: var(--mono-main);
}
input[type="checkbox"].mono:focus:after,
.mono-all input[type="checkbox"]:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.4rem);
height: calc(100% + 0.4rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 2px,
var(--mono-main) 2px 3px
);
clip-path: polygon(
calc(100% - 0.4rem) 0.2rem,
calc(100% - 0.4rem) calc(100% - 0.4rem),
0.2rem calc(100% - 0.4rem),
0.2rem 100%,
100% 100%,
100% 0.2rem
);
}
input[type="checkbox"].mono:active:after,
.mono-all input[type="checkbox"]:active:after {
background-image: repeating-linear-gradient(
-45deg,
transparent 0 2px,
var(--mono-main) 2px 4px
);
}
input[type="color"].mono,
.mono-all input[type="color"] {
position: relative;
outline: none;
height: 2.5rem;
}
input[type="color"].mono:focus:after,
.mono-all input[type="color"]:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.6rem);
height: calc(100% + 0.6rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 5px
);
clip-path: polygon(
calc(100% - 0.5rem) 0.25rem,
calc(100% - 0.5rem) calc(100% - 0.5rem),
0.25rem calc(100% - 0.5rem),
0.25rem 100%,
100% 100%,
100% 0.25rem
);
}
input[type="color"].mono:active:after,
.mono-all input[type="color"]:active:after {
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 7px
);
}
input[type="radio"].mono,
.mono-all input[type="radio"] {
position: relative;
top: 0.5em;
margin: 0;
width: 1.5rem;
height: 1.5rem;
margin-right: 0.5rem;
margin-bottom: 1rem;
border-radius: 50%;
box-shadow: inset 0 0 0 1rem var(--mono-main);
outline: none;
cursor: pointer;
}
input[type="radio"].mono:before,
.mono-all input[type="radio"]:before {
position: absolute;
content: "";
left: 0.125rem;
top: 0.125rem;
width: 1.25rem;
height: 1.25rem;
background-color: var(--mono-back);
border: 0.15rem solid var(--mono-back);
border-radius: 50%;
}
input[type="radio"].mono:checked:before,
.mono-all input[type="radio"]:checked:before {
background-color: var(--mono-main);
}
input[type="radio"].mono:focus:after,
.mono-all input[type="radio"]:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.4rem);
height: calc(100% + 0.4rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 2px,
var(--mono-main) 2px 3px
);
clip-path: polygon(
calc(100% - 0.4rem) 0.2rem,
calc(100% - 0.4rem) calc(100% - 0.4rem),
0.2rem calc(100% - 0.4rem),
0.2rem 100%,
100% 100%,
100% 0.2rem
);
}
input[type="range"].mono,
.mono-all input[type="range"] {
appearance: none;
-webkit-appearance: none;
outline: none;
position: relative;
border: 0.2rem solid var(--mono-main);
padding: 0.8rem 0.5rem;
height: 1.5rem;
width: 20rem;
}
input[type="range"].mono::-webkit-slider-runnable-track,
.mono-all input[type="range"]::-webkit-slider-runnable-track {
width: 100%;
height: 0.2rem;
cursor: pointer;
background: var(--mono-main);
}
input[type="range"].mono::-webkit-slider-thumb,
.mono-all input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
border: 0.2rem solid var(--mono-main);
height: 1rem;
width: 1rem;
background: var(--mono-back);
cursor: pointer;
margin-top: -0.4rem;
}
input[type="range"].mono:active::-webkit-slider-thumb,
.mono-all input[type="range"]:active::-webkit-slider-thumb {
background-color: var(--mono-main);
}
input[type="range"].mono:focus:after,
.mono-all input[type="range"]:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.7rem);
height: calc(100% + 0.7rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 5px
);
clip-path: polygon(
calc(100% - 0.5rem) 0.25rem,
calc(100% - 0.5rem) calc(100% - 0.5rem),
0.25rem calc(100% - 0.5rem),
0.25rem 100%,
100% 100%,
100% 0.25rem
);
}
fieldset.mono,
.mono-all fieldset {
border: 0.2rem solid var(--mono-main);
}
legend.mono,
.mono-all legend {
font-size: 1.4em;
}
li.mono,
.mono-all li {
list-style: none;
position: relative;
}
li.mono + li.mono,
.mono-all li + li {
margin-top: 1.5rem;
}
li.mono:before,
.mono-all li:before {
content: "";
position: absolute;
top: 0.75rem;
left: -1.5rem;
width: 1rem;
height: 1rem;
color: var(--mono-back);
background-color: var(--mono-main);
/* box-shadow: 0.4rem -0.4rem 0 -0.1rem var(--mono-main); */
}
p.mono:before,
.mono-all p:before {
content: " ";
width: 1.5rem;
display: inline-block;
}
pre.mono,
.mono-all pre {
position: relative;
flex-shrink: 0;
padding: 0.5rem 1rem;
margin: 1.5rem 0;
border: 2px dashed var(--mono-main);
overflow-x: scroll;
line-height: 2rem;
}
pre.mono,
pre.mono *,
.mono-all pre,
.mono-all pre * {
line-height: 2rem;
background-color: transparent;
}
/* pre.mono:hover:before,
.mono-all pre:hover:before {
content: '';
position: absolute;
top: 0.5rem;
right: 0.5rem;
width: 2.5rem;
height: 2.5rem;
background-color: var(--mono-main);
opacity: 0.7;
clip-path: polygon(
0 0,
0 65%,
65% 65%,
65% 0,
100% 0,
100% 100%,
35% 100%,
35% 35%,
100% 35%,
100% 0
);
} */
strong.mono,
.mono-all strong {
font-weight: normal;
box-shadow:
inset 0 -0.2em var(--mono-main),
0 0.25em 0 0 var(--mono-main);
}
summary.mono,
.mono-all summary {
display: inline;
position: relative;
margin-right: 100%;
list-style: none;
font-size: 1.4rem;
outline: none;
}
summary.mono:before,
.mono-all summary:before {
content: "";
position: absolute;
top: -0.5rem;
left: -1.2rem;
width: 0.8rem;
height: calc(100% + 1rem);
background-color: var(--mono-main);
clip-path: polygon(
25% 0,
25% calc(100% - 0.6rem),
0 calc(100% - 0.6rem),
50% 100%,
100% calc(100% - 0.6rem),
75% calc(100% - 0.6rem),
75% 0
);
}
summary.mono:focus:after,
.mono-all summary:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.8rem);
height: calc(100% + 0.4rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 5px
);
clip-path: polygon(
calc(100% - 0.5rem) 0.25rem,
calc(100% - 0.5rem) calc(100% - 0.5rem),
0.25rem calc(100% - 0.5rem),
0.25rem 100%,
100% 100%,
100% 0.25rem
);
}
summary.mono:active:after,
.mono-all summary:active:after {
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 7px
);
}
table.mono,
.mono-all table {
display: block;
width: 100%;
width: max-content;
max-width: 100%;
overflow: auto;
}
td.mono,
.mono-all td,
th.mono,
.mono-all th {
border-top: 0.5rem solid var(--mono-main);
padding: 0 1rem;
}
ul.mono,
.mono-all ul {
padding-left: 1.5rem;
}

10
_site/feed.xml Normal file
View File

@@ -0,0 +1,10 @@
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="http://localhost:4999/feed.xml" rel="self" type="application/rss+xml" />
<title>llmex</title>
<link>http://localhost:4999</link>
<description>My beautiful website</description>
<language>en-us</language>
<generator>Tableau v0.26.0</generator>
</channel>
</rss>

76
_site/index.html Normal file
View File

@@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http_equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>
Elixir.Llmex
</title>
<link rel="stylesheet" href="/css/simple.css">
</head>
<body>
<main>
<p>
hello, world!
</p>
</main>
</body>
<script>
function log(message) {
if (true) {
console.log(`[web_dev_utils] ${message}`)
}
}
function connect() {
try {
window.socket = new WebSocket('ws://' + location.host + '/ws');
window.socket.onmessage = function(e) {
if (e.data === "reload") {
log("reloading!");
location.reload();
} else if (e.data === "subscribed") {
log("connected and subscribed!");
}
}
window.socket.onopen = () => {
waitForConnection(() => {
log("sending 'subscribe' message");
window.socket.send("subscribe")
}
, 300);
};
window.socket.onclose = () => {
setTimeout(() => connect(), 500);
};
function waitForConnection(callback, interval) {
log("waiting for connection!")
if (window.socket.readyState === 1) {
callback();
} else {
log("setting a timeout")
setTimeout(() => waitForConnection(callback, interval), interval);
}
}
} catch (e) {
log(e);
setTimeout(() => connect(), 500);
}
}
log("about to connect");
connect();
</script>
</html>

1
_site/sitemap.xml Normal file
View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"><url><loc>http://localhost:4999/</loc></url></urlset>

48
config/config.exs Normal file
View File

@@ -0,0 +1,48 @@
import Config
config :tableau, :reloader,
patterns: [
~r"^lib/.*.ex",
~r"^(_posts|_pages)/.*.md",~r"^extra/.*.(css|js)"
]
config :web_dev_utils, :reload_log, true
# uncomment this if you use something like ngrok
# config :web_dev_utils, :reload_url, "'wss://' + location.host + '/ws'"
config :tableau, :config,
url: "http://localhost:4999",
markdown: [
mdex: [
extension: [
table: true,
header_ids: "",
tasklist: true,
strikethrough: true,
autolink: true,
alerts: true,
footnotes: true
],
render: [unsafe: true],
syntax_highlight: [formatter: {:html_inline, theme: "neovim_dark"}]
]
]
config :tableau, Tableau.PageExtension, enabled: true
config :tableau, Tableau.PostExtension, enabled: true
config :tableau, Tableau.DataExtension, enabled: true
config :tableau, Tableau.SitemapExtension, enabled: true
config :tableau, Tableau.RSSExtension,
enabled: true,
title: "llmex",
description: "My beautiful website"
config :elixir, :time_zone_database, Tz.TimeZoneDatabase
import_config "#{Mix.env()}.exs"

4
config/dev.exs Normal file
View File

@@ -0,0 +1,4 @@
import Config
config :tableau, Tableau.PageExtension, dir: ["_pages", "_wip"]
config :tableau, Tableau.PostExtension, future: true, dir: ["_posts", "_drafts"]

5
config/prod.exs Normal file
View File

@@ -0,0 +1,5 @@
import Config
config :tableau, :config, url: "https://example.com"
config :tableau, Tableau.PostExtension, future: false, dir: ["_posts"]
config :tableau, Tableau.PageExtension, dir: ["_pages"]

1
config/test.exs Normal file
View File

@@ -0,0 +1 @@
import Config

0
extra/.keep Normal file
View File

669
extra/css/simple.css Normal file
View File

@@ -0,0 +1,669 @@
/* Copied from the origin (https://github.com/artalar/mono) for fast interaction and fixing. Reatom docs is a good playground form mono. */
.mono-all,
.mono,
.mono-all *,
.mono:before,
.mono-all *:before,
.mono:after,
.mono-all *:after {
color: var(--mono-main, #111111);
background-color: var(--mono-back, #eeeeee);
font-family: "Roboto Mono", monospace;
line-height: 2.5rem;
font-size: 1.2rem;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.mono::selection,
.mono-all *::selection {
color: var(--mono-back);
background-color: var(--mono-main);
}
a.mono,
.mono-all a {
position: relative;
/* margin-right: 0.5rem; */
text-decoration: none;
outline: none;
border-bottom: 0.25rem solid var(--mono-main);
}
a.mono:hover,
.mono-all a:hover {
border-bottom-width: 0.5rem;
}
a.mono:visited,
.mono-all a:visited {
border-bottom: 0.1rem solid var(--mono-main);
}
a.mono:after,
.mono-all a:after {
content: "00";
color: transparent;
background-color: var(--mono-main);
clip-path: polygon(25% 25%, 75% 50%, 25% 75%);
}
a.mono:focus:after,
.mono-all a:focus:after {
clip-path: polygon(
0 0,
20% 20%,
20% 80%,
80% 50%,
20% 20%,
0 0,
100% 0,
100% 100%,
0 100%
);
background-color: unset;
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 5px
);
}
a.mono:active:after,
.mono-all a:active:after {
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 7px
);
}
b.mono,
.mono-all b {
font-weight: 600;
border: 0.2rem solid var(--mono-main);
}
body.mono,
body.mono-all,
.mono-all body {
margin: 0;
position: relative;
min-width: min(calc(100vw + 20rem), 85rem);
scroll-snap-type: x mandatory;
display: flex;
}
main.mono,
.mono-all main {
scroll-snap-align: start;
margin: auto;
width: min(100vw, 65rem);
display: flex;
flex-direction: column;
padding: 0 1rem;
}
aside.mono,
.mono-all aside {
position: sticky;
top: 0;
display: flex;
flex-direction: column;
width: 20rem;
min-width: 20rem;
max-width: 20rem;
max-height: 100vh;
overflow-y: scroll;
padding: 1rem;
}
/* TODO: stick it bottom */
footer.mono,
.mono-all footer {
width: 100%;
display: flex;
justify-content: center;
margin-top: auto;
padding: 1rem;
border-top: 1px solid var(--mono-main);
}
blockquote.mono,
.mono-all blockquote {
position: relative;
margin: 2rem;
margin-left: 3rem;
}
blockquote.mono:before,
.mono-all blockquote:before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 1rem;
width: 3rem;
background-color: var(--mono-main);
clip-path: polygon(
0 0,
calc(100% - 0.25rem) 0,
calc(100% - 0.25rem) 0.25rem,
100% 0.25rem,
100% calc(100% - 0.25rem),
1rem calc(100% - 0.25rem),
1rem 100%,
0.25rem 100%,
0.25rem calc(100% - 0.25rem),
0 calc(100% - 0.25rem)
);
}
button.mono,
.mono-all button {
position: relative;
outline: none;
margin-top: 0.4rem;
margin-bottom: 0.2rem;
border: 0.2rem solid var(--mono-main);
border-top: none;
height: 2rem;
min-width: 5rem;
color: var(--mono-main);
background-color: var(--mono-back);
font-weight: 600;
display: inline-flex;
justify-content: center;
align-items: center;
}
button.mono + button.mono,
.mono-all button + button {
margin-left: 1rem;
}
button.mono:before,
.mono-all button:before {
content: "";
position: absolute;
top: -0.4rem;
left: -0.2rem;
width: calc(100% + 0.4rem);
height: 0.8rem;
background-color: var(--mono-main);
clip-path: polygon(
0 30%,
calc(100% - 0.8rem) 30%,
calc(100% - 0.8rem) 0%,
100% 50%,
calc(100% - 0.8rem) 100%,
calc(100% - 0.8rem) 70%,
0 70%
);
}
button.mono:focus:after,
.mono-all button:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.8rem);
height: calc(100% + 0.8rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 5px
);
clip-path: polygon(
calc(100% - 0.5rem) 0.25rem,
calc(100% - 0.5rem) calc(100% - 0.5rem),
0.25rem calc(100% - 0.5rem),
0.25rem 100%,
100% 100%,
100% 0.25rem
);
}
button.mono:active:after,
.mono-all button:active:after {
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 7px
);
}
:not(pre) > code.mono,
.mono-all :not(pre) > code {
border: 1px dashed var(--mono-main);
padding: 0 0.25rem;
}
:not(pre) > code.mono:before,
.mono-all :not(pre) > code:before,
:not(pre) > code.mono:after,
.mono-all :not(pre) > code:after {
font-weight: bold;
color: var(--mono-back);
background-color: var(--mono-main);
/* fix empty space when scale */
box-shadow: 0 0 0 1px var(--mono-main);
/* FIXME: does not work */
transform: scaleX(0.5);
}
details.mono,
.mono-all details {
margin: 1rem 0;
padding: 1rem;
padding-left: 1.5rem;
border: 0.2rem solid var(--mono-main);
overflow-x: hidden;
}
details[open].mono summary.mono,
.mono-all details[open] summary {
margin-bottom: 0.5rem;
}
details[open].mono summary.mono::before,
.mono-all details[open] summary::before {
transform: rotate(180deg);
}
h1.mono,
.mono-all h1,
h2.mono,
.mono-all h2,
h3.mono,
.mono-all h3,
h4.mono,
.mono-all h4 {
border-left: 4px solid var(--mono-main);
border-top: 2px solid var(--mono-main);
padding-top: 0.2em;
padding-left: 0.3em;
margin: 3rem 0 1rem;
}
h1.mono,
.mono-all h1 {
margin-top: 2rem;
font-size: 2.2em;
}
h2.mono,
.mono-all h2 {
font-size: 1.6em;
}
h3.mono,
.mono-all h3 {
font-size: 1.2em;
}
input[type="checkbox"].mono,
.mono-all input[type="checkbox"] {
position: relative;
top: 0.5em;
margin: 0;
width: 1.5rem;
height: 1.5rem;
margin-right: 0.5rem;
margin-bottom: 1rem;
border-radius: 50%;
box-shadow: inset 0 0 0 1rem var(--mono-main);
outline: none;
cursor: pointer;
}
input[type="checkbox"].mono:before,
.mono-all input[type="checkbox"]:before {
position: absolute;
content: "";
left: 0.125rem;
top: 0.125rem;
width: 1.25rem;
height: 1.25rem;
background-color: var(--mono-back);
border: 0.25rem solid var(--mono-back);
}
input[type="checkbox"].mono:checked:before,
.mono-all input[type="checkbox"]:checked:before {
background-color: var(--mono-main);
}
input[type="checkbox"].mono:focus:after,
.mono-all input[type="checkbox"]:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.4rem);
height: calc(100% + 0.4rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 2px,
var(--mono-main) 2px 3px
);
clip-path: polygon(
calc(100% - 0.4rem) 0.2rem,
calc(100% - 0.4rem) calc(100% - 0.4rem),
0.2rem calc(100% - 0.4rem),
0.2rem 100%,
100% 100%,
100% 0.2rem
);
}
input[type="checkbox"].mono:active:after,
.mono-all input[type="checkbox"]:active:after {
background-image: repeating-linear-gradient(
-45deg,
transparent 0 2px,
var(--mono-main) 2px 4px
);
}
input[type="color"].mono,
.mono-all input[type="color"] {
position: relative;
outline: none;
height: 2.5rem;
}
input[type="color"].mono:focus:after,
.mono-all input[type="color"]:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.6rem);
height: calc(100% + 0.6rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 5px
);
clip-path: polygon(
calc(100% - 0.5rem) 0.25rem,
calc(100% - 0.5rem) calc(100% - 0.5rem),
0.25rem calc(100% - 0.5rem),
0.25rem 100%,
100% 100%,
100% 0.25rem
);
}
input[type="color"].mono:active:after,
.mono-all input[type="color"]:active:after {
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 7px
);
}
input[type="radio"].mono,
.mono-all input[type="radio"] {
position: relative;
top: 0.5em;
margin: 0;
width: 1.5rem;
height: 1.5rem;
margin-right: 0.5rem;
margin-bottom: 1rem;
border-radius: 50%;
box-shadow: inset 0 0 0 1rem var(--mono-main);
outline: none;
cursor: pointer;
}
input[type="radio"].mono:before,
.mono-all input[type="radio"]:before {
position: absolute;
content: "";
left: 0.125rem;
top: 0.125rem;
width: 1.25rem;
height: 1.25rem;
background-color: var(--mono-back);
border: 0.15rem solid var(--mono-back);
border-radius: 50%;
}
input[type="radio"].mono:checked:before,
.mono-all input[type="radio"]:checked:before {
background-color: var(--mono-main);
}
input[type="radio"].mono:focus:after,
.mono-all input[type="radio"]:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.4rem);
height: calc(100% + 0.4rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 2px,
var(--mono-main) 2px 3px
);
clip-path: polygon(
calc(100% - 0.4rem) 0.2rem,
calc(100% - 0.4rem) calc(100% - 0.4rem),
0.2rem calc(100% - 0.4rem),
0.2rem 100%,
100% 100%,
100% 0.2rem
);
}
input[type="range"].mono,
.mono-all input[type="range"] {
appearance: none;
-webkit-appearance: none;
outline: none;
position: relative;
border: 0.2rem solid var(--mono-main);
padding: 0.8rem 0.5rem;
height: 1.5rem;
width: 20rem;
}
input[type="range"].mono::-webkit-slider-runnable-track,
.mono-all input[type="range"]::-webkit-slider-runnable-track {
width: 100%;
height: 0.2rem;
cursor: pointer;
background: var(--mono-main);
}
input[type="range"].mono::-webkit-slider-thumb,
.mono-all input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
border: 0.2rem solid var(--mono-main);
height: 1rem;
width: 1rem;
background: var(--mono-back);
cursor: pointer;
margin-top: -0.4rem;
}
input[type="range"].mono:active::-webkit-slider-thumb,
.mono-all input[type="range"]:active::-webkit-slider-thumb {
background-color: var(--mono-main);
}
input[type="range"].mono:focus:after,
.mono-all input[type="range"]:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.7rem);
height: calc(100% + 0.7rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 5px
);
clip-path: polygon(
calc(100% - 0.5rem) 0.25rem,
calc(100% - 0.5rem) calc(100% - 0.5rem),
0.25rem calc(100% - 0.5rem),
0.25rem 100%,
100% 100%,
100% 0.25rem
);
}
fieldset.mono,
.mono-all fieldset {
border: 0.2rem solid var(--mono-main);
}
legend.mono,
.mono-all legend {
font-size: 1.4em;
}
li.mono,
.mono-all li {
list-style: none;
position: relative;
}
li.mono + li.mono,
.mono-all li + li {
margin-top: 1.5rem;
}
li.mono:before,
.mono-all li:before {
content: "";
position: absolute;
top: 0.75rem;
left: -1.5rem;
width: 1rem;
height: 1rem;
color: var(--mono-back);
background-color: var(--mono-main);
/* box-shadow: 0.4rem -0.4rem 0 -0.1rem var(--mono-main); */
}
p.mono:before,
.mono-all p:before {
content: " ";
width: 1.5rem;
display: inline-block;
}
pre.mono,
.mono-all pre {
position: relative;
flex-shrink: 0;
padding: 0.5rem 1rem;
margin: 1.5rem 0;
border: 2px dashed var(--mono-main);
overflow-x: scroll;
line-height: 2rem;
}
pre.mono,
pre.mono *,
.mono-all pre,
.mono-all pre * {
line-height: 2rem;
background-color: transparent;
}
/* pre.mono:hover:before,
.mono-all pre:hover:before {
content: '';
position: absolute;
top: 0.5rem;
right: 0.5rem;
width: 2.5rem;
height: 2.5rem;
background-color: var(--mono-main);
opacity: 0.7;
clip-path: polygon(
0 0,
0 65%,
65% 65%,
65% 0,
100% 0,
100% 100%,
35% 100%,
35% 35%,
100% 35%,
100% 0
);
} */
strong.mono,
.mono-all strong {
font-weight: normal;
box-shadow:
inset 0 -0.2em var(--mono-main),
0 0.25em 0 0 var(--mono-main);
}
summary.mono,
.mono-all summary {
display: inline;
position: relative;
margin-right: 100%;
list-style: none;
font-size: 1.4rem;
outline: none;
}
summary.mono:before,
.mono-all summary:before {
content: "";
position: absolute;
top: -0.5rem;
left: -1.2rem;
width: 0.8rem;
height: calc(100% + 1rem);
background-color: var(--mono-main);
clip-path: polygon(
25% 0,
25% calc(100% - 0.6rem),
0 calc(100% - 0.6rem),
50% 100%,
100% calc(100% - 0.6rem),
75% calc(100% - 0.6rem),
75% 0
);
}
summary.mono:focus:after,
.mono-all summary:focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: calc(100% + 0.8rem);
height: calc(100% + 0.4rem);
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 5px
);
clip-path: polygon(
calc(100% - 0.5rem) 0.25rem,
calc(100% - 0.5rem) calc(100% - 0.5rem),
0.25rem calc(100% - 0.5rem),
0.25rem 100%,
100% 100%,
100% 0.25rem
);
}
summary.mono:active:after,
.mono-all summary:active:after {
background-image: repeating-linear-gradient(
-45deg,
transparent 0 3px,
var(--mono-main) 3px 7px
);
}
table.mono,
.mono-all table {
display: block;
width: 100%;
width: max-content;
max-width: 100%;
overflow: auto;
}
td.mono,
.mono-all td,
th.mono,
.mono-all th {
border-top: 0.5rem solid var(--mono-main);
padding: 0 1rem;
}
ul.mono,
.mono-all ul {
padding-left: 1.5rem;
}

5
formatter.exs Normal file
View File

@@ -0,0 +1,5 @@
[
import_deps: [],
plugins: [Phoenix.LiveView.HTMLFormatter],
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

View File

@@ -0,0 +1,10 @@
defmodule Llmex.PostLayout do
use Tableau.Layout, layout: Llmex.RootLayout
use Phoenix.Component
def template(assigns) do
~H"""
<%= {:safe, render(@inner_content)} %>
"""
end
end

View File

@@ -0,0 +1,38 @@
defmodule Llmex.RootLayout do
use Tableau.Layout
use Phoenix.Component
def template(assigns) do
~H"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http_equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>
<%= [@page[:title], Llmex]
|> Enum.filter(& &1)
|> Enum.intersperse("|")
|> Enum.join(" ") %>
</title>
<link rel="stylesheet" href="/css/simple.css" />
</head>
<body>
<main>
<%= render @inner_content %>
</main>
</body>
<%= if Mix.env() == :dev do %>
<%= Phoenix.HTML.raw(Tableau.live_reload(assigns)) %>
<% end %>
</html>
"""
|> Phoenix.HTML.Safe.to_iodata()
end
end

45
lib/mix/tasks/post.ex Normal file
View File

@@ -0,0 +1,45 @@
defmodule Mix.Tasks.Llmex.Gen.Post do
use Mix.Task
@shortdoc "Generate a new post"
@moduledoc @shortdoc
@doc false
def run(argv) do
if argv == [] do
raise "Missing argument: Filename"
end
post_title = Enum.join(argv, " ")
post_date = Date.utc_today()
post_time = "01:00:00 -04:00"
file_name =
post_title
|> String.replace(" ", "-")
|> String.replace("_", "-")
|> String.replace(~r/[^[:alnum:]\/\-.]/, "")
|> String.downcase()
file_path =
"./_posts/#{post_date}-#{file_name}.md"
if File.exists?(file_path) do
raise "File already exists"
end
front_matter = """
---
layout: Llmex.PostLayout
title: \"#{post_title}\"
date: #{post_date} #{post_time}
permalink: /:title/
---
"""
File.write!(file_path, front_matter)
Mix.shell().info("Succesfully created #{file_path}!")
end
end

15
lib/pages/home_page.ex Normal file
View File

@@ -0,0 +1,15 @@
defmodule Llmex.HomePage do
use Tableau.Page,
layout: Llmex.RootLayout,
permalink: "/"
use Phoenix.Component
def template(assigns) do
~H"""
<p>
hello, world!
</p>
"""
end
end

3
mise.toml Normal file
View File

@@ -0,0 +1,3 @@
[tools]
erlang = "27.3.4.2"
elixir = "1.18.3-otp-27"

39
mix.exs Normal file
View File

@@ -0,0 +1,39 @@
defmodule Llmex.MixProject do
use Mix.Project
def project do
[
app: :llmex,
version: "0.1.0",
elixir: "~> 1.15",
start_permanent: Mix.env() == :prod,
compilers: Mix.compilers(),
aliases: aliases(),
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:tableau, "~> 0.25"},
{:phoenix_live_view, "~> 1.0"}
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
defp aliases do
[
build: ["tableau.build"]
]
end
end

36
mix.lock Normal file
View File

@@ -0,0 +1,36 @@
%{
"autumn": {:hex, :autumn, "0.5.0", "0fcf328ad625ef0fdacd5cd93365402c7d8f50de1a9005413f0f034c247723a8", [:mix], [{:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:rustler, "~> 0.29", [hex: :rustler, repo: "hexpm", optional: false]}, {:rustler_precompiled, "~> 0.6", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "75eb7d711bf25505f29961e0942a5948a9da9a6e3b014eb8656815895ffea938"},
"bandit": {:hex, :bandit, "1.7.0", "d1564f30553c97d3e25f9623144bb8df11f3787a26733f00b21699a128105c0c", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "3e2f7a98c7a11f48d9d8c037f7177cd39778e74d55c7af06fe6227c742a8168a"},
"castore": {:hex, :castore, "1.0.14", "4582dd7d630b48cf5e1ca8d3d42494db51e406b7ba704e81fbd401866366896a", [:mix], [], "hexpm", "7bc1b65249d31701393edaaac18ec8398d8974d52c647b7904d01b964137b9f4"},
"date_time_parser": {:hex, :date_time_parser, "1.2.1", "5bc272b064d21e969c1a15ab406f65767b03fb0825b69dbfd5fc3e8980cdcd05", [:mix], [{:kday, "~> 1.0", [hex: :kday, repo: "hexpm", optional: false]}], "hexpm", "477333e15db3c9031e9281634ce8ae4fd505d0c8e51b9fa51b68933a0e5fed92"},
"file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"},
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"kday": {:hex, :kday, "1.1.0", "64efac85279a12283eaaf3ad6f13001ca2dff943eda8c53288179775a8c057a0", [:mix], [{:ex_doc, "~> 0.21", [hex: :ex_doc, repo: "hexpm", optional: true]}], "hexpm", "69703055d63b8d5b260479266c78b0b3e66f7aecdd2022906cd9bf09892a266d"},
"libgraph": {:hex, :libgraph, "0.16.0", "3936f3eca6ef826e08880230f806bfea13193e49bf153f93edcf0239d4fd1d07", [:mix], [], "hexpm", "41ca92240e8a4138c30a7e06466acc709b0cbb795c643e9e17174a178982d6bf"},
"mdex": {:hex, :mdex, "0.7.5", "3259fdb1511bcd61080477f62c5e2473b4c47112d9d2086ea280b58c896067e9", [:mix], [{:autumn, ">= 0.4.0", [hex: :autumn, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:rustler, "~> 0.32", [hex: :rustler, repo: "hexpm", optional: false]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "dc06cbfa391566a010d12d975d73c923ab998c394385b4886553db10a4577afc"},
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
"phoenix": {:hex, :phoenix, "1.7.21", "14ca4f1071a5f65121217d6b57ac5712d1857e40a0833aff7a691b7870fc9a3b", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "336dce4f86cba56fed312a7d280bf2282c720abb6074bdb1b61ec8095bdd0bc9"},
"phoenix_html": {:hex, :phoenix_html, "4.2.1", "35279e2a39140068fc03f8874408d58eef734e488fc142153f055c5454fd1c08", [:mix], [], "hexpm", "cff108100ae2715dd959ae8f2a8cef8e20b593f8dfd031c9cba92702cf23e053"},
"phoenix_live_view": {:hex, :phoenix_live_view, "1.0.17", "beeb16d83a7d3760f7ad463df94e83b087577665d2acc0bf2987cd7d9778068f", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a4ca05c1eb6922c4d07a508a75bfa12c45e5f4d8f77ae83283465f02c53741e1"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
"plug": {:hex, :plug, "1.18.1", "5067f26f7745b7e31bc3368bc1a2b818b9779faa959b49c934c17730efc911cf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "57a57db70df2b422b564437d2d33cf8d33cd16339c1edb190cd11b1a3a546cc2"},
"plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"},
"rustler": {:hex, :rustler, "0.36.2", "6c2142f912166dfd364017ab2bf61242d4a5a3c88e7b872744642ae004b82501", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.7", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "93832a6dbc1166739a19cd0c25e110e4cf891f16795deb9361dfcae95f6c88fe"},
"rustler_precompiled": {:hex, :rustler_precompiled, "0.8.3", "4e741024b0b097fe783add06e53ae9a6f23ddc78df1010f215df0c02915ef5a8", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "c23f5f33cb6608542de4d04faf0f0291458c352a4648e4d28d17ee1098cddcc4"},
"schematic": {:hex, :schematic, "0.5.1", "be4b2c03115d5a593459c11a7249a6fbb45855947d9653e9250455dcd7df1d42", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02f913c97e6e04ccdaa02004679a7a16bb16fe0449583ad647e296d8e8961546"},
"slugify": {:hex, :slugify, "1.3.1", "0d3b8b7e5c1eeaa960e44dce94382bee34a39b3ea239293e457a9c5b47cc6fd3", [:mix], [], "hexpm", "cb090bbeb056b312da3125e681d98933a360a70d327820e4b7f91645c4d8be76"},
"tableau": {:hex, :tableau, "0.26.0", "353acc80ff2681a4371403f9072b4da5957d2358ff05c460266210920fb37628", [:mix], [{:bandit, "~> 1.0", [hex: :bandit, repo: "hexpm", optional: false]}, {:date_time_parser, "~> 1.2", [hex: :date_time_parser, repo: "hexpm", optional: false]}, {:html_entities, "~> 0.5.2", [hex: :html_entities, repo: "hexpm", optional: false]}, {:libgraph, "~> 0.16.0", [hex: :libgraph, repo: "hexpm", optional: false]}, {:mdex, "~> 0.7.0", [hex: :mdex, repo: "hexpm", optional: false]}, {:schematic, "~> 0.5.1", [hex: :schematic, repo: "hexpm", optional: false]}, {:slugify, "~> 1.3", [hex: :slugify, repo: "hexpm", optional: false]}, {:tz, "~> 0.28.1", [hex: :tz, repo: "hexpm", optional: false]}, {:web_dev_utils, "~> 0.3", [hex: :web_dev_utils, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5", [hex: :websock_adapter, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.9", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "689e64f33ea1e8fbf28cf33ad4419fc584d8576f10a78880788ceb21809b56fc"},
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
"thousand_island": {:hex, :thousand_island, "1.3.14", "ad45ebed2577b5437582bcc79c5eccd1e2a8c326abf6a3464ab6c06e2055a34a", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d0d24a929d31cdd1d7903a4fe7f2409afeedff092d277be604966cd6aa4307ef"},
"toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"},
"tz": {:hex, :tz, "0.28.1", "717f5ffddfd1e475e2a233e221dc0b4b76c35c4b3650b060c8e3ba29dd6632e9", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:mint, "~> 1.6", [hex: :mint, repo: "hexpm", optional: true]}], "hexpm", "bfdca1aa1902643c6c43b77c1fb0cb3d744fd2f09a8a98405468afdee0848c8a"},
"web_dev_utils": {:hex, :web_dev_utils, "0.3.0", "463f3695dcdee9a6f18dbc783ee76f0ecdd1c9a489a6482aadcf166b3e5fee12", [:mix], [{:file_system, "~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "c239d4d24bfc61110a98b7d75bb7bbbb1752a5d8fcb5a2d369c5d4f64d1d7aec"},
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
"websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},
"yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"},
"yaml_elixir": {:hex, :yaml_elixir, "2.11.0", "9e9ccd134e861c66b84825a3542a1c22ba33f338d82c07282f4f1f52d847bd50", [:mix], [{:yamerl, "~> 0.10", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "53cc28357ee7eb952344995787f4bb8cc3cecbf189652236e9b163e8ce1bc242"},
}