commit
a0b8f9aa42
|
@ -0,0 +1,3 @@
|
|||
# Binaries
|
||||
/caniuse
|
||||
/caniuse.exe
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2022 John Olheiser
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,9 @@
|
|||
# caniuse
|
||||
|
||||
CLI for [caniuse](https://caniuse.com)
|
||||
|
||||
Retrieves data from the [repository](https://github.com/Fyrd/caniuse)
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
|
@ -0,0 +1,5 @@
|
|||
module go.jolheiser.com/caniuse
|
||||
|
||||
go 1.19
|
||||
|
||||
require github.com/peterbourgon/ff/v3 v3.3.0
|
|
@ -0,0 +1,2 @@
|
|||
github.com/peterbourgon/ff/v3 v3.3.0 h1:PaKe7GW8orVFh8Unb5jNHS+JZBwWUMa2se0HM6/BI24=
|
||||
github.com/peterbourgon/ff/v3 v3.3.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ=
|
|
@ -0,0 +1,45 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
const downloadURL = "https://raw.githubusercontent.com/Fyrd/caniuse/main/data.json"
|
||||
|
||||
// Download downloads caniuse data to path
|
||||
func Download(path string) error {
|
||||
res, err := http.Get(downloadURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get data: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != 200 {
|
||||
return fmt.Errorf("could not download data: %s", res.Status)
|
||||
}
|
||||
|
||||
fi, err := os.Create(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create %q: %v", path, err)
|
||||
}
|
||||
defer fi.Close()
|
||||
|
||||
_, err = io.Copy(fi, res.Body)
|
||||
return err
|
||||
}
|
||||
|
||||
func Load(path string) (Data, error) {
|
||||
var data Data
|
||||
|
||||
fi, err := os.Open(path)
|
||||
if err != nil {
|
||||
return data, fmt.Errorf("could not read data: %v", err)
|
||||
}
|
||||
defer fi.Close()
|
||||
|
||||
return data, json.NewDecoder(fi).Decode(&data)
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/peterbourgon/ff/v3"
|
||||
)
|
||||
|
||||
var (
|
||||
resultmap = map[string]string{
|
||||
"y": "✔",
|
||||
"n": "✘",
|
||||
"a": "◒",
|
||||
"u": "‽",
|
||||
"i": "ⓘ",
|
||||
"w": "⚠",
|
||||
}
|
||||
supernums = "⁰¹²³⁴⁵⁶⁷⁸⁹"
|
||||
refresh = time.Hour * 24 * 30
|
||||
)
|
||||
|
||||
func main() {
|
||||
fs := flag.NewFlagSet("caniuse", flag.ContinueOnError)
|
||||
|
||||
if err := ff.Parse(fs, os.Args[1:],
|
||||
ff.WithEnvVarPrefix("CANIUSE"),
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if fs.NArg() != 1 {
|
||||
fmt.Println("caniuse requires one argument")
|
||||
return
|
||||
}
|
||||
|
||||
data, err := loadData()
|
||||
if err != nil {
|
||||
fmt.Printf("could not load data: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(data)
|
||||
}
|
||||
|
||||
func loadData() (Data, error) {
|
||||
var data Data
|
||||
|
||||
cache, err := os.UserCacheDir()
|
||||
if err != nil {
|
||||
return data, fmt.Errorf("could not determine cache dir: %v", err)
|
||||
}
|
||||
|
||||
caniuseCache := filepath.Join(cache, "caniuse")
|
||||
if err := os.MkdirAll(caniuseCache, os.ModePerm); err != nil {
|
||||
return data, fmt.Errorf("could not create dir %q: %v", caniuseCache, err)
|
||||
}
|
||||
|
||||
dataPath := filepath.Join(caniuseCache, "data.json")
|
||||
fi, err := os.Stat(dataPath)
|
||||
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||
return data, fmt.Errorf("could not stat %q: %v", dataPath, err)
|
||||
} else if errors.Is(err, fs.ErrNotExist) || time.Since(fi.ModTime()) > refresh {
|
||||
if err := Download(dataPath); err != nil {
|
||||
return data, fmt.Errorf("could not download data: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return Load(dataPath)
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package main
|
||||
|
||||
type Data struct {
|
||||
Eras map[string]string `json:"eras"`
|
||||
Agents map[string]struct {
|
||||
Browser string `json:"browser"`
|
||||
LongName string `json:"long_name"`
|
||||
Abbr string `json:"abbr"`
|
||||
Prefix string `json:"prefix"`
|
||||
Type string `json:"type"`
|
||||
UsageGlobal map[string]float64 `json:"usage_global"`
|
||||
Versions []string `json:"versions"`
|
||||
} `json:"agents"`
|
||||
Statuses struct {
|
||||
Rec string `json:"rec"`
|
||||
Pr string `json:"pr"`
|
||||
Cr string `json:"cr"`
|
||||
Wd string `json:"wd"`
|
||||
Ls string `json:"ls"`
|
||||
Other string `json:"other"`
|
||||
Unoff string `json:"unoff"`
|
||||
} `json:"statuses"`
|
||||
Cats map[string][]string `json:"cats"`
|
||||
Data map[string]struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Spec string `json:"spec"`
|
||||
Status string `json:"status"`
|
||||
Links []struct {
|
||||
URL string `json:"url"`
|
||||
Title string `json:"title"`
|
||||
} `json:"links"`
|
||||
Categories []string `json:"categories"`
|
||||
Stats map[string]map[string]stat `json:"stats"`
|
||||
Notes string `json:"notes"`
|
||||
NotesByNum map[string]string `json:"notes_by_num"`
|
||||
UsagePercY float64 `json:"usage_perc_y"`
|
||||
UsagePercA float64 `json:"usage_perc_a"`
|
||||
UCPrefix bool `json:"ucprefix"`
|
||||
Parent string `json:"parent"`
|
||||
Keywords string `json:"keywords"`
|
||||
IEID string `json:"ie_id"`
|
||||
ChromeID string `json:"chrome_id"`
|
||||
FirefoxID string `json:"firefox_id"`
|
||||
WebkitID string `json:"webkit_id"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type stat string
|
||||
|
||||
func (s stat) Bool() bool {
|
||||
return s == "y"
|
||||
}
|
Loading…
Reference in New Issue