Wire kage pack and kage open into the CLI
pack packs a mirror to a zim file or a runnable viewer, accepting a bare host that it resolves against the default output directory. open serves a zim over http like serve does for a folder. Execute checks for an appended archive first, so a packed kage runs as an offline viewer on an ephemeral port and ignores its arguments.
This commit is contained in:
+46
@@ -7,15 +7,28 @@ package cli
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/charmbracelet/fang"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/tamnd/kage/pack"
|
||||
"github.com/tamnd/kage/zim"
|
||||
)
|
||||
|
||||
// Execute builds the root command and runs it through fang. main passes the
|
||||
// signal-aware context so Ctrl-C cancels the in-flight clone and flushes resume
|
||||
// state. It returns the process exit code.
|
||||
func Execute(ctx context.Context) int {
|
||||
// A kage binary with a ZIM appended runs as an offline viewer for that site,
|
||||
// ignoring its arguments. A normal build has no trailer and falls through.
|
||||
if ra, size, ok := pack.Embedded(); ok {
|
||||
return runEmbeddedViewer(ctx, ra, size)
|
||||
}
|
||||
|
||||
root := newRoot()
|
||||
opts := []fang.Option{
|
||||
fang.WithVersion(Version),
|
||||
@@ -41,5 +54,38 @@ func newRoot() *cobra.Command {
|
||||
}
|
||||
root.AddCommand(newCloneCmd())
|
||||
root.AddCommand(newServeCmd())
|
||||
root.AddCommand(newPackCmd())
|
||||
root.AddCommand(newOpenCmd())
|
||||
return root
|
||||
}
|
||||
|
||||
// runEmbeddedViewer serves the ZIM appended to this executable on an ephemeral
|
||||
// local port and opens the browser. It runs until the context is cancelled
|
||||
// (Ctrl-C) and ignores all command-line arguments: a packed binary is the site,
|
||||
// not the kage CLI.
|
||||
func runEmbeddedViewer(ctx context.Context, ra io.ReaderAt, size int64) int {
|
||||
r, err := zim.NewReader(ra, size)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "kage: corrupt embedded archive:", err)
|
||||
return 1
|
||||
}
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "kage: cannot start viewer:", err)
|
||||
return 1
|
||||
}
|
||||
url := "http://" + ln.Addr().String()
|
||||
fmt.Fprintln(os.Stderr, "serving offline site at "+url+" (Ctrl-C to stop)")
|
||||
_ = pack.OpenInBrowser(url)
|
||||
|
||||
srv := &http.Server{Handler: pack.Handler(r)}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
_ = srv.Close()
|
||||
}()
|
||||
if err := srv.Serve(ln); err != nil && err != http.ErrServerClosed {
|
||||
fmt.Fprintln(os.Stderr, "kage:", err)
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user