init project

This commit is contained in:
graphiteisaac 2025-01-19 23:16:57 +11:00
commit 0f5ec5fd9c
17 changed files with 1651 additions and 0 deletions

23
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,23 @@
name: test
on:
push:
branches:
- master
- main
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: "27.1.2"
gleam-version: "1.6.0"
rebar3-version: "3"
# elixir-version: "1.15.4"
- run: gleam deps download
- run: gleam test
- run: gleam format --check src test

6
.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
*.beam
*.ez
/build
erl_crash.dump
/dist
node_modules

24
README.md Normal file
View file

@ -0,0 +1,24 @@
# promptbox
[![Package Version](https://img.shields.io/hexpm/v/promptbox)](https://hex.pm/packages/promptbox)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/promptbox/)
```sh
gleam add promptbox@1
```
```gleam
import promptbox
pub fn main() {
// TODO: An example of the project in use
}
```
Further documentation can be found at <https://hexdocs.pm/promptbox>.
## Development
```sh
gleam run # Run the project
gleam test # Run the tests
```

23
gleam.toml Normal file
View file

@ -0,0 +1,23 @@
name = "promptbox"
version = "1.0.0"
# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
#
# description = ""
# licences = ["Apache-2.0"]
# repository = { type = "github", user = "", repo = "" }
# links = [{ title = "Website", href = "" }]
#
# For a full reference of all the available options, you can have a look at
# https://gleam.run/writing-gleam/gleam-toml/.
[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
jot = ">= 2.0.0 and < 3.0.0"
simplifile = ">= 2.2.0 and < 3.0.0"
lustre = ">= 4.6.3 and < 5.0.0"
birl = ">= 1.8.0 and < 2.0.0"
[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"

26
manifest.toml Normal file
View file

@ -0,0 +1,26 @@
# This file was generated by Gleam
# You typically do not need to edit this file
packages = [
{ name = "birl", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_regexp", "gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "2AC7BA26F998E3DFADDB657148BD5DDFE966958AD4D6D6957DD0D22E5B56C400" },
{ name = "filepath", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "67A6D15FB39EEB69DD31F8C145BB5A421790581BD6AA14B33D64D5A55DBD6587" },
{ name = "gleam_erlang", version = "0.33.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "A1D26B80F01901B59AABEE3475DD4C18D27D58FA5C897D922FCB9B099749C064" },
{ name = "gleam_json", version = "2.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "C55C5C2B318533A8072D221C5E06E5A75711C129E420DD1CE463342106012E5D" },
{ name = "gleam_otp", version = "0.16.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "FA0EB761339749B4E82D63016C6A18C4E6662DA05BAB6F1346F9AF2E679E301A" },
{ name = "gleam_regexp", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "A3655FDD288571E90EE9C4009B719FEF59FA16AFCDF3952A76A125AF23CF1592" },
{ name = "gleam_stdlib", version = "0.52.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "50703862DF26453B277688FFCDBE9DD4AC45B3BD9742C0B370DB62BC1629A07D" },
{ name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" },
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
{ name = "jot", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "jot", source = "hex", outer_checksum = "81E61DA896901BFC0522DCFB14C661B6C70F0664C01D8B461F5F9B1A9E965FD4" },
{ name = "lustre", version = "4.6.3", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib"], otp_app = "lustre", source = "hex", outer_checksum = "BDF833368F6C8F152F948D5B6A79866E9881CB80CB66C0685B3327E7DCBFB12F" },
{ name = "ranger", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_yielder"], otp_app = "ranger", source = "hex", outer_checksum = "C8988E8F8CDBD3E7F4D8F2E663EF76490390899C2B2885A6432E942495B3E854" },
{ name = "simplifile", version = "2.2.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0DFABEF7DC7A9E2FF4BB27B108034E60C81BEBFCB7AB816B9E7E18ED4503ACD8" },
]
[requirements]
birl = { version = ">= 1.8.0 and < 2.0.0" }
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
jot = { version = ">= 2.0.0 and < 3.0.0" }
lustre = { version = ">= 4.6.3 and < 5.0.0" }
simplifile = { version = ">= 2.2.0 and < 3.0.0" }

1271
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

18
package.json Normal file
View file

@ -0,0 +1,18 @@
{
"name": "promptbox",
"version": "1.0.0",
"description": "[![Package Version](https://img.shields.io/hexpm/v/promptbox)](https://hex.pm/packages/promptbox) [![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/promptbox/)",
"main": "index.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"tailwindcss": "^3.4.17"
}
}

9
priv/assets/input.css Normal file
View file

@ -0,0 +1,9 @@
@import url(https://fonts.bunny.net/css?family=alegreya:400,400i,700,700i);
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
font-family: 'Alegreya', serif;
}

View file

@ -0,0 +1,38 @@
---
title: Ebb and Flow
week: 1
date: 2024-01-01
---
The two natural states of any changing being. As we all are, between them or reaching, life seldom finds stillness. When tides recede, we must work harder to be ourselves - don't disrupt our friendships, carry on our routines, push ourselves through it. Or rest. Allow healing, and comfort - risking the costs in connections, health, responsibilities.
When the pendulum swings back the challenges differ. Goodness and effort come easy. There is plenty of zest and fervour to light each day. We relish these hours, and come to expect them, though these joys can never go on forever. Even the richest - in any and all measures - experience hardship and lows. A lost opportunity; no welcome relief, a broken relationship; painful and seething. Unanticipated death knocking an unfair door. All the preventative factors in the world couldn't prepare a person for these things, nor make them easy.
In the flow, recall ebb, its bitterness and dark. Let it creep in just a little. That piece who finds warmth or kindness during abundance may resurface again, between thrashing waves - a small piece of light bringing hope for the end of the tunnel.
+++
would you like to meet up sometime quite soon
that was so fun, can't wait to hang again
let's meet up if your free this afternoon
no problem, dont stress, just let me know when
I'm so glad I spotted you at that tree
I love getting to spend time together
I'm keen, I'll let you know next time i'm free
I'm so sorry, I cant with this weather
I'm glad you called, I've been thinking of you
I need to say, you mean so much to me
can't wait to meet again, it's over due
no family first, I dont disagree
I've been missing you so much as of late
An ebb I pray ends, the flow I await

38
priv/posts/second.md Normal file
View file

@ -0,0 +1,38 @@
---
title: second one
week: 2
date: 2024-01-08
---
The two natural states of any changing being. As we all are, between them or reaching, life seldom finds stillness. When tides recede, we must work harder to be ourselves - don't disrupt our friendships, carry on our routines, push ourselves through it. Or rest. Allow healing, and comfort - risking the costs in connections, health, responsibilities.
When the pendulum swings back the challenges differ. Goodness and effort come easy. There is plenty of zest and fervour to light each day. We relish these hours, and come to expect them, though these joys can never go on forever. Even the richest - in any and all measures - experience hardship and lows. A lost opportunity; no welcome relief, a broken relationship; painful and seething. Unanticipated death knocking an unfair door. All the preventative factors in the world couldn't prepare a person for these things, nor make them easy.
In the flow, recall ebb, its bitterness and dark. Let it creep in just a little. That piece who finds warmth or kindness during abundance may resurface again, between thrashing waves - a small piece of light bringing hope for the end of the tunnel.
+++
would you like to meet up sometime quite soon
that was so fun, can't wait to hang again
let's meet up if your free this afternoon
no problem, dont stress, just let me know when
I'm so glad I spotted you at that tree
I love getting to spend time together
I'm keen, I'll let you know next time i'm free
I'm so sorry, I cant with this weather
I'm glad you called, I've been thinking of you
I need to say, you mean so much to me
can't wait to meet again, it's over due
no family first, I dont disagree
I've been missing you so much as of late
An ebb I pray ends, the flow I await

5
src/promptbox.gleam Normal file
View file

@ -0,0 +1,5 @@
import gleam/io
pub fn main() {
io.println("Hello from promptbox!")
}

19
src/promptbox/files.gleam Normal file
View file

@ -0,0 +1,19 @@
import gleam/order
import promptbox/parser
import gleam/list
import simplifile
pub fn read_all_posts() {
let assert Ok(posts) = simplifile.read_directory("./priv/posts")
let posts = list.map(posts, fn(p) {
let assert Ok(content) = simplifile.read("./priv/posts/" <> p)
parser.parse_post(content)
})
use a, b <- list.sort(posts)
case a.week >= b.week {
True -> order.Gt
_ -> order.Lt
}
}

6
src/promptbox/gen.gleam Normal file
View file

@ -0,0 +1,6 @@
import promptbox/web
import promptbox/parser
pub fn generate_posts(posts: List(parser.Post)) {
web.home(posts)
}

View file

@ -0,0 +1,55 @@
import birl
import gleam/dict
import gleam/int
import gleam/list
import gleam/result
import gleam/string
import jot
pub type Post {
Post(
title: String,
week: Int,
date: birl.Time,
post_p: String,
post_j: String,
)
}
pub fn parse_post(content: String) -> Post {
let assert [_, frontmatter, posts] = string.split(content, "---\n")
let frontmatter =
frontmatter
|> string.split("\n")
|> list.filter_map(fn(entry) {
case string.contains(entry, ":") {
False -> Error(Nil)
True -> {
let assert [key, value] =
string.split(entry, ":") |> list.map(string.trim)
Ok(#(key, value))
}
}
})
|> dict.from_list
let assert [post_p, post_j] =
string.split(posts, "\n+++\n")
|> list.map(jot.to_html)
Post(
title: result.unwrap(
dict.get(frontmatter, "title"),
"Title failed to parse",
),
week: dict.get(frontmatter, "week")
|> result.try(int.parse)
|> result.unwrap(-1),
date: dict.get(frontmatter, "date")
|> result.try(birl.parse)
|> result.unwrap(birl.now()),
post_p:,
post_j:,
)
}

42
src/promptbox/web.gleam Normal file
View file

@ -0,0 +1,42 @@
import gleam/list
import lustre/attribute.{attribute}
import lustre/element/html
import promptbox/parser
fn layout(contents, title) {
html.html([attribute("lang", "en")], [
html.head([], [
html.meta([attribute("charset", "utf-8")]),
html.meta([
attribute("content", "width=device-width, initial-scale=1"),
attribute.name("viewport"),
]),
html.title([], title),
html.link([attribute.href("styles.css"), attribute.rel("stylesheet")]),
]),
html.body(
[],
list.append(contents, [html.script([attribute.src("scripts.js")], "")]),
),
])
}
pub fn home(posts: List(parser.Post)) {
list.map(posts, prompt_element)
|> layout("all writing")
}
pub fn individual(post: parser.Post) {
[prompt_element(post)]
|> layout(post.title)
}
fn prompt_element(post: parser.Post) {
html.article([attribute.class("post")], [
html.h3([attribute.class("post_title")], [html.text(post.title)]),
html.div([attribute.class("grid lg:grid-cols-2 gap-6")], [
html.div([attribute("dangerous-unescaped-html", post.post_p)], []),
html.div([attribute("dangerous-unescaped-html", post.post_j)], []),
])
])
}

9
tailwind.config.js Normal file
View file

@ -0,0 +1,9 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.gleam'],
theme: {
extend: {},
},
plugins: [],
}

39
test/promptbox_test.gleam Normal file
View file

@ -0,0 +1,39 @@
import lustre/element
import promptbox/gen
import promptbox/files
import birl
import gleam/io
import gleam/result
import gleeunit
import gleeunit/should
import promptbox/parser
import simplifile
pub fn main() {
gleeunit.main()
}
// gleeunit test functions end in `_test`
pub fn hello_world_test() {
let post = simplifile.read("./priv/posts/ebb_and_flow.md")
|> result.unwrap("")
|> parser.parse_post
|> io.debug
io.debug(birl.to_date_string(post.date))
files.read_all_posts()
|> io.debug
1
|> should.equal(1)
}
pub fn generate_test() {
let _ = simplifile.create_directory("./dist")
files.read_all_posts()
|> gen.generate_posts
|> element.to_document_string
|> simplifile.write(to: "./dist/index.html")
}