ComicInfo Ruby Gem
A Ruby gem that provides an idiomatic interface for reading and writing ComicInfo.xml files, following the official ComicInfo schema specifications from the Anansi Project.
Features
- ๐ Complete Schema Support: Full ComicInfo v2.0 schema implementation
- ๐ง Idiomatic Ruby API: Ruby-style interface with proper method naming
- ๐ Flexible Loading: Load from file paths or XML strings
- ๐ Unicode Support: Full Unicode and special character handling
- ๐ Manga Support: Right-to-left reading direction and manga-specific fields
- โ Comprehensive Validation: Schema-compliant enum validation and type coercion
- ๐จ Detailed Error Handling: Custom exception classes with helpful error messages
- ๐ Export Support: JSON, YAML, and XML serialization with hash representation
- โ๏ธ XML Generation: Complete ComicInfo.xml writing with round-trip consistency
Installation
Add this line to your application's Gemfile:
gem 'comicinfo'And then execute:
bundle installOr install it yourself as:
gem install comicinfoUsage
Loading ComicInfo Files
require 'comicinfo'
# Load from file path
comic = ComicInfo.load 'path/to/ComicInfo.xml'
# Load from XML string
xml_content = File.read 'ComicInfo.xml'
comic = ComicInfo.load xml_contentAccessing Comic Information
# Basic information
puts comic.title #=> "The Amazing Spider-Man"
puts comic.series #=> "The Amazing Spider-Man"
puts comic.number #=> "1"
puts comic.count #=> 600
puts comic.volume #=> 3
# Publication details
puts comic.publisher #=> "Marvel Comics"
puts comic.year #=> 2018
puts comic.month #=> 3
puts comic.day #=> 15
# Creator information
puts comic.writer #=> "Dan Slott, Christos Gage"
puts comic.penciller #=> "Ryan Ottley"
puts comic.cover_artist #=> "Ryan Ottley"
# Content details
puts comic.page_count #=> 20
puts comic.genre #=> "Superhero, Action, Adventure"
puts comic.language_iso #=> "en-US"
puts comic.format #=> "Digital"
# Ratings and reviews
puts comic.age_rating #=> "Teen"
puts comic.community_rating #=> 4.25Convenience Methods
# Boolean helpers
puts comic.manga? #=> false
puts comic.right_to_left? #=> false
puts comic.black_and_white? #=> false
# Page information
puts comic.pages? #=> true
puts comic.pages.length #=> 12
# Get specific page types
covers = comic.cover_pages
stories = comic.story_pages
# Multi-value fields as arrays
characters = comic.characters #=> ["Spider-Man", "Peter Parker", ...]
teams = comic.teams #=> ["Avengers"]
locations = comic.locations #=> ["New York City", "Manhattan", ...]
genres = comic.genres #=> ["Superhero", "Action", "Adventure"]
web_urls = comic.web_urls #=> ["https://marvel.com/...", "https://comicvine.com/..."]
# Raw data methods for original comma-separated strings
genres_raw = comic.genres_raw_data #=> "Superhero, Action, Adventure"
characters_raw = comic.characters_raw_data #=> "Spider-Man, Peter Parker, J. Jonah Jameson, Aunt May"
story_arcs_raw = comic.story_arcs_raw_data #=> "Brand New Day, Spider-Island"
# Singular schema elements alias to plural arrays
genre = comic.genre #=> ["Superhero", "Action", "Adventure"] (same as genres)
story_arc = comic.story_arc #=> ["Brand New Day", "Spider-Island"] (same as story_arcs)
story_arc_num = comic.story_arc_number #=> ["1", "5"] (same as story_arc_numbers)Working with Pages
comic.pages.each do |page|
puts "Page #{page.image}: #{page.type}"
puts " Double page: #{page.double_page?}" if page.double_page?
puts " Bookmark: #{page.bookmark}" if page.bookmarked?
puts " Dimensions: #{page.image_width}x#{page.image_height}" if page.dimensions_available?
end
# Page type checks
page = comic.pages.first
puts page.cover? #=> true for FrontCover, BackCover, InnerCover
puts page.story? #=> true for Story pages
puts page.deleted? #=> true for Deleted pagesManga Support
# Load a manga ComicInfo file
manga = ComicInfo.load 'path/to/manga/ComicInfo.xml'
puts manga.title #=> "้ฒๆใฎๅทจไบบ"
puts manga.series #=> "Attack on Titan"
puts manga.manga #=> "YesAndRightToLeft"
puts manga.right_to_left? #=> true
puts manga.language_iso #=> "ja-JP"
puts manga.black_and_white? #=> true
puts manga.black_and_white #=> "Yes"Error Handling
begin
comic = ComicInfo.load('nonexistent.xml')
rescue ComicInfo::Errors::FileError => e
puts "File error: #{e.message}"
rescue ComicInfo::Errors::ParseError => e
puts "Parse error: #{e.message}"
rescue ComicInfo::Errors::InvalidEnumError => e
puts "Invalid enum: #{e.field} = '#{e.value}', valid: #{e.valid_values}"
rescue ComicInfo::Errors::RangeError => e
puts "Out of range: #{e.field} = #{e.value}, range: #{e.min}..#{e.max}"
rescue ComicInfo::Errors::TypeCoercionError => e
puts "Type coercion error: #{e.message}"
endSchema Support
This gem fully supports the ComicInfo v2.0 XSD schema with all field types:
String Fields
- Title, Series, Number, Summary, Notes
- Creator fields (Writer, Penciller, Inker, Colorist, Letterer, CoverArtist, Editor, Translator)
- Publication fields (Publisher, Imprint, Web, LanguageISO, Format)
- Character/Location fields (MainCharacterOrTeam)
- Story fields (SeriesGroup, ScanInformation, Review)
Multi-value Fields (String + Array Access)
- Genre/Genres: Raw comma-separated string + parsed array
- Characters: Raw comma-separated string + parsed array
- Teams: Raw comma-separated string + parsed array
- Locations: Raw comma-separated string + parsed array
- StoryArc/StoryArcs: Raw comma-separated string + parsed array
- StoryArcNumber/StoryArcNumbers: Raw comma-separated string + parsed array
Integer Fields
- Count, Volume, AlternateCount, PageCount
- Date fields (Year, Month, Day)
Enum Fields
- BlackAndWhite: "Unknown", "No", "Yes"
- Manga: "Unknown", "No", "Yes", "YesAndRightToLeft"
- AgeRating: Various ESRB and international ratings
Decimal Fields
- CommunityRating: 0.0 to 5.0 range with validation
Complex Fields
- Pages: Array of ComicPageInfo objects with full attribute support
- Page types: FrontCover, BackCover, InnerCover, Roundup, Story, Advertisement, Editorial, Letters, Preview, Other, Deleted
Export Formats
- JSON: Complete serialization with all fields
- YAML: Human-readable format with array structures
- XML: Valid ComicInfo v2.0 compliant XML generation
- Hash: Ruby hash representation with symbol keys
Data Export & XML Generation
comic = ComicInfo.load 'path/to/ComicInfo.xml'
# Export as JSON
json_string = comic.to_json
puts JSON.pretty_generate(JSON.parse(json_string))
# Export as YAML
yaml_string = comic.to_yaml
puts yaml_string
# Generate XML
xml_string = comic.to_xml
puts xml_string
# Save to file
comic.save 'path/to/new/ComicInfo.xml'
# Save to IO object
File.open('path/to/new/ComicInfo.xml', 'w') do |file|
comic.save file
end
# Export as Hash
hash = comic.to_h
puts hash[:title] #=> "The Amazing Spider-Man"
puts hash[:genre] #=> "Superhero, Action, Adventure" (raw data)
puts hash[:genres] #=> ["Superhero", "Action", "Adventure"] (parsed array)
puts hash[:genres_raw_data] #=> "Superhero, Action, Adventure" (same as :genre)
puts hash[:characters] #=> ["Spider-Man", "Peter Parker", ...]
puts hash[:characters_raw_data] #=> "Spider-Man, Peter Parker, J. Jonah Jameson, Aunt May"
puts hash[:pages].length #=> 12Development
After checking out the repo, run bin/setup to install dependencies.
Then, run rake spec to run the tests.
You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install.
To release a new version, update the version number in version.rb,
and then run bundle exec rake release,
which will create a git tag for the version,
push git commits and the created tag,
and push the .gem file to rubygems.org.
Running Tests
# Run all tests
bundle exec rspec
# Run with documentation format
bundle exec rspec --format documentation
# Run specific test file
bundle exec rspec spec/comic_info_spec.rbCode Quality
# Run RuboCop linter
bundle exec rubocop
# Auto-fix correctable issues
bundle exec rubocop --autocorrectImplementation Status
Current Features โ
- Core Reading: Complete ComicInfo.xml parsing
- XML Writing: Full ComicInfo.xml generation with round-trip consistency
- Schema Compliance: Full ComicInfo v2.0 support
- Field Types: String, Integer, Decimal, Enum, Boolean, Arrays
- Multi-value Fields: Both string and array access methods
- Issue &Page Support: Complete Issue and nested Page objects
- Error Handling: Custom exceptions with detailed messages
- Data Export: JSON, YAML, and XML serialization
- Validation: Enum values, ranges, type coercion
- Unicode Support: International characters and special symbols
- Test Coverage: 178 comprehensive test cases
Planned Features ๐ง
- CLI Tool: Command-line interface for file manipulation
- Schema Migration: Support for multiple ComicInfo versions
Schema Versions
- โ ComicInfo v2.0: Full support (current)
- ๐ง ComicInfo v2.1: Planned
- ๐ง ComicInfo v1.0: Planned
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/veganstraightedge/comicinfo. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the ComicInfo project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
Acknowledgments
- Anansi Project for the ComicInfo schema specification
- Nokogiri for XML parsing capabilities