diff --git a/README.md b/README.md index 9eeaa5a..be8c6b2 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ Server that renders markdown files and live updates the page each time that the file is updated. ![screenshot00](https://raw.githubusercontent.com/arnaucube/md-live-server/master/screenshot00.png 'screenshot00') +*(Current visual style is more similar to GitHub's style)* ## Usage Put the binary file `md-live-server` in your `$PATH`, and then go to the directory where are the markdown files that want to live render, and just use: @@ -23,4 +24,3 @@ set backupcopy=yes - [x] LaTex support - [x] mermaidjs - [ ] graphviz -- [ ] colour `` with syntax highlighting diff --git a/css.go b/css.go new file mode 100644 index 0000000..280f7b0 --- /dev/null +++ b/css.go @@ -0,0 +1,3383 @@ +package main + +// The CSS code in this file is originally from https://github.com/sindresorhus/github-markdown-css +// under MIT license + +const cssTemplate = ` + +` diff --git a/go.mod b/go.mod index fdf4fcf..f456072 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module md-live-server -go 1.19 +go 1.21 require ( github.com/fatih/color v1.9.0 diff --git a/main.go b/main.go index 95e11f4..9b9a864 100644 --- a/main.go +++ b/main.go @@ -8,12 +8,13 @@ import ( "strings" "time" + "github.com/fatih/color" "github.com/fsnotify/fsnotify" "github.com/gorilla/mux" "github.com/gorilla/websocket" ) -const version = "v0_20230804" +const version = "v0_20240128" var ( upgrader = websocket.Upgrader{ @@ -31,6 +32,10 @@ type PageModel struct { func main() { fmt.Println("md-live-server version:", version) + // fill the CSS into the HTML templates + dirTemplate = fillCSSintoTemplate(dirTemplate) + htmlTemplate = fillCSSintoTemplate(htmlTemplate) + router := mux.NewRouter() router.HandleFunc("/", getDir).Methods("GET") router.HandleFunc("/{path}", getPage).Methods("GET") @@ -76,7 +81,11 @@ func getPage(w http.ResponseWriter, r *http.Request) { } content, err := fileToHTML(path) - check(err) + if err != nil { + color.Red(err.Error()) + fmt.Fprintf(w, errTemplate) + return + } var page PageModel page.Title = path diff --git a/templates.go b/templates.go index 6b97f53..37425d7 100644 --- a/templates.go +++ b/templates.go @@ -1,25 +1,41 @@ package main +import ( + "strings" +) + // html templates are here instead of an .html file to avoid depending on external files // in this way, everything is inside the binary -const dirTemplate = ` +func fillCSSintoTemplate(template string) string { + if strings.Contains(template, "[CSS]") { + template = strings.Replace(template, "[CSS]", cssTemplate, -1) + } + return template +} + +var dirTemplate = ` {{.Title}} +[CSS] - + +
{{.Content}} @@ -29,13 +45,15 @@ body { if (theme === "light") { document.getElementById("themeSwitcher").checked = false; document.body.className = theme; + } else { + document.getElementById("themeSwitcher").checked = true; } function switchThemeClick() { theme = localStorage.getItem("theme"); if (theme === "light") { document.getElementById("themeSwitcher").checked = true; - theme = "dark"; + theme = "dark-theme"; localStorage.setItem("theme", theme); } else { document.getElementById("themeSwitcher").checked = false; @@ -46,105 +64,34 @@ body { } +
` -const htmlTemplate = ` +var htmlTemplate = ` {{.Title}} +[CSS] - + +
root
@@ -219,13 +166,15 @@ td{ if (theme === "light") { document.getElementById("themeSwitcher").checked = false; document.body.className = theme; + } else { + document.getElementById("themeSwitcher").checked = true; } function switchThemeClick() { theme = localStorage.getItem("theme"); if (theme === "light") { document.getElementById("themeSwitcher").checked = true; - theme = "dark"; + theme = "dark-theme"; localStorage.setItem("theme", theme); } else { document.getElementById("themeSwitcher").checked = false; @@ -236,6 +185,7 @@ td{ } +
` diff --git a/test.md b/test.md index 102fa03..8005821 100644 --- a/test.md +++ b/test.md @@ -13,6 +13,7 @@ ### third header Asdf asdf asdf +- Lorem ipsum bla bla `ipsum` bla bla - Lorem ipsum bla bla `ipsum` bla bla ### Some code @@ -46,3 +47,16 @@ graph LR B-->C[fa:fa-ban forbidden] B-->D(fa:fa-spinner); + + +## Lorem ipsum + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Fermentum dui faucibus in ornare quam viverra orci sagittis. Augue lacus viverra vitae congue eu consequat ac. Integer quis auctor elit sed vulputate mi. Dolor purus non enim praesent elementum facilisis. In ornare quam viverra orci sagittis. Feugiat vivamus at augue eget. Dui nunc mattis enim ut. Pellentesque diam volutpat commodo sed egestas. Ut consequat semper viverra nam libero justo. Nisi porta lorem mollis aliquam ut porttitor. Nulla facilisi etiam dignissim diam quis enim. Vestibulum sed arcu non odio. + +Eleifend quam adipiscing vitae proin sagittis nisl rhoncus. Vel risus commodo viverra maecenas accumsan lacus vel facilisis. Integer enim neque volutpat ac tincidunt vitae semper quis lectus. Faucibus scelerisque eleifend donec pretium. Eu facilisis sed odio morbi quis commodo. Phasellus vestibulum lorem sed risus ultricies tristique nulla. Magnis dis parturient montes nascetur ridiculus mus. Lorem mollis aliquam ut porttitor leo a. A lacus vestibulum sed arcu. Egestas fringilla phasellus faucibus scelerisque eleifend. Erat velit scelerisque in dictum non consectetur a erat. Neque sodales ut etiam sit amet. Montes nascetur ridiculus mus mauris vitae. + +Ac feugiat sed lectus vestibulum mattis. Cum sociis natoque penatibus et magnis dis. Lectus urna duis convallis convallis tellus id interdum velit. Fermentum leo vel orci porta non pulvinar. Volutpat diam ut venenatis tellus. Sagittis id consectetur purus ut. Felis donec et odio pellentesque diam volutpat. Tortor dignissim convallis aenean et tortor at risus viverra. Justo donec enim diam vulputate ut pharetra. A cras semper auctor neque. Id interdum velit laoreet id donec ultrices. Ac auctor augue mauris augue neque gravida in fermentum et. At tellus at urna condimentum mattis pellentesque. Diam quam nulla porttitor massa id neque aliquam vestibulum. Cursus vitae congue mauris rhoncus aenean. Nunc sed id semper risus in hendrerit. + +Ornare arcu odio ut sem. Volutpat ac tincidunt vitae semper quis lectus. Elit scelerisque mauris pellentesque pulvinar. Metus dictum at tempor commodo ullamcorper a lacus vestibulum. Tincidunt lobortis feugiat vivamus at. Quam id leo in vitae turpis massa sed elementum tempus. Feugiat in fermentum posuere urna nec tincidunt. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin. Pharetra et ultrices neque ornare aenean. Dui vivamus arcu felis bibendum ut tristique et egestas. Ultrices eros in cursus turpis massa. Parturient montes nascetur ridiculus mus mauris vitae. Urna nec tincidunt praesent semper feugiat nibh sed pulvinar. Egestas dui id ornare arcu odio ut sem nulla pharetra. Vel facilisis volutpat est velit egestas. Cras semper auctor neque vitae tempus quam pellentesque. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. + +Etiam erat velit scelerisque in. Mauris vitae ultricies leo integer. Duis convallis convallis tellus id interdum velit laoreet id donec. Vitae elementum curabitur vitae nunc sed velit dignissim. Arcu bibendum at varius vel pharetra vel turpis nunc. Pretium aenean pharetra magna ac placerat vestibulum. Velit egestas dui id ornare arcu odio. At tempor commodo ullamcorper a lacus vestibulum sed arcu non. Blandit libero volutpat sed cras ornare. Nulla facilisi nullam vehicula ipsum a arcu cursus. Interdum posuere lorem ipsum dolor sit amet. Turpis egestas maecenas pharetra convallis posuere morbi. Nunc sed blandit libero volutpat. Felis eget velit aliquet sagittis id consectetur purus ut. Ac felis donec et odio pellentesque diam volutpat. Varius sit amet mattis vulputate enim nulla aliquet porttitor lacus. diff --git a/utils.go b/utils.go index 3d442eb..96820a3 100644 --- a/utils.go +++ b/utils.go @@ -25,13 +25,13 @@ func readDir(dirpath string) []string { return elems } -func readFile(path string) string { +func readFile(path string) (string, error) { dat, err := ioutil.ReadFile(path) if err != nil { color.Red(path) + return "", err } - check(err) - return string(dat) + return string(dat), nil } func fileToHTML(path string) (string, error) { @@ -39,7 +39,10 @@ func fileToHTML(path string) (string, error) { parser.Autolink | parser.Strikethrough | parser.SpaceHeadings | parser.HeadingIDs | parser.BackslashLineBreak | parser.DefinitionLists | parser.MathJax - mdcontent := readFile(path) + mdcontent, err := readFile(path) + if err != nil { + return "", err + } mdParser := parser.NewWithExtensions(mdExtensions) htmlcontent := markdown.ToHTML([]byte(mdcontent), mdParser, nil)