From 8d69c24f5c8f2758932b04d23701a8adc143c9e7 Mon Sep 17 00:00:00 2001 From: Mattias Wadman Date: Mon, 31 Oct 2022 11:15:05 +0100 Subject: [PATCH] Replace go.rice module with std embed --- .gitattributes | 1 - fileserver/fileserver.go | 2 +- fileserver/fileserver_test.go | 20 +++++----- ricetemp/ricetemp.go => fstmpl/fstmpl.go | 37 ++++++++++-------- go.mod | 3 +- go.sum | 10 ----- livereload/{static => }/LICENSE | 0 livereload/{static => }/client.js | 0 livereload/livereload.go | 11 ++++-- livereload/rice-box.go | 48 ------------------------ modd.conf | 19 +--------- rice-box.go | 48 ------------------------ route_test.go | 16 ++------ server.go | 6 +-- server_test.go | 8 ++-- templates/embed.go | 9 +++++ 16 files changed, 64 insertions(+), 174 deletions(-) rename ricetemp/ricetemp.go => fstmpl/fstmpl.go (52%) rename livereload/{static => }/LICENSE (100%) rename livereload/{static => }/client.js (100%) delete mode 100644 livereload/rice-box.go delete mode 100644 rice-box.go create mode 100644 templates/embed.go diff --git a/.gitattributes b/.gitattributes index 890aba2..e69de29 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +0,0 @@ -rice-box.go binary diff --git a/fileserver/fileserver.go b/fileserver/fileserver.go index f188800..524504f 100644 --- a/fileserver/fileserver.go +++ b/fileserver/fileserver.go @@ -229,7 +229,7 @@ func localRedirect(w http.ResponseWriter, r *http.Request, newPath string) { // To use the operating system's file system implementation, // use http.Dir: // -// http.Handle("/", &fileserver.FileServer{Root: http.Dir("/tmp")}) +// http.Handle("/", &fileserver.FileServer{Root: http.Dir("/tmp")}) type FileServer struct { Version string Root http.FileSystem diff --git a/fileserver/fileserver_test.go b/fileserver/fileserver_test.go index 1a7fcf2..220addb 100644 --- a/fileserver/fileserver_test.go +++ b/fileserver/fileserver_test.go @@ -23,10 +23,10 @@ import ( "testing" "time" - rice "github.com/GeertJohan/go.rice" + "github.com/cortesi/devd/fstmpl" "github.com/cortesi/devd/inject" - "github.com/cortesi/devd/ricetemp" "github.com/cortesi/devd/routespec" + "github.com/cortesi/devd/templates" "github.com/cortesi/termlog" ) @@ -40,7 +40,7 @@ func ServeFile(w http.ResponseWriter, r *http.Request, name string) { "version", http.Dir(dir), inject.CopyInject{}, - ricetemp.MustMakeTemplates(rice.MustFindBox("../templates")), + fstmpl.MustMakeTemplates(templates.FS), []routespec.RouteSpec{}, "", } @@ -168,7 +168,7 @@ func TestFSRedirect(t *testing.T) { "version", http.Dir("."), inject.CopyInject{}, - ricetemp.MustMakeTemplates(rice.MustFindBox("../templates")), + fstmpl.MustMakeTemplates(templates.FS), []routespec.RouteSpec{}, "", }, @@ -208,7 +208,7 @@ func _TestFileServerCleans(t *testing.T) { }, }, inject.CopyInject{}, - ricetemp.MustMakeTemplates(rice.MustFindBox("../templates")), + fstmpl.MustMakeTemplates(templates.FS), []routespec.RouteSpec{}, "", } @@ -250,7 +250,7 @@ func TestFileServerImplicitLeadingSlash(t *testing.T) { "version", http.Dir(tempDir), inject.CopyInject{}, - ricetemp.MustMakeTemplates(rice.MustFindBox("../templates")), + fstmpl.MustMakeTemplates(templates.FS), []routespec.RouteSpec{}, "", } @@ -415,7 +415,7 @@ func TestServeIndexHtml(t *testing.T) { "version", http.Dir("."), inject.CopyInject{}, - ricetemp.MustMakeTemplates(rice.MustFindBox("../templates")), + fstmpl.MustMakeTemplates(templates.FS), []routespec.RouteSpec{}, "", } @@ -444,7 +444,7 @@ func TestFileServerZeroByte(t *testing.T) { "version", http.Dir("."), inject.CopyInject{}, - ricetemp.MustMakeTemplates(rice.MustFindBox("../templates")), + fstmpl.MustMakeTemplates(templates.FS), []routespec.RouteSpec{}, "", } @@ -539,7 +539,7 @@ func TestNotFoundOverride(t *testing.T) { "version", fsys, inject.CopyInject{}, - ricetemp.MustMakeTemplates(rice.MustFindBox("../templates")), + fstmpl.MustMakeTemplates(templates.FS), []routespec.RouteSpec{ {Host: "", Path: "/", Value: "foo.html"}, }, @@ -611,7 +611,7 @@ func TestDirectoryIfNotModified(t *testing.T) { "version", fsys, inject.CopyInject{}, - ricetemp.MustMakeTemplates(rice.MustFindBox("../templates")), + fstmpl.MustMakeTemplates(templates.FS), []routespec.RouteSpec{}, "", } diff --git a/ricetemp/ricetemp.go b/fstmpl/fstmpl.go similarity index 52% rename from ricetemp/ricetemp.go rename to fstmpl/fstmpl.go index 7a788cb..ee54aca 100644 --- a/ricetemp/ricetemp.go +++ b/fstmpl/fstmpl.go @@ -1,12 +1,13 @@ -// Package ricetemp makes templates from a ricebox. -package ricetemp +// Package fstmpl makes templates from a fs.FS +package fstmpl import ( "html/template" + "io" + "io/fs" "os" "strings" - "github.com/GeertJohan/go.rice" "github.com/dustin/go-humanize" ) @@ -25,16 +26,16 @@ func fileType(f os.FileInfo) string { } // MustMakeTemplates makes templates, and panic on error -func MustMakeTemplates(rb *rice.Box) *template.Template { - templates, err := MakeTemplates(rb) +func MustMakeTemplates(fs fs.ReadDirFS) *template.Template { + templates, err := MakeTemplates(fs) if err != nil { panic(err) } return templates } -// MakeTemplates takes a rice.Box and returns a html.Template -func MakeTemplates(rb *rice.Box) (*template.Template, error) { +// MakeTemplates takes a fs.ReadDirFS and returns a html.Template +func MakeTemplates(fs fs.ReadDirFS) (*template.Template, error) { tmpl := template.New("") funcMap := template.FuncMap{ @@ -44,14 +45,20 @@ func MakeTemplates(rb *rice.Box) (*template.Template, error) { } tmpl.Funcs(funcMap) - err := rb.Walk("", func(path string, info os.FileInfo, err error) error { - if !info.IsDir() { - _, err := tmpl.New(path).Parse(rb.MustString(path)) - if err != nil { - return err - } + ds, err := fs.ReadDir(".") + if err != nil { + return nil, err + } + + for _, d := range ds { + f, _ := fs.Open(d.Name()) + fbs, _ := io.ReadAll(f) + + _, err := tmpl.New(d.Name()).Parse(string(fbs)) + if err != nil { + return nil, err } - return nil - }) + } + return tmpl, err } diff --git a/go.mod b/go.mod index 9764bc3..5e690fc 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/cortesi/devd go 1.25.0 require ( - github.com/GeertJohan/go.rice v1.0.3 github.com/cortesi/moddwatch v0.1.0 github.com/cortesi/termlog v0.0.0-20250523085554-f86697764bb0 github.com/dustin/go-humanize v1.0.1 @@ -21,7 +20,7 @@ require ( github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect github.com/bmatcuk/doublestar v1.3.4 // indirect - github.com/daaku/go.zipexe v1.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect diff --git a/go.sum b/go.sum index 5c029d3..11b50d3 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,3 @@ -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.3 h1:k5viR+xGtIhF61125vCE1cmJ5957RQGXG6dmbaWZSmI= -github.com/GeertJohan/go.rice v1.0.3/go.mod h1:XVdrU4pW00M4ikZed5q56tPf1v2KwnIKeIdc9CBYNt4= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= @@ -13,8 +9,6 @@ github.com/cortesi/moddwatch v0.1.0/go.mod h1:PFkhcmmwsRMQ76IMjKbaIIMcGQt7BSMtFO github.com/cortesi/termlog v0.0.0-20250523085554-f86697764bb0 h1:i6kD96U0+1ht4pxADqe3Vz+P44SN8TeBS4A5bPidu90= github.com/cortesi/termlog v0.0.0-20250523085554-f86697764bb0/go.mod h1:GjgJh2CGR2AEiiH4po295B0ZEKRrt+0P1mlLrGwos+w= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/daaku/go.zipexe v1.0.2 h1:Zg55YLYTr7M9wjKn8SY/WcpuuEi+kR2u4E8RhvpyXmk= -github.com/daaku/go.zipexe v1.0.2/go.mod h1:5xWogtqlYnfBXkSB1o9xysukNP9GTvaNkqzUZbt3Bw8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -29,7 +23,6 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/juju/ratelimit v1.0.2 h1:sRxmtRiajbvrcLQT7S+JbqU0ntsb9W2yhSdNN8tWfaI= github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -44,7 +37,6 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nkovacs/streamquote v1.0.0/go.mod h1:BN+NaZ2CmdKqUuTUXUEm9j95B2TRbpOWpxbJYzzgUsc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rjeczalik/notify v0.9.3 h1:6rJAzHTGKXGj76sbRgDiDcYj/HniypXmSJo1SWakZeY= @@ -55,8 +47,6 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/livereload/static/LICENSE b/livereload/LICENSE similarity index 100% rename from livereload/static/LICENSE rename to livereload/LICENSE diff --git a/livereload/static/client.js b/livereload/client.js similarity index 100% rename from livereload/static/client.js rename to livereload/client.js diff --git a/livereload/livereload.go b/livereload/livereload.go index e0cc4a2..18219d1 100644 --- a/livereload/livereload.go +++ b/livereload/livereload.go @@ -3,17 +3,23 @@ package livereload import ( + _ "embed" "net/http" "regexp" "strings" "sync" - "github.com/GeertJohan/go.rice" "github.com/cortesi/devd/inject" "github.com/cortesi/termlog" "github.com/gorilla/websocket" ) +//go:embed client.js +var clientJS []byte + +//go:embed LICENSE +var license []byte + // Reloader triggers a reload type Reloader interface { Reload(paths []string) @@ -130,8 +136,7 @@ func (s *Server) Watch(ch chan []string) { // ServeScript is a handler function that serves the livereload JavaScript file func (s *Server) ServeScript(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("Content-Type", "application/javascript") - clientBox := rice.MustFindBox("static") - _, err := rw.Write(clientBox.MustBytes("client.js")) + _, err := rw.Write(clientJS) if err != nil { s.logger.Warn("Error serving livereload script: %s", err) } diff --git a/livereload/rice-box.go b/livereload/rice-box.go deleted file mode 100644 index 8111e98..0000000 --- a/livereload/rice-box.go +++ /dev/null @@ -1,48 +0,0 @@ -package livereload - -import ( - "github.com/GeertJohan/go.rice/embedded" - "time" -) - -func init() { - - // define files - file2 := &embedded.EmbeddedFile{ - Filename: "LICENSE", - FileModTime: time.Unix(1503017339, 0), - Content: string("// reconnecting-websocket - MIT License:\n//\n// Copyright (c) 2010-2012, Joe Walnes\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n"), - } - file3 := &embedded.EmbeddedFile{ - Filename: "client.js", - FileModTime: time.Unix(1503017339, 0), - Content: string("(function() {\n if (!('WebSocket' in window)) {\n return;\n }\n\n function DevdReconnectingWebSocket(url, protocols, options) {\n\n // Default settings\n var settings = {\n\n /** Whether this instance should log debug messages. */\n debug: false,\n\n /** Whether or not the websocket should attempt to connect immediately upon instantiation. */\n automaticOpen: true,\n\n /** The number of milliseconds to delay before attempting to reconnect. */\n reconnectInterval: 1000,\n /** The maximum number of milliseconds to delay a reconnection attempt. */\n maxReconnectInterval: 30000,\n /** The rate of increase of the reconnect delay. Allows reconnect attempts to back off when problems persist. */\n reconnectDecay: 1.5,\n\n /** The maximum time in milliseconds to wait for a connection to succeed before closing and retrying. */\n timeoutInterval: 2000,\n\n /** The maximum number of reconnection attempts to make. Unlimited if null. */\n maxReconnectAttempts: null,\n\n /** The binary type, possible values 'blob' or 'arraybuffer', default 'blob'. */\n binaryType: 'blob'\n }\n if (!options) {\n options = {};\n }\n\n // Overwrite and define settings with options if they exist.\n for (var key in settings) {\n if (typeof options[key] !== 'undefined') {\n this[key] = options[key];\n } else {\n this[key] = settings[key];\n }\n }\n\n // These should be treated as read-only properties\n\n /** The URL as resolved by the constructor. This is always an absolute URL. Read only. */\n this.url = url;\n\n /** The number of attempted reconnects since starting, or the last successful connection. Read only. */\n this.reconnectAttempts = 0;\n\n /**\n * The current state of the connection.\n * Can be one of: WebSocket.CONNECTING, WebSocket.OPEN, WebSocket.CLOSING, WebSocket.CLOSED\n * Read only.\n */\n this.readyState = WebSocket.CONNECTING;\n\n /**\n * A string indicating the name of the sub-protocol the server selected; this will be one of\n * the strings specified in the protocols parameter when creating the WebSocket object.\n * Read only.\n */\n this.protocol = null;\n\n // Private state variables\n\n var self = this;\n var ws;\n var forcedClose = false;\n var timedOut = false;\n var eventTarget = document.createElement('div');\n\n // Wire up \"on*\" properties as event handlers\n\n eventTarget.addEventListener('open', function(event) {\n self.onopen(event);\n });\n eventTarget.addEventListener('close', function(event) {\n self.onclose(event);\n });\n eventTarget.addEventListener('connecting', function(event) {\n self.onconnecting(event);\n });\n eventTarget.addEventListener('message', function(event) {\n self.onmessage(event);\n });\n eventTarget.addEventListener('error', function(event) {\n self.onerror(event);\n });\n\n // Expose the API required by EventTarget\n\n this.addEventListener = eventTarget.addEventListener.bind(eventTarget);\n this.removeEventListener = eventTarget.removeEventListener.bind(eventTarget);\n this.dispatchEvent = eventTarget.dispatchEvent.bind(eventTarget);\n\n /**\n * This function generates an event that is compatible with standard\n * compliant browsers and IE9 - IE11\n *\n * This will prevent the error:\n * Object doesn't support this action\n *\n * http://stackoverflow.com/questions/19345392/why-arent-my-parameters-getting-passed-through-to-a-dispatched-event/19345563#19345563\n * @param s String The name that the event should use\n * @param args Object an optional object that the event will use\n */\n function generateEvent(s, args) {\n var evt = document.createEvent(\"CustomEvent\");\n evt.initCustomEvent(s, false, false, args);\n return evt;\n };\n\n this.open = function(reconnectAttempt) {\n ws = new WebSocket(self.url, protocols || []);\n ws.binaryType = this.binaryType;\n\n if (reconnectAttempt) {\n if (this.maxReconnectAttempts && this.reconnectAttempts > this.maxReconnectAttempts) {\n return;\n }\n } else {\n eventTarget.dispatchEvent(generateEvent('connecting'));\n this.reconnectAttempts = 0;\n }\n\n if (self.debug || DevdReconnectingWebSocket.debugAll) {\n console.debug('DevdReconnectingWebSocket', 'attempt-connect', self.url);\n }\n\n var localWs = ws;\n var timeout = setTimeout(function() {\n if (self.debug || DevdReconnectingWebSocket.debugAll) {\n console.debug('DevdReconnectingWebSocket', 'connection-timeout', self.url);\n }\n timedOut = true;\n localWs.close();\n timedOut = false;\n }, self.timeoutInterval);\n\n ws.onopen = function(event) {\n clearTimeout(timeout);\n if (self.debug || DevdReconnectingWebSocket.debugAll) {\n console.debug('DevdReconnectingWebSocket', 'onopen', self.url);\n }\n self.protocol = ws.protocol;\n self.readyState = WebSocket.OPEN;\n self.reconnectAttempts = 0;\n var e = generateEvent('open');\n e.isReconnect = reconnectAttempt;\n reconnectAttempt = false;\n eventTarget.dispatchEvent(e);\n };\n\n ws.onclose = function(event) {\n clearTimeout(timeout);\n ws = null;\n if (forcedClose) {\n self.readyState = WebSocket.CLOSED;\n eventTarget.dispatchEvent(generateEvent('close'));\n } else {\n self.readyState = WebSocket.CONNECTING;\n var e = generateEvent('connecting');\n e.code = event.code;\n e.reason = event.reason;\n e.wasClean = event.wasClean;\n eventTarget.dispatchEvent(e);\n if (!reconnectAttempt && !timedOut) {\n if (self.debug || DevdReconnectingWebSocket.debugAll) {\n console.debug('DevdReconnectingWebSocket', 'onclose', self.url);\n }\n eventTarget.dispatchEvent(generateEvent('close'));\n }\n\n var timeout = self.reconnectInterval * Math.pow(self.reconnectDecay, self.reconnectAttempts);\n setTimeout(function() {\n self.reconnectAttempts++;\n self.open(true);\n }, timeout > self.maxReconnectInterval ? self.maxReconnectInterval : timeout);\n }\n };\n ws.onmessage = function(event) {\n if (self.debug || DevdReconnectingWebSocket.debugAll) {\n console.debug('DevdReconnectingWebSocket', 'onmessage', self.url, event.data);\n }\n var e = generateEvent('message');\n e.data = event.data;\n eventTarget.dispatchEvent(e);\n };\n ws.onerror = function(event) {\n if (self.debug || DevdReconnectingWebSocket.debugAll) {\n console.debug('DevdReconnectingWebSocket', 'onerror', self.url, event);\n }\n eventTarget.dispatchEvent(generateEvent('error'));\n };\n }\n\n // Whether or not to create a websocket upon instantiation\n if (this.automaticOpen == true) {\n this.open(false);\n }\n\n /**\n * Transmits data to the server over the WebSocket connection.\n *\n * @param data a text string, ArrayBuffer or Blob to send to the server.\n */\n this.send = function(data) {\n if (ws) {\n if (self.debug || DevdReconnectingWebSocket.debugAll) {\n console.debug('DevdReconnectingWebSocket', 'send', self.url, data);\n }\n return ws.send(data);\n } else {\n throw 'INVALID_STATE_ERR : Pausing to reconnect websocket';\n }\n };\n\n /**\n * Closes the WebSocket connection or connection attempt, if any.\n * If the connection is already CLOSED, this method does nothing.\n */\n this.close = function(code, reason) {\n // Default CLOSE_NORMAL code\n if (typeof code == 'undefined') {\n code = 1000;\n }\n forcedClose = true;\n if (ws) {\n ws.close(code, reason);\n }\n };\n\n /**\n * Additional public API method to refresh the connection if still open (close, re-open).\n * For example, if the app suspects bad data / missed heart beats, it can try to refresh.\n */\n this.refresh = function() {\n if (ws) {\n ws.close();\n }\n };\n }\n\n /**\n * An event listener to be called when the WebSocket connection's readyState changes to OPEN;\n * this indicates that the connection is ready to send and receive data.\n */\n DevdReconnectingWebSocket.prototype.onopen = function(event) {};\n /** An event listener to be called when the WebSocket connection's readyState changes to CLOSED. */\n DevdReconnectingWebSocket.prototype.onclose = function(event) {};\n /** An event listener to be called when a connection begins being attempted. */\n DevdReconnectingWebSocket.prototype.onconnecting = function(event) {};\n /** An event listener to be called when a message is received from the server. */\n DevdReconnectingWebSocket.prototype.onmessage = function(event) {};\n /** An event listener to be called when an error occurs. */\n DevdReconnectingWebSocket.prototype.onerror = function(event) {};\n\n /**\n * Whether all instances of DevdReconnectingWebSocket should log debug messages.\n * Setting this to true is the equivalent of setting all instances of DevdReconnectingWebSocket.debug to true.\n */\n DevdReconnectingWebSocket.debugAll = false;\n\n DevdReconnectingWebSocket.CONNECTING = WebSocket.CONNECTING;\n DevdReconnectingWebSocket.OPEN = WebSocket.OPEN;\n DevdReconnectingWebSocket.CLOSING = WebSocket.CLOSING;\n DevdReconnectingWebSocket.CLOSED = WebSocket.CLOSED;\n\n window.DevdReconnectingWebSocket = DevdReconnectingWebSocket;\n\n var proto = \"ws://\";\n if (window.location.protocol == \"https:\") {\n proto = \"wss://\";\n }\n\n ws = new DevdReconnectingWebSocket(\n proto + window.location.host + \"/.devd.livereload\",\n null,\n {\n debug: true,\n maxReconnectInterval: 3000,\n }\n )\n ws.onmessage = function(event) {\n if (event.data == \"page\") {\n ws.close();\n location.reload();\n } else if (event.data == \"css\") {\n // This snippet pinched from quickreload, under the MIT license:\n // https://github.com/bjoerge/quickreload/blob/master/client.js\n var killcache = '__devd=' + new Date().getTime();\n var stylesheets = Array.prototype.slice.call(\n document.querySelectorAll('link[rel=\"stylesheet\"]')\n );\n stylesheets.forEach(function (el) {\n var href = el.href.replace(/(&|\\?)__devd\\=\\d+/, '');\n el.href = '';\n el.href = href + (href.indexOf(\"?\") == -1 ? '?' : '&') + killcache;\n });\n }\n }\n window.addEventListener(\"beforeunload\", function(e) {\n ws.close();\n delete e.returnValue;\n return;\n });\n})();\n"), - } - - // define dirs - dir1 := &embedded.EmbeddedDir{ - Filename: "", - DirModTime: time.Unix(1503017339, 0), - ChildFiles: []*embedded.EmbeddedFile{ - file2, // "LICENSE" - file3, // "client.js" - - }, - } - - // link ChildDirs - dir1.ChildDirs = []*embedded.EmbeddedDir{} - - // register embeddedBox - embedded.RegisterEmbeddedBox(`static`, &embedded.EmbeddedBox{ - Name: `static`, - Time: time.Unix(1503017339, 0), - Dirs: map[string]*embedded.EmbeddedDir{ - "": dir1, - }, - Files: map[string]*embedded.EmbeddedFile{ - "LICENSE": file2, - "client.js": file3, - }, - }) -} diff --git a/modd.conf b/modd.conf index 082bf70..6f6f30b 100644 --- a/modd.conf +++ b/modd.conf @@ -1,23 +1,8 @@ - -templates/*.html { - prep: " - rice embed-go - " -} - -livereload/static/*.js { - indir: ./livereload - prep: " - # rice embed-go livereload - rice embed-go - " -} - -**/*.go !vendor/** { +**/*.go livereload/*.js templates/*.html !vendor/** { prep: go test @dirmods } -**/*.go !**/*_test.go { +**/*.go livereload/*.js templates/*.html !**/*_test.go { prep: go install ./cmd/devd daemon +sigterm: devd -ml ./tmp } diff --git a/rice-box.go b/rice-box.go deleted file mode 100644 index 851c8d1..0000000 --- a/rice-box.go +++ /dev/null @@ -1,48 +0,0 @@ -package devd - -import ( - "github.com/GeertJohan/go.rice/embedded" - "time" -) - -func init() { - - // define files - file2 := &embedded.EmbeddedFile{ - Filename: "404.html", - FileModTime: time.Unix(1503017339, 0), - Content: string("\n \n \n \n \n

404: Page not found

\n
\n {{ .Version }}\n
\n \n\n"), - } - file3 := &embedded.EmbeddedFile{ - Filename: "dirlist.html", - FileModTime: time.Unix(1503017339, 0), - Content: string("\n \n \n \n \n

{{.Name}}

\n \n {{ range .Files }}\n \t\t\t\n \n \n \n \n {{ else }}\n \n {{ end }}\n
\n {{.Name}}{{ if .IsDir }}/{{ end }}\n {{ .Size | bytes }}{{ .ModTime | reltime }}
No files found.
\n
\n {{ .Version }}\n
\n \n\n"), - } - - // define dirs - dir1 := &embedded.EmbeddedDir{ - Filename: "", - DirModTime: time.Unix(1503017339, 0), - ChildFiles: []*embedded.EmbeddedFile{ - file2, // "404.html" - file3, // "dirlist.html" - - }, - } - - // link ChildDirs - dir1.ChildDirs = []*embedded.EmbeddedDir{} - - // register embeddedBox - embedded.RegisterEmbeddedBox(`templates`, &embedded.EmbeddedBox{ - Name: `templates`, - Time: time.Unix(1503017339, 0), - Dirs: map[string]*embedded.EmbeddedDir{ - "": dir1, - }, - Files: map[string]*embedded.EmbeddedFile{ - "404.html": file2, - "dirlist.html": file3, - }, - }) -} diff --git a/route_test.go b/route_test.go index 9aa97dd..c48332c 100644 --- a/route_test.go +++ b/route_test.go @@ -6,9 +6,9 @@ import ( "strings" "testing" - rice "github.com/GeertJohan/go.rice" + "github.com/cortesi/devd/fstmpl" "github.com/cortesi/devd/inject" - "github.com/cortesi/devd/ricetemp" + "github.com/cortesi/devd/templates" ) func tFilesystemEndpoint(s string) *filesystemEndpoint { @@ -121,11 +121,7 @@ func TestForwardEndpoint(t *testing.T) { if err != nil { t.Errorf("Unexpected error: %s", err) } - rb, err := rice.FindBox("templates") - if err != nil { - t.Error(err) - } - templates, err := ricetemp.MakeTemplates(rb) + templates, err := fstmpl.MakeTemplates(templates.FS) if err != nil { panic(err) } @@ -161,11 +157,7 @@ func TestRouteHandler(t *testing.T) { ) } - rb, err := rice.FindBox("templates") - if err != nil { - t.Error(err) - } - templates, err := ricetemp.MakeTemplates(rb) + templates, err := fstmpl.MakeTemplates(templates.FS) if err != nil { panic(err) } diff --git a/server.go b/server.go index 7e164ff..d1332c8 100644 --- a/server.go +++ b/server.go @@ -15,14 +15,14 @@ import ( "golang.org/x/net/context" - rice "github.com/GeertJohan/go.rice" "github.com/goji/httpauth" + "github.com/cortesi/devd/fstmpl" "github.com/cortesi/devd/httpctx" "github.com/cortesi/devd/inject" "github.com/cortesi/devd/livereload" - "github.com/cortesi/devd/ricetemp" "github.com/cortesi/devd/slowdown" + "github.com/cortesi/devd/templates" "github.com/cortesi/devd/timer" "github.com/cortesi/termlog" ) @@ -337,7 +337,7 @@ func (dd *Devd) Router(logger termlog.TermLog, templates *template.Template) (ht // Serve starts the devd server. The callback is called with the serving URL // just before service starts. func (dd *Devd) Serve(address string, port int, certFile string, logger termlog.TermLog, callback func(string)) error { - templates, err := ricetemp.MakeTemplates(rice.MustFindBox("templates")) + templates, err := fstmpl.MakeTemplates(templates.FS) if err != nil { return fmt.Errorf("Error loading templates: %s", err) } diff --git a/server_test.go b/server_test.go index 0f46d5b..b2de12b 100644 --- a/server_test.go +++ b/server_test.go @@ -4,9 +4,9 @@ import ( "reflect" "testing" - rice "github.com/GeertJohan/go.rice" + "github.com/cortesi/devd/fstmpl" "github.com/cortesi/devd/inject" - "github.com/cortesi/devd/ricetemp" + "github.com/cortesi/devd/templates" "github.com/cortesi/termlog" ) @@ -53,7 +53,7 @@ func TestDevdRouteHandler(t *testing.T) { logger := termlog.NewLog() logger.Quiet() r := Route{"", "/", fsEndpoint("./testdata")} - templates := ricetemp.MustMakeTemplates(rice.MustFindBox("templates")) + templates := fstmpl.MustMakeTemplates(templates.FS) ci := inject.CopyInject{} devd := Devd{LivereloadRoutes: true} @@ -66,7 +66,7 @@ func TestDevdRouteHandler(t *testing.T) { func TestDevdHandler(t *testing.T) { logger := termlog.NewLog() logger.Quiet() - templates := ricetemp.MustMakeTemplates(rice.MustFindBox("templates")) + templates := fstmpl.MustMakeTemplates(templates.FS) devd := Devd{LivereloadRoutes: true, WatchPaths: []string{"./"}} err := devd.AddRoutes([]string{"./"}, []string{}) diff --git a/templates/embed.go b/templates/embed.go new file mode 100644 index 0000000..c732844 --- /dev/null +++ b/templates/embed.go @@ -0,0 +1,9 @@ +package templates + +import ( + "embed" +) + +//go:embed 404.html +//go:embed dirlist.html +var FS embed.FS