claude go reimplement
This commit is contained in:
1 parent
4bcb924158
commit
f523c79618
83 files changed
+3714
-3454
No files matched your search
@@ -0,0 +1,113 @@
|
||||
package kjv
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Everything the program serves or reads besides the Bible itself (pages,
|
||||
// scripts, styles, the 1828 dictionary, word lists) lives in the assets table
|
||||
// of the companion database, so the program and the database are the only two
|
||||
// files that need to be distributed.
|
||||
|
||||
var assetMIME = map[string]string{
|
||||
".html": "text/html; charset=utf-8",
|
||||
".css": "text/css; charset=utf-8",
|
||||
".js": "application/javascript; charset=utf-8",
|
||||
".json": "application/json",
|
||||
".svg": "image/svg+xml",
|
||||
".dic": "text/plain; charset=utf-8",
|
||||
".aff": "text/plain; charset=utf-8",
|
||||
}
|
||||
|
||||
func isAssetFile(rel string) bool {
|
||||
dir := path.Dir(rel)
|
||||
switch {
|
||||
case rel == "kjv_fe.html":
|
||||
return true
|
||||
case dir == "html", dir == "js", dir == "static":
|
||||
return true
|
||||
case dir == "styles":
|
||||
return strings.HasSuffix(rel, ".css")
|
||||
case dir == "data":
|
||||
ext := path.Ext(rel)
|
||||
return ext == ".json" || ext == ".dic" || ext == ".aff"
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ImportAssets replaces the assets table with the files of a source checkout.
|
||||
func ImportAssets(dbPath, srcDir string) error {
|
||||
db, err := sql.Open("sqlite", "file:"+dbPath+"?_pragma=busy_timeout(5000)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
for _, stmt := range []string{
|
||||
"CREATE TABLE IF NOT EXISTS assets (path TEXT PRIMARY KEY, mime TEXT NOT NULL, body BLOB NOT NULL)",
|
||||
"DELETE FROM assets",
|
||||
} {
|
||||
if _, err := tx.Exec(stmt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
n := 0
|
||||
err = filepath.WalkDir(srcDir, func(p string, d fs.DirEntry, err error) error {
|
||||
if err != nil || !d.Type().IsRegular() { // no directories, and never follow a symlink out of the tree
|
||||
return err
|
||||
}
|
||||
rel, _ := filepath.Rel(srcDir, p)
|
||||
rel = filepath.ToSlash(rel)
|
||||
if !isAssetFile(rel) {
|
||||
return nil
|
||||
}
|
||||
body, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mime := assetMIME[path.Ext(rel)]
|
||||
if mime == "" {
|
||||
mime = "application/octet-stream"
|
||||
}
|
||||
n++
|
||||
_, err = tx.Exec("INSERT INTO assets (path, mime, body) VALUES (?, ?, ?)", rel, mime, body)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n == 0 {
|
||||
return fmt.Errorf("no assets found under %s (expected html/, js/, styles/, data/*.json ...)", srcDir)
|
||||
}
|
||||
fmt.Printf("imported %d assets into %s\n", n, dbPath)
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
// LoadAssets reads every asset into memory.
|
||||
func (s *Store) LoadAssets() (map[string][]byte, error) {
|
||||
rows, err := s.db.Query("SELECT path, body FROM assets")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("no assets table (run: kjv-api import-assets <source dir>): %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
out := map[string][]byte{}
|
||||
for rows.Next() {
|
||||
var p string
|
||||
var b []byte
|
||||
if err := rows.Scan(&p, &b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[p] = b
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
Reference in new issue
Block a user