Claude-skill-registry compare-erb-js
Compare ERB and JavaScript template outputs for the offline scoring SPA. Use when working on ERB-to-JS conversion, debugging template parity issues, or verifying that changes to scoring views work correctly in both ERB and SPA modes.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/compare-erb-js" ~/.claude/skills/majiayu000-claude-skill-registry-compare-erb-js && rm -rf "$T"
manifest:
skills/data/compare-erb-js/SKILL.mdsource content
Compare ERB vs JavaScript Template Output
Use
scripts/render_erb_and_js.rb to verify that ERB templates and their JavaScript-converted equivalents produce matching output. This is essential for the offline scoring SPA which uses auto-converted ERB templates.
Basic Usage
# Compare heat list bundle exec ruby scripts/render_erb_and_js.rb db/2025-barcelona-november.sqlite3 83 # Compare individual heat bundle exec ruby scripts/render_erb_and_js.rb db/2025-barcelona-november.sqlite3 83 1 # With style parameter bundle exec ruby scripts/render_erb_and_js.rb db/2025-barcelona-november.sqlite3 83 1 radio
Or using environment variable:
RAILS_APP_DB=2025-barcelona-november bundle exec ruby scripts/render_erb_and_js.rb 83 1
What It Does
- Renders the ERB template via Rails routing (extracts
content)<main> - Fetches converted JavaScript templates from
/templates/scoring.js - Fetches normalized data from
/scores/:judge/heats/data - Hydrates the data using
(for individual heats)heat_hydrator.js - Renders using the JavaScript template
- Compares row counts and saves both outputs for diff analysis
Output Files
All files are saved to
/tmp/ for analysis:
- ERB template output (main content only)/tmp/erb_rendered.html
- JavaScript template output/tmp/js_rendered.html
- Converted templates from/tmp/scoring_templates.js/templates/scoring.js
- Raw normalized data from server/tmp/heats_data.json
- Hydrated data passed to JS template/tmp/js_template_data.json
Analyzing Differences
# Quick diff diff /tmp/erb_rendered.html /tmp/js_rendered.html # Side-by-side comparison diff -y /tmp/erb_rendered.html /tmp/js_rendered.html | less # Compare specific attributes diff <(grep -o 'href="[^"]*"' /tmp/erb_rendered.html | sort) \ <(grep -o 'href="[^"]*"' /tmp/js_rendered.html | sort)
Common Differences
Some differences are expected due to ERB-to-JS conversion limitations:
- HTML entity encoding: ERB uses
while JS uses"" - link_to blocks: Block form of
may render differentlylink_to - Whitespace: Minor whitespace differences are normal
Architecture
This tool supports the "Server computes, hydration joins, templates filter" principle:
- Server: Computes derived values and paths (respects RAILS_APP_SCOPE)
- Hydration:
joins normalized data by resolving IDsheat_hydrator.js - Templates: ERB and JS templates filter/format data identically
Key Source Files
Server-side (Rails)
-
app/controllers/scores_controller.rb
action: Returns normalized JSON data for SPAheats_data
action: Sets instance variables for ERB templatesheat- Computes
hash with server-computed URLspaths:
-
app/controllers/templates_controller.rb
action: Converts ERB templates to JavaScript on-the-flyscoring- Defines path helper stubs for JS templates
- Uses
for conversionErbPrismConverter
-
lib/erb_prism_converter.rb- Converts ERB templates to JavaScript functions using Ruby's Prism parser
- Handles Ruby-to-JS translation (loops, conditionals, method calls)
Client-side (JavaScript)
-
app/javascript/lib/heat_hydrator.js
: Creates Maps for O(1) entity lookupbuildLookupTables()
: Resolves IDs to full objectshydrateHeat()
: Prepares complete data for templatesbuildHeatTemplateData()
-
app/javascript/controllers/heat_app_controller.js- Main Stimulus controller for the offline scoring SPA
- Loads templates and data, handles navigation
- Manages offline/online state transitions
ERB Templates (source of truth)
- Main heat viewapp/views/scores/heat.html.erb
- Heat list viewapp/views/scores/heatlist.html.erb
- Heat header partialapp/views/scores/_heat_header.html.erb
- Info box with feedback errorsapp/views/scores/_info_box.html.erb
- Prev/next navigationapp/views/scores/_navigation_footer.html.erb
- Standard heat tableapp/views/scores/_table_heat.html.erb
- Finals ranking viewapp/views/scores/_rank_heat.html.erb
- Solo heat viewapp/views/scores/_solo_heat.html.erb
- Card-based scoring viewapp/views/scores/_cards_heat.html.erb
Scripts
- This comparison toolscripts/render_erb_and_js.rb
- Node.js script for hydrating data (used by comparison tool)scripts/hydrate_heats.mjs