better_seo 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bbb87756b71cdc491faaba16bd349149051ef870ac1eea6dab55c31db3e09bd9
4
- data.tar.gz: b34bc18d112710290991d430ff5525b920dadc25938aed97a6e20a3309118d45
3
+ metadata.gz: 42834acb5d5dca21a12b20288b28544bd5112aac2fe8a05dbf3123707f1f21fe
4
+ data.tar.gz: 8efa2fd4287fbf0078d57691148c2cdc78e2f03a18c5af2eb96fc6819d32c5d6
5
5
  SHA512:
6
- metadata.gz: ca7e8d51f6c035725975a2326908156c0e6c5281d4ded7a10fd709775e4aa44208a5a609589fbbaf66c62ef0f54ab4f024b5a685001ab472cb2d1e0bb24097a2
7
- data.tar.gz: b353b67665a36f045d2db900d3285996d021ec19db9b5ac7c1fd697ecfa5c4082fc895a3517190f70c79ae7f4f78d9290ab0f79034c3ecdc2da6ad490df20436
6
+ metadata.gz: 934a6db489cbda29d885011c889d268b66858b9d202d5c561907543365a639547c7e9bc39cd2dc0acc529e4fba4c9f9eb21de10fb76cdb7211c15c4622249073
7
+ data.tar.gz: d5ceb959972b3e687140a87c87c649525d0844abaffb1ddd316259eaa4cd82b7b5780152a92e06120c8ab7ff46fdce33f1c2449f8f225321a92958f87d8895bc
data/CHANGELOG.md CHANGED
@@ -7,6 +7,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.13.0] - 2025-01-23
11
+
12
+ ### Added
13
+ - Advanced SEO Tools for validation and content management
14
+ - **Robots.txt Generator** (`BetterSeo::Generators::RobotsTxtGenerator`)
15
+ - `add_rule(user_agent, allow:, disallow:)` - Add robot directives
16
+ - `set_crawl_delay(user_agent, seconds)` - Set crawl delay for bots
17
+ - `add_sitemap(url)` - Add sitemap references
18
+ - `clear` - Remove all rules and sitemaps
19
+ - `to_text` - Generate robots.txt content
20
+ - `write_to_file(path)` - Write robots.txt to file
21
+ - Support for multiple user agents (*, Googlebot, Bingbot, etc.)
22
+ - Allow/Disallow path directives
23
+ - Automatic directory creation
24
+ - Method chaining for fluent API
25
+ - **SEO Validator** (`BetterSeo::Validators::SeoValidator`)
26
+ - `check_title(text)` - Validate title length (30-60 chars optimal)
27
+ - `check_description(text)` - Validate description length (120-160 chars optimal)
28
+ - `check_headings(html)` - Validate H1-H6 structure
29
+ - `check_images(html)` - Validate image alt text presence
30
+ - `validate_page(html)` - Complete page validation
31
+ - `generate_report(validation)` - Human-readable SEO report
32
+ - Overall SEO score (0-100) with weighted components
33
+ - Detailed issue tracking and recommendations
34
+ - Warning levels for sub-optimal content
35
+ - HTML parsing for meta tags extraction
36
+
37
+ ### Enhanced
38
+ - Validators module introduced for SEO quality checks
39
+ - Comprehensive validation rules following SEO best practices
40
+ - Detailed error messages with actionable recommendations
41
+
42
+ ### Test Coverage
43
+ - 858 tests passing (+47 from v0.12.0)
44
+ - 96.7% code coverage (1668/1725 lines)
45
+ - 47 new tests across SEO tools:
46
+ - Robots.txt Generator: 25 tests
47
+ - SEO Validator: 22 tests
48
+
10
49
  ## [0.12.0] - 2025-01-23
11
50
 
12
51
  ### Added
data/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  A comprehensive SEO gem for Ruby and Rails applications. BetterSeo provides a clean, fluent DSL for managing meta tags, Open Graph, Twitter Cards, structured data, sitemaps, and more.
4
4
 
