working? demo

This commit is contained in:
graphiteisaac 2025-01-30 16:44:45 +11:00
parent 617771d89a
commit 39b2e47ec7
16 changed files with 1755 additions and 1084 deletions

BIN
bun.lockb Executable file

Binary file not shown.

12
index.html Normal file
View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>writing</title>
</head>
<body>
<div id="app"></div>
<script src="./priv/static/vite.ts" type="module"></script>
</body>
</html>

2647
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
{ {
"name": "promptbox", "name": "promptbox",
"type": "module",
"version": "1.0.0", "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/)", "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", "main": "index.js",
@ -13,6 +14,10 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"tailwindcss": "^3.4.17" "@tailwindcss/postcss": "^4.0.1",
"@tailwindcss/vite": "^4.0.1",
"tailwindcss": "^4.0.1",
"vite": "^6.0.11",
"vite-gleam": "^0.4.3"
} }
} }

View file

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

6
priv/static/vite.ts Normal file
View file

@ -0,0 +1,6 @@
import '../assets/input.css'
import lustre_main from '../../src/promptbox/devserver.gleam'
console.log('hello world')
lustre_main()

View file

@ -1,10 +1,50 @@
import promptbox/postcss
import argv import argv
import gleam/io import gleam/io
import gleam/list
import lustre/element
import promptbox/devserver
import promptbox/files
import promptbox/web
pub fn main() { pub fn main() {
case argv.load().arguments { case argv.load().arguments {
["serve"] -> Nil ["serve"] -> {
["build"] -> Nil // postcss.compile_css()
devserver.run_vite_server()
}
["build"] -> {
// Parse all posts
let posts = files.read_all_posts()
// Generate HTML
let index =
posts
|> web.home
|> web.layout("All Posts")
|> element.to_document_string
// Clear and/or create the dist directory
let _ = files.freshen_dist_dir()
// Write the index page
let _ = files.write_built_file("index.html", index)
// Write individual prompt pages
list.each(posts, fn(post) {
let _ =
files.write_built_file(
"prompts/" <> post.slug <> ".html",
web.layout([web.individual(post)], post.title)
|> element.to_document_string,
)
})
// Move assets over, and create the asset folder
postcss.compile_css()
// Finish
Nil
}
_ -> io.println("usage: gleam run <serve|build>") _ -> io.println("usage: gleam run <serve|build>")
} }
} }

View file

@ -0,0 +1,39 @@
import birl
import lustre
import lustre/element/html
import promptbox/parser
import promptbox/web
@external(javascript, "./devserver_ffi.js", "run_vite_server")
pub fn run_vite_server() -> Nil
pub fn lustre_main() {
let app = lustre.simple(init, update, view)
let assert Ok(_) = lustre.start(app, "#app", Nil)
Nil
}
fn init(_flags) {
0
}
fn update(model, _msg) {
model
}
fn view(_model) {
html.div(
[],
web.home([
parser.Post(
slug: "ebben-flow",
title: "ebben flow",
week: 1,
date: birl.now(),
post_p: "No",
post_j: "OK",
),
]),
)
}

View file

@ -0,0 +1,22 @@
import { createServer } from 'vite'
import gleam from 'vite-gleam'
import tailwindcss from '@tailwindcss/vite'
export async function run_vite_server() {
const server = await createServer({
configFile: false,
root: './',
server: {
port: 1337,
},
plugins: [
gleam(),
tailwindcss()
]
})
await server.listen()
server.printUrls()
server.bindCLIShortcuts()
}

View file

