Load HTML templates and SCSS styling

This commit is contained in:
Naman Sood 2021-02-15 02:31:18 -05:00
parent 8daaa1b330
commit d347551455
10 changed files with 581 additions and 22 deletions

View file

@ -4,7 +4,7 @@ Prose is a blogging platform written in Go, which I am building to serve my own
## Usage
Blog posts should be created in the format `DATE-title-slug.md`. Work in progress posts should be stored as `WIP-title-slug.md`. Static content should be stored in the `static/` folder, appropriately arranged.
Blog posts should be created in the format `title-slug.md`. Work in progress posts should be stored as `WIP-title-slug.md`. Static content should be stored in the `static/` folder, appropriately arranged.
Posts will be served as `/title-slug`, and files like `static/random/file/structure.txt` will be served as `/random/file/structure.txt`. When title slugs and static files conflict, slugs will have higher precdence.

10
go.mod
View file

@ -2,4 +2,12 @@ module prose
go 1.15
require github.com/yuin/goldmark v1.3.1
require (
github.com/aymerick/raymond v2.0.2+incompatible
github.com/mitchellh/mapstructure v1.4.1
github.com/wellington/go-libsass v0.9.2
github.com/yuin/goldmark v1.3.1
github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691
github.com/yuin/goldmark-meta v1.0.0
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
)

60
go.sum
View file

@ -1,9 +1,60 @@
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
github.com/alecthomas/chroma v0.7.2-0.20200305040604-4f3623dce67a h1:3v1NrYWWqp2S72e4HLgxKt83B3l0lnORDholH/ihoMM=
github.com/alecthomas/chroma v0.7.2-0.20200305040604-4f3623dce67a/go.mod h1:fv5SzZPFJbwp2NXJWpFIX7DZS4HgV1K4ew4Pc2OZD9s=
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
github.com/alecthomas/kong v0.1.17-0.20190424132513-439c674f7ae0/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/aymerick/raymond v1.1.0 h1:phuNN2s67eI/HtO8CrvqFcdR2JP+BtkGJZ9n692Hr2Y=
github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0=
github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI=
github.com/gorilla/handlers v1.4.1/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/wellington/go-libsass v0.9.2 h1:6Ims04UDdBs6/CGSVK5JC8FNikR5ssrsMMKE/uaO5Q8=
github.com/wellington/go-libsass v0.9.2/go.mod h1:mxgxgam0N0E+NAUMHLcu20Ccfc3mVpDkyrLDayqfiTs=
github.com/yuin/goldmark v1.1.22/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.1 h1:eVwehsLsZlCJCwXyGLgg+Q4iFWE/eTIMG0e8waCmm/I=
github.com/yuin/goldmark v1.3.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691 h1:VWSxtAiQNh3zgHJpdpkpVYjTPqRE3P6UZCOPa1nRDio=
github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691/go.mod h1:YLF3kDffRfUH/bTxOxHhV6lxwIB3Vfj91rEwNMS9MXo=
github.com/yuin/goldmark-meta v1.0.0 h1:ScsatUIT2gFS6azqzLGUjgOnELsBOxMXerM3ogdJhAM=
github.com/yuin/goldmark-meta v1.0.0/go.mod h1:zsNNOrZ4nLuyHAJeLQEZcQat8dm70SmB2kHbls092Gc=
gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181 h1:K+bMSIx9A7mLES1rtG+qKduLIXq40DAzYHtb0XuCukA=
gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181/go.mod h1:dzYhVIwWCtzPAa4QP98wfB9+mzt33MSmM8wsKiMi2ow=
gitlab.com/golang-commonmark/linkify v0.0.0-20191026162114-a0c2df6c8f82 h1:oYrL81N608MLZhma3ruL8qTM4xcpYECGut8KSxRY59g=
@ -17,8 +68,17 @@ gitlab.com/golang-commonmark/mdurl v0.0.0-20191124015652-932350d1cb84/go.mod h1:
gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f h1:Wku8eEdeJqIOFHtrfkYUByc4bCaTeA6fL0UJgfEiFMI=
gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f/go.mod h1:Tiuhl+njh/JIg0uS/sOJVYi0x2HEa5rc1OAaVsb5tAs=
gitlab.com/opennota/wd v0.0.0-20180912061657-c5d65f63c638/go.mod h1:EGRJaqe2eO9XGmFtQCvV3Lm9NLico3UhFwUpCG/+mVU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

61
page.go
View file

