Procházet zdrojové kódy

Create basic application

This supports a single-profile site based on a JSON file. It also
includes very basic styles for the site.
main
Matt Baer před 6 roky
rodič
revize
f297d9fd7d
11 změnil soubory, kde provedl 262 přidání a 0 odebrání
  1. +65
    -0
      app.go
  2. +9
    -0
      cmd/publicbio/main.go
  3. +5
    -0
      generate.sh
  4. +37
    -0
      handler.go
  5. +1
    -0
      less/app.less
  6. +30
    -0
      less/core.less
  7. +28
    -0
      routes.go
  8. +1
    -0
      static/css/.gitignore
  9. +26
    -0
      templates.go
  10. +39
    -0
      templates/profile.tmpl
  11. +21
    -0
      user.go

+ 65
- 0
app.go Zobrazit soubor

@@ -0,0 +1,65 @@
package publicbio

import (
"encoding/json"
"flag"
"fmt"
"github.com/gorilla/mux"
"github.com/gorilla/schema"
"github.com/writeas/web-core/converter"
"io/ioutil"
"log"
"net/http"
)

type app struct {
router *mux.Router
cfg *config
keys *keychain

singleUser *Profile
}

func (app *app) multiUser() bool {
return app.singleUser == nil
}

type config struct {
host string
port int
}

func Serve() {
app := &app{
cfg: &config{},
}

flag.IntVar(&app.cfg.port, "p", 8080, "Port to start server on")
flag.StringVar(&app.cfg.host, "h", "https://public.bio", "Site's base URL")
var userFile string
flag.StringVar(&userFile, "u", "", "Configuration file for single-user site")
flag.Parse()

if userFile != "" {
f, err := ioutil.ReadFile(userFile)
if err != nil {
log.Fatal("File error: %v\n", err)
}

json.Unmarshal(f, &app.singleUser)
fmt.Printf("Results: %v\n", app.singleUser)
} else {
log.Fatal("No user configuration")
}

initRoutes(app)

http.Handle("/", app.router)
log.Printf("Serving on localhost:%d", app.cfg.port)
http.ListenAndServe(fmt.Sprintf(":%d", app.cfg.port), nil)
}

func initConverter() {
formDecoder := schema.NewDecoder()
formDecoder.RegisterConverter(converter.NullJSONString{}, converter.JSONNullString)
}

+ 9
- 0
cmd/publicbio/main.go Zobrazit soubor

@@ -0,0 +1,9 @@
package main

import (
"github.com/abunchtell/publicbio"
)

func main() {
publicbio.Serve()
}

+ 5
- 0
generate.sh Zobrazit soubor

@@ -0,0 +1,5 @@
#!/bin/bash

CSSDIR=static/css/

lessc less/app.less --clean-css="--s1 --advanced" ${CSSDIR}main.css

+ 37
- 0
handler.go Zobrazit soubor

@@ -0,0 +1,37 @@
package publicbio

import (
"github.com/writeas/impart"
"log"
"net/http"
"strings"
)

type handlerFunc func(app *app, w http.ResponseWriter, r *http.Request) error

func (app *app) handler(h handlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
handleError(w, r, func() error {
return h(app, w, r)
}())
}
}

func handleError(w http.ResponseWriter, r *http.Request, err error) {
if err == nil {
return
}

if err, ok := err.(impart.HTTPError); ok {
log.Printf("Error: %v", err)
if err.Status >= 300 && err.Status < 400 {
impart.WriteRedirect(w, err)
return
}
impart.WriteError(w, err)
return
}
log.Printf("Error: %v", err)

impart.WriteError(w, impart.HTTPError{http.StatusInternalServerError, "We encountered an error we couldn't handle."})
}

+ 1
- 0
less/app.less Zobrazit soubor

@@ -0,0 +1 @@
@import "core";

+ 30
- 0
less/core.less Zobrazit soubor

