42f57491c0
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.
64 lines
1.6 KiB
Go
64 lines
1.6 KiB
Go
package cli
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/tamnd/kage/pack"
|
|
"github.com/tamnd/kage/zim"
|
|
)
|
|
|
|
func newOpenCmd() *cobra.Command {
|
|
var addr string
|
|
var openBrowser bool
|
|
cmd := &cobra.Command{
|
|
Use: "open <file.zim>",
|
|
Short: "Serve a ZIM archive in your browser for offline reading",
|
|
Long: "open serves a packed ZIM file over a local HTTP server so you can browse the\n" +
|
|
"site exactly as it was cloned. It is the read side of kage pack --format zim.",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return runOpen(cmd.Context(), args[0], addr, openBrowser)
|
|
},
|
|
}
|
|
cmd.Flags().StringVarP(&addr, "addr", "a", "127.0.0.1:8800", "address to listen on")
|
|
cmd.Flags().BoolVar(&openBrowser, "open", true, "open the default browser")
|
|
return cmd
|
|
}
|
|
|
|
func runOpen(ctx context.Context, path, addr string, openBrowser bool) error {
|
|
r, err := zim.Open(path)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot open %q: %w", path, err)
|
|
}
|
|
defer r.Close()
|
|
|
|
ln, err := net.Listen("tcp", addr)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot listen on %s: %w", addr, err)
|
|
}
|
|
url := "http://" + ln.Addr().String()
|
|
|
|
fmt.Fprintln(os.Stderr, styleTitle.Render("kage open")+" "+styleDim.Render(path))
|
|
fmt.Fprintln(os.Stderr, " open "+styleAccent.Render(url))
|
|
fmt.Fprintln(os.Stderr, styleDim.Render(" press Ctrl-C to stop"))
|
|
if openBrowser {
|
|
_ = 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 {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|