@ -5,33 +5,74 @@ import (
"fmt"
"io/ioutil"
"github.com/aymerick/raymond"
"github.com/mitchellh/mapstructure"
"github.com/yuin/goldmark"
highlighting "github.com/yuin/goldmark-highlighting"
meta "github.com/yuin/goldmark-meta"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/renderer/html"
)
type page struct {
slug string
// Metadata stores the data about a page that needs to be visible
// at the home page.
type Metadata struct {
Title string
Summary string
Date string // TODO: better representation? time.Time might cause timezone issues...
}
func (p *page) render() ([]byte, error) {
data, err := ioutil.ReadFile("posts/" + p.slug + ".md")
// Page stores the contents of a blog post.
type Page struct {
Slug string
Metadata Metadata
Contents string
}
func newPage(slug string) (*Page, error) {
data, err := ioutil.ReadFile("posts/" + slug + ".md")
if err != nil {
return nil, fmt.Errorf("Could not read from %s.md: %s", p.slug, err)
return nil, fmt.Errorf("could not read file: %s", err)
}
md := goldmark.New(
goldmark.WithExtensions(extension.Linkify),
goldmark.WithExtensions(
extension.Linkify,
extension.Strikethrough,
extension.Typographer,
meta.Meta,
highlighting.Highlighting,
),
goldmark.WithRendererOptions(
html.WithUnsafe(),
),
)
var converted bytes.Buffer
err = md.Convert(data, &converted)
ctx := parser.NewContext()
err = md.Convert(data, &converted, parser.WithContext(ctx))
if err != nil {
return nil, fmt.Errorf("Could not parse markdown from %s.md: %s", p.slug, err)
return nil, fmt.Errorf("could not parse markdown: %s", err)
}
mdMap, err := meta.TryGet(ctx)
if err != nil {
return nil, fmt.Errorf("could not parse metadata: %s", err)
}
var metadata Metadata
err = mapstructure.Decode(mdMap, &metadata)
if err != nil {
return nil, fmt.Errorf("could not destructure metadata: %s", err)
}
return converted.Bytes(), nil
page := &Page{
Slug: slug,
Metadata: metadata,
Contents: converted.String(),
}
return page, nil
}
func (p *Page) render(tpl *raymond.Template) (string, error) {
return tpl.Exec(p)
}

121
server.go
View file

@ -2,15 +2,23 @@ package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"github.com/aymerick/raymond"
"github.com/wellington/go-libsass"
)
type server struct {
pages []page
pages []*Page
staticHandler http.Handler
pageTpl *raymond.Template
fullPostTpl *raymond.Template
summaryTpl *raymond.Template
}
func newServer() (*server, error) {
@ -21,7 +29,7 @@ func newServer() (*server, error) {
}
s := &server{
pages: make([]page, 0, len(files)),
pages: make([]*Page, 0, len(files)),
staticHandler: http.FileServer(http.Dir("static/")),
}
@ -29,10 +37,73 @@ func newServer() (*server, error) {
filename := f.Name()
if strings.HasSuffix(filename, ".md") {
s.pages = append(s.pages, page{slug: strings.TrimSuffix(filename, ".md")})
page, err := newPage(strings.TrimSuffix(filename, ".md"))
if err != nil {
return nil, fmt.Errorf("could not render %s: %s", filename, err)
}
s.pages = append(s.pages, page)
log.Printf("Loaded page %s", filename)
}
}
s.pageTpl, err = raymond.ParseFile("templates/page.html")
if err != nil {
return nil, fmt.Errorf("could not parse page template")
}
log.Printf("Loaded page template")
s.fullPostTpl, err = raymond.ParseFile("templates/fullpost.html")
if err != nil {
return nil, fmt.Errorf("could not parse full post template")
}
log.Printf("Loaded full post template")
s.summaryTpl, err = raymond.ParseFile("templates/summary.html")
if err != nil {
return nil, fmt.Errorf("could not parse summary template")
}
log.Printf("Loaded summary template")
styles, err := ioutil.ReadDir("styles/")
if err != nil {
return nil, fmt.Errorf("Could not load styles directory: %s", err)
}
for _, s := range styles {
filename := s.Name()
in, err := os.Open("styles/" + filename)
if err != nil {
return nil, fmt.Errorf("Could not open style infile %s: %s", filename, err)
}
if strings.HasSuffix(filename, ".scss") {
outFilename := strings.TrimSuffix(filename, ".scss") + ".css"
out, err := os.Create("static/css/" + outFilename)
if err != nil {
return nil, fmt.Errorf("Could not open style outfile %s: %s", outFilename, err)
}
comp, err := libsass.New(out, in)
if err != nil {
return nil, fmt.Errorf("Could not start sass compiler for file %s: %s", filename, err)
}
if err = comp.Run(); err != nil {
return nil, fmt.Errorf("Could not generate stylesheet %s: %s", filename, err)
}
} else if strings.HasSuffix(filename, ".css") {
out, err := os.Create("static/css/" + filename)
if err != nil {
return nil, fmt.Errorf("Could not open style outfile %s: %s", filename, err)
}
_, err = io.Copy(out, in)
if err != nil {
return nil, fmt.Errorf("Could not copy stylesheet %s: %s", filename, err)
}
} else {
log.Printf("Skipping stylesheet %s, don't know how to handle", filename)
continue
}
log.Printf("Loaded stylesheet %s", filename)
}
return s, nil
}
@ -50,16 +121,20 @@ func (s *server) router(res http.ResponseWriter, req *http.Request) {
}
for _, p := range s.pages {
if p.slug == slug {
buf, err := p.render()
if p.Slug == slug {
res.Header().Add("content-type", "text/html")
contents, err := p.render(s.fullPostTpl)
if err != nil {
res.WriteHeader(http.StatusInternalServerError)
res.Write([]byte("oh no"))
s.errorInRequest(res, req, err)
}
res.Write(buf)
page, err := s.createPage(p.Metadata.Title, contents)
if err != nil {
s.errorInRequest(res, req, err)
}
res.Write([]byte(page))
return
}
}
@ -67,12 +142,38 @@ func (s *server) router(res http.ResponseWriter, req *http.Request) {
s.staticHandler.ServeHTTP(res, req)
}
func (s *server) errorInRequest(res http.ResponseWriter, req *http.Request, err error) {
res.WriteHeader(http.StatusInternalServerError)
res.Write([]byte("oh no"))
log.Printf("ERR %s: %s", req.URL.Path, err)
}
func (s *server) createPage(title, contents string) (string, error) {
ctx := map[string]interface{}{
"title": title,
"contents": contents,
}
return s.pageTpl.Exec(ctx)
}
func (s *server) homePage(res http.ResponseWriter, req *http.Request) {
res.Header().Add("content-type", "text/html")
res.Write([]byte("<h1>blog</h1>"))
var posts string
for _, p := range s.pages {
fmt.Fprintf(res, "<a href=\"/%s\">%s</a><br>", p.slug, p.slug)
summary, err := p.render(s.summaryTpl)
if err != nil {
log.Printf("could not render page summary for %s", p.Slug)
}
posts = posts + summary
}
page, err := s.createPage("Home", posts)
if err != nil {
s.errorInRequest(res, req, err)
}
res.Write([]byte(page))
}

1
static/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
css

306
styles/main.scss Normal file
View file

@ -0,0 +1,306 @@
*, *:before, *:after {
box-sizing: border-box;
}
@mixin transition-all {
transition: all 0.1s ease-in-out;
}
html {
font-size: 14pt;
min-height: 100%;
position: relative;
}
$ls: 1.4rem;
$darkMode: true;
$bgColor: white;
$bodyColor: #555;
$strongColor: #333;
$lightColor: #999;
$accentColor: #3498db;
body {
height: 100%;
background-color: $bgColor;
font-family: 'Nunito', sans-serif;
margin: 0;
color: $bodyColor;
}
.grid {
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
z-index: 5000;
background-image: linear-gradient(transparent 93%, rgba(0,0,0,0.3) 93%, rgba(0,0,0,0.3));
background-size: 1*$ls 1*$ls;
pointer-events: none;
&.hidden {
display: none;
}
}
button.grid-button {
position: fixed;
bottom: 0.5*$ls;
right: 0.5*$ls;
height: 2*$ls;
padding: 0 1*$ls;
margin: 0;
border: 0;
outline: none;
font: inherit;
font-size: 0.8rem;
background: $accentColor;
color: white;
z-index: 6000;
border-radius: 0.2*$ls;
box-shadow: 0 0.1*$ls 0.1*$ls 0.0125*$ls rgba(0,0,0,0.3);
}
header {
height: 3*$ls;
display: flex;
align-items: center;
justify-content: space-between;
width: 40*$ls;
max-width: 100%;
margin: 0 auto;
h1.title {
margin: 0;
line-height: 3*$ls;
color: $strongColor;
font-size: 1.8rem;
padding: 0;
}
img {
height: 80%;
margin: 0 0.5*$ls;
}
nav {
display: flex;
height: 100%;
a {
color: $strongColor;
text-decoration: none;
display: block;
line-height: 3*$ls;
padding: 0 $ls;
position: relative;
height: 100%;
&:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 0.15rem;
background: white;
opacity: 0;
@include transition-all;
}
&:hover:before {
opacity: 1;
}
}
}
}
main {
width: 40*$ls;
max-width: 100%;
margin: 4*$ls auto 2*$ls;
}
article {
padding: 2*$ls;
//background: white;
//box-shadow: 0 0.05*$ls 0.1*$ls rgba(0,0,0,0.5);
border-radius: 0.2*$ls;
margin: 1*$ls 0 0;
date {
font-size: 0.9rem;
height: $ls;
line-height: $ls;
display: block;
font-weight: 400;
}
h1 {
font-size: 2.6rem;
margin: 0;
line-height: 2*$ls;
color: $strongColor;
}
h2 {
font-size: 1.4rem;
font-weight: 300;
font-style: italic;
color: $lightColor;
line-height: 1*$ls;
margin: 1*$ls 0 0;
}
h3 {
line-height: $ls;
margin: $ls 0;
font-size: 1.3rem;
color: $strongColor;
}
h4 {
line-height: $ls;
margin: $ls 0;
font-size: 1rem;
color: $strongColor;
}
p {
line-height: $ls;
margin: $ls 0 0;
color: $bodyColor;
}
blockquote {
margin: $ls 0;
padding: 0 $ls;
border-left: 0.2rem solid $lightColor;
color: $lightColor;
font-style: italic;
p {
margin: 0;
}
}
code {
font-family: 'JetBrains Mono', monospace;
font-size: 0.9em;
color: $strongColor;
}
pre {
margin: $ls 0;
line-height: $ls;
max-width: 100%;
overflow-x: auto;
padding: 0 2*$ls;
code {
line-height: $ls;
display: block;
}
}
figure {
height: 20*$ls;
padding-bottom: 2*$ls;
margin: 2*$ls 0 0;
img {
height: 100%;
width: 100%;
display: block;
object-fit: contain;
}
img.fill {
object-fit: cover;
}
figcaption {
height: 2*$ls;
line-height: 2*$ls;
text-align: center;
font-style: italic;
color: $lightColor;
font-size: 0.8rem;
}
}
section.content {
a {
color: $strongColor;
text-decoration: none;
background-image: linear-gradient(
transparent 80%,
$lightColor 80%,
$lightColor 85%,
transparent 85%
);
&:hover {
color: $bodyColor;
background-image: linear-gradient(
transparent 80%,
lighten($lightColor, 15%) 80%,
lighten($lightColor, 15%) 85%,
transparent 85%
);
}
}
ul, ol {
color: $bodyColor;
margin: $ls 0;
padding: 0 0 0 $ls;
line-height: $ls;
ul, ol {
margin: 0;
}
}
ul {
li {
list-style: none;
position: relative;
&:before {
content: '·';
height: $ls;
width: $ls;
display: block;
position: absolute;
top: 0;
left: -$ls;
text-align: center;
line-height: $ls;
font-weight: bold;
color: $strongColor;
}
}
}
}
a.load-content {
display: block;
height: 3*$ls;
line-height: 3*$ls;
color: $accentColor;
text-align: center;
text-decoration: none;
}
}
footer {
text-align: center;
padding: $ls 0;
}

9
templates/fullpost.html Normal file
View file

@ -0,0 +1,9 @@
<article>
<date>{{metadata.date}}</date>
<h1>{{metadata.title}}</h1>
<h2>{{metadata.summary}}</h2>
<section class="content">
{{{contents}}}
</section>
<a class="load-content" href="/">&larr; Back home</a>
</article>

27
templates/page.html Normal file
View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="/css/main.css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&family=Nunito:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap" rel="stylesheet">
<title>{{title}} &ndash; Prose</title>
</head>
<body>
<div class="grid"></div>
<header>
<h1 class="title">Prose</h1>
<nav>
<a href="https://nsood.in">Home</a>
<a href="https://notes.nsood.in">Blog</a>
<a href="https://nsood.in/#contact">Contact</a>
</nav>
</header>
<main>
{{{contents}}}
</main>
<footer>
Made by Naman Sood, with love.
</footer>
</body>
</html>

6
templates/summary.html Normal file
View file

@ -0,0 +1,6 @@
<article>
<date>{{metadata.date}}</date>
<h1>{{metadata.title}}</h1>
<h2>{{metadata.summary}}</h2>
<a class="load-content" href="/{{slug}}">Read more &rarr;</a>
</article>