mirror of
https://github.com/danog/gojekyll.git
synced 2025-01-22 23:11:26 +01:00
Theme in-browser error reports
This commit is contained in:
parent
d88b2bda2f
commit
0fc1fc6023
@ -90,7 +90,6 @@ Missing features:
|
||||
- Liquid filter `sassify`
|
||||
- Markdown features: [attribute lists](https://kramdown.gettalong.org/syntax.html#attribute-list-definitions), [`markdown=1`](https://kramdown.gettalong.org/syntax.html#html-blocks).
|
||||
- `site.data` is not sorted.
|
||||
- Undefined Liquid tags and filters are errors, not warnings.
|
||||
- Windows compatibility
|
||||
|
||||
Also see the [detailed status](#feature-status) below.
|
||||
@ -102,12 +101,12 @@ These will probably not change:
|
||||
By design:
|
||||
|
||||
- Plugins must be listed in the config file, not a Gemfile.
|
||||
- Liquid is run in strict mode.
|
||||
- Liquid is run in strict mode; undefined filters are errors.a
|
||||
- The wrong type in a `_config.yml` is an error.
|
||||
- Server live reload is always on.
|
||||
- `serve --watch` (the default) reloads the `_config.yml` and data files too.
|
||||
- `serve` generates pages on the fly; it doesn't write to the file system.
|
||||
- Files are cached to `/tmp/gojekyll-${USER}`, not `./.sass-cache`
|
||||
- Files are cached in `/tmp/gojekyll-${USER}`, not `./.sass-cache`
|
||||
- Jekyll provides an (undocumented) `jekyll.version` variable to templates. Copying this didn't seem right.
|
||||
|
||||
Muzukashii:
|
||||
@ -144,7 +143,7 @@ Muzukashii:
|
||||
- [x] `build`
|
||||
- [x] `--source`, `--destination`, `--drafts`, `--future`, `--unpublished`, `--watch`
|
||||
- [ ] `--baseurl`, `--config`, `--incremental`, `--lsi`
|
||||
- [ ] `--force-polling`, `--limit-posts`, `JEKYLL_ENV=production` – not planned
|
||||
- [ ] `--force_polling`, `--limit-posts`, `JEKYLL_ENV=production` – not planned
|
||||
- [x] `clean`
|
||||
- [x] `help`
|
||||
- [x] `serve`
|
||||
@ -187,6 +186,8 @@ They are used under the terms of the MIT License.
|
||||
| [`jekyll-sitemap` plugin](https://github.com/jekyll/jekyll-redirect-from) | plugin emulation | sitemap template |
|
||||
| [`jekyll-seo-tag` plugin](https://github.com/jekyll/jekyll-redirect-from) | plugin emulation | feed template |
|
||||
|
||||
The theme for in-browser error reporting was adapted from facebookincubator/create-react-app.
|
||||
|
||||
The gopher image in the `testdata` directory is from [Wikimedia Commons](https://commons.wikimedia.org/wiki/File:Gophercolor.jpg). It is used under the [Creative Commons Attribution-Share Alike 3.0 Unported license](https://creativecommons.org/licenses/by-sa/3.0/deed.en).
|
||||
|
||||
In addition to being totally and obviously inspired by Jekyll and its plugins, Jekyll's solid *documentation* was indispensible --- especially since I wanted to implement Jekyll as documented, not port its source code. The [Jekyll docs](https://jekyllrb.com/docs/home/) were always open in at least one tab during development.
|
||||
|
@ -1,15 +1,20 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/jaschaephraim/lrserver"
|
||||
"github.com/osteele/gojekyll/site"
|
||||
"github.com/osteele/liquid"
|
||||
"github.com/pkg/browser"
|
||||
)
|
||||
|
||||
@ -75,7 +80,69 @@ func (s *Server) handler(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
err := site.WriteDocument(w, p)
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "<div>%s</div>", err)
|
||||
fmt.Printf("Error rendering %s: %s\n", urlpath, err)
|
||||
fmt.Fprintf(os.Stderr, "Error rendering %s: %s\n", urlpath, err)
|
||||
eng := liquid.NewEngine()
|
||||
excerpt, path := fileErrorContext(err)
|
||||
out, e := eng.ParseAndRenderString(renderErrorTemplate, liquid.Bindings{
|
||||
"error": err,
|
||||
"excerpt": excerpt,
|
||||
"path": path,
|
||||
"watch": site.Config().Watch,
|
||||
})
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
if _, err := io.WriteString(w, out); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error writing HTTP response: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fileErrorContext(e error) (s, path string) {
|
||||
cause, ok := e.(liquid.SourceError)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
path, n := cause.Path(), cause.LineNumber()
|
||||
b, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
lines := strings.Split(strings.TrimRight(string(b), "\n"), "\n")
|
||||
l0, l1 := n-4, n+4
|
||||
w := new(bytes.Buffer)
|
||||
for i := l0; i < l1; i++ {
|
||||
if i < 0 || len(lines) <= i {
|
||||
continue
|
||||
}
|
||||
var class string
|
||||
if i+1 == n {
|
||||
class = "error"
|
||||
}
|
||||
fmt.Fprintf(w, `<span class="line %s"><span class="gutter"></span><span class="lineno">%4d</span>%s<br /></span>`, class, i+1, html.EscapeString(lines[i]))
|
||||
}
|
||||
return w.String(), path
|
||||
}
|
||||
|
||||
// CSS theme adapted from github.com/facebookincubator/create-react-app
|
||||
const renderErrorTemplate = `<html><head>
|
||||
<style type="text/css">
|
||||
body { background-color: black; color: rgb(232, 232, 232); font-family: Menlo, Consolas, monospace; padding: 2rem; line-height: 1.2; }
|
||||
h1 { color: #E36049 }
|
||||
div { margin: 20px 0; }
|
||||
code { font-size: xx-large; }
|
||||
.line.error .gutter::before { content: "⚠️"; width: 0; float:left; }
|
||||
.line.error, .line.error .lineno { color: red; }
|
||||
.lineno { color: #6D7891; border-right: 1px solid #6D7891; padding-right: 10px; margin: 0 10px 0 55px; display: inline-block; text-align: right; }
|
||||
footer { border-top: 1px solid #6D7891; margin-top: 5ex; padding-top: 5px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Failed to render.</h1>
|
||||
<div>{{ error }}:</div>
|
||||
<code>{{ excerpt }}</code>
|
||||
{% if watch and path != "" %}
|
||||
<footer>Edit and save “{{ path }}” to reload this page.</footer>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>`
|
||||
|
Loading…
x
Reference in New Issue
Block a user