@@ -0,0 +1,30 @@
@themeColor: #1FBF99;

body {
min-width: 320px;
min-height: 100vh;
line-height: 1.0;
word-wrap: break-word;
overflow-x: hidden;
background-color: #F7F7F7;
}

h1, h2, h3, p {
color: rgba(0, 0, 0, 0.42);
font-family: 'Roboto', 'sans-serif';
letter-spacing: -0.025rem;
width: 100%;
font-size: 2em;
line-height: 1.625;
font-weight: 400;
text-align: justify;
}

h2 {
color: @themeColor;
letter-spacing: -0.05rem;
font-size: 1.25em;
line-height: 1.375;
font-weight: 500;
text-align: inherit;
}

+ 28
- 0
routes.go Zobrazit soubor

@@ -0,0 +1,28 @@
package publicbio

import (
"github.com/gorilla/mux"
"net/http"
)

func initRoutes(app *app) {
app.router = mux.NewRouter()

app.router.HandleFunc("/", app.handler(handleViewProfile))
app.router.PathPrefix("/").Handler(http.FileServer(http.Dir("../../static/")))
}

func handleViewProfile(app *app, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
username := vars["username"]

var p *Profile
if username == "" {
p = app.singleUser
}

if err := renderTemplate(w, "profile", p); err != nil {
return err
}
return nil
}

+ 1
- 0
static/css/.gitignore Zobrazit soubor

@@ -0,0 +1 @@
main.css

+ 26
- 0
templates.go Zobrazit soubor

@@ -0,0 +1,26 @@
package publicbio

import (
"html/template"
"io"
"log"
)

var profileTmpl *template.Template

const templatesDir = "../../templates/"

func init() {
profileTmpl = template.Must(template.New("profile").ParseFiles(templatesDir + "profile.tmpl"))
}

// renderTemplate retrieves the given template and renders it to the given io.Writer.
// If something goes wrong, the error is logged and returned.
func renderTemplate(w io.Writer, tmpl string, data interface{}) error {
err := profileTmpl.ExecuteTemplate(w, tmpl, data)
if err != nil {
log.Printf("[ERROR] Error rendering %s: %s\n", tmpl, err)
}

return err
}

+ 39
- 0
templates/profile.tmpl Zobrazit soubor

@@ -0,0 +1,39 @@
{{define "profile"}}<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>{{.Name.String}}</title>
<link rel="stylesheet" type="text/css" href="/css/main.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="wrapper">
<div id="main">
<div class="inner">
<div id="container01" class="container">
<div class="inner">
<div>
<div id="image01" class="image">
<img src="" alt="Profile Image" />
</div>
<h1 id="text04">{{.Name.String}}</h1>
<h2 id="text03">{{.Header.String}}</h2>
<p id="bio">{{.RenderedBio}}</p>
</div>
<div>
<ul id="buttons02" class="buttons">
<li><a href="http://domain.tld/path" class="button n01">Twitter</a></li>
<li><a href="http://domain.tld/path" class="button n02">Mastodon</a></li>
<li><a href="http://domain.tld/path" class="button n03">Pixelfed</a></li>
<li><a href="http://domain.tld/path" class="button n04">Instagram</a></li>
<li><a href="http://domain.tld/path" class="button n05">Whatever Else</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
{{end}}

+ 21
- 0
user.go Zobrazit soubor

@@ -0,0 +1,21 @@
package publicbio

import (
"github.com/writeas/web-core/converter"
"html/template"
)

type (
// Profile is a publicly-viewable user, containing only the data necessary
// to display a profile.
Profile struct {
Username string `json:"username"`
Name converter.NullJSONString `json:"name"`
Header converter.NullJSONString `json:"header"`
Bio converter.NullJSONString `json:"bio"`
}
)

func (p *Profile) RenderedBio() template.HTML {
return template.HTML(p.Bio.String)
}

Načítá se…
Zrušit
Uložit