mirror of
https://github.com/lunchcat/sif.git
synced 2026-07-06 04:34:11 -07:00
fix(frameworks): stop ghost detector matching the generic ghost-button (#163)
the ghost detector keyed on the bare "ghost-" body substring, which fires on any page using the common "ghost-button" or skeleton-loader CSS class (e.g. a WordPress theme), scoring 0.65 and reporting it as Ghost CMS. key on the canonical `<meta name="generator" content="Ghost` tag instead, matching the existing astro detector. the /ghost/api/ path and Ghost header markers are unchanged. a ghost site that emits neither the generator meta nor a /ghost/api/ reference is no longer detected; the Ghost response header alone scores below the detection floor.
This commit is contained in:
@@ -568,6 +568,85 @@ func TestDetectFramework_Astro(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectFramework_Ghost(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content="Ghost 6.46">
|
||||
</head>
|
||||
<body>Content</body>
|
||||
</html>
|
||||
`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
result, err := frameworks.DetectFramework(server.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if result == nil {
|
||||
t.Fatal("expected result, got nil")
|
||||
}
|
||||
if result.Name != "Ghost" {
|
||||
t.Errorf("expected framework 'Ghost', got '%s'", result.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// ghost-button is a common generic CSS class and must not read as Ghost CMS.
|
||||
func TestDetectFramework_GhostButtonNoMatch(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<a class="ghost-button" href="/signup">Sign up</a>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
result, err := frameworks.DetectFramework(server.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if result != nil && result.Name == "Ghost" {
|
||||
t.Errorf("expected no Ghost detection for a ghost-button page, got confidence %.2f", result.Confidence)
|
||||
}
|
||||
}
|
||||
|
||||
// the /ghost/api/ path is the only Ghost marker left for pages without the
|
||||
// generator meta, so guard that it still detects on its own.
|
||||
func TestDetectFramework_GhostAPIPath(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script src="/ghost/api/content/posts/?key=abc"></script>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
result, err := frameworks.DetectFramework(server.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if result == nil {
|
||||
t.Fatal("expected result, got nil")
|
||||
}
|
||||
if result.Name != "Ghost" {
|
||||
t.Errorf("expected framework 'Ghost', got '%s'", result.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractVersion_Astro(t *testing.T) {
|
||||
tests := []struct {
|
||||
body string
|
||||
|
||||
@@ -173,7 +173,7 @@ func (d *ghostDetector) Name() string { return "Ghost" }
|
||||
|
||||
func (d *ghostDetector) Signatures() []fw.Signature {
|
||||
return []fw.Signature{
|
||||
{Pattern: "ghost-", Weight: 0.4},
|
||||
{Pattern: `<meta name="generator" content="Ghost`, Weight: 0.4},
|
||||
{Pattern: "Ghost", Weight: 0.3, HeaderOnly: true},
|
||||
{Pattern: "/ghost/api/", Weight: 0.4},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user