diff --git a/.gitignore b/.gitignore index f1c181e..8e93913 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,20 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out + +# Jetbrainse +.idea/ + +# VSCode +.vscode/ +.history + +assets/reveal + +# packr2 generated +*-packr.go + +# binaries +goveal + +!goveal/ \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..c1a9910 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,53 @@ +project_name: goveal +before: + hooks: + - mkdir -p ./assets/reveal + - ./download_revealjs.sh + - go mod download + - go build -v ./... + - go get -u github.com/gobuffalo/packr/v2/packr2 + - packr2 +builds: + - main: ./cmd/goveal/main.go + binary: goveal + goos: + - linux + - windows + - darwin + goarch: + - amd64 + - arm + - arm64 + ldflags: + - -w -s + env: + - CGO_ENABLED=0 + ignore: + - goos: darwin + goarch: 386 + - goos: linux + goarch: arm + goarm: 7 +archives: + - replacements: + darwin: Darwin + linux: Linux + windows: Windows + 386: i386 + amd64: x86_64 + format_overrides: + - goos: windows + format: zip + files: + - LICENSE + - README.md +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ .Tag }}-next" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9794593 --- /dev/null +++ b/Makefile @@ -0,0 +1,119 @@ +VERSION = $(shell git describe --dirty --tags --always) +REPO = github.com/baez90/go-reveal-slides +BUILD_PATH = $(REPO)/cmd/goveal +PKGS = $(shell go list ./... | grep -v /vendor/) +TEST_PKGS = $(shell find . -type f -name "*_test.go" -printf '%h\n' | sort -u) +GOARGS = GOOS=linux GOARCH=amd64 +GO_BUILD_ARGS = -ldflags="-w -s" +BINARY_NAME = goveal +DIR = $(dir $(realpath $(firstword $(MAKEFILE_LIST)))) +DEBUG_PORT = 2345 + +REVEALJS_VERSION = 3.8.0 +GORELEASER_VERSION = 0.106.0 + +.PHONY: all clean clean-all clean-vendor rebuild format revive test deps compile run debug watch watch-test cloc docs serve-docs serve-godoc ensure-revive ensure-reflex ensure-delve ensure-godoc ensure-packr2 ensure-goreleaser + +export CGO_ENABLED:=0 + +all: format compile + +clean-all: clean clean-vendor + +rebuild: clean format compile + +format: + @go fmt $(PKGS) + +revive: ensure-revive + @revive --config $(DIR)assets/lint/config.toml -exclude $(DIR)vendor/... -formatter friendly $(DIR)... + +clean: ensure-packr2 + @rm -f debug $(BINARY_NAME) + @rm -rf dist + @packr2 clean + +clean-vendor: + rm -rf vendor/ + +test: + @go test -coverprofile=./cov-raw.out -v $(TEST_PKGS) + @cat ./cov-raw.out | grep -v "generated" > ./cov.out + +cli-cover-report: + @go tool cover -func=cov.out + +html-cover-report: + @go tool cover -html=cov.out -o .coverage.html + +deps: + @go build -v ./... + +compile: deps ensure-packr2 + @$(GOARGS) packr2 build $(GO_BUILD_ARGS) -o $(DIR)/$(BINARY_NAME) $(BUILD_PATH) + +run: + @go run $(BUILD_PATH) + +debug: ensure-delve + @dlv debug \ + --headless \ + --listen=127.10.10.2:$(DEBUG_PORT) \ + --api-version=2 $(BUILD_PATH) \ + --build-flags="-tags debug" \ + -- serve --config ./examples/goveal.yaml $(DIR)/examples/slides.md + +download-reveal: + @mkdir -p $(DIR)/assets/reveal + @curl -sL https://github.com/hakimel/reveal.js/archive/$(REVEALJS_VERSION).tar.gz | tar -xvz --strip-components=1 -C $(DIR)/assets/reveal --wildcards "*.js" --wildcards "*.css" --exclude "test" --exclude "gruntfile.js" + +watch: ensure-reflex + @reflex -r '\.go$$' -s -- sh -c 'make debug' + +watch-test: ensure-reflex + @reflex -r '_test\.go$$' -s -- sh -c 'make test' + +cloc: + @cloc --vcs=git --exclude-dir=.idea,.vscode,.theia,public,docs, . + +serve-godoc: ensure-godoc + @godoc -http=:6060 + +serve-docs: ensure-reflex docs + @reflex -r '\.md$$' -s -- sh -c 'mdbook serve -d $(DIR)/public -n 127.0.0.1 $(DIR)/docs' + +docs: + @mdbook build -d $(DIR)/public $(DIR)/docs` + +test-release: ensure-goreleaser ensure-packr2 + @goreleaser --snapshot --skip-publish --rm-dist + +ensure-revive: +ifeq (, $(shell which revive)) + $(shell go get -u github.com/mgechev/revive) +endif + +ensure-delve: +ifeq (, $(shell which dlv)) + $(shell go get -u github.com/go-delve/delve/cmd/dlv) +endif + +ensure-reflex: +ifeq (, $(shell which reflex)) + $(shell go get -u github.com/cespare/reflex) +endif + +ensure-godoc: +ifeq (, $(shell which godoc)) + $(shell go get -u golang.org/x/tools/cmd/godoc) +endif + +ensure-packr2: +ifeq (, $(shell which packr2)) + $(shell go get -u github.com/gobuffalo/packr/v2/packr2) +endif + +ensure-goreleaser: +ifeq (, $(shell which goreleaser)) + $(shell curl -sL https://github.com/goreleaser/goreleaser/releases/download/v$(GORELEASER_VERSION)/goreleaser_Linux_x86_64.tar.gz | tar -xvz --exclude "*.md" -C $$GOPATH/bin) +endif \ No newline at end of file diff --git a/README.md b/README.md index da0c95b..4394123 100644 --- a/README.md +++ b/README.md @@ -1 +1,35 @@ -# go-reveal-slides \ No newline at end of file +# Goveal + +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 3.8.0 to create presentations and therefore also includes all features of Reveal.js 3.8.0. + +## Usage + +The easiest way to use `goveal` is to download a release, and run it from your `$PATH`. + +```bash +goveal serve ./slides.md +``` + +| Param | Description | Default value | +| ------------------------ | --------------------------------------------- | ----------------------- | +| `--host` | Hostname the binary is listening on | `localhost` | +| `--port` | Port the binary is listening on | `2233` | +| `--code-theme` | highlight.js theme to use | `monokai` | +| `--config` | Path to the config file see [config](#config) | `$HOME/goveal:./goveal` | +| `-h` / `--help` | shows help | | +| `--horizontal-separator` | horizontal separator to split slides | `===` | +| `--vertical-separator` | vertical separator to split slides | `---` | +| `--theme` | reveal.js theme to use | `white` | + +## Config + +Goveal supports multiple configuration mechanisms. +It tries to load a configuration file from `$HOME` or from `.` i.e. `$HOME/goveal.yaml` or `$HOME/goveal.yml` or `./goveal.yaml` and so on. + +Most options that can be set via commandline flags can also be set via configuration file (actually all but the `--config` switch does not make sense in the configuration file, does it? :wink:). +It is more a convenience feature to be able to set a theme and so on and so forth for the presentation without having to pass it every time as parameter. + +Furthermore goveal supports configuration hot reloading i.e. you can play around with different themes and the rendered theme will be changed whenever you hit the save button! + +See also an example at [`./examples/goveal.yaml`](./examples/goveal.yaml). \ No newline at end of file diff --git a/assets/lint/config.toml b/assets/lint/config.toml new file mode 100644 index 0000000..c61446b --- /dev/null +++ b/assets/lint/config.toml @@ -0,0 +1,46 @@ +ignoreGeneratedHeader = false +severity = "warning" +confidence = 0.8 +errorCode = 1 +warningCode = 1 +empty-block = true +confusing-naming = true +get-return = true +deep-exit = true +unused-parameter = true +unreachable-code = true + + +[rule.blank-imports] +[rule.context-as-argument] +[rule.context-keys-type] +[rule.dot-imports] +[rule.error-return] +[rule.error-strings] +[rule.error-naming] +[rule.exported] +[rule.if-return] +[rule.increment-decrement] +[rule.var-naming] +[rule.var-declaration] +[rule.package-comments] +[rule.range] +[rule.receiver-naming] +[rule.time-naming] +[rule.unexported-return] +[rule.indent-error-flow] +[rule.errorf] +[rule.empty-block] +[rule.superfluous-else] +[rule.unused-parameter] +[rule.unreachable-code] +[rule.redefines-builtin-id] + +[argument-limit] + arguments =[4] + +[line-length-limit] + arguments =[80] + +[rule.add-constant] + arguments = [{maxLitCount = "3",allowStrs ="\"\"",allowInts="0,1,2",allowFloats="0.0,0.,1.0,1.,2.0,2."}] \ No newline at end of file diff --git a/assets/template/reveal-markdown.tmpl b/assets/template/reveal-markdown.tmpl new file mode 100644 index 0000000..a84a670 --- /dev/null +++ b/assets/template/reveal-markdown.tmpl @@ -0,0 +1,52 @@ + + + + + + + goveal + + + + + + + + + +
+
+ +
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/main.go b/cmd/goveal/main.go similarity index 91% rename from main.go rename to cmd/goveal/main.go index 441aeb9..ebc6867 100644 --- a/main.go +++ b/cmd/goveal/main.go @@ -14,7 +14,7 @@ package main -import "github.com/baez90/go-reveal-slides/cmd" +import "github.com/baez90/go-reveal-slides/internal/app/cmd" func main() { cmd.Execute() diff --git a/cmd/root.go b/cmd/root.go deleted file mode 100644 index b19d1c1..0000000 --- a/cmd/root.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright © 2019 Peter Kurfer -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package cmd - -import ( - "fmt" - "os" - - homedir "github.com/mitchellh/go-homedir" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var cfgFile string - -// rootCmd represents the base command when called without any subcommands -var rootCmd = &cobra.Command{ - Use: "go-reveal-slides", - Short: "A brief description of your application", - Long: `A longer description that spans multiple lines and likely contains -examples and usage of using your application. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, -} - -// Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } -} - -func init() { - cobra.OnInitialize(initConfig) - - // Here you will define your flags and configuration settings. - // Cobra supports persistent flags, which, if defined here, - // will be global for your application. - rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.go-reveal-slides.yaml)") - - // Cobra also supports local flags, which will only run - // when this action is called directly. - rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") -} - -// initConfig reads in config file and ENV variables if set. -func initConfig() { - if cfgFile != "" { - // Use config file from the flag. - viper.SetConfigFile(cfgFile) - } else { - // Find home directory. - home, err := homedir.Dir() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - // Search config in home directory with name ".go-reveal-slides" (without extension). - viper.AddConfigPath(home) - viper.SetConfigName(".go-reveal-slides") - } - - viper.AutomaticEnv() // read in environment variables that match - - // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { - fmt.Println("Using config file:", viper.ConfigFileUsed()) - } -} diff --git a/download_revealjs.sh b/download_revealjs.sh new file mode 100755 index 0000000..94c9d8c --- /dev/null +++ b/download_revealjs.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +mkdir -p ./assets/reveal +curl -sL "https://github.com/hakimel/reveal.js/archive/${1:-3.8.0}.tar.gz" | tar -xvz --strip-components=1 -C ./assets/reveal --wildcards *.js --wildcards *.css --exclude test --exclude gruntfile.js diff --git a/examples/gopher.jpg b/examples/gopher.jpg new file mode 100644 index 0000000..bcf63e9 Binary files /dev/null and b/examples/gopher.jpg differ diff --git a/examples/goveal.yaml b/examples/goveal.yaml new file mode 100644 index 0000000..c8bee6d --- /dev/null +++ b/examples/goveal.yaml @@ -0,0 +1,4 @@ +theme: night +code-theme: monokai +horizontal-separator: === +vertical-separator: --- \ No newline at end of file diff --git a/examples/slides.md b/examples/slides.md new file mode 100644 index 0000000..1f96f3e --- /dev/null +++ b/examples/slides.md @@ -0,0 +1,45 @@ +# Markdown Demo + +## External 1.1 + +Content 1.1 + +asdf + +Note: This will only appear in the speaker notes window. + +--- + +## External 1.2 + +Content 1.2 + +=== + +## External 2 + +Content 2.1 + +=== + +## External 3.1 + +Content 3.1 + +--- + +## External 3.2 + +Content 3.2 + +--- + +## External 3.3 + +![External Image](https://s3.amazonaws.com/static.slid.es/logo/v2/slides-symbol-512x512.png) + +=== + +## External 4.1 + +![Local image](/local/examples/gopher.jpg) \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c77dc3c --- /dev/null +++ b/go.mod @@ -0,0 +1,22 @@ +module github.com/baez90/go-reveal-slides + +go 1.12 + +require ( + github.com/fsnotify/fsnotify v1.4.7 + github.com/gobuffalo/flect v0.1.3 // indirect + github.com/gobuffalo/packr/v2 v2.2.0 + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/kr/pty v1.1.4 // indirect + github.com/mitchellh/go-homedir v1.1.0 + github.com/sirupsen/logrus v1.4.1 + github.com/spf13/cobra v0.0.3 + github.com/spf13/pflag v1.0.3 + github.com/spf13/viper v1.3.2 + github.com/stretchr/objx v0.2.0 // indirect + golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 // indirect + golang.org/x/net v0.0.0-20190419010253-1f3472d942ba // indirect + golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a // indirect + golang.org/x/tools v0.0.0-20190419195823-c39e7748f6eb // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..0d48e15 --- /dev/null +++ b/go.sum @@ -0,0 +1,123 @@ +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +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/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e h1:JbHBQOMhE0wmpSuejnSkdnL2rULqQTwEGgVe85o7+No= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5 h1:f3Fpd5AqsFuTHUEhUeEMIFJkX8FpVnzdW+GpYxIyXkA= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2 h1:8thhT+kUJMTMy3HlX4+y9Da+BNJck+p109tqqKp7WDs= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2 h1:fq9WcL1BYrm36SzK6+aAnZ8hcp+SrmnDyAxhNx8dvJk= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0 h1:P6naWPiHm/7R3eYx/ub3VhaW9G+1xAMJ6vzACePaGPI= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0 h1:Ir9W9XIm9j7bhhkKE9cokvtTl1vBm62A/fene/ZCj6A= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754 h1:tpom+2CJmpzAWj5/VEHync2rJGi+epHNIeRSWjzGA+4= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/karrick/godirwalk v1.8.0 h1:ycpSqVon/QJJoaT1t8sae0tp1Stg21j+dyuS7OoagcA= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2 h1:JgVTCPf0uBVcUSWpyXmGpgOc62nK5HWUBKAGc3Qqa5k= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +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/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +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/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 h1:O5YqonU5IWby+w98jVUG9h7zlCWCcH4RHyPVReBmhzk= +golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84 h1:IqXQ59gzdXv58Jmm2xn0tSOR9i6HqroaOFRQ3wR/dJQ= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a h1:1n5lsVfiQW3yfsRGu98756EH1YthsFqr/5mxHduZW2A= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be h1:mI+jhqkn68ybP0ORJqunXn+fq+Eeb4hHKqLQcFICjAc= +golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a h1:XCr/YX7O0uxRkLq2k1ApNQMims9eCioF9UpzIPBDmuo= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190418235243-4796d4bd3df0 h1:lbNsjVP0Wn4gPLH85BefnAUMitP3PYyQQbeRTwdAPJw= +golang.org/x/tools v0.0.0-20190418235243-4796d4bd3df0/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190419195823-c39e7748f6eb h1:JbWwiXQ1L1jWKTGSwj6y63WT+bESGWOhXY8xoAs0yoo= +golang.org/x/tools v0.0.0-20190419195823-c39e7748f6eb/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/app/cmd/root.go b/internal/app/cmd/root.go new file mode 100644 index 0000000..77337af --- /dev/null +++ b/internal/app/cmd/root.go @@ -0,0 +1,120 @@ +// Copyright © 2019 Peter Kurfer +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "github.com/baez90/go-reveal-slides/internal/app/config" + "github.com/fsnotify/fsnotify" + "os" + + "github.com/mitchellh/go-homedir" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + defaultTheme string = "white" +) + +var ( + cfgFile string + theme string + codeTheme string + horizontalSeparator string + verticalSeparator string + rootCmd = &cobra.Command{ + Use: "goveal", + Short: "goveal is a small reveal.js server", + Long: `goveal is a single static binary to host your reveal.js based markdown presentation. +It is running a small web server that loads your markdown file, renders a complete HTML page and delivers it including all the reveal.js assets. +It is not required to restart the server when you edit the markdown - a simple reload of the page is doing all the required magic.`, + } + params config.RevealParams +) + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { + cobra.OnInitialize(initConfig) + cobra.OnInitialize(initLogging) + + 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(&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)") + +} + +func initLogging() { + log.SetFormatter(&log.TextFormatter{ + ForceColors: true, + }) +} + +// initConfig reads in config file and ENV variables if set. +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + log.Infof("Failed to determine home directory: %v", err) + } else { + viper.AddConfigPath(home) + } + + cwd, err := os.Getwd() + if err != nil { + log.Infof("Failed to determine current working directory: %v", err) + } else { + viper.AddConfigPath(cwd) + } + + viper.SetConfigName("goveal") + } + + viper.AutomaticEnv() // read in environment variables that match + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + log.Info("Using config file:", viper.ConfigFileUsed()) + + log.Info("Starting to watch config file...") + viper.WatchConfig() + viper.OnConfigChange(func(in fsnotify.Event) { + log.Info("Noticed configuration change...") + params.Load() + }) + } + + if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil { + log.Errorf("Failed to bind flags to viper") + } + + params.Load() + +} diff --git a/internal/app/cmd/serve.go b/internal/app/cmd/serve.go new file mode 100644 index 0000000..c90f069 --- /dev/null +++ b/internal/app/cmd/serve.go @@ -0,0 +1,71 @@ +// Copyright © 2019 Peter Kurfer peter.kurfer@googlemail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "github.com/baez90/go-reveal-slides/internal/app/template" + "github.com/gobuffalo/packr/v2" + "github.com/spf13/cobra" + "net/http" + "os" + + log "github.com/sirupsen/logrus" +) + +var ( + host string + port uint16 + serveCmd = &cobra.Command{ + Use: "serve", + Args: cobra.ExactArgs(1), + Short: "", + Long: ``, + Run: func(cmd *cobra.Command, args []string) { + + tmplRenderer, err := template.NewRevealRenderer(args[0], ¶ms) + + if err != nil { + log.Errorf("Failed to initialize reveal renderer due to error: %v", err) + os.Exit(1) + } + + log.Info("Setup reveal assets under route /reveal/ route...") + revealBox := packr.New("reveal-assets", "./../../../assets/reveal") + http.Handle("/reveal/", http.StripPrefix("/reveal/", http.FileServer(revealBox))) + + // + log.Info("Setup static file serving under /local/ route...") + fs := http.FileServer(http.Dir(".")) + http.Handle("/local/", http.StripPrefix("/local/", fs)) + + http.Handle("/", tmplRenderer) + + hostPort := fmt.Sprintf("%s:%d", host, port) + + log.Infof("Running at addr http://%s/", hostPort) + if err := http.ListenAndServe(hostPort, nil); err != nil { + log.Error("Error while running serve command: %v", err) + } + }, + } +) + +func init() { + rootCmd.AddCommand(serveCmd) + + serveCmd.Flags().StringVar(&host, "host", "localhost", "host the CLI should listen on") + serveCmd.Flags().Uint16Var(&port, "port", 2233, "port the CLI should listen on") +} diff --git a/internal/app/config/reveal_params.go b/internal/app/config/reveal_params.go new file mode 100644 index 0000000..7b5f3fe --- /dev/null +++ b/internal/app/config/reveal_params.go @@ -0,0 +1,31 @@ +// Copyright © 2019 Peter Kurfer peter.kurfer@googlemail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package config + +import "github.com/spf13/viper" + +type RevealParams struct { + Theme string + CodeTheme string + HorizontalSeparator string + VerticalSeparator string +} + +func (params *RevealParams) Load() { + params.Theme = viper.GetString("theme") + params.CodeTheme = viper.GetString("code-theme") + params.HorizontalSeparator = viper.GetString("horizontal-separator") + params.VerticalSeparator = viper.GetString("vertical-separator") +} diff --git a/internal/app/template/renderer.go b/internal/app/template/renderer.go new file mode 100644 index 0000000..6d87e60 --- /dev/null +++ b/internal/app/template/renderer.go @@ -0,0 +1,103 @@ +// Copyright © 2019 Peter Kurfer peter.kurfer@googlemail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package template + +import ( + "fmt" + "github.com/baez90/go-reveal-slides/internal/app/config" + "github.com/gobuffalo/packr/v2" + "html/template" + "io/ioutil" + "net/http" + "os" + "path" + + log "github.com/sirupsen/logrus" +) + +type RevealRenderer interface { + http.Handler + init() error +} + +func NewRevealRenderer(markdownPath string, params *config.RevealParams) (renderer RevealRenderer, err error) { + var info os.FileInfo + info, err = os.Stat(markdownPath) + if err != nil { + return + } + + if info.IsDir() || path.Ext(info.Name()) != ".md" { + err = fmt.Errorf("path %s did not pass sanity checks for markdown files", markdownPath) + return + } + + renderer = &revealRenderer{ + markdownPath: markdownPath, + params: params, + } + err = renderer.init() + + return +} + +type revealRenderer struct { + markdownPath string + template *template.Template + renderedTemplate string + params *config.RevealParams +} + +func (renderer *revealRenderer) init() (err error) { + templateBox := packr.New("template", "./../../../assets/template") + templateString, err := templateBox.FindString("reveal-markdown.tmpl") + if err != nil { + return + } + + renderer.template, err = template.New("index").Parse(templateString) + return +} + +func (renderer *revealRenderer) ServeHTTP(response http.ResponseWriter, request *http.Request) { + + if renderer.template == nil { + writeErrorResponse(500, "template is not set - probably error during startup", response) + return + } + + markdownContent, err := ioutil.ReadFile(renderer.markdownPath) + if err != nil { + writeErrorResponse(500, "failed to read markdown content", response) + log.Errorf("Failed to read markdown content: %v", err) + return + } + + err = renderer.template.Execute(response, struct { + Reveal config.RevealParams + MarkdownBody string + }{Reveal: *renderer.params, MarkdownBody: string(markdownContent)}) + + if err != nil { + writeErrorResponse(500, "Failed to render Markdown to template", response) + log.Errorf("Failed to render Markdown template: %v", err) + } +} + +func writeErrorResponse(code int, msg string, response http.ResponseWriter) { + response.WriteHeader(code) + _, err := response.Write([]byte(msg)) + log.Errorf("Failed to write error reponse: %v", err) +} diff --git a/packr2_hack.go b/packr2_hack.go new file mode 100644 index 0000000..8d39157 --- /dev/null +++ b/packr2_hack.go @@ -0,0 +1,20 @@ +// Copyright © 2019 Peter Kurfer peter.kurfer@googlemail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package go_reveal_slides + +import ( + _ "github.com/baez90/go-reveal-slides/internal/app/cmd" + _ "github.com/baez90/go-reveal-slides/internal/app/template" +)