@ -1,5 +1,8 @@
import gleam/list import gleam/list
import gleam/order import gleam/order
import gleam/pair
import gleam/result
import gleam/string
import promptbox/parser import promptbox/parser
import simplifile import simplifile
@ -7,9 +10,15 @@ pub fn read_all_posts() {
let assert Ok(posts) = simplifile.read_directory("./priv/posts") let assert Ok(posts) = simplifile.read_directory("./priv/posts")
let posts = let posts =
list.map(posts, fn(p) { list.map(posts, fn(prompt_file) {
let assert Ok(content) = simplifile.read("./priv/posts/" <> p) let assert Ok(content) = simplifile.read("./priv/posts/" <> prompt_file)
parser.parse_post(content) let post_slug =
prompt_file
|> string.split_once(".md")
|> result.unwrap(#("", ""))
|> pair.first
parser.parse_post(post_slug, content)
}) })
use a, b <- list.sort(posts) use a, b <- list.sort(posts)
@ -20,10 +29,10 @@ pub fn read_all_posts() {
} }
pub fn freshen_dist_dir() { pub fn freshen_dist_dir() {
// void this result since we dont care if it cant be deleted / doesn't exist // void this results since we dont care if it cant be deleted / doesn't exist, or can't be created.
let _ = simplifile.delete("./dist") let _ = simplifile.delete("./dist")
let _ = simplifile.create_directory("./dist")
simplifile.create_directory("./dist") let _ = simplifile.create_directory("./dist/prompts")
} }
pub fn write_built_file(name: String, contents: String) { pub fn write_built_file(name: String, contents: String) {

View file

@ -2,5 +2,7 @@ import promptbox/parser
import promptbox/web import promptbox/web
pub fn generate_posts(posts: List(parser.Post)) { pub fn generate_posts(posts: List(parser.Post)) {
web.home(posts) posts
|> web.home
|> web.layout("all writing")
} }

View file

@ -8,6 +8,7 @@ import jot
pub type Post { pub type Post {
Post( Post(
slug: String,
title: String, title: String,
week: Int, week: Int,
date: birl.Time, date: birl.Time,
@ -16,7 +17,7 @@ pub type Post {
) )
} }
pub fn parse_post(content: String) -> Post { pub fn parse_post(slug: String, content: String) -> Post {
let assert [_, frontmatter, posts] = string.split(content, "---\n") let assert [_, frontmatter, posts] = string.split(content, "---\n")
let frontmatter = let frontmatter =
frontmatter frontmatter
@ -39,6 +40,7 @@ pub fn parse_post(content: String) -> Post {
|> list.map(jot.to_html) |> list.map(jot.to_html)
Post( Post(
slug:,
title: result.unwrap( title: result.unwrap(
dict.get(frontmatter, "title"), dict.get(frontmatter, "title"),
"Title failed to parse", "Title failed to parse",

View file

@ -1,2 +1,2 @@
@external(javascript, "./promptbox/postcss_ffi.js", "compile_css") @external(javascript, "./postcss_ffi.js", "compile_css")
pub fn compile_css() -> Nil pub fn compile_css() -> Nil

View file

@ -1,3 +1,17 @@
export function compile_css() { import tailwindcss from '@tailwindcss/postcss'
import postcss from 'postcss'
import fs from 'node:fs'
export function compile_css() {
const css = fs.readFileSync('./priv/assets/input.css').toString()
postcss([tailwindcss])
.process(css, { from: './priv/assets/input.css', to: './dist/assets/main.css' })
.then(result => {
fs.mkdir('./dist/assets/', { recursive: true }, () => true)
fs.writeFile('./dist/assets/main.css', result.css, () => true)
if (result.map) {
fs.writeFile('./dist/assets/main.css.map', result.map.toString(), () => true)
}
})
} }

View file

@ -3,7 +3,7 @@ import lustre/attribute.{attribute}
import lustre/element/html import lustre/element/html
import promptbox/parser import promptbox/parser
fn layout(contents, title) { pub fn layout(contents, title) {
html.html([attribute("lang", "en")], [ html.html([attribute("lang", "en")], [
html.head([], [ html.head([], [
html.meta([attribute("charset", "utf-8")]), html.meta([attribute("charset", "utf-8")]),
@ -12,7 +12,7 @@ fn layout(contents, title) {
attribute.name("viewport"), attribute.name("viewport"),
]), ]),
html.title([], title), html.title([], title),
html.link([attribute.href("styles.css"), attribute.rel("stylesheet")]), html.link([attribute.href("/assets/main.css"), attribute.rel("stylesheet")]),
]), ]),
html.body( html.body(
[], [],
@ -23,12 +23,10 @@ fn layout(contents, title) {
pub fn home(posts: List(parser.Post)) { pub fn home(posts: List(parser.Post)) {
list.map(posts, prompt_element) list.map(posts, prompt_element)
|> layout("all writing")
} }
pub fn individual(post: parser.Post) { pub fn individual(post: parser.Post) {
[prompt_element(post)] prompt_element(post)
|> layout(post.title)
} }
fn prompt_element(post: parser.Post) { fn prompt_element(post: parser.Post) {

View file

@ -18,7 +18,7 @@ pub fn hello_world_test() {
let post = let post =
simplifile.read("./priv/posts/ebb_and_flow.md") simplifile.read("./priv/posts/ebb_and_flow.md")
|> result.unwrap("") |> result.unwrap("")
|> parser.parse_post |> parser.parse_post("ebb_and_flow")
|> io.debug |> io.debug
io.debug(birl.to_date_string(post.date)) io.debug(birl.to_date_string(post.date))