mirror of
https://github.com/thomiceli/opengist.git
synced 2025-01-03 16:22:40 +00:00
Optimize assets
This commit is contained in:
parent
0e0e92b88f
commit
6c981570a1
14 changed files with 6547 additions and 791 deletions
|
@ -77,8 +77,6 @@ func parseLog(out io.Reader) []*Commit {
|
||||||
}
|
}
|
||||||
scanNext = true
|
scanNext = true
|
||||||
|
|
||||||
fmt.Println("> " + string(scanner.Bytes()))
|
|
||||||
|
|
||||||
// new commit found
|
// new commit found
|
||||||
currentFile = nil
|
currentFile = nil
|
||||||
currentCommit = &Commit{Hash: string(scanner.Bytes()[2:]), Files: []File{}}
|
currentCommit = &Commit{Hash: string(scanner.Bytes()[2:]), Files: []File{}}
|
||||||
|
|
|
@ -45,9 +45,18 @@ func gistInit(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
setData(ctx, "httpProtocol", strings.ToUpper(httpProtocol))
|
setData(ctx, "httpProtocol", strings.ToUpper(httpProtocol))
|
||||||
|
|
||||||
if config.C.HTTP.Git {
|
if config.C.HTTP.Git {
|
||||||
setData(ctx, "httpCloneUrl", httpProtocol+"://"+config.C.HTTP.Domain+":"+config.C.HTTP.Port+"/"+userName+"/"+gistName+".git")
|
if config.C.HTTP.Port == "80" || config.C.HTTP.Port == "443" {
|
||||||
|
setData(ctx, "httpCloneUrl", httpProtocol+"://"+config.C.HTTP.Domain+"/"+userName+"/"+gistName+".git")
|
||||||
|
} else {
|
||||||
|
setData(ctx, "httpCloneUrl", httpProtocol+"://"+config.C.HTTP.Domain+":"+config.C.HTTP.Port+"/"+userName+"/"+gistName+".git")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.C.HTTP.Port == "80" || config.C.HTTP.Port == "443" {
|
||||||
|
setData(ctx, "httpCopyUrl", httpProtocol+"://"+config.C.HTTP.Domain+"/"+userName+"/"+gistName)
|
||||||
|
} else {
|
||||||
|
setData(ctx, "httpCopyUrl", httpProtocol+"://"+config.C.HTTP.Domain+":"+config.C.HTTP.Port+"/"+userName+"/"+gistName)
|
||||||
}
|
}
|
||||||
setData(ctx, "httpCopyUrl", httpProtocol+"://"+config.C.HTTP.Domain+":"+config.C.HTTP.Port+"/"+userName+"/"+gistName)
|
|
||||||
|
|
||||||
setData(ctx, "currentUrl", template.URL(ctx.Request().URL.Path))
|
setData(ctx, "currentUrl", template.URL(ctx.Request().URL.Path))
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package web
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/sessions"
|
"github.com/gorilla/sessions"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
"opengist/internal/config"
|
"opengist/internal/config"
|
||||||
"opengist/internal/git"
|
"opengist/internal/git"
|
||||||
"opengist/internal/models"
|
"opengist/internal/models"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -23,6 +25,59 @@ import (
|
||||||
|
|
||||||
var store *sessions.CookieStore
|
var store *sessions.CookieStore
|
||||||
var re = regexp.MustCompile("[^a-z0-9]+")
|
var re = regexp.MustCompile("[^a-z0-9]+")
|
||||||
|
var fm = template.FuncMap{
|
||||||
|
"split": strings.Split,
|
||||||
|
"indexByte": strings.IndexByte,
|
||||||
|
"toInt": func(i string) int64 {
|
||||||
|
val, _ := strconv.ParseInt(i, 10, 64)
|
||||||
|
return val
|
||||||
|
},
|
||||||
|
"inc": func(i int64) int64 {
|
||||||
|
return i + 1
|
||||||
|
},
|
||||||
|
"splitGit": func(i string) []string {
|
||||||
|
return strings.FieldsFunc(i, func(r rune) bool {
|
||||||
|
return r == ',' || r == ' '
|
||||||
|
})
|
||||||
|
},
|
||||||
|
"lines": func(i string) []string {
|
||||||
|
return strings.Split(i, "\n")
|
||||||
|
},
|
||||||
|
"isMarkdown": func(i string) bool {
|
||||||
|
return ".md" == strings.ToLower(filepath.Ext(i))
|
||||||
|
},
|
||||||
|
"isCsv": func(i string) bool {
|
||||||
|
return ".csv" == strings.ToLower(filepath.Ext(i))
|
||||||
|
},
|
||||||
|
"csvFile": func(file *git.File) *git.CsvFile {
|
||||||
|
if ".csv" != strings.ToLower(filepath.Ext(file.Filename)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
csvFile, err := git.ParseCsv(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return csvFile
|
||||||
|
},
|
||||||
|
"httpStatusText": http.StatusText,
|
||||||
|
"loadedTime": func(startTime time.Time) string {
|
||||||
|
return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms"
|
||||||
|
},
|
||||||
|
"slug": func(s string) string {
|
||||||
|
return strings.Trim(re.ReplaceAllString(strings.ToLower(s), "-"), "-")
|
||||||
|
},
|
||||||
|
"avatarUrl": func(userHash string) string {
|
||||||
|
return "https://www.gravatar.com/avatar/" + userHash + "?d=identicon&s=200"
|
||||||
|
},
|
||||||
|
"emailToMD5": func(email string) string {
|
||||||
|
return fmt.Sprintf("%x", md5.Sum([]byte(strings.ToLower(strings.TrimSpace(email)))))
|
||||||
|
},
|
||||||
|
"asset": func(jsfile string) string {
|
||||||
|
return "/" + manifestEntries[jsfile].File
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
type Template struct {
|
type Template struct {
|
||||||
templates *template.Template
|
templates *template.Template
|
||||||
|
@ -34,6 +89,7 @@ func (t *Template) Render(w io.Writer, name string, data interface{}, _ echo.Con
|
||||||
|
|
||||||
func Start() {
|
func Start() {
|
||||||
store = sessions.NewCookieStore([]byte("opengist"))
|
store = sessions.NewCookieStore([]byte("opengist"))
|
||||||
|
parseManifestEntries()
|
||||||
|
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.HideBanner = true
|
e.HideBanner = true
|
||||||
|
@ -57,57 +113,7 @@ func Start() {
|
||||||
e.Use(middleware.Secure())
|
e.Use(middleware.Secure())
|
||||||
|
|
||||||
e.Renderer = &Template{
|
e.Renderer = &Template{
|
||||||
templates: template.Must(template.New("t").Funcs(
|
templates: template.Must(template.New("t").Funcs(fm).ParseGlob("templates/*/*.html")),
|
||||||
template.FuncMap{
|
|
||||||
"split": strings.Split,
|
|
||||||
"indexByte": strings.IndexByte,
|
|
||||||
"toInt": func(i string) int64 {
|
|
||||||
val, _ := strconv.ParseInt(i, 10, 64)
|
|
||||||
return val
|
|
||||||
},
|
|
||||||
"inc": func(i int64) int64 {
|
|
||||||
return i + 1
|
|
||||||
},
|
|
||||||
"splitGit": func(i string) []string {
|
|
||||||
return strings.FieldsFunc(i, func(r rune) bool {
|
|
||||||
return r == ',' || r == ' '
|
|
||||||
})
|
|
||||||
},
|
|
||||||
"lines": func(i string) []string {
|
|
||||||
return strings.Split(i, "\n")
|
|
||||||
},
|
|
||||||
"isMarkdown": func(i string) bool {
|
|
||||||
return ".md" == strings.ToLower(filepath.Ext(i))
|
|
||||||
},
|
|
||||||
"isCsv": func(i string) bool {
|
|
||||||
return ".csv" == strings.ToLower(filepath.Ext(i))
|
|
||||||
},
|
|
||||||
"csvFile": func(file *git.File) *git.CsvFile {
|
|
||||||
if ".csv" != strings.ToLower(filepath.Ext(file.Filename)) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
csvFile, err := git.ParseCsv(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return csvFile
|
|
||||||
},
|
|
||||||
"httpStatusText": http.StatusText,
|
|
||||||
"loadedTime": func(startTime time.Time) string {
|
|
||||||
return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms"
|
|
||||||
},
|
|
||||||
"slug": func(s string) string {
|
|
||||||
return strings.Trim(re.ReplaceAllString(strings.ToLower(s), "-"), "-")
|
|
||||||
},
|
|
||||||
"avatarUrl": func(userHash string) string {
|
|
||||||
return "https://www.gravatar.com/avatar/" + userHash + "?d=identicon&s=200"
|
|
||||||
},
|
|
||||||
"emailToMD5": func(email string) string {
|
|
||||||
return fmt.Sprintf("%x", md5.Sum([]byte(strings.ToLower(strings.TrimSpace(email)))))
|
|
||||||
},
|
|
||||||
}).ParseGlob("templates/*/*.html")),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e.HTTPErrorHandler = func(er error, ctx echo.Context) {
|
e.HTTPErrorHandler = func(er error, ctx echo.Context) {
|
||||||
|
@ -291,3 +297,25 @@ func logged(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
func noRouteFound(echo.Context) error {
|
func noRouteFound(echo.Context) error {
|
||||||
return notFound("Page not found")
|
return notFound("Page not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
type Asset struct {
|
||||||
|
File string `json:"file"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var manifestEntries map[string]Asset
|
||||||
|
|
||||||
|
func parseManifestEntries() {
|
||||||
|
file, err := os.Open("public/manifest.json")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().Err(err).Msg("Failed to open manifest.json")
|
||||||
|
}
|
||||||
|
byteValue, err := io.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().Err(err).Msg("Failed to read manifest.json")
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal(byteValue, &manifestEntries); err != nil {
|
||||||
|
log.Fatal().Err(err).Msg("Failed to unmarshal manifest.json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ func validateReservedKeywords(fl validator.FieldLevel) bool {
|
||||||
name := fl.Field().String()
|
name := fl.Field().String()
|
||||||
|
|
||||||
restrictedNames := map[string]struct{}{}
|
restrictedNames := map[string]struct{}{}
|
||||||
for _, restrictedName := range []string{"register", "login", "logout", "config", "admin", "all"} {
|
for _, restrictedName := range []string{"assets", "register", "login", "logout", "config", "admin", "all"} {
|
||||||
restrictedNames[restrictedName] = struct{}{}
|
restrictedNames[restrictedName] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7133
package-lock.json
generated
7133
package-lock.json
generated
File diff suppressed because it is too large
Load diff
25
package.json
25
package.json
|
@ -8,18 +8,23 @@
|
||||||
"preview": "node_modules/.bin/vite preview"
|
"preview": "node_modules/.bin/vite preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@codemirror/commands": "^6.0.0",
|
"@codemirror/commands": "^6.2.2",
|
||||||
"@codemirror/lang-javascript": "^6.0.0",
|
"@codemirror/lang-javascript": "^6.1.4",
|
||||||
"@codemirror/view": "^6.0.1",
|
"@codemirror/view": "^6.9.3",
|
||||||
"@tailwindcss/forms": "^0.5.1",
|
"@tailwindcss/forms": "^0.5.3",
|
||||||
"@tailwindcss/typography": "^0.5.2",
|
"@tailwindcss/typography": "^0.5.9",
|
||||||
"autoprefixer": "^10.4.7",
|
"autoprefixer": "^10.4.14",
|
||||||
"codemirror": "^6.0.0",
|
"codemirror": "^6.0.1",
|
||||||
"highlight.js": "^11.5.1",
|
"cssnano": "^5.1.15",
|
||||||
|
"highlight.js": "^11.7.0",
|
||||||
"markdown-it": "^13.0.1",
|
"markdown-it": "^13.0.1",
|
||||||
"moment": "^2.29.3",
|
"moment": "^2.29.3",
|
||||||
"postcss": "^8.4.13",
|
"postcss": "^8.4.13",
|
||||||
"tailwindcss": "^3.0.24",
|
"postcss-cssnext": "^3.1.1",
|
||||||
"vite": "^2.9.2"
|
"postcss-import": "^15.1.0",
|
||||||
|
"postcss-loader": "^7.1.0",
|
||||||
|
"sugarss": "^4.0.1",
|
||||||
|
"tailwindcss": "^3.2.7",
|
||||||
|
"vite": "^4.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: [
|
plugins: {
|
||||||
require('tailwindcss'),
|
tailwindcss: {},
|
||||||
require('autoprefixer'),
|
autoprefixer: {},
|
||||||
],
|
cssnano: {},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
1
public/main.js
vendored
1
public/main.js
vendored
|
@ -1,5 +1,6 @@
|
||||||
import './style.css'
|
import './style.css'
|
||||||
import './markdown.css'
|
import './markdown.css'
|
||||||
|
import './favicon.svg'
|
||||||
import 'highlight.js/styles/tokyo-night-dark.css'
|
import 'highlight.js/styles/tokyo-night-dark.css'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import md from 'markdown-it'
|
import md from 'markdown-it'
|
||||||
|
|
4
public/style.css
vendored
4
public/style.css
vendored
|
@ -8,6 +8,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
@apply bg-gray-800;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@apply text-primary-500;
|
@apply text-primary-500;
|
||||||
}
|
}
|
||||||
|
|
10
templates/base/base_header.html
vendored
10
templates/base/base_header.html
vendored
|
@ -3,14 +3,10 @@
|
||||||
<html lang="en" class="h-full">
|
<html lang="en" class="h-full">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="http://localhost:3000/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="{{ asset "favicon.svg" }}" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<style>
|
<link rel="stylesheet" href="{{ asset "main.css" }}" />
|
||||||
html {
|
<script type="module" src="{{ asset "main.js" }}"></script>
|
||||||
background-color: #0d1117;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script type="module" src="http://localhost:3000/main.js"></script>
|
|
||||||
|
|
||||||
{{ if .htmlTitle }}
|
{{ if .htmlTitle }}
|
||||||
<title>{{ .htmlTitle }} - Opengist</title>
|
<title>{{ .htmlTitle }} - Opengist</title>
|
||||||
|
|
3
templates/base/gist_header.html
vendored
3
templates/base/gist_header.html
vendored
|
@ -146,9 +146,6 @@
|
||||||
<p class="text-xs font-normal text-gray-400">Clone with Git using an SSH key.</p>
|
<p class="text-xs font-normal text-gray-400">Clone with Git using an SSH key.</p>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<div class="text-slate-300 block px-4 py-2 text-sm hover:bg-gray-700 gist-menu-item" role="menuitem" id="gist-menu-embed" data-link="(soon)"><p>Embed</p>
|
|
||||||
<p class="text-xs font-normal text-gray-400">Embed this gist in your website. (soon)</p>
|
|
||||||
</div>
|
|
||||||
<div class="text-slate-300 block px-4 py-2 text-sm hover:bg-gray-700 gist-menu-item" role="menuitem" id="gist-menu-share" data-link="{{ .httpCopyUrl }}"><p>Share</p>
|
<div class="text-slate-300 block px-4 py-2 text-sm hover:bg-gray-700 gist-menu-item" role="menuitem" id="gist-menu-share" data-link="{{ .httpCopyUrl }}"><p>Share</p>
|
||||||
<p class="text-xs font-normal text-gray-400">Copy shareable link for this gist.</p>
|
<p class="text-xs font-normal text-gray-400">Copy shareable link for this gist.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
2
templates/pages/create.html
vendored
2
templates/pages/create.html
vendored
|
@ -44,6 +44,6 @@
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module" src="http://localhost:3000/editor.js"></script>
|
<script type="module" src="{{ asset "editor.js" }}"></script>
|
||||||
|
|
||||||
{{ template "footer" .}}
|
{{ template "footer" .}}
|
||||||
|
|
3
templates/pages/edit.html
vendored
3
templates/pages/edit.html
vendored
|
@ -81,7 +81,6 @@
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module" src="http://localhost:3000/editor.js"></script>
|
<script type="module" src="{{ asset "editor.js" }}"></script>
|
||||||
|
|
||||||
|
|
||||||
{{ template "footer" .}}
|
{{ template "footer" .}}
|
||||||
|
|
|
@ -9,7 +9,6 @@ export default defineConfig({
|
||||||
assetsDir: 'assets',
|
assetsDir: 'assets',
|
||||||
manifest: true,
|
manifest: true,
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
// overwrite default .html entry
|
|
||||||
input: ['./public/main.js', './public/editor.js']
|
input: ['./public/main.js', './public/editor.js']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue