Do not cache files that are monitored
- rename repo to goveal - add working directory option - remove most CLI switches in favor of config file
This commit is contained in:
parent
d56271ef50
commit
b953310df8
14 changed files with 119 additions and 68 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -21,14 +21,10 @@
|
||||||
# CI
|
# CI
|
||||||
bin/
|
bin/
|
||||||
|
|
||||||
assets/reveal
|
assets/reveal/
|
||||||
|
|
||||||
pkged.go
|
pkged.go
|
||||||
|
|
||||||
# binaries
|
|
||||||
goveal
|
|
||||||
!goveal/
|
|
||||||
|
|
||||||
# gorelease
|
# gorelease
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
||||||
VERSION = $(shell git describe --dirty --tags --always)
|
VERSION = $(shell git describe --dirty --tags --always)
|
||||||
REPO = github.com/baez90/go-reveal-slides
|
REPO = github.com/baez90/goveal
|
||||||
BUILD_PATH = $(REPO)/cmd/goveal
|
BUILD_PATH = $(REPO)/cmd/goveal
|
||||||
PKGS = $(shell go list ./... | grep -v /vendor/)
|
PKGS = $(shell go list ./... | grep -v /vendor/)
|
||||||
TEST_PKGS = $(shell find . -type f -name "*_test.go" -printf '%h\n' | sort -u)
|
TEST_PKGS = $(shell find . -type f -name "*_test.go" -printf '%h\n' | sort -u)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Goveal
|
# Goveal
|
||||||
|
|
||||||
[![CircleCI](https://circleci.com/gh/baez90/go-reveal-slides.svg?style=svg)](https://circleci.com/gh/baez90/go-reveal-slides)
|
[![Actions Status](https://github.com/baez90/goveal/workflows/Go/badge.svg)](https://github.com/baez90/goveal/actions)
|
||||||
|
|
||||||
Goveal is very small an very simple tool that reads Markdown from a given file, renders it into a HTML template and serves it as local HTTP server.
|
Goveal is very small an very simple tool that reads Markdown from a given file, renders it into a HTML template and serves it as local HTTP server.
|
||||||
Right now Goveal uses Reveal.js 4.0.2 to create presentations and therefore also includes all features of Reveal.js 4.0.2.
|
Right now Goveal uses Reveal.js 4.0.2 to create presentations and therefore also includes all features of Reveal.js 4.0.2.
|
||||||
|
|
|
@ -6,7 +6,7 @@ vars:
|
||||||
BINARY_NAME: goveal
|
BINARY_NAME: goveal
|
||||||
OUT_DIR: ./out
|
OUT_DIR: ./out
|
||||||
GO_BUILD_ARGS: -ldflags="-w -s"
|
GO_BUILD_ARGS: -ldflags="-w -s"
|
||||||
CMD_PACKAGE: github.com/baez90/go-reveal-slides/cmd/goveal
|
CMD_PACKAGE: github.com/baez90/goveal/cmd/goveal
|
||||||
|
|
||||||
emv:
|
emv:
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
|
|
|
@ -90,7 +90,7 @@
|
||||||
|
|
||||||
{{ if .Reveal.FilesToMonitor }}
|
{{ if .Reveal.FilesToMonitor }}
|
||||||
{{ range $idx, $file := .Reveal.FilesToMonitor }}
|
{{ range $idx, $file := .Reveal.FilesToMonitor }}
|
||||||
subscribeForUpdates("/{{ trimPrefix "/" $file }}")
|
subscribeForUpdates("/{{ $file }}")
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "github.com/baez90/go-reveal-slides"
|
_ "github.com/baez90/goveal"
|
||||||
"github.com/baez90/go-reveal-slides/internal/app/cmd"
|
"github.com/baez90/goveal/internal/app/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
theme: night
|
theme: night
|
||||||
code-theme: monokai
|
codeTheme: monokai
|
||||||
horizontal-separator: ===
|
horizontalSeparator: ===
|
||||||
vertical-separator: ---
|
verticalSeparator: ---
|
||||||
transition: fade
|
transition: fade
|
||||||
stylesheets:
|
stylesheets:
|
||||||
- examples/custom.css
|
- custom.css
|
||||||
filesToMonitor:
|
filesToMonitor:
|
||||||
- examples/**/*.css
|
- ./**/*.css
|
4
go.mod
4
go.mod
|
@ -1,4 +1,4 @@
|
||||||
module github.com/baez90/go-reveal-slides
|
module github.com/baez90/goveal
|
||||||
|
|
||||||
go 1.15
|
go 1.15
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ require (
|
||||||
github.com/gobuffalo/here v0.6.2 // indirect
|
github.com/gobuffalo/here v0.6.2 // indirect
|
||||||
github.com/google/uuid v1.1.2 // indirect
|
github.com/google/uuid v1.1.2 // indirect
|
||||||
github.com/huandu/xstrings v1.3.2 // indirect
|
github.com/huandu/xstrings v1.3.2 // indirect
|
||||||
github.com/imdario/mergo v0.3.11 // indirect
|
github.com/imdario/mergo v0.3.11
|
||||||
github.com/markbates/pkger v0.17.1
|
github.com/markbates/pkger v0.17.1
|
||||||
github.com/mitchellh/copystructure v1.0.0 // indirect
|
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
|
|
|
@ -17,8 +17,9 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/baez90/go-reveal-slides/internal/app/rendering"
|
"github.com/baez90/goveal/internal/app/rendering"
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
|
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
|
@ -27,20 +28,9 @@ import (
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
defaultTheme string = "white"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cfgFile string
|
cfgFile string
|
||||||
theme string
|
workingDir string
|
||||||
codeTheme string
|
|
||||||
transition string
|
|
||||||
navigationMode string
|
|
||||||
horizontalSeparator string
|
|
||||||
verticalSeparator string
|
|
||||||
slideNumberVisibility string
|
|
||||||
slideNumberFormat string
|
|
||||||
rootCmd = &cobra.Command{
|
rootCmd = &cobra.Command{
|
||||||
Use: "goveal",
|
Use: "goveal",
|
||||||
Short: "goveal is a small reveal.js server",
|
Short: "goveal is a small reveal.js server",
|
||||||
|
@ -61,18 +51,18 @@ func Execute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cobra.OnInitialize(initConfig)
|
|
||||||
cobra.OnInitialize(initLogging)
|
cobra.OnInitialize(initLogging)
|
||||||
|
cobra.OnInitialize(initConfig)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
workingDir, err = os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
rootCmd.PersistentFlags().StringVar(&theme, "theme", defaultTheme, "reveal.js theme to use")
|
|
||||||
rootCmd.PersistentFlags().StringVar(&codeTheme, "code-theme", "monokai", "name of the code theme to use for highlighting")
|
|
||||||
rootCmd.PersistentFlags().StringVar(&transition, "transition", "none", "transition effect to use")
|
|
||||||
rootCmd.PersistentFlags().StringVar(&navigationMode, "navigationMode", "default", "determine the navigation mode to use ['default', 'linear', 'grid']")
|
|
||||||
rootCmd.PersistentFlags().StringVar(&horizontalSeparator, "horizontal-separator", "===", "horizontal separator in slides")
|
|
||||||
rootCmd.PersistentFlags().StringVar(&verticalSeparator, "vertical-separator", "---", "vertical separator in slides")
|
|
||||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.go-reveal-slides.yaml)")
|
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.go-reveal-slides.yaml)")
|
||||||
rootCmd.PersistentFlags().StringVar(&slideNumberVisibility, "slide-number-visibility", "all", "where should slide numbers be visible ['all', 'speaker', 'print']")
|
rootCmd.PersistentFlags().StringVar(&workingDir, "working-dir", workingDir, "working directory to use")
|
||||||
rootCmd.PersistentFlags().StringVar(&slideNumberFormat, "slide-number-format", "h.v", "Format of the slide number ['h.v', 'h/v', 'c', 'c/t']")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func initLogging() {
|
func initLogging() {
|
||||||
|
@ -83,6 +73,24 @@ func initLogging() {
|
||||||
|
|
||||||
// initConfig reads in config file and ENV variables if set.
|
// initConfig reads in config file and ENV variables if set.
|
||||||
func initConfig() {
|
func initConfig() {
|
||||||
|
var err error
|
||||||
|
if workingDir, err = filepath.Abs(workingDir); err != nil {
|
||||||
|
log.Warnf("Failed to determine absolute path for working dir %s: %v", workingDir, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var cwd string
|
||||||
|
if cwd, err = os.Getwd(); err != nil {
|
||||||
|
log.Warnf("Failed to determine current working directory")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if cwd != workingDir {
|
||||||
|
if err = os.Chdir(workingDir); err != nil {
|
||||||
|
log.Warnf("Failed to change working directory to %s", workingDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if cfgFile != "" {
|
if cfgFile != "" {
|
||||||
// Use config file from the flag.
|
// Use config file from the flag.
|
||||||
viper.SetConfigFile(cfgFile)
|
viper.SetConfigFile(cfgFile)
|
||||||
|
@ -95,14 +103,9 @@ func initConfig() {
|
||||||
viper.AddConfigPath(home)
|
viper.AddConfigPath(home)
|
||||||
}
|
}
|
||||||
|
|
||||||
cwd, err := os.Getwd()
|
viper.AddConfigPath(workingDir)
|
||||||
if err != nil {
|
|
||||||
log.Infof("Failed to determine current working directory: %v", err)
|
|
||||||
} else {
|
|
||||||
viper.AddConfigPath(cwd)
|
|
||||||
}
|
|
||||||
|
|
||||||
viper.SetConfigName("goveal")
|
viper.SetConfigName("goveal")
|
||||||
|
viper.SetConfigType("yaml")
|
||||||
}
|
}
|
||||||
|
|
||||||
viper.AutomaticEnv() // read in environment variables that match
|
viper.AutomaticEnv() // read in environment variables that match
|
||||||
|
@ -119,10 +122,6 @@ func initConfig() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil {
|
params.WorkingDirectory = workingDir
|
||||||
log.Errorf("Failed to bind flags to viper")
|
|
||||||
}
|
|
||||||
|
|
||||||
params.Load()
|
params.Load()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/baez90/go-reveal-slides/internal/app/server"
|
"github.com/baez90/goveal/internal/app/server"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
|
@ -16,25 +16,45 @@ package rendering
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/bmatcuk/doublestar/v2"
|
"github.com/bmatcuk/doublestar/v2"
|
||||||
|
"github.com/imdario/mergo"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultParams = RevealParams{
|
||||||
|
Theme: "white",
|
||||||
|
CodeTheme: "vs",
|
||||||
|
Transition: "None",
|
||||||
|
NavigationMode: "default",
|
||||||
|
HorizontalSeparator: "===",
|
||||||
|
VerticalSeparator: "---",
|
||||||
|
SlideNumberVisibility: "all",
|
||||||
|
SlideNumberFormat: "h.v",
|
||||||
|
StyleSheets: make([]string, 0),
|
||||||
|
FilesToMonitor: make([]string, 0),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
type RevealParams struct {
|
type RevealParams struct {
|
||||||
Theme string `mapstructure:"theme"`
|
Theme string `mapstructure:"theme"`
|
||||||
CodeTheme string `mapstructure:"code-theme"`
|
CodeTheme string `mapstructure:"codeTheme"`
|
||||||
Transition string `mapstructure:"transition"`
|
Transition string `mapstructure:"transition"`
|
||||||
NavigationMode string `mapstructure:"navigationMode"`
|
NavigationMode string `mapstructure:"navigationMode"`
|
||||||
HorizontalSeparator string `mapstructure:"horizontal-separator"`
|
HorizontalSeparator string `mapstructure:"horizontalSeparator"`
|
||||||
VerticalSeparator string `mapstructure:"vertical-separator"`
|
VerticalSeparator string `mapstructure:"verticalSeparator"`
|
||||||
SlideNumberVisibility string `mapstructure:"slide-number-visibility"`
|
SlideNumberVisibility string `mapstructure:"slideNumberVisibility"`
|
||||||
SlideNumberFormat string `mapstructure:"slide-number-format"`
|
SlideNumberFormat string `mapstructure:"slideNumberFormat"`
|
||||||
StyleSheets []string `mapstructure:"stylesheets"`
|
StyleSheets []string `mapstructure:"stylesheets"`
|
||||||
FilesToMonitor []string `mapstructure:"filesToMonitor"`
|
FilesToMonitor []string `mapstructure:"filesToMonitor"`
|
||||||
|
WorkingDirectory string `mapstructure:"working-dir"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (params *RevealParams) Load() {
|
func (params *RevealParams) Load() error {
|
||||||
_ = viper.Unmarshal(params)
|
_ = viper.Unmarshal(params)
|
||||||
expandGlobs(params)
|
expandGlobs(params)
|
||||||
|
return mergo.Merge(params, &defaultParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func expandGlobs(params *RevealParams) {
|
func expandGlobs(params *RevealParams) {
|
||||||
|
@ -43,10 +63,24 @@ func expandGlobs(params *RevealParams) {
|
||||||
for _, f := range params.FilesToMonitor {
|
for _, f := range params.FilesToMonitor {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
f, err = filepath.Abs(f)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var matches []string
|
var matches []string
|
||||||
if matches, err = doublestar.Glob(f); err != nil {
|
if matches, err = doublestar.Glob(f); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for idx := range matches {
|
||||||
|
if relative, err := filepath.Rel(params.WorkingDirectory, matches[idx]); err != nil {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
matches[idx] = path.Join("/", relative)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
allFiles = append(allFiles, matches...)
|
allFiles = append(allFiles, matches...)
|
||||||
}
|
}
|
||||||
params.FilesToMonitor = allFiles
|
params.FilesToMonitor = allFiles
|
||||||
|
|
|
@ -2,6 +2,7 @@ package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,8 +24,21 @@ var etagHeaders = []string{
|
||||||
"If-Unmodified-Since",
|
"If-Unmodified-Since",
|
||||||
}
|
}
|
||||||
|
|
||||||
func NoCache(h http.Handler) http.Handler {
|
func NoCache(h http.Handler, pathsToDisableCache []string) http.Handler {
|
||||||
|
|
||||||
|
pathLookup := make(map[string]bool)
|
||||||
|
|
||||||
|
for idx := range pathsToDisableCache {
|
||||||
|
pathLookup[strings.ToLower(pathsToDisableCache[idx])] = true
|
||||||
|
}
|
||||||
|
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
if _, shouldBeHandled := pathLookup[strings.ToLower(r.URL.Path)]; !shouldBeHandled {
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Delete any ETag headers that may have been set
|
// Delete any ETag headers that may have been set
|
||||||
for _, v := range etagHeaders {
|
for _, v := range etagHeaders {
|
||||||
if r.Header.Get(v) != "" {
|
if r.Header.Get(v) != "" {
|
||||||
|
|
|
@ -79,6 +79,7 @@ func (h hashHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request
|
||||||
Hash: encodedHash,
|
Hash: encodedHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writer.Header().Set("Content-Type", "application/json")
|
||||||
encoder := json.NewEncoder(writer)
|
encoder := json.NewEncoder(writer)
|
||||||
if err = encoder.Encode(resp); err != nil {
|
if err = encoder.Encode(resp); err != nil {
|
||||||
writer.WriteHeader(500)
|
writer.WriteHeader(500)
|
||||||
|
|
|
@ -5,11 +5,15 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/baez90/go-reveal-slides/internal/app/rendering"
|
"github.com/baez90/goveal/internal/app/rendering"
|
||||||
"github.com/baez90/go-reveal-slides/internal/app/routing"
|
"github.com/baez90/goveal/internal/app/routing"
|
||||||
"github.com/markbates/pkger"
|
"github.com/markbates/pkger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
markdownFilePath = "/content.md"
|
||||||
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Host string
|
Host string
|
||||||
Port uint16
|
Port uint16
|
||||||
|
@ -31,6 +35,9 @@ func (srv HTTPServer) ListenAddress() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPServer(config Config) (srv *HTTPServer, err error) {
|
func NewHTTPServer(config Config) (srv *HTTPServer, err error) {
|
||||||
|
|
||||||
|
noCacheFiles := append(config.RevealParams.FilesToMonitor, markdownFilePath)
|
||||||
|
|
||||||
router := &routing.RegexpRouter{}
|
router := &routing.RegexpRouter{}
|
||||||
var tmplRenderer rendering.RevealRenderer
|
var tmplRenderer rendering.RevealRenderer
|
||||||
if tmplRenderer, err = rendering.NewRevealRenderer(config.RevealParams); err != nil {
|
if tmplRenderer, err = rendering.NewRevealRenderer(config.RevealParams); err != nil {
|
||||||
|
@ -50,20 +57,20 @@ func NewHTTPServer(config Config) (srv *HTTPServer, err error) {
|
||||||
fs := routing.NewLayeredFileSystem(pkger.Dir("/assets/reveal"), pkger.Dir("/assets/web"), http.Dir("."), mdFS)
|
fs := routing.NewLayeredFileSystem(pkger.Dir("/assets/reveal"), pkger.Dir("/assets/web"), http.Dir("."), mdFS)
|
||||||
|
|
||||||
//language=regexp
|
//language=regexp
|
||||||
if err = router.AddRule(`^(?i)/hash/(md5|sha1|sha2)/.*`, routing.NoCache(NewHashHandler(fs))); err != nil {
|
if err = router.AddRule(`^(?i)/hash/(md5|sha1|sha2)/.*`, NewHashHandler(fs)); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = router.AddRule("^/.*\\.md$", routing.NoCache(http.FileServer(mdFS))); err != nil {
|
if err = router.AddRule("^/.*\\.md$", http.FileServer(mdFS)); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = router.AddRule("/.+", routing.NoCache(http.FileServer(fs))); err != nil {
|
if err = router.AddRule("/.+", http.FileServer(fs)); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hostPort := fmt.Sprintf("%s:%d", config.Host, config.Port)
|
hostPort := fmt.Sprintf("%s:%d", config.Host, config.Port)
|
||||||
|
|
||||||
srv = &HTTPServer{
|
srv = &HTTPServer{
|
||||||
handler: router,
|
handler: routing.NoCache(router, noCacheFiles),
|
||||||
}
|
}
|
||||||
|
|
||||||
if srv.listener, err = net.Listen("tcp", hostPort); err != nil {
|
if srv.listener, err = net.Listen("tcp", hostPort); err != nil {
|
||||||
|
|
Loading…
Reference in a new issue