5
- [![Tests](https://img.shields.io/badge/tests-811%20passing-brightgreen)](https://github.com/yourusername/better_seo)
6
- [![Coverage](https://img.shields.io/badge/coverage-96.41%25-brightgreen)](https://github.com/yourusername/better_seo)
5
+ [![Tests](https://img.shields.io/badge/tests-858%20passing-brightgreen)](https://github.com/yourusername/better_seo)
6
+ [![Coverage](https://img.shields.io/badge/coverage-96.7%25-brightgreen)](https://github.com/yourusername/better_seo)
7
7
  [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.0.0-red)](https://www.ruby-lang.org)
8
8
  [![Rails](https://img.shields.io/badge/rails-%3E%3D%206.1-red)](https://rubyonrails.org)
9
9
 
10
10
  ## Features
11
11
 
12
- ### ✅ Implemented (v0.12.0)
12
+ ### ✅ Implemented (v0.13.0)
13
13
 
14
14
  - **Core Configuration System**
15
15
  - Singleton configuration with block-style setup
@@ -1793,6 +1793,199 @@ manager.validate! # Raises: "URL is required"
1793
1793
 
1794
1794
  ---
1795
1795
 
1796
+ ## SEO Tools
1797
+
1798
+ ### Robots.txt Generator
1799
+
1800
+ Generate robots.txt files to control search engine crawler access.
1801
+
1802
+ #### Basic Usage
1803
+
1804
+ ```ruby
1805
+ robots = BetterSeo::Generators::RobotsTxtGenerator.new
1806
+
1807
+ # Allow all bots except specific paths
1808
+ robots.add_rule("*", disallow: ["/admin", "/api/private", "/tmp"])
1809
+
1810
+ # Add sitemap
1811
+ robots.add_sitemap("https://example.com/sitemap.xml")
1812
+
1813
+ # Generate robots.txt content
1814
+ text = robots.to_text
1815
+ # User-agent: *
1816
+ # Disallow: /admin
1817
+ # Disallow: /api/private
1818
+ # Disallow: /tmp
1819
+ #
1820
+ # Sitemap: https://example.com/sitemap.xml
1821
+ ```
1822
+
1823
+ #### Multiple User Agents
1824
+
1825
+ ```ruby
1826
+ robots = BetterSeo::Generators::RobotsTxtGenerator.new
1827
+
1828
+ # Rules for all bots
1829
+ robots.add_rule("*", allow: "/", disallow: "/admin")
1830
+
1831
+ # Specific rules for Googlebot
1832
+ robots.add_rule("Googlebot", allow: "/api/public", disallow: "/temp")
1833
+
1834
+ # Crawl delay for aggressive bots
1835
+ robots.add_rule("Bingbot", disallow: "/admin")
1836
+ robots.set_crawl_delay("Bingbot", 2)
1837
+
1838
+ text = robots.to_text
1839
+ ```
1840
+
1841
+ #### Write to File
1842
+
1843
+ ```ruby
1844
+ robots = BetterSeo::Generators::RobotsTxtGenerator.new
1845
+ robots.add_rule("*", disallow: ["/admin", "/private"])
1846
+ robots.add_sitemap("https://example.com/sitemap.xml")
1847
+
1848
+ # Write to public directory
1849
+ robots.write_to_file(Rails.root.join('public', 'robots.txt'))
1850
+ ```
1851
+
1852
+ #### Rails Controller Integration
1853
+
1854
+ ```ruby
1855
+ # app/controllers/robots_controller.rb
1856
+ class RobotsController < ApplicationController
1857
+ def index
1858
+ robots = BetterSeo::Generators::RobotsTxtGenerator.new
1859
+
1860
+ if Rails.env.production?
1861
+ robots.add_rule("*", disallow: ["/admin", "/api/private"])
1862
+ robots.add_sitemap("#{request.base_url}/sitemap.xml")
1863
+ else
1864
+ # Block all bots in non-production
1865
+ robots.add_rule("*", disallow: "/")
1866
+ end
1867
+
1868
+ render plain: robots.to_text, content_type: "text/plain"
1869
+ end
1870
+ end
1871
+
1872
+ # config/routes.rb
1873
+ get '/robots.txt', to: 'robots#index'
1874
+ ```
1875
+
1876
+ ---
1877
+
1878
+ ### SEO Validator
1879
+
1880
+ Validate and score your pages for SEO best practices.
1881
+
1882
+ #### Basic Usage
1883
+
1884
+ ```ruby
1885
+ validator = BetterSeo::Validators::SeoValidator.new
1886
+
1887
+ # Check individual elements
1888
+ title_result = validator.check_title("My Awesome SEO-Friendly Page Title")
1889
+ # => { valid: true, score: 100, message: "Title length is optimal", length: 35 }
1890
+
1891
+ desc_result = validator.check_description("This is a comprehensive meta description...")
1892
+ # => { valid: true, score: 100, message: "Description length is optimal", length: 145 }
1893
+ ```
1894
+
1895
+ #### Validate Complete Page
1896
+
1897
+ ```ruby
1898
+ validator = BetterSeo::Validators::SeoValidator.new
1899
+
1900
+ html = <<~HTML
1901
+ <!DOCTYPE html>
1902
+ <html>
1903
+ <head>
1904
+ <title>Best Ruby SEO Gem for Rails Applications</title>
1905
+ <meta name="description" content="BetterSeo provides comprehensive SEO tools for Ruby on Rails including meta tags, structured data, sitemaps, and validators.">
1906
+ </head>
1907
+ <body>
1908
+ <h1>BetterSeo: Complete SEO Solution</h1>
1909
+ <img src="logo.png" alt="BetterSeo Logo">
1910
+ <h2>Features</h2>
1911
+ <h2>Getting Started</h2>
1912
+ </body>
1913
+ </html>
1914
+ HTML
1915
+
1916
+ result = validator.validate_page(html)
1917
+ # => {
1918
+ # overall_score: 95,
1919
+ # title: { valid: true, score: 100, ... },
1920
+ # description: { valid: true, score: 100, ... },
1921
+ # headings: { valid: true, score: 100, h1_count: 1, ... },
1922
+ # images: { valid: true, score: 100, ... },
1923
+ # issues: []
1924
+ # }
1925
+ ```
1926
+
1927
+ #### Generate SEO Report
1928
+
1929
+ ```ruby
1930
+ validator = BetterSeo::Validators::SeoValidator.new
1931
+ result = validator.validate_page(html)
1932
+
1933
+ report = validator.generate_report(result)
1934
+ puts report
1935
+ # ============================================================
1936
+ # SEO Validation Report
1937
+ # ============================================================
1938
+ #
1939
+ # Overall Score: 95/100
1940
+ #
1941
+ # Title:
1942
+ # Status: ✓
1943
+ # Score: 100/100
1944
+ # Length: 45 chars
1945
+ # Message: Title length is optimal
1946
+ #
1947
+ # Description:
1948
+ # Status: ✓
1949
+ # Score: 100/100
1950
+ # ...
1951
+ ```
1952
+
1953
+ #### Rails Integration
1954
+
1955
+ ```ruby
1956
+ # app/services/seo_validator_service.rb
1957
+ class SeoValidatorService
1958
+ def self.validate_page_seo(url)
1959
+ html = fetch_page_html(url)
1960
+ validator = BetterSeo::Validators::SeoValidator.new
1961
+ validator.validate_page(html)
1962
+ end
1963
+
1964
+ def self.audit_site
1965
+ pages = Page.published.pluck(:url)
1966
+ validator = BetterSeo::Validators::SeoValidator.new
1967
+
1968
+ results = pages.map do |url|
1969
+ html = fetch_page_html(url)
1970
+ validation = validator.validate_page(html)
1971
+ { url: url, score: validation[:overall_score], issues: validation[:issues] }
1972
+ end
1973
+
1974
+ results.sort_by { |r| r[:score] }
1975
+ end
1976
+ end
1977
+ ```
1978
+
1979
+ #### Validation Rules
1980
+
1981
+ - **Title**: 30-60 characters optimal
1982
+ - **Description**: 120-160 characters optimal
1983
+ - **Headings**: Exactly one H1 tag required
1984
+ - **Images**: All images must have alt text
1985
+ - **Overall Score**: Weighted average (Title: 30%, Description: 30%, Headings: 20%, Images: 20%)
1986
+
1987
+ ---
1988
+
1796
1989
  ## Configuration Reference
1797
1990
 
1798
1991
  ### Global Configuration
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BetterSeo
4
- VERSION = "0.12.0"
4
+ VERSION = "0.13.0"
5
5
  end
data/lib/better_seo.rb CHANGED
@@ -16,6 +16,8 @@ require_relative "better_seo/generators/twitter_cards_generator"
16
16
  require_relative "better_seo/generators/breadcrumbs_generator"
17
17
  require_relative "better_seo/generators/amp_generator"
18
18
  require_relative "better_seo/generators/canonical_url_manager"
19
+ require_relative "better_seo/generators/robots_txt_generator"
20
+ require_relative "better_seo/validators/seo_validator"
19
21
  require_relative "better_seo/sitemap/url_entry"
20
22
  require_relative "better_seo/sitemap/builder"
21
23
  require_relative "better_seo/sitemap/generator"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_seo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - alessiobussolari