fix: extract pure SVG content from AbacusReact renders

Fixed generateAbacusIcons.tsx to properly extract SVG content from
AbacusReact server-side renders, removing invalid div wrappers that
prevented the abacus from displaying in icon.svg and og-image.svg.

Changes:
- Added extractSvgContent() function to parse rendered markup
- Regenerated icon.svg with proper SVG structure
- Regenerated og-image.svg showing abacus value 123
- Removed unused React import (modern TSX doesn't need it)

The Open Graph image now correctly displays the abacus visualization
alongside the site text, fixing the issue where only text was visible.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2025-11-03 04:25:34 -06:00
parent 174370b6bc
commit b07f1c4216
3 changed files with 24 additions and 8 deletions

View File

@@ -12,7 +12,7 @@
<!-- Left side - Abacus from @soroban/abacus-react -->
<g transform="translate(80, 100) scale(0.9)">
<div class="abacus-container" style="display:inline-block;text-align:center;position:relative"><svg width="135" height="216" viewBox="0 0 135 216" class="abacus-svg " style="overflow:visible;display:block"><defs><style>
<defs><style>
/* CSS-based opacity system for hidden inactive beads */
.abacus-bead {
transition: opacity 0.2s ease-in-out;
@@ -37,7 +37,7 @@
.abacus-svg.hide-inactive-mode:not(.interactive) .abacus-bead.hidden-inactive {
opacity: 0 !important;
}
</style></defs><rect x="19.8" y="0" width="5.4" height="216" fill="#7c2d12" stroke="#92400e" stroke-width="2" opacity="1"></rect><rect x="64.8" y="0" width="5.4" height="216" fill="#7c2d12" stroke="#92400e" stroke-width="2" opacity="1"></rect><rect x="109.8" y="0" width="5.4" height="216" fill="#7c2d12" stroke="#92400e" stroke-width="2" opacity="1"></rect><rect x="11.7" y="54" width="111.6" height="3.6" fill="#92400e" stroke="#92400e" stroke-width="3" opacity="1"></rect><g class="abacus-bead inactive " transform="translate(7.380000000000001, 18)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(7.380000000000001, 59.400000000000006)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(7.380000000000001, 95.4)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(7.380000000000001, 117.89999999999999)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(7.380000000000001, 140.39999999999998)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(52.38, 18)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(52.38, 59.400000000000006)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(52.38, 81.9)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(52.38, 117.90000000000002)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(52.38, 140.4)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(97.38, 18)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(97.38, 59.400000000000006)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(97.38, 81.9)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(97.38, 104.4)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(97.38, 140.4)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><rect x="0" y="0" width="45" height="216" fill="transparent" stroke="none" style="cursor:default;pointer-events:none"></rect><rect x="45" y="0" width="45" height="216" fill="transparent" stroke="none" style="cursor:default;pointer-events:none"></rect><rect x="90" y="0" width="45" height="216" fill="transparent" stroke="none" style="cursor:default;pointer-events:none"></rect></svg></div>
</style></defs><rect x="19.8" y="0" width="5.4" height="216" fill="#7c2d12" stroke="#92400e" stroke-width="2" opacity="1"></rect><rect x="64.8" y="0" width="5.4" height="216" fill="#7c2d12" stroke="#92400e" stroke-width="2" opacity="1"></rect><rect x="109.8" y="0" width="5.4" height="216" fill="#7c2d12" stroke="#92400e" stroke-width="2" opacity="1"></rect><rect x="11.7" y="54" width="111.6" height="3.6" fill="#92400e" stroke="#92400e" stroke-width="3" opacity="1"></rect><g class="abacus-bead inactive " transform="translate(7.380000000000001, 18)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(7.380000000000001, 59.400000000000006)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(7.380000000000001, 95.4)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(7.380000000000001, 117.89999999999999)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(7.380000000000001, 140.39999999999998)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(52.38, 18)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(52.38, 59.400000000000006)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(52.38, 81.9)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(52.38, 117.90000000000002)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(52.38, 140.4)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(97.38, 18)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(97.38, 59.400000000000006)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(97.38, 81.9)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead active " transform="translate(97.38, 104.4)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(97.38, 140.4)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="15.12,0 30.24,10.8 15.12,21.6 0,10.8" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><rect x="0" y="0" width="45" height="216" fill="transparent" stroke="none" style="cursor:default;pointer-events:none"></rect><rect x="45" y="0" width="45" height="216" fill="transparent" stroke="none" style="cursor:default;pointer-events:none"></rect><rect x="90" y="0" width="45" height="216" fill="transparent" stroke="none" style="cursor:default;pointer-events:none"></rect>
</g>
<!-- Right side - Text content -->

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -12,9 +12,19 @@ import { writeFileSync } from 'fs'
import { join } from 'path'
import { AbacusReact } from '@soroban/abacus-react'
// Extract just the SVG element content from rendered output
function extractSvgContent(markup: string): string {
// Find the opening <svg and closing </svg> tags
const svgMatch = markup.match(/<svg[^>]*>([\s\S]*?)<\/svg>/)
if (!svgMatch) {
throw new Error('No SVG element found in rendered output')
}
return svgMatch[1] // Return just the inner content
}
// Generate the favicon (icon.svg) - single column showing value 5
function generateFavicon(): string {
const iconSvg = renderToStaticMarkup(
const abacusMarkup = renderToStaticMarkup(
<AbacusReact
value={5}
columns={1}
@@ -39,6 +49,9 @@ function generateFavicon(): string {
/>
)
// Extract just the SVG content (without div wrapper)
const svgContent = extractSvgContent(abacusMarkup)
// Wrap in SVG with proper viewBox for favicon sizing
return `<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<!-- Background circle for better visibility -->
@@ -46,7 +59,7 @@ function generateFavicon(): string {
<!-- Abacus from @soroban/abacus-react -->
<g transform="translate(32, 8) scale(0.36)">
${iconSvg}
${svgContent}
</g>
</svg>
`
@@ -54,7 +67,7 @@ function generateFavicon(): string {
// Generate the Open Graph image (og-image.svg)
function generateOGImage(): string {
const abacusSvg = renderToStaticMarkup(
const abacusMarkup = renderToStaticMarkup(
<AbacusReact
value={123}
columns={3}
@@ -79,6 +92,9 @@ function generateOGImage(): string {
/>
)
// Extract just the SVG content (without div wrapper)
const svgContent = extractSvgContent(abacusMarkup)
return `<svg width="1200" height="630" viewBox="0 0 1200 630" xmlns="http://www.w3.org/2000/svg">
<!-- Gradient background -->
<defs>
@@ -93,7 +109,7 @@ function generateOGImage(): string {
<!-- Left side - Abacus from @soroban/abacus-react -->
<g transform="translate(80, 100) scale(0.9)">
${abacusSvg}
${svgContent}
</g>
<!-- Right side - Text content -->

View File

@@ -4,7 +4,7 @@
<!-- Abacus from @soroban/abacus-react -->
<g transform="translate(32, 8) scale(0.36)">
<div class="abacus-container" style="display:inline-block;text-align:center;position:relative"><svg width="25" height="120" viewBox="0 0 25 120" class="abacus-svg " style="overflow:visible;display:block"><defs><style>
<defs><style>
/* CSS-based opacity system for hidden inactive beads */
.abacus-bead {
transition: opacity 0.2s ease-in-out;
@@ -29,6 +29,6 @@
.abacus-svg.hide-inactive-mode:not(.interactive) .abacus-bead.hidden-inactive {
opacity: 0 !important;
}
</style></defs><rect x="11" y="0" width="3" height="120" fill="#7c2d12" stroke="#92400e" stroke-width="2" opacity="1"></rect><rect x="6.5" y="30" width="12" height="2" fill="#92400e" stroke="#92400e" stroke-width="3" opacity="1"></rect><g class="abacus-bead active " transform="translate(4.100000000000001, 17)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="8.399999999999999,0 16.799999999999997,6 8.399999999999999,12 0,6" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(4.100000000000001, 40)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="8.399999999999999,0 16.799999999999997,6 8.399999999999999,12 0,6" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(4.100000000000001, 52.5)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="8.399999999999999,0 16.799999999999997,6 8.399999999999999,12 0,6" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(4.100000000000001, 65)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="8.399999999999999,0 16.799999999999997,6 8.399999999999999,12 0,6" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(4.100000000000001, 77.5)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="8.399999999999999,0 16.799999999999997,6 8.399999999999999,12 0,6" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><rect x="0" y="0" width="25" height="120" fill="transparent" stroke="none" style="cursor:default;pointer-events:none"></rect></svg></div>
</style></defs><rect x="11" y="0" width="3" height="120" fill="#7c2d12" stroke="#92400e" stroke-width="2" opacity="1"></rect><rect x="6.5" y="30" width="12" height="2" fill="#92400e" stroke="#92400e" stroke-width="3" opacity="1"></rect><g class="abacus-bead active " transform="translate(4.100000000000001, 17)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="8.399999999999999,0 16.799999999999997,6 8.399999999999999,12 0,6" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(4.100000000000001, 40)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="8.399999999999999,0 16.799999999999997,6 8.399999999999999,12 0,6" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(4.100000000000001, 52.5)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="8.399999999999999,0 16.799999999999997,6 8.399999999999999,12 0,6" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(4.100000000000001, 65)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="8.399999999999999,0 16.799999999999997,6 8.399999999999999,12 0,6" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><g class="abacus-bead inactive " transform="translate(4.100000000000001, 77.5)" style="cursor:default;touch-action:none;transition:opacity 0.2s ease-in-out"><polygon points="8.399999999999999,0 16.799999999999997,6 8.399999999999999,12 0,6" fill="#fbbf24" stroke="#000" stroke-width="0.5"></polygon></g><rect x="0" y="0" width="25" height="120" fill="transparent" stroke="none" style="cursor:default;pointer-events:none"></rect>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB